Compatibility fragment commit
authorEdward Mann <phpeclipse.dev@edmann.com>
Fri, 27 Jun 2008 05:09:05 +0000 (05:09 +0000)
committerEdward Mann <phpeclipse.dev@edmann.com>
Fri, 27 Jun 2008 05:09:05 +0000 (05:09 +0000)
39 files changed:
net.sourceforge.phpeclipse.32.compatibility/.classpath [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/.project [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/META-INF/MANIFEST.MF [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/build.properties [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/fragment.xml [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/externaltools/actions/ExternalPHPParser.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/compiler/lookup/CompilationUnitScope.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/core/JavaModelManager.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/corext/phpdoc/PHPDocUtil.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/corext/util/Resources.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGProxy.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/debug/ui/launcher/LoadPathEntryLabelProvider.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/debug/ui/launcher/PHPEnvironmentTab.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/launching/InterpreterRunner.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/launching/InterpreterRunnerConfiguration.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/launching/PHPSourceLocator.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/ui/text/template/DeclarationProposal.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/ui/util/PHPFileUtil.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/ltk/core/RenameIdentifierDelegate.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/ltk/core/RenameLocalVariableDelegate.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/actions/IncludesScanner.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/actions/OpenDeclarationEditorAction.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/actions/PHPOpenAllIncludesEditorAction.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorIgnores.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/obfuscator/export/WizardObfuscatorResourceExportPage1.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/phpeditor/PHPTextHover.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/ui/WebUI.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/ui/editor/ShowExternalPreviewAction.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/webbrowser/internal/OpenWithBrowserActionDelegate.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/webbrowser/internal/WebBrowserEditor.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/webbrowser/views/BrowserView.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/wizards/NewProjectCreationWizard.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/launching/PHPLaunchConfigurationDelegate.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/launching/PHPSourceLookupParticipant.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/model/XDebugTarget.java [new file with mode: 0644]
net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xml/core/internal/model/XMLDocument.java [new file with mode: 0644]

diff --git a/net.sourceforge.phpeclipse.32.compatibility/.classpath b/net.sourceforge.phpeclipse.32.compatibility/.classpath
new file mode 100644 (file)
index 0000000..ce73933
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/net.sourceforge.phpeclipse.32.compatibility/.project b/net.sourceforge.phpeclipse.32.compatibility/.project
new file mode 100644 (file)
index 0000000..f3c7947
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>net.sourceforge.phpeclipse.32.compatibility</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/net.sourceforge.phpeclipse.32.compatibility/.settings/org.eclipse.jdt.core.prefs b/net.sourceforge.phpeclipse.32.compatibility/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..8ba6423
--- /dev/null
@@ -0,0 +1,7 @@
+#Thu Jun 26 21:18:27 CDT 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
+org.eclipse.jdt.core.compiler.compliance=1.4
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
+org.eclipse.jdt.core.compiler.source=1.3
diff --git a/net.sourceforge.phpeclipse.32.compatibility/META-INF/MANIFEST.MF b/net.sourceforge.phpeclipse.32.compatibility/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..848862d
--- /dev/null
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Compatability Fragment
+Bundle-SymbolicName: net.sourceforge.phpeclipse.32.compatibility
+Bundle-Version: 1.0.0
+Fragment-Host: net.sourceforge.phpeclipse;bundle-version="0.0.0"
+Bundle-RequiredExecutionEnvironment: J2SE-1.4
+Bundle-ClassPath: compatability.jar,
+ .
+Eclipse-PatchFragment: true
+Require-Bundle: net.sourceforge.phpeclipse.launching,
+ net.sourceforge.phpeclipse.core;bundle-version="0.0.0"
diff --git a/net.sourceforge.phpeclipse.32.compatibility/build.properties b/net.sourceforge.phpeclipse.32.compatibility/build.properties
new file mode 100644 (file)
index 0000000..e3c6d90
--- /dev/null
@@ -0,0 +1,5 @@
+bin.includes = META-INF/,\
+               fragment.xml,\
+               compatability.jar
+source.compatability.jar = src/
+jars.compile.order = compatability.jar
diff --git a/net.sourceforge.phpeclipse.32.compatibility/fragment.xml b/net.sourceforge.phpeclipse.32.compatibility/fragment.xml
new file mode 100644 (file)
index 0000000..9441a04
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<fragment>
+
+</fragment>
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/externaltools/actions/ExternalPHPParser.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/externaltools/actions/ExternalPHPParser.java
new file mode 100644 (file)
index 0000000..ffb9ca7
--- /dev/null
@@ -0,0 +1,345 @@
+package net.sourceforge.phpdt.externaltools.actions;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.Hashtable;
+
+import net.sourceforge.phpdt.externaltools.util.StringUtil;
+import net.sourceforge.phpeclipse.externaltools.ExternalToolsPlugin;
+import net.sourceforge.phpeclipse.externaltools.PHPConsole;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.ui.texteditor.MarkerUtilities;
+
+/**
+ * Calls the external parser and generates problem markers if necessary
+ */
+public class ExternalPHPParser {
+       private final static String PROBLEM_ID = "net.sourceforge.phpeclipse.problem";
+
+       // strings for external parser call
+       private static final String PARSE_ERROR_STRING = "Parse error"; //$NON-NLS-1$
+
+       private static final String PARSE_WARNING_STRING = "Warning"; //$NON-NLS-1$
+
+       public static final int ERROR = 2;
+
+       public static final int WARNING = 1;
+
+       public static final int INFO = 0;
+
+       public static final int TASK = 3;
+
+       // TODO design error? Analyze why fileToParse must be static ???
+       final protected IFile fFileToParse;
+
+       public ExternalPHPParser(IFile file) {
+               fFileToParse = file;
+       }
+
+       /**
+        * Call the php parse command ( php -l -f &lt;filename&gt; ) and create
+        * markers according to the external parser output.
+        * 
+        * @param file
+        *            the file that will be parsed
+        */
+       public void phpExternalParse() {
+               // IFile file = (IFile) resource;
+               // final IPath path = file.getFullPath();
+               final IPreferenceStore store = ExternalToolsPlugin.getDefault()
+                               .getPreferenceStore();
+               final String filename = fFileToParse.getLocation().toString();
+
+               final String[] arguments = { filename };
+               final MessageFormat form = new MessageFormat(store
+                               .getString(ExternalToolsPlugin.EXTERNAL_PARSER_PREF));
+               final String command = form.format(arguments);
+
+               final String parserResult = getParserOutput(command,
+                               "External parser: ");
+
+               try {
+                       // parse the buffer to find the errors and warnings
+                       createMarkers(parserResult, fFileToParse);
+               } catch (CoreException e) {
+               }
+       }
+
+       /**
+        * Create markers according to the external parser output.
+        * 
+        * @param output
+        *            the external parser output
+        * @param file
+        *            the file that was parsed.
+        */
+       protected void createMarkers(final String output, final IFile file)
+                       throws CoreException {
+               // delete all markers
+               file.deleteMarkers(PROBLEM_ID, false, 0);
+
+               int indx = 0;
+               int brIndx;
+               boolean flag = true;
+               while ((brIndx = output.indexOf("<br />", indx)) != -1) {
+                       // newer php error output (tested with 4.2.3)
+                       scanLine(output, file, indx, brIndx);
+                       indx = brIndx + 6;
+                       flag = false;
+               }
+               if (flag) {
+                       while ((brIndx = output.indexOf("<br>", indx)) != -1) {
+                               // older php error output (tested with 4.2.3)
+                               scanLine(output, file, indx, brIndx);
+                               indx = brIndx + 4;
+                       }
+               }
+       }
+
+       private void scanLine(final String output, final IFile file,
+                       final int indx, final int brIndx) throws CoreException {
+               String current;
+               // String outLineNumberString; never used
+               final StringBuffer lineNumberBuffer = new StringBuffer(10);
+               char ch;
+               current = output.substring(indx, brIndx);
+
+               if (current.indexOf(PARSE_WARNING_STRING) != -1
+                               || current.indexOf(PARSE_ERROR_STRING) != -1) {
+                       final int onLine = current.indexOf("on line <b>");
+                       if (onLine != -1) {
+                               lineNumberBuffer.delete(0, lineNumberBuffer.length());
+                               for (int i = onLine; i < current.length(); i++) {
+                                       ch = current.charAt(i);
+                                       if ('0' <= ch && '9' >= ch) {
+                                               lineNumberBuffer.append(ch);
+                                       }
+                               }
+
+                               final int lineNumber = Integer.parseInt(lineNumberBuffer
+                                               .toString());
+
+                               final Hashtable attributes = new Hashtable();
+
+                               current = StringUtil.replaceAll(current, "\n", "");
+                               current = StringUtil.replaceAll(current, "<b>", "");
+                               current = StringUtil.replaceAll(current, "</b>", "");
+                               MarkerUtilities.setMessage(attributes, current);
+
+                               if (current.indexOf(PARSE_ERROR_STRING) != -1)
+                                       attributes.put(IMarker.SEVERITY, new Integer(
+                                                       IMarker.SEVERITY_ERROR));
+                               else if (current.indexOf(PARSE_WARNING_STRING) != -1)
+                                       attributes.put(IMarker.SEVERITY, new Integer(
+                                                       IMarker.SEVERITY_WARNING));
+                               else
+                                       attributes.put(IMarker.SEVERITY, new Integer(
+                                                       IMarker.SEVERITY_INFO));
+                               MarkerUtilities.setLineNumber(attributes, lineNumber);
+                               MarkerUtilities.createMarker(file, attributes, PROBLEM_ID);
+                       }
+               }
+       }
+
+       /**
+        * This will set a marker.
+        * 
+        * @param file
+        *            the file that generated the marker
+        * @param message
+        *            the message
+        * @param charStart
+        *            the starting character
+        * @param charEnd
+        *            the end character
+        * @param errorLevel
+        *            the error level ({@link ExternalPHPParser#ERROR},{@link ExternalPHPParser#INFO},{@link ExternalPHPParser#WARNING}),
+        *            {@link ExternalPHPParser#TASK})
+        * @throws CoreException
+        *             an exception throwed by the MarkerUtilities
+        */
+       private void setMarker(final IFile file, final String message,
+                       final int charStart, final int charEnd, final int errorLevel)
+                       throws CoreException {
+               if (file != null) {
+                       final Hashtable attributes = new Hashtable();
+                       MarkerUtilities.setMessage(attributes, message);
+                       switch (errorLevel) {
+                       case ERROR:
+                               attributes.put(IMarker.SEVERITY, new Integer(
+                                               IMarker.SEVERITY_ERROR));
+                               break;
+                       case WARNING:
+                               attributes.put(IMarker.SEVERITY, new Integer(
+                                               IMarker.SEVERITY_WARNING));
+                               break;
+                       case INFO:
+                               attributes.put(IMarker.SEVERITY, new Integer(
+                                               IMarker.SEVERITY_INFO));
+                               break;
+                       case TASK:
+                               attributes.put(IMarker.SEVERITY, new Integer(IMarker.TASK));
+                               break;
+                       }
+                       MarkerUtilities.setCharStart(attributes, charStart);
+                       MarkerUtilities.setCharEnd(attributes, charEnd);
+                       MarkerUtilities.createMarker(file, attributes, PROBLEM_ID);
+               }
+       }
+
+       /**
+        * This will set a marker.
+        * 
+        * @param file
+        *            the file that generated the marker
+        * @param message
+        *            the message
+        * @param line
+        *            the line number
+        * @param errorLevel
+        *            the error level ({@link ExternalPHPParser#ERROR},{@link ExternalPHPParser#INFO},{@link ExternalPHPParser#WARNING})
+        * @throws CoreException
+        *             an exception throwed by the MarkerUtilities
+        */
+       private void setMarker(final IFile file, final String message,
+                       final int line, final int errorLevel, final String location)
+                       throws CoreException {
+               if (file != null) {
+                       String markerKind = PROBLEM_ID;
+                       final Hashtable attributes = new Hashtable();
+                       MarkerUtilities.setMessage(attributes, message);
+                       switch (errorLevel) {
+                       case ERROR:
+                               attributes.put(IMarker.SEVERITY, new Integer(
+                                               IMarker.SEVERITY_ERROR));
+                               break;
+                       case WARNING:
+                               attributes.put(IMarker.SEVERITY, new Integer(
+                                               IMarker.SEVERITY_WARNING));
+                               break;
+                       case INFO:
+                               attributes.put(IMarker.SEVERITY, new Integer(
+                                               IMarker.SEVERITY_INFO));
+                               break;
+                       case TASK:
+                               attributes.put(IMarker.SEVERITY, new Integer(
+                                               IMarker.SEVERITY_INFO));
+                               markerKind = IMarker.TASK;
+                               break;
+                       }
+                       attributes.put(IMarker.LOCATION, location);
+                       MarkerUtilities.setLineNumber(attributes, line);
+                       MarkerUtilities.createMarker(file, attributes, markerKind);
+               }
+       }
+
+       /**
+        * This will set a marker.
+        * 
+        * @param message
+        *            the message
+        * @param charStart
+        *            the starting character
+        * @param charEnd
+        *            the end character
+        * @param errorLevel
+        *            the error level ({@link ExternalPHPParser#ERROR},{@link ExternalPHPParser#INFO},{@link ExternalPHPParser#WARNING})
+        * @throws CoreException
+        *             an exception throwed by the MarkerUtilities
+        */
+       private void setMarker(final String message, final int charStart,
+                       final int charEnd, final int errorLevel, final String location)
+                       throws CoreException {
+               if (fFileToParse != null) {
+                       setMarker(fFileToParse, message, charStart, charEnd, errorLevel,
+                                       location);
+               }
+       }
+
+       /**
+        * This will set a marker.
+        * 
+        * @param file
+        *            the file that generated the marker
+        * @param message
+        *            the message
+        * @param charStart
+        *            the starting character
+        * @param charEnd
+        *            the end character
+        * @param errorLevel
+        *            the error level ({@link ExternalPHPParser#ERROR},{@link ExternalPHPParser#INFO},{@link ExternalPHPParser#WARNING})
+        * @param location
+        *            the location of the error
+        * @throws CoreException
+        *             an exception throwed by the MarkerUtilities
+        */
+       private void setMarker(final IFile file, final String message,
+                       final int charStart, final int charEnd, final int errorLevel,
+                       final String location) throws CoreException {
+               if (file != null) {
+                       final Hashtable attributes = new Hashtable();
+                       MarkerUtilities.setMessage(attributes, message);
+                       switch (errorLevel) {
+                       case ERROR:
+                               attributes.put(IMarker.SEVERITY, new Integer(
+                                               IMarker.SEVERITY_ERROR));
+                               break;
+                       case WARNING:
+                               attributes.put(IMarker.SEVERITY, new Integer(
+                                               IMarker.SEVERITY_WARNING));
+                               break;
+                       case INFO:
+                               attributes.put(IMarker.SEVERITY, new Integer(
+                                               IMarker.SEVERITY_INFO));
+                               break;
+                       case TASK:
+                               attributes.put(IMarker.SEVERITY, new Integer(IMarker.TASK));
+                               break;
+                       }
+                       attributes.put(IMarker.LOCATION, location);
+                       MarkerUtilities.setCharStart(attributes, charStart);
+                       MarkerUtilities.setCharEnd(attributes, charEnd);
+                       MarkerUtilities.createMarker(file, attributes, PROBLEM_ID); // IMarker.PROBLEM);
+               }
+       }
+
+       private String getParserOutput(String command, String consoleMessage) {
+               try {
+                       PHPConsole console = new PHPConsole();
+                       try {
+                               console.println(consoleMessage + command);
+                       } catch (Throwable th) {
+
+                       }
+
+                       Runtime runtime = Runtime.getRuntime();
+
+                       // runs the command
+                       Process p = runtime.exec(command);
+
+                       // gets the input stream to have the post-compile-time information
+                       InputStream stream = p.getInputStream();
+
+                       // get the string from Stream
+                       String consoleOutput = PHPConsole.getStringFromStream(stream);
+
+                       // prints out the information
+                       if (console != null) {
+                               console.print(consoleOutput);
+                       }
+                       return consoleOutput;
+
+               } catch (IOException e) {
+                       MessageDialog
+                                       .openInformation(null, "IOException: ", e.getMessage());
+               }
+               return "";
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/compiler/lookup/CompilationUnitScope.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/compiler/lookup/CompilationUnitScope.java
new file mode 100644 (file)
index 0000000..0e03ef2
--- /dev/null
@@ -0,0 +1,728 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.compiler.util.CompoundNameVector;
+import net.sourceforge.phpdt.internal.compiler.util.HashtableOfObject;
+import net.sourceforge.phpdt.internal.compiler.util.HashtableOfType;
+import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
+import net.sourceforge.phpdt.internal.compiler.util.SimpleNameVector;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+
+public class CompilationUnitScope extends Scope {
+
+       public LookupEnvironment environment;
+
+       public CompilationUnitDeclaration referenceContext;
+
+       public char[][] currentPackageName;
+
+       public PackageBinding fPackage;
+
+       public ImportBinding[] imports;
+
+       public SourceTypeBinding[] topLevelTypes;
+
+       private CompoundNameVector qualifiedReferences;
+
+       private SimpleNameVector simpleNameReferences;
+
+       private ObjectVector referencedTypes;
+
+       HashtableOfType constantPoolNameUsage;
+
+       public HashtableOfObject resolvedSingeTypeImports;
+
+       public CompilationUnitScope(CompilationUnitDeclaration unit,
+                       LookupEnvironment environment) {
+               super(COMPILATION_UNIT_SCOPE, null);
+               this.environment = environment;
+               this.referenceContext = unit;
+               unit.scope = this;
+               // this.currentPackageName = unit.currentPackage == null ?
+               // CharOperation.NO_CHAR_CHAR : unit.currentPackage.tokens;
+               this.currentPackageName = null;
+               // if (environment.options.produceReferenceInfo) {
+               // this.qualifiedReferences = new CompoundNameVector();
+               // this.simpleNameReferences = new SimpleNameVector();
+               // this.referencedTypes = new ObjectVector();
+               // } else {
+               this.qualifiedReferences = null; // used to test if dependencies
+                                                                                       // should be recorded
+               this.simpleNameReferences = null;
+               this.referencedTypes = null;
+               // }
+       }
+
+       void buildFieldsAndMethods() {
+               for (int i = 0, length = topLevelTypes.length; i < length; i++)
+                       topLevelTypes[i].scope.buildFieldsAndMethods();
+       }
+
+       void buildTypeBindings() {
+               if (referenceContext.compilationResult.compilationUnit != null) {
+                       char[][] expectedPackageName = referenceContext.compilationResult.compilationUnit
+                                       .getPackageName();
+                       if (expectedPackageName != null
+                                       && !CharOperation.equals(currentPackageName,
+                                                       expectedPackageName)) {
+
+                               // only report if the unit isn't structurally empty
+                               // if (referenceContext.currentPackage != null
+                               // || referenceContext.types != null
+                               // || referenceContext.imports != null) {
+                               // problemReporter().packageIsNotExpectedPackage(referenceContext);
+                               // }
+                               currentPackageName = expectedPackageName.length == 0 ? CharOperation.NO_CHAR_CHAR
+                                               : expectedPackageName;
+                       }
+               }
+               if (currentPackageName == CharOperation.NO_CHAR_CHAR) {
+                       if ((fPackage = environment.defaultPackage) == null) {
+                               problemReporter().mustSpecifyPackage(referenceContext);
+                               return;
+                       }
+               } else {
+                       if ((fPackage = environment.createPackage(currentPackageName)) == null) {
+                               // problemReporter().packageCollidesWithType(referenceContext);
+                               return;
+                       }
+                       recordQualifiedReference(currentPackageName); // always dependent
+                                                                                                                       // on your own
+                                                                                                                       // package
+               }
+
+               // Skip typeDeclarations which know of previously reported errors
+               ArrayList types = referenceContext.types;
+               int typeLength = (types == null) ? 0 : types.size();
+               topLevelTypes = new SourceTypeBinding[typeLength];
+               int count = 0;
+               nextType: for (int i = 0; i < typeLength; i++) {
+                       if (types.get(i) instanceof TypeDeclaration) {
+                               TypeDeclaration typeDecl = (TypeDeclaration) types.get(i);
+                               ReferenceBinding typeBinding = fPackage.getType0(typeDecl.name);
+                               recordSimpleReference(typeDecl.name); // needed to detect
+                                                                                                               // collision cases
+                               if (typeBinding != null
+                                               && !(typeBinding instanceof UnresolvedReferenceBinding)) {
+                                       // if a type exists, it must be a valid type - cannot be a
+                                       // NotFound problem type
+                                       // unless its an unresolved type which is now being defined
+                                       problemReporter()
+                                                       .duplicateTypes(referenceContext, typeDecl);
+                                       continue nextType;
+                               }
+                               if (fPackage != environment.defaultPackage
+                                               && fPackage.getPackage(typeDecl.name) != null) {
+                                       // if a package exists, it must be a valid package - cannot
+                                       // be a NotFound problem package
+                                       problemReporter().typeCollidesWithPackage(referenceContext,
+                                                       typeDecl);
+                                       continue nextType;
+                               }
+
+                               if ((typeDecl.modifiers & AccPublic) != 0) {
+                                       char[] mainTypeName;
+                                       if ((mainTypeName = referenceContext.getMainTypeName()) != null
+                                                       // mainTypeName == null means that implementor of
+                                                       // ICompilationUnit decided to return null
+                                                       && !CharOperation.equals(mainTypeName,
+                                                                       typeDecl.name)) {
+                                               problemReporter().publicClassMustMatchFileName(
+                                                               referenceContext, typeDecl);
+                                               continue nextType;
+                                       }
+                               }
+
+                               ClassScope child = new ClassScope(this, typeDecl);
+                               SourceTypeBinding type = child.buildType(null, fPackage);
+                               if (type != null) {
+                                       topLevelTypes[count++] = type;
+                               }
+                       }
+               }
+
+               // shrink topLevelTypes... only happens if an error was reported
+               if (count != topLevelTypes.length)
+                       System.arraycopy(topLevelTypes, 0,
+                                       topLevelTypes = new SourceTypeBinding[count], 0, count);
+       }
+
+       void checkAndSetImports() {
+               // initialize the default imports if necessary... share the default
+               // java.lang.* import
+               if (environment.defaultImports == null) {
+                       Binding importBinding = environment.getTopLevelPackage(JAVA);
+                       if (importBinding != null)
+                               importBinding = ((PackageBinding) importBinding)
+                                               .getTypeOrPackage(JAVA_LANG[1]);
+
+                       // abort if java.lang cannot be found...
+                       if (importBinding == null || !importBinding.isValidBinding())
+                               problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT,
+                                               referenceCompilationUnit());
+
+                       environment.defaultImports = new ImportBinding[] { new ImportBinding(
+                                       JAVA_LANG, true, importBinding, null) };
+               }
+               if (referenceContext.imports == null) {
+                       imports = environment.defaultImports;
+                       return;
+               }
+
+               // allocate the import array, add java.lang.* by default
+               int numberOfStatements = referenceContext.imports.length;
+               // int numberOfImports = numberOfStatements + 1;
+               int numberOfImports = numberOfStatements;
+               // for (int i = 0; i < numberOfStatements; i++) {
+               // ImportReference importReference = referenceContext.imports[i];
+               // if (importReference.onDemand && CharOperation.equals(JAVA_LANG,
+               // importReference.tokens)) {
+               // numberOfImports--;
+               // break;
+               // }
+               // }
+               ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
+               resolvedImports[0] = environment.defaultImports[0];
+               int index = 1;
+
+               nextImport: for (int i = 0; i < numberOfStatements; i++) {
+                       ImportReference importReference = referenceContext.imports[i];
+                       IFile file = importReference.getFile();
+                       SourceTypeBinding typeBinding;
+                       // char[][] compoundName = importReference.tokens;
+                       char[][] compoundName = null;
+                       if (file != null) {
+                               IPath path = file.getProjectRelativePath();
+                               String[] segs = path.segments();
+                               compoundName = new char[segs.length][];
+                               for (int j = 0; j < segs.length; j++) {
+                                       compoundName[j] = segs[j].toCharArray();
+                               }
+                       }
+                       if (compoundName == null) {
+                               continue nextImport;
+                       }
+
+                       // skip duplicates or imports of the current package
+                       for (int j = 0; j < index; j++)
+                               if (resolvedImports[j].onDemand == importReference.onDemand)
+                                       if (CharOperation.equals(compoundName,
+                                                       resolvedImports[j].compoundName))
+                                               continue nextImport;
+                       if (importReference.onDemand == true)
+                               if (CharOperation.equals(compoundName, currentPackageName))
+                                       continue nextImport;
+
+                       if (importReference.onDemand) {
+                               Binding importBinding = findOnDemandImport(compoundName);
+                               if (!importBinding.isValidBinding())
+                                       continue nextImport; // we report all problems in
+                                                                                       // faultInImports()
+                               resolvedImports[index++] = new ImportBinding(compoundName,
+                                               true, importBinding, importReference);
+                       } else {
+                               resolvedImports[index++] = new ImportBinding(compoundName,
+                                               false, null, importReference);
+                       }
+               }
+
+               // shrink resolvedImports... only happens if an error was reported
+               if (resolvedImports.length > index)
+                       System.arraycopy(resolvedImports, 0,
+                                       resolvedImports = new ImportBinding[index], 0, index);
+               imports = resolvedImports;
+       }
+
+       /*
+        * INTERNAL USE-ONLY Innerclasses get their name computed as they are
+        * generated, since some may not be actually outputed if sitting inside
+        * unreachable code.
+        */
+       public char[] computeConstantPoolName(LocalTypeBinding localType) {
+               if (localType.constantPoolName() != null) {
+                       return localType.constantPoolName();
+               }
+               // delegates to the outermost enclosing classfile, since it is the only
+               // one with a global vision of its innertypes.
+
+               if (constantPoolNameUsage == null)
+                       constantPoolNameUsage = new HashtableOfType();
+
+               ReferenceBinding outerMostEnclosingType = localType.scope
+                               .outerMostClassScope().enclosingSourceType();
+
+               // ensure there is not already such a local type name defined by the
+               // user
+               int index = 0;
+               char[] candidateName;
+               while (true) {
+                       if (localType.isMemberType()) {
+                               if (index == 0) {
+                                       candidateName = CharOperation.concat(localType
+                                                       .enclosingType().constantPoolName(),
+                                                       localType.sourceName, '$');
+                               } else {
+                                       // in case of collision, then member name gets extra $1
+                                       // inserted
+                                       // e.g. class X { { class L{} new X(){ class L{} } } }
+                                       candidateName = CharOperation.concat(localType
+                                                       .enclosingType().constantPoolName(), '$', String
+                                                       .valueOf(index).toCharArray(), '$',
+                                                       localType.sourceName);
+                               }
+                       } else if (localType.isAnonymousType()) {
+                               candidateName = CharOperation.concat(outerMostEnclosingType
+                                               .constantPoolName(), String.valueOf(index + 1)
+                                               .toCharArray(), '$');
+                       } else {
+                               candidateName = CharOperation.concat(outerMostEnclosingType
+                                               .constantPoolName(), '$', String.valueOf(index + 1)
+                                               .toCharArray(), '$', localType.sourceName);
+                       }
+                       if (constantPoolNameUsage.get(candidateName) != null) {
+                               index++;
+                       } else {
+                               constantPoolNameUsage.put(candidateName, localType);
+                               break;
+                       }
+               }
+               return candidateName;
+       }
+
+       void connectTypeHierarchy() {
+               for (int i = 0, length = topLevelTypes.length; i < length; i++)
+                       topLevelTypes[i].scope.connectTypeHierarchy();
+       }
+
+       void faultInImports() {
+               if (referenceContext.imports == null)
+                       return;
+               //
+               // // collect the top level type names if a single type import exists
+               int numberOfStatements = referenceContext.imports.length;
+               // HashtableOfType typesBySimpleNames = null;
+               // for (int i = 0; i < numberOfStatements; i++) {
+               // if (!referenceContext.imports[i].onDemand) {
+               // typesBySimpleNames = new HashtableOfType(topLevelTypes.length +
+               // numberOfStatements);
+               // for (int j = 0, length = topLevelTypes.length; j < length; j++)
+               // typesBySimpleNames.put(topLevelTypes[j].sourceName,
+               // topLevelTypes[j]);
+               // break;
+               // }
+               // }
+               //
+               // // allocate the import array, add java.lang.* by default
+               // int numberOfImports = numberOfStatements + 1;
+               // for (int i = 0; i < numberOfStatements; i++) {
+               // ImportReference importReference = referenceContext.imports[i];
+               // if (importReference.onDemand && CharOperation.equals(JAVA_LANG,
+               // importReference.tokens)) {
+               // numberOfImports--;
+               // break;
+               // }
+               // }
+               ImportBinding[] resolvedImports = new ImportBinding[numberOfStatements];
+               // resolvedImports[0] = environment.defaultImports[0];
+               // int index = 1;
+               int index = 0;
+               nextImport: for (int i = 0; i < numberOfStatements; i++) {
+                       ImportReference importReference = referenceContext.imports[i];
+                       // create the file name segments here:
+                       // char[][] compoundName = importReference.tokens;
+                       //
+                       // // skip duplicates or imports of the current package
+                       // for (int j = 0; j < index; j++)
+                       // if (resolvedImports[j].onDemand == importReference.onDemand)
+                       // if (CharOperation.equals(compoundName,
+                       // resolvedImports[j].compoundName)) {
+                       // problemReporter().unusedImport(importReference); // since
+                       // skipped, must be reported now
+                       // continue nextImport;
+                       // }
+                       // if (importReference.onDemand == true)
+                       // if (CharOperation.equals(compoundName, currentPackageName)) {
+                       // problemReporter().unusedImport(importReference); // since
+                       // skipped, must be reported now
+                       // continue nextImport;
+                       // }
+                       // if (importReference.onDemand) {
+                       // Binding importBinding = findOnDemandImport(compoundName);
+                       // if (!importBinding.isValidBinding()) {
+                       // problemReporter().importProblem(importReference, importBinding);
+                       // continue nextImport;
+                       // }
+                       // resolvedImports[index++] = new ImportBinding(compoundName, true,
+                       // importBinding, importReference);
+                       // } else {
+                       IFile file = importReference.getFile();
+                       SourceTypeBinding typeBinding;
+                       char[][] compoundName;
+                       if (file != null) {
+                               typeBinding = new SourceTypeBinding();
+                               // findSingleTypeImport(compoundName);
+                               IPath path = file.getProjectRelativePath();
+                               String[] segs = path.segments();
+                               compoundName = new char[segs.length][];
+                               for (int j = 0; j < segs.length; j++) {
+                                       compoundName[j] = segs[j].toCharArray();
+                               }
+                               typeBinding.compoundName = compoundName; // compoundName;
+                               // this.fPackage = fPackage;
+                               typeBinding.fileName = file.getLocation().toString()
+                                               .toCharArray();
+                               // typeBinding.modifiers = scope.referenceContext.modifiers;
+                               // typeBinding.sourceName = scope.referenceContext.name;
+                               typeBinding.sourceName = path.lastSegment().toCharArray();
+                               // this.scope = scope;
+                       } else {
+                               // if (!typeBinding.isValidBinding()) {
+                               // problemReporter().importProblem(importReference,
+                               // typeBinding);
+                               continue nextImport;
+                               // }
+                       }
+                       // if (typeBinding instanceof PackageBinding) {
+                       // problemReporter().cannotImportPackage(importReference);
+                       // continue nextImport;
+                       // }
+                       // if (typeBinding instanceof ReferenceBinding) {
+                       // ReferenceBinding referenceBinding = (ReferenceBinding)
+                       // typeBinding;
+                       // if (importReference.isTypeUseDeprecated(referenceBinding, this))
+                       // {
+                       // problemReporter().deprecatedType((TypeBinding) typeBinding,
+                       // importReference);
+                       // }
+                       // }
+                       // ReferenceBinding existingType =
+                       // typesBySimpleNames.get(compoundName[compoundName.length - 1]);
+                       // if (existingType != null) {
+                       // // duplicate test above should have caught this case, but make
+                       // sure
+                       // if (existingType == typeBinding) {
+                       // continue nextImport;
+                       // }
+                       // // either the type collides with a top level type or another
+                       // imported type
+                       // for (int j = 0, length = topLevelTypes.length; j < length; j++) {
+                       // if (CharOperation.equals(topLevelTypes[j].sourceName,
+                       // existingType.sourceName)) {
+                       // problemReporter().conflictingImport(importReference);
+                       // continue nextImport;
+                       // }
+                       // }
+                       // problemReporter().duplicateImport(importReference);
+                       // continue nextImport;
+                       // }
+                       resolvedImports[index++] = new ImportBinding(compoundName, false,
+                                       typeBinding, importReference);
+                       imports = resolvedImports;
+                       // typesBySimpleNames.put(compoundName[compoundName.length - 1],
+                       // (ReferenceBinding) typeBinding);
+                       // }
+               }
+               //
+               // // shrink resolvedImports... only happens if an error was reported
+               if (resolvedImports.length > index)
+                       System.arraycopy(resolvedImports, 0,
+                                       resolvedImports = new ImportBinding[index], 0, index);
+               imports = resolvedImports;
+
+               int length = imports.length;
+               resolvedSingeTypeImports = new HashtableOfObject(length);
+               for (int i = 0; i < length; i++) {
+                       ImportBinding binding = imports[i];
+                       if (!binding.onDemand)
+                               resolvedSingeTypeImports.put(
+                                               binding.compoundName[binding.compoundName.length - 1],
+                                               binding);
+               }
+       }
+
+       public void faultInTypes() {
+               faultInImports();
+               if (topLevelTypes == null) {
+                       topLevelTypes = new SourceTypeBinding[0];
+               }
+               for (int i = 0, length = topLevelTypes.length; i < length; i++)
+                       topLevelTypes[i].faultInTypesForFieldsAndMethods();
+       }
+
+       private Binding findOnDemandImport(char[][] compoundName) {
+               recordQualifiedReference(compoundName);
+
+               Binding binding = environment.getTopLevelPackage(compoundName[0]);
+               int i = 1;
+               int length = compoundName.length;
+               foundNothingOrType: if (binding != null) {
+                       PackageBinding packageBinding = (PackageBinding) binding;
+                       while (i < length) {
+                               binding = packageBinding.getTypeOrPackage(compoundName[i++]);
+                               if (binding == null || !binding.isValidBinding()) {
+                                       binding = null;
+                                       break foundNothingOrType;
+                               }
+                               if (!(binding instanceof PackageBinding))
+                                       break foundNothingOrType;
+
+                               packageBinding = (PackageBinding) binding;
+                       }
+                       return packageBinding;
+               }
+
+               ReferenceBinding type;
+               if (binding == null) {
+                       // if (environment.defaultPackage == null
+                       // || environment.options.complianceLevel >=
+                       // CompilerOptions.JDK1_4){
+                       // return new ProblemReferenceBinding(
+                       // CharOperation.subarray(compoundName, 0, i),
+                       // NotFound);
+                       // }
+                       type = findType(compoundName[0], environment.defaultPackage,
+                                       environment.defaultPackage);
+                       if (type == null || !type.isValidBinding())
+                               return new ProblemReferenceBinding(CharOperation.subarray(
+                                               compoundName, 0, i), NotFound);
+                       i = 1; // reset to look for member types inside the default package
+                                       // type
+               } else {
+                       type = (ReferenceBinding) binding;
+               }
+
+               for (; i < length; i++) {
+                       if (!type.canBeSeenBy(fPackage)) {
+                               return new ProblemReferenceBinding(CharOperation.subarray(
+                                               compoundName, 0, i), type, NotVisible);
+                       }
+                       // does not look for inherited member types on purpose
+                       if ((type = type.getMemberType(compoundName[i])) == null) {
+                               return new ProblemReferenceBinding(CharOperation.subarray(
+                                               compoundName, 0, i + 1), NotFound);
+                       }
+               }
+               if (!type.canBeSeenBy(fPackage))
+                       return new ProblemReferenceBinding(compoundName, type, NotVisible);
+               return type;
+       }
+
+       private Binding findSingleTypeImport(char[][] compoundName) {
+               // if (compoundName.length == 1) {
+               // findType records the reference
+               // the name cannot be a package
+               // if (environment.defaultPackage == null
+               // || environment.options.complianceLevel >= CompilerOptions.JDK1_4)
+               // return new ProblemReferenceBinding(compoundName, NotFound);
+               ReferenceBinding typeBinding = findType(compoundName[0],
+                               environment.defaultPackage, fPackage);
+               if (typeBinding == null)
+                       return new ProblemReferenceBinding(compoundName, NotFound);
+               else
+                       return typeBinding;
+               // }
+               // return findOnDemandImport(compoundName);
+       }
+
+       /*
+        * Answer the problem reporter to use for raising new problems.
+        * 
+        * Note that as a side-effect, this updates the current reference context
+        * (unit, type or method) in case the problem handler decides it is
+        * necessary to abort.
+        */
+
+       public ProblemReporter problemReporter() {
+               ProblemReporter problemReporter = referenceContext.problemReporter;
+               problemReporter.referenceContext = referenceContext;
+               return problemReporter;
+       }
+
+       /*
+        * What do we hold onto:
+        * 
+        * 1. when we resolve 'a.b.c', say we keep only 'a.b.c' & when we fail to
+        * resolve 'c' in 'a.b', lets keep 'a.b.c' THEN when we come across a
+        * new/changed/removed item named 'a.b.c', we would find all references to
+        * 'a.b.c' -> This approach fails because every type is resolved in every
+        * onDemand import to detect collision cases... so the references could be
+        * 10 times bigger than necessary.
+        * 
+        * 2. when we resolve 'a.b.c', lets keep 'a.b' & 'c' & when we fail to
+        * resolve 'c' in 'a.b', lets keep 'a.b' & 'c' THEN when we come across a
+        * new/changed/removed item named 'a.b.c', we would find all references to
+        * 'a.b' & 'c' -> This approach does not have a space problem but fails to
+        * handle collision cases. What happens if a type is added named 'a.b'? We
+        * would search for 'a' & 'b' but would not find a match.
+        * 
+        * 3. when we resolve 'a.b.c', lets keep 'a', 'a.b' & 'a', 'b', 'c' & when
+        * we fail to resolve 'c' in 'a.b', lets keep 'a', 'a.b' & 'a', 'b', 'c'
+        * THEN when we come across a new/changed/removed item named 'a.b.c', we
+        * would find all references to 'a.b' & 'c' OR 'a.b' -> 'a' & 'b' OR 'a' -> '' &
+        * 'a' -> As long as each single char[] is interned, we should not have a
+        * space problem and can handle collision cases.
+        * 
+        * 4. when we resolve 'a.b.c', lets keep 'a.b' & 'a', 'b', 'c' & when we
+        * fail to resolve 'c' in 'a.b', lets keep 'a.b' & 'a', 'b', 'c' THEN when
+        * we come across a new/changed/removed item named 'a.b.c', we would find
+        * all references to 'a.b' & 'c' OR 'a.b' -> 'a' & 'b' in the simple name
+        * collection OR 'a' -> 'a' in the simple name collection -> As long as each
+        * single char[] is interned, we should not have a space problem and can
+        * handle collision cases.
+        */
+       void recordQualifiedReference(char[][] qualifiedName) {
+               if (qualifiedReferences == null)
+                       return; // not recording dependencies
+
+               int length = qualifiedName.length;
+               if (length > 1) {
+                       while (!qualifiedReferences.contains(qualifiedName)) {
+                               qualifiedReferences.add(qualifiedName);
+                               if (length == 2) {
+                                       recordSimpleReference(qualifiedName[0]);
+                                       recordSimpleReference(qualifiedName[1]);
+                                       return;
+                               }
+                               length--;
+                               recordSimpleReference(qualifiedName[length]);
+                               System.arraycopy(qualifiedName, 0,
+                                               qualifiedName = new char[length][], 0, length);
+                       }
+               } else if (length == 1) {
+                       recordSimpleReference(qualifiedName[0]);
+               }
+       }
+
+       void recordReference(char[][] qualifiedEnclosingName, char[] simpleName) {
+               recordQualifiedReference(qualifiedEnclosingName);
+               recordSimpleReference(simpleName);
+       }
+
+       void recordSimpleReference(char[] simpleName) {
+               if (simpleNameReferences == null)
+                       return; // not recording dependencies
+
+               if (!simpleNameReferences.contains(simpleName))
+                       simpleNameReferences.add(simpleName);
+       }
+
+       void recordTypeReference(TypeBinding type) {
+               if (referencedTypes == null)
+                       return; // not recording dependencies
+
+               if (type.isArrayType())
+                       type = ((ArrayBinding) type).leafComponentType;
+               if (!type.isBaseType() && !referencedTypes.containsIdentical(type))
+                       referencedTypes.add(type);
+       }
+
+       void recordTypeReferences(TypeBinding[] types) {
+               if (qualifiedReferences == null)
+                       return; // not recording dependencies
+               if (types == null || types.length == 0)
+                       return;
+
+               for (int i = 0, max = types.length; i < max; i++) {
+                       // No need to record supertypes of method arguments & thrown
+                       // exceptions, just the compoundName
+                       // If a field/method is retrieved from such a type then a separate
+                       // call does the job
+                       TypeBinding type = types[i];
+                       if (type.isArrayType())
+                               type = ((ArrayBinding) type).leafComponentType;
+                       if (!type.isBaseType()) {
+                               ReferenceBinding actualType = (ReferenceBinding) type;
+                               if (!actualType.isLocalType())
+                                       recordQualifiedReference(actualType.isMemberType() ? CharOperation
+                                                       .splitOn('.', actualType.readableName())
+                                                       : actualType.compoundName);
+                       }
+               }
+       }
+
+       Binding resolveSingleTypeImport(ImportBinding importBinding) {
+               if (importBinding.resolvedImport == null) {
+                       importBinding.resolvedImport = findSingleTypeImport(importBinding.compoundName);
+                       if (!importBinding.resolvedImport.isValidBinding()
+                                       || importBinding.resolvedImport instanceof PackageBinding) {
+                               if (this.imports != null) {
+                                       ImportBinding[] newImports = new ImportBinding[imports.length - 1];
+                                       for (int i = 0, n = 0, max = this.imports.length; i < max; i++)
+                                               if (this.imports[i] != importBinding) {
+                                                       newImports[n++] = this.imports[i];
+                                               }
+                                       this.imports = newImports;
+                               }
+                               return null;
+                       }
+               }
+               return importBinding.resolvedImport;
+       }
+
+       public void storeDependencyInfo() {
+               // add the type hierarchy of each referenced type
+               // cannot do early since the hierarchy may not be fully resolved
+               for (int i = 0; i < referencedTypes.size; i++) { // grows as more
+                                                                                                                       // types are added
+                       ReferenceBinding type = (ReferenceBinding) referencedTypes
+                                       .elementAt(i);
+                       if (!type.isLocalType()) {
+                               recordQualifiedReference(type.isMemberType() ? CharOperation
+                                               .splitOn('.', type.readableName()) : type.compoundName);
+                               ReferenceBinding enclosing = type.enclosingType();
+                               if (enclosing != null
+                                               && !referencedTypes.containsIdentical(enclosing))
+                                       referencedTypes.add(enclosing); // to record its supertypes
+                       }
+                       ReferenceBinding superclass = type.superclass();
+                       if (superclass != null
+                                       && !referencedTypes.containsIdentical(superclass))
+                               referencedTypes.add(superclass); // to record its supertypes
+                       ReferenceBinding[] interfaces = type.superInterfaces();
+                       if (interfaces != null && interfaces.length > 0)
+                               for (int j = 0, length = interfaces.length; j < length; j++)
+                                       if (!referencedTypes.containsIdentical(interfaces[j]))
+                                               referencedTypes.add(interfaces[j]); // to record its
+                                                                                                                       // supertypes
+               }
+
+               int size = qualifiedReferences.size;
+               char[][][] qualifiedRefs = new char[size][][];
+               for (int i = 0; i < size; i++)
+                       qualifiedRefs[i] = qualifiedReferences.elementAt(i);
+               referenceContext.compilationResult.qualifiedReferences = qualifiedRefs;
+
+               size = simpleNameReferences.size;
+               char[][] simpleRefs = new char[size][];
+               for (int i = 0; i < size; i++)
+                       simpleRefs[i] = simpleNameReferences.elementAt(i);
+               referenceContext.compilationResult.simpleNameReferences = simpleRefs;
+       }
+
+       public String toString() {
+               return "--- CompilationUnit Scope : " + new String(referenceContext.getFileName()); //$NON-NLS-1$
+       }
+
+       public void verifyMethods(MethodVerifier verifier) {
+               for (int i = 0, length = topLevelTypes.length; i < length; i++)
+                       topLevelTypes[i].verifyMethods(verifier);
+       }
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/compiler/parser/Parser.java
new file mode 100644 (file)
index 0000000..b27c78c
--- /dev/null
@@ -0,0 +1,5118 @@
+/***********************************************************************************************************************************
+ * Copyright (c) 2002 www.phpeclipse.de All rights reserved. This program and the accompanying material are made available under the
+ * terms of the Common Public License v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: www.phpeclipse.de
+ **********************************************************************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+
+import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.ast.AND_AND_Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.ASTNode;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.BinaryExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.Block;
+import net.sourceforge.phpdt.internal.compiler.ast.BreakStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ConditionalExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.ContinueStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.EqualExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldReference;
+import net.sourceforge.phpdt.internal.compiler.ast.IfStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+import net.sourceforge.phpdt.internal.compiler.ast.InstanceOfExpression;
+import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.OR_OR_Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.OperatorIds;
+import net.sourceforge.phpdt.internal.compiler.ast.ReturnStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.Statement;
+import net.sourceforge.phpdt.internal.compiler.ast.StringLiteral;
+import net.sourceforge.phpdt.internal.compiler.ast.StringLiteralDQ;
+import net.sourceforge.phpdt.internal.compiler.ast.StringLiteralSQ;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
+import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
+import net.sourceforge.phpeclipse.ui.overlaypages.ProjectPrefUtil;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+
+public class Parser implements ITerminalSymbols, CompilerModifiers,
+               ParserBasicInformation {
+       protected final static int StackIncrement = 255;
+
+       protected int stateStackTop;
+
+       // protected int[] stack = new int[StackIncrement];
+
+       public int firstToken; // handle for multiple parsing goals
+
+       public int lastAct; // handle for multiple parsing goals
+
+       // protected RecoveredElement currentElement;
+
+       public static boolean VERBOSE_RECOVERY = false;
+
+       protected boolean diet = false; // tells the scanner to jump over some
+
+       /**
+        * the PHP token scanner
+        */
+       public Scanner scanner;
+
+       int token;
+
+       protected int modifiers;
+
+       protected int modifiersSourceStart;
+
+       protected Parser(ProblemReporter problemReporter) {
+               this.problemReporter = problemReporter;
+               this.options = problemReporter.options;
+               this.token = TokenNameEOF;
+               this.initializeScanner();
+       }
+
+       public void setFileToParse(IFile fileToParse) {
+               this.token = TokenNameEOF;
+               this.initializeScanner();
+       }
+
+       /**
+        * ClassDeclaration Constructor.
+        * 
+        * @param s
+        * @param sess
+        *            Description of Parameter
+        * @see
+        */
+       public Parser(IFile fileToParse) {
+               // if (keywordMap == null) {
+               // keywordMap = new HashMap();
+               // for (int i = 0; i < PHP_KEYWORS.length; i++) {
+               // keywordMap.put(PHP_KEYWORS[i], new Integer(PHP_KEYWORD_TOKEN[i]));
+               // }
+               // }
+               // this.currentPHPString = 0;
+               // PHPParserSuperclass.fileToParse = fileToParse;
+               // this.phpList = null;
+               this.includesList = null;
+               // this.str = "";
+               this.token = TokenNameEOF;
+               // this.chIndx = 0;
+               // this.rowCount = 1;
+               // this.columnCount = 0;
+               // this.phpEnd = false;
+               // getNextToken();
+               this.initializeScanner();
+       }
+
+       public void initializeScanner() {
+               this.scanner = new Scanner(
+                               false /* comment */,
+                               false /* whitespace */,
+                               this.options.getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /* nls */,
+                               false, false, this.options.taskTags/* taskTags */,
+                               this.options.taskPriorites/* taskPriorities */, true/* isTaskCaseSensitive */);
+       }
+
+       /**
+        * Create marker for the parse error
+        */
+       // private void setMarker(String message, int charStart, int charEnd, int
+       // errorLevel) {
+       // setMarker(fileToParse, message, charStart, charEnd, errorLevel);
+       // }
+       /**
+        * This method will throw the SyntaxError. It will add the good lines and
+        * columns to the Error
+        * 
+        * @param error
+        *            the error message
+        * @throws SyntaxError
+        *             the error raised
+        */
+       private void throwSyntaxError(String error) {
+               int problemStartPosition = scanner.getCurrentTokenStartPosition();
+               int problemEndPosition = scanner.getCurrentTokenEndPosition() + 1;
+               if (scanner.source.length <= problemEndPosition
+                               && problemEndPosition > 0) {
+                       problemEndPosition = scanner.source.length - 1;
+                       if (problemStartPosition > 0
+                                       && problemStartPosition >= problemEndPosition
+                                       && problemEndPosition > 0) {
+                               problemStartPosition = problemEndPosition - 1;
+                       }
+               }
+               throwSyntaxError(error, problemStartPosition, problemEndPosition);
+       }
+
+       /**
+        * This method will throw the SyntaxError. It will add the good lines and
+        * columns to the Error
+        * 
+        * @param error
+        *            the error message
+        * @throws SyntaxError
+        *             the error raised
+        */
+       // private void throwSyntaxError(String error, int startRow) {
+       // throw new SyntaxError(startRow, 0, " ", error);
+       // }
+       private void throwSyntaxError(String error, int problemStartPosition,
+                       int problemEndPosition) {
+               if (referenceContext != null) {
+                       problemReporter.phpParsingError(new String[] { error },
+                                       problemStartPosition, problemEndPosition, referenceContext,
+                                       compilationUnit.compilationResult);
+               }
+               throw new SyntaxError(1, 0, " ", error);
+       }
+
+       private void reportSyntaxError(String error) {
+               int problemStartPosition = scanner.getCurrentTokenStartPosition();
+               int problemEndPosition = scanner.getCurrentTokenEndPosition();
+               reportSyntaxError(error, problemStartPosition, problemEndPosition + 1);
+       }
+
+       private void reportSyntaxError(String error, int problemStartPosition,
+                       int problemEndPosition) {
+               if (referenceContext != null) {
+                       problemReporter.phpParsingError(new String[] { error },
+                                       problemStartPosition, problemEndPosition, referenceContext,
+                                       compilationUnit.compilationResult);
+               }
+       }
+
+       // private void reportSyntaxWarning(String error, int problemStartPosition,
+       // int problemEndPosition) {
+       // if (referenceContext != null) {
+       // problemReporter.phpParsingWarning(new String[] { error },
+       // problemStartPosition, problemEndPosition, referenceContext,
+       // compilationUnit.compilationResult);
+       // }
+       // }
+
+       /**
+        * gets the next token from input
+        */
+       private void getNextToken() {
+               try {
+                       token = scanner.getNextToken();
+                       if (Scanner.DEBUG) {
+                               int currentEndPosition = scanner.getCurrentTokenEndPosition();
+                               int currentStartPosition = scanner
+                                               .getCurrentTokenStartPosition();
+                               System.out.print(currentStartPosition + ","
+                                               + currentEndPosition + ": ");
+                               System.out.println(scanner.toStringAction(token));
+                       }
+               } catch (InvalidInputException e) {
+                       token = TokenNameERROR;
+                       String detailedMessage = e.getMessage();
+
+                       if (detailedMessage == Scanner.UNTERMINATED_STRING) {
+                               throwSyntaxError("Unterminated string.");
+                       } else if (detailedMessage == Scanner.UNTERMINATED_COMMENT) {
+                               throwSyntaxError("Unterminated commment.");
+                       }
+               }
+               return;
+       }
+
+       public void init(String s) {
+               // this.str = s;
+               this.token = TokenNameEOF;
+               this.includesList = new ArrayList();
+               // this.chIndx = 0;
+               // this.rowCount = 1;
+               // this.columnCount = 0;
+               // this.phpEnd = false;
+               // this.phpMode = false;
+               /* scanner initialization */
+               scanner.setSource(s.toCharArray());
+               scanner.setPHPMode(false);
+               astPtr = 0;
+       }
+
+       protected void initialize(boolean phpMode) {
+               initialize(phpMode, null);
+       }
+
+       protected void initialize(boolean phpMode,
+                       IdentifierIndexManager indexManager) {
+               compilationUnit = null;
+               referenceContext = null;
+               this.includesList = new ArrayList();
+               // this.indexManager = indexManager;
+               // this.str = "";
+               this.token = TokenNameEOF;
+               // this.chIndx = 0;
+               // this.rowCount = 1;
+               // this.columnCount = 0;
+               // this.phpEnd = false;
+               // this.phpMode = phpMode;
+               scanner.setPHPMode(phpMode);
+               astPtr = 0;
+       }
+
+       /**
+        * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt;
+        * &lt;/body&gt;'
+        */
+       public void parse(String s) {
+               parse(s, null);
+       }
+
+       /**
+        * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt;
+        * &lt;/body&gt;'
+        */
+       public void parse(String s, HashMap variables) {
+               fMethodVariables = variables;
+               fStackUnassigned = new ArrayList();
+               init(s);
+               parse();
+       }
+
+       /**
+        * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt;
+        * &lt;/body&gt;'
+        */
+       protected void parse() {
+               if (scanner.compilationUnit != null) {
+                       IResource resource = scanner.compilationUnit.getResource();
+                       if (resource != null && resource instanceof IFile) {
+                               // set the package name
+                               consumePackageDeclarationName((IFile) resource);
+                       }
+               }
+               getNextToken();
+               do {
+                       try {
+                               if (token != TokenNameEOF && token != TokenNameERROR) {
+                                       statementList();
+                               }
+                               if (token != TokenNameEOF) {
+                                       if (token == TokenNameERROR) {
+                                               throwSyntaxError("Scanner error (Found unknown token: "
+                                                               + scanner.toStringAction(token) + ")");
+                                       }
+                                       if (token == TokenNameRPAREN) {
+                                               throwSyntaxError("Too many closing ')'; end-of-file not reached.");
+                                       }
+                                       if (token == TokenNameRBRACE) {
+                                               throwSyntaxError("Too many closing '}'; end-of-file not reached.");
+                                       }
+                                       if (token == TokenNameRBRACKET) {
+                                               throwSyntaxError("Too many closing ']'; end-of-file not reached.");
+                                       }
+                                       if (token == TokenNameLPAREN) {
+                                               throwSyntaxError("Read character '('; end-of-file not reached.");
+                                       }
+                                       if (token == TokenNameLBRACE) {
+                                               throwSyntaxError("Read character '{';  end-of-file not reached.");
+                                       }
+                                       if (token == TokenNameLBRACKET) {
+                                               throwSyntaxError("Read character '[';  end-of-file not reached.");
+                                       }
+                                       throwSyntaxError("End-of-file not reached.");
+                               }
+                               break;
+                       } catch (SyntaxError syntaxError) {
+                               // syntaxError.printStackTrace();
+                               break;
+                       }
+               } while (true);
+
+               endParse(0);
+       }
+
+       /**
+        * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt;
+        * &lt;/body&gt;'
+        */
+       public void parseFunction(String s, HashMap variables) {
+               init(s);
+               scanner.phpMode = true;
+               parseFunction(variables);
+       }
+
+       /**
+        * Parses a string with php tags i.e. '&lt;body&gt; &lt;?php phpinfo() ?&gt;
+        * &lt;/body&gt;'
+        */
+       protected void parseFunction(HashMap variables) {
+               getNextToken();
+               boolean hasModifiers = member_modifiers();
+               if (token == TokenNamefunction) {
+                       if (!hasModifiers) {
+                               checkAndSetModifiers(AccPublic);
+                       }
+                       this.fMethodVariables = variables;
+
+                       MethodDeclaration methodDecl = new MethodDeclaration(null);
+                       methodDecl.declarationSourceStart = scanner
+                                       .getCurrentTokenStartPosition();
+                       methodDecl.modifiers = this.modifiers;
+                       methodDecl.type = MethodDeclaration.METHOD_DEFINITION;
+                       try {
+                               getNextToken();
+                               functionDefinition(methodDecl);
+                       } catch (SyntaxError sytaxErr1) {
+                               return;
+                       } finally {
+                               int sourceEnd = methodDecl.sourceEnd;
+                               if (sourceEnd <= 0
+                                               || methodDecl.declarationSourceStart > sourceEnd) {
+                                       sourceEnd = methodDecl.declarationSourceStart + 1;
+                               }
+                               methodDecl.sourceEnd = sourceEnd;
+                               methodDecl.declarationSourceEnd = sourceEnd;
+                       }
+               }
+       }
+
+       protected CompilationUnitDeclaration endParse(int act) {
+
+               this.lastAct = act;
+
+               // if (currentElement != null) {
+               // currentElement.topElement().updateParseTree();
+               // if (VERBOSE_RECOVERY) {
+               // System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
+               // System.out.println("--------------------------"); //$NON-NLS-1$
+               // System.out.println(compilationUnit);
+               // System.out.println("----------------------------------");
+               // //$NON-NLS-1$
+               // }
+               // } else {
+               if (diet & VERBOSE_RECOVERY) {
+                       System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
+                       System.out.println("--------------------------"); //$NON-NLS-1$
+                       System.out.println(compilationUnit);
+                       System.out.println("----------------------------------"); //$NON-NLS-1$
+               }
+               // }
+               if (scanner.recordLineSeparator) {
+                       compilationUnit.compilationResult.lineSeparatorPositions = scanner
+                                       .getLineEnds();
+               }
+               if (scanner.taskTags != null) {
+                       for (int i = 0; i < scanner.foundTaskCount; i++) {
+                               problemReporter().task(
+                                               new String(scanner.foundTaskTags[i]),
+                                               new String(scanner.foundTaskMessages[i]),
+                                               scanner.foundTaskPriorities[i] == null ? null
+                                                               : new String(scanner.foundTaskPriorities[i]),
+                                               scanner.foundTaskPositions[i][0],
+                                               scanner.foundTaskPositions[i][1]);
+                       }
+               }
+               compilationUnit.imports = new ImportReference[includesList.size()];
+               for (int i = 0; i < includesList.size(); i++) {
+                       compilationUnit.imports[i] = (ImportReference) includesList.get(i);
+               }
+               return compilationUnit;
+       }
+
+       private Block statementList() {
+               boolean branchStatement = false;
+               Statement statement;
+               int blockStart = scanner.getCurrentTokenStartPosition();
+               ArrayList blockStatements = new ArrayList();
+               do {
+                       try {
+                               statement = statement();
+                               blockStatements.add(statement);
+                               if (token == TokenNameEOF) {
+                                       return null;
+                               }
+                               if (branchStatement && statement != null) {
+                                       // reportSyntaxError("Unreachable code",
+                                       // statement.sourceStart,
+                                       // statement.sourceEnd);
+                                       if (!(statement instanceof BreakStatement)) {
+                                               /*
+                                                * don't give an error for break statement following
+                                                * return statement Technically it's unreachable code,
+                                                * but in switch-case it's recommended to avoid
+                                                * accidental fall-through later when editing the code
+                                                */
+                                               problemReporter.unreachableCode(new String(scanner
+                                                               .getCurrentIdentifierSource()),
+                                                               statement.sourceStart, statement.sourceEnd,
+                                                               referenceContext,
+                                                               compilationUnit.compilationResult);
+                                       }
+                               }
+                               if ((token == TokenNameRBRACE) || (token == TokenNamecase)
+                                               || (token == TokenNamedefault)
+                                               || (token == TokenNameelse)
+                                               || (token == TokenNameelseif)
+                                               || (token == TokenNameendif)
+                                               || (token == TokenNameendfor)
+                                               || (token == TokenNameendforeach)
+                                               || (token == TokenNameendwhile)
+                                               || (token == TokenNameendswitch)
+                                               || (token == TokenNameenddeclare)
+                                               || (token == TokenNameEOF) || (token == TokenNameERROR)) {
+                                       return createBlock(blockStart, blockStatements);
+                               }
+                               branchStatement = checkUnreachableStatements(statement);
+                       } catch (SyntaxError sytaxErr1) {
+                               // if an error occured,
+                               // try to find keywords
+                               // to parse the rest of the string
+                               boolean tokenize = scanner.tokenizeStrings;
+                               if (!tokenize) {
+                                       scanner.tokenizeStrings = true;
+                               }
+                               try {
+                                       while (token != TokenNameEOF) {
+                                               if ((token == TokenNameRBRACE)
+                                                               || (token == TokenNamecase)
+                                                               || (token == TokenNamedefault)
+                                                               || (token == TokenNameelse)
+                                                               || (token == TokenNameelseif)
+                                                               || (token == TokenNameendif)
+                                                               || (token == TokenNameendfor)
+                                                               || (token == TokenNameendforeach)
+                                                               || (token == TokenNameendwhile)
+                                                               || (token == TokenNameendswitch)
+                                                               || (token == TokenNameenddeclare)
+                                                               || (token == TokenNameEOF)
+                                                               || (token == TokenNameERROR)) {
+                                                       return createBlock(blockStart, blockStatements);
+                                               }
+                                               if (token == TokenNameif || token == TokenNameswitch
+                                                               || token == TokenNamefor
+                                                               || token == TokenNamewhile
+                                                               || token == TokenNamedo
+                                                               || token == TokenNameforeach
+                                                               || token == TokenNamecontinue
+                                                               || token == TokenNamebreak
+                                                               || token == TokenNamereturn
+                                                               || token == TokenNameexit
+                                                               || token == TokenNameecho
+                                                               || token == TokenNameECHO_INVISIBLE
+                                                               || token == TokenNameglobal
+                                                               || token == TokenNamestatic
+                                                               || token == TokenNameunset
+                                                               || token == TokenNamefunction
+                                                               || token == TokenNamedeclare
+                                                               || token == TokenNametry
+                                                               || token == TokenNamecatch
+                                                               || token == TokenNamethrow
+                                                               || token == TokenNamefinal
+                                                               || token == TokenNameabstract
+                                                               || token == TokenNameclass
+                                                               || token == TokenNameinterface) {
+                                                       break;
+                                               }
+                                               // System.out.println(scanner.toStringAction(token));
+                                               getNextToken();
+                                               // System.out.println(scanner.toStringAction(token));
+                                       }
+                                       if (token == TokenNameEOF) {
+                                               throw sytaxErr1;
+                                       }
+                               } finally {
+                                       scanner.tokenizeStrings = tokenize;
+                               }
+                       }
+               } while (true);
+       }
+
+       /**
+        * @param statement
+        * @return
+        */
+       private boolean checkUnreachableStatements(Statement statement) {
+               if (statement instanceof ReturnStatement
+                               || statement instanceof ContinueStatement
+                               || statement instanceof BreakStatement) {
+                       return true;
+               } else if (statement instanceof IfStatement
+                               && ((IfStatement) statement).checkUnreachable) {
+                       return true;
+               }
+               return false;
+       }
+
+       /**
+        * @param blockStart
+        * @param blockStatements
+        * @return
+        */
+       private Block createBlock(int blockStart, ArrayList blockStatements) {
+               int blockEnd = scanner.getCurrentTokenEndPosition();
+               Block b = Block.EmptyWith(blockStart, blockEnd);
+               b.statements = new Statement[blockStatements.size()];
+               blockStatements.toArray(b.statements);
+               return b;
+       }
+
+       private void functionBody(MethodDeclaration methodDecl) {
+               // '{' [statement-list] '}'
+               if (token == TokenNameLBRACE) {
+                       getNextToken();
+               } else {
+                       methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
+                       throwSyntaxError("'{' expected in compound-statement.");
+               }
+               if (token != TokenNameRBRACE) {
+                       statementList();
+               }
+               if (token == TokenNameRBRACE) {
+                       methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
+                       getNextToken();
+               } else {
+                       methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
+                       throwSyntaxError("'}' expected in compound-statement.");
+               }
+       }
+
+       private Statement statement() {
+               Statement statement = null;
+               Expression expression;
+               int sourceStart = scanner.getCurrentTokenStartPosition();
+               int sourceEnd;
+               if (token == TokenNameif) {
+                       // T_IF '(' expr ')' statement elseif_list else_single
+                       // T_IF '(' expr ')' ':' inner_statement_list new_elseif_list
+                       // new_else_single T_ENDIF ';'
+                       getNextToken();
+                       if (token == TokenNameLPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("'(' expected after 'if' keyword.");
+                       }
+                       expression = expr();
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("')' expected after 'if' condition.");
+                       }
+                       // create basic IfStatement
+                       IfStatement ifStatement = new IfStatement(expression, null, null,
+                                       sourceStart, -1);
+                       if (token == TokenNameCOLON) {
+                               getNextToken();
+                               ifStatementColon(ifStatement);
+                       } else {
+                               ifStatement(ifStatement);
+                       }
+                       return ifStatement;
+               } else if (token == TokenNameswitch) {
+                       getNextToken();
+                       if (token == TokenNameLPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("'(' expected after 'switch' keyword.");
+                       }
+                       expr();
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("')' expected after 'switch' condition.");
+                       }
+                       switchStatement();
+                       return statement;
+               } else if (token == TokenNamefor) {
+                       getNextToken();
+                       if (token == TokenNameLPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("'(' expected after 'for' keyword.");
+                       }
+                       if (token == TokenNameSEMICOLON) {
+                               getNextToken();
+                       } else {
+                               expressionList();
+                               if (token == TokenNameSEMICOLON) {
+                                       getNextToken();
+                               } else {
+                                       throwSyntaxError("';' expected after 'for'.");
+                               }
+                       }
+                       if (token == TokenNameSEMICOLON) {
+                               getNextToken();
+                       } else {
+                               expressionList();
+                               if (token == TokenNameSEMICOLON) {
+                                       getNextToken();
+                               } else {
+                                       throwSyntaxError("';' expected after 'for'.");
+                               }
+                       }
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                       } else {
+                               expressionList();
+                               if (token == TokenNameRPAREN) {
+                                       getNextToken();
+                               } else {
+                                       throwSyntaxError("')' expected after 'for'.");
+                               }
+                       }
+                       forStatement();
+                       return statement;
+               } else if (token == TokenNamewhile) {
+                       getNextToken();
+                       if (token == TokenNameLPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("'(' expected after 'while' keyword.");
+                       }
+                       expr();
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("')' expected after 'while' condition.");
+                       }
+                       whileStatement();
+                       return statement;
+               } else if (token == TokenNamedo) {
+                       getNextToken();
+                       if (token == TokenNameLBRACE) {
+                               getNextToken();
+                               if (token != TokenNameRBRACE) {
+                                       statementList();
+                               }
+                               if (token == TokenNameRBRACE) {
+                                       getNextToken();
+                               } else {
+                                       throwSyntaxError("'}' expected after 'do' keyword.");
+                               }
+                       } else {
+                               statement();
+                       }
+                       if (token == TokenNamewhile) {
+                               getNextToken();
+                               if (token == TokenNameLPAREN) {
+                                       getNextToken();
+                               } else {
+                                       throwSyntaxError("'(' expected after 'while' keyword.");
+                               }
+                               expr();
+                               if (token == TokenNameRPAREN) {
+                                       getNextToken();
+                               } else {
+                                       throwSyntaxError("')' expected after 'while' condition.");
+                               }
+                       } else {
+                               throwSyntaxError("'while' expected after 'do' keyword.");
+                       }
+                       if (token == TokenNameSEMICOLON) {
+                               getNextToken();
+                       } else {
+                               if (token != TokenNameINLINE_HTML) {
+                                       throwSyntaxError("';' expected after do-while statement.");
+                               }
+                               getNextToken();
+                       }
+                       return statement;
+               } else if (token == TokenNameforeach) {
+                       getNextToken();
+                       if (token == TokenNameLPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("'(' expected after 'foreach' keyword.");
+                       }
+                       expr();
+                       if (token == TokenNameas) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("'as' expected after 'foreach' exxpression.");
+                       }
+                       // variable();
+                       foreach_variable();
+                       foreach_optional_arg();
+                       if (token == TokenNameEQUAL_GREATER) {
+                               getNextToken();
+                               variable(false, false);
+                       }
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("')' expected after 'foreach' expression.");
+                       }
+                       foreachStatement();
+                       return statement;
+               } else if (token == TokenNamebreak) {
+                       expression = null;
+                       getNextToken();
+                       if (token != TokenNameSEMICOLON) {
+                               expression = expr();
+                       }
+                       if (token == TokenNameSEMICOLON) {
+                               sourceEnd = scanner.getCurrentTokenEndPosition();
+                               getNextToken();
+                       } else {
+                               if (token != TokenNameINLINE_HTML) {
+                                       throwSyntaxError("';' expected after 'break'.");
+                               }
+                               sourceEnd = scanner.getCurrentTokenEndPosition();
+                               getNextToken();
+                       }
+                       return new BreakStatement(null, sourceStart, sourceEnd);
+               } else if (token == TokenNamecontinue) {
+                       expression = null;
+                       getNextToken();
+                       if (token != TokenNameSEMICOLON) {
+                               expression = expr();
+                       }
+                       if (token == TokenNameSEMICOLON) {
+                               sourceEnd = scanner.getCurrentTokenEndPosition();
+                               getNextToken();
+                       } else {
+                               if (token != TokenNameINLINE_HTML) {
+                                       throwSyntaxError("';' expected after 'continue'.");
+                               }
+                               sourceEnd = scanner.getCurrentTokenEndPosition();
+                               getNextToken();
+                       }
+                       return new ContinueStatement(null, sourceStart, sourceEnd);
+               } else if (token == TokenNamereturn) {
+                       expression = null;
+                       getNextToken();
+                       if (token != TokenNameSEMICOLON) {
+                               expression = expr();
+                       }
+                       if (token == TokenNameSEMICOLON) {
+                               sourceEnd = scanner.getCurrentTokenEndPosition();
+                               getNextToken();
+                       } else {
+                               if (token != TokenNameINLINE_HTML) {
+                                       throwSyntaxError("';' expected after 'return'.");
+                               }
+                               sourceEnd = scanner.getCurrentTokenEndPosition();
+                               getNextToken();
+                       }
+                       return new ReturnStatement(expression, sourceStart, sourceEnd);
+               } else if (token == TokenNameecho) {
+                       getNextToken();
+                       expressionList();
+                       if (token == TokenNameSEMICOLON) {
+                               getNextToken();
+                       } else {
+                               if (token != TokenNameINLINE_HTML) {
+                                       throwSyntaxError("';' expected after 'echo' statement.");
+                               }
+                               getNextToken();
+                       }
+                       return statement;
+               } else if (token == TokenNameECHO_INVISIBLE) {
+                       // 0-length token directly after PHP short tag &lt;?=
+                       getNextToken();
+                       expressionList();
+                       if (token == TokenNameSEMICOLON) {
+                               getNextToken();
+                               // if (token != TokenNameINLINE_HTML) {
+                               // // TODO should this become a configurable warning?
+                               // reportSyntaxError("Probably '?>' expected after PHP short tag
+                               // expression (only the first expression will be echoed).");
+                               // }
+                       } else {
+                               if (token != TokenNameINLINE_HTML) {
+                                       throwSyntaxError("';' expected after PHP short tag '<?=' expression.");
+                               }
+                               getNextToken();
+                       }
+                       return statement;
+               } else if (token == TokenNameINLINE_HTML) {
+                       getNextToken();
+                       return statement;
+               } else if (token == TokenNameglobal) {
+                       getNextToken();
+                       global_var_list();
+                       if (token == TokenNameSEMICOLON) {
+                               getNextToken();
+                       } else {
+                               if (token != TokenNameINLINE_HTML) {
+                                       throwSyntaxError("';' expected after 'global' statement.");
+                               }
+                               getNextToken();
+                       }
+                       return statement;
+               } else if (token == TokenNamestatic) {
+                       getNextToken();
+                       static_var_list();
+                       if (token == TokenNameSEMICOLON) {
+                               getNextToken();
+                       } else {
+                               if (token != TokenNameINLINE_HTML) {
+                                       throwSyntaxError("';' expected after 'static' statement.");
+                               }
+                               getNextToken();
+                       }
+                       return statement;
+               } else if (token == TokenNameunset) {
+                       getNextToken();
+                       if (token == TokenNameLPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("'(' expected after 'unset' statement.");
+                       }
+                       unset_variables();
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("')' expected after 'unset' statement.");
+                       }
+                       if (token == TokenNameSEMICOLON) {
+                               getNextToken();
+                       } else {
+                               if (token != TokenNameINLINE_HTML) {
+                                       throwSyntaxError("';' expected after 'unset' statement.");
+                               }
+                               getNextToken();
+                       }
+                       return statement;
+               } else if (token == TokenNamefunction) {
+                       MethodDeclaration methodDecl = new MethodDeclaration(
+                                       this.compilationUnit.compilationResult);
+                       methodDecl.declarationSourceStart = scanner
+                                       .getCurrentTokenStartPosition();
+                       methodDecl.modifiers = AccDefault;
+                       methodDecl.type = MethodDeclaration.FUNCTION_DEFINITION;
+                       try {
+                               getNextToken();
+                               functionDefinition(methodDecl);
+                       } finally {
+                               sourceEnd = methodDecl.sourceEnd;
+                               if (sourceEnd <= 0
+                                               || methodDecl.declarationSourceStart > sourceEnd) {
+                                       sourceEnd = methodDecl.declarationSourceStart + 1;
+                               }
+                               methodDecl.declarationSourceEnd = sourceEnd;
+                               methodDecl.sourceEnd = sourceEnd;
+                       }
+                       return statement;
+               } else if (token == TokenNamedeclare) {
+                       // T_DECLARE '(' declare_list ')' declare_statement
+                       getNextToken();
+                       if (token != TokenNameLPAREN) {
+                               throwSyntaxError("'(' expected in 'declare' statement.");
+                       }
+                       getNextToken();
+                       declare_list();
+                       if (token != TokenNameRPAREN) {
+                               throwSyntaxError("')' expected in 'declare' statement.");
+                       }
+                       getNextToken();
+                       declare_statement();
+                       return statement;
+               } else if (token == TokenNametry) {
+                       getNextToken();
+                       if (token != TokenNameLBRACE) {
+                               throwSyntaxError("'{' expected in 'try' statement.");
+                       }
+                       getNextToken();
+                       statementList();
+                       if (token != TokenNameRBRACE) {
+                               throwSyntaxError("'}' expected in 'try' statement.");
+                       }
+                       getNextToken();
+                       return statement;
+               } else if (token == TokenNamecatch) {
+                       getNextToken();
+                       if (token != TokenNameLPAREN) {
+                               throwSyntaxError("'(' expected in 'catch' statement.");
+                       }
+                       getNextToken();
+                       fully_qualified_class_name();
+                       if (token != TokenNameVariable) {
+                               throwSyntaxError("Variable expected in 'catch' statement.");
+                       }
+                       addVariableSet();
+                       getNextToken();
+                       if (token != TokenNameRPAREN) {
+                               throwSyntaxError("')' expected in 'catch' statement.");
+                       }
+                       getNextToken();
+                       if (token != TokenNameLBRACE) {
+                               throwSyntaxError("'{' expected in 'catch' statement.");
+                       }
+                       getNextToken();
+                       if (token != TokenNameRBRACE) {
+                               statementList();
+                               if (token != TokenNameRBRACE) {
+                                       throwSyntaxError("'}' expected in 'catch' statement.");
+                               }
+                       }
+                       getNextToken();
+                       additional_catches();
+                       return statement;
+               } else if (token == TokenNamethrow) {
+                       getNextToken();
+                       expr();
+                       if (token == TokenNameSEMICOLON) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("';' expected after 'throw' exxpression.");
+                       }
+                       return statement;
+               } else if (token == TokenNamefinal || token == TokenNameabstract
+                               || token == TokenNameclass || token == TokenNameinterface) {
+                       try {
+                               TypeDeclaration typeDecl = new TypeDeclaration(
+                                               this.compilationUnit.compilationResult);
+                               typeDecl.declarationSourceStart = scanner
+                                               .getCurrentTokenStartPosition();
+                               typeDecl.declarationSourceEnd = scanner
+                                               .getCurrentTokenEndPosition();
+                               typeDecl.name = new char[] { ' ' };
+                               // default super class
+                               typeDecl.superclass = new SingleTypeReference(
+                                               TypeConstants.OBJECT, 0);
+                               compilationUnit.types.add(typeDecl);
+                               pushOnAstStack(typeDecl);
+                               unticked_class_declaration_statement(typeDecl);
+                       } finally {
+                               // reduce stack:
+                               astPtr--;
+                               astLengthPtr--;
+                       }
+                       return statement;
+                       // } else {
+                       // throwSyntaxError("Unexpected keyword '" + keyword + "'");
+               } else if (token == TokenNameLBRACE) {
+                       getNextToken();
+                       if (token != TokenNameRBRACE) {
+                               statement = statementList();
+                       }
+                       if (token == TokenNameRBRACE) {
+                               getNextToken();
+                               return statement;
+                       } else {
+                               throwSyntaxError("'}' expected.");
+                       }
+               } else {
+                       if (token != TokenNameSEMICOLON) {
+                               expr();
+                       }
+                       if (token == TokenNameSEMICOLON) {
+                               getNextToken();
+                               return statement;
+                       } else {
+                               if (token == TokenNameRBRACE) {
+                                       reportSyntaxError("';' expected after expression (Found token: "
+                                                       + scanner.toStringAction(token) + ")");
+                               } else {
+                                       if (token != TokenNameINLINE_HTML && token != TokenNameEOF) {
+                                               throwSyntaxError("';' expected after expression (Found token: "
+                                                               + scanner.toStringAction(token) + ")");
+                                       }
+                                       getNextToken();
+                               }
+                       }
+               }
+               // may be null
+               return statement;
+       }
+
+       private void declare_statement() {
+               // statement
+               // | ':' inner_statement_list T_ENDDECLARE ';'
+               // ;
+               if (token == TokenNameCOLON) {
+                       getNextToken();
+                       // TODO: implement inner_statement_list();
+                       statementList();
+                       if (token != TokenNameenddeclare) {
+                               throwSyntaxError("'enddeclare' expected in 'declare' statement.");
+                       }
+                       getNextToken();
+                       if (token != TokenNameSEMICOLON) {
+                               throwSyntaxError("';' expected after 'enddeclare' keyword.");
+                       }
+                       getNextToken();
+               } else {
+                       statement();
+               }
+       }
+
+       private void declare_list() {
+               // T_STRING '=' static_scalar
+               // | declare_list ',' T_STRING '=' static_scalar
+               while (true) {
+                       if (token != TokenNameIdentifier) {
+                               throwSyntaxError("Identifier expected in 'declare' list.");
+                       }
+                       getNextToken();
+                       if (token != TokenNameEQUAL) {
+                               throwSyntaxError("'=' expected in 'declare' list.");
+                       }
+                       getNextToken();
+                       static_scalar();
+                       if (token != TokenNameCOMMA) {
+                               break;
+                       }
+                       getNextToken();
+               }
+       }
+
+       private void additional_catches() {
+               while (token == TokenNamecatch) {
+                       getNextToken();
+                       if (token != TokenNameLPAREN) {
+                               throwSyntaxError("'(' expected in 'catch' statement.");
+                       }
+                       getNextToken();
+                       fully_qualified_class_name();
+                       if (token != TokenNameVariable) {
+                               throwSyntaxError("Variable expected in 'catch' statement.");
+                       }
+                       addVariableSet();
+                       getNextToken();
+                       if (token != TokenNameRPAREN) {
+                               throwSyntaxError("')' expected in 'catch' statement.");
+                       }
+                       getNextToken();
+                       if (token != TokenNameLBRACE) {
+                               throwSyntaxError("'{' expected in 'catch' statement.");
+                       }
+                       getNextToken();
+                       if (token != TokenNameRBRACE) {
+                               statementList();
+                       }
+                       if (token != TokenNameRBRACE) {
+                               throwSyntaxError("'}' expected in 'catch' statement.");
+                       }
+                       getNextToken();
+               }
+       }
+
+       private void foreach_variable() {
+               // w_variable
+               // | '&' w_variable
+               if (token == TokenNameAND) {
+                       getNextToken();
+               }
+               w_variable(true);
+       }
+
+       private void foreach_optional_arg() {
+               // /* empty */
+               // | T_DOUBLE_ARROW foreach_variable
+               if (token == TokenNameEQUAL_GREATER) {
+                       getNextToken();
+                       foreach_variable();
+               }
+       }
+
+       private void global_var_list() {
+               // global_var_list:
+               // global_var_list ',' global_var
+               // | global_var
+               HashSet set = peekVariableSet();
+               while (true) {
+                       global_var(set);
+                       if (token != TokenNameCOMMA) {
+                               break;
+                       }
+                       getNextToken();
+               }
+       }
+
+       private void global_var(HashSet set) {
+               // global_var:
+               // T_VARIABLE
+               // | '$' r_variable
+               // | '$' '{' expr '}'
+               if (token == TokenNameVariable) {
+                       if (fMethodVariables != null) {
+                               VariableInfo info = new VariableInfo(scanner
+                                               .getCurrentTokenStartPosition(),
+                                               VariableInfo.LEVEL_GLOBAL_VAR);
+                               fMethodVariables.put(new String(scanner
+                                               .getCurrentIdentifierSource()), info);
+                       }
+                       addVariableSet(set);
+                       getNextToken();
+               } else if (token == TokenNameDOLLAR) {
+                       getNextToken();
+                       if (token == TokenNameLBRACE) {
+                               getNextToken();
+                               expr();
+                               if (token != TokenNameRBRACE) {
+                                       throwSyntaxError("'}' expected in global variable.");
+                               }
+                               getNextToken();
+                       } else {
+                               r_variable();
+                       }
+               }
+       }
+
+       private void static_var_list() {
+               // static_var_list:
+               // static_var_list ',' T_VARIABLE
+               // | static_var_list ',' T_VARIABLE '=' static_scalar
+               // | T_VARIABLE
+               // | T_VARIABLE '=' static_scalar,
+               HashSet set = peekVariableSet();
+               while (true) {
+                       if (token == TokenNameVariable) {
+                               if (fMethodVariables != null) {
+                                       VariableInfo info = new VariableInfo(scanner
+                                                       .getCurrentTokenStartPosition(),
+                                                       VariableInfo.LEVEL_STATIC_VAR);
+                                       fMethodVariables.put(new String(scanner
+                                                       .getCurrentIdentifierSource()), info);
+                               }
+                               addVariableSet(set);
+                               getNextToken();
+                               if (token == TokenNameEQUAL) {
+                                       getNextToken();
+                                       static_scalar();
+                               }
+                               if (token != TokenNameCOMMA) {
+                                       break;
+                               }
+                               getNextToken();
+                       } else {
+                               break;
+                       }
+               }
+       }
+
+       private void unset_variables() {
+               // unset_variables:
+               // unset_variable
+               // | unset_variables ',' unset_variable
+               // unset_variable:
+               // variable
+               while (true) {
+                       variable(false, false);
+                       if (token != TokenNameCOMMA) {
+                               break;
+                       }
+                       getNextToken();
+               }
+       }
+
+       private final void initializeModifiers() {
+               this.modifiers = 0;
+               this.modifiersSourceStart = -1;
+       }
+
+       private final void checkAndSetModifiers(int flag) {
+               this.modifiers |= flag;
+               if (this.modifiersSourceStart < 0)
+                       this.modifiersSourceStart = this.scanner.startPosition;
+       }
+
+       private void unticked_class_declaration_statement(TypeDeclaration typeDecl) {
+               initializeModifiers();
+               if (token == TokenNameinterface) {
+                       // interface_entry T_STRING
+                       // interface_extends_list
+                       // '{' class_statement_list '}'
+                       checkAndSetModifiers(AccInterface);
+                       getNextToken();
+                       typeDecl.modifiers = this.modifiers;
+                       typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
+                       typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
+                       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
+                               typeDecl.name = scanner.getCurrentIdentifierSource();
+                               if (token > TokenNameKEYWORD) {
+                                       problemReporter.phpKeywordWarning(new String[] { scanner
+                                                       .toStringAction(token) }, scanner
+                                                       .getCurrentTokenStartPosition(), scanner
+                                                       .getCurrentTokenEndPosition(), referenceContext,
+                                                       compilationUnit.compilationResult);
+                                       // throwSyntaxError("Don't use a keyword for interface
+                                       // declaration ["
+                                       // + scanner.toStringAction(token) + "].",
+                                       // typeDecl.sourceStart, typeDecl.sourceEnd);
+                               }
+                               getNextToken();
+                               interface_extends_list(typeDecl);
+                       } else {
+                               typeDecl.name = new char[] { ' ' };
+                               throwSyntaxError(
+                                               "Interface name expected after keyword 'interface'.",
+                                               typeDecl.sourceStart, typeDecl.sourceEnd);
+                               return;
+                       }
+               } else {
+                       // class_entry_type T_STRING extends_from
+                       // implements_list
+                       // '{' class_statement_list'}'
+                       class_entry_type();
+                       typeDecl.modifiers = this.modifiers;
+                       typeDecl.sourceStart = scanner.getCurrentTokenStartPosition();
+                       typeDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
+                       // identifier
+                       // identifier 'extends' identifier
+                       if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
+                               typeDecl.name = scanner.getCurrentIdentifierSource();
+                               if (token > TokenNameKEYWORD) {
+                                       problemReporter.phpKeywordWarning(new String[] { scanner
+                                                       .toStringAction(token) }, scanner
+                                                       .getCurrentTokenStartPosition(), scanner
+                                                       .getCurrentTokenEndPosition(), referenceContext,
+                                                       compilationUnit.compilationResult);
+                                       // throwSyntaxError("Don't use a keyword for class
+                                       // declaration [" +
+                                       // scanner.toStringAction(token) + "].",
+                                       // typeDecl.sourceStart, typeDecl.sourceEnd);
+                               }
+                               getNextToken();
+                               // extends_from:
+                               // /* empty */
+                               // | T_EXTENDS fully_qualified_class_name
+                               if (token == TokenNameextends) {
+                                       class_extends_list(typeDecl);
+                                       // getNextToken();
+                                       // if (token != TokenNameIdentifier) {
+                                       // throwSyntaxError("Class name expected after keyword
+                                       // 'extends'.",
+                                       // scanner.getCurrentTokenStartPosition(), scanner
+                                       // .getCurrentTokenEndPosition());
+                                       // }
+                               }
+                               implements_list(typeDecl);
+                       } else {
+                               typeDecl.name = new char[] { ' ' };
+                               throwSyntaxError("Class name expected after keyword 'class'.",
+                                               typeDecl.sourceStart, typeDecl.sourceEnd);
+                               return;
+                       }
+               }
+               // '{' class_statement_list '}'
+               if (token == TokenNameLBRACE) {
+                       getNextToken();
+                       if (token != TokenNameRBRACE) {
+                               ArrayList list = new ArrayList();
+                               class_statement_list(list);
+                               typeDecl.fields = new FieldDeclaration[list.size()];
+                               for (int i = 0; i < list.size(); i++) {
+                                       typeDecl.fields[i] = (FieldDeclaration) list.get(i);
+                               }
+                       }
+                       if (token == TokenNameRBRACE) {
+                               typeDecl.declarationSourceEnd = scanner
+                                               .getCurrentTokenEndPosition();
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("'}' expected at end of class body.");
+                       }
+               } else {
+                       throwSyntaxError("'{' expected at start of class body.");
+               }
+       }
+
+       private void class_entry_type() {
+               // T_CLASS
+               // | T_ABSTRACT T_CLASS
+               // | T_FINAL T_CLASS
+               if (token == TokenNameclass) {
+                       getNextToken();
+               } else if (token == TokenNameabstract) {
+                       checkAndSetModifiers(AccAbstract);
+                       getNextToken();
+                       if (token != TokenNameclass) {
+                               throwSyntaxError("Keyword 'class' expected after keyword 'abstract'.");
+                       }
+                       getNextToken();
+               } else if (token == TokenNamefinal) {
+                       checkAndSetModifiers(AccFinal);
+                       getNextToken();
+                       if (token != TokenNameclass) {
+                               throwSyntaxError("Keyword 'class' expected after keyword 'final'.");
+                       }
+                       getNextToken();
+               } else {
+                       throwSyntaxError("Keyword 'class' 'final' or 'abstract' expected");
+               }
+       }
+
+       // private void class_extends(TypeDeclaration typeDecl) {
+       // // /* empty */
+       // // | T_EXTENDS interface_list
+       // if (token == TokenNameextends) {
+       // getNextToken();
+       //
+       // if (token == TokenNameIdentifier) {
+       // getNextToken();
+       // } else {
+       // throwSyntaxError("Class name expected after keyword 'extends'.");
+       // }
+       // }
+       // }
+
+       private void interface_extends_list(TypeDeclaration typeDecl) {
+               // /* empty */
+               // | T_EXTENDS interface_list
+               if (token == TokenNameextends) {
+                       getNextToken();
+                       interface_list(typeDecl);
+               }
+       }
+
+       private void class_extends_list(TypeDeclaration typeDecl) {
+               // /* empty */
+               // | T_EXTENDS interface_list
+               if (token == TokenNameextends) {
+                       getNextToken();
+                       class_list(typeDecl);
+               }
+       }
+
+       private void implements_list(TypeDeclaration typeDecl) {
+               // /* empty */
+               // | T_IMPLEMENTS interface_list
+               if (token == TokenNameimplements) {
+                       getNextToken();
+                       interface_list(typeDecl);
+               }
+       }
+
+       private void class_list(TypeDeclaration typeDecl) {
+               // class_list:
+               // fully_qualified_class_name
+               do {
+                       if (token == TokenNameIdentifier) {
+                               char[] ident = scanner.getCurrentIdentifierSource();
+                               // TODO make this code working better:
+                               // SingleTypeReference ref =
+                               // ParserUtil.getTypeReference(scanner,
+                               // includesList, ident);
+                               // if (ref != null) {
+                               // typeDecl.superclass = ref;
+                               // }
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("Classname expected after keyword 'extends'.");
+                       }
+                       if (token == TokenNameCOMMA) {
+                               reportSyntaxError("No multiple inheritance allowed. Expected token 'implements' or '{'.");
+                               getNextToken();
+                               continue;
+                       } else {
+                               break;
+                       }
+               } while (true);
+       }
+
+       private void interface_list(TypeDeclaration typeDecl) {
+               // interface_list:
+               // fully_qualified_class_name
+               // | interface_list ',' fully_qualified_class_name
+               do {
+                       if (token == TokenNameIdentifier) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("Interfacename expected after keyword 'implements'.");
+                       }
+                       if (token != TokenNameCOMMA) {
+                               return;
+                       }
+                       getNextToken();
+               } while (true);
+       }
+
+       // private void classBody(TypeDeclaration typeDecl) {
+       // //'{' [class-element-list] '}'
+       // if (token == TokenNameLBRACE) {
+       // getNextToken();
+       // if (token != TokenNameRBRACE) {
+       // class_statement_list();
+       // }
+       // if (token == TokenNameRBRACE) {
+       // typeDecl.declarationSourceEnd = scanner.getCurrentTokenEndPosition();
+       // getNextToken();
+       // } else {
+       // throwSyntaxError("'}' expected at end of class body.");
+       // }
+       // } else {
+       // throwSyntaxError("'{' expected at start of class body.");
+       // }
+       // }
+       private void class_statement_list(ArrayList list) {
+               do {
+                       try {
+                               class_statement(list);
+                               if (token == TokenNamepublic || token == TokenNameprotected
+                                               || token == TokenNameprivate
+                                               || token == TokenNamestatic
+                                               || token == TokenNameabstract
+                                               || token == TokenNamefinal
+                                               || token == TokenNamefunction || token == TokenNamevar
+                                               || token == TokenNameconst) {
+                                       continue;
+                               }
+                               if (token == TokenNameRBRACE) {
+                                       break;
+                               }
+                               throwSyntaxError("'}' at end of class statement.");
+                       } catch (SyntaxError sytaxErr1) {
+                               boolean tokenize = scanner.tokenizeStrings;
+                               if (!tokenize) {
+                                       scanner.tokenizeStrings = true;
+                               }
+                               try {
+                                       // if an error occured,
+                                       // try to find keywords
+                                       // to parse the rest of the string
+                                       while (token != TokenNameEOF) {
+                                               if (token == TokenNamepublic
+                                                               || token == TokenNameprotected
+                                                               || token == TokenNameprivate
+                                                               || token == TokenNamestatic
+                                                               || token == TokenNameabstract
+                                                               || token == TokenNamefinal
+                                                               || token == TokenNamefunction
+                                                               || token == TokenNamevar
+                                                               || token == TokenNameconst) {
+                                                       break;
+                                               }
+                                               // System.out.println(scanner.toStringAction(token));
+                                               getNextToken();
+                                       }
+                                       if (token == TokenNameEOF) {
+                                               throw sytaxErr1;
+                                       }
+                               } finally {
+                                       scanner.tokenizeStrings = tokenize;
+                               }
+                       }
+               } while (true);
+       }
+
+       private void class_statement(ArrayList list) {
+               // class_statement:
+               // variable_modifiers class_variable_declaration ';'
+               // | class_constant_declaration ';'
+               // | method_modifiers T_FUNCTION is_reference T_STRING
+               // '(' parameter_list ')' method_body
+               initializeModifiers();
+               int declarationSourceStart = scanner.getCurrentTokenStartPosition();
+
+               if (token == TokenNamevar) {
+                       checkAndSetModifiers(AccPublic);
+                       problemReporter.phpVarDeprecatedWarning(scanner
+                                       .getCurrentTokenStartPosition(), scanner
+                                       .getCurrentTokenEndPosition(), referenceContext,
+                                       compilationUnit.compilationResult);
+                       getNextToken();
+                       class_variable_declaration(declarationSourceStart, list);
+               } else if (token == TokenNameconst) {
+                       checkAndSetModifiers(AccFinal | AccPublic);
+                       class_constant_declaration(declarationSourceStart, list);
+                       if (token != TokenNameSEMICOLON) {
+                               throwSyntaxError("';' expected after class const declaration.");
+                       }
+                       getNextToken();
+               } else {
+                       boolean hasModifiers = member_modifiers();
+                       if (token == TokenNamefunction) {
+                               if (!hasModifiers) {
+                                       checkAndSetModifiers(AccPublic);
+                               }
+                               MethodDeclaration methodDecl = new MethodDeclaration(
+                                               this.compilationUnit.compilationResult);
+                               methodDecl.declarationSourceStart = scanner
+                                               .getCurrentTokenStartPosition();
+                               methodDecl.modifiers = this.modifiers;
+                               methodDecl.type = MethodDeclaration.METHOD_DEFINITION;
+                               try {
+                                       getNextToken();
+                                       functionDefinition(methodDecl);
+                               } finally {
+                                       int sourceEnd = methodDecl.sourceEnd;
+                                       if (sourceEnd <= 0
+                                                       || methodDecl.declarationSourceStart > sourceEnd) {
+                                               sourceEnd = methodDecl.declarationSourceStart + 1;
+                                       }
+                                       methodDecl.declarationSourceEnd = sourceEnd;
+                                       methodDecl.sourceEnd = sourceEnd;
+                               }
+                       } else {
+                               if (!hasModifiers) {
+                                       throwSyntaxError("'public' 'private' or 'protected' modifier expected for field declarations.");
+                               }
+                               class_variable_declaration(declarationSourceStart, list);
+                       }
+               }
+       }
+
+       private void class_constant_declaration(int declarationSourceStart,
+                       ArrayList list) {
+               // class_constant_declaration ',' T_STRING '=' static_scalar
+               // | T_CONST T_STRING '=' static_scalar
+               if (token != TokenNameconst) {
+                       throwSyntaxError("'const' keyword expected in class declaration.");
+               } else {
+                       getNextToken();
+               }
+               while (true) {
+                       if (token != TokenNameIdentifier) {
+                               throwSyntaxError("Identifier expected in class const declaration.");
+                       }
+                       FieldDeclaration fieldDeclaration = new FieldDeclaration(scanner
+                                       .getCurrentIdentifierSource(), scanner
+                                       .getCurrentTokenStartPosition(), scanner
+                                       .getCurrentTokenEndPosition());
+                       fieldDeclaration.modifiers = this.modifiers;
+                       fieldDeclaration.declarationSourceStart = declarationSourceStart;
+                       fieldDeclaration.declarationSourceEnd = scanner
+                                       .getCurrentTokenEndPosition();
+                       fieldDeclaration.modifiersSourceStart = declarationSourceStart;
+                       // fieldDeclaration.type
+                       list.add(fieldDeclaration);
+                       getNextToken();
+                       if (token != TokenNameEQUAL) {
+                               throwSyntaxError("'=' expected in class const declaration.");
+                       }
+                       getNextToken();
+                       static_scalar();
+                       if (token != TokenNameCOMMA) {
+                               break; // while(true)-loop
+                       }
+                       getNextToken();
+               }
+       }
+
+       // private void variable_modifiers() {
+       // // variable_modifiers:
+       // // non_empty_member_modifiers
+       // //| T_VAR
+       // initializeModifiers();
+       // if (token == TokenNamevar) {
+       // checkAndSetModifiers(AccPublic);
+       // reportSyntaxError(
+       // "Keyword 'var' is deprecated. Please use 'public' 'private' or
+       // 'protected'
+       // modifier for field declarations.",
+       // scanner.getCurrentTokenStartPosition(), scanner
+       // .getCurrentTokenEndPosition());
+       // getNextToken();
+       // } else {
+       // if (!member_modifiers()) {
+       // throwSyntaxError("'public' 'private' or 'protected' modifier expected for
+       // field declarations.");
+       // }
+       // }
+       // }
+       // private void method_modifiers() {
+       // //method_modifiers:
+       // // /* empty */
+       // //| non_empty_member_modifiers
+       // initializeModifiers();
+       // if (!member_modifiers()) {
+       // checkAndSetModifiers(AccPublic);
+       // }
+       // }
+       private boolean member_modifiers() {
+               // T_PUBLIC
+               // | T_PROTECTED
+               // | T_PRIVATE
+               // | T_STATIC
+               // | T_ABSTRACT
+               // | T_FINAL
+               boolean foundToken = false;
+               while (true) {
+                       if (token == TokenNamepublic) {
+                               checkAndSetModifiers(AccPublic);
+                               getNextToken();
+                               foundToken = true;
+                       } else if (token == TokenNameprotected) {
+                               checkAndSetModifiers(AccProtected);
+                               getNextToken();
+                               foundToken = true;
+                       } else if (token == TokenNameprivate) {
+                               checkAndSetModifiers(AccPrivate);
+                               getNextToken();
+                               foundToken = true;
+                       } else if (token == TokenNamestatic) {
+                               checkAndSetModifiers(AccStatic);
+                               getNextToken();
+                               foundToken = true;
+                       } else if (token == TokenNameabstract) {
+                               checkAndSetModifiers(AccAbstract);
+                               getNextToken();
+                               foundToken = true;
+                       } else if (token == TokenNamefinal) {
+                               checkAndSetModifiers(AccFinal);
+                               getNextToken();
+                               foundToken = true;
+                       } else {
+                               break;
+                       }
+               }
+               return foundToken;
+       }
+
+       private void class_variable_declaration(int declarationSourceStart,
+                       ArrayList list) {
+               // class_variable_declaration:
+               // class_variable_declaration ',' T_VARIABLE
+               // | class_variable_declaration ',' T_VARIABLE '=' static_scalar
+               // | T_VARIABLE
+               // | T_VARIABLE '=' static_scalar
+               char[] classVariable;
+               do {
+                       if (token == TokenNameVariable) {
+                               classVariable = scanner.getCurrentIdentifierSource();
+                               // indexManager.addIdentifierInformation('v', classVariable,
+                               // buf, -1,
+                               // -1);
+                               FieldDeclaration fieldDeclaration = new FieldDeclaration(
+                                               classVariable, scanner.getCurrentTokenStartPosition(),
+                                               scanner.getCurrentTokenEndPosition());
+                               fieldDeclaration.modifiers = this.modifiers;
+                               fieldDeclaration.declarationSourceStart = declarationSourceStart;
+                               fieldDeclaration.declarationSourceEnd = scanner
+                                               .getCurrentTokenEndPosition();
+                               fieldDeclaration.modifiersSourceStart = declarationSourceStart;
+                               list.add(fieldDeclaration);
+                               if (fTypeVariables != null) {
+                                       VariableInfo info = new VariableInfo(scanner
+                                                       .getCurrentTokenStartPosition(),
+                                                       VariableInfo.LEVEL_CLASS_UNIT);
+                                       fTypeVariables.put(new String(scanner
+                                                       .getCurrentIdentifierSource()), info);
+                               }
+                               getNextToken();
+                               if (token == TokenNameEQUAL) {
+                                       getNextToken();
+                                       static_scalar();
+                               }
+                       } else {
+                               // if (token == TokenNamethis) {
+                               // throwSyntaxError("'$this' not allowed after keyword 'public'
+                               // 'protected' 'private' 'var'.");
+                               // }
+                               throwSyntaxError("Variable expected after keyword 'public' 'protected' 'private' 'var'.");
+                       }
+                       if (token != TokenNameCOMMA) {
+                               break;
+                       }
+                       getNextToken();
+               } while (true);
+               if (token != TokenNameSEMICOLON) {
+                       throwSyntaxError("';' expected after field declaration.");
+               }
+               getNextToken();
+       }
+
+       private void functionDefinition(MethodDeclaration methodDecl) {
+               boolean isAbstract = false;
+               if (astPtr == 0) {
+                       if (compilationUnit != null) {
+                               compilationUnit.types.add(methodDecl);
+                       }
+               } else {
+                       ASTNode node = astStack[astPtr];
+                       if (node instanceof TypeDeclaration) {
+                               TypeDeclaration typeDecl = ((TypeDeclaration) node);
+                               if (typeDecl.methods == null) {
+                                       typeDecl.methods = new AbstractMethodDeclaration[] { methodDecl };
+                               } else {
+                                       AbstractMethodDeclaration[] newMethods;
+                                       System
+                                                       .arraycopy(
+                                                                       typeDecl.methods,
+                                                                       0,
+                                                                       newMethods = new AbstractMethodDeclaration[typeDecl.methods.length + 1],
+                                                                       0, typeDecl.methods.length);
+                                       newMethods[typeDecl.methods.length] = methodDecl;
+                                       typeDecl.methods = newMethods;
+                               }
+                               if ((typeDecl.modifiers & AccAbstract) == AccAbstract) {
+                                       isAbstract = true;
+                               } else if ((typeDecl.modifiers & AccInterface) == AccInterface) {
+                                       isAbstract = true;
+                               }
+                       }
+               }
+               try {
+                       pushFunctionVariableSet();
+                       functionDeclarator(methodDecl);
+                       if (token == TokenNameSEMICOLON) {
+                               if (!isAbstract) {
+                                       methodDecl.sourceEnd = scanner
+                                                       .getCurrentTokenStartPosition() - 1;
+                                       throwSyntaxError("Body declaration expected for method: "
+                                                       + new String(methodDecl.selector));
+                               }
+                               getNextToken();
+                               return;
+                       }
+                       functionBody(methodDecl);
+               } finally {
+                       if (!fStackUnassigned.isEmpty()) {
+                               fStackUnassigned.remove(fStackUnassigned.size() - 1);
+                       }
+               }
+       }
+
+       private void functionDeclarator(MethodDeclaration methodDecl) {
+               // identifier '(' [parameter-list] ')'
+               if (token == TokenNameAND) {
+                       getNextToken();
+               }
+               methodDecl.sourceStart = scanner.getCurrentTokenStartPosition();
+               methodDecl.sourceEnd = scanner.getCurrentTokenEndPosition();
+               if (Scanner.isIdentifierOrKeyword(token)) {
+                       methodDecl.selector = scanner.getCurrentIdentifierSource();
+                       if (token > TokenNameKEYWORD) {
+                               problemReporter.phpKeywordWarning(new String[] { scanner
+                                               .toStringAction(token) }, scanner
+                                               .getCurrentTokenStartPosition(), scanner
+                                               .getCurrentTokenEndPosition(), referenceContext,
+                                               compilationUnit.compilationResult);
+                       }
+                       getNextToken();
+                       if (token == TokenNameLPAREN) {
+                               getNextToken();
+                       } else {
+                               methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
+                               throwSyntaxError("'(' expected in function declaration.");
+                       }
+                       if (token != TokenNameRPAREN) {
+                               parameter_list(methodDecl);
+                       }
+                       if (token != TokenNameRPAREN) {
+                               methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
+                               throwSyntaxError("')' expected in function declaration.");
+                       } else {
+                               methodDecl.bodyStart = scanner.getCurrentTokenEndPosition() + 1;
+                               getNextToken();
+                       }
+               } else {
+                       methodDecl.selector = "<undefined>".toCharArray();
+                       methodDecl.sourceEnd = scanner.getCurrentTokenStartPosition() - 1;
+                       throwSyntaxError("Function name expected after keyword 'function'.");
+               }
+       }
+
+       //
+       private void parameter_list(MethodDeclaration methodDecl) {
+               // non_empty_parameter_list
+               // | /* empty */
+               non_empty_parameter_list(methodDecl, true);
+       }
+
+       private void non_empty_parameter_list(MethodDeclaration methodDecl,
+                       boolean empty_allowed) {
+               // optional_class_type T_VARIABLE
+               // | optional_class_type '&' T_VARIABLE
+               // | optional_class_type '&' T_VARIABLE '=' static_scalar
+               // | optional_class_type T_VARIABLE '=' static_scalar
+               // | non_empty_parameter_list ',' optional_class_type T_VARIABLE
+               // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE
+               // | non_empty_parameter_list ',' optional_class_type '&' T_VARIABLE '='
+               // static_scalar
+               // | non_empty_parameter_list ',' optional_class_type T_VARIABLE '='
+               // static_scalar
+               char[] typeIdentifier = null;
+               if (token == TokenNameIdentifier || token == TokenNamearray
+                               || token == TokenNameVariable || token == TokenNameAND) {
+                       HashSet set = peekVariableSet();
+                       while (true) {
+                               if (token == TokenNameIdentifier || token == TokenNamearray) {// feature
+                                                                                                                                                               // req.
+                                                                                                                                                               // #1254275
+                                       typeIdentifier = scanner.getCurrentIdentifierSource();
+                                       getNextToken();
+                               }
+                               if (token == TokenNameAND) {
+                                       getNextToken();
+                               }
+                               if (token == TokenNameVariable) {
+                                       if (fMethodVariables != null) {
+                                               VariableInfo info;
+                                               if (methodDecl.type == MethodDeclaration.FUNCTION_DEFINITION) {
+                                                       info = new VariableInfo(scanner
+                                                                       .getCurrentTokenStartPosition(),
+                                                                       VariableInfo.LEVEL_FUNCTION_DEFINITION);
+                                               } else {
+                                                       info = new VariableInfo(scanner
+                                                                       .getCurrentTokenStartPosition(),
+                                                                       VariableInfo.LEVEL_METHOD_DEFINITION);
+                                               }
+                                               info.typeIdentifier = typeIdentifier;
+                                               fMethodVariables.put(new String(scanner
+                                                               .getCurrentIdentifierSource()), info);
+                                       }
+                                       addVariableSet(set);
+                                       getNextToken();
+                                       if (token == TokenNameEQUAL) {
+                                               getNextToken();
+                                               static_scalar();
+                                       }
+                               } else {
+                                       throwSyntaxError("Variable expected in parameter list.");
+                               }
+                               if (token != TokenNameCOMMA) {
+                                       break;
+                               }
+                               getNextToken();
+                       }
+                       return;
+               }
+               if (!empty_allowed) {
+                       throwSyntaxError("Identifier expected in parameter list.");
+               }
+       }
+
+       private void optional_class_type() {
+               // /* empty */
+               // | T_STRING
+       }
+
+       // private void parameterDeclaration() {
+       // //variable
+       // //variable-reference
+       // if (token == TokenNameAND) {
+       // getNextToken();
+       // if (isVariable()) {
+       // getNextToken();
+       // } else {
+       // throwSyntaxError("Variable expected after reference operator '&'.");
+       // }
+       // }
+       // //variable '=' constant
+       // if (token == TokenNameVariable) {
+       // getNextToken();
+       // if (token == TokenNameEQUAL) {
+       // getNextToken();
+       // static_scalar();
+       // }
+       // return;
+       // }
+       // // if (token == TokenNamethis) {
+       // // throwSyntaxError("Reserved word '$this' not allowed in parameter
+       // // declaration.");
+       // // }
+       // }
+
+       private void labeledStatementList() {
+               if (token != TokenNamecase && token != TokenNamedefault) {
+                       throwSyntaxError("'case' or 'default' expected.");
+               }
+               do {
+                       if (token == TokenNamecase) {
+                               getNextToken();
+                               expr(); // constant();
+                               if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
+                                       getNextToken();
+                                       if (token == TokenNameRBRACE) {
+                                               // empty case; assumes that the '}' token belongs to the
+                                               // wrapping
+                                               // switch statement - #1371992
+                                               break;
+                                       }
+                                       if (token == TokenNamecase || token == TokenNamedefault) {
+                                               // empty case statement ?
+                                               continue;
+                                       }
+                                       statementList();
+                               }
+                               // else if (token == TokenNameSEMICOLON) {
+                               // setMarker(
+                               // "':' expected after 'case' keyword (Found token: " +
+                               // scanner.toStringAction(token) + ")",
+                               // scanner.getCurrentTokenStartPosition(),
+                               // scanner.getCurrentTokenEndPosition(),
+                               // INFO);
+                               // getNextToken();
+                               // if (token == TokenNamecase) { // empty case statement ?
+                               // continue;
+                               // }
+                               // statementList();
+                               // }
+                               else {
+                                       throwSyntaxError("':' character expected after 'case' constant (Found token: "
+                                                       + scanner.toStringAction(token) + ")");
+                               }
+                       } else { // TokenNamedefault
+                               getNextToken();
+                               if (token == TokenNameCOLON || token == TokenNameSEMICOLON) {
+                                       getNextToken();
+                                       if (token == TokenNameRBRACE) {
+                                               // empty default case; ; assumes that the '}' token
+                                               // belongs to the
+                                               // wrapping switch statement - #1371992
+                                               break;
+                                       }
+                                       if (token != TokenNamecase) {
+                                               statementList();
+                                       }
+                               } else {
+                                       throwSyntaxError("':' character expected after 'default'.");
+                               }
+                       }
+               } while (token == TokenNamecase || token == TokenNamedefault);
+       }
+
+       private void ifStatementColon(IfStatement iState) {
+               // T_IF '(' expr ')' ':' inner_statement_list new_elseif_list
+               // new_else_single T_ENDIF ';'
+               HashSet assignedVariableSet = null;
+               try {
+                       Block b = inner_statement_list();
+                       iState.thenStatement = b;
+                       checkUnreachable(iState, b);
+               } finally {
+                       assignedVariableSet = removeIfVariableSet();
+               }
+               if (token == TokenNameelseif) {
+                       try {
+                               pushIfVariableSet();
+                               new_elseif_list(iState);
+                       } finally {
+                               HashSet set = removeIfVariableSet();
+                               if (assignedVariableSet != null && set != null) {
+                                       assignedVariableSet.addAll(set);
+                               }
+                       }
+               }
+               try {
+                       pushIfVariableSet();
+                       new_else_single(iState);
+               } finally {
+                       HashSet set = removeIfVariableSet();
+                       if (assignedVariableSet != null) {
+                               HashSet topSet = peekVariableSet();
+                               if (topSet != null) {
+                                       if (set != null) {
+                                               topSet.addAll(set);
+                                       }
+                                       topSet.addAll(assignedVariableSet);
+                               }
+                       }
+               }
+               if (token != TokenNameendif) {
+                       throwSyntaxError("'endif' expected.");
+               }
+               getNextToken();
+               if (token != TokenNameSEMICOLON) {
+                       reportSyntaxError("';' expected after if-statement.");
+                       iState.sourceEnd = scanner.getCurrentTokenStartPosition();
+               } else {
+                       iState.sourceEnd = scanner.getCurrentTokenEndPosition();
+                       getNextToken();
+               }
+       }
+
+       private void ifStatement(IfStatement iState) {
+               // T_IF '(' expr ')' statement elseif_list else_single
+               HashSet assignedVariableSet = null;
+               try {
+                       pushIfVariableSet();
+                       Statement s = statement();
+                       iState.thenStatement = s;
+                       checkUnreachable(iState, s);
+               } finally {
+                       assignedVariableSet = removeIfVariableSet();
+               }
+
+               if (token == TokenNameelseif) {
+                       try {
+                               pushIfVariableSet();
+                               elseif_list(iState);
+                       } finally {
+                               HashSet set = removeIfVariableSet();
+                               if (assignedVariableSet != null && set != null) {
+                                       assignedVariableSet.addAll(set);
+                               }
+                       }
+               }
+               try {
+                       pushIfVariableSet();
+                       else_single(iState);
+               } finally {
+                       HashSet set = removeIfVariableSet();
+                       if (assignedVariableSet != null) {
+                               HashSet topSet = peekVariableSet();
+                               if (topSet != null) {
+                                       if (set != null) {
+                                               topSet.addAll(set);
+                                       }
+                                       topSet.addAll(assignedVariableSet);
+                               }
+                       }
+               }
+       }
+
+       private void elseif_list(IfStatement iState) {
+               // /* empty */
+               // | elseif_list T_ELSEIF '(' expr ')' statement
+               ArrayList conditionList = new ArrayList();
+               ArrayList statementList = new ArrayList();
+               Expression e;
+               Statement s;
+               while (token == TokenNameelseif) {
+                       getNextToken();
+                       if (token == TokenNameLPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("'(' expected after 'elseif' keyword.");
+                       }
+                       e = expr();
+                       conditionList.add(e);
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("')' expected after 'elseif' condition.");
+                       }
+                       s = statement();
+                       statementList.add(s);
+                       checkUnreachable(iState, s);
+               }
+               iState.elseifConditions = new Expression[conditionList.size()];
+               iState.elseifStatements = new Statement[statementList.size()];
+               conditionList.toArray(iState.elseifConditions);
+               statementList.toArray(iState.elseifStatements);
+       }
+
+       private void new_elseif_list(IfStatement iState) {
+               // /* empty */
+               // | new_elseif_list T_ELSEIF '(' expr ')' ':' inner_statement_list
+               ArrayList conditionList = new ArrayList();
+               ArrayList statementList = new ArrayList();
+               Expression e;
+               Block b;
+               while (token == TokenNameelseif) {
+                       getNextToken();
+                       if (token == TokenNameLPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("'(' expected after 'elseif' keyword.");
+                       }
+                       e = expr();
+                       conditionList.add(e);
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("')' expected after 'elseif' condition.");
+                       }
+                       if (token == TokenNameCOLON) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("':' expected after 'elseif' keyword.");
+                       }
+                       b = inner_statement_list();
+                       statementList.add(b);
+                       checkUnreachable(iState, b);
+               }
+               iState.elseifConditions = new Expression[conditionList.size()];
+               iState.elseifStatements = new Statement[statementList.size()];
+               conditionList.toArray(iState.elseifConditions);
+               statementList.toArray(iState.elseifStatements);
+       }
+
+       private void else_single(IfStatement iState) {
+               // /* empty */
+               // T_ELSE statement
+               if (token == TokenNameelse) {
+                       getNextToken();
+                       Statement s = statement();
+                       iState.elseStatement = s;
+                       checkUnreachable(iState, s);
+               } else {
+                       iState.checkUnreachable = false;
+               }
+               iState.sourceEnd = scanner.getCurrentTokenStartPosition();
+       }
+
+       private void new_else_single(IfStatement iState) {
+               // /* empty */
+               // | T_ELSE ':' inner_statement_list
+               if (token == TokenNameelse) {
+                       getNextToken();
+                       if (token == TokenNameCOLON) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("':' expected after 'else' keyword.");
+                       }
+                       Block b = inner_statement_list();
+                       iState.elseStatement = b;
+                       checkUnreachable(iState, b);
+               } else {
+                       iState.checkUnreachable = false;
+               }
+       }
+
+       private Block inner_statement_list() {
+               // inner_statement_list inner_statement
+               // /* empty */
+               return statementList();
+       }
+
+       /**
+        * @param iState
+        * @param b
+        */
+       private void checkUnreachable(IfStatement iState, Statement s) {
+               if (s instanceof Block) {
+                       Block b = (Block) s;
+                       if (b.statements == null || b.statements.length == 0) {
+                               iState.checkUnreachable = false;
+                       } else {
+                               int off = b.statements.length - 1;
+                               if (!(b.statements[off] instanceof ReturnStatement)
+                                               && !(b.statements[off] instanceof ContinueStatement)
+                                               && !(b.statements[off] instanceof BreakStatement)) {
+                                       if (!(b.statements[off] instanceof IfStatement)
+                                                       || !((IfStatement) b.statements[off]).checkUnreachable) {
+                                               iState.checkUnreachable = false;
+                                       }
+                               }
+                       }
+               } else {
+                       if (!(s instanceof ReturnStatement)
+                                       && !(s instanceof ContinueStatement)
+                                       && !(s instanceof BreakStatement)) {
+                               if (!(s instanceof IfStatement)
+                                               || !((IfStatement) s).checkUnreachable) {
+                                       iState.checkUnreachable = false;
+                               }
+                       }
+               }
+       }
+
+       // private void elseifStatementList() {
+       // do {
+       // elseifStatement();
+       // switch (token) {
+       // case TokenNameelse:
+       // getNextToken();
+       // if (token == TokenNameCOLON) {
+       // getNextToken();
+       // if (token != TokenNameendif) {
+       // statementList();
+       // }
+       // return;
+       // } else {
+       // if (token == TokenNameif) { //'else if'
+       // getNextToken();
+       // } else {
+       // throwSyntaxError("':' expected after 'else'.");
+       // }
+       // }
+       // break;
+       // case TokenNameelseif:
+       // getNextToken();
+       // break;
+       // default:
+       // return;
+       // }
+       // } while (true);
+       // }
+
+       // private void elseifStatement() {
+       // if (token == TokenNameLPAREN) {
+       // getNextToken();
+       // expr();
+       // if (token != TokenNameRPAREN) {
+       // throwSyntaxError("')' expected in else-if-statement.");
+       // }
+       // getNextToken();
+       // if (token != TokenNameCOLON) {
+       // throwSyntaxError("':' expected in else-if-statement.");
+       // }
+       // getNextToken();
+       // if (token != TokenNameendif) {
+       // statementList();
+       // }
+       // }
+       // }
+
+       private void switchStatement() {
+               if (token == TokenNameCOLON) {
+                       // ':' [labeled-statement-list] 'endswitch' ';'
+                       getNextToken();
+                       labeledStatementList();
+                       if (token != TokenNameendswitch) {
+                               throwSyntaxError("'endswitch' expected.");
+                       }
+                       getNextToken();
+                       if (token != TokenNameSEMICOLON) {
+                               throwSyntaxError("';' expected after switch-statement.");
+                       }
+                       getNextToken();
+               } else {
+                       // '{' [labeled-statement-list] '}'
+                       if (token != TokenNameLBRACE) {
+                               throwSyntaxError("'{' expected in switch statement.");
+                       }
+                       getNextToken();
+                       if (token != TokenNameRBRACE) {
+                               labeledStatementList();
+                       }
+                       if (token != TokenNameRBRACE) {
+                               throwSyntaxError("'}' expected in switch statement.");
+                       }
+                       getNextToken();
+               }
+       }
+
+       private void forStatement() {
+               if (token == TokenNameCOLON) {
+                       getNextToken();
+                       statementList();
+                       if (token != TokenNameendfor) {
+                               throwSyntaxError("'endfor' expected.");
+                       }
+                       getNextToken();
+                       if (token != TokenNameSEMICOLON) {
+                               throwSyntaxError("';' expected after for-statement.");
+                       }
+                       getNextToken();
+               } else {
+                       statement();
+               }
+       }
+
+       private void whileStatement() {
+               // ':' statement-list 'endwhile' ';'
+               if (token == TokenNameCOLON) {
+                       getNextToken();
+                       statementList();
+                       if (token != TokenNameendwhile) {
+                               throwSyntaxError("'endwhile' expected.");
+                       }
+                       getNextToken();
+                       if (token != TokenNameSEMICOLON) {
+                               throwSyntaxError("';' expected after while-statement.");
+                       }
+                       getNextToken();
+               } else {
+                       statement();
+               }
+       }
+
+       private void foreachStatement() {
+               if (token == TokenNameCOLON) {
+                       getNextToken();
+                       statementList();
+                       if (token != TokenNameendforeach) {
+                               throwSyntaxError("'endforeach' expected.");
+                       }
+                       getNextToken();
+                       if (token != TokenNameSEMICOLON) {
+                               throwSyntaxError("';' expected after foreach-statement.");
+                       }
+                       getNextToken();
+               } else {
+                       statement();
+               }
+       }
+
+       // private void exitStatus() {
+       // if (token == TokenNameLPAREN) {
+       // getNextToken();
+       // } else {
+       // throwSyntaxError("'(' expected in 'exit-status'.");
+       // }
+       // if (token != TokenNameRPAREN) {
+       // expression();
+       // }
+       // if (token == TokenNameRPAREN) {
+       // getNextToken();
+       // } else {
+       // throwSyntaxError("')' expected after 'exit-status'.");
+       // }
+       // }
+       private void expressionList() {
+               do {
+                       expr();
+                       if (token == TokenNameCOMMA) {
+                               getNextToken();
+                       } else {
+                               break;
+                       }
+               } while (true);
+       }
+
+       private Expression expr() {
+               // r_variable
+               // | expr_without_variable
+               // if (token!=TokenNameEOF) {
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: expr()");
+               }
+               return expr_without_variable(true, null);
+               // }
+       }
+
+       private Expression expr_without_variable(boolean only_variable,
+                       UninitializedVariableHandler initHandler) {
+               int exprSourceStart = scanner.getCurrentTokenStartPosition();
+               int exprSourceEnd = scanner.getCurrentTokenEndPosition();
+               Expression expression = new Expression();
+               expression.sourceStart = exprSourceStart;
+               // default, may be overwritten
+               expression.sourceEnd = exprSourceEnd;
+               try {
+                       // internal_functions_in_yacc
+                       // | T_CLONE expr
+                       // | T_PRINT expr
+                       // | '(' expr ')'
+                       // | '@' expr
+                       // | '+' expr
+                       // | '-' expr
+                       // | '!' expr
+                       // | '~' expr
+                       // | T_INC rw_variable
+                       // | T_DEC rw_variable
+                       // | T_INT_CAST expr
+                       // | T_DOUBLE_CAST expr
+                       // | T_STRING_CAST expr
+                       // | T_ARRAY_CAST expr
+                       // | T_OBJECT_CAST expr
+                       // | T_BOOL_CAST expr
+                       // | T_UNSET_CAST expr
+                       // | T_EXIT exit_expr
+                       // | scalar
+                       // | T_ARRAY '(' array_pair_list ')'
+                       // | '`' encaps_list '`'
+                       // | T_LIST '(' assignment_list ')' '=' expr
+                       // | T_NEW class_name_reference ctor_arguments
+                       // | variable '=' expr
+                       // | variable '=' '&' variable
+                       // | variable '=' '&' T_NEW class_name_reference ctor_arguments
+                       // | variable T_PLUS_EQUAL expr
+                       // | variable T_MINUS_EQUAL expr
+                       // | variable T_MUL_EQUAL expr
+                       // | variable T_DIV_EQUAL expr
+                       // | variable T_CONCAT_EQUAL expr
+                       // | variable T_MOD_EQUAL expr
+                       // | variable T_AND_EQUAL expr
+                       // | variable T_OR_EQUAL expr
+                       // | variable T_XOR_EQUAL expr
+                       // | variable T_SL_EQUAL expr
+                       // | variable T_SR_EQUAL expr
+                       // | rw_variable T_INC
+                       // | rw_variable T_DEC
+                       // | expr T_BOOLEAN_OR expr
+                       // | expr T_BOOLEAN_AND expr
+                       // | expr T_LOGICAL_OR expr
+                       // | expr T_LOGICAL_AND expr
+                       // | expr T_LOGICAL_XOR expr
+                       // | expr '|' expr
+                       // | expr '&' expr
+                       // | expr '^' expr
+                       // | expr '.' expr
+                       // | expr '+' expr
+                       // | expr '-' expr
+                       // | expr '*' expr
+                       // | expr '/' expr
+                       // | expr '%' expr
+                       // | expr T_SL expr
+                       // | expr T_SR expr
+                       // | expr T_IS_IDENTICAL expr
+                       // | expr T_IS_NOT_IDENTICAL expr
+                       // | expr T_IS_EQUAL expr
+                       // | expr T_IS_NOT_EQUAL expr
+                       // | expr '<' expr
+                       // | expr T_IS_SMALLER_OR_EQUAL expr
+                       // | expr '>' expr
+                       // | expr T_IS_GREATER_OR_EQUAL expr
+                       // | expr T_INSTANCEOF class_name_reference
+                       // | expr '?' expr ':' expr
+                       if (Scanner.TRACE) {
+                               System.out.println("TRACE: expr_without_variable() PART 1");
+                       }
+                       switch (token) {
+                       case TokenNameisset:
+                               // T_ISSET '(' isset_variables ')'
+                               getNextToken();
+                               if (token != TokenNameLPAREN) {
+                                       throwSyntaxError("'(' expected after keyword 'isset'");
+                               }
+                               getNextToken();
+                               isset_variables();
+                               if (token != TokenNameRPAREN) {
+                                       throwSyntaxError("')' expected after keyword 'isset'");
+                               }
+                               getNextToken();
+                               break;
+                       case TokenNameempty:
+                               getNextToken();
+                               if (token != TokenNameLPAREN) {
+                                       throwSyntaxError("'(' expected after keyword 'empty'");
+                               }
+                               getNextToken();
+                               variable(true, false);
+                               if (token != TokenNameRPAREN) {
+                                       throwSyntaxError("')' expected after keyword 'empty'");
+                               }
+                               getNextToken();
+                               break;
+                       case TokenNameeval:
+                       case TokenNameinclude:
+                       case TokenNameinclude_once:
+                       case TokenNamerequire:
+                       case TokenNamerequire_once:
+                               internal_functions_in_yacc();
+                               break;
+                       // | '(' expr ')'
+                       case TokenNameLPAREN:
+                               getNextToken();
+                               expr();
+                               if (token == TokenNameRPAREN) {
+                                       getNextToken();
+                               } else {
+                                       throwSyntaxError("')' expected in expression.");
+                               }
+                               break;
+                       // | T_CLONE expr
+                       // | T_PRINT expr
+                       // | '@' expr
+                       // | '+' expr
+                       // | '-' expr
+                       // | '!' expr
+                       // | '~' expr
+                       // | T_INT_CAST expr
+                       // | T_DOUBLE_CAST expr
+                       // | T_STRING_CAST expr
+                       // | T_ARRAY_CAST expr
+                       // | T_OBJECT_CAST expr
+                       // | T_BOOL_CAST expr
+                       // | T_UNSET_CAST expr
+                       case TokenNameclone:
+                       case TokenNameprint:
+                       case TokenNameAT:
+                       case TokenNamePLUS:
+                       case TokenNameMINUS:
+                       case TokenNameNOT:
+                       case TokenNameTWIDDLE:
+                       case TokenNameintCAST:
+                       case TokenNamedoubleCAST:
+                       case TokenNamestringCAST:
+                       case TokenNamearrayCAST:
+                       case TokenNameobjectCAST:
+                       case TokenNameboolCAST:
+                       case TokenNameunsetCAST:
+                               getNextToken();
+                               expr();
+                               break;
+                       case TokenNameexit:
+                               getNextToken();
+                               exit_expr();
+                               break;
+                       // scalar:
+                       // T_STRING
+                       // | T_STRING_VARNAME
+                       // | class_constant
+                       // | T_START_HEREDOC encaps_list T_END_HEREDOC
+                       // | '`' encaps_list '`'
+                       // | common_scalar
+                       // | '`' encaps_list '`'
+                       // case TokenNameEncapsedString0:
+                       // scanner.encapsedStringStack.push(new Character('`'));
+                       // getNextToken();
+                       // try {
+                       // if (token == TokenNameEncapsedString0) {
+                       // } else {
+                       // encaps_list();
+                       // if (token != TokenNameEncapsedString0) {
+                       // throwSyntaxError("\'`\' expected at end of string" + "(Found
+                       // token: " +
+                       // scanner.toStringAction(token) + " )");
+                       // }
+                       // }
+                       // } finally {
+                       // scanner.encapsedStringStack.pop();
+                       // getNextToken();
+                       // }
+                       // break;
+                       // // | '\'' encaps_list '\''
+                       // case TokenNameEncapsedString1:
+                       // scanner.encapsedStringStack.push(new Character('\''));
+                       // getNextToken();
+                       // try {
+                       // exprSourceStart = scanner.getCurrentTokenStartPosition();
+                       // if (token == TokenNameEncapsedString1) {
+                       // expression = new
+                       // StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
+                       // exprSourceStart, scanner
+                       // .getCurrentTokenEndPosition());
+                       // } else {
+                       // encaps_list();
+                       // if (token != TokenNameEncapsedString1) {
+                       // throwSyntaxError("\'\'\' expected at end of string" + "(Found
+                       // token: "
+                       // + scanner.toStringAction(token) + " )");
+                       // } else {
+                       // expression = new
+                       // StringLiteralSQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
+                       // exprSourceStart, scanner
+                       // .getCurrentTokenEndPosition());
+                       // }
+                       // }
+                       // } finally {
+                       // scanner.encapsedStringStack.pop();
+                       // getNextToken();
+                       // }
+                       // break;
+                       // //| '"' encaps_list '"'
+                       // case TokenNameEncapsedString2:
+                       // scanner.encapsedStringStack.push(new Character('"'));
+                       // getNextToken();
+                       // try {
+                       // exprSourceStart = scanner.getCurrentTokenStartPosition();
+                       // if (token == TokenNameEncapsedString2) {
+                       // expression = new
+                       // StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
+                       // exprSourceStart, scanner
+                       // .getCurrentTokenEndPosition());
+                       // } else {
+                       // encaps_list();
+                       // if (token != TokenNameEncapsedString2) {
+                       // throwSyntaxError("'\"' expected at end of string" + "(Found
+                       // token: " +
+                       // scanner.toStringAction(token) + " )");
+                       // } else {
+                       // expression = new
+                       // StringLiteralDQ(scanner.getCurrentStringLiteralSource(exprSourceStart),
+                       // exprSourceStart, scanner
+                       // .getCurrentTokenEndPosition());
+                       // }
+                       // }
+                       // } finally {
+                       // scanner.encapsedStringStack.pop();
+                       // getNextToken();
+                       // }
+                       // break;
+                       case TokenNameStringDoubleQuote:
+                               expression = new StringLiteralDQ(scanner
+                                               .getCurrentStringLiteralSource(), scanner
+                                               .getCurrentTokenStartPosition(), scanner
+                                               .getCurrentTokenEndPosition());
+                               common_scalar();
+                               break;
+                       case TokenNameStringSingleQuote:
+                               expression = new StringLiteralSQ(scanner
+                                               .getCurrentStringLiteralSource(), scanner
+                                               .getCurrentTokenStartPosition(), scanner
+                                               .getCurrentTokenEndPosition());
+                               common_scalar();
+                               break;
+                       case TokenNameIntegerLiteral:
+                       case TokenNameDoubleLiteral:
+                       case TokenNameStringInterpolated:
+                       case TokenNameFILE:
+                       case TokenNameLINE:
+                       case TokenNameCLASS_C:
+                       case TokenNameMETHOD_C:
+                       case TokenNameFUNC_C:
+                               common_scalar();
+                               break;
+                       case TokenNameHEREDOC:
+                               getNextToken();
+                               break;
+                       case TokenNamearray:
+                               // T_ARRAY '(' array_pair_list ')'
+                               getNextToken();
+                               if (token == TokenNameLPAREN) {
+                                       getNextToken();
+                                       if (token == TokenNameRPAREN) {
+                                               getNextToken();
+                                               break;
+                                       }
+                                       array_pair_list();
+                                       if (token != TokenNameRPAREN) {
+                                               throwSyntaxError("')' or ',' expected after keyword 'array'"
+                                                               + "(Found token: "
+                                                               + scanner.toStringAction(token) + ")");
+                                       }
+                                       getNextToken();
+                               } else {
+                                       throwSyntaxError("'(' expected after keyword 'array'"
+                                                       + "(Found token: " + scanner.toStringAction(token)
+                                                       + ")");
+                               }
+                               break;
+                       case TokenNamelist:
+                               // | T_LIST '(' assignment_list ')' '=' expr
+                               getNextToken();
+                               if (token == TokenNameLPAREN) {
+                                       getNextToken();
+                                       assignment_list();
+                                       if (token != TokenNameRPAREN) {
+                                               throwSyntaxError("')' expected after 'list' keyword.");
+                                       }
+                                       getNextToken();
+                                       if (token != TokenNameEQUAL) {
+                                               throwSyntaxError("'=' expected after 'list' keyword.");
+                                       }
+                                       getNextToken();
+                                       expr();
+                               } else {
+                                       throwSyntaxError("'(' expected after 'list' keyword.");
+                               }
+                               break;
+                       case TokenNamenew:
+                               // | T_NEW class_name_reference ctor_arguments
+                               getNextToken();
+                               Expression typeRef = class_name_reference();
+                               ctor_arguments();
+                               if (typeRef != null) {
+                                       expression = typeRef;
+                               }
+                               break;
+                       // | T_INC rw_variable
+                       // | T_DEC rw_variable
+                       case TokenNamePLUS_PLUS:
+                       case TokenNameMINUS_MINUS:
+                               getNextToken();
+                               rw_variable();
+                               break;
+                       // | variable '=' expr
+                       // | variable '=' '&' variable
+                       // | variable '=' '&' T_NEW class_name_reference ctor_arguments
+                       // | variable T_PLUS_EQUAL expr
+                       // | variable T_MINUS_EQUAL expr
+                       // | variable T_MUL_EQUAL expr
+                       // | variable T_DIV_EQUAL expr
+                       // | variable T_CONCAT_EQUAL expr
+                       // | variable T_MOD_EQUAL expr
+                       // | variable T_AND_EQUAL expr
+                       // | variable T_OR_EQUAL expr
+                       // | variable T_XOR_EQUAL expr
+                       // | variable T_SL_EQUAL expr
+                       // | variable T_SR_EQUAL expr
+                       // | rw_variable T_INC
+                       // | rw_variable T_DEC
+                       case TokenNameIdentifier:
+                       case TokenNameVariable:
+                       case TokenNameDOLLAR:
+                               Expression lhs = null;
+                               boolean rememberedVar = false;
+                               if (token == TokenNameIdentifier) {
+                                       lhs = identifier(true, true);
+                                       if (lhs != null) {
+                                               expression = lhs;
+                                       }
+                               } else {
+                                       lhs = variable(true, true);
+                                       if (lhs != null) {
+                                               expression = lhs;
+                                       }
+                                       if (lhs != null && lhs instanceof FieldReference
+                                                       && token != TokenNameEQUAL
+                                                       && token != TokenNamePLUS_EQUAL
+                                                       && token != TokenNameMINUS_EQUAL
+                                                       && token != TokenNameMULTIPLY_EQUAL
+                                                       && token != TokenNameDIVIDE_EQUAL
+                                                       && token != TokenNameDOT_EQUAL
+                                                       && token != TokenNameREMAINDER_EQUAL
+                                                       && token != TokenNameAND_EQUAL
+                                                       && token != TokenNameOR_EQUAL
+                                                       && token != TokenNameXOR_EQUAL
+                                                       && token != TokenNameRIGHT_SHIFT_EQUAL
+                                                       && token != TokenNameLEFT_SHIFT_EQUAL) {
+                                               FieldReference ref = (FieldReference) lhs;
+                                               if (!containsVariableSet(ref.token)) {
+                                                       if (null == initHandler
+                                                                       || initHandler.reportError()) {
+                                                               problemReporter.uninitializedLocalVariable(
+                                                                               new String(ref.token), ref.sourceStart,
+                                                                               ref.sourceEnd, referenceContext,
+                                                                               compilationUnit.compilationResult);
+                                                       }
+                                                       addVariableSet(ref.token);
+                                               }
+                                       }
+                               }
+                               switch (token) {
+                               case TokenNameEQUAL:
+                                       if (lhs != null && lhs instanceof FieldReference) {
+                                               addVariableSet(((FieldReference) lhs).token);
+                                       }
+                                       getNextToken();
+                                       if (token == TokenNameAND) {
+                                               getNextToken();
+                                               if (token == TokenNamenew) {
+                                                       // | variable '=' '&' T_NEW class_name_reference
+                                                       // ctor_arguments
+                                                       getNextToken();
+                                                       SingleTypeReference classRef = class_name_reference();
+                                                       ctor_arguments();
+                                                       if (classRef != null) {
+                                                               if (lhs != null
+                                                                               && lhs instanceof FieldReference) {
+                                                                       // example:
+                                                                       // $var = & new Object();
+                                                                       if (fMethodVariables != null) {
+                                                                               VariableInfo lhsInfo = new VariableInfo(
+                                                                                               ((FieldReference) lhs).sourceStart);
+                                                                               lhsInfo.reference = classRef;
+                                                                               lhsInfo.typeIdentifier = classRef.token;
+                                                                               fMethodVariables.put(new String(
+                                                                                               ((FieldReference) lhs).token),
+                                                                                               lhsInfo);
+                                                                               rememberedVar = true;
+                                                                       }
+                                                               }
+                                                       }
+                                               } else {
+                                                       Expression rhs = variable(false, false);
+                                                       if (rhs != null && rhs instanceof FieldReference
+                                                                       && lhs != null
+                                                                       && lhs instanceof FieldReference) {
+                                                               // example:
+                                                               // $var = &$ref;
+                                                               if (fMethodVariables != null) {
+                                                                       VariableInfo rhsInfo = (VariableInfo) fMethodVariables
+                                                                                       .get(((FieldReference) rhs).token);
+                                                                       if (rhsInfo != null
+                                                                                       && rhsInfo.reference != null) {
+                                                                               VariableInfo lhsInfo = new VariableInfo(
+                                                                                               ((FieldReference) lhs).sourceStart);
+                                                                               lhsInfo.reference = rhsInfo.reference;
+                                                                               lhsInfo.typeIdentifier = rhsInfo.typeIdentifier;
+                                                                               fMethodVariables.put(new String(
+                                                                                               ((FieldReference) lhs).token),
+                                                                                               lhsInfo);
+                                                                               rememberedVar = true;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       } else {
+                                               Expression rhs = expr();
+                                               if (lhs != null && lhs instanceof FieldReference) {
+                                                       if (rhs != null && rhs instanceof FieldReference) {
+                                                               // example:
+                                                               // $var = $ref;
+                                                               if (fMethodVariables != null) {
+                                                                       VariableInfo rhsInfo = (VariableInfo) fMethodVariables
+                                                                                       .get(((FieldReference) rhs).token);
+                                                                       if (rhsInfo != null
+                                                                                       && rhsInfo.reference != null) {
+                                                                               VariableInfo lhsInfo = new VariableInfo(
+                                                                                               ((FieldReference) lhs).sourceStart);
+                                                                               lhsInfo.reference = rhsInfo.reference;
+                                                                               lhsInfo.typeIdentifier = rhsInfo.typeIdentifier;
+                                                                               fMethodVariables.put(new String(
+                                                                                               ((FieldReference) lhs).token),
+                                                                                               lhsInfo);
+                                                                               rememberedVar = true;
+                                                                       }
+                                                               }
+                                                       } else if (rhs != null
+                                                                       && rhs instanceof SingleTypeReference) {
+                                                               // example:
+                                                               // $var = new Object();
+                                                               if (fMethodVariables != null) {
+                                                                       VariableInfo lhsInfo = new VariableInfo(
+                                                                                       ((FieldReference) lhs).sourceStart);
+                                                                       lhsInfo.reference = (SingleTypeReference) rhs;
+                                                                       lhsInfo.typeIdentifier = ((SingleTypeReference) rhs).token;
+                                                                       fMethodVariables.put(new String(
+                                                                                       ((FieldReference) lhs).token),
+                                                                                       lhsInfo);
+                                                                       rememberedVar = true;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       if (rememberedVar == false && lhs != null
+                                                       && lhs instanceof FieldReference) {
+                                               if (fMethodVariables != null) {
+                                                       VariableInfo lhsInfo = new VariableInfo(
+                                                                       ((FieldReference) lhs).sourceStart);
+                                                       fMethodVariables.put(new String(
+                                                                       ((FieldReference) lhs).token), lhsInfo);
+                                               }
+                                       }
+                                       break;
+                               case TokenNamePLUS_EQUAL:
+                               case TokenNameMINUS_EQUAL:
+                               case TokenNameMULTIPLY_EQUAL:
+                               case TokenNameDIVIDE_EQUAL:
+                               case TokenNameDOT_EQUAL:
+                               case TokenNameREMAINDER_EQUAL:
+                               case TokenNameAND_EQUAL:
+                               case TokenNameOR_EQUAL:
+                               case TokenNameXOR_EQUAL:
+                               case TokenNameRIGHT_SHIFT_EQUAL:
+                               case TokenNameLEFT_SHIFT_EQUAL:
+                                       if (lhs != null && lhs instanceof FieldReference) {
+                                               addVariableSet(((FieldReference) lhs).token);
+                                       }
+                                       getNextToken();
+                                       expr();
+                                       break;
+                               case TokenNamePLUS_PLUS:
+                               case TokenNameMINUS_MINUS:
+                                       getNextToken();
+                                       break;
+                               default:
+                                       if (!only_variable) {
+                                               throwSyntaxError("Variable expression not allowed (found token '"
+                                                               + scanner.toStringAction(token) + "').");
+                                       }
+                                       if (lhs != null) {
+                                               expression = lhs;
+                                       }
+                               }
+                               break;
+                       default:
+                               if (token != TokenNameINLINE_HTML) {
+                                       if (token > TokenNameKEYWORD) {
+                                               getNextToken();
+                                               break;
+                                       } else {
+                                               // System.out.println(scanner.getCurrentTokenStartPosition());
+                                               // System.out.println(scanner.getCurrentTokenEndPosition());
+
+                                               throwSyntaxError("Error in expression (found token '"
+                                                               + scanner.toStringAction(token) + "').");
+                                       }
+                               }
+                               return expression;
+                       }
+                       if (Scanner.TRACE) {
+                               System.out.println("TRACE: expr_without_variable() PART 2");
+                       }
+                       // | expr T_BOOLEAN_OR expr
+                       // | expr T_BOOLEAN_AND expr
+                       // | expr T_LOGICAL_OR expr
+                       // | expr T_LOGICAL_AND expr
+                       // | expr T_LOGICAL_XOR expr
+                       // | expr '|' expr
+                       // | expr '&' expr
+                       // | expr '^' expr
+                       // | expr '.' expr
+                       // | expr '+' expr
+                       // | expr '-' expr
+                       // | expr '*' expr
+                       // | expr '/' expr
+                       // | expr '%' expr
+                       // | expr T_SL expr
+                       // | expr T_SR expr
+                       // | expr T_IS_IDENTICAL expr
+                       // | expr T_IS_NOT_IDENTICAL expr
+                       // | expr T_IS_EQUAL expr
+                       // | expr T_IS_NOT_EQUAL expr
+                       // | expr '<' expr
+                       // | expr T_IS_SMALLER_OR_EQUAL expr
+                       // | expr '>' expr
+                       // | expr T_IS_GREATER_OR_EQUAL expr
+                       while (true) {
+                               switch (token) {
+                               case TokenNameOR_OR:
+                                       getNextToken();
+                                       expression = new OR_OR_Expression(expression, expr(), token);
+                                       break;
+                               case TokenNameAND_AND:
+                                       getNextToken();
+                                       expression = new AND_AND_Expression(expression, expr(),
+                                                       token);
+                                       break;
+                               case TokenNameEQUAL_EQUAL:
+                                       getNextToken();
+                                       expression = new EqualExpression(expression, expr(), token);
+                                       break;
+                               case TokenNameand:
+                               case TokenNameor:
+                               case TokenNamexor:
+                               case TokenNameAND:
+                               case TokenNameOR:
+                               case TokenNameXOR:
+                               case TokenNameDOT:
+                               case TokenNamePLUS:
+                               case TokenNameMINUS:
+                               case TokenNameMULTIPLY:
+                               case TokenNameDIVIDE:
+                               case TokenNameREMAINDER:
+                               case TokenNameLEFT_SHIFT:
+                               case TokenNameRIGHT_SHIFT:
+                               case TokenNameEQUAL_EQUAL_EQUAL:
+                               case TokenNameNOT_EQUAL_EQUAL:
+                               case TokenNameNOT_EQUAL:
+                               case TokenNameLESS:
+                               case TokenNameLESS_EQUAL:
+                               case TokenNameGREATER:
+                               case TokenNameGREATER_EQUAL:
+                                       getNextToken();
+                                       expression = new BinaryExpression(expression, expr(), token);
+                                       break;
+                               // | expr T_INSTANCEOF class_name_reference
+                               // | expr '?' expr ':' expr
+                               case TokenNameinstanceof:
+                                       getNextToken();
+                                       TypeReference classRef = class_name_reference();
+                                       if (classRef != null) {
+                                               expression = new InstanceOfExpression(expression,
+                                                               classRef, OperatorIds.INSTANCEOF);
+                                               expression.sourceStart = exprSourceStart;
+                                               expression.sourceEnd = scanner
+                                                               .getCurrentTokenEndPosition();
+                                       }
+                                       break;
+                               case TokenNameQUESTION:
+                                       getNextToken();
+                                       Expression valueIfTrue = expr();
+                                       if (token != TokenNameCOLON) {
+                                               throwSyntaxError("':' expected in conditional expression.");
+                                       }
+                                       getNextToken();
+                                       Expression valueIfFalse = expr();
+
+                                       expression = new ConditionalExpression(expression,
+                                                       valueIfTrue, valueIfFalse);
+                                       break;
+                               default:
+                                       return expression;
+                               }
+                       }
+               } catch (SyntaxError e) {
+                       // try to find next token after expression with errors:
+                       if (token == TokenNameSEMICOLON) {
+                               getNextToken();
+                               return expression;
+                       }
+                       if (token == TokenNameRBRACE || token == TokenNameRPAREN
+                                       || token == TokenNameRBRACKET) {
+                               getNextToken();
+                               return expression;
+                       }
+                       throw e;
+               }
+       }
+
+       private SingleTypeReference class_name_reference() {
+               // class_name_reference:
+               // T_STRING
+               // | dynamic_class_name_reference
+               SingleTypeReference ref = null;
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: class_name_reference()");
+               }
+               if (token == TokenNameIdentifier) {
+                       ref = new SingleTypeReference(scanner.getCurrentIdentifierSource(),
+                                       scanner.getCurrentTokenStartPosition());
+                       getNextToken();
+               } else {
+                       ref = null;
+                       dynamic_class_name_reference();
+               }
+               return ref;
+       }
+
+       private void dynamic_class_name_reference() {
+               // dynamic_class_name_reference:
+               // base_variable T_OBJECT_OPERATOR object_property
+               // dynamic_class_name_variable_properties
+               // | base_variable
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: dynamic_class_name_reference()");
+               }
+               base_variable(true);
+               if (token == TokenNameMINUS_GREATER) {
+                       getNextToken();
+                       object_property();
+                       dynamic_class_name_variable_properties();
+               }
+       }
+
+       private void dynamic_class_name_variable_properties() {
+               // dynamic_class_name_variable_properties:
+               // dynamic_class_name_variable_properties
+               // dynamic_class_name_variable_property
+               // | /* empty */
+               if (Scanner.TRACE) {
+                       System.out
+                                       .println("TRACE: dynamic_class_name_variable_properties()");
+               }
+               while (token == TokenNameMINUS_GREATER) {
+                       dynamic_class_name_variable_property();
+               }
+       }
+
+       private void dynamic_class_name_variable_property() {
+               // dynamic_class_name_variable_property:
+               // T_OBJECT_OPERATOR object_property
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: dynamic_class_name_variable_property()");
+               }
+               if (token == TokenNameMINUS_GREATER) {
+                       getNextToken();
+                       object_property();
+               }
+       }
+
+       private void ctor_arguments() {
+               // ctor_arguments:
+               // /* empty */
+               // | '(' function_call_parameter_list ')'
+               if (token == TokenNameLPAREN) {
+                       getNextToken();
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                               return;
+                       }
+                       non_empty_function_call_parameter_list();
+                       if (token != TokenNameRPAREN) {
+                               throwSyntaxError("')' expected in ctor_arguments.");
+                       }
+                       getNextToken();
+               }
+       }
+
+       private void assignment_list() {
+               // assignment_list:
+               // assignment_list ',' assignment_list_element
+               // | assignment_list_element
+               while (true) {
+                       assignment_list_element();
+                       if (token != TokenNameCOMMA) {
+                               break;
+                       }
+                       getNextToken();
+               }
+       }
+
+       private void assignment_list_element() {
+               // assignment_list_element:
+               // variable
+               // | T_LIST '(' assignment_list ')'
+               // | /* empty */
+               if (token == TokenNameVariable) {
+                       variable(true, false);
+               } else if (token == TokenNameDOLLAR) {
+                       variable(false, false);
+               } else if (token == TokenNameIdentifier) {
+                       identifier(true, true);
+               } else {
+                       if (token == TokenNamelist) {
+                               getNextToken();
+                               if (token == TokenNameLPAREN) {
+                                       getNextToken();
+                                       assignment_list();
+                                       if (token != TokenNameRPAREN) {
+                                               throwSyntaxError("')' expected after 'list' keyword.");
+                                       }
+                                       getNextToken();
+                               } else {
+                                       throwSyntaxError("'(' expected after 'list' keyword.");
+                               }
+                       }
+               }
+       }
+
+       private void array_pair_list() {
+               // array_pair_list:
+               // /* empty */
+               // | non_empty_array_pair_list possible_comma
+               non_empty_array_pair_list();
+               if (token == TokenNameCOMMA) {
+                       getNextToken();
+               }
+       }
+
+       private void non_empty_array_pair_list() {
+               // non_empty_array_pair_list:
+               // non_empty_array_pair_list ',' expr T_DOUBLE_ARROW expr
+               // | non_empty_array_pair_list ',' expr
+               // | expr T_DOUBLE_ARROW expr
+               // | expr
+               // | non_empty_array_pair_list ',' expr T_DOUBLE_ARROW '&' w_variable
+               // | non_empty_array_pair_list ',' '&' w_variable
+               // | expr T_DOUBLE_ARROW '&' w_variable
+               // | '&' w_variable
+               while (true) {
+                       if (token == TokenNameAND) {
+                               getNextToken();
+                               variable(true, false);
+                       } else {
+                               expr();
+                               if (token == TokenNameAND) {
+                                       getNextToken();
+                                       variable(true, false);
+                               } else if (token == TokenNameEQUAL_GREATER) {
+                                       getNextToken();
+                                       if (token == TokenNameAND) {
+                                               getNextToken();
+                                               variable(true, false);
+                                       } else {
+                                               expr();
+                                       }
+                               }
+                       }
+                       if (token != TokenNameCOMMA) {
+                               return;
+                       }
+                       getNextToken();
+                       if (token == TokenNameRPAREN) {
+                               return;
+                       }
+               }
+       }
+
+       // private void variableList() {
+       // do {
+       // variable();
+       // if (token == TokenNameCOMMA) {
+       // getNextToken();
+       // } else {
+       // break;
+       // }
+       // } while (true);
+       // }
+       private Expression variable_without_objects(boolean lefthandside,
+                       boolean ignoreVar) {
+               // variable_without_objects:
+               // reference_variable
+               // | simple_indirect_reference reference_variable
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: variable_without_objects()");
+               }
+               while (token == TokenNameDOLLAR) {
+                       getNextToken();
+               }
+               return reference_variable(lefthandside, ignoreVar);
+       }
+
+       private Expression function_call(boolean lefthandside, boolean ignoreVar) {
+               // function_call:
+               // T_STRING '(' function_call_parameter_list ')'
+               // | class_constant '(' function_call_parameter_list ')'
+               // | static_member '(' function_call_parameter_list ')'
+               // | variable_without_objects '(' function_call_parameter_list ')'
+               char[] defineName = null;
+               char[] ident = null;
+               int startPos = 0;
+               int endPos = 0;
+               Expression ref = null;
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: function_call()");
+               }
+               if (token == TokenNameIdentifier) {
+                       ident = scanner.getCurrentIdentifierSource();
+                       defineName = ident;
+                       startPos = scanner.getCurrentTokenStartPosition();
+                       endPos = scanner.getCurrentTokenEndPosition();
+                       getNextToken();
+                       switch (token) {
+                       case TokenNamePAAMAYIM_NEKUDOTAYIM:
+                               // static member:
+                               defineName = null;
+                               getNextToken();
+                               if (token == TokenNameIdentifier) {
+                                       // class _constant
+                                       getNextToken();
+                               } else {
+                                       // static member:
+                                       variable_without_objects(true, false);
+                               }
+                               break;
+                       }
+               } else {
+                       ref = variable_without_objects(lefthandside, ignoreVar);
+               }
+               if (token != TokenNameLPAREN) {
+                       if (defineName != null) {
+                               // does this identifier contain only uppercase characters?
+                               if (defineName.length == 3) {
+                                       if (defineName[0] == 'd' && defineName[1] == 'i'
+                                                       && defineName[2] == 'e') {
+                                               defineName = null;
+                                       }
+                               } else if (defineName.length == 4) {
+                                       if (defineName[0] == 't' && defineName[1] == 'r'
+                                                       && defineName[2] == 'u' && defineName[3] == 'e') {
+                                               defineName = null;
+                                       } else if (defineName[0] == 'n' && defineName[1] == 'u'
+                                                       && defineName[2] == 'l' && defineName[3] == 'l') {
+                                               defineName = null;
+                                       }
+                               } else if (defineName.length == 5) {
+                                       if (defineName[0] == 'f' && defineName[1] == 'a'
+                                                       && defineName[2] == 'l' && defineName[3] == 's'
+                                                       && defineName[4] == 'e') {
+                                               defineName = null;
+                                       }
+                               }
+                               if (defineName != null) {
+                                       for (int i = 0; i < defineName.length; i++) {
+                                               if (Character.isLowerCase(defineName[i])) {
+                                                       problemReporter.phpUppercaseIdentifierWarning(
+                                                                       startPos, endPos, referenceContext,
+                                                                       compilationUnit.compilationResult);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               } else {
+                       getNextToken();
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                               return ref;
+                       }
+                       non_empty_function_call_parameter_list();
+                       if (token != TokenNameRPAREN) {
+                               String functionName;
+                               if (ident == null) {
+                                       functionName = new String(" ");
+                               } else {
+                                       functionName = new String(ident);
+                               }
+                               throwSyntaxError("')' expected in function call ("
+                                               + functionName + ").");
+                       }
+                       getNextToken();
+               }
+               return ref;
+       }
+
+       private void non_empty_function_call_parameter_list() {
+               this.non_empty_function_call_parameter_list(null);
+       }
+
+       // private void function_call_parameter_list() {
+       // function_call_parameter_list:
+       // non_empty_function_call_parameter_list { $$ = $1; }
+       // | /* empty */
+       // }
+       private void non_empty_function_call_parameter_list(String functionName) {
+               // non_empty_function_call_parameter_list:
+               // expr_without_variable
+               // | variable
+               // | '&' w_variable
+               // | non_empty_function_call_parameter_list ',' expr_without_variable
+               // | non_empty_function_call_parameter_list ',' variable
+               // | non_empty_function_call_parameter_list ',' '&' w_variable
+               if (Scanner.TRACE) {
+                       System.out
+                                       .println("TRACE: non_empty_function_call_parameter_list()");
+               }
+               UninitializedVariableHandler initHandler = new UninitializedVariableHandler();
+               initHandler.setFunctionName(functionName);
+               while (true) {
+                       initHandler.incrementArgumentCount();
+                       if (token == TokenNameAND) {
+                               getNextToken();
+                               w_variable(true);
+                       } else {
+                               // if (token == TokenNameIdentifier || token ==
+                               // TokenNameVariable
+                               // || token == TokenNameDOLLAR) {
+                               // variable();
+                               // } else {
+                               expr_without_variable(true, initHandler);
+                               // }
+                       }
+                       if (token != TokenNameCOMMA) {
+                               break;
+                       }
+                       getNextToken();
+               }
+       }
+
+       private void fully_qualified_class_name() {
+               if (token == TokenNameIdentifier) {
+                       getNextToken();
+               } else {
+                       throwSyntaxError("Class name expected.");
+               }
+       }
+
+       private void static_member() {
+               // static_member:
+               // fully_qualified_class_name T_PAAMAYIM_NEKUDOTAYIM
+               // variable_without_objects
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: static_member()");
+               }
+               fully_qualified_class_name();
+               if (token != TokenNamePAAMAYIM_NEKUDOTAYIM) {
+                       throwSyntaxError("'::' expected after class name (static_member).");
+               }
+               getNextToken();
+               variable_without_objects(false, false);
+       }
+
+       private Expression base_variable_with_function_calls(boolean lefthandside,
+                       boolean ignoreVar) {
+               // base_variable_with_function_calls:
+               // base_variable
+               // | function_call
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: base_variable_with_function_calls()");
+               }
+               return function_call(lefthandside, ignoreVar);
+       }
+
+       private Expression base_variable(boolean lefthandside) {
+               // base_variable:
+               // reference_variable
+               // | simple_indirect_reference reference_variable
+               // | static_member
+               Expression ref = null;
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: base_variable()");
+               }
+               if (token == TokenNameIdentifier) {
+                       static_member();
+               } else {
+                       while (token == TokenNameDOLLAR) {
+                               getNextToken();
+                       }
+                       reference_variable(lefthandside, false);
+               }
+               return ref;
+       }
+
+       // private void simple_indirect_reference() {
+       // // simple_indirect_reference:
+       // // '$'
+       // //| simple_indirect_reference '$'
+       // }
+       private Expression reference_variable(boolean lefthandside,
+                       boolean ignoreVar) {
+               // reference_variable:
+               // reference_variable '[' dim_offset ']'
+               // | reference_variable '{' expr '}'
+               // | compound_variable
+               Expression ref = null;
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: reference_variable()");
+               }
+               ref = compound_variable(lefthandside, ignoreVar);
+               while (true) {
+                       if (token == TokenNameLBRACE) {
+                               ref = null;
+                               getNextToken();
+                               expr();
+                               if (token != TokenNameRBRACE) {
+                                       throwSyntaxError("'}' expected in reference variable.");
+                               }
+                               getNextToken();
+                       } else if (token == TokenNameLBRACKET) {
+                               // To remove "ref = null;" here, is probably better than the
+                               // patch
+                               // commented in #1368081 - axelcl
+                               getNextToken();
+                               if (token != TokenNameRBRACKET) {
+                                       expr();
+                                       // dim_offset();
+                                       if (token != TokenNameRBRACKET) {
+                                               throwSyntaxError("']' expected in reference variable.");
+                                       }
+                               }
+                               getNextToken();
+                       } else {
+                               break;
+                       }
+               }
+               return ref;
+       }
+
+       private Expression compound_variable(boolean lefthandside, boolean ignoreVar) {
+               // compound_variable:
+               // T_VARIABLE
+               // | '$' '{' expr '}'
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: compound_variable()");
+               }
+               if (token == TokenNameVariable) {
+                       if (!lefthandside) {
+                               if (!containsVariableSet()) {
+                                       // reportSyntaxError("The local variable " + new
+                                       // String(scanner.getCurrentIdentifierSource())
+                                       // + " may not have been initialized");
+                                       problemReporter.uninitializedLocalVariable(new String(
+                                                       scanner.getCurrentIdentifierSource()), scanner
+                                                       .getCurrentTokenStartPosition(), scanner
+                                                       .getCurrentTokenEndPosition(), referenceContext,
+                                                       compilationUnit.compilationResult);
+                               }
+                       } else {
+                               if (!ignoreVar) {
+                                       addVariableSet();
+                               }
+                       }
+                       FieldReference ref = new FieldReference(scanner
+                                       .getCurrentIdentifierSource(), scanner
+                                       .getCurrentTokenStartPosition());
+                       getNextToken();
+                       return ref;
+               } else {
+                       // because of simple_indirect_reference
+                       while (token == TokenNameDOLLAR) {
+                               getNextToken();
+                       }
+                       if (token != TokenNameLBRACE) {
+                               reportSyntaxError("'{' expected after compound variable token '$'.");
+                               return null;
+                       }
+                       getNextToken();
+                       expr();
+                       if (token != TokenNameRBRACE) {
+                               throwSyntaxError("'}' expected after compound variable token '$'.");
+                       }
+                       getNextToken();
+               }
+               return null;
+       } // private void dim_offset() { // // dim_offset: // // /* empty */
+
+       // // | expr
+       // expr();
+       // }
+       private void object_property() {
+               // object_property:
+               // object_dim_list
+               // | variable_without_objects
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: object_property()");
+               }
+               if (token == TokenNameVariable || token == TokenNameDOLLAR) {
+                       variable_without_objects(false, false);
+               } else {
+                       object_dim_list();
+               }
+       }
+
+       private void object_dim_list() {
+               // object_dim_list:
+               // object_dim_list '[' dim_offset ']'
+               // | object_dim_list '{' expr '}'
+               // | variable_name
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: object_dim_list()");
+               }
+               variable_name();
+               while (true) {
+                       if (token == TokenNameLBRACE) {
+                               getNextToken();
+                               expr();
+                               if (token != TokenNameRBRACE) {
+                                       throwSyntaxError("'}' expected in object_dim_list.");
+                               }
+                               getNextToken();
+                       } else if (token == TokenNameLBRACKET) {
+                               getNextToken();
+                               if (token == TokenNameRBRACKET) {
+                                       getNextToken();
+                                       continue;
+                               }
+                               expr();
+                               if (token != TokenNameRBRACKET) {
+                                       throwSyntaxError("']' expected in object_dim_list.");
+                               }
+                               getNextToken();
+                       } else {
+                               break;
+                       }
+               }
+       }
+
+       private void variable_name() {
+               // variable_name:
+               // T_STRING
+               // | '{' expr '}'
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: variable_name()");
+               }
+               if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
+                       if (token > TokenNameKEYWORD) {
+                               // TODO show a warning "Keyword used as variable" ?
+                       }
+                       getNextToken();
+               } else {
+                       if (token != TokenNameLBRACE) {
+                               throwSyntaxError("'{' expected in variable name.");
+                       }
+                       getNextToken();
+                       expr();
+                       if (token != TokenNameRBRACE) {
+                               throwSyntaxError("'}' expected in variable name.");
+                       }
+                       getNextToken();
+               }
+       }
+
+       private void r_variable() {
+               variable(false, false);
+       }
+
+       private void w_variable(boolean lefthandside) {
+               variable(lefthandside, false);
+       }
+
+       private void rw_variable() {
+               variable(false, false);
+       }
+
+       private Expression variable(boolean lefthandside, boolean ignoreVar) {
+               // variable:
+               // base_variable_with_function_calls T_OBJECT_OPERATOR
+               // object_property method_or_not variable_properties
+               // | base_variable_with_function_calls
+               Expression ref = base_variable_with_function_calls(lefthandside,
+                               ignoreVar);
+               if (token == TokenNameMINUS_GREATER) {
+                       ref = null;
+                       getNextToken();
+                       object_property();
+                       method_or_not();
+                       variable_properties();
+               }
+               return ref;
+       }
+
+       private void variable_properties() {
+               // variable_properties:
+               // variable_properties variable_property
+               // | /* empty */
+               while (token == TokenNameMINUS_GREATER) {
+                       variable_property();
+               }
+       }
+
+       private void variable_property() {
+               // variable_property:
+               // T_OBJECT_OPERATOR object_property method_or_not
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: variable_property()");
+               }
+               if (token == TokenNameMINUS_GREATER) {
+                       getNextToken();
+                       object_property();
+                       method_or_not();
+               } else {
+                       throwSyntaxError("'->' expected in variable_property.");
+               }
+       }
+
+       private Expression identifier(boolean lefthandside, boolean ignoreVar) {
+               // variable:
+               // base_variable_with_function_calls T_OBJECT_OPERATOR
+               // object_property method_or_not variable_properties
+               // | base_variable_with_function_calls
+
+               // Expression ref = function_call(lefthandside, ignoreVar);
+
+               // function_call:
+               // T_STRING '(' function_call_parameter_list ')'
+               // | class_constant '(' function_call_parameter_list ')'
+               // | static_member '(' function_call_parameter_list ')'
+               // | variable_without_objects '(' function_call_parameter_list ')'
+               char[] defineName = null;
+               char[] ident = null;
+               int startPos = 0;
+               int endPos = 0;
+               Expression ref = null;
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: function_call()");
+               }
+               if (token == TokenNameIdentifier) {
+                       ident = scanner.getCurrentIdentifierSource();
+                       defineName = ident;
+                       startPos = scanner.getCurrentTokenStartPosition();
+                       endPos = scanner.getCurrentTokenEndPosition();
+                       getNextToken();
+
+                       if (token == TokenNameEQUAL || token == TokenNamePLUS_EQUAL
+                                       || token == TokenNameMINUS_EQUAL
+                                       || token == TokenNameMULTIPLY_EQUAL
+                                       || token == TokenNameDIVIDE_EQUAL
+                                       || token == TokenNameDOT_EQUAL
+                                       || token == TokenNameREMAINDER_EQUAL
+                                       || token == TokenNameAND_EQUAL
+                                       || token == TokenNameOR_EQUAL
+                                       || token == TokenNameXOR_EQUAL
+                                       || token == TokenNameRIGHT_SHIFT_EQUAL
+                                       || token == TokenNameLEFT_SHIFT_EQUAL) {
+                               String error = "Assignment operator '"
+                                               + scanner.toStringAction(token)
+                                               + "' not allowed after identifier '"
+                                               + new String(ident)
+                                               + "' (use 'define(...)' to define constants).";
+                               reportSyntaxError(error);
+                       }
+
+                       switch (token) {
+                       case TokenNamePAAMAYIM_NEKUDOTAYIM:
+                               // static member:
+                               defineName = null;
+                               getNextToken();
+                               if (token == TokenNameIdentifier) {
+                                       // class _constant
+                                       getNextToken();
+                               } else {
+                                       // static member:
+                                       variable_without_objects(true, false);
+                               }
+                               break;
+                       }
+               } else {
+                       ref = variable_without_objects(lefthandside, ignoreVar);
+               }
+               if (token != TokenNameLPAREN) {
+                       if (defineName != null) {
+                               // does this identifier contain only uppercase characters?
+                               if (defineName.length == 3) {
+                                       if (defineName[0] == 'd' && defineName[1] == 'i'
+                                                       && defineName[2] == 'e') {
+                                               defineName = null;
+                                       }
+                               } else if (defineName.length == 4) {
+                                       if (defineName[0] == 't' && defineName[1] == 'r'
+                                                       && defineName[2] == 'u' && defineName[3] == 'e') {
+                                               defineName = null;
+                                       } else if (defineName[0] == 'n' && defineName[1] == 'u'
+                                                       && defineName[2] == 'l' && defineName[3] == 'l') {
+                                               defineName = null;
+                                       }
+                               } else if (defineName.length == 5) {
+                                       if (defineName[0] == 'f' && defineName[1] == 'a'
+                                                       && defineName[2] == 'l' && defineName[3] == 's'
+                                                       && defineName[4] == 'e') {
+                                               defineName = null;
+                                       }
+                               }
+                               if (defineName != null) {
+                                       for (int i = 0; i < defineName.length; i++) {
+                                               if (Character.isLowerCase(defineName[i])) {
+                                                       problemReporter.phpUppercaseIdentifierWarning(
+                                                                       startPos, endPos, referenceContext,
+                                                                       compilationUnit.compilationResult);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+                       // TODO is this ok ?
+                       // return ref;
+                       // throwSyntaxError("'(' expected in function call.");
+               } else {
+                       getNextToken();
+
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                               ref = null;
+                       } else {
+                               String functionName;
+                               if (ident == null) {
+                                       functionName = new String(" ");
+                               } else {
+                                       functionName = new String(ident);
+                               }
+                               non_empty_function_call_parameter_list(functionName);
+                               if (token != TokenNameRPAREN) {
+                                       throwSyntaxError("')' expected in function call ("
+                                                       + functionName + ").");
+                               }
+                               getNextToken();
+                       }
+               }
+               if (token == TokenNameMINUS_GREATER) {
+                       ref = null;
+                       getNextToken();
+                       object_property();
+                       method_or_not();
+                       variable_properties();
+               }
+               return ref;
+       }
+
+       private void method_or_not() {
+               // method_or_not:
+               // '(' function_call_parameter_list ')'
+               // | /* empty */
+               if (Scanner.TRACE) {
+                       System.out.println("TRACE: method_or_not()");
+               }
+               if (token == TokenNameLPAREN) {
+                       getNextToken();
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                               return;
+                       }
+                       non_empty_function_call_parameter_list();
+                       if (token != TokenNameRPAREN) {
+                               throwSyntaxError("')' expected in method_or_not.");
+                       }
+                       getNextToken();
+               }
+       }
+
+       private void exit_expr() {
+               // /* empty */
+               // | '(' ')'
+               // | '(' expr ')'
+               if (token != TokenNameLPAREN) {
+                       return;
+               }
+               getNextToken();
+               if (token == TokenNameRPAREN) {
+                       getNextToken();
+                       return;
+               }
+               expr();
+               if (token != TokenNameRPAREN) {
+                       throwSyntaxError("')' expected after keyword 'exit'");
+               }
+               getNextToken();
+       }
+
+       // private void encaps_list() {
+       // // encaps_list encaps_var
+       // // | encaps_list T_STRING
+       // // | encaps_list T_NUM_STRING
+       // // | encaps_list T_ENCAPSED_AND_WHITESPACE
+       // // | encaps_list T_CHARACTER
+       // // | encaps_list T_BAD_CHARACTER
+       // // | encaps_list '['
+       // // | encaps_list ']'
+       // // | encaps_list '{'
+       // // | encaps_list '}'
+       // // | encaps_list T_OBJECT_OPERATOR
+       // // | /* empty */
+       // while (true) {
+       // switch (token) {
+       // case TokenNameSTRING:
+       // getNextToken();
+       // break;
+       // case TokenNameLBRACE:
+       // // scanner.encapsedStringStack.pop();
+       // getNextToken();
+       // break;
+       // case TokenNameRBRACE:
+       // // scanner.encapsedStringStack.pop();
+       // getNextToken();
+       // break;
+       // case TokenNameLBRACKET:
+       // // scanner.encapsedStringStack.pop();
+       // getNextToken();
+       // break;
+       // case TokenNameRBRACKET:
+       // // scanner.encapsedStringStack.pop();
+       // getNextToken();
+       // break;
+       // case TokenNameMINUS_GREATER:
+       // // scanner.encapsedStringStack.pop();
+       // getNextToken();
+       // break;
+       // case TokenNameVariable:
+       // case TokenNameDOLLAR_LBRACE:
+       // case TokenNameLBRACE_DOLLAR:
+       // encaps_var();
+       // break;
+       // default:
+       // char encapsedChar = ((Character)
+       // scanner.encapsedStringStack.peek()).charValue();
+       // if (encapsedChar == '$') {
+       // scanner.encapsedStringStack.pop();
+       // encapsedChar = ((Character)
+       // scanner.encapsedStringStack.peek()).charValue();
+       // switch (encapsedChar) {
+       // case '`':
+       // if (token == TokenNameEncapsedString0) {
+       // return;
+       // }
+       // token = TokenNameSTRING;
+       // continue;
+       // case '\'':
+       // if (token == TokenNameEncapsedString1) {
+       // return;
+       // }
+       // token = TokenNameSTRING;
+       // continue;
+       // case '"':
+       // if (token == TokenNameEncapsedString2) {
+       // return;
+       // }
+       // token = TokenNameSTRING;
+       // continue;
+       // }
+       // }
+       // return;
+       // }
+       // }
+       // }
+
+       // private void encaps_var() {
+       // // T_VARIABLE
+       // // | T_VARIABLE '[' encaps_var_offset ']'
+       // // | T_VARIABLE T_OBJECT_OPERATOR T_STRING
+       // // | T_DOLLAR_OPEN_CURLY_BRACES expr '}'
+       // // | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}'
+       // // | T_CURLY_OPEN variable '}'
+       // switch (token) {
+       // case TokenNameVariable:
+       // getNextToken();
+       // if (token == TokenNameLBRACKET) {
+       // getNextToken();
+       // expr(); //encaps_var_offset();
+       // if (token != TokenNameRBRACKET) {
+       // throwSyntaxError("']' expected after variable.");
+       // }
+       // // scanner.encapsedStringStack.pop();
+       // getNextToken();
+       // // }
+       // } else if (token == TokenNameMINUS_GREATER) {
+       // getNextToken();
+       // if (token != TokenNameIdentifier) {
+       // throwSyntaxError("Identifier expected after '->'.");
+       // }
+       // // scanner.encapsedStringStack.pop();
+       // getNextToken();
+       // }
+       // // else {
+       // // // scanner.encapsedStringStack.pop();
+       // // int tempToken = TokenNameSTRING;
+       // // if (!scanner.encapsedStringStack.isEmpty()
+       // // && (token == TokenNameEncapsedString0
+       // // || token == TokenNameEncapsedString1
+       // // || token == TokenNameEncapsedString2 || token ==
+       // // TokenNameERROR)) {
+       // // char encapsedChar = ((Character)
+       // // scanner.encapsedStringStack.peek())
+       // // .charValue();
+       // // switch (token) {
+       // // case TokenNameEncapsedString0 :
+       // // if (encapsedChar == '`') {
+       // // tempToken = TokenNameEncapsedString0;
+       // // }
+       // // break;
+       // // case TokenNameEncapsedString1 :
+       // // if (encapsedChar == '\'') {
+       // // tempToken = TokenNameEncapsedString1;
+       // // }
+       // // break;
+       // // case TokenNameEncapsedString2 :
+       // // if (encapsedChar == '"') {
+       // // tempToken = TokenNameEncapsedString2;
+       // // }
+       // // break;
+       // // case TokenNameERROR :
+       // // if (scanner.source[scanner.currentPosition - 1] == '\\') {
+       // // scanner.currentPosition--;
+       // // getNextToken();
+       // // }
+       // // break;
+       // // }
+       // // }
+       // // token = tempToken;
+       // // }
+       // break;
+       // case TokenNameDOLLAR_LBRACE:
+       // getNextToken();
+       // if (token == TokenNameDOLLAR_LBRACE) {
+       // encaps_var();
+       // } else if (token == TokenNameIdentifier) {
+       // getNextToken();
+       // if (token == TokenNameLBRACKET) {
+       // getNextToken();
+       // // if (token == TokenNameRBRACKET) {
+       // // getNextToken();
+       // // } else {
+       // expr();
+       // if (token != TokenNameRBRACKET) {
+       // throwSyntaxError("']' expected after '${'.");
+       // }
+       // getNextToken();
+       // // }
+       // }
+       // } else {
+       // expr();
+       // }
+       // if (token != TokenNameRBRACE) {
+       // throwSyntaxError("'}' expected.");
+       // }
+       // getNextToken();
+       // break;
+       // case TokenNameLBRACE_DOLLAR:
+       // getNextToken();
+       // if (token == TokenNameLBRACE_DOLLAR) {
+       // encaps_var();
+       // } else if (token == TokenNameIdentifier || token > TokenNameKEYWORD) {
+       // getNextToken();
+       // if (token == TokenNameLBRACKET) {
+       // getNextToken();
+       // // if (token == TokenNameRBRACKET) {
+       // // getNextToken();
+       // // } else {
+       // expr();
+       // if (token != TokenNameRBRACKET) {
+       // throwSyntaxError("']' expected.");
+       // }
+       // getNextToken();
+       // // }
+       // } else if (token == TokenNameMINUS_GREATER) {
+       // getNextToken();
+       // if (token != TokenNameIdentifier && token != TokenNameVariable) {
+       // throwSyntaxError("String or Variable token expected.");
+       // }
+       // getNextToken();
+       // if (token == TokenNameLBRACKET) {
+       // getNextToken();
+       // // if (token == TokenNameRBRACKET) {
+       // // getNextToken();
+       // // } else {
+       // expr();
+       // if (token != TokenNameRBRACKET) {
+       // throwSyntaxError("']' expected after '${'.");
+       // }
+       // getNextToken();
+       // // }
+       // }
+       // }
+       // // if (token != TokenNameRBRACE) {
+       // // throwSyntaxError("'}' expected after '{$'.");
+       // // }
+       // // // scanner.encapsedStringStack.pop();
+       // // getNextToken();
+       // } else {
+       // expr();
+       // if (token != TokenNameRBRACE) {
+       // throwSyntaxError("'}' expected.");
+       // }
+       // // scanner.encapsedStringStack.pop();
+       // getNextToken();
+       // }
+       // break;
+       // }
+       // }
+
+       // private void encaps_var_offset() {
+       // // T_STRING
+       // // | T_NUM_STRING
+       // // | T_VARIABLE
+       // switch (token) {
+       // case TokenNameSTRING:
+       // getNextToken();
+       // break;
+       // case TokenNameIntegerLiteral:
+       // getNextToken();
+       // break;
+       // case TokenNameVariable:
+       // getNextToken();
+       // break;
+       // case TokenNameIdentifier:
+       // getNextToken();
+       // break;
+       // default:
+       // throwSyntaxError("Variable or String token expected.");
+       // break;
+       // }
+       // }
+
+       private void internal_functions_in_yacc() {
+               // int start = 0;
+               switch (token) {
+               // case TokenNameisset:
+               // // T_ISSET '(' isset_variables ')'
+               // getNextToken();
+               // if (token != TokenNameLPAREN) {
+               // throwSyntaxError("'(' expected after keyword 'isset'");
+               // }
+               // getNextToken();
+               // isset_variables();
+               // if (token != TokenNameRPAREN) {
+               // throwSyntaxError("')' expected after keyword 'isset'");
+               // }
+               // getNextToken();
+               // break;
+               // case TokenNameempty:
+               // // T_EMPTY '(' variable ')'
+               // getNextToken();
+               // if (token != TokenNameLPAREN) {
+               // throwSyntaxError("'(' expected after keyword 'empty'");
+               // }
+               // getNextToken();
+               // variable(false);
+               // if (token != TokenNameRPAREN) {
+               // throwSyntaxError("')' expected after keyword 'empty'");
+               // }
+               // getNextToken();
+               // break;
+               case TokenNameinclude:
+                       // T_INCLUDE expr
+                       checkFileName(token);
+                       break;
+               case TokenNameinclude_once:
+                       // T_INCLUDE_ONCE expr
+                       checkFileName(token);
+                       break;
+               case TokenNameeval:
+                       // T_EVAL '(' expr ')'
+                       getNextToken();
+                       if (token != TokenNameLPAREN) {
+                               throwSyntaxError("'(' expected after keyword 'eval'");
+                       }
+                       getNextToken();
+                       expr();
+                       if (token != TokenNameRPAREN) {
+                               throwSyntaxError("')' expected after keyword 'eval'");
+                       }
+                       getNextToken();
+                       break;
+               case TokenNamerequire:
+                       // T_REQUIRE expr
+                       checkFileName(token);
+                       break;
+               case TokenNamerequire_once:
+                       // T_REQUIRE_ONCE expr
+                       checkFileName(token);
+                       break;
+               }
+       }
+
+       /**
+        * Parse and check the include file name
+        * 
+        * @param includeToken
+        */
+       private void checkFileName(int includeToken) {
+               // <include-token> expr
+               int start = scanner.getCurrentTokenStartPosition();
+               boolean hasLPAREN = false;
+               getNextToken();
+               if (token == TokenNameLPAREN) {
+                       hasLPAREN = true;
+                       getNextToken();
+               }
+               Expression expression = expr();
+               if (hasLPAREN) {
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                       } else {
+                               throwSyntaxError("')' expected for keyword '"
+                                               + scanner.toStringAction(includeToken) + "'");
+                       }
+               }
+               char[] currTokenSource = scanner.getCurrentTokenSource(start);
+               IFile file = null;
+               if (scanner.compilationUnit != null) {
+                       IResource resource = scanner.compilationUnit.getResource();
+                       if (resource != null && resource instanceof IFile) {
+                               file = (IFile) resource;
+                       }
+               }
+               char[][] tokens;
+               tokens = new char[1][];
+               tokens[0] = currTokenSource;
+
+               ImportReference impt = new ImportReference(tokens, currTokenSource,
+                               start, scanner.getCurrentTokenEndPosition(), false);
+               impt.declarationSourceEnd = impt.sourceEnd;
+               impt.declarationEnd = impt.declarationSourceEnd;
+               // endPosition is just before the ;
+               impt.declarationSourceStart = start;
+               includesList.add(impt);
+
+               if (expression instanceof StringLiteral) {
+                       StringLiteral literal = (StringLiteral) expression;
+                       char[] includeName = literal.source();
+                       if (includeName.length == 0) {
+                               reportSyntaxError("Empty filename after keyword '"
+                                               + scanner.toStringAction(includeToken) + "'",
+                                               literal.sourceStart, literal.sourceStart + 1);
+                       }
+                       String includeNameString = new String(includeName);
+                       if (literal instanceof StringLiteralDQ) {
+                               if (includeNameString.indexOf('$') >= 0) {
+                                       // assuming that the filename contains a variable => no
+                                       // filename check
+                                       return;
+                               }
+                       }
+                       if (includeNameString.startsWith("http://")) {
+                               // assuming external include location
+                               return;
+                       }
+                       if (file != null) {
+                               // check the filename:
+                               // System.out.println(new
+                               // String(compilationUnit.getFileName())+" - "+
+                               // expression.toStringExpression());
+                               IProject project = file.getProject();
+                               if (project != null) {
+                                       IPath path = PHPFileUtil.determineFilePath(
+                                                       includeNameString, file, project);
+
+                                       if (path == null) {
+                                               // SyntaxError: "File: << >> doesn't exist in project."
+                                               String[] args = { expression.toStringExpression(),
+                                                               project.getLocation().toString() };
+                                               problemReporter.phpIncludeNotExistWarning(args,
+                                                               literal.sourceStart, literal.sourceEnd,
+                                                               referenceContext,
+                                                               compilationUnit.compilationResult);
+                                       } else {
+                                               try {
+                                                       String filePath = path.toString();
+                                                       String ext = file.getRawLocation()
+                                                                       .getFileExtension();
+                                                       int fileExtensionLength = ext == null ? 0 : ext
+                                                                       .length() + 1;
+
+                                                       IFile f = PHPFileUtil.createFile(path, project);
+
+                                                       impt.tokens = CharOperation.splitOn('/', filePath
+                                                                       .toCharArray(), 0, filePath.length()
+                                                                       - fileExtensionLength);
+                                                       impt.setFile(f);
+                                               } catch (Exception e) {
+                                                       // the file is outside of the workspace
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       private void isset_variables() {
+               // variable
+               // | isset_variables ','
+               if (token == TokenNameRPAREN) {
+                       throwSyntaxError("Variable expected after keyword 'isset'");
+               }
+               while (true) {
+                       variable(true, false);
+                       if (token == TokenNameCOMMA) {
+                               getNextToken();
+                       } else {
+                               break;
+                       }
+               }
+       }
+
+       private boolean common_scalar() {
+               // common_scalar:
+               // T_LNUMBER
+               // | T_DNUMBER
+               // | T_CONSTANT_ENCAPSED_STRING
+               // | T_LINE
+               // | T_FILE
+               // | T_CLASS_C
+               // | T_METHOD_C
+               // | T_FUNC_C
+               switch (token) {
+               case TokenNameIntegerLiteral:
+                       getNextToken();
+                       return true;
+               case TokenNameDoubleLiteral:
+                       getNextToken();
+                       return true;
+               case TokenNameStringDoubleQuote:
+                       getNextToken();
+                       return true;
+               case TokenNameStringSingleQuote:
+                       getNextToken();
+                       return true;
+               case TokenNameStringInterpolated:
+                       getNextToken();
+                       return true;
+               case TokenNameFILE:
+                       getNextToken();
+                       return true;
+               case TokenNameLINE:
+                       getNextToken();
+                       return true;
+               case TokenNameCLASS_C:
+                       getNextToken();
+                       return true;
+               case TokenNameMETHOD_C:
+                       getNextToken();
+                       return true;
+               case TokenNameFUNC_C:
+                       getNextToken();
+                       return true;
+               }
+               return false;
+       }
+
+       private void scalar() {
+               // scalar:
+               // T_STRING
+               // | T_STRING_VARNAME
+               // | class_constant
+               // | common_scalar
+               // | '"' encaps_list '"'
+               // | '\'' encaps_list '\''
+               // | T_START_HEREDOC encaps_list T_END_HEREDOC
+               throwSyntaxError("Not yet implemented (scalar).");
+       }
+
+       private void static_scalar() {
+               // static_scalar: /* compile-time evaluated scalars */
+               // common_scalar
+               // | T_STRING
+               // | '+' static_scalar
+               // | '-' static_scalar
+               // | T_ARRAY '(' static_array_pair_list ')'
+               // | static_class_constant
+               if (common_scalar()) {
+                       return;
+               }
+               switch (token) {
+               case TokenNameIdentifier:
+                       getNextToken();
+                       // static_class_constant:
+                       // T_STRING T_PAAMAYIM_NEKUDOTAYIM T_STRING
+                       if (token == TokenNamePAAMAYIM_NEKUDOTAYIM) {
+                               getNextToken();
+                               if (token == TokenNameIdentifier) {
+                                       getNextToken();
+                               } else {
+                                       throwSyntaxError("Identifier expected after '::' operator.");
+                               }
+                       }
+                       break;
+               case TokenNameEncapsedString0:
+                       try {
+                               scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+                               while (scanner.currentCharacter != '`') {
+                                       if (scanner.currentCharacter == '\\') {
+                                               scanner.currentPosition++;
+                                       }
+                                       scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+                               }
+                               getNextToken();
+                       } catch (IndexOutOfBoundsException e) {
+                               throwSyntaxError("'`' expected at end of static string.");
+                       }
+                       break;
+               // case TokenNameEncapsedString1:
+               // try {
+               // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+               // while (scanner.currentCharacter != '\'') {
+               // if (scanner.currentCharacter == '\\') {
+               // scanner.currentPosition++;
+               // }
+               // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+               // }
+               // getNextToken();
+               // } catch (IndexOutOfBoundsException e) {
+               // throwSyntaxError("'\'' expected at end of static string.");
+               // }
+               // break;
+               // case TokenNameEncapsedString2:
+               // try {
+               // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+               // while (scanner.currentCharacter != '"') {
+               // if (scanner.currentCharacter == '\\') {
+               // scanner.currentPosition++;
+               // }
+               // scanner.currentCharacter = scanner.source[scanner.currentPosition++];
+               // }
+               // getNextToken();
+               // } catch (IndexOutOfBoundsException e) {
+               // throwSyntaxError("'\"' expected at end of static string.");
+               // }
+               // break;
+               case TokenNameStringSingleQuote:
+                       getNextToken();
+                       break;
+               case TokenNameStringDoubleQuote:
+                       getNextToken();
+                       break;
+               case TokenNamePLUS:
+                       getNextToken();
+                       static_scalar();
+                       break;
+               case TokenNameMINUS:
+                       getNextToken();
+                       static_scalar();
+                       break;
+               case TokenNamearray:
+                       getNextToken();
+                       if (token != TokenNameLPAREN) {
+                               throwSyntaxError("'(' expected after keyword 'array'");
+                       }
+                       getNextToken();
+                       if (token == TokenNameRPAREN) {
+                               getNextToken();
+                               break;
+                       }
+                       non_empty_static_array_pair_list();
+                       if (token != TokenNameRPAREN) {
+                               throwSyntaxError("')' or ',' expected after keyword 'array'");
+                       }
+                       getNextToken();
+                       break;
+               // case TokenNamenull :
+               // getNextToken();
+               // break;
+               // case TokenNamefalse :
+               // getNextToken();
+               // break;
+               // case TokenNametrue :
+               // getNextToken();
+               // break;
+               default:
+                       throwSyntaxError("Static scalar/constant expected.");
+               }
+       }
+
+       private void non_empty_static_array_pair_list() {
+               // non_empty_static_array_pair_list:
+               // non_empty_static_array_pair_list ',' static_scalar T_DOUBLE_ARROW
+               // static_scalar
+               // | non_empty_static_array_pair_list ',' static_scalar
+               // | static_scalar T_DOUBLE_ARROW static_scalar
+               // | static_scalar
+               while (true) {
+                       static_scalar();
+                       if (token == TokenNameEQUAL_GREATER) {
+                               getNextToken();
+                               static_scalar();
+                       }
+                       if (token != TokenNameCOMMA) {
+                               break;
+                       }
+                       getNextToken();
+                       if (token == TokenNameRPAREN) {
+                               break;
+                       }
+               }
+       }
+
+       // public void reportSyntaxError() { //int act, int currentKind, int
+       // // stateStackTop) {
+       // /* remember current scanner position */
+       // int startPos = scanner.startPosition;
+       // int currentPos = scanner.currentPosition;
+       //
+       // this.checkAndReportBracketAnomalies(problemReporter());
+       // /* reset scanner where it was */
+       // scanner.startPosition = startPos;
+       // scanner.currentPosition = currentPos;
+       // }
+
+       public static final int RoundBracket = 0;
+
+       public static final int SquareBracket = 1;
+
+       public static final int CurlyBracket = 2;
+
+       public static final int BracketKinds = 3;
+
+       protected int[] nestedMethod; // the ptr is nestedType
+
+       protected int nestedType, dimensions;
+
+       // variable set stack
+       final static int VariableStackIncrement = 10;
+
+       HashMap fTypeVariables = null;
+
+       HashMap fMethodVariables = null;
+
+       ArrayList fStackUnassigned = new ArrayList();
+
+       // ast stack
+       final static int AstStackIncrement = 100;
+
+       protected int astPtr;
+
+       protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
+
+       protected int astLengthPtr;
+
+       protected int[] astLengthStack;
+
+       ASTNode[] noAstNodes = new ASTNode[AstStackIncrement];
+
+       public CompilationUnitDeclaration compilationUnit; /*
+                                                                                                                * the result from
+                                                                                                                * parse()
+                                                                                                                */
+
+       protected ReferenceContext referenceContext;
+
+       protected ProblemReporter problemReporter;
+
+       protected CompilerOptions options;
+
+       private ArrayList includesList;
+
+       // protected CompilationResult compilationResult;
+       /**
+        * Returns this parser's problem reporter initialized with its reference
+        * context. Also it is assumed that a problem is going to be reported, so
+        * initializes the compilation result's line positions.
+        */
+       public ProblemReporter problemReporter() {
+               if (scanner.recordLineSeparator) {
+                       compilationUnit.compilationResult.lineSeparatorPositions = scanner
+                                       .getLineEnds();
+               }
+               problemReporter.referenceContext = referenceContext;
+               return problemReporter;
+       }
+
+       /*
+        * Reconsider the entire source looking for inconsistencies in {} () []
+        */
+       // public boolean checkAndReportBracketAnomalies(ProblemReporter
+       // problemReporter) {
+       // scanner.wasAcr = false;
+       // boolean anomaliesDetected = false;
+       // try {
+       // char[] source = scanner.source;
+       // int[] leftCount = { 0, 0, 0 };
+       // int[] rightCount = { 0, 0, 0 };
+       // int[] depths = { 0, 0, 0 };
+       // int[][] leftPositions = new int[][] { new int[10], new int[10], new
+       // int[10]
+       // };
+       // int[][] leftDepths = new int[][] { new int[10], new int[10], new int[10]
+       // };
+       // int[][] rightPositions = new int[][] { new int[10], new int[10], new
+       // int[10] };
+       // int[][] rightDepths = new int[][] { new int[10], new int[10], new int[10]
+       // };
+       // scanner.currentPosition = scanner.initialPosition; //starting
+       // // point
+       // // (first-zero-based
+       // // char)
+       // while (scanner.currentPosition < scanner.eofPosition) { //loop for
+       // // jumping
+       // // over
+       // // comments
+       // try {
+       // // ---------Consume white space and handles
+       // // startPosition---------
+       // boolean isWhiteSpace;
+       // do {
+       // scanner.startPosition = scanner.currentPosition;
+       // // if (((scanner.currentCharacter =
+       // // source[scanner.currentPosition++]) == '\\') &&
+       // // (source[scanner.currentPosition] == 'u')) {
+       // // isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
+       // // } else {
+       // if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') ||
+       // (scanner.currentCharacter == '\n'))) {
+       // if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
+       // // only record line positions we have not
+       // // recorded yet
+       // scanner.pushLineSeparator();
+       // }
+       // }
+       // isWhiteSpace = CharOperation.isWhitespace(scanner.currentCharacter);
+       // // }
+       // } while (isWhiteSpace && (scanner.currentPosition <
+       // scanner.eofPosition));
+       // // -------consume token until } is found---------
+       // switch (scanner.currentCharacter) {
+       // case '{': {
+       // int index = leftCount[CurlyBracket]++;
+       // if (index == leftPositions[CurlyBracket].length) {
+       // System.arraycopy(leftPositions[CurlyBracket], 0,
+       // (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
+       // System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] =
+       // new int[index * 2]), 0, index);
+       // }
+       // leftPositions[CurlyBracket][index] = scanner.startPosition;
+       // leftDepths[CurlyBracket][index] = depths[CurlyBracket]++;
+       // }
+       // break;
+       // case '}': {
+       // int index = rightCount[CurlyBracket]++;
+       // if (index == rightPositions[CurlyBracket].length) {
+       // System.arraycopy(rightPositions[CurlyBracket], 0,
+       // (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
+       // System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket]
+       // =
+       // new int[index * 2]), 0, index);
+       // }
+       // rightPositions[CurlyBracket][index] = scanner.startPosition;
+       // rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
+       // }
+       // break;
+       // case '(': {
+       // int index = leftCount[RoundBracket]++;
+       // if (index == leftPositions[RoundBracket].length) {
+       // System.arraycopy(leftPositions[RoundBracket], 0,
+       // (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
+       // System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] =
+       // new int[index * 2]), 0, index);
+       // }
+       // leftPositions[RoundBracket][index] = scanner.startPosition;
+       // leftDepths[RoundBracket][index] = depths[RoundBracket]++;
+       // }
+       // break;
+       // case ')': {
+       // int index = rightCount[RoundBracket]++;
+       // if (index == rightPositions[RoundBracket].length) {
+       // System.arraycopy(rightPositions[RoundBracket], 0,
+       // (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
+       // System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket]
+       // =
+       // new int[index * 2]), 0, index);
+       // }
+       // rightPositions[RoundBracket][index] = scanner.startPosition;
+       // rightDepths[RoundBracket][index] = --depths[RoundBracket];
+       // }
+       // break;
+       // case '[': {
+       // int index = leftCount[SquareBracket]++;
+       // if (index == leftPositions[SquareBracket].length) {
+       // System.arraycopy(leftPositions[SquareBracket], 0,
+       // (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
+       // System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket]
+       // =
+       // new int[index * 2]), 0, index);
+       // }
+       // leftPositions[SquareBracket][index] = scanner.startPosition;
+       // leftDepths[SquareBracket][index] = depths[SquareBracket]++;
+       // }
+       // break;
+       // case ']': {
+       // int index = rightCount[SquareBracket]++;
+       // if (index == rightPositions[SquareBracket].length) {
+       // System.arraycopy(rightPositions[SquareBracket], 0,
+       // (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
+       // System.arraycopy(rightDepths[SquareBracket], 0,
+       // (rightDepths[SquareBracket]
+       // = new int[index * 2]), 0, index);
+       // }
+       // rightPositions[SquareBracket][index] = scanner.startPosition;
+       // rightDepths[SquareBracket][index] = --depths[SquareBracket];
+       // }
+       // break;
+       // case '\'': {
+       // if (scanner.getNextChar('\\')) {
+       // scanner.scanEscapeCharacter();
+       // } else { // consume next character
+       // scanner.unicodeAsBackSlash = false;
+       // // if (((scanner.currentCharacter =
+       // // source[scanner.currentPosition++]) ==
+       // // '\\') &&
+       // // (source[scanner.currentPosition] ==
+       // // 'u')) {
+       // // scanner.getNextUnicodeChar();
+       // // } else {
+       // if (scanner.withoutUnicodePtr != 0) {
+       // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
+       // scanner.currentCharacter;
+       // }
+       // // }
+       // }
+       // scanner.getNextChar('\'');
+       // break;
+       // }
+       // case '"':
+       // // consume next character
+       // scanner.unicodeAsBackSlash = false;
+       // // if (((scanner.currentCharacter =
+       // // source[scanner.currentPosition++]) == '\\') &&
+       // // (source[scanner.currentPosition] == 'u')) {
+       // // scanner.getNextUnicodeChar();
+       // // } else {
+       // if (scanner.withoutUnicodePtr != 0) {
+       // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
+       // scanner.currentCharacter;
+       // }
+       // // }
+       // while (scanner.currentCharacter != '"') {
+       // if (scanner.currentCharacter == '\r') {
+       // if (source[scanner.currentPosition] == '\n')
+       // scanner.currentPosition++;
+       // break; // the string cannot go further that
+       // // the line
+       // }
+       // if (scanner.currentCharacter == '\n') {
+       // break; // the string cannot go further that
+       // // the line
+       // }
+       // if (scanner.currentCharacter == '\\') {
+       // scanner.scanEscapeCharacter();
+       // }
+       // // consume next character
+       // scanner.unicodeAsBackSlash = false;
+       // // if (((scanner.currentCharacter =
+       // // source[scanner.currentPosition++]) == '\\')
+       // // && (source[scanner.currentPosition] == 'u'))
+       // // {
+       // // scanner.getNextUnicodeChar();
+       // // } else {
+       // if (scanner.withoutUnicodePtr != 0) {
+       // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
+       // scanner.currentCharacter;
+       // }
+       // // }
+       // }
+       // break;
+       // case '/': {
+       // int test;
+       // if ((test = scanner.getNextChar('/', '*')) == 0) { //line
+       // // comment
+       // //get the next char
+       // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
+       // '\\')
+       // && (source[scanner.currentPosition] == 'u')) {
+       // //-------------unicode traitement
+       // // ------------
+       // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+       // scanner.currentPosition++;
+       // while (source[scanner.currentPosition] == 'u') {
+       // scanner.currentPosition++;
+       // }
+       // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15 || c1 < 0
+       // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c2 < 0
+       // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c3 < 0
+       // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c4 < 0) { //error
+       // // don't
+       // // care of the
+       // // value
+       // scanner.currentCharacter = 'A';
+       // } //something different from \n and \r
+       // else {
+       // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+       // }
+       // }
+       // while (scanner.currentCharacter != '\r' && scanner.currentCharacter !=
+       // '\n') {
+       // //get the next char
+       // scanner.startPosition = scanner.currentPosition;
+       // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
+       // '\\')
+       // && (source[scanner.currentPosition] == 'u')) {
+       // //-------------unicode traitement
+       // // ------------
+       // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+       // scanner.currentPosition++;
+       // while (source[scanner.currentPosition] == 'u') {
+       // scanner.currentPosition++;
+       // }
+       // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15 || c1 < 0
+       // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c2 < 0
+       // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c3 < 0
+       // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c4 < 0) { //error
+       // // don't
+       // // care of the
+       // // value
+       // scanner.currentCharacter = 'A';
+       // } //something different from \n
+       // // and \r
+       // else {
+       // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+       // }
+       // }
+       // }
+       // if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') ||
+       // (scanner.currentCharacter == '\n'))) {
+       // if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
+       // // only record line positions we
+       // // have not recorded yet
+       // scanner.pushLineSeparator();
+       // if (this.scanner.taskTags != null) {
+       // this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(),
+       // this.scanner
+       // .getCurrentTokenEndPosition());
+       // }
+       // }
+       // }
+       // break;
+       // }
+       // if (test > 0) { //traditional and annotation
+       // // comment
+       // boolean star = false;
+       // // consume next character
+       // scanner.unicodeAsBackSlash = false;
+       // // if (((scanner.currentCharacter =
+       // // source[scanner.currentPosition++]) ==
+       // // '\\') &&
+       // // (source[scanner.currentPosition] ==
+       // // 'u')) {
+       // // scanner.getNextUnicodeChar();
+       // // } else {
+       // if (scanner.withoutUnicodePtr != 0) {
+       // scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] =
+       // scanner.currentCharacter;
+       // }
+       // // }
+       // if (scanner.currentCharacter == '*') {
+       // star = true;
+       // }
+       // //get the next char
+       // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
+       // '\\')
+       // && (source[scanner.currentPosition] == 'u')) {
+       // //-------------unicode traitement
+       // // ------------
+       // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+       // scanner.currentPosition++;
+       // while (source[scanner.currentPosition] == 'u') {
+       // scanner.currentPosition++;
+       // }
+       // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15 || c1 < 0
+       // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c2 < 0
+       // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c3 < 0
+       // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c4 < 0) { //error
+       // // don't
+       // // care of the
+       // // value
+       // scanner.currentCharacter = 'A';
+       // } //something different from * and /
+       // else {
+       // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+       // }
+       // }
+       // //loop until end of comment */
+       // while ((scanner.currentCharacter != '/') || (!star)) {
+       // star = scanner.currentCharacter == '*';
+       // //get next char
+       // if (((scanner.currentCharacter = source[scanner.currentPosition++]) ==
+       // '\\')
+       // && (source[scanner.currentPosition] == 'u')) {
+       // //-------------unicode traitement
+       // // ------------
+       // int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+       // scanner.currentPosition++;
+       // while (source[scanner.currentPosition] == 'u') {
+       // scanner.currentPosition++;
+       // }
+       // if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15 || c1 < 0
+       // || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c2 < 0
+       // || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c3 < 0
+       // || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) >
+       // 15
+       // || c4 < 0) { //error
+       // // don't
+       // // care of the
+       // // value
+       // scanner.currentCharacter = 'A';
+       // } //something different from * and
+       // // /
+       // else {
+       // scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+       // }
+       // }
+       // }
+       // if (this.scanner.taskTags != null) {
+       // this.scanner.checkTaskTag(this.scanner.getCurrentTokenStartPosition(),
+       // this.scanner.getCurrentTokenEndPosition());
+       // }
+       // break;
+       // }
+       // break;
+       // }
+       // default:
+       // if (Scanner.isPHPIdentifierStart(scanner.currentCharacter)) {
+       // scanner.scanIdentifierOrKeyword(false);
+       // break;
+       // }
+       // if (Character.isDigit(scanner.currentCharacter)) {
+       // scanner.scanNumber(false);
+       // break;
+       // }
+       // }
+       // //-----------------end switch while
+       // // try--------------------
+       // } catch (IndexOutOfBoundsException e) {
+       // break; // read until EOF
+       // } catch (InvalidInputException e) {
+       // return false; // no clue
+       // }
+       // }
+       // if (scanner.recordLineSeparator) {
+       // compilationUnit.compilationResult.lineSeparatorPositions =
+       // scanner.getLineEnds();
+       // }
+       // // check placement anomalies against other kinds of brackets
+       // for (int kind = 0; kind < BracketKinds; kind++) {
+       // for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
+       // int start = leftPositions[kind][leftIndex]; // deepest
+       // // first
+       // // find matching closing bracket
+       // int depth = leftDepths[kind][leftIndex];
+       // int end = -1;
+       // for (int i = 0; i < rightCount[kind]; i++) {
+       // int pos = rightPositions[kind][i];
+       // // want matching bracket further in source with same
+       // // depth
+       // if ((pos > start) && (depth == rightDepths[kind][i])) {
+       // end = pos;
+       // break;
+       // }
+       // }
+       // if (end < 0) { // did not find a good closing match
+       // problemReporter.unmatchedBracket(start, referenceContext,
+       // compilationUnit.compilationResult);
+       // return true;
+       // }
+       // // check if even number of opening/closing other brackets
+       // // in between this pair of brackets
+       // int balance = 0;
+       // for (int otherKind = 0; (balance == 0) && (otherKind < BracketKinds);
+       // otherKind++) {
+       // for (int i = 0; i < leftCount[otherKind]; i++) {
+       // int pos = leftPositions[otherKind][i];
+       // if ((pos > start) && (pos < end))
+       // balance++;
+       // }
+       // for (int i = 0; i < rightCount[otherKind]; i++) {
+       // int pos = rightPositions[otherKind][i];
+       // if ((pos > start) && (pos < end))
+       // balance--;
+       // }
+       // if (balance != 0) {
+       // problemReporter.unmatchedBracket(start, referenceContext,
+       // compilationUnit.compilationResult); //bracket
+       // // anomaly
+       // return true;
+       // }
+       // }
+       // }
+       // // too many opening brackets ?
+       // for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
+       // anomaliesDetected = true;
+       // problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i
+       // -
+       // 1], referenceContext,
+       // compilationUnit.compilationResult);
+       // }
+       // // too many closing brackets ?
+       // for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
+       // anomaliesDetected = true;
+       // problemReporter.unmatchedBracket(rightPositions[kind][i],
+       // referenceContext,
+       // compilationUnit.compilationResult);
+       // }
+       // if (anomaliesDetected)
+       // return true;
+       // }
+       // return anomaliesDetected;
+       // } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
+       // return anomaliesDetected;
+       // } catch (NullPointerException e) { // jdk1.2.2 jit bug
+       // return anomaliesDetected;
+       // }
+       // }
+       protected void pushOnAstLengthStack(int pos) {
+               try {
+                       astLengthStack[++astLengthPtr] = pos;
+               } catch (IndexOutOfBoundsException e) {
+                       int oldStackLength = astLengthStack.length;
+                       int[] oldPos = astLengthStack;
+                       astLengthStack = new int[oldStackLength + StackIncrement];
+                       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
+                       astLengthStack[astLengthPtr] = pos;
+               }
+       }
+
+       protected void pushOnAstStack(ASTNode node) {
+               /*
+                * add a new obj on top of the ast stack
+                */
+               try {
+                       astStack[++astPtr] = node;
+               } catch (IndexOutOfBoundsException e) {
+                       int oldStackLength = astStack.length;
+                       ASTNode[] oldStack = astStack;
+                       astStack = new ASTNode[oldStackLength + AstStackIncrement];
+                       System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
+                       astPtr = oldStackLength;
+                       astStack[astPtr] = node;
+               }
+               try {
+                       astLengthStack[++astLengthPtr] = 1;
+               } catch (IndexOutOfBoundsException e) {
+                       int oldStackLength = astLengthStack.length;
+                       int[] oldPos = astLengthStack;
+                       astLengthStack = new int[oldStackLength + AstStackIncrement];
+                       System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
+                       astLengthStack[astLengthPtr] = 1;
+               }
+       }
+
+       protected void resetModifiers() {
+               this.modifiers = AccDefault;
+               this.modifiersSourceStart = -1; // <-- see comment into
+               // modifiersFlag(int)
+               this.scanner.commentPtr = -1;
+       }
+
+       protected void consumePackageDeclarationName(IFile file) {
+               // create a package name similar to java package names
+               String projectPath = ProjectPrefUtil.getDocumentRoot(file.getProject())
+                               .toString();
+               String filePath = file.getRawLocation().toString();
+               String ext = file.getRawLocation().getFileExtension();
+               int fileExtensionLength = ext == null ? 0 : ext.length() + 1;
+               ImportReference impt;
+               char[][] tokens;
+               if (filePath.startsWith(projectPath)) {
+                       tokens = CharOperation.splitOn('/', filePath.toCharArray(),
+                                       projectPath.length() + 1, filePath.length()
+                                                       - fileExtensionLength);
+               } else {
+                       String name = file.getName();
+                       tokens = new char[1][];
+                       tokens[0] = name.substring(0, name.length() - fileExtensionLength)
+                                       .toCharArray();
+               }
+
+               this.compilationUnit.currentPackage = impt = new ImportReference(
+                               tokens, new char[0], 0, 0, true);
+
+               impt.declarationSourceStart = 0;
+               impt.declarationSourceEnd = 0;
+               impt.declarationEnd = 0;
+               // endPosition is just before the ;
+
+       }
+
+       public final static String[] GLOBALS = { "$this", "$_COOKIE", "$_ENV",
+                       "$_FILES", "$_GET", "$GLOBALS", "$_POST", "$_REQUEST", "$_SESSION",
+                       "$_SERVER" };
+
+       /**
+        * 
+        */
+       private void pushFunctionVariableSet() {
+               HashSet set = new HashSet();
+               if (fStackUnassigned.isEmpty()) {
+                       for (int i = 0; i < GLOBALS.length; i++) {
+                               set.add(GLOBALS[i]);
+                       }
+               }
+               fStackUnassigned.add(set);
+       }
+
+       private void pushIfVariableSet() {
+               if (!fStackUnassigned.isEmpty()) {
+                       HashSet set = new HashSet();
+                       fStackUnassigned.add(set);
+               }
+       }
+
+       private HashSet removeIfVariableSet() {
+               if (!fStackUnassigned.isEmpty()) {
+                       return (HashSet) fStackUnassigned
+                                       .remove(fStackUnassigned.size() - 1);
+               }
+               return null;
+       }
+
+       /**
+        * Returns the <i>set of assigned variables </i> returns null if no Set is
+        * defined at the current scanner position
+        */
+       private HashSet peekVariableSet() {
+               if (!fStackUnassigned.isEmpty()) {
+                       return (HashSet) fStackUnassigned.get(fStackUnassigned.size() - 1);
+               }
+               return null;
+       }
+
+       /**
+        * add the current identifier source to the <i>set of assigned variables
+        * </i>
+        * 
+        * @param set
+        */
+       private void addVariableSet(HashSet set) {
+               if (set != null) {
+                       set.add(new String(scanner.getCurrentTokenSource()));
+               }
+       }
+
+       /**
+        * add the current identifier source to the <i>set of assigned variables
+        * </i>
+        * 
+        */
+       private void addVariableSet() {
+               HashSet set = peekVariableSet();
+               if (set != null) {
+                       set.add(new String(scanner.getCurrentTokenSource()));
+               }
+       }
+
+       /**
+        * add the current identifier source to the <i>set of assigned variables
+        * </i>
+        * 
+        */
+       private void addVariableSet(char[] token) {
+               HashSet set = peekVariableSet();
+               if (set != null) {
+                       set.add(new String(token));
+               }
+       }
+
+       /**
+        * check if the current identifier source is in the <i>set of assigned
+        * variables </i> Returns true, if no set is defined for the current scanner
+        * position
+        * 
+        */
+       private boolean containsVariableSet() {
+               return containsVariableSet(scanner.getCurrentTokenSource());
+       }
+
+       private boolean containsVariableSet(char[] token) {
+
+               if (!fStackUnassigned.isEmpty()) {
+                       HashSet set;
+                       String str = new String(token);
+                       for (int i = 0; i < fStackUnassigned.size(); i++) {
+                               set = (HashSet) fStackUnassigned.get(i);
+                               if (set.contains(str)) {
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+               return true;
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/core/JavaModelManager.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/core/JavaModelManager.java
new file mode 100644 (file)
index 0000000..b64d468
--- /dev/null
@@ -0,0 +1,2482 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.core;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.zip.ZipFile;
+
+import net.sourceforge.phpdt.core.ElementChangedEvent;
+import net.sourceforge.phpdt.core.IClasspathEntry;
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IElementChangedListener;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaElementDelta;
+import net.sourceforge.phpdt.core.IJavaModel;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.IPackageFragment;
+import net.sourceforge.phpdt.core.IPackageFragmentRoot;
+import net.sourceforge.phpdt.core.IParent;
+import net.sourceforge.phpdt.core.IProblemRequestor;
+import net.sourceforge.phpdt.core.IWorkingCopy;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.WorkingCopyOwner;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.core.builder.PHPBuilder;
+import net.sourceforge.phpdt.internal.core.util.Util;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.ISaveContext;
+import org.eclipse.core.resources.ISaveParticipant;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceDescription;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
+
+/**
+ * The <code>JavaModelManager</code> manages instances of
+ * <code>IJavaModel</code>. <code>IElementChangedListener</code>s register
+ * with the <code>JavaModelManager</code>, and receive
+ * <code>ElementChangedEvent</code>s for all <code>IJavaModel</code>s.
+ * <p>
+ * The single instance of <code>JavaModelManager</code> is available from the
+ * static method <code>JavaModelManager.getJavaModelManager()</code>.
+ */
+public class JavaModelManager implements ISaveParticipant {
+       /**
+        * Unique handle onto the JavaModel
+        */
+       final JavaModel javaModel = new JavaModel();
+
+       // public IndexManager indexManager = new IndexManager();
+       /**
+        * Classpath variables pool
+        */
+       public static HashMap Variables = new HashMap(5);
+
+       public static HashMap PreviousSessionVariables = new HashMap(5);
+
+       public static HashSet OptionNames = new HashSet(20);
+
+       public final static String CP_VARIABLE_PREFERENCES_PREFIX = PHPeclipsePlugin.PLUGIN_ID
+                       + ".classpathVariable."; //$NON-NLS-1$
+
+       public final static String CP_CONTAINER_PREFERENCES_PREFIX = PHPeclipsePlugin.PLUGIN_ID
+                       + ".classpathContainer."; //$NON-NLS-1$
+
+       public final static String CP_ENTRY_IGNORE = "##<cp entry ignore>##"; //$NON-NLS-1$
+
+       /**
+        * Classpath containers pool
+        */
+       public static HashMap containers = new HashMap(5);
+
+       public static HashMap PreviousSessionContainers = new HashMap(5);
+
+       /**
+        * Name of the extension point for contributing classpath variable
+        * initializers
+        */
+       // public static final String CPVARIABLE_INITIALIZER_EXTPOINT_ID =
+       // "classpathVariableInitializer" ; //$NON-NLS-1$
+       /**
+        * Name of the extension point for contributing classpath container
+        * initializers
+        */
+       // public static final String CPCONTAINER_INITIALIZER_EXTPOINT_ID =
+       // "classpathContainerInitializer" ; //$NON-NLS-1$
+       /**
+        * Name of the extension point for contributing a source code formatter
+        */
+       public static final String FORMATTER_EXTPOINT_ID = "codeFormatter"; // $/**
+
+       /**
+        * Value of the content-type for Java source files
+        */
+       public static final String JAVA_SOURCE_CONTENT_TYPE = PHPeclipsePlugin.PLUGIN_ID
+                       + ".phpSource"; //$NON-NLS-1$NON-NLS-1$
+
+       /**
+        * Special value used for recognizing ongoing initialization and breaking
+        * initialization cycles
+        */
+       public final static IPath VariableInitializationInProgress = new Path(
+                       "Variable Initialization In Progress"); //$NON-NLS-1$
+       // public final static IClasspathContainer ContainerInitializationInProgress
+       // = new IClasspathContainer() {
+       // public IClasspathEntry[] getClasspathEntries() { return null; }
+       // public String getDescription() { return "Container Initialization In
+       // Progress"; } //$NON-NLS-1$
+       // public int getKind() { return 0; }
+       // public IPath getPath() { return null; }
+       // public String toString() { return getDescription(); }
+       // };
+
+       private static final String INDEX_MANAGER_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/indexmanager"; //$NON-NLS-1$
+
+       private static final String COMPILER_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/compiler"; //$NON-NLS-1$
+
+       private static final String JAVAMODEL_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/javamodel"; //$NON-NLS-1$
+
+       private static final String CP_RESOLVE_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/cpresolution"; //$NON-NLS-1$
+
+       private static final String ZIP_ACCESS_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/zipaccess"; //$NON-NLS-1$
+
+       private static final String DELTA_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/javadelta"; //$NON-NLS-1$
+
+       private static final String HIERARCHY_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/hierarchy"; //$NON-NLS-1$
+
+       private static final String POST_ACTION_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/postaction"; //$NON-NLS-1$
+
+       private static final String BUILDER_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/builder"; //$NON-NLS-1$
+
+       private static final String COMPLETION_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/completion"; //$NON-NLS-1$
+
+       private static final String SELECTION_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/selection"; //$NON-NLS-1$
+
+       private static final String SHARED_WC_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/sharedworkingcopy"; //$NON-NLS-1$
+
+       private static final String SEARCH_DEBUG = PHPeclipsePlugin.PLUGIN_ID
+                       + "/debug/search"; //$NON-NLS-1$
+
+       public final static IWorkingCopy[] NoWorkingCopy = new IWorkingCopy[0];
+
+       /**
+        * Table from WorkingCopyOwner to a table of ICompilationUnit (working copy
+        * handle) to PerWorkingCopyInfo. NOTE: this object itself is used as a lock
+        * to synchronize creation/removal of per working copy infos
+        */
+       protected Map perWorkingCopyInfos = new HashMap(5);
+
+       /**
+        * Returns whether the given full path (for a package) conflicts with the
+        * output location of the given project.
+        */
+       public static boolean conflictsWithOutputLocation(IPath folderPath,
+                       JavaProject project) {
+               try {
+                       IPath outputLocation = project.getOutputLocation();
+                       if (outputLocation == null) {
+                               // in doubt, there is a conflict
+                               return true;
+                       }
+                       if (outputLocation.isPrefixOf(folderPath)) {
+                               // only allow nesting in project's output if there is a
+                               // corresponding source folder
+                               // or if the project's output is not used (in other words, if
+                               // all source folders have their custom output)
+                               IClasspathEntry[] classpath = project
+                                               .getResolvedClasspath(true);
+                               boolean isOutputUsed = false;
+                               for (int i = 0, length = classpath.length; i < length; i++) {
+                                       IClasspathEntry entry = classpath[i];
+                                       if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+                                               if (entry.getPath().equals(outputLocation)) {
+                                                       return false;
+                                               }
+                                               if (entry.getOutputLocation() == null) {
+                                                       isOutputUsed = true;
+                                               }
+                                       }
+                               }
+                               return isOutputUsed;
+                       }
+                       return false;
+               } catch (JavaModelException e) {
+                       // in doubt, there is a conflict
+                       return true;
+               }
+       }
+
+       // public static IClasspathContainer containerGet(IJavaProject project,
+       // IPath containerPath) {
+       // Map projectContainers = (Map)Containers.get(project);
+       // if (projectContainers == null){
+       // return null;
+       // }
+       // IClasspathContainer container =
+       // (IClasspathContainer)projectContainers.get(containerPath);
+       // return container;
+       // }
+
+       // public static void containerPut(IJavaProject project, IPath
+       // containerPath, IClasspathContainer container){
+       //
+       // Map projectContainers = (Map)Containers.get(project);
+       // if (projectContainers == null){
+       // projectContainers = new HashMap(1);
+       // Containers.put(project, projectContainers);
+       // }
+       //
+       // if (container == null) {
+       // projectContainers.remove(containerPath);
+       // Map previousContainers = (Map)PreviousSessionContainers.get(project);
+       // if (previousContainers != null){
+       // previousContainers.remove(containerPath);
+       // }
+       // } else {
+       // projectContainers.put(containerPath, container);
+       // }
+       //
+       // // do not write out intermediate initialization value
+       // if (container == JavaModelManager.ContainerInitializationInProgress) {
+       // return;
+       // }
+       // Preferences preferences =
+       // PHPeclipsePlugin.getPlugin().getPluginPreferences();
+       // String containerKey =
+       // CP_CONTAINER_PREFERENCES_PREFIX+project.getElementName()
+       // +"|"+containerPath;//$NON-NLS-1$
+       // String containerString = CP_ENTRY_IGNORE;
+       // try {
+       // if (container != null) {
+       // containerString =
+       // ((JavaProject)project).encodeClasspath(container.getClasspathEntries(),
+       // null, false);
+       // }
+       // } catch(JavaModelException e){
+       // }
+       // preferences.setDefault(containerKey, CP_ENTRY_IGNORE); // use this
+       // default to get rid of removed ones
+       // preferences.setValue(containerKey, containerString);
+       // PHPeclipsePlugin.getPlugin().savePluginPreferences();
+       // }
+
+       /**
+        * Returns the Java element corresponding to the given resource, or
+        * <code>null</code> if unable to associate the given resource with a Java
+        * element.
+        * <p>
+        * The resource must be one of:
+        * <ul>
+        * <li>a project - the element returned is the corresponding
+        * <code>IJavaProject</code></li>
+        * <li>a <code>.java</code> file - the element returned is the
+        * corresponding <code>ICompilationUnit</code></li>
+        * <li>a <code>.class</code> file - the element returned is the
+        * corresponding <code>IClassFile</code></li>
+        * <li>a <code>.jar</code> file - the element returned is the
+        * corresponding <code>IPackageFragmentRoot</code></li>
+        * <li>a folder - the element returned is the corresponding
+        * <code>IPackageFragmentRoot</code> or <code>IPackageFragment</code></li>
+        * <li>the workspace root resource - the element returned is the
+        * <code>IJavaModel</code></li>
+        * </ul>
+        * <p>
+        * Creating a Java element has the side effect of creating and opening all
+        * of the element's parents if they are not yet open.
+        */
+       public static IJavaElement create(IResource resource, IJavaProject project) {
+               if (resource == null) {
+                       return null;
+               }
+               int type = resource.getType();
+               switch (type) {
+               case IResource.PROJECT:
+                       return JavaCore.create((IProject) resource);
+               case IResource.FILE:
+                       return create((IFile) resource, project);
+               case IResource.FOLDER:
+                       return create((IFolder) resource, project);
+               case IResource.ROOT:
+                       return JavaCore.create((IWorkspaceRoot) resource);
+               default:
+                       return null;
+               }
+       }
+
+       /**
+        * Returns the Java element corresponding to the given file, its project
+        * being the given project. Returns <code>null</code> if unable to
+        * associate the given file with a Java element.
+        * 
+        * <p>
+        * The file must be one of:
+        * <ul>
+        * <li>a <code>.java</code> file - the element returned is the
+        * corresponding <code>ICompilationUnit</code></li>
+        * <li>a <code>.class</code> file - the element returned is the
+        * corresponding <code>IClassFile</code></li>
+        * <li>a <code>.jar</code> file - the element returned is the
+        * corresponding <code>IPackageFragmentRoot</code></li>
+        * </ul>
+        * <p>
+        * Creating a Java element has the side effect of creating and opening all
+        * of the element's parents if they are not yet open.
+        */
+       public static IJavaElement create(IFile file, IJavaProject project) {
+               if (file == null) {
+                       return null;
+               }
+               if (project == null) {
+                       project = JavaCore.create(file.getProject());
+               }
+
+               if (file.getFileExtension() != null) {
+                       String name = file.getName();
+                       if (PHPFileUtil.isValidPHPUnitName(name))
+                               // if (PHPFileUtil.isPHPFile(file))
+                               return createCompilationUnitFrom(file, project);
+                       // if (ProjectPrefUtil.isValidClassFileName(name))
+                       // return createClassFileFrom(file, project);
+                       // if (ProjectPrefUtil.isArchiveFileName(name))
+                       // return createJarPackageFragmentRootFrom(file, project);
+               }
+               return null;
+       }
+
+       /**
+        * Returns the package fragment or package fragment root corresponding to
+        * the given folder, its parent or great parent being the given project. or
+        * <code>null</code> if unable to associate the given folder with a Java
+        * element.
+        * <p>
+        * Note that a package fragment root is returned rather than a default
+        * package.
+        * <p>
+        * Creating a Java element has the side effect of creating and opening all
+        * of the element's parents if they are not yet open.
+        */
+       public static IJavaElement create(IFolder folder, IJavaProject project) {
+               if (folder == null) {
+                       return null;
+               }
+               if (project == null) {
+                       project = JavaCore.create(folder.getProject());
+               }
+               IJavaElement element = determineIfOnClasspath(folder, project);
+               if (conflictsWithOutputLocation(folder.getFullPath(),
+                               (JavaProject) project)
+                               || (folder.getName().indexOf('.') >= 0 && !(element instanceof IPackageFragmentRoot))) {
+                       return null; // only package fragment roots are allowed with dot
+                                                       // names
+               } else {
+                       return element;
+               }
+       }
+
+       /**
+        * Creates and returns a class file element for the given
+        * <code>.class</code> file, its project being the given project. Returns
+        * <code>null</code> if unable to recognize the class file.
+        */
+       // public static IClassFile createClassFileFrom(IFile file, IJavaProject
+       // project ) {
+       // if (file == null) {
+       // return null;
+       // }
+       // if (project == null) {
+       // project = PHPCore.create(file.getProject());
+       // }
+       // IPackageFragment pkg = (IPackageFragment) determineIfOnClasspath(file,
+       // project);
+       // if (pkg == null) {
+       // // fix for 1FVS7WE
+       // // not on classpath - make the root its folder, and a default package
+       // IPackageFragmentRoot root =
+       // project.getPackageFragmentRoot(file.getParent());
+       // pkg = root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+       // }
+       // return pkg.getClassFile(file.getName());
+       // }
+       /**
+        * Creates and returns a compilation unit element for the given
+        * <code>.java</code> file, its project being the given project. Returns
+        * <code>null</code> if unable to recognize the compilation unit.
+        */
+       public static ICompilationUnit createCompilationUnitFrom(IFile file,
+                       IJavaProject project) {
+
+               if (file == null)
+                       return null;
+
+               if (project == null) {
+                       project = JavaCore.create(file.getProject());
+               }
+               IPackageFragment pkg = (IPackageFragment) determineIfOnClasspath(file,
+                               project);
+               if (pkg == null) {
+                       // not on classpath - make the root its folder, and a default
+                       // package
+                       IPackageFragmentRoot root = project.getPackageFragmentRoot(file
+                                       .getParent());
+                       pkg = root
+                                       .getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+
+                       if (VERBOSE) {
+                               System.out
+                                               .println("WARNING : creating unit element outside classpath (" + Thread.currentThread() + "): " + file.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$
+                       }
+               }
+               return pkg.getCompilationUnit(file.getName());
+       }
+
+       /**
+        * Creates and returns a handle for the given JAR file, its project being
+        * the given project. The Java model associated with the JAR's project may
+        * be created as a side effect. Returns <code>null</code> if unable to
+        * create a JAR package fragment root. (for example, if the JAR file
+        * represents a non-Java resource)
+        */
+       // public static IPackageFragmentRoot createJarPackageFragmentRootFrom(IFile
+       // file, IJavaProject project) {
+       // if (file == null) {
+       // return null;
+       // }
+       // if (project == null) {
+       // project = PHPCore.create(file.getProject());
+       // }
+       //
+       // // Create a jar package fragment root only if on the classpath
+       // IPath resourcePath = file.getFullPath();
+       // try {
+       // IClasspathEntry[] entries =
+       // ((JavaProject)project).getResolvedClasspath(true);
+       // for (int i = 0, length = entries.length; i < length; i++) {
+       // IClasspathEntry entry = entries[i];
+       // IPath rootPath = entry.getPath();
+       // if (rootPath.equals(resourcePath)) {
+       // return project.getPackageFragmentRoot(file);
+       // }
+       // }
+       // } catch (JavaModelException e) {
+       // }
+       // return null;
+       // }
+       /**
+        * Returns the package fragment root represented by the resource, or the
+        * package fragment the given resource is located in, or <code>null</code>
+        * if the given resource is not on the classpath of the given project.
+        */
+       public static IJavaElement determineIfOnClasspath(IResource resource,
+                       IJavaProject project) {
+
+               IPath resourcePath = resource.getFullPath();
+               try {
+                       IClasspathEntry[] entries = net.sourceforge.phpdt.internal.compiler.util.Util
+                                       .isJavaFileName(resourcePath.lastSegment()) ? project
+                                       .getRawClasspath() // JAVA file can only live inside SRC
+                                                                               // folder (on the raw path)
+                                       : ((JavaProject) project).getResolvedClasspath(true);
+
+                       for (int i = 0; i < entries.length; i++) {
+                               IClasspathEntry entry = entries[i];
+                               if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT)
+                                       continue;
+                               IPath rootPath = entry.getPath();
+                               if (rootPath.equals(resourcePath)) {
+                                       return project.getPackageFragmentRoot(resource);
+                               } else if (rootPath.isPrefixOf(resourcePath)
+                                               && !Util.isExcluded(resource, null,
+                                                               ((ClasspathEntry) entry)
+                                                                               .fullExclusionPatternChars())) {
+                                       // given we have a resource child of the root, it cannot be
+                                       // a JAR pkg root
+                                       IPackageFragmentRoot root = ((JavaProject) project)
+                                                       .getFolderPackageFragmentRoot(rootPath);
+                                       if (root == null)
+                                               return null;
+                                       IPath pkgPath = resourcePath.removeFirstSegments(rootPath
+                                                       .segmentCount());
+                                       if (resource.getType() == IResource.FILE) {
+                                               // if the resource is a file, then remove the last
+                                               // segment which
+                                               // is the file name in the package
+                                               pkgPath = pkgPath.removeLastSegments(1);
+
+                                               // don't check validity of package name (see
+                                               // http://bugs.eclipse.org/bugs/show_bug.cgi?id=26706)
+                                               // String pkgName = pkgPath.toString().replace('/',
+                                               // '.');
+                                               String pkgName = pkgPath.toString();
+                                               return root.getPackageFragment(pkgName);
+                                       } else {
+                                               String pkgName = Util.packageName(pkgPath);
+                                               if (pkgName == null) {// ||
+                                                                                               // JavaConventions.validatePackageName(pkgName).getSeverity()
+                                                                                               // == IStatus.ERROR) {
+                                                       return null;
+                                               }
+                                               return root.getPackageFragment(pkgName);
+                                       }
+                               }
+                       }
+               } catch (JavaModelException npe) {
+                       return null;
+               }
+               return null;
+       }
+
+       /**
+        * The singleton manager
+        */
+       private final static JavaModelManager Manager = new JavaModelManager();
+
+       /**
+        * Infos cache.
+        */
+       protected JavaModelCache cache = new JavaModelCache();
+
+       /*
+        * Temporary cache of newly opened elements
+        */
+       private ThreadLocal temporaryCache = new ThreadLocal();
+
+       /**
+        * Set of elements which are out of sync with their buffers.
+        */
+       protected Map elementsOutOfSynchWithBuffers = new HashMap(11);
+
+       /**
+        * Holds the state used for delta processing.
+        */
+       public DeltaProcessingState deltaState = new DeltaProcessingState();
+
+       /**
+        * Turns delta firing on/off. By default it is on.
+        */
+       private boolean isFiring = true;
+
+       /**
+        * Queue of deltas created explicily by the Java Model that have yet to be
+        * fired.
+        */
+       ArrayList javaModelDeltas = new ArrayList();
+
+       /**
+        * Queue of reconcile deltas on working copies that have yet to be fired.
+        * This is a table form IWorkingCopy to IJavaElementDelta
+        */
+       HashMap reconcileDeltas = new HashMap();
+
+       /**
+        * Collection of listeners for Java element deltas
+        */
+       private IElementChangedListener[] elementChangedListeners = new IElementChangedListener[5];
+
+       private int[] elementChangedListenerMasks = new int[5];
+
+       private int elementChangedListenerCount = 0;
+
+       public int currentChangeEventType = ElementChangedEvent.PRE_AUTO_BUILD;
+
+       public static final int DEFAULT_CHANGE_EVENT = 0; // must not collide with
+                                                                                                               // ElementChangedEvent
+                                                                                                               // event masks
+
+       /**
+        * Used to convert <code>IResourceDelta</code>s into
+        * <code>IJavaElementDelta</code>s.
+        */
+       // public final DeltaProcessor deltaProcessor = new DeltaProcessor(this);
+       /**
+        * Used to update the JavaModel for <code>IJavaElementDelta</code>s.
+        */
+       private final ModelUpdater modelUpdater = new ModelUpdater();
+
+       /**
+        * Workaround for bug 15168 circular errors not reported This is a cache of
+        * the projects before any project addition/deletion has started.
+        */
+       public IJavaProject[] javaProjectsCache;
+
+       /**
+        * Table from IProject to PerProjectInfo. NOTE: this object itself is used
+        * as a lock to synchronize creation/removal of per project infos
+        */
+       protected Map perProjectInfo = new HashMap(5);
+
+       /**
+        * A map from ICompilationUnit to IWorkingCopy of the shared working copies.
+        */
+       public Map sharedWorkingCopies = new HashMap();
+
+       /**
+        * A weak set of the known scopes.
+        */
+       protected WeakHashMap searchScopes = new WeakHashMap();
+
+       // public static class PerProjectInfo {
+       // public IProject project;
+       // public Object savedState;
+       // public boolean triedRead;
+       // public IClasspathEntry[] classpath;
+       // public IClasspathEntry[] lastResolvedClasspath;
+       // public Map resolvedPathToRawEntries; // reverse map from resolved path to
+       // raw entries
+       // public IPath outputLocation;
+       // public Preferences preferences;
+       // public PerProjectInfo(IProject project) {
+       //
+       // this.triedRead = false;
+       // this.savedState = null;
+       // this.project = project;
+       // }
+       // }
+
+       public static class PerProjectInfo {
+
+               public IProject project;
+
+               public Object savedState;
+
+               public boolean triedRead;
+
+               public IClasspathEntry[] rawClasspath;
+
+               public IClasspathEntry[] resolvedClasspath;
+
+               public Map resolvedPathToRawEntries; // reverse map from resolved
+                                                                                               // path to raw entries
+
+               public IPath outputLocation;
+
+               public Preferences preferences;
+
+               public PerProjectInfo(IProject project) {
+
+                       this.triedRead = false;
+                       this.savedState = null;
+                       this.project = project;
+               }
+
+               // updating raw classpath need to flush obsoleted cached information
+               // about resolved entries
+               public synchronized void updateClasspathInformation(
+                               IClasspathEntry[] newRawClasspath) {
+
+                       this.rawClasspath = newRawClasspath;
+                       this.resolvedClasspath = null;
+                       this.resolvedPathToRawEntries = null;
+               }
+
+               public String toString() {
+                       StringBuffer buffer = new StringBuffer();
+                       buffer.append("Info for "); //$NON-NLS-1$
+                       buffer.append(this.project.getFullPath());
+                       buffer.append("\nRaw classpath:\n"); //$NON-NLS-1$
+                       if (this.rawClasspath == null) {
+                               buffer.append("  <null>\n"); //$NON-NLS-1$
+                       } else {
+                               for (int i = 0, length = this.rawClasspath.length; i < length; i++) {
+                                       buffer.append("  "); //$NON-NLS-1$
+                                       buffer.append(this.rawClasspath[i]);
+                                       buffer.append('\n');
+                               }
+                       }
+                       buffer.append("Resolved classpath:\n"); //$NON-NLS-1$
+                       IClasspathEntry[] resolvedCP = this.resolvedClasspath;
+                       if (resolvedCP == null) {
+                               buffer.append("  <null>\n"); //$NON-NLS-1$
+                       } else {
+                               for (int i = 0, length = resolvedCP.length; i < length; i++) {
+                                       buffer.append("  "); //$NON-NLS-1$
+                                       buffer.append(resolvedCP[i]);
+                                       buffer.append('\n');
+                               }
+                       }
+                       buffer.append("Output location:\n  "); //$NON-NLS-1$
+                       if (this.outputLocation == null) {
+                               buffer.append("<null>"); //$NON-NLS-1$
+                       } else {
+                               buffer.append(this.outputLocation);
+                       }
+                       return buffer.toString();
+               }
+       }
+
+       public static class PerWorkingCopyInfo implements IProblemRequestor {
+               int useCount = 0;
+
+               IProblemRequestor problemRequestor;
+
+               ICompilationUnit workingCopy;
+
+               public PerWorkingCopyInfo(ICompilationUnit workingCopy,
+                               IProblemRequestor problemRequestor) {
+                       this.workingCopy = workingCopy;
+                       this.problemRequestor = problemRequestor;
+               }
+
+               public void acceptProblem(IProblem problem) {
+                       if (this.problemRequestor == null)
+                               return;
+                       this.problemRequestor.acceptProblem(problem);
+               }
+
+               public void beginReporting() {
+                       if (this.problemRequestor == null)
+                               return;
+                       this.problemRequestor.beginReporting();
+               }
+
+               public void endReporting() {
+                       if (this.problemRequestor == null)
+                               return;
+                       this.problemRequestor.endReporting();
+               }
+
+               public ICompilationUnit getWorkingCopy() {
+                       return this.workingCopy;
+               }
+
+               public boolean isActive() {
+                       return this.problemRequestor != null
+                                       && this.problemRequestor.isActive();
+               }
+
+               public String toString() {
+                       StringBuffer buffer = new StringBuffer();
+                       buffer.append("Info for "); //$NON-NLS-1$
+                       buffer.append(((JavaElement) workingCopy).toStringWithAncestors());
+                       buffer.append("\nUse count = "); //$NON-NLS-1$
+                       buffer.append(this.useCount);
+                       buffer.append("\nProblem requestor:\n  "); //$NON-NLS-1$
+                       buffer.append(this.problemRequestor);
+                       return buffer.toString();
+               }
+       }
+
+       public static boolean VERBOSE = false;
+
+       public static boolean CP_RESOLVE_VERBOSE = false;
+
+       public static boolean ZIP_ACCESS_VERBOSE = false;
+
+       /**
+        * A cache of opened zip files per thread. (map from Thread to map of IPath
+        * to java.io.ZipFile) NOTE: this object itself is used as a lock to
+        * synchronize creation/removal of entries
+        */
+       private HashMap zipFiles = new HashMap();
+
+       /**
+        * Update the classpath variable cache
+        */
+       public static class PluginPreferencesListener implements
+                       Preferences.IPropertyChangeListener {
+               /**
+                * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+                */
+               public void propertyChange(Preferences.PropertyChangeEvent event) {
+                       // TODO : jsurfer temp-del
+                       // String propertyName = event.getProperty();
+                       // if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)) {
+                       // String varName =
+                       // propertyName.substring(CP_VARIABLE_PREFERENCES_PREFIX.length());
+                       // String newValue = (String)event.getNewValue();
+                       // if (newValue != null && !(newValue =
+                       // newValue.trim()).equals(CP_ENTRY_IGNORE)) {
+                       // Variables.put(varName, new Path(newValue));
+                       // } else {
+                       // Variables.remove(varName);
+                       // }
+                       // }
+                       // if (propertyName.startsWith(CP_CONTAINER_PREFERENCES_PREFIX)) {
+                       // recreatePersistedContainer(propertyName,
+                       // (String)event.getNewValue(), false);
+                       // }
+               }
+       }
+
+       /**
+        * Line separator to use throughout the JavaModel for any source edit
+        * operation
+        */
+       public static String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
+
+       /**
+        * Constructs a new JavaModelManager
+        */
+       private JavaModelManager() {
+       }
+
+       /**
+        * @deprecated - discard once debug has converted to not using it
+        */
+       public void addElementChangedListener(IElementChangedListener listener) {
+               this.addElementChangedListener(listener,
+                               ElementChangedEvent.POST_CHANGE
+                                               | ElementChangedEvent.POST_RECONCILE);
+       }
+
+       /**
+        * addElementChangedListener method comment. Need to clone defensively the
+        * listener information, in case some listener is reacting to some
+        * notification iteration by adding/changing/removing any of the other (for
+        * example, if it deregisters itself).
+        */
+       public void addElementChangedListener(IElementChangedListener listener,
+                       int eventMask) {
+               for (int i = 0; i < this.elementChangedListenerCount; i++) {
+                       if (this.elementChangedListeners[i].equals(listener)) {
+
+                               // only clone the masks, since we could be in the middle of
+                               // notifications and one listener decide to change
+                               // any event mask of another listeners (yet not notified).
+                               int cloneLength = this.elementChangedListenerMasks.length;
+                               System
+                                               .arraycopy(
+                                                               this.elementChangedListenerMasks,
+                                                               0,
+                                                               this.elementChangedListenerMasks = new int[cloneLength],
+                                                               0, cloneLength);
+                               this.elementChangedListenerMasks[i] = eventMask; // could be
+                                                                                                                                       // different
+                               return;
+                       }
+               }
+               // may need to grow, no need to clone, since iterators will have cached
+               // original arrays and max boundary and we only add to the end.
+               int length;
+               if ((length = this.elementChangedListeners.length) == this.elementChangedListenerCount) {
+                       System
+                                       .arraycopy(
+                                                       this.elementChangedListeners,
+                                                       0,
+                                                       this.elementChangedListeners = new IElementChangedListener[length * 2],
+                                                       0, length);
+                       System.arraycopy(this.elementChangedListenerMasks, 0,
+                                       this.elementChangedListenerMasks = new int[length * 2], 0,
+                                       length);
+               }
+               this.elementChangedListeners[this.elementChangedListenerCount] = listener;
+               this.elementChangedListenerMasks[this.elementChangedListenerCount] = eventMask;
+               this.elementChangedListenerCount++;
+       }
+
+       /**
+        * Starts caching ZipFiles. Ignores if there are already clients.
+        */
+       public void cacheZipFiles() {
+               synchronized (this.zipFiles) {
+                       Thread currentThread = Thread.currentThread();
+                       if (this.zipFiles.get(currentThread) != null)
+                               return;
+                       this.zipFiles.put(currentThread, new HashMap());
+               }
+       }
+
+       public void closeZipFile(ZipFile zipFile) {
+               if (zipFile == null)
+                       return;
+               synchronized (this.zipFiles) {
+                       if (this.zipFiles.get(Thread.currentThread()) != null) {
+                               return; // zip file will be closed by call to flushZipFiles
+                       }
+                       try {
+                               if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
+                                       System.out
+                                                       .println("(" + Thread.currentThread() + ") [JavaModelManager.closeZipFile(ZipFile)] Closing ZipFile on " + zipFile.getName()); //$NON-NLS-1$    //$NON-NLS-2$
+                               }
+                               zipFile.close();
+                       } catch (IOException e) {
+                       }
+               }
+       }
+
+       /**
+        * Configure the plugin with respect to option settings defined in
+        * ".options" file
+        */
+       public void configurePluginDebugOptions() {
+               if (JavaCore.getPlugin().isDebugging()) {
+                       // TODO jsurfer temp-del
+
+                       String option = Platform.getDebugOption(BUILDER_DEBUG);
+                       // if(option != null) JavaBuilder.DEBUG =
+                       // option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+                       //
+                       // option = Platform.getDebugOption(COMPILER_DEBUG);
+                       // if(option != null) Compiler.DEBUG =
+                       // option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+                       //
+                       // option = Platform.getDebugOption(COMPLETION_DEBUG);
+                       // if(option != null) CompletionEngine.DEBUG =
+                       // option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+                       //
+                       option = Platform.getDebugOption(CP_RESOLVE_DEBUG);
+                       if (option != null)
+                               JavaModelManager.CP_RESOLVE_VERBOSE = option
+                                               .equalsIgnoreCase("true"); //$NON-NLS-1$
+
+                       option = Platform.getDebugOption(DELTA_DEBUG);
+                       if (option != null)
+                               DeltaProcessor.VERBOSE = option.equalsIgnoreCase("true"); //$NON-NLS-1$
+
+                       // option = Platform.getDebugOption(HIERARCHY_DEBUG);
+                       // if(option != null) TypeHierarchy.DEBUG =
+                       // option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+                       //
+                       // option = Platform.getDebugOption(INDEX_MANAGER_DEBUG);
+                       // if(option != null) IndexManager.VERBOSE =
+                       // option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+
+                       option = Platform.getDebugOption(JAVAMODEL_DEBUG);
+                       if (option != null)
+                               JavaModelManager.VERBOSE = option.equalsIgnoreCase("true"); //$NON-NLS-1$
+
+                       option = Platform.getDebugOption(POST_ACTION_DEBUG);
+                       if (option != null)
+                               JavaModelOperation.POST_ACTION_VERBOSE = option
+                                               .equalsIgnoreCase("true"); //$NON-NLS-1$
+
+                       // option = Platform.getDebugOption(SEARCH_DEBUG);
+                       // if(option != null) SearchEngine.VERBOSE =
+                       // option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+                       //
+                       // option = Platform.getDebugOption(SELECTION_DEBUG);
+                       // if(option != null) SelectionEngine.DEBUG =
+                       // option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+
+                       option = Platform.getDebugOption(ZIP_ACCESS_DEBUG);
+                       if (option != null)
+                               JavaModelManager.ZIP_ACCESS_VERBOSE = option
+                                               .equalsIgnoreCase("true"); //$NON-NLS-1$
+               }
+       }
+
+       /*
+        * Discards the per working copy info for the given working copy (making it
+        * a compilation unit) if its use count was 1. Otherwise, just decrement the
+        * use count. If the working copy is primary, computes the delta between its
+        * state and the original compilation unit and register it. Close the
+        * working copy, its buffer and remove it from the shared working copy
+        * table. Ignore if no per-working copy info existed. NOTE: it must be
+        * synchronized as it may interact with the element info cache (if useCount
+        * is decremented to 0), see bug 50667. Returns the new use count (or -1 if
+        * it didn't exist).
+        */
+       public synchronized int discardPerWorkingCopyInfo(
+                       CompilationUnit workingCopy) throws JavaModelException {
+               synchronized (perWorkingCopyInfos) {
+                       WorkingCopyOwner owner = workingCopy.owner;
+                       Map workingCopyToInfos = (Map) this.perWorkingCopyInfos.get(owner);
+                       if (workingCopyToInfos == null)
+                               return -1;
+
+                       PerWorkingCopyInfo info = (PerWorkingCopyInfo) workingCopyToInfos
+                                       .get(workingCopy);
+                       if (info == null)
+                               return -1;
+
+                       if (--info.useCount == 0) {
+                               // create the delta builder (this remembers the current content
+                               // of the working copy)
+                               JavaElementDeltaBuilder deltaBuilder = null;
+                               if (workingCopy.isPrimary()) {
+                                       deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
+                               }
+
+                               // remove per working copy info
+                               workingCopyToInfos.remove(workingCopy);
+                               if (workingCopyToInfos.isEmpty()) {
+                                       this.perWorkingCopyInfos.remove(owner);
+                               }
+
+                               // remove infos + close buffer (since no longer working copy)
+                               removeInfoAndChildren(workingCopy);
+                               workingCopy.closeBuffer();
+
+                               // compute the delta if needed and register it if there are
+                               // changes
+                               if (deltaBuilder != null) {
+                                       deltaBuilder.buildDeltas();
+                                       if ((deltaBuilder.delta != null)
+                                                       && (deltaBuilder.delta.getAffectedChildren().length > 0)) {
+                                               getDeltaProcessor().registerJavaModelDelta(
+                                                               deltaBuilder.delta);
+                                       }
+                               }
+
+                       }
+                       return info.useCount;
+               }
+       }
+
+       /**
+        * @see ISaveParticipant
+        */
+       public void doneSaving(ISaveContext context) {
+       }
+
+       /**
+        * Fire Java Model delta, flushing them after the fact after post_change
+        * notification. If the firing mode has been turned off, this has no effect.
+        */
+       public void fire(IJavaElementDelta customDelta, int eventType) {
+
+               if (!this.isFiring)
+                       return;
+
+               if (DeltaProcessor.VERBOSE
+                               && (eventType == DEFAULT_CHANGE_EVENT || eventType == ElementChangedEvent.PRE_AUTO_BUILD)) {
+                       System.out
+                                       .println("-----------------------------------------------------------------------------------------------------------------------");//$NON-NLS-1$
+               }
+
+               IJavaElementDelta deltaToNotify;
+               if (customDelta == null) {
+                       deltaToNotify = this.mergeDeltas(this.javaModelDeltas);
+               } else {
+                       deltaToNotify = customDelta;
+               }
+
+               // Refresh internal scopes
+               if (deltaToNotify != null) {
+                       // TODO temp-del
+                       // Iterator scopes = this.scopes.keySet().iterator();
+                       // while (scopes.hasNext()) {
+                       // AbstractSearchScope scope = (AbstractSearchScope)scopes.next();
+                       // scope.processDelta(deltaToNotify);
+                       // }
+               }
+
+               // Notification
+
+               // Important: if any listener reacts to notification by updating the
+               // listeners list or mask, these lists will
+               // be duplicated, so it is necessary to remember original lists in a
+               // variable (since field values may change under us)
+               IElementChangedListener[] listeners = this.elementChangedListeners;
+               int[] listenerMask = this.elementChangedListenerMasks;
+               int listenerCount = this.elementChangedListenerCount;
+
+               switch (eventType) {
+               case DEFAULT_CHANGE_EVENT:
+                       firePreAutoBuildDelta(deltaToNotify, listeners, listenerMask,
+                                       listenerCount);
+                       firePostChangeDelta(deltaToNotify, listeners, listenerMask,
+                                       listenerCount);
+                       fireReconcileDelta(listeners, listenerMask, listenerCount);
+                       break;
+               case ElementChangedEvent.PRE_AUTO_BUILD:
+                       firePreAutoBuildDelta(deltaToNotify, listeners, listenerMask,
+                                       listenerCount);
+                       break;
+               case ElementChangedEvent.POST_CHANGE:
+                       firePostChangeDelta(deltaToNotify, listeners, listenerMask,
+                                       listenerCount);
+                       fireReconcileDelta(listeners, listenerMask, listenerCount);
+                       break;
+               }
+
+       }
+
+       private void firePreAutoBuildDelta(IJavaElementDelta deltaToNotify,
+                       IElementChangedListener[] listeners, int[] listenerMask,
+                       int listenerCount) {
+
+               if (DeltaProcessor.VERBOSE) {
+                       System.out
+                                       .println("FIRING PRE_AUTO_BUILD Delta [" + Thread.currentThread() + "]:"); //$NON-NLS-1$//$NON-NLS-2$
+                       System.out
+                                       .println(deltaToNotify == null ? "<NONE>" : deltaToNotify.toString()); //$NON-NLS-1$
+               }
+               if (deltaToNotify != null) {
+                       notifyListeners(deltaToNotify, ElementChangedEvent.PRE_AUTO_BUILD,
+                                       listeners, listenerMask, listenerCount);
+               }
+       }
+
+       private void firePostChangeDelta(IJavaElementDelta deltaToNotify,
+                       IElementChangedListener[] listeners, int[] listenerMask,
+                       int listenerCount) {
+
+               // post change deltas
+               if (DeltaProcessor.VERBOSE) {
+                       System.out
+                                       .println("FIRING POST_CHANGE Delta [" + Thread.currentThread() + "]:"); //$NON-NLS-1$//$NON-NLS-2$
+                       System.out
+                                       .println(deltaToNotify == null ? "<NONE>" : deltaToNotify.toString()); //$NON-NLS-1$
+               }
+               if (deltaToNotify != null) {
+                       // flush now so as to keep listener reactions to post their own
+                       // deltas for subsequent iteration
+                       this.flush();
+
+                       notifyListeners(deltaToNotify, ElementChangedEvent.POST_CHANGE,
+                                       listeners, listenerMask, listenerCount);
+               }
+       }
+
+       private void fireReconcileDelta(IElementChangedListener[] listeners,
+                       int[] listenerMask, int listenerCount) {
+
+               IJavaElementDelta deltaToNotify = mergeDeltas(this.reconcileDeltas
+                               .values());
+               if (DeltaProcessor.VERBOSE) {
+                       System.out
+                                       .println("FIRING POST_RECONCILE Delta [" + Thread.currentThread() + "]:"); //$NON-NLS-1$//$NON-NLS-2$
+                       System.out
+                                       .println(deltaToNotify == null ? "<NONE>" : deltaToNotify.toString()); //$NON-NLS-1$
+               }
+               if (deltaToNotify != null) {
+                       // flush now so as to keep listener reactions to post their own
+                       // deltas for subsequent iteration
+                       this.reconcileDeltas = new HashMap();
+
+                       notifyListeners(deltaToNotify, ElementChangedEvent.POST_RECONCILE,
+                                       listeners, listenerMask, listenerCount);
+               }
+       }
+
+       public void notifyListeners(IJavaElementDelta deltaToNotify, int eventType,
+                       IElementChangedListener[] listeners, int[] listenerMask,
+                       int listenerCount) {
+               final ElementChangedEvent extraEvent = new ElementChangedEvent(
+                               deltaToNotify, eventType);
+               for (int i = 0; i < listenerCount; i++) {
+                       if ((listenerMask[i] & eventType) != 0) {
+                               final IElementChangedListener listener = listeners[i];
+                               long start = -1;
+                               if (DeltaProcessor.VERBOSE) {
+                                       System.out
+                                                       .print("Listener #" + (i + 1) + "=" + listener.toString());//$NON-NLS-1$//$NON-NLS-2$
+                                       start = System.currentTimeMillis();
+                               }
+                               // wrap callbacks with Safe runnable for subsequent listeners to
+                               // be called when some are causing grief
+                               Platform.run(new ISafeRunnable() {
+                                       public void handleException(Throwable exception) {
+                                               Util
+                                                               .log(exception,
+                                                                               "Exception occurred in listener of Java element change notification"); //$NON-NLS-1$
+                                       }
+
+                                       public void run() throws Exception {
+                                               listener.elementChanged(extraEvent);
+                                       }
+                               });
+                               if (DeltaProcessor.VERBOSE) {
+                                       System.out
+                                                       .println(" -> " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Flushes all deltas without firing them.
+        */
+       protected void flush() {
+               this.javaModelDeltas = new ArrayList();
+       }
+
+       /**
+        * Flushes ZipFiles cache if there are no more clients.
+        */
+       public void flushZipFiles() {
+               synchronized (this.zipFiles) {
+                       Thread currentThread = Thread.currentThread();
+                       HashMap map = (HashMap) this.zipFiles.remove(currentThread);
+                       if (map == null)
+                               return;
+                       Iterator iterator = map.values().iterator();
+                       while (iterator.hasNext()) {
+                               try {
+                                       ZipFile zipFile = (ZipFile) iterator.next();
+                                       if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
+                                               System.out
+                                                               .println("(" + currentThread + ") [JavaModelManager.flushZipFiles()] Closing ZipFile on " + zipFile.getName()); //$NON-NLS-1$//$NON-NLS-2$
+                                       }
+                                       zipFile.close();
+                               } catch (IOException e) {
+                               }
+                       }
+               }
+       }
+
+       public DeltaProcessor getDeltaProcessor() {
+               return this.deltaState.getDeltaProcessor();
+       }
+
+       /**
+        * Returns the set of elements which are out of synch with their buffers.
+        */
+       protected Map getElementsOutOfSynchWithBuffers() {
+               return this.elementsOutOfSynchWithBuffers;
+       }
+
+       // public IndexManager getIndexManager() {
+       // return this.indexManager;
+       // }
+       /**
+        * Returns the <code>IJavaElement</code> represented by the
+        * <code>String</code> memento.
+        */
+       public IJavaElement getHandleFromMemento(String memento)
+                       throws JavaModelException {
+               if (memento == null) {
+                       return null;
+               }
+               JavaModel model = (JavaModel) getJavaModel();
+               if (memento.equals("")) { // workspace memento //$NON-NLS-1$
+                       return model;
+               }
+               int modelEnd = memento.indexOf(JavaElement.JEM_JAVAPROJECT);
+               if (modelEnd == -1) {
+                       return null;
+               }
+               boolean returnProject = false;
+               int projectEnd = memento.indexOf(JavaElement.JEM_PACKAGEFRAGMENTROOT,
+                               modelEnd);
+               if (projectEnd == -1) {
+                       projectEnd = memento.length();
+                       returnProject = true;
+               }
+               String projectName = memento.substring(modelEnd + 1, projectEnd);
+               JavaProject proj = (JavaProject) model.getJavaProject(projectName);
+               if (returnProject) {
+                       return proj;
+               }
+               int rootEnd = memento.indexOf(JavaElement.JEM_PACKAGEFRAGMENT,
+                               projectEnd + 1);
+               // TODO temp-del
+               // if (rootEnd == -1) {
+               // return model.getHandleFromMementoForRoot(memento, proj, projectEnd,
+               // memento.length());
+               // }
+               // IPackageFragmentRoot root =
+               // model.getHandleFromMementoForRoot(memento, proj, projectEnd,
+               // rootEnd);
+               // if (root == null)
+               // return null;
+               //
+               // int end= memento.indexOf(JavaElement.JEM_COMPILATIONUNIT, rootEnd);
+               // if (end == -1) {
+               // end= memento.indexOf(JavaElement.JEM_CLASSFILE, rootEnd);
+               // if (end == -1) {
+               // if (rootEnd + 1 == memento.length()) {
+               // return
+               // root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
+               // } else {
+               // return root.getPackageFragment(memento.substring(rootEnd + 1));
+               // }
+               // }
+               // //deal with class file and binary members
+               // return model.getHandleFromMementoForBinaryMembers(memento, root,
+               // rootEnd, end);
+               // }
+               //
+               // //deal with compilation units and source members
+               // return model.getHandleFromMementoForSourceMembers(memento, root,
+               // rootEnd, end);
+               return null;
+       }
+
+       // public IndexManager getIndexManager() {
+       // return this.deltaProcessor.indexManager;
+       // }
+
+       /**
+        * Returns the info for the element.
+        */
+       public Object getInfo(IJavaElement element) {
+               return this.cache.getInfo(element);
+       }
+
+       /**
+        * Returns the handle to the active Java Model.
+        */
+       public final JavaModel getJavaModel() {
+               return javaModel;
+       }
+
+       /**
+        * Returns the singleton JavaModelManager
+        */
+       public final static JavaModelManager getJavaModelManager() {
+               return Manager;
+       }
+
+       /**
+        * Returns the last built state for the given project, or null if there is
+        * none. Deserializes the state if necessary.
+        * 
+        * For use by image builder and evaluation support only
+        */
+       public Object getLastBuiltState(IProject project, IProgressMonitor monitor) {
+               if (!JavaProject.hasJavaNature(project))
+                       return null; // should never be requested on non-Java projects
+               PerProjectInfo info = getPerProjectInfo(project, true/*
+                                                                                                                                * create if
+                                                                                                                                * missing
+                                                                                                                                */);
+               if (!info.triedRead) {
+                       info.triedRead = true;
+                       try {
+                               if (monitor != null)
+                                       monitor.subTask(Util.bind(
+                                                       "build.readStateProgress", project.getName())); //$NON-NLS-1$
+                               info.savedState = readState(project);
+                       } catch (CoreException e) {
+                               e.printStackTrace();
+                       }
+               }
+               return info.savedState;
+       }
+
+       /*
+        * Returns the per-project info for the given project. If specified, create
+        * the info if the info doesn't exist.
+        */
+       public PerProjectInfo getPerProjectInfo(IProject project, boolean create) {
+               synchronized (perProjectInfo) { // use the perProjectInfo collection as
+                                                                               // its own lock
+                       PerProjectInfo info = (PerProjectInfo) perProjectInfo.get(project);
+                       if (info == null && create) {
+                               info = new PerProjectInfo(project);
+                               perProjectInfo.put(project, info);
+                       }
+                       return info;
+               }
+       }
+
+       /*
+        * Returns the per-project info for the given project. If the info doesn't
+        * exist, check for the project existence and create the info. @throws
+        * JavaModelException if the project doesn't exist.
+        */
+       public PerProjectInfo getPerProjectInfoCheckExistence(IProject project)
+                       throws JavaModelException {
+               JavaModelManager.PerProjectInfo info = getPerProjectInfo(project, false /*
+                                                                                                                                                                * don't
+                                                                                                                                                                * create
+                                                                                                                                                                * info
+                                                                                                                                                                */);
+               if (info == null) {
+                       if (!JavaProject.hasJavaNature(project)) {
+                               throw ((JavaProject) JavaCore.create(project))
+                                               .newNotPresentException();
+                       }
+                       info = getPerProjectInfo(project, true /* create info */);
+               }
+               return info;
+       }
+
+       /*
+        * Returns the per-working copy info for the given working copy at the given
+        * path. If it doesn't exist and if create, add a new per-working copy info
+        * with the given problem requestor. If recordUsage, increment the
+        * per-working copy info's use count. Returns null if it doesn't exist and
+        * not create.
+        */
+       public PerWorkingCopyInfo getPerWorkingCopyInfo(
+                       CompilationUnit workingCopy, boolean create, boolean recordUsage,
+                       IProblemRequestor problemRequestor) {
+               synchronized (perWorkingCopyInfos) { // use the perWorkingCopyInfo
+                                                                                               // collection as its own lock
+                       WorkingCopyOwner owner = workingCopy.owner;
+                       Map workingCopyToInfos = (Map) this.perWorkingCopyInfos.get(owner);
+                       if (workingCopyToInfos == null && create) {
+                               workingCopyToInfos = new HashMap();
+                               this.perWorkingCopyInfos.put(owner, workingCopyToInfos);
+                       }
+
+                       PerWorkingCopyInfo info = workingCopyToInfos == null ? null
+                                       : (PerWorkingCopyInfo) workingCopyToInfos.get(workingCopy);
+                       if (info == null && create) {
+                               info = new PerWorkingCopyInfo(workingCopy, problemRequestor);
+                               workingCopyToInfos.put(workingCopy, info);
+                       }
+                       if (info != null && recordUsage)
+                               info.useCount++;
+                       return info;
+               }
+       }
+
+       /**
+        * Returns the name of the variables for which an CP variable initializer is
+        * registered through an extension point
+        */
+       public static String[] getRegisteredVariableNames() {
+
+               Plugin jdtCorePlugin = JavaCore.getPlugin();
+               if (jdtCorePlugin == null)
+                       return null;
+
+               ArrayList variableList = new ArrayList(5);
+               // IExtensionPoint extension =
+               // jdtCorePlugin.getDescriptor().getExtensionPoint(JavaModelManager.CPVARIABLE_INITIALIZER_EXTPOINT_ID);
+               // if (extension != null) {
+               // IExtension[] extensions = extension.getExtensions();
+               // for(int i = 0; i < extensions.length; i++){
+               // IConfigurationElement [] configElements =
+               // extensions[i].getConfigurationElements();
+               // for(int j = 0; j < configElements.length; j++){
+               // String varAttribute = configElements[j].getAttribute("variable");
+               // //$NON-NLS-1$
+               // if (varAttribute != null) variableList.add(varAttribute);
+               // }
+               // }
+               // }
+               String[] variableNames = new String[variableList.size()];
+               variableList.toArray(variableNames);
+               return variableNames;
+       }
+
+       /**
+        * Returns the name of the container IDs for which an CP container
+        * initializer is registered through an extension point
+        */
+       // public static String[] getRegisteredContainerIDs(){
+       //
+       // Plugin jdtCorePlugin = PHPCore.getPlugin();
+       // if (jdtCorePlugin == null) return null;
+       //
+       // ArrayList containerIDList = new ArrayList(5);
+       // IExtensionPoint extension =
+       // jdtCorePlugin.getDescriptor().getExtensionPoint(JavaModelManager.CPCONTAINER_INITIALIZER_EXTPOINT_ID);
+       // if (extension != null) {
+       // IExtension[] extensions = extension.getExtensions();
+       // for(int i = 0; i < extensions.length; i++){
+       // IConfigurationElement [] configElements =
+       // extensions[i].getConfigurationElements();
+       // for(int j = 0; j < configElements.length; j++){
+       // String idAttribute = configElements[j].getAttribute("id"); //$NON-NLS-1$
+       // if (idAttribute != null) containerIDList.add(idAttribute);
+       // }
+       // }
+       // }
+       // String[] containerIDs = new String[containerIDList.size()];
+       // containerIDList.toArray(containerIDs);
+       // return containerIDs;
+       // }
+       /**
+        * Returns the File to use for saving and restoring the last built state for
+        * the given project.
+        */
+       private File getSerializationFile(IProject project) {
+               if (!project.exists())
+                       return null;
+               IPath workingLocation = project.getWorkingLocation(JavaCore.PLUGIN_ID);
+               return workingLocation.append("state.dat").toFile(); //$NON-NLS-1$
+       }
+
+       /*
+        * Returns the temporary cache for newly opened elements for the current
+        * thread. Creates it if not already created.
+        */
+       public HashMap getTemporaryCache() {
+               HashMap result = (HashMap) this.temporaryCache.get();
+               if (result == null) {
+                       result = new HashMap();
+                       this.temporaryCache.set(result);
+               }
+               return result;
+       }
+
+       /**
+        * Returns the open ZipFile at the given location. If the ZipFile does not
+        * yet exist, it is created, opened, and added to the cache of open
+        * ZipFiles. The location must be a absolute path.
+        * 
+        * @exception CoreException
+        *                If unable to create/open the ZipFile
+        */
+       public ZipFile getZipFile(IPath path) throws CoreException {
+
+               synchronized (this.zipFiles) { // TODO: use PeThreadObject which does
+                                                                               // synchronization
+                       Thread currentThread = Thread.currentThread();
+                       HashMap map = null;
+                       ZipFile zipFile;
+                       if ((map = (HashMap) this.zipFiles.get(currentThread)) != null
+                                       && (zipFile = (ZipFile) map.get(path)) != null) {
+
+                               return zipFile;
+                       }
+                       String fileSystemPath = null;
+                       IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+                       IResource file = root.findMember(path);
+                       if (path.isAbsolute() && file != null) {
+                               if (file == null) { // external file
+                                       fileSystemPath = path.toOSString();
+                               } else { // internal resource (not an IFile or not existing)
+                                       IPath location;
+                                       if (file.getType() != IResource.FILE
+                                                       || (location = file.getLocation()) == null) {
+                                               throw new CoreException(
+                                                               new Status(
+                                                                               IStatus.ERROR,
+                                                                               JavaCore.PLUGIN_ID,
+                                                                               -1,
+                                                                               Util
+                                                                                               .bind(
+                                                                                                               "file.notFound", path.toString()), null)); //$NON-NLS-1$
+                                       }
+                                       fileSystemPath = location.toOSString();
+                               }
+                       } else if (!path.isAbsolute()) {
+                               file = root.getFile(path);
+                               if (file == null || file.getType() != IResource.FILE) {
+                                       throw new CoreException(new Status(IStatus.ERROR,
+                                                       JavaCore.PLUGIN_ID, -1, Util.bind(
+                                                                       "file.notFound", path.toString()), null)); //$NON-NLS-1$
+                               }
+                               IPath location = file.getLocation();
+                               if (location == null) {
+                                       throw new CoreException(new Status(IStatus.ERROR,
+                                                       JavaCore.PLUGIN_ID, -1, Util.bind(
+                                                                       "file.notFound", path.toString()), null)); //$NON-NLS-1$
+                               }
+                               fileSystemPath = location.toOSString();
+                       } else {
+                               fileSystemPath = path.toOSString();
+                       }
+
+                       try {
+                               if (ZIP_ACCESS_VERBOSE) {
+                                       System.out
+                                                       .println("(" + currentThread + ") [JavaModelManager.getZipFile(IPath)] Creating ZipFile on " + fileSystemPath); //$NON-NLS-1$ //$NON-NLS-2$
+                               }
+                               zipFile = new ZipFile(fileSystemPath);
+                               if (map != null) {
+                                       map.put(path, zipFile);
+                               }
+                               return zipFile;
+                       } catch (IOException e) {
+                               throw new CoreException(new Status(Status.ERROR,
+                                               JavaCore.PLUGIN_ID, -1,
+                                               Util.bind("status.IOException"), e)); //$NON-NLS-1$
+                       }
+               }
+       }
+
+       /*
+        * Returns whether there is a temporary cache for the current thread.
+        */
+       public boolean hasTemporaryCache() {
+               return this.temporaryCache.get() != null;
+       }
+
+       // public void loadVariablesAndContainers() throws CoreException {
+       //
+       // // backward compatibility, consider persistent property
+       // QualifiedName qName = new QualifiedName(PHPCore.PLUGIN_ID, "variables");
+       // //$NON-NLS-1$
+       // String xmlString =
+       // ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
+       //
+       // try {
+       // if (xmlString != null){
+       // StringReader reader = new StringReader(xmlString);
+       // Element cpElement;
+       // try {
+       // DocumentBuilder parser =
+       // DocumentBuilderFactory.newInstance().newDocumentBuilder();
+       // cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
+       // } catch(SAXException e) {
+       // return;
+       // } catch(ParserConfigurationException e){
+       // return;
+       // } finally {
+       // reader.close();
+       // }
+       // if (cpElement == null) return;
+       // if (!cpElement.getNodeName().equalsIgnoreCase("variables")) {
+       // //$NON-NLS-1$
+       // return;
+       // }
+       //
+       // NodeList list= cpElement.getChildNodes();
+       // int length= list.getLength();
+       // for (int i= 0; i < length; ++i) {
+       // Node node= list.item(i);
+       // short type= node.getNodeType();
+       // if (type == Node.ELEMENT_NODE) {
+       // Element element= (Element) node;
+       // if (element.getNodeName().equalsIgnoreCase("variable")) { //$NON-NLS-1$
+       // variablePut(
+       // element.getAttribute("name"), //$NON-NLS-1$
+       // new Path(element.getAttribute("path"))); //$NON-NLS-1$
+       // }
+       // }
+       // }
+       // }
+       // } catch(IOException e){
+       // } finally {
+       // if (xmlString != null){
+       // ResourcesPlugin.getWorkspace().getRoot().setPersistentProperty(qName,
+       // null); // flush old one
+       // }
+       //
+       // }
+       //
+       // // load variables and containers from preferences into cache
+       // Preferences preferences =
+       // PHPeclipsePlugin.getDefault().getPluginPreferences();
+
+       // // only get variable from preferences not set to their default
+       // String[] propertyNames = preferences.propertyNames();
+       // int variablePrefixLength = CP_VARIABLE_PREFERENCES_PREFIX.length();
+       // for (int i = 0; i < propertyNames.length; i++){
+       // String propertyName = propertyNames[i];
+       // if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)){
+       // String varName = propertyName.substring(variablePrefixLength);
+       // IPath varPath = new Path(preferences.getString(propertyName).trim());
+       //
+       // Variables.put(varName, varPath);
+       // PreviousSessionVariables.put(varName, varPath);
+       // }
+       // if (propertyName.startsWith(CP_CONTAINER_PREFERENCES_PREFIX)){
+       // recreatePersistedContainer(propertyName,
+       // preferences.getString(propertyName), true/*add to container values*/);
+       // }
+       // }
+       // // override persisted values for variables which have a registered
+       // initializer
+       // String[] registeredVariables = getRegisteredVariableNames();
+       // for (int i = 0; i < registeredVariables.length; i++) {
+       // String varName = registeredVariables[i];
+       // Variables.put(varName, null); // reset variable, but leave its entry in
+       // the Map, so it will be part of variable names.
+       // }
+       // // override persisted values for containers which have a registered
+       // initializer
+       // String[] registeredContainerIDs = getRegisteredContainerIDs();
+       // for (int i = 0; i < registeredContainerIDs.length; i++) {
+       // String containerID = registeredContainerIDs[i];
+       // Iterator projectIterator = Containers.keySet().iterator();
+       // while (projectIterator.hasNext()){
+       // IJavaProject project = (IJavaProject)projectIterator.next();
+       // Map projectContainers = (Map)Containers.get(project);
+       // if (projectContainers != null){
+       // Iterator containerIterator = projectContainers.keySet().iterator();
+       // while (containerIterator.hasNext()){
+       // IPath containerPath = (IPath)containerIterator.next();
+       // if (containerPath.segment(0).equals(containerID)) { // registered
+       // container
+       // projectContainers.put(containerPath, null); // reset container value, but
+       // leave entry in Map
+       // }
+       // }
+       // }
+       // }
+       // }
+       // }
+
+       /**
+        * Merged all awaiting deltas.
+        */
+       public IJavaElementDelta mergeDeltas(Collection deltas) {
+               if (deltas.size() == 0)
+                       return null;
+               if (deltas.size() == 1)
+                       return (IJavaElementDelta) deltas.iterator().next();
+
+               if (DeltaProcessor.VERBOSE) {
+                       System.out
+                                       .println("MERGING " + deltas.size() + " DELTAS [" + Thread.currentThread() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+               }
+
+               Iterator iterator = deltas.iterator();
+               IJavaElement javaModel = this.getJavaModel();
+               JavaElementDelta rootDelta = new JavaElementDelta(javaModel);
+               boolean insertedTree = false;
+               while (iterator.hasNext()) {
+                       JavaElementDelta delta = (JavaElementDelta) iterator.next();
+                       if (DeltaProcessor.VERBOSE) {
+                               System.out.println(delta.toString());
+                       }
+                       IJavaElement element = delta.getElement();
+                       if (javaModel.equals(element)) {
+                               IJavaElementDelta[] children = delta.getAffectedChildren();
+                               for (int j = 0; j < children.length; j++) {
+                                       JavaElementDelta projectDelta = (JavaElementDelta) children[j];
+                                       rootDelta.insertDeltaTree(projectDelta.getElement(),
+                                                       projectDelta);
+                                       insertedTree = true;
+                               }
+                               IResourceDelta[] resourceDeltas = delta.getResourceDeltas();
+                               if (resourceDeltas != null) {
+                                       for (int i = 0, length = resourceDeltas.length; i < length; i++) {
+                                               rootDelta.addResourceDelta(resourceDeltas[i]);
+                                               insertedTree = true;
+                                       }
+                               }
+                       } else {
+                               rootDelta.insertDeltaTree(element, delta);
+                               insertedTree = true;
+                       }
+               }
+               if (insertedTree) {
+                       return rootDelta;
+               } else {
+                       return null;
+               }
+       }
+
+       /**
+        * Returns the info for this element without disturbing the cache ordering.
+        */
+       // TODO: should be synchronized, could answer unitialized info or if cache
+       // is in middle of rehash, could even answer distinct element info
+       protected Object peekAtInfo(IJavaElement element) {
+               return this.cache.peekAtInfo(element);
+       }
+
+       /**
+        * @see ISaveParticipant
+        */
+       public void prepareToSave(ISaveContext context) throws CoreException {
+       }
+
+       protected void putInfo(IJavaElement element, Object info) {
+               this.cache.putInfo(element, info);
+       }
+
+       /*
+        * Puts the infos in the given map (keys are IJavaElements and values are
+        * JavaElementInfos) in the Java model cache in an atomic way. First checks
+        * that the info for the opened element (or one of its ancestors) has not
+        * been added to the cache. If it is the case, another thread has opened the
+        * element (or one of its ancestors). So returns without updating the cache.
+        */
+       protected synchronized void putInfos(IJavaElement openedElement,
+                       Map newElements) {
+               // remove children
+               Object existingInfo = this.cache.peekAtInfo(openedElement);
+               if (openedElement instanceof IParent
+                               && existingInfo instanceof JavaElementInfo) {
+                       IJavaElement[] children = ((JavaElementInfo) existingInfo)
+                                       .getChildren();
+                       for (int i = 0, size = children.length; i < size; ++i) {
+                               JavaElement child = (JavaElement) children[i];
+                               try {
+                                       child.close();
+                               } catch (JavaModelException e) {
+                                       // ignore
+                               }
+                       }
+               }
+
+               Iterator iterator = newElements.keySet().iterator();
+               while (iterator.hasNext()) {
+                       IJavaElement element = (IJavaElement) iterator.next();
+                       Object info = newElements.get(element);
+                       this.cache.putInfo(element, info);
+               }
+       }
+
+       /**
+        * Reads the build state for the relevant project.
+        */
+       protected Object readState(IProject project) throws CoreException {
+               File file = getSerializationFile(project);
+               if (file != null && file.exists()) {
+                       try {
+                               DataInputStream in = new DataInputStream(
+                                               new BufferedInputStream(new FileInputStream(file)));
+                               try {
+                                       String pluginID = in.readUTF();
+                                       if (!pluginID.equals(JavaCore.PLUGIN_ID))
+                                               throw new IOException(Util
+                                                               .bind("build.wrongFileFormat")); //$NON-NLS-1$
+                                       String kind = in.readUTF();
+                                       if (!kind.equals("STATE")) //$NON-NLS-1$
+                                               throw new IOException(Util
+                                                               .bind("build.wrongFileFormat")); //$NON-NLS-1$
+                                       if (in.readBoolean())
+                                               return PHPBuilder.readState(project, in);
+                                       if (PHPBuilder.DEBUG)
+                                               System.out
+                                                               .println("Saved state thinks last build failed for " + project.getName()); //$NON-NLS-1$
+                               } finally {
+                                       in.close();
+                               }
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                               throw new CoreException(
+                                               new Status(
+                                                               IStatus.ERROR,
+                                                               JavaCore.PLUGIN_ID,
+                                                               Platform.PLUGIN_ERROR,
+                                                               "Error reading last build state for project " + project.getName(), e)); //$NON-NLS-1$
+                       }
+               }
+               return null;
+       }
+
+       // public static void recreatePersistedContainer(String propertyName, String
+       // containerString, boolean addToContainerValues) {
+       // int containerPrefixLength = CP_CONTAINER_PREFERENCES_PREFIX.length();
+       // int index = propertyName.indexOf('|', containerPrefixLength);
+       // if (containerString != null) containerString = containerString.trim();
+       // if (index > 0) {
+       // final String projectName = propertyName.substring(containerPrefixLength,
+       // index).trim();
+       // JavaProject project =
+       // (JavaProject)getJavaModelManager().getJavaModel().getJavaProject(projectName);
+       // final IPath containerPath = new
+       // Path(propertyName.substring(index+1).trim());
+       //
+       // if (containerString == null || containerString.equals(CP_ENTRY_IGNORE)) {
+       // containerPut(project, containerPath, null);
+       // } else {
+       // final IClasspathEntry[] containerEntries =
+       // project.decodeClasspath(containerString, false, false);
+       // if (containerEntries != null && containerEntries !=
+       // JavaProject.INVALID_CLASSPATH) {
+       // IClasspathContainer container = new IClasspathContainer() {
+       // public IClasspathEntry[] getClasspathEntries() {
+       // return containerEntries;
+       // }
+       // public String getDescription() {
+       // return "Persisted container ["+containerPath+" for project ["+
+       // projectName+"]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+       // }
+       // public int getKind() {
+       // return 0;
+       // }
+       // public IPath getPath() {
+       // return containerPath;
+       // }
+       // public String toString() {
+       // return getDescription();
+       // }
+       //
+       // };
+       // if (addToContainerValues) {
+       // containerPut(project, containerPath, container);
+       // }
+       // Map projectContainers = (Map)PreviousSessionContainers.get(project);
+       // if (projectContainers == null){
+       // projectContainers = new HashMap(1);
+       // PreviousSessionContainers.put(project, projectContainers);
+       // }
+       // projectContainers.put(containerPath, container);
+       // }
+       // }
+       // }
+       // }
+
+       /**
+        * Registers the given delta with this manager.
+        */
+       protected void registerJavaModelDelta(IJavaElementDelta delta) {
+               this.javaModelDeltas.add(delta);
+       }
+
+       /**
+        * Remembers the given scope in a weak set (so no need to remove it: it will
+        * be removed by the garbage collector)
+        */
+       // public void rememberScope(AbstractSearchScope scope) {
+       // // NB: The value has to be null so as to not create a strong reference on
+       // the scope
+       // this.scopes.put(scope, null);
+       // }
+       /**
+        * removeElementChangedListener method comment.
+        */
+       public void removeElementChangedListener(IElementChangedListener listener) {
+
+               for (int i = 0; i < this.elementChangedListenerCount; i++) {
+
+                       if (this.elementChangedListeners[i].equals(listener)) {
+
+                               // need to clone defensively since we might be in the middle of
+                               // listener notifications (#fire)
+                               int length = this.elementChangedListeners.length;
+                               IElementChangedListener[] newListeners = new IElementChangedListener[length];
+                               System.arraycopy(this.elementChangedListeners, 0, newListeners,
+                                               0, i);
+                               int[] newMasks = new int[length];
+                               System.arraycopy(this.elementChangedListenerMasks, 0, newMasks,
+                                               0, i);
+
+                               // copy trailing listeners
+                               int trailingLength = this.elementChangedListenerCount - i - 1;
+                               if (trailingLength > 0) {
+                                       System.arraycopy(this.elementChangedListeners, i + 1,
+                                                       newListeners, i, trailingLength);
+                                       System.arraycopy(this.elementChangedListenerMasks, i + 1,
+                                                       newMasks, i, trailingLength);
+                               }
+
+                               // update manager listener state (#fire need to iterate over
+                               // original listeners through a local variable to hold onto
+                               // the original ones)
+                               this.elementChangedListeners = newListeners;
+                               this.elementChangedListenerMasks = newMasks;
+                               this.elementChangedListenerCount--;
+                               return;
+                       }
+               }
+       }
+
+       /**
+        * Remembers the given scope in a weak set (so no need to remove it: it will
+        * be removed by the garbage collector)
+        */
+       // public void rememberScope(AbstractSearchScope scope) {
+       // // NB: The value has to be null so as to not create a strong reference on
+       // the scope
+       // this.searchScopes.put(scope, null);
+       // }
+       /*
+        * Removes all cached info for the given element (including all children)
+        * from the cache. Returns the info for the given element, or null if it was
+        * closed.
+        */
+       public synchronized Object removeInfoAndChildren(JavaElement element)
+                       throws JavaModelException {
+               Object info = this.cache.peekAtInfo(element);
+               if (info != null) {
+                       boolean wasVerbose = false;
+                       try {
+                               if (VERBOSE) {
+                                       System.out
+                                                       .println("CLOSING Element (" + Thread.currentThread() + "): " + element.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
+                                       wasVerbose = true;
+                                       VERBOSE = false;
+                               }
+                               element.closing(info);
+                               if (element instanceof IParent
+                                               && info instanceof JavaElementInfo) {
+                                       IJavaElement[] children = ((JavaElementInfo) info)
+                                                       .getChildren();
+                                       for (int i = 0, size = children.length; i < size; ++i) {
+                                               JavaElement child = (JavaElement) children[i];
+                                               child.close();
+                                       }
+                               }
+                               this.cache.removeInfo(element);
+                               if (wasVerbose) {
+                                       System.out
+                                                       .println("-> Package cache size = " + this.cache.pkgSize()); //$NON-NLS-1$
+                                       System.out
+                                                       .println("-> Openable cache filling ratio = " + NumberFormat.getInstance().format(this.cache.openableFillingRatio()) + "%"); //$NON-NLS-1$//$NON-NLS-2$
+                               }
+                       } finally {
+                               JavaModelManager.VERBOSE = wasVerbose;
+                       }
+                       return info;
+               }
+               return null;
+       }
+
+       public void removePerProjectInfo(JavaProject javaProject) {
+               synchronized (perProjectInfo) { // use the perProjectInfo collection as
+                                                                               // its own lock
+                       IProject project = javaProject.getProject();
+                       PerProjectInfo info = (PerProjectInfo) perProjectInfo.get(project);
+                       if (info != null) {
+                               perProjectInfo.remove(project);
+                       }
+               }
+       }
+
+       /*
+        * Resets the temporary cache for newly created elements to null.
+        */
+       public void resetTemporaryCache() {
+               this.temporaryCache.set(null);
+       }
+
+       /**
+        * @see ISaveParticipant
+        */
+       public void rollback(ISaveContext context) {
+       }
+
+       private void saveState(PerProjectInfo info, ISaveContext context)
+                       throws CoreException {
+
+               // passed this point, save actions are non trivial
+               if (context.getKind() == ISaveContext.SNAPSHOT)
+                       return;
+
+               // save built state
+               if (info.triedRead)
+                       saveBuiltState(info);
+       }
+
+       /**
+        * Saves the built state for the project.
+        */
+       private void saveBuiltState(PerProjectInfo info) throws CoreException {
+               if (PHPBuilder.DEBUG)
+                       System.out.println(Util.bind(
+                                       "build.saveStateProgress", info.project.getName())); //$NON-NLS-1$
+               File file = getSerializationFile(info.project);
+               if (file == null)
+                       return;
+               long t = System.currentTimeMillis();
+               try {
+                       DataOutputStream out = new DataOutputStream(
+                                       new BufferedOutputStream(new FileOutputStream(file)));
+                       try {
+                               out.writeUTF(JavaCore.PLUGIN_ID);
+                               out.writeUTF("STATE"); //$NON-NLS-1$
+                               if (info.savedState == null) {
+                                       out.writeBoolean(false);
+                               } else {
+                                       out.writeBoolean(true);
+                                       PHPBuilder.writeState(info.savedState, out);
+                               }
+                       } finally {
+                               out.close();
+                       }
+               } catch (RuntimeException e) {
+                       try {
+                               file.delete();
+                       } catch (SecurityException se) {
+                       }
+                       throw new CoreException(
+                                       new Status(
+                                                       IStatus.ERROR,
+                                                       JavaCore.PLUGIN_ID,
+                                                       Platform.PLUGIN_ERROR,
+                                                       Util
+                                                                       .bind(
+                                                                                       "build.cannotSaveState", info.project.getName()), e)); //$NON-NLS-1$
+               } catch (IOException e) {
+                       try {
+                               file.delete();
+                       } catch (SecurityException se) {
+                       }
+                       throw new CoreException(
+                                       new Status(
+                                                       IStatus.ERROR,
+                                                       JavaCore.PLUGIN_ID,
+                                                       Platform.PLUGIN_ERROR,
+                                                       Util
+                                                                       .bind(
+                                                                                       "build.cannotSaveState", info.project.getName()), e)); //$NON-NLS-1$
+               }
+               if (PHPBuilder.DEBUG) {
+                       t = System.currentTimeMillis() - t;
+                       System.out.println(Util.bind(
+                                       "build.saveStateComplete", String.valueOf(t))); //$NON-NLS-1$
+               }
+       }
+
+       private synchronized Map containerClone(IJavaProject project) {
+               Map originalProjectContainers = (Map) this.containers.get(project);
+               if (originalProjectContainers == null)
+                       return null;
+               Map projectContainers = new HashMap(originalProjectContainers.size());
+               projectContainers.putAll(originalProjectContainers);
+               return projectContainers;
+       }
+
+       /**
+        * @see ISaveParticipant
+        */
+       public void saving(ISaveContext context) throws CoreException {
+
+               // save container values on snapshot/full save
+               Preferences preferences = JavaCore.getPlugin().getPluginPreferences();
+               IJavaProject[] projects = getJavaModel().getJavaProjects();
+               for (int i = 0, length = projects.length; i < length; i++) {
+                       IJavaProject project = projects[i];
+                       // clone while iterating (see
+                       // https://bugs.eclipse.org/bugs/show_bug.cgi?id=59638)
+                       Map projectContainers = containerClone(project);
+                       if (projectContainers == null)
+                               continue;
+                       for (Iterator keys = projectContainers.keySet().iterator(); keys
+                                       .hasNext();) {
+                               IPath containerPath = (IPath) keys.next();
+                               // IClasspathContainer container = (IClasspathContainer)
+                               // projectContainers.get(containerPath);
+                               String containerKey = CP_CONTAINER_PREFERENCES_PREFIX
+                                               + project.getElementName() + "|" + containerPath;//$NON-NLS-1$
+                               String containerString = CP_ENTRY_IGNORE;
+                               // try {
+                               // if (container != null) {
+                               // containerString =
+                               // ((JavaProject)project).encodeClasspath(container.getClasspathEntries(),
+                               // null, false);
+                               // }
+                               // } catch(JavaModelException e){
+                               // // could not encode entry: leave it as CP_ENTRY_IGNORE
+                               // }
+                               preferences.setDefault(containerKey, CP_ENTRY_IGNORE); // use
+                                                                                                                                               // this
+                                                                                                                                               // default
+                                                                                                                                               // to
+                                                                                                                                               // get
+                                                                                                                                               // rid
+                                                                                                                                               // of
+                                                                                                                                               // removed
+                                                                                                                                               // ones
+                               preferences.setValue(containerKey, containerString);
+                       }
+               }
+               JavaCore.getPlugin().savePluginPreferences();
+
+               // if (context.getKind() == ISaveContext.FULL_SAVE) {
+               // // will need delta since this save (see
+               // https://bugs.eclipse.org/bugs/show_bug.cgi?id=38658)
+               // context.needDelta();
+               //
+               // // clean up indexes on workspace full save
+               // // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=52347)
+               // IndexManager manager = this.indexManager;
+               // if (manager != null) {
+               // manager.cleanUpIndexes();
+               // }
+               // }
+
+               IProject savedProject = context.getProject();
+               if (savedProject != null) {
+                       if (!JavaProject.hasJavaNature(savedProject))
+                               return; // ignore
+                       PerProjectInfo info = getPerProjectInfo(savedProject, true /*
+                                                                                                                                                * create
+                                                                                                                                                * info
+                                                                                                                                                */);
+                       saveState(info, context);
+                       return;
+               }
+
+               ArrayList vStats = null; // lazy initialized
+               for (Iterator iter = perProjectInfo.values().iterator(); iter.hasNext();) {
+                       try {
+                               PerProjectInfo info = (PerProjectInfo) iter.next();
+                               saveState(info, context);
+                       } catch (CoreException e) {
+                               if (vStats == null)
+                                       vStats = new ArrayList();
+                               vStats.add(e.getStatus());
+                       }
+               }
+               if (vStats != null) {
+                       IStatus[] stats = new IStatus[vStats.size()];
+                       vStats.toArray(stats);
+                       throw new CoreException(new MultiStatus(JavaCore.PLUGIN_ID,
+                                       IStatus.ERROR, stats,
+                                       Util.bind("build.cannotSaveStates"), null)); //$NON-NLS-1$
+               }
+       }
+
+       /**
+        * @see ISaveParticipant
+        */
+       // public void saving(ISaveContext context) throws CoreException {
+       //
+       // IProject savedProject = context.getProject();
+       // if (savedProject != null) {
+       // if (!JavaProject.hasJavaNature(savedProject)) return; // ignore
+       // PerProjectInfo info = getPerProjectInfo(savedProject, true /* create info
+       // */);
+       // saveState(info, context);
+       // return;
+       // }
+       //
+       // ArrayList vStats= null; // lazy initialized
+       // for (Iterator iter = perProjectInfo.values().iterator(); iter.hasNext();)
+       // {
+       // try {
+       // PerProjectInfo info = (PerProjectInfo) iter.next();
+       // saveState(info, context);
+       // } catch (CoreException e) {
+       // if (vStats == null)
+       // vStats= new ArrayList();
+       // vStats.add(e.getStatus());
+       // }
+       // }
+       // if (vStats != null) {
+       // IStatus[] stats= new IStatus[vStats.size()];
+       // vStats.toArray(stats);
+       // throw new CoreException(new MultiStatus(JavaCore.PLUGIN_ID,
+       // IStatus.ERROR, stats, Util.bind("build.cannotSaveStates"), null));
+       // //$NON-NLS-1$
+       // }
+       // }
+       /**
+        * Record the order in which to build the java projects (batch build). This
+        * order is based on the projects classpath settings.
+        */
+       protected void setBuildOrder(String[] javaBuildOrder)
+                       throws JavaModelException {
+
+               // optional behaviour
+               // possible value of index 0 is Compute
+               if (!JavaCore.COMPUTE.equals(JavaCore
+                               .getOption(JavaCore.CORE_JAVA_BUILD_ORDER)))
+                       return; // cannot be customized at project level
+
+               if (javaBuildOrder == null || javaBuildOrder.length <= 1)
+                       return;
+
+               IWorkspace workspace = ResourcesPlugin.getWorkspace();
+               IWorkspaceDescription description = workspace.getDescription();
+               String[] wksBuildOrder = description.getBuildOrder();
+
+               String[] newOrder;
+               if (wksBuildOrder == null) {
+                       newOrder = javaBuildOrder;
+               } else {
+                       // remove projects which are already mentionned in java builder
+                       // order
+                       int javaCount = javaBuildOrder.length;
+                       HashMap newSet = new HashMap(javaCount); // create a set for fast
+                                                                                                               // check
+                       for (int i = 0; i < javaCount; i++) {
+                               newSet.put(javaBuildOrder[i], javaBuildOrder[i]);
+                       }
+                       int removed = 0;
+                       int oldCount = wksBuildOrder.length;
+                       for (int i = 0; i < oldCount; i++) {
+                               if (newSet.containsKey(wksBuildOrder[i])) {
+                                       wksBuildOrder[i] = null;
+                                       removed++;
+                               }
+                       }
+                       // add Java ones first
+                       newOrder = new String[oldCount - removed + javaCount];
+                       System.arraycopy(javaBuildOrder, 0, newOrder, 0, javaCount); // java
+                                                                                                                                                       // projects
+                                                                                                                                                       // are
+                                                                                                                                                       // built
+                                                                                                                                                       // first
+
+                       // copy previous items in their respective order
+                       int index = javaCount;
+                       for (int i = 0; i < oldCount; i++) {
+                               if (wksBuildOrder[i] != null) {
+                                       newOrder[index++] = wksBuildOrder[i];
+                               }
+                       }
+               }
+               // commit the new build order out
+               description.setBuildOrder(newOrder);
+               try {
+                       workspace.setDescription(description);
+               } catch (CoreException e) {
+                       throw new JavaModelException(e);
+               }
+       }
+
+       /**
+        * Sets the last built state for the given project, or null to reset it.
+        */
+       public void setLastBuiltState(IProject project, Object state) {
+               if (!JavaProject.hasJavaNature(project))
+                       return; // should never be requested on non-Java projects
+               PerProjectInfo info = getPerProjectInfo(project, true /*
+                                                                                                                                * create if
+                                                                                                                                * missing
+                                                                                                                                */);
+               info.triedRead = true; // no point trying to re-read once using setter
+               info.savedState = state;
+               if (state == null) { // delete state file to ensure a full build
+                                                               // happens if the workspace crashes
+                       try {
+                               File file = getSerializationFile(project);
+                               if (file != null && file.exists())
+                                       file.delete();
+                       } catch (SecurityException se) {
+                       }
+               }
+       }
+
+       public void shutdown() {
+               // TODO temp-del
+               // if (this.deltaProcessor.indexManager != null){ // no more indexing
+               // this.deltaProcessor.indexManager.shutdown();
+               // }
+               try {
+                       IJavaModel model = this.getJavaModel();
+                       if (model != null) {
+
+                               model.close();
+                       }
+               } catch (JavaModelException e) {
+               }
+       }
+
+       /**
+        * Turns the firing mode to on. That is, deltas that are/have been
+        * registered will be fired.
+        */
+       public void startDeltas() {
+               this.isFiring = true;
+       }
+
+       /**
+        * Turns the firing mode to off. That is, deltas that are/have been
+        * registered will not be fired until deltas are started again.
+        */
+       public void stopDeltas() {
+               this.isFiring = false;
+       }
+
+       /**
+        * Update Java Model given some delta
+        */
+       public void updateJavaModel(IJavaElementDelta customDelta) {
+
+               if (customDelta == null) {
+                       for (int i = 0, length = this.javaModelDeltas.size(); i < length; i++) {
+                               IJavaElementDelta delta = (IJavaElementDelta) this.javaModelDeltas
+                                               .get(i);
+                               this.modelUpdater.processJavaDelta(delta);
+                       }
+               } else {
+                       this.modelUpdater.processJavaDelta(customDelta);
+               }
+       }
+
+       public static IPath variableGet(String variableName) {
+               return (IPath) Variables.get(variableName);
+       }
+
+       public static String[] variableNames() {
+               int length = Variables.size();
+               String[] result = new String[length];
+               Iterator vars = Variables.keySet().iterator();
+               int index = 0;
+               while (vars.hasNext()) {
+                       result[index++] = (String) vars.next();
+               }
+               return result;
+       }
+
+       public static void variablePut(String variableName, IPath variablePath) {
+
+               // update cache - do not only rely on listener refresh
+               if (variablePath == null) {
+                       Variables.remove(variableName);
+                       PreviousSessionVariables.remove(variableName);
+               } else {
+                       Variables.put(variableName, variablePath);
+               }
+
+               // do not write out intermediate initialization value
+               if (variablePath == JavaModelManager.VariableInitializationInProgress) {
+                       return;
+               }
+               Preferences preferences = JavaCore.getPlugin().getPluginPreferences();
+               String variableKey = CP_VARIABLE_PREFERENCES_PREFIX + variableName;
+               String variableString = variablePath == null ? CP_ENTRY_IGNORE
+                               : variablePath.toString();
+               preferences.setDefault(variableKey, CP_ENTRY_IGNORE); // use this
+                                                                                                                               // default to
+                                                                                                                               // get rid of
+                                                                                                                               // removed ones
+               preferences.setValue(variableKey, variableString);
+               JavaCore.getPlugin().savePluginPreferences();
+       }
+
+       /*
+        * Returns all the working copies which have the given owner. Adds the
+        * working copies of the primary owner if specified. Returns null if it has
+        * none.
+        */
+       public ICompilationUnit[] getWorkingCopies(WorkingCopyOwner owner,
+                       boolean addPrimary) {
+               synchronized (perWorkingCopyInfos) {
+                       ICompilationUnit[] primaryWCs = addPrimary
+                                       && owner != DefaultWorkingCopyOwner.PRIMARY ? getWorkingCopies(
+                                       DefaultWorkingCopyOwner.PRIMARY, false)
+                                       : null;
+                       Map workingCopyToInfos = (Map) perWorkingCopyInfos.get(owner);
+                       if (workingCopyToInfos == null)
+                               return primaryWCs;
+                       int primaryLength = primaryWCs == null ? 0 : primaryWCs.length;
+                       int size = workingCopyToInfos.size(); // note size is > 0
+                                                                                                       // otherwise
+                                                                                                       // pathToPerWorkingCopyInfos
+                                                                                                       // would be null
+                       ICompilationUnit[] result = new ICompilationUnit[primaryLength
+                                       + size];
+                       if (primaryWCs != null) {
+                               System.arraycopy(primaryWCs, 0, result, 0, primaryLength);
+                       }
+                       Iterator iterator = workingCopyToInfos.values().iterator();
+                       int index = primaryLength;
+                       while (iterator.hasNext()) {
+                               result[index++] = ((JavaModelManager.PerWorkingCopyInfo) iterator
+                                               .next()).getWorkingCopy();
+                       }
+                       return result;
+               }
+       }
+
+       /*
+        * A HashSet that contains the IJavaProject whose classpath is being
+        * resolved.
+        */
+       private ThreadLocal classpathsBeingResolved = new ThreadLocal();
+
+       private HashSet getClasspathBeingResolved() {
+               HashSet result = (HashSet) this.classpathsBeingResolved.get();
+               if (result == null) {
+                       result = new HashSet();
+                       this.classpathsBeingResolved.set(result);
+               }
+               return result;
+       }
+
+       public boolean isClasspathBeingResolved(IJavaProject project) {
+               return getClasspathBeingResolved().contains(project);
+       }
+
+       public void setClasspathBeingResolved(IJavaProject project,
+                       boolean classpathIsResolved) {
+               if (classpathIsResolved) {
+                       getClasspathBeingResolved().add(project);
+               } else {
+                       getClasspathBeingResolved().remove(project);
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/corext/phpdoc/PHPDocUtil.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/corext/phpdoc/PHPDocUtil.java
new file mode 100644 (file)
index 0000000..0d477e1
--- /dev/null
@@ -0,0 +1,93 @@
+package net.sourceforge.phpdt.internal.corext.phpdoc;
+
+import java.io.FileReader;
+import java.io.IOException;
+
+import net.sourceforge.phpeclipse.builder.PHPIdentifierLocation;
+
+/**
+ * Utility class for static PHPdoc helper mehods
+ */
+public class PHPDocUtil {
+
+       /**
+        * Generate a PHPDoc hover text if possible
+        * 
+        * @param hoverInfoBuffer
+        * @param filename
+        * @param location
+        */
+       public static void appendPHPDoc(StringBuffer hoverInfoBuffer,
+                       String filename, PHPIdentifierLocation location) {
+               FileReader phpFileReader;
+               hoverInfoBuffer.append(location.toString());
+               hoverInfoBuffer.append(" - <b>");
+               try {
+                       hoverInfoBuffer.append(getUsage(filename, location));
+                       hoverInfoBuffer.append("</b><br>");
+
+                       // read the phpdoc for the function
+                       if (location.getPHPDocOffset() >= 0) {
+                               phpFileReader = new FileReader(filename);
+                               char[] phpDocDeclarationCharArray = new char[location
+                                               .getPHPDocLength()];
+                               phpFileReader.skip(location.getPHPDocOffset());
+                               phpFileReader.read(phpDocDeclarationCharArray, 0, location
+                                               .getPHPDocLength());
+                               PHPDocCharArrayCommentReader phpdocConverter = new PHPDocCharArrayCommentReader(
+                                               phpDocDeclarationCharArray);
+                               hoverInfoBuffer.append(phpdocConverter.getString());
+                               // hoverInfoBuffer.append("<br><br>");
+                               phpFileReader.close();
+                       }
+
+               } catch (IOException e) {
+                       return;
+               }
+       }
+
+       public static String getUsage(String filename,
+                       PHPIdentifierLocation location) {
+               FileReader phpFileReader;
+               String usage = location.getUsage();
+               if (usage != null) {
+                       return usage;
+               }
+               usage = "";
+               try {
+
+                       phpFileReader = new FileReader(filename);
+                       // read the function declaration
+                       if (location.getOffset() >= 0
+                                       && (location.isMethod() || location.isConstructor()
+                                                       || location.isFunction() || location.isDefine())) {
+                               char[] functionDeclarationCharArray = new char[256];
+                               int offset = location.getOffset();
+                               phpFileReader.skip(offset);
+                               int length = phpFileReader.read(functionDeclarationCharArray,
+                                               0, 256);
+                               if (length == -1) {
+                                       length = 256;
+                               }
+                               for (int i = 0; i < length; i++) {
+                                       if (functionDeclarationCharArray[i] == ')') {
+                                               length = i + 1;
+                                               break;
+                                       }
+                                       if (functionDeclarationCharArray[i] == '{'
+                                                       || functionDeclarationCharArray[i] == '}') {
+                                               length = i;
+                                               break;
+                                       }
+                               }
+                               usage = new String(functionDeclarationCharArray, 0, length);
+                       }
+                       phpFileReader.close();
+               } catch (IOException e) {
+                       // do nothing
+               }
+               // cache the usage string:
+               location.setUsage(usage);
+               return usage;
+       }
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/corext/util/Resources.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/corext/util/Resources.java
new file mode 100644 (file)
index 0000000..d03b7b3
--- /dev/null
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpdt.internal.corext.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.corext.CorextMessages;
+import net.sourceforge.phpdt.internal.ui.IJavaStatusConstants;
+import net.sourceforge.phpdt.internal.ui.PHPUIStatus;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceStatus;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+
+public class Resources {
+
+       private Resources() {
+       }
+
+       /**
+        * Checks if the given resource is in sync with the underlying file system.
+        * 
+        * @param resource
+        *            the resource to be checked
+        * @return IStatus status describing the check's result. If <code>status.
+        * isOK()</code>
+        *         returns <code>true</code> then the resource is in sync
+        */
+       public static IStatus checkInSync(IResource resource) {
+               return checkInSync(new IResource[] { resource });
+       }
+
+       /**
+        * Checks if the given resources are in sync with the underlying file
+        * system.
+        * 
+        * @param resources
+        *            the resources to be checked
+        * @return IStatus status describing the check's result. If <code>status.
+        *  isOK() </code>
+        *         returns <code>true</code> then the resources are in sync
+        */
+       public static IStatus checkInSync(IResource[] resources) {
+               IStatus result = null;
+               for (int i = 0; i < resources.length; i++) {
+                       IResource resource = resources[i];
+                       if (!resource.isSynchronized(IResource.DEPTH_INFINITE)) {
+                               result = addOutOfSync(result, resource);
+                       }
+               }
+               if (result != null)
+                       return result;
+               return new Status(IStatus.OK, PHPeclipsePlugin.getPluginId(),
+                               IStatus.OK, "", null); //$NON-NLS-1$
+       }
+
+       /**
+        * Makes the given resource committable. Committable means that it is
+        * writeable and that its content hasn't changed by calling
+        * <code>validateEdit</code> for the given resource on <tt>IWorkspace</tt>.
+        * 
+        * @param resource
+        *            the resource to be checked
+        * @param context
+        *            the context passed to <code>validateEdit</code>
+        * @return status describing the method's result. If
+        *         <code>status.isOK()</code> returns <code>true</code> then the
+        *         resources are committable.
+        * 
+        * @see org.eclipse.core.resources.IWorkspace#validateEdit(org.eclipse.core.resources.IFile[],
+        *      java.lang.Object)
+        */
+       public static IStatus makeCommittable(IResource resource, Object context) {
+               return makeCommittable(new IResource[] { resource }, context);
+       }
+
+       /**
+        * Makes the given resources committable. Committable means that all
+        * resources are writeable and that the content of the resources hasn't
+        * changed by calling <code>validateEdit</code> for a given file on
+        * <tt>IWorkspace</tt>.
+        * 
+        * @param resources
+        *            the resources to be checked
+        * @param context
+        *            the context passed to <code>validateEdit</code>
+        * @return IStatus status describing the method's result. If <code>status.
+        * isOK()</code>
+        *         returns <code>true</code> then the add resources are
+        *         committable
+        * 
+        * @see org.eclipse.core.resources.IWorkspace#validateEdit(org.eclipse.core.resources.IFile[],
+        *      java.lang.Object)
+        */
+       public static IStatus makeCommittable(IResource[] resources, Object context) {
+               List readOnlyFiles = new ArrayList();
+               for (int i = 0; i < resources.length; i++) {
+                       IResource resource = resources[i];
+                       if (resource.getType() == IResource.FILE
+                                       && resource.getResourceAttributes().isReadOnly())
+                               readOnlyFiles.add(resource);
+               }
+               if (readOnlyFiles.size() == 0)
+                       return new Status(IStatus.OK, PHPeclipsePlugin.getPluginId(),
+                                       IStatus.OK, "", null); //$NON-NLS-1$
+
+               Map oldTimeStamps = createModificationStampMap(readOnlyFiles);
+               IStatus status = ResourcesPlugin.getWorkspace().validateEdit(
+                               (IFile[]) readOnlyFiles
+                                               .toArray(new IFile[readOnlyFiles.size()]), context);
+               if (!status.isOK())
+                       return status;
+
+               IStatus modified = null;
+               Map newTimeStamps = createModificationStampMap(readOnlyFiles);
+               for (Iterator iter = oldTimeStamps.keySet().iterator(); iter.hasNext();) {
+                       IFile file = (IFile) iter.next();
+                       if (!oldTimeStamps.get(file).equals(newTimeStamps.get(file)))
+                               modified = addModified(modified, file);
+               }
+               if (modified != null)
+                       return modified;
+               return new Status(IStatus.OK, PHPeclipsePlugin.getPluginId(),
+                               IStatus.OK, "", null); //$NON-NLS-1$
+       }
+
+       private static Map createModificationStampMap(List files) {
+               Map map = new HashMap();
+               for (Iterator iter = files.iterator(); iter.hasNext();) {
+                       IFile file = (IFile) iter.next();
+                       map.put(file, new Long(file.getModificationStamp()));
+               }
+               return map;
+       }
+
+       private static IStatus addModified(IStatus status, IFile file) {
+               IStatus entry = PHPUIStatus
+                               .createError(
+                                               IJavaStatusConstants.VALIDATE_EDIT_CHANGED_CONTENT,
+                                               CorextMessages
+                                                               .getFormattedString(
+                                                                               "Resources.fileModified", file.getFullPath().toString()), //$NON-NLS-1$
+                                               null);
+               if (status == null) {
+                       return entry;
+               } else if (status.isMultiStatus()) {
+                       ((MultiStatus) status).add(entry);
+                       return status;
+               } else {
+                       MultiStatus result = new MultiStatus(
+                                       PHPeclipsePlugin.getPluginId(),
+                                       IJavaStatusConstants.VALIDATE_EDIT_CHANGED_CONTENT,
+                                       CorextMessages.getString("Resources.modifiedResources"), null); //$NON-NLS-1$
+                       result.add(status);
+                       result.add(entry);
+                       return result;
+               }
+       }
+
+       private static IStatus addOutOfSync(IStatus status, IResource resource) {
+               IStatus entry = new Status(
+                               IStatus.ERROR,
+                               ResourcesPlugin.PI_RESOURCES,
+                               IResourceStatus.OUT_OF_SYNC_LOCAL,
+                               CorextMessages
+                                               .getFormattedString(
+                                                               "Resources.outOfSync", resource.getFullPath().toString()), //$NON-NLS-1$
+                               null);
+               if (status == null) {
+                       return entry;
+               } else if (status.isMultiStatus()) {
+                       ((MultiStatus) status).add(entry);
+                       return status;
+               } else {
+                       MultiStatus result = new MultiStatus(ResourcesPlugin.PI_RESOURCES,
+                                       IResourceStatus.OUT_OF_SYNC_LOCAL, CorextMessages
+                                                       .getString("Resources.outOfSyncResources"), null); //$NON-NLS-1$
+                       result.add(status);
+                       result.add(entry);
+                       return result;
+               }
+       }
+
+       public static String[] getLocationOSStrings(IResource[] resources) {
+               List result = new ArrayList(resources.length);
+               for (int i = 0; i < resources.length; i++) {
+                       IPath location = resources[i].getLocation();
+                       if (location != null)
+                               result.add(location.toOSString());
+               }
+               return (String[]) result.toArray(new String[result.size()]);
+       }
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGProxy.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/debug/core/PHPDBGProxy.java
new file mode 100644 (file)
index 0000000..5c5b26b
--- /dev/null
@@ -0,0 +1,703 @@
+/***********************************************************************************************************************************
+ * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors: IBM Corporation - Initial implementation Vicente Fernando - www.alfersoft.com.ar Christian Perkonig - remote debug
+ **********************************************************************************************************************************/
+package net.sourceforge.phpdt.internal.debug.core;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.util.Map;
+import java.util.Vector;
+
+import net.sourceforge.phpdt.internal.debug.core.breakpoints.PHPLineBreakpoint;
+import net.sourceforge.phpdt.internal.debug.core.model.PHPDebugTarget;
+import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame;
+import net.sourceforge.phpdt.internal.debug.core.model.PHPThread;
+import net.sourceforge.phpdt.internal.debug.core.model.PHPVariable;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.model.IBreakpoint;
+
+public class PHPDBGProxy {
+
+       private ServerSocket            server          = null;
+       private BufferedReader          reader          = null;
+       private PHPDBGInterface         DBGInt          = null;         // The DBG interface which is linked with the proxy
+       private PHPDebugTarget          debugTarget = null;
+       private PHPDBGProxy             thisProxy       = null;
+       private PHPLoop                         phpLoop;
+       private PHPThread                       PHPMainThread;
+       private Socket                          socket;
+       private int                             port;
+       private boolean                         remote;
+       private boolean                         pathtranslation;
+       private Map                             pathmap;
+       private IPath                           remoteSourcePath;
+
+       /**
+        */
+       public PHPDBGProxy () {
+         thisProxy = this;
+       }
+
+       /**
+        * @param remote
+        * @param remoteSourcePath
+        * @param pathTranslate
+        * @param paths
+        */
+       public PHPDBGProxy (boolean remote, String remoteSourcePath, boolean pathTranslate, Map paths) {
+               thisProxy             = this;
+               this.remote               = remote;
+               this.remoteSourcePath = new Path (remoteSourcePath);
+               this.pathmap          = paths;
+               this.pathtranslation  = pathTranslate;
+       }
+
+       /**
+        *
+        */
+       public void start () {
+               createServerSocket ();                                      // Create a server socket for communicatio with DBG
+
+               this.startPHPLoop ();                                                                           //
+       }
+
+       /**
+        *
+        */
+       public void stop () {
+               phpLoop.setShouldStop ();                                   // Notify the thread's 'run loop' to stop
+
+               if (DBGInt != null) {                                       // If we have a DBG interface linked with this proxy
+               DBGInt.setShouldStop ();                                //  Notify the DBG interface to stop the waiting for response
+               }
+
+               if (!remote) {                                              // If it's not a remote proxy session
+               try {
+                       getDebugTarget ().getProcess ().terminate ();       //
+               } catch (DebugException e) {
+                       e.printStackTrace ();
+               }
+               }
+
+               phpLoop.notifyWait ();
+       }
+       
+       public void setTerminated () {
+               try {
+                       PHPMainThread.terminate ();
+               }
+               catch (DebugException e) {
+               }
+       }
+
+       /**
+        * TODO Is this method called from anywhere?
+        *
+        * Returns a already created server socket, or
+        * creates a server socket if none exists, and
+        * returns the newly created one.
+        *
+        * @return A server socket
+        */
+       protected ServerSocket getServerSocket () throws IOException {
+               if (server == null) {                                                                           // Do we have already a server socket
+               createServerSocket ();                                                                  //  No, then create one
+               }
+
+               return server;                                                                                          // Return the server socket
+       }
+
+       /**
+        * Find a free unused port between 10001 and 10101 if the current debug session
+        * is for remote debugging, and a unused port 7869 if it is used as non remote debugging.
+        * 
+        * For remote debugging the used port is submitted with the URL.
+        * E.g. http://localhost/index.php?DBGSESSID=1@localhost:10001
+        * For non remote debugging (if PHPeclipse used e.g. php cli directly) no port
+        * can be submitted by parameter, and only the default port (7869) can be used.
+        * 
+        * @note: The free dbg version doesn't allow to set the appropriate port within php.ini! 
+        * 
+        * 
+        */
+       protected void createServerSocket () {
+               if (this.remote) {
+                       port = SocketUtil.findUnusedLocalPort ("localhost", 10001, 10101);      // Get the first free port in the range from 10001 to 10101
+               }
+               else {
+                       port = SocketUtil.findUnusedLocalPort ("localhost", 7869, 7869);        // Get the first free port in the range from 7869 to 7869
+               }
+               
+               if (port == -1) {                                                   // Did we get a free port?
+               PHPDebugCorePlugin.log (5, "Cannot find free port!!!!");        //  No, output a error message
+
+               return;                                                         //  And return
+               }
+               try {
+               if (server == null) {                                           // If there is no server socket yet
+                       server = new ServerSocket (port);                           //  create a server socket for the free port
+                       //System.out.println("ServerSocket on port: " + port);
+               }
+               } catch (IOException e) {
+               PHPDebugCorePlugin.log (e);
+               stop ();
+               }
+       }
+
+       /**
+        *
+        */
+       public Socket getSocket () throws IOException {
+               return socket;                                                          // Return the socket
+       }
+
+       /**
+        * Set the DBG interface which is linked to this proxy
+        *
+        * @paran DBGInt The DGB interface which is linked with this proxy
+        */
+       protected void setDBGInterface (PHPDBGInterface DBGInt) {
+               this.DBGInt = DBGInt;
+       }
+
+       /**
+        * Get the DBG interface which is linked to this proxy
+        *
+        * @paran DBGInt The DGB interface which is linked with this proxy
+        */
+       public PHPDBGInterface getDBGInterface () {
+               return DBGInt;
+       }
+       
+       /**
+        * Give back a buffered input stream for the socket which is
+        * linked with this proxy
+        */
+       public BufferedReader getReader () throws IOException {
+               if (reader == null) {                                               // Do we already have a buffered input stream
+               reader = new BufferedReader (new InputStreamReader (this.getSocket ().getInputStream (),
+                                                                       "ISO8859_1"));
+               }
+
+         return reader;                                                      // Return the buffered input stream
+       }
+
+       /**
+        *
+        */
+       public BufferedReader getReader (Socket socket) throws IOException {
+               if (socket != null) {                                                                                           // Is a socket provided
+               return new BufferedReader (new InputStreamReader (socket.getInputStream (),
+                                                                                                 "ISO8859_1"));  // Then create a buffered input stream
+               }
+               else {
+               return null;                                                      // Without a socket we can't create a input stream
+               }
+       }
+
+       /**
+        *
+        * @return The output stream for this proxy's socket
+        */
+       public OutputStream getOutputStream () throws IOException {
+               return this.getSocket ().getOutputStream ();
+       }
+
+       /**
+        *
+        */
+       protected void setBreakPoints () throws IOException, CoreException {
+               IBreakpoint[] breakpoints = DebugPlugin.getDefault ().getBreakpointManager ().getBreakpoints ();
+
+               for (int i = 0; i < breakpoints.length; i++) {
+                       if (breakpoints[i].isEnabled ()) {
+                               addBreakpoint (breakpoints[i]);
+                       }
+               }
+       }
+
+       /**
+        *
+        */
+       private String MapPath (PHPLineBreakpoint phpLBP) {
+               IPath    filename;
+               IPath    remotePath;
+               IPath    newpath;
+               IPath    localPath;
+               String   local;
+
+               if (remote) {
+                       filename = phpLBP.getMarker().getResource().getProjectRelativePath();
+                       filename = remoteSourcePath.append (filename);
+               } else {
+                       filename = phpLBP.getMarker().getResource().getLocation();
+               }
+
+               String path = filename.toOSString();
+
+               if ((pathmap != null) && remote) {
+                       java.util.Iterator i = pathmap.keySet().iterator();
+
+                       while (i.hasNext()) {
+                               String k = (String) i.next();
+                               if (path.startsWith(k)) {
+                                       path = pathmap.get(k) + path.substring(k.length());
+                                       break;
+                               }
+                       }
+               }
+
+               if (remoteSourcePath.isEmpty ()) {
+                       if ((pathmap != null) && remote) {
+                               java.util.Iterator iterator = pathmap.keySet().iterator();
+
+                               while (iterator.hasNext ()) {
+                                       local      = (String) iterator.next ();                 // Get the local/client side path of the mapping
+                                       remotePath = new Path ((String) pathmap.get (local));   // Get the remote/server side path of the mapping
+                                       localPath  = new Path (local);                          // Get the remote/server side path of the mapping
+
+                                       if (localPath.isPrefixOf (filename)) {                  // Starts the remote/server side file path with the remote/server side mapping path
+                                                                                                                                                       // dann prefix abhängen und den remote path davorhägen
+                                               newpath = filename.removeFirstSegments (localPath.matchingFirstSegments (filename));
+                                               newpath = remotePath.append (newpath);
+                                               path    = newpath.toString ();
+
+                                               if (path.substring (0, 1).equals ("/")) {
+                                                       path = path.replace ('\\', '/');
+                                               }
+                                               else {
+                                                       path = path.replace ('/', '\\');
+                                               }
+
+                                               return path;
+                                       }
+                               }
+                       }
+               }
+               else {
+                       if (pathtranslation && remote) {
+                               if (remoteSourcePath.toString ().substring (0, 1).equals ("/")) {
+                                       path = path.replace ('\\', '/');
+                               }
+                               else {
+                                       path = path.replace ('/', '\\');
+                               }
+                       }
+               }
+
+               return path;
+       }
+
+       /**
+        *
+        */
+       public void addBreakpoint (IBreakpoint breakpoint) {
+               if (DBGInt == null) {
+               return;
+               }
+
+               int bpNo = 0;
+
+               try {
+               PHPLineBreakpoint phpLBP;
+
+               if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier()) {
+                       phpLBP = (PHPLineBreakpoint) breakpoint;
+
+                       //      bpNo= DBGInt.addBreakpoint(phpLBP.getMarker().getResource().getLocation().toOSString(), phpLBP.getLineNumber());
+                       if (phpLBP.isConditionEnabled ()) {
+                               bpNo = DBGInt.addBreakpoint (MapPath(phpLBP),
+                                                                                        phpLBP.getLineNumber(), 
+                                                                phpLBP.getHitCount(),
+                                                                phpLBP.getCondition ());
+                       }
+                       else {
+                               bpNo = DBGInt.addBreakpoint (MapPath(phpLBP),
+                                                                                        phpLBP.getLineNumber(), 
+                                                                phpLBP.getHitCount(),
+                                                                "");
+                       }
+                       
+                       phpLBP.setDBGBpNo(bpNo);
+               }
+               } catch (IOException e) {
+                   PHPDebugCorePlugin.log(e);
+                   stop();
+               } catch (CoreException e) {
+               PHPDebugCorePlugin.log(e);
+               stop();
+               }
+       }
+
+       /**
+        *
+        */
+       public void removeBreakpoint (IBreakpoint breakpoint) {
+               if (DBGInt == null) {
+               return;
+               }
+
+               try {
+               PHPLineBreakpoint phpLBP;
+
+               if (breakpoint.getModelIdentifier() == PHPDebugCorePlugin.getUniqueIdentifier ()) {
+                       phpLBP = (PHPLineBreakpoint) breakpoint;
+
+                       //      bpNo= DBGInt.addBreakpoint(filename.toOSString(), phpLBP.getLineNumber());
+
+                       DBGInt.removeBreakpoint(MapPath(phpLBP), phpLBP.getLineNumber(), phpLBP.getDBGBpNo());
+               }
+               } catch (IOException e) {
+               PHPDebugCorePlugin.log (e);
+               stop ();
+               } catch (CoreException e) {
+               PHPDebugCorePlugin.log (e);
+               stop ();
+               }
+       }
+
+       /**
+        *
+        */
+       public void phpLoopNotify () {
+               phpLoop.notifyWait ();
+       }
+
+       /**
+        *
+        */
+       public void startPHPLoop () {
+               phpLoop = new PHPLoop ();                                                                       // Create a DBG communication loop object
+
+               phpLoop.start ();                                                                                       // And start the communication loop
+       }
+
+       /**
+        *
+        */
+       public void resume () {
+               try {
+               DBGInt.continueExecution();
+               phpLoop.notifyWait();
+               } catch (IOException e) {
+               PHPeclipsePlugin.log("Debugging session ended.", e);
+               stop();
+               }
+       }
+
+       /**
+        *
+        */
+       public void pause () {
+               try {
+               if (null != DBGInt) {
+                               DBGInt.pauseExecution();
+                       }
+               else {
+                       // TODO Make sure the Suspend action is grayed out
+                       // when DBGInt is null
+               }
+               } catch (IOException e) {
+               PHPDebugCorePlugin.log (e);
+               stop ();
+               }
+       }
+
+       /**
+        *
+        */
+       protected PHPDebugTarget getDebugTarget() {
+               return debugTarget;
+       }
+
+       /**
+        * Is called by the DebuggerRunner
+        * 
+        * @param debugTarget
+        */
+       public void setDebugTarget (PHPDebugTarget debugTarget) {
+               this.debugTarget = debugTarget;
+               debugTarget.setPHPDBGProxy(this);
+       }
+
+       /**
+        * This method is called by a stackframe.
+        * It reads the variables from PHP via DBG
+        *
+        * @param frame The stackframe which wants the variables.
+        * @return      The list of variables for this stackframe.
+        */
+       public Vector readVariables (PHPStackFrame frame) {
+               try {
+               return DBGInt.getVariables (frame);                                             // Get the variables from DBG interface
+               } catch (IOException ioex) {
+               ioex.printStackTrace ();
+               throw new RuntimeException (ioex.getMessage ());
+               } catch (DebugException ex) {
+                   ex.printStackTrace ();
+                   throw new RuntimeException (ex.getMessage ());
+               }
+       }
+
+       /**
+        *
+        * @param frame
+        * @param evalString
+        * @return
+        */
+       public PHPVariable[] eval (PHPStackFrame frame, String evalString) {
+               try {
+               return DBGInt.evalBlock (frame, evalString);
+               //return DBGInt.getVariables(frame);
+               } catch (IOException ioex) {
+               ioex.printStackTrace();
+               throw new RuntimeException(ioex.getMessage());
+               } catch (DebugException ex) {
+               ex.printStackTrace();
+               throw new RuntimeException(ex.getMessage());
+               }
+       }
+
+       public void readStepOverEnd (PHPStackFrame stackFrame) {
+               try {
+               DBGInt.stepOver();
+               phpLoop.notifyWait();
+               } catch (Exception e) {
+               PHPDebugCorePlugin.log(e);
+               }
+       }
+
+       public void readStepReturnEnd (PHPStackFrame stackFrame) {
+               try {
+               DBGInt.stepOut();
+                   phpLoop.notifyWait();
+               } catch (Exception e) {
+               PHPDebugCorePlugin.log(e);
+               }
+       }
+
+       public void readStepIntoEnd (PHPStackFrame stackFrame) {
+               try {
+               DBGInt.stepInto();
+               phpLoop.notifyWait();
+               } catch (Exception e) {
+               PHPDebugCorePlugin.log(e);
+               }
+       }
+
+       /*
+        * public PHPStackFrame[] readFrames(PHPThread thread) { //try { //this.println("th " + thread.getId() + " ; f "); //return new
+        * FramesReader(getMultiReaderStrategy()).readFrames(thread); return null; //} catch (IOException e) { //
+        * PHPDebugCorePlugin.log(e); // return null; //}
+        *  }
+        */
+
+       public void closeSocket() throws IOException {
+               if (socket != null) {
+               socket.close();
+               }
+       }
+
+       public void closeServerSocket() throws IOException {
+               if (server != null) {
+               server.close();
+               }
+       }
+
+       public int getPort() {
+               return port;
+       }
+
+       /**
+        *
+        *
+        */
+       class PHPLoop extends Thread {
+               private boolean shouldStop;
+
+               public PHPLoop () {
+               shouldStop = false;
+               this.setName ("PHPDebuggerLoop");
+               }
+
+               /**
+                *
+                */
+               public synchronized void setShouldStop () {
+                       shouldStop = true;                                                                                      // The run loop should stop
+
+                       try {
+                               // If the loop thread is blocked on the server socket,
+                               // forcibly unblock it to avoid leaking the thread,
+                               // the socket and the port
+                               closeServerSocket ();
+                       } catch (IOException x) {
+                               // Log this as a warning?
+                               PHPDebugCorePlugin.log (x);
+                       }
+               }
+
+               /**
+                *
+                */
+               public synchronized void notifyWait () {
+               notify ();
+               }
+
+               /**
+                *
+                *
+                */
+               public void run () {
+               try {
+                       int                     i;
+                               int                     timeout;
+                       long                    interval        = 200;                                  // Wait 200 ms maximum for a DBG response
+                       boolean                 newconnect      = false;                                //
+                       Socket                  newSocket       = null;
+                       PHPStackFrame[] StackList;
+                       PHPDBGInterface newDBGInt;
+
+                       //                              synchronized (this) {
+                       //                                      wait();
+                       //                              }
+
+                       PHPMainThread = new PHPThread (getDebugTarget (), getPort ());
+                       PHPMainThread.setName ("Thread [main]");
+                       timeout       = 0;
+
+                       //                              while ((getDebugTarget() == null) && (timeout < 100)) {
+                       //                                      sleep(100);
+                       //                                      timeout++;
+                       //                              }
+                       // Be sure debug target is set
+                       //                              PHPMainThread.setDebugTarget(getDebugTarget());
+
+                               getDebugTarget ().addThread (PHPMainThread);
+
+                       //System.out.println("Waiting for breakpoints.");
+
+                       while (!shouldStop) {                                                           // As long as nobody will stop us
+                               newconnect = true;                              // The first time
+
+                               try {
+                                       newSocket = server.accept();                            // Waits until DBG want to connect
+                                       //System.out.println("Accepted! : " + socket.toString());
+                               } catch (SocketTimeoutException e) {
+                                       newconnect = false;                                                     // No one wants to connect (connection already done)
+                               } catch (IOException e) {
+                                       PHPDebugCorePlugin.log(e);
+                                       return;
+                               }
+
+                               if (newconnect) {                                                               // Is it just after a new connection
+                                       if (DBGInt == null) {                                           // Do we have a DBG interface?
+                                       server.setSoTimeout(1);                                 // ???
+                                               }
+
+                                       newDBGInt = new PHPDBGInterface (getReader (newSocket),                 // Create a new interface
+                                                                                                                newSocket.getOutputStream (),
+                                                                                                                thisProxy);
+                                       newDBGInt.waitResponse (1000);                          // Wait for the initial DBG response
+                                       newDBGInt.flushAllPackets ();               // Read and process the DBG response
+
+                                       // Check version and session ID
+                                       if ((DBGInt == null) ||                                 // If we have no interface
+                                               (DBGInt.getSID () == newDBGInt.getSID ())) {// or the new session ID is different to the old one
+                                       DBGInt = newDBGInt;                                                     // Set the new interface as current one
+
+                                       try {
+                                               closeSocket ();
+                                       }
+                                                       catch (IOException e) {
+                                               PHPDebugCorePlugin.log (e);
+                                               shouldStop = true;
+                                       }
+
+                                       socket = newSocket;
+                                       setBreakPoints ();
+                                       DBGInt.continueExecution ();                    // Notify DBG that PHP should continue
+                                       }
+                                               else {
+                                       newDBGInt.continueExecution ();                         // Notify DBG that PHP should continue
+                                       newSocket.close ();
+                                       }
+                               }
+
+                               if (DBGInt.waitResponse (interval)) {                                           // Wait for a DBG response (200 ms)
+                                       DBGInt.flushAllPackets ();                                                              // If we got something, read and process it
+
+                                       if (DBGInt.BPUnderHit != 0) {                                                   // ???
+                                       StackList = DBGInt.getStackList ();                 // Get the stack list from DBGInterface
+
+                                           if (StackList.length > 0) {                         // If there is something in stack list
+                                               for (i = 0; i < StackList.length; i++) {        // For all stack list
+                                                       StackList[i].setThread (PHPMainThread);     // Set the PHPTread for all PHPStackFrames
+
+                                                       if (DBGInt.getModByNo (StackList[i].getModNo ()).equals ("")) {
+                                                               DBGInt.getSourceTree ();
+                                                       }
+
+                                                       StackList[i].setFile (DBGInt.getModByNo (StackList[i].getModNo ()));
+                                               }
+
+                                               PHPMainThread.setStackFrames (StackList);
+                                       }
+
+                                       PHPMainThread.suspend ();                             // Fire debug event
+
+                                           synchronized (this) {
+                                               wait ();
+                                       }
+                                       }
+                               }
+
+                               if (remote) {
+                                       if (PHPMainThread.isTerminated ()) {
+                                       shouldStop = true;
+
+                                           break;                                                // Go for terminating the thread
+                                       }
+                               } else {
+                                       if (PHPMainThread.isTerminated () ||
+                                               getDebugTarget ().getProcess ().isTerminated ()) {
+                                       shouldStop = true;
+
+                                       break;                                                // Go for terminating the thread
+                                       }
+                               }
+                       }
+               } catch (Exception ex) {
+                       PHPDebugCorePlugin.log (ex);
+                       System.out.println (ex);
+               } finally {
+                       try {
+                               getDebugTarget ().terminate ();
+                               closeSocket();
+                               closeServerSocket ();
+                       } catch (IOException e) {
+                               PHPDebugCorePlugin.log (e);
+
+                               return;
+                       }
+
+                       //System.out.println("Socket loop finished.");
+               }
+               }
+       }
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/debug/ui/launcher/LoadPathEntryLabelProvider.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/debug/ui/launcher/LoadPathEntryLabelProvider.java
new file mode 100644 (file)
index 0000000..7831922
--- /dev/null
@@ -0,0 +1,64 @@
+package net.sourceforge.phpdt.internal.debug.ui.launcher;
+
+import net.sourceforge.phpdt.internal.debug.ui.PHPDebugUiPlugin;
+import net.sourceforge.phpeclipse.LoadPathEntry;
+
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * @author xp4
+ * 
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ */
+public class LoadPathEntryLabelProvider implements ILabelProvider {
+
+       /**
+        * @see ILabelProvider#getImage(Object)
+        */
+       public Image getImage(Object element) {
+               return null;
+       }
+
+       /**
+        * @see ILabelProvider#getText(Object)
+        */
+       public String getText(Object element) {
+               if (element != null && element.getClass() == LoadPathEntry.class)
+                       return ((LoadPathEntry) element).getProject().getLocation()
+                                       .toOSString();
+
+               PHPDebugUiPlugin
+                               .log(new RuntimeException("Unable to render load path."));
+               return null;
+       }
+
+       /**
+        * @see IBaseLabelProvider#addListener(ILabelProviderListener)
+        */
+       public void addListener(ILabelProviderListener listener) {
+       }
+
+       /**
+        * @see IBaseLabelProvider#dispose()
+        */
+       public void dispose() {
+       }
+
+       /**
+        * @see IBaseLabelProvider#isLabelProperty(Object, String)
+        */
+       public boolean isLabelProperty(Object element, String property) {
+               return false;
+       }
+
+       /**
+        * @see IBaseLabelProvider#removeListener(ILabelProviderListener)
+        */
+       public void removeListener(ILabelProviderListener listener) {
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/debug/ui/launcher/PHPEnvironmentTab.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/debug/ui/launcher/PHPEnvironmentTab.java
new file mode 100644 (file)
index 0000000..0257ce1
--- /dev/null
@@ -0,0 +1,775 @@
+package net.sourceforge.phpdt.internal.debug.ui.launcher;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.debug.ui.PHPDebugUiMessages;
+import net.sourceforge.phpdt.internal.debug.ui.PHPDebugUiPlugin;
+import net.sourceforge.phpdt.internal.debug.ui.preferences.EditPathMapDialog;
+import net.sourceforge.phpdt.internal.debug.ui.preferences.PHPInterpreterPreferencePage;
+import net.sourceforge.phpdt.internal.launching.PHPInterpreter;
+import net.sourceforge.phpdt.internal.launching.PHPLaunchConfigurationAttribute;
+import net.sourceforge.phpdt.internal.launching.PHPRuntime;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ListViewer;
+import org.eclipse.jface.viewers.TableLayout;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+
+public class PHPEnvironmentTab extends AbstractLaunchConfigurationTab {
+       protected ListViewer loadPathListViewer;
+
+       protected java.util.List installedInterpretersWorkingCopy;
+
+       protected Combo interpreterCombo;
+
+       // protected Button loadPathDefaultButton;
+       protected Button fRemoteDebugCheckBox;
+
+       protected Button fRemoteDebugTranslate;
+
+       protected Button fOpenDBGSessionInBrowserCheckBox;
+
+       protected Button fPathMapRemoveButton;
+
+       protected Button fPathMapAddButton;
+
+       protected Button fPathMapEditButton;
+
+       protected Text fRemoteSourcePath;
+
+       protected Table fRemoteDebugPathMapTable;
+
+       protected TabFolder tabFolder;
+
+       private class RemoteDebugTabListener extends SelectionAdapter implements
+                       ModifyListener {
+
+               /*
+                * (non-Javadoc)
+                * 
+                * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
+                */
+               public void modifyText(ModifyEvent e) {
+                       updateLaunchConfigurationDialog();
+               }
+
+               /*
+                * (non-Javadoc)
+                * 
+                * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+                */
+               public void widgetSelected(SelectionEvent e) {
+                       Object source = e.getSource();
+                       if (source == fRemoteDebugPathMapTable) {
+                               setPathMapButtonsEnableState();
+                       } else if (source == fPathMapAddButton) {
+                               handlePathMapAddButtonSelected();
+                       } else if (source == fPathMapEditButton) {
+                               handlePathMapEditButtonSelected();
+                       } else if (source == fPathMapRemoveButton) {
+                               handlePathMapRemoveButtonSelected();
+                       } else if (source == fRemoteDebugCheckBox) {
+                               setRemoteTabEnableState();
+                       } else if (source == fRemoteDebugTranslate) {
+                               setRemoteTabEnableState();
+                       } else {
+                               updateLaunchConfigurationDialog();
+                               ;
+                       }
+
+               }
+
+       }
+
+       private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+
+       private RemoteDebugTabListener fListener = new RemoteDebugTabListener();
+
+       private static final boolean DEFAULT_REMOTE_DEBUG = false;
+
+       private static final boolean DEFAULT_REMOTE_DEBUG_TRANSLATE = false;
+
+       private static final boolean DEFAULT_OPEN_DBGSESSION_IN_BROWSER = true;
+
+       static String[] columnTitles = {
+                       PHPDebugUiMessages
+                                       .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.PathMapTableTitle.local"),
+                       PHPDebugUiMessages
+                                       .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.PathMapTableTitle.remote") };
+
+       public PHPEnvironmentTab() {
+               super();
+       }
+
+       public void createControl(Composite parent) {
+               Composite composite = createPageRoot(parent);
+
+               tabFolder = new TabFolder(composite, SWT.NONE);
+               GridData gridData = new GridData(GridData.FILL_BOTH);
+               tabFolder.setLayoutData(gridData);
+
+               // addLoadPathTab(tabFolder);
+               addInterpreterTab(tabFolder);
+               addRemoteDebugTab(tabFolder);
+       }
+
+       protected void addRemoteDebugTab(TabFolder tabFolder) {
+               Label label;
+
+               TabItem remoteDebugTab = new TabItem(tabFolder, SWT.NONE, 0);
+               remoteDebugTab
+                               .setText(PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.label"));
+
+               Composite comp = new Composite(tabFolder, SWT.NONE);
+               comp.setLayout(new GridLayout());
+               remoteDebugTab.setControl(comp);
+               GridData gd;
+
+               fRemoteDebugCheckBox = new Button(comp, SWT.CHECK);
+               fRemoteDebugCheckBox
+                               .setText(PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.RemoteCheckBox.label"));
+               fRemoteDebugCheckBox.setLayoutData(new GridData(
+                               GridData.HORIZONTAL_ALIGN_BEGINNING));
+               fRemoteDebugCheckBox.addSelectionListener(fListener);
+
+               fRemoteDebugTranslate = new Button(comp, SWT.CHECK);
+               fRemoteDebugTranslate
+                               .setText(PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.RemoteTranslate.label"));
+               fRemoteDebugTranslate.setLayoutData(new GridData(
+                               GridData.HORIZONTAL_ALIGN_BEGINNING));
+               fRemoteDebugTranslate.addSelectionListener(fListener);
+
+               fOpenDBGSessionInBrowserCheckBox = new Button(comp, SWT.CHECK);
+               fOpenDBGSessionInBrowserCheckBox
+                               .setText(PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.OpenDBGSessionInBrowserCheckBox.label"));
+               fOpenDBGSessionInBrowserCheckBox.setLayoutData(new GridData(
+                               GridData.HORIZONTAL_ALIGN_BEGINNING));
+               fOpenDBGSessionInBrowserCheckBox.addSelectionListener(fListener);
+
+               label = new Label(comp, SWT.NONE);
+               label
+                               .setText(PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.RemoteSourcePath.label"));
+               fRemoteSourcePath = new Text(comp, SWT.BORDER | SWT.SINGLE);
+               gd = new GridData(GridData.FILL_HORIZONTAL);
+               fRemoteSourcePath.setLayoutData(gd);
+               fRemoteSourcePath.addModifyListener(fListener);
+
+               createVerticalSpacer(comp, 1);
+
+               Composite pathMapComp = new Composite(comp, SWT.NONE);
+               gd = new GridData(GridData.FILL_BOTH);
+               pathMapComp.setLayoutData(gd);
+               GridLayout parametersLayout = new GridLayout();
+               parametersLayout.numColumns = 2;
+               parametersLayout.marginHeight = 0;
+               parametersLayout.marginWidth = 0;
+               pathMapComp.setLayout(parametersLayout);
+
+               Label pathMapLabel = new Label(pathMapComp, SWT.NONE);
+               pathMapLabel
+                               .setText(PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.PathMap.label"));
+               gd = new GridData();
+               gd.horizontalSpan = 2;
+               pathMapLabel.setLayoutData(gd);
+
+               fRemoteDebugPathMapTable = new Table(pathMapComp, SWT.BORDER
+                               | SWT.MULTI);
+               TableLayout tableLayout = new TableLayout();
+               fRemoteDebugPathMapTable.setLayout(tableLayout);
+
+               gd = new GridData(GridData.FILL_BOTH);
+               fRemoteDebugPathMapTable.setLayoutData(gd);
+               TableColumn column1 = new TableColumn(this.fRemoteDebugPathMapTable,
+                               SWT.NONE);
+               column1
+                               .setText(PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.PathMap.Table.Title.local")); //$NON-NLS-1$
+               TableColumn column2 = new TableColumn(this.fRemoteDebugPathMapTable,
+                               SWT.NONE);
+               column2
+                               .setText(PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.PathMap.Table.Title.remote")); //$NON-NLS-1$
+               tableLayout.addColumnData(new ColumnWeightData(100));
+               tableLayout.addColumnData(new ColumnWeightData(100));
+               fRemoteDebugPathMapTable.setHeaderVisible(true);
+               fRemoteDebugPathMapTable.setLinesVisible(true);
+               fRemoteDebugPathMapTable.addSelectionListener(fListener);
+               fRemoteDebugPathMapTable.addMouseListener(new MouseAdapter() {
+                       public void mouseDoubleClick(MouseEvent e) {
+                               setPathMapButtonsEnableState();
+                               if (fPathMapEditButton.isEnabled()) {
+                                       handlePathMapEditButtonSelected();
+                               }
+                       }
+               });
+               // fRemoteDebugPathMapTable.setEnabled(false);
+
+               Composite envButtonComp = new Composite(pathMapComp, SWT.NONE);
+               GridLayout envButtonLayout = new GridLayout();
+               envButtonLayout.marginHeight = 0;
+               envButtonLayout.marginWidth = 0;
+               envButtonComp.setLayout(envButtonLayout);
+               gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
+                               | GridData.HORIZONTAL_ALIGN_FILL);
+               envButtonComp.setLayoutData(gd);
+
+               fPathMapAddButton = createPushButton(
+                               envButtonComp,
+                               PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.PathMap.Button.Add.label"), null); //$NON-NLS-1$
+               fPathMapAddButton.addSelectionListener(fListener);
+               // fPathMapAddButton.setEnabled(false);
+
+               fPathMapEditButton = createPushButton(
+                               envButtonComp,
+                               PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.PathMap.Button.Edit.label"), null); //$NON-NLS-1$
+               fPathMapEditButton.addSelectionListener(fListener);
+               // fPathMapEditButton.setEnabled(false);
+
+               fPathMapRemoveButton = createPushButton(
+                               envButtonComp,
+                               PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.remoteDebugTab.PathMap.Button.Remove.label"), null); //$NON-NLS-1$
+               fPathMapRemoveButton.addSelectionListener(fListener);
+               // fPathMapRemoveButton.setEnabled(false);
+
+       }
+
+       void handlePathMapAddButtonSelected() {
+               EditPathMapDialog dialog = new EditPathMapDialog(getShell(),
+                               "Edit File Map", new String[] { EMPTY_STRING, EMPTY_STRING });
+               openNewPathMapDialog(dialog, null);
+               // dialog.create();
+               // if (dialog.open()==EditPathMapDialog.OK)
+               // {
+               // TableItem item = new TableItem (fRemoteDebugPathMapTable, SWT.NONE);
+               // item.setText(0,dialog.getLocalPath());
+               // item.setText(1,dialog.getRemotePath());
+               // updateLaunchConfigurationDialog();
+               // }
+               // updateLaunchConfigurationDialog();
+               setPathMapButtonsEnableState();
+       }
+
+       void handlePathMapRemoveButtonSelected() {
+               int[] selectedIndices = this.fRemoteDebugPathMapTable
+                               .getSelectionIndices();
+               this.fRemoteDebugPathMapTable.remove(selectedIndices);
+               setPathMapButtonsEnableState();
+               updateLaunchConfigurationDialog();
+       }
+
+       void handlePathMapEditButtonSelected() {
+               TableItem selectedItem = this.fRemoteDebugPathMapTable.getSelection()[0];
+               String local = selectedItem.getText(0);
+               String remote = selectedItem.getText(1);
+               EditPathMapDialog dialog = new EditPathMapDialog(getShell(),
+                               "Edit File Map", new String[] { local, remote });
+               openNewPathMapDialog(dialog, selectedItem);
+       }
+
+       /**
+        * Set the enabled state of whole tab.
+        */
+       private void setRemoteTabEnableState() {
+               boolean state = fRemoteDebugCheckBox.getSelection();
+               fRemoteSourcePath.setEnabled(state);
+               fRemoteDebugTranslate.setEnabled(state);
+
+               fRemoteDebugPathMapTable.setEnabled(state);
+               if (!state) {
+                       fPathMapEditButton.setEnabled(false);
+                       fPathMapRemoveButton.setEnabled(false);
+                       fPathMapAddButton.setEnabled(false);
+                       fOpenDBGSessionInBrowserCheckBox.setEnabled(false);
+               } else {
+                       setPathMapButtonsEnableState();
+               }
+
+               updateLaunchConfigurationDialog();
+       }
+
+       /**
+        * Set the enabled state of the three environment variable-related buttons
+        * based on the selection in the PathMapTable widget.
+        */
+       private void setPathMapButtonsEnableState() {
+               // just do nothing for now
+               //
+               if (fRemoteDebugCheckBox.getSelection()) {
+                       fOpenDBGSessionInBrowserCheckBox.setEnabled(true);
+                       fRemoteDebugTranslate.setEnabled(true);
+                       int selectCount = this.fRemoteDebugPathMapTable
+                                       .getSelectionIndices().length;
+                       if (selectCount < 1) {
+                               fPathMapEditButton.setEnabled(false);
+                               fPathMapRemoveButton.setEnabled(false);
+                       } else {
+                               fPathMapRemoveButton.setEnabled(true);
+                               if (selectCount == 1) {
+                                       fPathMapEditButton.setEnabled(true);
+                               } else {
+                                       fPathMapEditButton.setEnabled(false);
+                               }
+                       }
+                       fPathMapAddButton.setEnabled(true);
+               }
+       }
+
+       /**
+        * Show the specified dialog and update the pathMapTable table based on its
+        * results.
+        * 
+        * @param updateItem
+        *            the item to update, or <code>null</code> if adding a new
+        *            item
+        */
+       private void openNewPathMapDialog(EditPathMapDialog dialog,
+                       TableItem updateItem) {
+               if (dialog.open() != EditPathMapDialog.OK) {
+                       return;
+               }
+               String[] pathPair = dialog.getPathPair();
+               TableItem tableItem = updateItem;
+               if (tableItem == null) {
+                       tableItem = getTableItemForName(pathPair[0]);
+                       if (tableItem == null) {
+                               tableItem = new TableItem(this.fRemoteDebugPathMapTable,
+                                               SWT.NONE);
+                       }
+               }
+               tableItem.setText(pathPair);
+               this.fRemoteDebugPathMapTable
+                               .setSelection(new TableItem[] { tableItem });
+               updateLaunchConfigurationDialog();
+       }
+
+       /**
+        * Helper method that indicates whether the specified parameter name is
+        * already present in the parameters table.
+        */
+       private TableItem getTableItemForName(String candidateName) {
+               TableItem[] items = this.fRemoteDebugPathMapTable.getItems();
+               for (int i = 0; i < items.length; i++) {
+                       String name = items[i].getText(0);
+                       if (name.equals(candidateName)) {
+                               return items[i];
+                       }
+               }
+               return null;
+       }
+
+       // protected void addLoadPathTab(TabFolder tabFolder) {
+       // Composite loadPathComposite = new Composite(tabFolder, SWT.NONE);
+       // loadPathComposite.setLayout(new GridLayout());
+       //
+       // loadPathListViewer = new ListViewer(loadPathComposite, SWT.BORDER |
+       // SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
+       // loadPathListViewer.setContentProvider(new ListContentProvider());
+       // loadPathListViewer.setLabelProvider(new LoadPathEntryLabelProvider());
+       // loadPathListViewer.getList().setLayoutData(new
+       // GridData(GridData.FILL_BOTH));
+       //
+       // TabItem loadPathTab = new TabItem(tabFolder, SWT.NONE, 0);
+       // loadPathTab.setText(PHPDebugUiMessages.getString("LaunchConfigurationTab.PHPEnvironment.loadPathTab.label"));
+       // loadPathTab.setControl(loadPathComposite);
+       // loadPathTab.setData(loadPathListViewer);
+
+       // loadPathDefaultButton = new Button(loadPathComposite, SWT.CHECK);
+       // loadPathDefaultButton.setText(PHPDebugUiMessages.getString("LaunchConfigurationTab.PHPEnvironment.loadPathDefaultButton.label"));
+       // loadPathDefaultButton.setLayoutData(new
+       // GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
+       // loadPathDefaultButton.addSelectionListener(getLoadPathDefaultButtonSelectionListener());
+       //              
+       // loadPathDefaultButton.setEnabled(false); //for now, until the load path
+       // is customizable on the configuration
+       // }
+
+       protected SelectionListener getLoadPathSelectionListener() {
+               return new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent e) {
+                               System.out.println("Loadpath list selection occurred: "
+                                               + e.getSource());
+                       }
+               };
+       }
+
+       protected SelectionListener getLoadPathDefaultButtonSelectionListener() {
+               return new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent e) {
+                               setUseLoadPathDefaults(((Button) e.getSource()).getSelection());
+                       }
+               };
+       }
+
+       protected void addInterpreterTab(TabFolder tabFolder) {
+               Composite interpreterComposite = new Composite(tabFolder, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 2;
+               layout.marginHeight = 0;
+               layout.marginWidth = 0;
+               interpreterComposite.setLayout(layout);
+               interpreterComposite.setLayoutData(new GridData(
+                               GridData.FILL_HORIZONTAL));
+
+               createVerticalSpacer(interpreterComposite, 2);
+
+               interpreterCombo = new Combo(interpreterComposite, SWT.READ_ONLY);
+               interpreterCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+               initializeInterpreterCombo(interpreterCombo);
+               interpreterCombo.addModifyListener(getInterpreterComboModifyListener());
+
+               Button interpreterAddButton = new Button(interpreterComposite, SWT.PUSH);
+               interpreterAddButton
+                               .setText(PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.interpreterAddButton.label"));
+               interpreterAddButton.addSelectionListener(new SelectionAdapter() {
+                       public void widgetSelected(SelectionEvent evt) {
+                               PHPInterpreter newInterpreter = new PHPInterpreter(null);
+                               File phpRuntime = PHPInterpreterPreferencePage.getFile(
+                                               getShell(), null);
+                               if (phpRuntime != null) {
+                                       newInterpreter.setInstallLocation(phpRuntime);
+                                       PHPRuntime.getDefault().addInstalledInterpreter(
+                                                       newInterpreter);
+                                       interpreterCombo.add(newInterpreter.getInstallLocation()
+                                                       .toString());
+                                       interpreterCombo.select(interpreterCombo
+                                                       .indexOf(newInterpreter.getInstallLocation()
+                                                                       .toString()));
+                               }
+                       }
+               });
+
+               TabItem interpreterTab = new TabItem(tabFolder, SWT.NONE);
+               interpreterTab
+                               .setText(PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.interpreterTab.label"));
+               interpreterTab.setControl(interpreterComposite);
+       }
+
+       protected ModifyListener getInterpreterComboModifyListener() {
+               return new ModifyListener() {
+                       public void modifyText(ModifyEvent evt) {
+                               updateLaunchConfigurationDialog();
+                       }
+               };
+       }
+
+       protected void createVerticalSpacer(Composite comp, int colSpan) {
+               Label label = new Label(comp, SWT.NONE);
+               GridData gd = new GridData();
+               gd.horizontalSpan = colSpan;
+               label.setLayoutData(gd);
+       }
+
+       public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+               PHPInterpreter selectedInterpreter = PHPRuntime.getDefault()
+                               .getSelectedInterpreter();
+               if (selectedInterpreter != null) {
+                       String interpreterLocation = selectedInterpreter
+                                       .getInstallLocation().toString();
+                       configuration.setAttribute(
+                                       PHPLaunchConfigurationAttribute.SELECTED_INTERPRETER,
+                                       interpreterLocation);
+               }
+               try {
+                       String projectName = configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.PROJECT_NAME, "");
+                       if (projectName != "") {
+                               IProject project = ResourcesPlugin.getWorkspace().getRoot()
+                                               .getProject(projectName);
+                               if (project != null) {
+                                       IPath remotePath = project.getLocation();
+                                       String fileName = configuration.getAttribute(
+                                                       PHPLaunchConfigurationAttribute.FILE_NAME, "");
+                                       if (fileName != "") {
+                                               Path filePath = new Path(fileName);
+                                               remotePath = remotePath.append(filePath
+                                                               .removeLastSegments(1));
+                                       }
+                                       configuration.setAttribute(
+                                                       PHPLaunchConfigurationAttribute.REMOTE_PATH,
+                                                       remotePath.toOSString());
+                               }
+                       }
+               } catch (CoreException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+       }
+
+       public void initializeFrom(ILaunchConfiguration configuration) {
+               // initializeLoadPath(configuration);
+               initializeInterpreterSelection(configuration);
+               initializeRemoteDebug(configuration);
+       }
+
+       protected void initializeRemoteDebug(ILaunchConfiguration configuration) {
+               try {
+                       fRemoteDebugCheckBox.setSelection(configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.REMOTE_DEBUG,
+                                       DEFAULT_REMOTE_DEBUG));
+               } catch (CoreException ce) {
+                       fRemoteDebugCheckBox.setSelection(DEFAULT_REMOTE_DEBUG);
+               }
+               try {
+                       fRemoteDebugTranslate.setSelection(configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.REMOTE_DEBUG_TRANSLATE,
+                                       DEFAULT_REMOTE_DEBUG_TRANSLATE));
+               } catch (CoreException ce) {
+                       fRemoteDebugTranslate.setSelection(DEFAULT_REMOTE_DEBUG_TRANSLATE);
+               }
+               try {
+                       fOpenDBGSessionInBrowserCheckBox
+                                       .setSelection(configuration
+                                                       .getAttribute(
+                                                                       PHPLaunchConfigurationAttribute.OPEN_DBGSESSION_IN_BROWSER,
+                                                                       DEFAULT_OPEN_DBGSESSION_IN_BROWSER));
+               } catch (CoreException ce) {
+                       fOpenDBGSessionInBrowserCheckBox
+                                       .setSelection(DEFAULT_OPEN_DBGSESSION_IN_BROWSER);
+               }
+               setRemoteTabEnableState();
+               try {
+                       fRemoteSourcePath.setText(configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.REMOTE_PATH, ""));
+               } catch (CoreException ce) {
+                       fRemoteSourcePath.setText("");
+               }
+
+               updatePathMapFromConfig(configuration);
+
+       }
+
+       private void updatePathMapFromConfig(ILaunchConfiguration config) {
+               Map envVars = null;
+               try {
+                       if (config != null) {
+                               envVars = config.getAttribute(
+                                               PHPLaunchConfigurationAttribute.FILE_MAP, (Map) null);
+                       }
+                       updatePathMapTable(envVars, this.fRemoteDebugPathMapTable);
+                       setPathMapButtonsEnableState();
+               } catch (CoreException ce) {
+                       log(ce);
+               }
+       }
+
+       private void updatePathMapTable(Map map, Table tableWidget) {
+               tableWidget.removeAll();
+               if (map == null) {
+                       return;
+               }
+               Iterator iterator = map.keySet().iterator();
+               while (iterator.hasNext()) {
+                       String key = (String) iterator.next();
+                       String value = (String) map.get(key);
+                       TableItem tableItem = new TableItem(tableWidget, SWT.NONE);
+                       tableItem.setText(new String[] { key, value });
+               }
+       }
+
+       // protected void initializeLoadPath(ILaunchConfiguration configuration) {
+       // boolean useDefaultLoadPath = true;
+       // try {
+       // useDefaultLoadPath =
+       // configuration.getAttribute(PHPLaunchConfigurationAttribute.USE_DEFAULT_LOAD_PATH,
+       // true);
+       // setUseLoadPathDefaults(useDefaultLoadPath);
+       // if (useDefaultLoadPath) {
+       // String projectName =
+       // configuration.getAttribute(PHPLaunchConfigurationAttribute.PROJECT_NAME,
+       // "");
+       // if (projectName != "") {
+       // IProject aProject =
+       // PHPeclipsePlugin.getWorkspace().getRoot().getProject(projectName);
+       // if ((aProject != null) && JavaCore.isPHPProject(aProject)) {
+       // JavaProject thePHPProject = new JavaProject();
+       // thePHPProject.setProject(aProject);
+       // List loadPathEntries = thePHPProject.getLoadPathEntries();
+       // loadPathListViewer.setInput(loadPathEntries);
+       // }
+       // }
+       // }
+       // } catch (CoreException e) {
+       // log(e);
+       // }
+       // }
+
+       protected void setUseLoadPathDefaults(boolean useDefaults) {
+               loadPathListViewer.getList().setEnabled(!useDefaults);
+               // loadPathDefaultButton.setSelection(useDefaults);
+       }
+
+       protected void initializeInterpreterSelection(
+                       ILaunchConfiguration configuration) {
+               String interpreterName = null;
+               try {
+                       interpreterName = configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.SELECTED_INTERPRETER, "");
+               } catch (CoreException e) {
+                       log(e);
+               }
+               if (interpreterName != null && !interpreterName.equals(""))
+                       interpreterCombo.select(interpreterCombo.indexOf(interpreterName));
+       }
+
+       protected void initializeInterpreterCombo(Combo interpreterCombo) {
+               installedInterpretersWorkingCopy = new ArrayList();
+               installedInterpretersWorkingCopy.addAll(PHPRuntime.getDefault()
+                               .getInstalledInterpreters());
+
+               String[] interpreterNames = new String[installedInterpretersWorkingCopy
+                               .size()];
+               for (int interpreterIndex = 0; interpreterIndex < installedInterpretersWorkingCopy
+                               .size(); interpreterIndex++) {
+                       PHPInterpreter interpreter = (PHPInterpreter) installedInterpretersWorkingCopy
+                                       .get(interpreterIndex);
+                       interpreterNames[interpreterIndex] = interpreter
+                                       .getInstallLocation().toString();
+               }
+               interpreterCombo.setItems(interpreterNames);
+
+               PHPInterpreter selectedInterpreter = PHPRuntime.getDefault()
+                               .getSelectedInterpreter();
+               if (selectedInterpreter != null)
+                       interpreterCombo.select(interpreterCombo
+                                       .indexOf(selectedInterpreter.getInstallLocation()
+                                                       .toString()));
+       }
+
+       public void performApply(ILaunchConfigurationWorkingCopy configuration) {
+               int selectionIndex = interpreterCombo.getSelectionIndex();
+               if (selectionIndex >= 0)
+                       configuration.setAttribute(
+                                       PHPLaunchConfigurationAttribute.SELECTED_INTERPRETER,
+                                       interpreterCombo.getItem(selectionIndex));
+
+               // configuration.setAttribute(PHPLaunchConfigurationAttribute.USE_DEFAULT_LOAD_PATH,
+               // loadPathDefaultButton.getSelection());
+
+               // if (!loadPathDefaultButton.getSelection()) {
+               // List loadPathEntries = (List) loadPathListViewer.getInput();
+               // List loadPathStrings = new ArrayList();
+               // for (Iterator iterator = loadPathEntries.iterator();
+               // iterator.hasNext();) {
+               // LoadPathEntry entry = (LoadPathEntry) iterator.next();
+               // loadPathStrings.add(entry.getPath().toString());
+               // }
+               // configuration.setAttribute(PHPLaunchConfigurationAttribute.CUSTOM_LOAD_PATH,
+               // loadPathStrings);
+               // }
+
+               configuration.setAttribute(
+                               PHPLaunchConfigurationAttribute.REMOTE_DEBUG,
+                               fRemoteDebugCheckBox.getSelection());
+               configuration.setAttribute(
+                               PHPLaunchConfigurationAttribute.REMOTE_DEBUG_TRANSLATE,
+                               fRemoteDebugTranslate.getSelection());
+               configuration.setAttribute(PHPLaunchConfigurationAttribute.FILE_MAP,
+                               getMapFromPathMapTable());
+               configuration.setAttribute(PHPLaunchConfigurationAttribute.REMOTE_PATH,
+                               fRemoteSourcePath.getText());
+               configuration.setAttribute(
+                               PHPLaunchConfigurationAttribute.OPEN_DBGSESSION_IN_BROWSER,
+                               fOpenDBGSessionInBrowserCheckBox.getSelection());
+       }
+
+       protected Composite createPageRoot(Composite parent) {
+               Composite composite = new Composite(parent, SWT.NULL);
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 2;
+               composite.setLayout(layout);
+               createVerticalSpacer(composite, 2);
+               setControl(composite);
+
+               return composite;
+       }
+
+       private Map getMapFromPathMapTable() {
+               TableItem[] items = fRemoteDebugPathMapTable.getItems();
+               if (items.length == 0) {
+                       return null;
+               }
+               Map map = new HashMap(items.length);
+               for (int i = 0; i < items.length; i++) {
+                       TableItem item = items[i];
+                       String key = item.getText(0);
+                       String value = item.getText(1);
+                       map.put(key, value);
+               }
+               return map;
+       }
+
+       public String getName() {
+               return PHPDebugUiMessages
+                               .getString("LaunchConfigurationTab.PHPEnvironment.name");
+       }
+
+       public boolean isValid(ILaunchConfiguration launchConfig) {
+               try {
+                       String selectedInterpreter = launchConfig.getAttribute(
+                                       PHPLaunchConfigurationAttribute.SELECTED_INTERPRETER, "");
+                       if (selectedInterpreter.length() == 0) {
+                               setErrorMessage(PHPDebugUiMessages
+                                               .getString("LaunchConfigurationTab.PHPEnvironment.interpreter_not_selected_error_message"));
+                               return false;
+                       }
+               } catch (CoreException e) {
+                       log(e);
+               }
+
+               setErrorMessage(null);
+               return true;
+       }
+
+       protected void log(Throwable t) {
+               PHPDebugUiPlugin.log(t);
+       }
+
+       public Image getImage() {
+               return PHPUiImages.get(PHPUiImages.IMG_CTOOLS_PHP);
+       }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/launching/InterpreterRunner.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/launching/InterpreterRunner.java
new file mode 100644 (file)
index 0000000..6aa5738
--- /dev/null
@@ -0,0 +1,140 @@
+package net.sourceforge.phpdt.internal.launching;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.core.JavaProject;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IProcess;
+
+public class InterpreterRunner {
+
+       public InterpreterRunner() {
+       }
+
+       public IProcess run(InterpreterRunnerConfiguration configuration,
+                       ILaunch launch) {
+               String commandLine = renderCommandLine(configuration);
+               File workingDirectory = configuration.getAbsoluteWorkingDirectory();
+
+               setEnvironmentVariables(configuration);
+               String[] env = configuration.getEnvironment();
+               Process nativePHPProcess = null;
+               try {
+                       nativePHPProcess = configuration.getInterpreter().exec(commandLine,
+                                       workingDirectory, env);
+               } catch (IOException e) {
+                       throw new RuntimeException("Unable to execute interpreter: "
+                                       + commandLine + workingDirectory);
+               }
+
+               IProcess process = DebugPlugin.newProcess(launch, nativePHPProcess,
+                               renderLabel(configuration));
+               process
+                               .setAttribute(PHPLaunchingPlugin.PLUGIN_ID
+                                               + ".launcher.cmdline", commandLine);
+               process.setAttribute(IProcess.ATTR_PROCESS_TYPE,
+                               PHPLaunchConfigurationAttribute.PHP_LAUNCH_PROCESS_TYPE);
+
+               return process;
+       }
+
+       protected String renderLabel(InterpreterRunnerConfiguration configuration) {
+               StringBuffer buffer = new StringBuffer();
+
+               PHPInterpreter interpreter = configuration.getInterpreter();
+               buffer.append("PHP ");
+               buffer.append(interpreter.getCommand());
+               buffer.append(" : ");
+               buffer.append(configuration.getFileName());
+
+               return buffer.toString();
+       }
+
+       protected String renderCommandLine(
+                       InterpreterRunnerConfiguration configuration) {
+               PHPInterpreter interpreter = configuration.getInterpreter();
+
+               StringBuffer buffer = new StringBuffer();
+               buffer.append(this.getDebugCommandLineArgument());
+               // buffer.append(renderLoadPath(configuration));
+               buffer.append(" " + configuration.getInterpreterArguments());
+               // buffer.append(interpreter.endOfOptionsDelimeter);
+               buffer.append(" "
+                               + osDependentPath(configuration.getAbsoluteFileName()));
+               buffer.append(" " + configuration.getProgramArguments());
+
+               return buffer.toString();
+       }
+
+       protected void setEnvironmentVariables(
+                       InterpreterRunnerConfiguration configuration) {
+               IPath FilePath = new Path(configuration.getAbsoluteFileName());
+               String OSFilePath = FilePath.toOSString();
+               configuration.addEnvironmentValue("REDIRECT_URL", OSFilePath, true);
+               configuration.addEnvironmentValue("REQUEST_URI", OSFilePath, true);
+               configuration.addEnvironmentValue("PATH_INFO", OSFilePath, true);
+               configuration.addEnvironmentValue("PATH_TRANSLATED", OSFilePath, true);
+               configuration.addEnvironmentValue("SCRIPT_FILENAME", configuration
+                               .getInterpreter().getCommand(), true);
+               configuration
+                               .addEnvironmentValue("SERVER_PROTOCOL", "HTTP / 1.1", true);
+
+               configuration.addEnvironmentValue("REDIRECT_QUERY_STRING", "", true);
+               configuration.addEnvironmentValue("REDIRECT_STATUS", "200", true);
+               configuration.addEnvironmentValue("SERVER_SOFTWARE", "DBG / 2.1", true);
+               configuration.addEnvironmentValue("SERVER_NAME", "localhost", true);
+               configuration.addEnvironmentValue("SERVER_ADDR", "127.0.0.1", true);
+               configuration.addEnvironmentValue("SERVER_PORT", "80", true);
+               configuration.addEnvironmentValue("REMOTE_ADDR", "127.0.0.1", true);
+
+               configuration.addEnvironmentValue("GATEWAY_INTERFACE", "CGI / 1.1",
+                               true);
+               configuration.addEnvironmentValue("REQUEST_METHOD", "GET", true);
+
+               Map stringVars = DebugPlugin.getDefault().getLaunchManager()
+                               .getNativeEnvironment();
+               if (stringVars.containsKey("SYSTEMROOT"))
+                       configuration.addEnvironmentValue("SYSTEMROOT", (String) stringVars
+                                       .get("SYSTEMROOT"), true);
+
+       }
+
+       protected String renderLoadPath(InterpreterRunnerConfiguration configuration) {
+               StringBuffer loadPath = new StringBuffer();
+
+               JavaProject project = configuration.getProject();
+               addToLoadPath(loadPath, project.getProject());
+
+               Iterator referencedProjects = project.getReferencedProjects()
+                               .iterator();
+               while (referencedProjects.hasNext())
+                       addToLoadPath(loadPath, (IProject) referencedProjects.next());
+
+               return loadPath.toString();
+       }
+
+       protected void addToLoadPath(StringBuffer loadPath, IProject project) {
+               loadPath.append(" -I "
+                               + osDependentPath(project.getLocation().toOSString()));
+       }
+
+       protected String osDependentPath(String aPath) {
+               if (Platform.getOS().equals(Platform.OS_WIN32))
+                       aPath = "\"" + aPath + "\"";
+
+               return aPath;
+       }
+
+       protected String getDebugCommandLineArgument() {
+               return "";
+       }
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/launching/InterpreterRunnerConfiguration.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/launching/InterpreterRunnerConfiguration.java
new file mode 100644 (file)
index 0000000..52fa78a
--- /dev/null
@@ -0,0 +1,207 @@
+package net.sourceforge.phpdt.internal.launching;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.core.JavaProject;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.internal.ui.launchConfigurations.EnvironmentVariable;
+
+public class InterpreterRunnerConfiguration {
+       protected ILaunchConfiguration configuration;
+
+       private HashMap fEnvironment;
+
+       public InterpreterRunnerConfiguration(ILaunchConfiguration aConfiguration) {
+               configuration = aConfiguration;
+               fEnvironment = new HashMap();
+       }
+
+       public String getAbsoluteFileName() {
+               IPath path = new Path(getFileName());
+               IProject project = getProject().getProject();
+
+               return project.getLocation().toOSString() + "/" + getFileName();
+       }
+
+       public String getFileName() {
+               String fileName = "";
+
+               try {
+                       fileName = configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.FILE_NAME,
+                                       "No file specified in configuration");
+               } catch (CoreException e) {
+               }
+
+               return fileName.replace('\\', '/');
+       }
+
+       public JavaProject getProject() {
+               String projectName = "";
+
+               try {
+                       projectName = configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.PROJECT_NAME, "");
+               } catch (CoreException e) {
+                       PHPLaunchingPlugin.log(e);
+               }
+
+               IProject project = PHPLaunchingPlugin.getWorkspace().getRoot()
+                               .getProject(projectName);
+
+               JavaProject phpProject = new JavaProject();
+               phpProject.setProject(project);
+               return phpProject;
+       }
+
+       public File getAbsoluteWorkingDirectory() {
+               String file = null;
+               try {
+                       file = configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.WORKING_DIRECTORY, "");
+               } catch (CoreException e) {
+                       PHPLaunchingPlugin.log(e);
+               }
+               return new File(file);
+       }
+
+       public String getInterpreterArguments() {
+               try {
+                       return configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.INTERPRETER_ARGUMENTS, "");
+               } catch (CoreException e) {
+               }
+
+               return "";
+       }
+
+       public String getProgramArguments() {
+               try {
+                       return configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.PROGRAM_ARGUMENTS, "");
+               } catch (CoreException e) {
+               }
+
+               return "";
+       }
+
+       public PHPInterpreter getInterpreter() {
+               String selectedInterpreter = null;
+               try {
+                       selectedInterpreter = configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.SELECTED_INTERPRETER, "");
+               } catch (CoreException e) {
+               }
+
+               return PHPRuntime.getDefault().getInterpreter(selectedInterpreter);
+       }
+
+       public boolean useRemoteDebugger() {
+               try {
+                       return configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.REMOTE_DEBUG, false);
+               } catch (CoreException e) {
+                       PHPLaunchingPlugin.log(e);
+               }
+               return false;
+       }
+
+       public boolean usePathTranslation() {
+               try {
+                       return configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.REMOTE_DEBUG_TRANSLATE,
+                                       false);
+               } catch (CoreException e) {
+                       PHPLaunchingPlugin.log(e);
+               }
+               return false;
+       }
+
+       public Map getPathMap() {
+               try {
+                       return configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.FILE_MAP, (Map) null);
+               } catch (CoreException e) {
+                       PHPLaunchingPlugin.log(e);
+               }
+               return (Map) null;
+       }
+
+       public boolean useDBGSessionInBrowser() {
+               try {
+                       return configuration.getAttribute(
+                                       PHPLaunchConfigurationAttribute.OPEN_DBGSESSION_IN_BROWSER,
+                                       true);
+               } catch (CoreException e) {
+                       PHPLaunchingPlugin.log(e);
+               }
+               return false;
+       }
+
+       public void setEnvironment(String[] envp) {
+               if (envp == null)
+                       return;
+               for (int i = 0; i < envp.length; i++) {
+                       addEnvironmentValue(envp[i], true);
+               }
+       }
+
+       public void addEnvironmentValue(String env, boolean replace) {
+               String value = env.substring(env.indexOf('=') + 1);
+               String key = env.substring(0, env.indexOf('='));
+               addEnvironmentValue(key, value, replace);
+       }
+
+       public void addEnvironmentValue(String key, String value, boolean replace) {
+               if (!replace && fEnvironment.containsKey(key)) {
+                       EnvironmentVariable ev = (EnvironmentVariable) fEnvironment
+                                       .get(key);
+                       ev.setValue(ev.getValue() + ";" + value);
+                       fEnvironment.put(key, ev);
+               } else
+                       this.fEnvironment.put(key, new EnvironmentVariable(key, value));
+       }
+
+       public String[] getEnvironment() {
+
+               Iterator iter = fEnvironment.entrySet().iterator();
+               List strings = new ArrayList(fEnvironment.size());
+               while (iter.hasNext()) {
+                       Map.Entry entry = (Map.Entry) iter.next();
+                       StringBuffer buffer = new StringBuffer((String) entry.getKey());
+                       buffer.append('=').append(
+                                       ((EnvironmentVariable) entry.getValue()).getValue());
+                       strings.add(buffer.toString());
+               }
+               return (String[]) strings.toArray(new String[strings.size()]);
+
+       }
+
+       public String getRemoteSourcePath() {
+
+               IProject project = getProject().getProject();
+               if (!useRemoteDebugger())
+                       return project.getLocation().toOSString();
+               else {
+                       try {
+                               return configuration.getAttribute(
+                                               PHPLaunchConfigurationAttribute.REMOTE_PATH, "");
+                       } catch (CoreException e) {
+                               PHPLaunchingPlugin.log(e);
+                       }
+               }
+
+               return "";
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/launching/PHPSourceLocator.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/launching/PHPSourceLocator.java
new file mode 100644 (file)
index 0000000..652a6c7
--- /dev/null
@@ -0,0 +1,219 @@
+package net.sourceforge.phpdt.internal.launching;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.builder.ExternalEditorInput;
+import net.sourceforge.phpeclipse.builder.FileStorage;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.model.IPersistableSourceLocator;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.ui.ISourcePresentation;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.FileEditorInput;
+
+public class PHPSourceLocator implements IPersistableSourceLocator, ISourcePresentation {
+       private String          absoluteWorkingDirectory;
+       private Map             pathMap = null;
+       private boolean         remoteDebug;
+       private IPath           remoteSourcePath;
+       private String          projectName;
+
+  public PHPSourceLocator() {
+
+  }
+
+  public String getAbsoluteWorkingDirectory() {
+    return absoluteWorkingDirectory;
+  }
+
+  /**
+   * @see org.eclipse.debug.core.model.IPersistableSourceLocator#getMemento()
+   */
+  public String getMemento() throws CoreException {
+    return null;
+  }
+
+  /**
+   * @see org.eclipse.debug.core.model.IPersistableSourceLocator#initializeFromMemento(String)
+   */
+  public void initializeFromMemento(String memento) throws CoreException {
+  }
+
+  /**
+   * @see org.eclipse.debug.core.model.IPersistableSourceLocator#initializeDefaults(ILaunchConfiguration)
+   */
+  public void initializeDefaults (ILaunchConfiguration configuration) throws CoreException {
+    this.absoluteWorkingDirectory = configuration.getAttribute (PHPLaunchConfigurationAttribute.WORKING_DIRECTORY, "");
+       this.remoteDebug              = configuration.getAttribute (PHPLaunchConfigurationAttribute.REMOTE_DEBUG,false);
+       this.pathMap                  = configuration.getAttribute (PHPLaunchConfigurationAttribute.FILE_MAP, (Map)null);
+       this.projectName              = configuration.getAttribute (PHPLaunchConfigurationAttribute.PROJECT_NAME, "");
+
+       if (Platform.getOS().equals(Platform.OS_WIN32)) {
+               this.remoteSourcePath = new Path ((configuration.getAttribute (PHPLaunchConfigurationAttribute.REMOTE_PATH, "")).toLowerCase());
+       }
+       else {
+               this.remoteSourcePath = new Path (configuration.getAttribute (PHPLaunchConfigurationAttribute.REMOTE_PATH, ""));
+       }
+
+//             system.os.name
+  }
+
+  /**
+   * @see org.eclipse.debug.core.model.ISourceLocator#getSourceElement(IStackFrame)
+   *
+   * Return the client side source filename for the server side source file.
+   * E.g. when cross debugging, the server side filename could be /var/www/index.php
+   * on the client side it is either a Eclipse_PHP_projectname\index.php (when it is a linked file)
+   *
+   *
+   * @param stackFrame    The stackframe for which we want the client side source file name
+   * @return              The filename as it appears on the client side
+   */
+  public Object getSourceElement (IStackFrame stackFrame) {
+       IPath    projectPath;
+       IPath    remotePath;
+       IPath    path;
+       IPath    localPath;
+       Iterator iterator;
+       String   fileName;
+       String   file;
+       String   local;
+
+       fileName = ((PHPStackFrame) stackFrame).getFileName ();                 // Get the filename as it is submitted by DBG
+       file     = "";
+
+    if (remoteDebug) {                                              // Is it a remote debugging session
+               path = new Path (fileName);                                 // Create a IPath object for the server side filename
+
+               if (!remoteSourcePath.isEmpty()) {
+                       if (remoteSourcePath.isPrefixOf (path)) {                   // Is the server side filename with the remote source path
+                               path        = path.removeFirstSegments (remoteSourcePath.matchingFirstSegments (path)); // Remove the remote source path
+                               file        = path.toString ();                         // The filename without the remote source path
+                               projectPath = (PHPeclipsePlugin.getWorkspace().getRoot().getProject(projectName).getLocation()); // Get the absolute project path
+
+                               return (projectPath.append (path)).toOSString ();       // Return the filename as absolute client side path
+                       }
+               }
+               else {
+                       if (pathMap == null) {                                      // Do we have path mapping (e.g. for cross platform debugging)
+                               return fileName;                                        // No, then return the filename as it given by DBG (the full server side path)
+                       }
+
+                       iterator = pathMap.keySet().iterator();
+
+                       while (iterator.hasNext ()) {
+                               local      = (String) iterator.next ();                 // Get the local/client side path of the mapping
+                               remotePath = new Path ((String) pathMap.get (local));   // Get the remote/server side path of the mapping
+
+                               if (remotePath.isPrefixOf (path)) {                     // Starts the remote/server side file path with the remote/server side mapping path
+                                       path      = path.removeFirstSegments (remotePath.matchingFirstSegments (path)); // Remove the absolute path from filename
+                                       localPath = new Path (local);                       // Create new IPath object for the local/client side path
+                                       path      = localPath.append (path);                // Prepend the project relative path to filename
+
+                                       projectPath = (PHPeclipsePlugin.getWorkspace().getRoot().getProject(projectName).getLocation()); // Get the absolute project path
+
+                                       return (projectPath.append (path)).toOSString ();       // Return the filename as absolute client side path
+                               }
+                       }
+               }
+
+               if (pathMap == null) {                                      // Do we have path mapping (e.g. for cross platform debugging)
+                       return fileName;                                        // No, then return the filename as it given by DBG (the full server side path)
+               }
+
+               iterator = pathMap.keySet().iterator();
+
+               while (iterator.hasNext ()) {
+                       local      = (String) iterator.next ();                 // Get the local/client side path of the mapping
+                       remotePath = new Path ((String) pathMap.get (local));   // Get the remote/server side path of the mapping
+
+                       if (remotePath.isPrefixOf (path)) {                     // Starts the remote/server side file path with the remote/server side mapping path
+                               path      = path.removeFirstSegments (remotePath.matchingFirstSegments (path)); // Remove the absolute path from filename
+                               localPath = new Path (local);                       // Create new IPath object for the local/client side path
+
+                               return localPath.append (path).toOSString ();       // Append the remote filename to the client side path (So we return the absolute path
+                                                                                                                                       // to the source file as the client side sees it.
+                       }
+               }
+
+               return fileName;
+       } else {
+               return fileName;
+    }
+  }
+
+  /**
+   * @see org.eclipse.debug.ui.ISourcePresentation#getEditorId(IEditorInput, Object)
+   */
+  public String getEditorId(IEditorInput input, Object element) {
+    return PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor((String) element).getId();
+  }
+
+  /**
+   * @see org.eclipse.debug.ui.ISourcePresentation#getEditorInput(Object)
+   *
+   * @param element The absolute local/client side file path
+   */
+  public IEditorInput getEditorInput (Object element) {
+       String           filename;
+       IWorkbench       workbench;
+       IWorkbenchWindow window;
+    IWorkbenchPage   page;
+       IPath            path;
+       IFile            eclipseFile;
+
+    filename  = (String) element;
+    workbench = PlatformUI.getWorkbench ();
+    window    = workbench.getWorkbenchWindows ()[0];
+    page      = window.getActivePage ();
+    path      = new Path (filename);                                // Create an IPath object of the absolute local/client side file name
+
+    // If the file exists in the workspace, open it
+    eclipseFile = PHPeclipsePlugin.getWorkspace().getRoot().getFileForLocation (path);
+
+    //    IFile eclipseFile = PHPeclipsePlugin.getWorkspace().getRoot().getFileForLocation(new Path(filename));
+//    if (eclipseFile == null) {
+//      filename = this.getAbsoluteWorkingDirectory() + "/" + filename;
+//      eclipseFile = PHPeclipsePlugin.getWorkspace().getRoot().getFileForLocation(new Path(filename));
+//      if (eclipseFile == null) {
+//        PHPeclipsePlugin.log(IStatus.INFO, "Could not find file \"" + element + "\".");
+//        return null;
+//      }
+//    } else
+
+    if (eclipseFile == null || !eclipseFile.exists ()) {
+      //               Otherwise open the stream directly
+         //
+      if (page == null) {
+        PHPeclipsePlugin.log(IStatus.INFO, "Could not find file \"" + element + "\".");
+        return null;
+      }
+
+      FileStorage storage = new FileStorage (path);
+      storage.setReadOnly ();
+
+      //      IEditorRegistry registry = workbench.getEditorRegistry();
+      //      IEditorDescriptor desc = registry.getDefaultEditor(filename);
+      //      if (desc == null) {
+      //        desc = registry.getDefaultEditor();
+      //      }
+      return new ExternalEditorInput(storage);
+    }
+
+    return new FileEditorInput (eclipseFile);
+  }
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/ui/text/template/DeclarationProposal.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/ui/text/template/DeclarationProposal.java
new file mode 100644 (file)
index 0000000..d2edd51
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpdt.internal.ui.text.template;
+
+import net.sourceforge.phpdt.internal.corext.phpdoc.PHPDocUtil;
+import net.sourceforge.phpdt.internal.corext.template.TemplateMessages;
+import net.sourceforge.phpdt.internal.corext.template.php.JavaContext;
+import net.sourceforge.phpdt.internal.ui.PHPUiImages;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
+import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.builder.PHPIdentifierLocation;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.ContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.swt.graphics.Image;
+
+// import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionManager;
+// import net.sourceforge.phpdt.internal.ui.text.link.LinkedPositionUI;
+// import net.sourceforge.phpdt.internal.ui.util.ExceptionHandler;
+
+/**
+ * A PHP identifier proposal.
+ */
+public class DeclarationProposal extends AbstractProposal { // implements
+       // IPHPCompletionProposal
+       // {
+       private IProject fProject;
+
+       private final TemplateContext fContext;
+
+       private final PHPIdentifierLocation fLocation;
+
+       String fInfo;
+
+       // private TemplateBuffer fTemplateBuffer;
+       // private String fOldText;
+       // private final Image fImage_fun;
+       // private final Image fImage_var;
+       private final IRegion fRegion;
+
+       // private IRegion fSelectedRegion; // initialized by apply()
+
+       private final String fIdentifierName;
+
+       // private final ITextViewer fViewer;
+
+       /**
+        * Creates a template proposal with a template and its context.
+        * 
+        * @param template
+        *            the template
+        * @param context
+        *            the context in which the template was requested.
+        * @param image
+        *            the icon of the proposal.
+        */
+       public DeclarationProposal(IProject project, String identifierName,
+                       PHPIdentifierLocation location, TemplateContext context,
+                       IRegion region, ITextViewer viewer) {
+               super(viewer);
+               // Image image_fun,
+               // Image image_var) {
+               fProject = project;
+               fIdentifierName = identifierName;
+               fLocation = location;
+               fContext = context;
+               fRegion = region;
+               fInfo = null;
+       }
+
+       /*
+        * @see ICompletionProposal#apply(IDocument)
+        */
+       public void apply(IDocument document) {
+               try {
+                       // if (fTemplateBuffer == null)
+                       // fTemplateBuffer= fContext.evaluate(fTemplate);
+
+                       int start = fRegion.getOffset();
+                       int end = fRegion.getOffset() + fRegion.getLength();
+
+                       switch (fLocation.getType()) {
+                       case PHPIdentifierLocation.FUNCTION:
+                               document.replace(start, end - start, fIdentifierName + "()");
+                               break;
+                       case PHPIdentifierLocation.CONSTRUCTOR:
+                               document.replace(start, end - start, fIdentifierName + "()");
+                               break;
+                       case PHPIdentifierLocation.METHOD:
+                               document.replace(start, end - start, fIdentifierName + "()");
+                               break;
+
+                       default:
+                               document.replace(start, end - start, fIdentifierName);
+                       }
+
+                       // translate positions
+                       LinkedPositionManager manager = new LinkedPositionManager(document);
+                       // TemplatePosition[] variables= fTemplateBuffer.getVariables();
+                       // for (int i= 0; i != variables.length; i++) {
+                       // TemplatePosition variable= variables[i];
+                       //
+                       // if (variable.isResolved())
+                       // continue;
+                       //
+                       // int[] offsets= variable.getOffsets();
+                       // int length= variable.getLength();
+                       //
+                       // for (int j= 0; j != offsets.length; j++)
+                       // manager.addPosition(offsets[j] + start, length);
+                       // }
+
+                       LinkedPositionUI editor = new LinkedPositionUI(fViewer, manager);
+                       switch (fLocation.getType()) {
+                       case PHPIdentifierLocation.FUNCTION:
+                               editor
+                                               .setFinalCaretOffset(fIdentifierName.length() + start
+                                                               + 1);
+                               break;
+                       case PHPIdentifierLocation.CONSTRUCTOR:
+                               editor
+                                               .setFinalCaretOffset(fIdentifierName.length() + start
+                                                               + 1);
+                               break;
+                       case PHPIdentifierLocation.METHOD:
+                               editor
+                                               .setFinalCaretOffset(fIdentifierName.length() + start
+                                                               + 1);
+                               break;
+
+                       default:
+                               editor.setFinalCaretOffset(fIdentifierName.length() + start);
+                       }
+                       editor.enter();
+
+                       fSelectedRegion = editor.getSelectedRegion();
+
+               } catch (BadLocationException e) {
+                       PHPeclipsePlugin.log(e);
+                       openErrorDialog(e);
+
+               }
+               // catch (CoreException e) {
+               // handleException(e);
+               // }
+       }
+
+       /*
+        * @see ICompletionProposal#getAdditionalProposalInfo()
+        */
+       public String getAdditionalProposalInfo() {
+               if (fInfo == null) {
+                       fInfo = computeProposalInfo();
+               }
+               return fInfo;
+       }
+
+       private String computeProposalInfo() {
+               StringBuffer hoverInfoBuffer = new StringBuffer();
+               // String workspaceLocation =
+               // PHPeclipsePlugin.getWorkspace().getRoot().getLocation().toString();
+               String workspaceLocation;
+               if (fProject != null) {
+                       workspaceLocation = fProject.getLocation().toString() + '/';
+               } else {
+                       // should never happen?
+                       workspaceLocation = PHPeclipsePlugin.getWorkspace().getRoot()
+                                       .getLocation().toString();
+               }
+               String filename = workspaceLocation + fLocation.getFilename();
+               PHPDocUtil.appendPHPDoc(hoverInfoBuffer, filename, fLocation);
+               return hoverInfoBuffer.toString();
+       }
+
+       public IContextInformation getContextInformation() {
+               if (fContextInfo == null) {
+                       if (fLocation != null) {
+                               fInfo = fLocation.getUsage();
+                               if (fInfo != null) {
+                                       // extract the parameter context information for the
+                                       // function:
+                                       int i0 = fInfo.indexOf('(');
+                                       int newline = fInfo.indexOf('\n');
+                                       if (i0 >= 0 && (i0 < newline || newline < 0)) {
+                                               int i1 = fInfo.indexOf(')', i0 + 1);
+                                               if (i1 > 0) {
+
+                                                       fContextInfo = new ContextInformation(null, fInfo
+                                                                       .substring(i0 + 1, i1));
+                                               } else {
+                                                       fContextInfo = new ContextInformation(null, fInfo);
+                                               }
+                                       } else {
+                                               fContextInfo = new ContextInformation(null, fInfo);
+                                       }
+                               }
+                       }
+               }
+               return fContextInfo;
+       }
+
+       /*
+        * @see ICompletionProposal#getDisplayString()
+        */
+       public String getDisplayString() {
+               String workspaceLocation;
+               if (fProject != null) {
+                       workspaceLocation = fProject.getName().toString() + '/';
+               } else {
+                       // should never happen?
+                       workspaceLocation = PHPeclipsePlugin.getWorkspace().getRoot()
+                                       .getLocation().toString();
+               }
+               String filename = workspaceLocation + fLocation.getFilename();
+               String usage = PHPDocUtil.getUsage(filename, fLocation);
+               String result = fIdentifierName
+                               + TemplateMessages.getString("TemplateProposal.delimiter");
+               if (usage.length() > 0) {
+                       result += usage
+                                       + TemplateMessages.getString("TemplateProposal.delimiter");
+               }
+               result += filename;
+               return result;
+       }
+
+       /*
+        * @see ICompletionProposal#getImage()
+        */
+       public Image getImage() {
+               switch (fLocation.getType()) {
+               case PHPIdentifierLocation.FUNCTION:
+                       return PHPUiImages.get(PHPUiImages.IMG_FUN);
+               case PHPIdentifierLocation.CLASS:
+                       return PHPUiImages.get(PHPUiImages.IMG_CLASS);
+               case PHPIdentifierLocation.CONSTRUCTOR:
+                       return PHPUiImages.get(PHPUiImages.IMG_CLASS);
+               case PHPIdentifierLocation.METHOD:
+                       return PHPUiImages.get(PHPUiImages.IMG_FUN);
+               case PHPIdentifierLocation.DEFINE:
+                       return PHPUiImages.get(PHPUiImages.IMG_DEFINE);
+               case PHPIdentifierLocation.VARIABLE:
+                       return PHPUiImages.get(PHPUiImages.IMG_VAR);
+               case PHPIdentifierLocation.GLOBAL_VARIABLE:
+                       return PHPUiImages.get(PHPUiImages.IMG_VAR);
+               }
+               return PHPUiImages.get(PHPUiImages.IMG_FUN);
+       }
+
+       /*
+        * @see IJavaCompletionProposal#getRelevance()
+        */
+       public int getRelevance() {
+
+               if (fContext instanceof JavaContext) {
+                       JavaContext context = (JavaContext) fContext;
+                       switch (context.getCharacterBeforeStart()) {
+                       // high relevance after whitespace
+                       case ' ':
+                       case '\r':
+                       case '\n':
+                       case '\t':
+                               return 80;
+                       case '>': // ->
+                       case ':': // ::
+                               return 85;
+                       default:
+                               return 0;
+                       }
+               } else {
+                       return 80;
+               }
+       }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/ui/util/PHPFileUtil.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/internal/ui/util/PHPFileUtil.java
new file mode 100644 (file)
index 0000000..d17c8e4
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Created on 09.08.2003
+ *
+ */
+package net.sourceforge.phpdt.internal.ui.util;
+
+import java.io.File;
+import java.util.List;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.overlaypages.ProjectPrefUtil;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorRegistry;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+
+public class PHPFileUtil {
+       // private static String[] PHP_EXTENSIONS = null;
+
+       public final static String[] SMARTY_EXTENSIONS = { "tpl" };
+
+       public static boolean isPHPFile(IFile file) {
+               // String extension = file.getFileExtension();
+               return isPHPFileName(file.getLocation().toString());
+       }
+
+       // public final static String getFileExtension(String name) {
+       // int index = name.lastIndexOf('.');
+       // if (index == -1)
+       // return null;
+       // if (index == (name.length() - 1))
+       // return null; //$NON-NLS-1$
+       // return name.substring(index + 1);
+       // }
+
+       /**
+        * Returns true iff str.toLowerCase().endsWith(".php") implementation is not
+        * creating extra strings.
+        */
+       public final static boolean isPHPFileName(String name) {
+
+               // avoid handling a file without base name, e.g. ".php", which is a
+               // valid
+               // Eclipse resource name
+               File file = new File(name);
+               if (file.getName().startsWith(".")) {
+                       return false;
+               }
+               IWorkbench workbench = PlatformUI.getWorkbench();
+               IEditorRegistry registry = workbench.getEditorRegistry();
+               IEditorDescriptor[] descriptors = registry.getEditors(name);
+
+               for (int i = 0; i < descriptors.length; i++) {
+                       if (descriptors[i].getId().equals(PHPeclipsePlugin.EDITOR_ID)) {
+                               return true;
+                       }
+               }
+               // String extension = getFileExtension(name);
+               // if (extension == null) {
+               // return false;
+               // }
+               // extension = extension.toLowerCase();
+               // PHP_EXTENSIONS = getExtensions();
+               // if (PHP_EXTENSIONS == null) {
+               // return false;
+               // }
+               // for (int i = 0; i < PHP_EXTENSIONS.length; i++) {
+               // if (extension.equals(PHP_EXTENSIONS[i])) {
+               // return true;
+               // }
+               // }
+               return false;
+       }
+
+       /**
+        * Returns true iff the file extension is a valid PHP Unit name
+        * implementation is not creating extra strings.
+        */
+       public final static boolean isValidPHPUnitName(String filename) {
+               return PHPFileUtil.isPHPFileName(filename);
+       }
+
+       /**
+        * @return Returns the PHP extensions.
+        */
+       // public static String[] getExtensions() {
+       // if (PHP_EXTENSIONS == null) {
+       // ArrayList list = new ArrayList();
+       // final IPreferenceStore store =
+       // PHPeclipsePlugin.getDefault().getPreferenceStore();
+       // String extensions =
+       // store.getString(PHPeclipsePlugin.PHP_EXTENSION_PREFS);
+       // extensions = extensions.trim();
+       // if (extensions.length() != 0) {
+       // StringTokenizer tokenizer = new StringTokenizer(extensions, " ,;:/-|");
+       // String token;
+       // while (tokenizer.hasMoreTokens()) {
+       // token = tokenizer.nextToken();
+       // if (token != null && token.length() >= 1) {
+       // list.add(token);
+       // }
+       // }
+       // if (list.size() != 0) {
+       // PHP_EXTENSIONS = new String[list.size()];
+       // for (int i = 0; i < list.size(); i++) {
+       // PHP_EXTENSIONS[i] = (String) list.get(i);
+       // }
+       // }
+       // }
+       // }
+       // return PHP_EXTENSIONS;
+       // }
+       /**
+        * @param php_extensions
+        *            The PHP extensions to set.
+        */
+       // public static void setExtensions(String[] php_extensions) {
+       // PHP_EXTENSIONS = php_extensions;
+       // }
+       /**
+        * Creata the file for the given absolute file path
+        * 
+        * @param absoluteFilePath
+        * @param project
+        * @return the file for the given absolute file path or <code>null</code>
+        *         if no existing file can be found
+        */
+       public static IFile createFile(IPath absoluteFilePath, IProject project) {
+               if (absoluteFilePath == null || project == null) {
+                       return null;
+               }
+
+               String projectPath = project.getLocation().toString();
+               String filePath = absoluteFilePath.toString().substring(
+                               projectPath.length() + 1);
+               return project.getFile(filePath);
+
+       }
+
+       /**
+        * Determine the path of an include name string
+        * 
+        * @param includeNameString
+        * @param resource
+        * @param project
+        * @return the path for the given include filename or <code>null</code> if
+        *         no existing file can be found
+        */
+       public static IPath determineFilePath(String includeNameString,
+                       IResource resource, IProject project) {
+               IPath documentRootPath = ProjectPrefUtil.getDocumentRoot(project);
+               IPath resourcePath = resource.getProjectRelativePath();
+
+               File file = null;
+               IPath path = null;
+               path = documentRootPath.append(includeNameString);
+               file = path.toFile();
+               if (file.exists()) {
+                       return path;
+               }
+
+               if (includeNameString.startsWith("../")) {
+                       path = project.getLocation().append(
+                                       resourcePath.removeLastSegments(1));
+                       path = path.append(includeNameString);
+                       file = path.toFile();
+                       if (file.exists()) {
+                               return path;
+                       }
+               }
+
+               // includeNameString contains no path separator
+               path = project.getLocation().append(resourcePath.removeLastSegments(1));
+               path = path.append(includeNameString);
+               file = path.toFile();
+               if (file.exists()) {
+                       return path;
+               }
+               // }
+
+               List includePaths = ProjectPrefUtil.getIncludePaths(project);
+               if (includePaths.size() > 0) {
+                       for (int i = 0; i < includePaths.size(); i++) {
+                               path = new Path(includePaths.get(i).toString())
+                                               .append(includeNameString);
+                               file = path.toFile();
+                               if (file.exists()) {
+                                       return path;
+                               }
+                       }
+               }
+               return null;
+       }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/ltk/core/RenameIdentifierDelegate.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/ltk/core/RenameIdentifierDelegate.java
new file mode 100644 (file)
index 0000000..beaf423
--- /dev/null
@@ -0,0 +1,386 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+// modified for phpeclipse.de project by axelcl
+package net.sourceforge.phpdt.ltk.core;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ltk.core.refactoring.Change;
+import org.eclipse.ltk.core.refactoring.CompositeChange;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.ltk.core.refactoring.TextFileChange;
+import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
+import org.eclipse.ltk.core.refactoring.participants.IConditionChecker;
+import org.eclipse.ltk.core.refactoring.participants.ValidateEditChecker;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+
+/**
+ * <p>
+ * delegate object that contains the logic used by the processor.
+ * </p>
+ * 
+ */
+public class RenameIdentifierDelegate {
+
+       // private static final String EXT_PROPERTIES = "properties"; //$NON-NLS-1$
+
+       protected final RenameIdentifierInfo info;
+
+       // PHP file with the identifier to rename -> offset of the key
+       protected final Map phpFiles;
+
+       public RenameIdentifierDelegate(final RenameIdentifierInfo info) {
+               this.info = info;
+               phpFiles = new HashMap();
+       }
+
+       RefactoringStatus checkInitialConditions() {
+               RefactoringStatus result = new RefactoringStatus();
+               IFile sourceFile = info.getSourceFile();
+               if (sourceFile == null || !sourceFile.exists()) {
+                       result.addFatalError(CoreTexts.renamePropertyDelegate_noSourceFile);
+               } else if (info.getSourceFile().isReadOnly()) {
+                       result.addFatalError(CoreTexts.renamePropertyDelegate_roFile);
+               } else if (isEmpty(info.getOldName())) {
+                       // || !isPropertyKey( info.getSourceFile(), info.getOldName() ) ) {
+                       result.addFatalError(CoreTexts.renamePropertyDelegate_noPHPKey);
+               }
+               return result;
+       }
+
+       RefactoringStatus checkFinalConditions(final IProgressMonitor pm,
+                       final CheckConditionsContext ctxt) {
+               RefactoringStatus result = new RefactoringStatus();
+               pm.beginTask(CoreTexts.renamePropertyDelegate_checking, 100);
+               // do something long-running here: traverse the entire project (or even
+               // workspace) to look for all *.properties files with the same bundle
+               // base name
+               IContainer rootContainer;
+               ArrayList phpProjects = new ArrayList();
+               IProject project;
+               if (info.isAllProjects()) {
+                       rootContainer = ResourcesPlugin.getWorkspace().getRoot();
+                       IResource[] members;
+                       try {
+                               members = rootContainer.members();
+                               for (int i = 0; i < members.length; i++) {
+                                       if (members[i] instanceof IProject) {
+                                               project = (IProject) members[i];
+                                               try {
+                                                       if (project
+                                                                       .isNatureEnabled(PHPeclipsePlugin.PHP_NATURE_ID)) {
+                                                               search(project, result);
+                                                       }
+                                               } catch (CoreException e) {
+                                                       String msg = "Project: "
+                                                                       + project.getLocation().toOSString()
+                                                                       + " CoreException " + e.getMessage();
+                                                       result.addError(msg);
+                                               } catch (Exception e) {
+                                                       String msg = "Project: "
+                                                                       + project.getLocation().toOSString()
+                                                                       + " Exception " + e.getMessage();
+                                                       result.addError(msg);
+                                               }
+                                       }
+                               }
+                       } catch (CoreException e) {
+                               String msg = "Workspace: "
+                                               + rootContainer.getLocation().toOSString()
+                                               + " CoreException " + e.getMessage();
+                               result.addError(msg);
+                       }
+               } else {
+                       project = info.getSourceFile().getProject();
+                       try {
+                               if (project.isNatureEnabled(PHPeclipsePlugin.PHP_NATURE_ID)) {
+                                       search(project, result);
+                               }
+                       } catch (CoreException e) {
+                               String msg = "Project: " + project.getLocation().toOSString()
+                                               + " CoreException " + e.getMessage();
+                               result.addError(msg);
+                       } catch (Exception e) {
+                               String msg = "Project: " + project.getLocation().toOSString()
+                                               + " Exception " + e.getMessage();
+                               result.addError(msg);
+                       }
+               }
+
+               pm.worked(50);
+
+               if (ctxt != null) {
+                       IFile[] files = new IFile[phpFiles.size()];
+                       phpFiles.keySet().toArray(files);
+                       IConditionChecker checker = ctxt
+                                       .getChecker(ValidateEditChecker.class);
+                       ValidateEditChecker editChecker = (ValidateEditChecker) checker;
+                       editChecker.addFiles(files);
+               }
+               pm.done();
+               return result;
+       }
+
+       protected void createChange(final IProgressMonitor pm,
+                       final CompositeChange rootChange) {
+               try {
+                       pm.beginTask(CoreTexts.renamePropertyDelegate_collectingChanges,
+                                       100);
+                       // all files in the same bundle
+                       if (info.isUpdateProject()) {
+                               rootChange.addAll(createChangesForContainer(pm));
+                       }
+               } finally {
+                       pm.done();
+               }
+       }
+
+       // helping methods
+       // ////////////////
+
+       // private Change createRenameChange() {
+       // // create a change object for the file that contains the property the
+       // // user has selected to rename
+       // IFile file = info.getSourceFile();
+       // TextFileChange result = new TextFileChange(file.getName(), file);
+       // // a file change contains a tree of edits, first add the root of them
+       // MultiTextEdit fileChangeRootEdit = new MultiTextEdit();
+       // result.setEdit(fileChangeRootEdit);
+       //
+       // // edit object for the text replacement in the file, this is the only
+       // child
+       // ReplaceEdit edit = new ReplaceEdit(info.getOffset(),
+       // info.getOldName().length(), info.getNewName());
+       // fileChangeRootEdit.addChild(edit);
+       // return result;
+       // }
+
+       protected Change[] createChangesForContainer(final IProgressMonitor pm) {
+               List result = new ArrayList();
+               Iterator it = phpFiles.keySet().iterator();
+               int numberOfFiles = phpFiles.size();
+               double percent = 100 / numberOfFiles;
+               int work = 0;
+               int indx = 0;
+               while (it.hasNext()) {
+                       IFile file = (IFile) it.next();
+                       List list = getKeyOffsets(file);
+                       if (list != null && list.size() > 0) {
+                               TextFileChange tfc = new TextFileChange(file.getName(), file);
+                               MultiTextEdit fileChangeRootEdit = new MultiTextEdit();
+                               tfc.setEdit(fileChangeRootEdit);
+
+                               // edit object for the text replacement in the file, there could
+                               // be
+                               // multiple childs
+                               ReplaceEdit edit;
+                               for (int i = 0; i < list.size(); i++) {
+                                       edit = new ReplaceEdit(((Integer) list.get(i)).intValue(),
+                                                       info.getOldName().length(), info.getNewName());
+                                       fileChangeRootEdit.addChild(edit);
+                               }
+                               result.add(tfc);
+                       }
+                       work = new Double((++indx) * percent).intValue();
+                       pm.worked(work);
+               }
+               return (Change[]) result.toArray(new Change[result.size()]);
+       }
+
+       protected boolean isEmpty(final String candidate) {
+               return candidate == null || candidate.trim().length() == 0;
+       }
+
+       // private boolean isPropertyKey( final IFile file, final String candidate )
+       // {
+       // boolean result = false;
+       // try {
+       // Properties props = new Properties();
+       // props.load( file.getContents() );
+       // result = props.containsKey( candidate );
+       // } catch( Exception ex ) {
+       // // ignore this, we just assume this is not a favourable situation
+       // ex.printStackTrace();
+       // }
+       // return result;
+       // }
+
+       // // whether the file is a PHP file with the same base name as the
+       // // one we refactor and contains the key that interests us
+       // private boolean isToRefactor(final IFile file) {
+       // return PHPFileUtil.isPHPFile(file);
+       // // && !file.equals( info.getSourceFile() )
+       // // && isPropertyKey( file, info.getOldName() );
+       // }
+
+       // private String getBundleBaseName() {
+       // String result = info.getSourceFile().getName();
+       // int underscoreIndex = result.indexOf( '_' );
+       // if( underscoreIndex != -1 ) {
+       // result = result.substring( 0, underscoreIndex );
+       // } else {
+       // int index = result.indexOf( EXT_PROPERTIES ) - 1;
+       // result = result.substring( 0, index );
+       // }
+       // return result;
+       // }
+
+       private void search(final IContainer rootContainer,
+                       final RefactoringStatus status) {
+               try {
+                       IResource[] members = rootContainer.members();
+                       for (int i = 0; i < members.length; i++) {
+                               if (members[i] instanceof IContainer) {
+                                       search((IContainer) members[i], status);
+                               } else {
+                                       IFile file = (IFile) members[i];
+                                       handleFile(file, status);
+                               }
+                       }
+               } catch (final CoreException cex) {
+                       status.addFatalError(cex.getMessage());
+               }
+       }
+
+       private void handleFile(final IFile file, final RefactoringStatus status) {
+               if (PHPFileUtil.isPHPFile(file)) {
+                       determineKeyOffsets(file, status);
+                       // if (keyOffsets.size() > 0) {
+                       // Integer offset = new Integer(keyOffsets);
+                       // phpFiles.put(file, offset);
+                       // }
+               }
+       }
+
+       protected List getKeyOffsets(final IFile file) {
+               return (List) phpFiles.get(file);
+       }
+
+       // finds the offsets of the identifier to rename
+       // usually, this would be the job of a proper parser;
+       // using a primitive brute-force approach here
+       private void determineKeyOffsets(final IFile file,
+                       final RefactoringStatus status) {
+               ArrayList matches = new ArrayList();
+               try {
+                       String content = readFileContent(file, status);
+                       Scanner scanner = new Scanner(true, false);
+                       scanner.setSource(content.toCharArray());
+                       scanner.setPHPMode(false);
+                       char[] word = info.getOldName().toCharArray();
+
+                       int fToken = ITerminalSymbols.TokenNameEOF;
+                       try {
+                               fToken = scanner.getNextToken();
+                               while (fToken != ITerminalSymbols.TokenNameEOF) {
+                                       if (fToken == ITerminalSymbols.TokenNameVariable
+                                                       || fToken == ITerminalSymbols.TokenNameIdentifier) {
+                                               if (scanner.equalsCurrentTokenSource(word)) {
+                                                       matches.add(new Integer(scanner
+                                                                       .getCurrentTokenStartPosition()));
+                                               }
+                                       }
+                                       fToken = scanner.getNextToken();
+                               }
+
+                       } catch (InvalidInputException e) {
+                               String msg = "File: " + file.getLocation().toOSString()
+                                               + " InvalidInputException " + e.getMessage();
+                               status.addError(msg);
+                       } catch (SyntaxError e) {
+                               String msg = "File: " + file.getLocation().toOSString()
+                                               + " SyntaxError " + e.getMessage();
+                               status.addError(msg);
+                       }
+
+               } catch (Exception e) {
+                       String msg = "File: " + file.getLocation().toOSString()
+                                       + " Exception " + e.getMessage();
+                       status.addError(msg);
+               }
+               if (matches.size() > 0) {
+                       phpFiles.put(file, matches);
+               }
+
+               // int result = -1;
+               // int candidateIndex = content.indexOf(info.getOldName());
+               // result = candidateIndex;
+               // while( result == -1 && candidateIndex != -1 ) {
+               // if( isKeyOccurrence( content, candidateIndex ) ) {
+               // result = candidateIndex;
+               // }
+               // }
+               // if( result == -1 ) {
+               // // still nothing found, we add a warning to the status
+               // // (we have checked the file contains the property, so that we can't
+               // // determine it's offset is probably because of the rough way
+               // employed
+               // // here to find it)
+               // String msg = CoreTexts.renamePropertyDelegate_propNotFound
+               // + file.getLocation().toOSString();
+               // status.addWarning( msg );
+               // }
+               // return result;
+       }
+
+       private String readFileContent(final IFile file,
+                       final RefactoringStatus refStatus) {
+               String result = null;
+               try {
+                       InputStream is = file.getContents();
+                       byte[] buf = new byte[1024];
+                       ByteArrayOutputStream bos = new ByteArrayOutputStream();
+                       int len = is.read(buf);
+                       while (len > 0) {
+                               bos.write(buf, 0, len);
+                               len = is.read(buf);
+                       }
+                       is.close();
+                       result = new String(bos.toByteArray());
+               } catch (Exception ex) {
+                       String msg = ex.toString();
+                       refStatus.addFatalError(msg);
+                       String pluginId = PHPeclipsePlugin.getPluginId();
+                       IStatus status = new Status(IStatus.ERROR, pluginId, 0, msg, ex);
+                       PHPeclipsePlugin.getDefault().getLog().log(status);
+               }
+               return result;
+       }
+
+       // we check only that there is a separator before the next line break (this
+       // is not sufficient, the whole thing may be in a comment etc. ...)
+       // private boolean isKeyOccurrence( final String content,
+       // final int candidateIndex ) {
+       // int index = candidateIndex + info.getOldName().length();
+       // // skip whitespace
+       // while( content.charAt( index ) == ' ' || content.charAt( index ) == '\t'
+       // )
+       // {
+       // index++;
+       // }
+       // return content.charAt( index ) == '=' || content.charAt( index ) == ':';
+       // }
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/ltk/core/RenameLocalVariableDelegate.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpdt/ltk/core/RenameLocalVariableDelegate.java
new file mode 100644 (file)
index 0000000..b61f6a4
--- /dev/null
@@ -0,0 +1,262 @@
+// Copyright (c) 2005 by Leif Frenzel. All rights reserved.
+// See http://leiffrenzel.de
+// modified for phpeclipse.de project by axelcl
+package net.sourceforge.phpdt.ltk.core;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.core.ISourceRange;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
+import net.sourceforge.phpdt.internal.core.SourceMethod;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ltk.core.refactoring.CompositeChange;
+import org.eclipse.ltk.core.refactoring.RefactoringStatus;
+import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
+import org.eclipse.ltk.core.refactoring.participants.IConditionChecker;
+import org.eclipse.ltk.core.refactoring.participants.ValidateEditChecker;
+
+/**
+ * <p>
+ * delegate object that contains the logic used by the processor.
+ * </p>
+ * 
+ */
+public class RenameLocalVariableDelegate extends RenameIdentifierDelegate {
+
+       public RenameLocalVariableDelegate(final RenameIdentifierInfo info) {
+               super(info);
+       }
+
+       RefactoringStatus checkInitialConditions() {
+               RefactoringStatus result = new RefactoringStatus();
+               IFile sourceFile = info.getSourceFile();
+               if (sourceFile == null || !sourceFile.exists()) {
+                       result.addFatalError(CoreTexts.renamePropertyDelegate_noSourceFile);
+               } else if (info.getSourceFile().isReadOnly()) {
+                       result.addFatalError(CoreTexts.renamePropertyDelegate_roFile);
+               } else if (isEmpty(info.getOldName())) {
+                       // || !isPropertyKey( info.getSourceFile(), info.getOldName() ) ) {
+                       result.addFatalError(CoreTexts.renamePropertyDelegate_noPHPKey);
+               }
+               return result;
+       }
+
+       RefactoringStatus checkFinalConditions(final IProgressMonitor pm,
+                       final CheckConditionsContext ctxt) {
+               RefactoringStatus result = new RefactoringStatus();
+               pm.beginTask(CoreTexts.renamePropertyDelegate_checking, 100);
+               // do something long-running here: traverse the entire project (or even
+               // workspace) to look for all *.p files with the same bundle
+               // base name
+               IFile file = info.getSourceFile();
+               IProject project = file.getProject();
+               try {
+                       SourceMethod method = info.getMethod();
+                       ISourceRange range = method.getSourceRange();
+                       if (project.isNatureEnabled(PHPeclipsePlugin.PHP_NATURE_ID)) {
+                               determineMethodOffsets(file, range.getOffset(), range
+                                               .getLength(), result);
+                       }
+               } catch (CoreException e) {
+                       String msg = "Project: " + project.getLocation().toOSString()
+                                       + " CoreException " + e.getMessage();
+                       result.addError(msg);
+               } catch (Exception e) {
+                       String msg = "Project: " + project.getLocation().toOSString()
+                                       + " Exception " + e.getMessage();
+                       result.addError(msg);
+               }
+
+               pm.worked(50);
+
+               if (ctxt != null) {
+                       IFile[] files = new IFile[phpFiles.size()];
+                       phpFiles.keySet().toArray(files);
+                       IConditionChecker checker = ctxt
+                                       .getChecker(ValidateEditChecker.class);
+                       ValidateEditChecker editChecker = (ValidateEditChecker) checker;
+                       editChecker.addFiles(files);
+               }
+               pm.done();
+               return result;
+       }
+
+       protected void createChange(final IProgressMonitor pm,
+                       final CompositeChange rootChange) {
+               try {
+                       pm.beginTask(CoreTexts.renamePropertyDelegate_collectingChanges,
+                                       100);
+                       // all files in the same bundle
+                       rootChange.addAll(createChangesForContainer(pm));
+               } finally {
+                       pm.done();
+               }
+       }
+
+       private void determineMethodOffsets(final IFile file, int offset,
+                       int length, final RefactoringStatus status) {
+               ArrayList matches = new ArrayList();
+               try {
+                       String content = readFileContent(file, status);
+
+                       //
+                       // Find a PHPdoc directly before the method
+                       //
+                       Scanner firstScanner = new Scanner(true, false);
+                       firstScanner.setSource(content.toCharArray());
+                       int fToken = ITerminalSymbols.TokenNameEOF;
+                       int start = 0;
+                       int phpdocStart = -1;
+                       try {
+                               fToken = firstScanner.getNextToken();
+                               while (fToken != ITerminalSymbols.TokenNameEOF
+                                               && start < offset) {
+                                       if (fToken == ITerminalSymbols.TokenNameCOMMENT_PHPDOC) {
+                                               phpdocStart = firstScanner
+                                                               .getCurrentTokenStartPosition();
+                                       } else {
+                                               phpdocStart = -1;
+                                       }
+                                       fToken = firstScanner.getNextToken();
+                                       start = firstScanner.getCurrentTokenStartPosition();
+                               }
+
+                       } catch (InvalidInputException e) {
+                               String msg = "File: " + file.getLocation().toOSString()
+                                               + " InvalidInputException " + e.getMessage();
+                               status.addError(msg);
+                       } catch (SyntaxError e) {
+                               String msg = "File: " + file.getLocation().toOSString()
+                                               + " SyntaxError " + e.getMessage();
+                               status.addError(msg);
+                       }
+
+                       //
+                       // Find matches for the word in the PHPdoc+method declaration
+                       //
+                       if (phpdocStart >= 0 && phpdocStart < offset) {
+                               length += offset - phpdocStart;
+                               offset = phpdocStart;
+                       }
+                       String methodString = content.substring(offset, offset + length);
+                       Scanner secondScanner = new Scanner(true, false);
+                       secondScanner.setSource(methodString.toCharArray());
+                       secondScanner.setPHPMode(true);
+                       String wordStr = info.getOldName();
+                       boolean renameDQString = info.isRenameDQString();
+                       boolean renamePHPdoc = info.isRenamePHPdoc();
+                       boolean renameOtherComments = info.isRenameOtherComments();
+                       char[] word = wordStr.toCharArray();
+
+                       fToken = ITerminalSymbols.TokenNameEOF;
+                       // double quoted string
+                       String tokenString;
+                       // double quoted string offset
+                       int tokenOffset;
+                       int index;
+                       try {
+                               fToken = secondScanner.getNextToken();
+                               while (fToken != ITerminalSymbols.TokenNameEOF) {
+                                       if (fToken == ITerminalSymbols.TokenNameVariable) {
+                                               if (secondScanner.equalsCurrentTokenSource(word)) {
+                                                       // the current variable token is equal to the given
+                                                       // word
+                                                       matches.add(new Integer(secondScanner
+                                                                       .getCurrentTokenStartPosition()
+                                                                       + offset));
+                                               }
+                                       } else if (fToken == ITerminalSymbols.TokenNameStringDoubleQuote
+                                                       && renameDQString) {
+                                               // determine the word in double quoted strings:
+                                               tokenString = new String(secondScanner
+                                                               .getCurrentTokenSource());
+                                               tokenOffset = secondScanner
+                                                               .getCurrentTokenStartPosition();
+                                               index = -1;
+                                               while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
+                                                       matches.add(new Integer(offset + tokenOffset
+                                                                       + index));
+                                               }
+                                       } else if (fToken == ITerminalSymbols.TokenNameCOMMENT_PHPDOC
+                                                       && renamePHPdoc) {
+                                               tokenString = new String(secondScanner
+                                                               .getCurrentTokenSource());
+                                               tokenOffset = secondScanner
+                                                               .getCurrentTokenStartPosition();
+                                               index = -1;
+                                               while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
+                                                       matches.add(new Integer(offset + tokenOffset
+                                                                       + index));
+                                               }
+                                       } else if ((fToken == ITerminalSymbols.TokenNameCOMMENT_BLOCK || fToken == ITerminalSymbols.TokenNameCOMMENT_LINE)
+                                                       && renameOtherComments) {
+                                               tokenString = new String(secondScanner
+                                                               .getCurrentTokenSource());
+                                               tokenOffset = secondScanner
+                                                               .getCurrentTokenStartPosition();
+                                               index = -1;
+                                               while ((index = tokenString.indexOf(wordStr, index + 1)) >= 0) {
+                                                       matches.add(new Integer(offset + tokenOffset
+                                                                       + index));
+                                               }
+                                       }
+                                       fToken = secondScanner.getNextToken();
+                               }
+
+                       } catch (InvalidInputException e) {
+                               String msg = "File: " + file.getLocation().toOSString()
+                                               + " InvalidInputException " + e.getMessage();
+                               status.addError(msg);
+                       } catch (SyntaxError e) {
+                               String msg = "File: " + file.getLocation().toOSString()
+                                               + " SyntaxError " + e.getMessage();
+                               status.addError(msg);
+                       }
+
+               } catch (Exception e) {
+                       String msg = "File: " + file.getLocation().toOSString()
+                                       + " Exception " + e.getMessage();
+                       status.addError(msg);
+               }
+               if (matches.size() > 0) {
+                       phpFiles.put(file, matches);
+               }
+       }
+
+       private String readFileContent(final IFile file,
+                       final RefactoringStatus refStatus) {
+               String result = null;
+               try {
+                       InputStream is = file.getContents();
+                       byte[] buf = new byte[1024];
+                       ByteArrayOutputStream bos = new ByteArrayOutputStream();
+                       int len = is.read(buf);
+                       while (len > 0) {
+                               bos.write(buf, 0, len);
+                               len = is.read(buf);
+                       }
+                       is.close();
+                       result = new String(bos.toByteArray());
+               } catch (Exception ex) {
+                       String msg = ex.toString();
+                       refStatus.addFatalError(msg);
+                       String pluginId = PHPeclipsePlugin.getPluginId();
+                       IStatus status = new Status(IStatus.ERROR, pluginId, 0, msg, ex);
+                       PHPeclipsePlugin.getDefault().getLog().log(status);
+               }
+               return result;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/actions/IncludesScanner.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/actions/IncludesScanner.java
new file mode 100644 (file)
index 0000000..bb1c88f
--- /dev/null
@@ -0,0 +1,187 @@
+package net.sourceforge.phpeclipse.actions;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.ui.IFileEditorInput;
+
+public class IncludesScanner implements ITerminalSymbols {
+       // private final PHPOpenAllIncludesEditorAction fOpenAllIncludesAction;
+       private IProject fProject;
+
+       private IFileEditorInput fEditorInput;
+
+       private HashSet fSet;
+
+       public IncludesScanner(IProject project, IFileEditorInput editorInput) {
+               fProject = project;
+               // fOpenAllIncludesAction = action;
+               fEditorInput = editorInput;
+               fSet = new HashSet();
+       }
+
+       /**
+        * Add the information for a given IFile resource
+        * 
+        */
+       public void addFile(IFile fileToParse) {
+
+               try {
+                       if (fileToParse.exists()) {
+                               addInputStream(new BufferedInputStream(fileToParse
+                                               .getContents()), fileToParse.getProjectRelativePath()
+                                               .toString());
+                       }
+               } catch (CoreException e1) {
+                       e1.printStackTrace();
+               }
+       }
+
+       private void addInputStream(InputStream stream, String filePath)
+                       throws CoreException {
+               try {
+                       if (fSet.add(filePath)) { // new entry in set
+                               parseIdentifiers(Util.getInputStreamAsCharArray(stream, -1,
+                                               null));
+                       }
+               } catch (IOException e) {
+                       e.printStackTrace();
+               } finally {
+                       try {
+                               if (stream != null) {
+                                       stream.close();
+                               }
+                       } catch (IOException e) {
+                       }
+               }
+       }
+
+       /**
+        * Get the next token from input
+        */
+       private int getNextToken(Scanner scanner) {
+               int token;
+               try {
+                       token = scanner.getNextToken();
+                       if (Scanner.DEBUG) {
+                               int currentEndPosition = scanner.getCurrentTokenEndPosition();
+                               int currentStartPosition = scanner
+                                               .getCurrentTokenStartPosition();
+                               System.out.print(currentStartPosition + ","
+                                               + currentEndPosition + ": ");
+                               System.out.println(scanner.toStringAction(token));
+                       }
+                       return token;
+               } catch (InvalidInputException e) {
+               }
+               return TokenNameERROR;
+       }
+
+       private void parseIdentifiers(char[] charArray) {
+               char[] ident;
+               IFile file;
+               String identifier;
+               int counter = 0;
+
+               Scanner scanner = new Scanner(false, false, false, false, true, null,
+                               null, true /* taskCaseSensitive */);
+               scanner.setSource(charArray);
+               scanner.setPHPMode(false);
+               int token = getNextToken(scanner);
+               try {
+                       while (token != TokenNameEOF) { // && fToken != TokenNameERROR) {
+                               if (token == TokenNameinclude || token == TokenNameinclude_once
+                                               || token == TokenNamerequire
+                                               || token == TokenNamerequire_once) {
+                                       while (token != TokenNameEOF && token != TokenNameERROR
+                                                       && token != TokenNameSEMICOLON
+                                                       && token != TokenNameRPAREN
+                                                       && token != TokenNameLBRACE
+                                                       && token != TokenNameRBRACE) {
+                                               token = getNextToken(scanner);
+                                               if (token == TokenNameStringDoubleQuote
+                                                               || token == TokenNameStringSingleQuote) {
+                                                       char[] includeName = scanner
+                                                                       .getCurrentStringLiteralSource();
+                                                       try {
+                                                               file = getIncludeFile(new String(includeName));
+                                                               addFile(file);
+                                                       } catch (Exception e) {
+                                                               // ignore
+                                                       }
+                                                       break;
+                                               }
+                                       }
+                               }
+                               token = getNextToken(scanner);
+                       }
+               } catch (SyntaxError e) {
+                       // e.printStackTrace();
+               }
+       }
+
+       private IContainer getWorkingLocation(IFileEditorInput editorInput) {
+               if (editorInput == null || editorInput.getFile() == null) {
+                       return null;
+               }
+               return editorInput.getFile().getParent();
+       }
+
+       public IFile getIncludeFile(String relativeFilename) {
+               IContainer container = getWorkingLocation(fEditorInput);
+               String fullPath = fProject.getLocation().toString();
+               IFile file = null;
+               if (relativeFilename.startsWith("../")) {
+                       Path path = new Path(relativeFilename);
+                       file = container.getFile(path);
+                       return file;
+               }
+               int index = relativeFilename.lastIndexOf('/');
+
+               if (index >= 0) {
+                       Path path = new Path(relativeFilename);
+                       file = fProject.getFile(path);
+                       if (file.exists()) {
+                               return file;
+                       }
+               }
+               Path path = new Path(relativeFilename);
+               file = container.getFile(path);
+
+               return file;
+       }
+
+       /**
+        * Returns a list of includes
+        * 
+        * @return the determined list of includes
+        */
+       public List getList() {
+               ArrayList list = new ArrayList();
+               list.addAll(fSet);
+               return list;
+       }
+
+       /**
+        * @return Returns the set.
+        */
+       public Set getSet() {
+               return fSet;
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/actions/OpenDeclarationEditorAction.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/actions/OpenDeclarationEditorAction.java
new file mode 100644 (file)
index 0000000..6d4e18b
--- /dev/null
@@ -0,0 +1,304 @@
+/***********************************************************************************************************************************
+ * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Common Public License v1.0 which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: www.phpeclipse.de
+ **********************************************************************************************************************************/
+package net.sourceforge.phpeclipse.actions;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
+import net.sourceforge.phpdt.internal.ui.viewsupport.ListContentProvider;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
+import net.sourceforge.phpeclipse.builder.PHPIdentifierLocation;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPWordExtractor;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.dialogs.ListSelectionDialog;
+
+public class OpenDeclarationEditorAction {
+
+       private PHPEditor fEditor;
+
+       private IProject fProject;
+
+       private boolean isIncludeString;
+
+       public OpenDeclarationEditorAction(PHPEditor editor) {
+               fEditor = editor;
+               fProject = null;
+               isIncludeString = false;
+       }
+
+       /**
+        * @param selection
+        */
+       protected void openSelectedElement(ITextSelection selection) {
+               IDocument doc = fEditor.getDocumentProvider().getDocument(
+                               fEditor.getEditorInput());
+               int pos = selection.getOffset();
+               openSelectedPosition(doc, pos);
+       }
+
+       protected void openSelectedPosition(IDocument doc, int position) {
+               IFile f = ((IFileEditorInput) fEditor.getEditorInput()).getFile();
+               fProject = f.getProject();
+               // System.out.println(selection.getText());
+               String identifierOrInclude = getIdentifierOrInclude(doc, position);
+               // System.out.println(word);
+               if (identifierOrInclude != null && !identifierOrInclude.equals("")) {
+                       if (isIncludeString) {
+                               openIncludeFile(identifierOrInclude);
+                       } else {
+                               openIdentifierDeclaration(f, identifierOrInclude);
+                       }
+               }
+       }
+
+       /**
+        * @param filename
+        */
+       private void openIncludeFile(String filename) {
+               if (filename != null && !filename.equals("")) {
+                       try {
+                               IFile currentFile = ((IFileEditorInput) fEditor
+                                               .getEditorInput()).getFile();
+                               IPath path = PHPFileUtil.determineFilePath(filename,
+                                               currentFile, fProject);
+                               if (path != null) {
+                                       IFile file = PHPFileUtil.createFile(path, fProject);
+                                       if (file != null && file.exists()) {
+                                               PHPeclipsePlugin.getDefault().openFileInTextEditor(
+                                                               file.getLocation().toString());
+                                               return;
+                                       }
+                               }
+                       } catch (Exception e) {
+                               // ignore
+                       }
+
+                       try {
+
+                               IdentifierIndexManager indexManager = PHPeclipsePlugin
+                                               .getDefault().getIndexManager(fProject);
+                               // filename = StringUtil.replaceRegExChars(filename);
+                               List list = indexManager.getFileList(filename);
+                               if (list != null && list.size() > 0) {
+                                       // String workspaceLocation =
+                                       // PHPeclipsePlugin.getWorkspace().getRoot().getLocation().toString();
+                                       String workspaceLocation = fProject.getLocation()
+                                                       .toString()
+                                                       + java.io.File.separatorChar;
+
+                                       ListSelectionDialog listSelectionDialog = new ListSelectionDialog(
+                                                       PHPeclipsePlugin.getDefault().getWorkbench()
+                                                                       .getActiveWorkbenchWindow().getShell(),
+                                                       list, new ListContentProvider(),
+                                                       new LabelProvider(), "Select the includes to open.");
+                                       listSelectionDialog.setTitle("Multiple includes found");
+                                       if (listSelectionDialog.open() == Window.OK) {
+                                               Object[] locations = listSelectionDialog.getResult();
+                                               if (locations != null) {
+                                                       try {
+                                                               for (int i = 0; i < locations.length; i++) {
+                                                                       // PHPIdentifierLocation location =
+                                                                       // (PHPIdentifierLocation)
+                                                                       // locations[i];
+                                                                       String openFilename = workspaceLocation
+                                                                                       + ((String) locations[i]);
+                                                                       PHPeclipsePlugin.getDefault()
+                                                                                       .openFileInTextEditor(openFilename);
+                                                               }
+                                                       } catch (CoreException e) {
+                                                               // TODO Auto-generated catch block
+                                                               e.printStackTrace();
+                                                       }
+                                               }
+                                       }
+
+                               }
+                       } catch (Exception e) {
+                       }
+
+               }
+               return;
+       }
+
+       /**
+        * @param f
+        * @param identiifer
+        */
+       private void openIdentifierDeclaration(IFile f, String identiifer) {
+               if (identiifer != null && !identiifer.equals("")) {
+                       IdentifierIndexManager indexManager = PHPeclipsePlugin.getDefault()
+                                       .getIndexManager(fProject);
+                       List locationsList = indexManager.getLocations(identiifer);
+                       if (locationsList != null && locationsList.size() > 0) {
+
+                               // String workspaceLocation =
+                               // PHPeclipsePlugin.getWorkspace().getRoot()
+                               // .getLocation().toString();
+
+                               String workspaceLocation = fProject.getLocation().toString()
+                                               + java.io.File.separatorChar;
+                               // TODO show all entries of the list in a dialog box
+                               // at the moment always the first entry will be opened
+                               if (locationsList.size() > 1) {
+                                       // determine all includes:
+                                       IncludesScanner includesScanner = new IncludesScanner(
+                                                       fProject, (IFileEditorInput) fEditor
+                                                                       .getEditorInput());
+                                       includesScanner.addFile(f);
+                                       Set exactIncludeSet = includesScanner.getSet();
+
+                                       PHPIdentifierLocation includeName;
+                                       for (int i = 0; i < locationsList.size(); i++) {
+                                               includeName = (PHPIdentifierLocation) locationsList
+                                                               .get(i);
+                                               if (exactIncludeSet.contains(includeName.getFilename())) {
+                                                       includeName
+                                                                       .setMatch(PHPIdentifierLocation.EXACT_MATCH);
+                                               } else {
+                                                       includeName
+                                                                       .setMatch(PHPIdentifierLocation.UNDEFINED_MATCH);
+                                               }
+                                       }
+                                       Collections.sort(locationsList);
+
+                                       ListSelectionDialog listSelectionDialog = new ListSelectionDialog(
+                                                       PHPeclipsePlugin.getDefault().getWorkbench()
+                                                                       .getActiveWorkbenchWindow().getShell(),
+                                                       locationsList, new ListContentProvider(),
+                                                       new LabelProvider(),
+                                                       "Select the resources to open.");
+                                       listSelectionDialog.setTitle("Multiple declarations found");
+                                       if (listSelectionDialog.open() == Window.OK) {
+                                               Object[] locations = listSelectionDialog.getResult();
+                                               if (locations != null) {
+                                                       try {
+                                                               for (int i = 0; i < locations.length; i++) {
+                                                                       PHPIdentifierLocation location = (PHPIdentifierLocation) locations[i];
+                                                                       String filename = workspaceLocation
+                                                                                       + location.getFilename();
+                                                                       // System.out.println(filename);
+                                                                       if (location.getOffset() >= 0) {
+                                                                               PHPeclipsePlugin.getDefault()
+                                                                                               .openFileAndGotoOffset(
+                                                                                                               filename,
+                                                                                                               location.getOffset(),
+                                                                                                               identiifer.length());
+                                                                       } else {
+                                                                               PHPeclipsePlugin.getDefault()
+                                                                                               .openFileAndFindString(
+                                                                                                               filename, identiifer);
+                                                                       }
+                                                               }
+                                                       } catch (CoreException e) {
+                                                               // TODO Auto-generated catch block
+                                                               e.printStackTrace();
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       try {
+                                               PHPIdentifierLocation location = (PHPIdentifierLocation) locationsList
+                                                               .get(0);
+                                               String filename = workspaceLocation
+                                                               + location.getFilename();
+                                               // System.out.println(filename);
+                                               if (location.getOffset() >= 0) {
+                                                       PHPeclipsePlugin.getDefault()
+                                                                       .openFileAndGotoOffset(filename,
+                                                                                       location.getOffset(),
+                                                                                       identiifer.length());
+                                               } else {
+                                                       PHPeclipsePlugin
+                                                                       .getDefault()
+                                                                       .openFileAndFindString(filename, identiifer);
+                                               }
+                                       } catch (CoreException e) {
+                                               // TODO Auto-generated catch block
+                                               e.printStackTrace();
+                                       }
+                               }
+                       }
+               }
+       }
+
+       private String getIdentifierOrInclude(IDocument doc, int pos) {
+               // private String getPHPIncludeText(IDocument doc, int pos) {
+               Point word = null;
+               int start = -1;
+               int end = -1;
+               isIncludeString = false;
+               try {
+                       // try to find an include string
+                       int position = pos;
+                       char character = ' ';
+
+                       while (position >= 0) {
+                               character = doc.getChar(position);
+                               if ((character == '\"') || (character == '\'')
+                                               || (character == '\r') || (character == '\n'))
+                                       break;
+                               --position;
+                       }
+                       if ((character == '\"') || (character == '\'')) {
+                               start = position;
+
+                               position = pos;
+                               int length = doc.getLength();
+                               character = ' ';
+                               while (position < length) {
+                                       character = doc.getChar(position);
+                                       if ((character == '\"') || (character == '\'')
+                                                       || (character == '\r') || (character == '\n'))
+                                               break;
+                                       ++position;
+                               }
+                               if ((character == '\"') || (character == '\'')) {
+                                       start++;
+                                       end = position;
+
+                                       if (end > start) {
+                                               word = new Point(start, end - start); // include name
+                                                                                                                               // found
+                                               isIncludeString = true;
+                                       }
+                               }
+                       }
+
+                       // try to find an identifier
+                       if (word == null) {
+                               word = PHPWordExtractor.findWord(doc, pos); // identifier found
+                               isIncludeString = false;
+                       }
+               } catch (BadLocationException x) {
+               }
+
+               if (word != null) {
+                       try {
+                               return doc.get(word.x, word.y);
+                       } catch (BadLocationException e) {
+                       }
+               }
+               return "";
+       }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/actions/PHPOpenAllIncludesEditorAction.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/actions/PHPOpenAllIncludesEditorAction.java
new file mode 100644 (file)
index 0000000..3dd63ff
--- /dev/null
@@ -0,0 +1,242 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2002 IBM Corp. and others. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Common Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors: www.phpeclipse.de
+ ******************************************************************************/
+package net.sourceforge.phpeclipse.actions;
+
+import java.io.File;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.ui.viewsupport.ListContentProvider;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.phpeditor.PHPEditor;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.actions.ActionDelegate;
+import org.eclipse.ui.dialogs.ListSelectionDialog;
+
+public class PHPOpenAllIncludesEditorAction extends ActionDelegate implements
+               IEditorActionDelegate {
+
+       private IWorkbenchWindow fWindow;
+
+       private PHPEditor fEditor;
+
+       private IProject fProject;
+
+       private IncludesScanner fIncludesScanner;
+
+       public void dispose() {
+       }
+
+       public void init(IWorkbenchWindow window) {
+               this.fWindow = window;
+       }
+
+       public void selectionChanged(IAction action, ISelection selection) {
+               if (!selection.isEmpty()) {
+                       if (selection instanceof TextSelection) {
+                               action.setEnabled(true);
+                       } else if (fWindow.getActivePage() != null
+                                       && fWindow.getActivePage().getActivePart() != null) {
+                               //
+                       }
+               }
+       }
+
+       private IWorkbenchPage getActivePage() {
+               IWorkbenchWindow workbenchWindow = fEditor.getEditorSite()
+                               .getWorkbenchWindow();
+               IWorkbenchPage page = workbenchWindow.getActivePage();
+               return page;
+       }
+
+       public IContainer getWorkingLocation(IFileEditorInput editorInput) {
+               if (editorInput == null || editorInput.getFile() == null) {
+                       return null;
+               }
+               return editorInput.getFile().getParent();
+       }
+
+       private IFile getIncludeFile(IProject project,
+                       IFileEditorInput editorInput, String relativeFilename) {
+               IContainer container = getWorkingLocation(editorInput);
+               String fullPath = project.getLocation().toString();
+               IFile file = null;
+               if (relativeFilename.startsWith("../")) {
+                       Path path = new Path(relativeFilename);
+                       file = container.getFile(path);
+                       return file;
+               }
+               int index = relativeFilename.lastIndexOf('/');
+
+               if (index >= 0) {
+                       Path path = new Path(relativeFilename);
+                       file = project.getFile(path);
+                       if (file.exists()) {
+                               return file;
+                       }
+               }
+
+               Path path = new Path(relativeFilename);
+               file = container.getFile(path);
+
+               return file;
+       }
+
+       public void run(IAction action) {
+               if (fEditor == null) {
+                       IEditorPart targetEditor = fWindow.getActivePage()
+                                       .getActiveEditor();
+                       if (targetEditor != null && (targetEditor instanceof PHPEditor)) {
+                               fEditor = (PHPEditor) targetEditor;
+                       }
+               }
+               if (fEditor != null) {
+                       // determine the current Project from a (file-based) Editor
+                       IFile f = ((IFileEditorInput) fEditor.getEditorInput()).getFile();
+                       fProject = f.getProject();
+                       // System.out.println(fProject.toString());
+
+                       ITextSelection selection = (ITextSelection) fEditor
+                                       .getSelectionProvider().getSelection();
+                       IDocument doc = fEditor.getDocumentProvider().getDocument(
+                                       fEditor.getEditorInput());
+                       fIncludesScanner = new IncludesScanner(fProject,
+                                       (IFileEditorInput) fEditor.getEditorInput());
+                       int pos = selection.getOffset();
+                       // System.out.println(selection.getText());
+                       String filename = getPHPIncludeText(doc, pos);
+
+                       if (filename != null && !filename.equals("")) {
+                               try {
+                                       IFile file = fIncludesScanner.getIncludeFile(filename);
+                                       fIncludesScanner.addFile(file);
+                               } catch (Exception e) {
+                                       // ignore
+                               }
+
+                               try {
+
+                                       List list = fIncludesScanner.getList();
+                                       if (list != null && list.size() > 0) {
+                                               // String workspaceLocation =
+                                               // PHPeclipsePlugin.getWorkspace().getRoot().getLocation().toString();
+                                               String workspaceLocation = fProject.getLocation()
+                                                               .toString()
+                                                               + File.separatorChar;
+
+                                               ListSelectionDialog listSelectionDialog = new ListSelectionDialog(
+                                                               PHPeclipsePlugin.getDefault().getWorkbench()
+                                                                               .getActiveWorkbenchWindow().getShell(),
+                                                               list, new ListContentProvider(),
+                                                               new LabelProvider(),
+                                                               "Select the includes to open.");
+                                               listSelectionDialog.setTitle("Multiple includes found");
+                                               if (listSelectionDialog.open() == Window.OK) {
+                                                       Object[] locations = listSelectionDialog
+                                                                       .getResult();
+                                                       if (locations != null) {
+                                                               try {
+                                                                       for (int i = 0; i < locations.length; i++) {
+                                                                               // PHPIdentifierLocation location =
+                                                                               // (PHPIdentifierLocation)
+                                                                               // locations[i];
+                                                                               String openFilename = workspaceLocation
+                                                                                               + ((String) locations[i]);
+                                                                               PHPeclipsePlugin.getDefault()
+                                                                                               .openFileInTextEditor(
+                                                                                                               openFilename);
+                                                                       }
+                                                               } catch (CoreException e) {
+                                                                       // TODO Auto-generated catch block
+                                                                       e.printStackTrace();
+                                                               }
+                                                       }
+                                               }
+
+                                       }
+                               } catch (Exception e) {
+                               }
+
+                       }
+               }
+       }
+
+       public void setActiveEditor(IAction action, IEditorPart targetEditor) {
+               if (targetEditor != null && (targetEditor instanceof PHPEditor)) {
+                       fEditor = (PHPEditor) targetEditor;
+               }
+       }
+
+       private String getPHPIncludeText(IDocument doc, int pos) {
+               Point word = null;
+               int start = -1;
+               int end = -1;
+
+               try {
+
+                       int position = pos;
+                       char character;
+
+                       while (position >= 0) {
+                               character = doc.getChar(position);
+                               if ((character == '\"') || (character == '\'')
+                                               || (character == '\r') || (character == '\n'))
+                                       break;
+                               --position;
+                       }
+
+                       start = position;
+
+                       position = pos;
+                       int length = doc.getLength();
+
+                       while (position < length) {
+                               character = doc.getChar(position);
+                               if ((character == '\"') || (character == '\'')
+                                               || (character == '\r') || (character == '\n'))
+                                       break;
+                               ++position;
+                       }
+
+                       start++;
+                       end = position;
+
+                       if (end > start)
+                               word = new Point(start, end - start);
+
+               } catch (BadLocationException x) {
+               }
+
+               if (word != null) {
+                       try {
+                               return doc.get(word.x, word.y);
+                       } catch (BadLocationException e) {
+                       }
+               }
+               return "";
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorIgnores.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/obfuscator/ObfuscatorIgnores.java
new file mode 100644 (file)
index 0000000..46a585e
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * (c) Copyright IBM Corp. 2000, 2001.
+ * All Rights Reserved.
+ */
+package net.sourceforge.phpeclipse.obfuscator;
+
+import java.io.File;
+import java.io.InputStream;
+
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.dialogs.ErrorDialog;
+
+/**
+ * <code>ObfuscatorIgnores</code> gives access to the available templates.
+ */
+public class ObfuscatorIgnores extends ObfuscatorIgnoreSet {
+
+       private static final String DEFAULT_FILE = "default-obfuscator.xml"; //$NON-NLS-1$
+
+       private static final String TEMPLATE_FILE = "obfuscator.xml"; //$NON-NLS-1$
+
+       /** Singleton. */
+       private static ObfuscatorIgnores fgIgnores;
+
+       private IProject fProject;
+
+       public ObfuscatorIgnores(IProject project) {
+               fProject = project;
+               try {
+                       File templateFile = getTemplateFile();
+                       if (templateFile.exists()) {
+                               addFromFile(templateFile);
+                       } else {
+                               addFromStream(getDefaultsAsStream());
+                               saveToFile(templateFile);
+                       }
+
+               } catch (CoreException e) {
+                       PHPeclipsePlugin.log(e);
+                       ErrorDialog.openError(null, ObfuscatorMessages
+                                       .getString("Obfuscator.error.title"), //$NON-NLS-1$
+                                       e.getMessage(), e.getStatus());
+
+                       clear();
+               }
+       }
+
+       /**
+        * Returns an instance of templates.
+        */
+       // public static ObfuscatorIgnores getInstance() {
+       // if (fgIgnores == null)
+       // fgIgnores = create();
+       //
+       // return fgIgnores;
+       // }
+       //
+       // private static ObfuscatorIgnores create() {
+       // ObfuscatorIgnores templates = new ObfuscatorIgnores();
+       //
+       // try {
+       // File templateFile = getTemplateFile();
+       // if (templateFile.exists()) {
+       // templates.addFromFile(templateFile);
+       // } else {
+       // templates.addFromStream(getDefaultsAsStream());
+       // templates.saveToFile(templateFile);
+       // }
+       //
+       // } catch (CoreException e) {
+       // PHPeclipsePlugin.log(e);
+       // ErrorDialog.openError(null,
+       // ObfuscatorMessages.getString("Templates.error.title"), //$NON-NLS-1$
+       // e.getMessage(), e.getStatus());
+       //
+       // templates.clear();
+       // }
+       //
+       // return templates;
+       // }
+       /**
+        * Resets the template set.
+        */
+       public void reset() throws CoreException {
+               clear();
+               addFromFile(getTemplateFile());
+       }
+
+       /**
+        * Resets the template set with the default templates.
+        */
+       public void restoreDefaults() throws CoreException {
+               clear();
+               addFromStream(getDefaultsAsStream());
+       }
+
+       /**
+        * Saves the template set.
+        */
+       public void save() throws CoreException {
+               saveToFile(getTemplateFile());
+       }
+
+       private InputStream getDefaultsAsStream() {
+               return ObfuscatorIgnores.class.getResourceAsStream(DEFAULT_FILE);
+       }
+
+       private File getTemplateFile() {
+               IPath path = fProject.getLocation();
+               // PHPeclipsePlugin.getDefault().getStateLocation();
+               path = path.append(TEMPLATE_FILE);
+
+               return path.toFile();
+       }
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/obfuscator/export/WizardObfuscatorResourceExportPage1.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/obfuscator/export/WizardObfuscatorResourceExportPage1.java
new file mode 100644 (file)
index 0000000..bb5dd99
--- /dev/null
@@ -0,0 +1,505 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.obfuscator.export;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Widget;
+import org.eclipse.ui.dialogs.WizardExportResourcesPage;
+
+/**
+ * Page 1 of the base resource export-to-file-system Wizard
+ */
+/* package */
+class WizardObfuscatorResourceExportPage1 extends WizardExportResourcesPage
+               implements Listener {
+
+       // widgets
+       private Combo destinationNameField;
+
+       private Button destinationBrowseButton;
+
+       protected Button overwriteExistingFilesCheckbox;
+
+       // protected Button createDirectoryStructureButton;
+       // protected Button createSelectionOnlyButton;
+
+       // constants
+       private static final int SIZING_TEXT_FIELD_WIDTH = 250;
+
+       // dialog store id constants
+       private static final String STORE_DESTINATION_NAMES_ID = "WizardObfuscatorResourceExportPage1.STORE_DESTINATION_NAMES_ID"; //$NON-NLS-1$
+
+       private static final String STORE_OVERWRITE_EXISTING_FILES_ID = "WizardObfuscatorResourceExportPage1.STORE_OVERWRITE_EXISTING_FILES_ID"; //$NON-NLS-1$
+       // private static final String STORE_CREATE_STRUCTURE_ID =
+       // "WizardObfuscatorResourceExportPage1.STORE_CREATE_STRUCTURE_ID";
+       // //$NON-NLS-1$
+
+       // messages
+       private static final String SELECT_DESTINATION_MESSAGE = ObfuscatorExportMessages
+                       .getString("FileExport.selectDestinationMessage"); //$NON-NLS-1$
+
+       private static final String SELECT_DESTINATION_TITLE = ObfuscatorExportMessages
+                       .getString("FileExport.selectDestinationTitle"); //$NON-NLS-1$
+
+       /**
+        * Create an instance of this class
+        */
+       protected WizardObfuscatorResourceExportPage1(String name,
+                       IStructuredSelection selection) {
+               super(name, selection);
+       }
+
+       /**
+        * Create an instance of this class
+        */
+       public WizardObfuscatorResourceExportPage1(IStructuredSelection selection) {
+               this("fileSystemExportPage1", selection); //$NON-NLS-1$
+               setTitle(ObfuscatorExportMessages
+                               .getString("ObfuscatorTransfer.fileSystemTitle")); //$NON-NLS-1$
+               setDescription(ObfuscatorExportMessages
+                               .getString("FileExport.exportLocalFileSystem")); //$NON-NLS-1$
+       }
+
+       /**
+        * Add the passed value to self's destination widget's history
+        * 
+        * @param value
+        *            java.lang.String
+        */
+       protected void addDestinationItem(String value) {
+               destinationNameField.add(value);
+       }
+
+       /**
+        * (non-Javadoc) Method declared on IDialogPage.
+        */
+       public void createControl(Composite parent) {
+               super.createControl(parent);
+               giveFocusToDestination();
+               // WorkbenchHelp.setHelp(
+               // getControl(),
+               // IDataTransferHelpContextIds.FILE_SYSTEM_EXPORT_WIZARD_PAGE);
+       }
+
+       /**
+        * Create the export destination specification widgets
+        * 
+        * @param parent
+        *            org.eclipse.swt.widgets.Composite
+        */
+       protected void createDestinationGroup(Composite parent) {
+
+               Font font = parent.getFont();
+               // destination specification group
+               Composite destinationSelectionGroup = new Composite(parent, SWT.NONE);
+               GridLayout layout = new GridLayout();
+               layout.numColumns = 3;
+               destinationSelectionGroup.setLayout(layout);
+               destinationSelectionGroup.setLayoutData(new GridData(
+                               GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL));
+               destinationSelectionGroup.setFont(font);
+
+               Label destinationLabel = new Label(destinationSelectionGroup, SWT.NONE);
+               destinationLabel.setText(getDestinationLabel());
+               destinationLabel.setFont(font);
+
+               // destination name entry field
+               destinationNameField = new Combo(destinationSelectionGroup, SWT.SINGLE
+                               | SWT.BORDER);
+               destinationNameField.addListener(SWT.Modify, this);
+               destinationNameField.addListener(SWT.Selection, this);
+               GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
+                               | GridData.GRAB_HORIZONTAL);
+               data.widthHint = SIZING_TEXT_FIELD_WIDTH;
+               destinationNameField.setLayoutData(data);
+               destinationNameField.setFont(font);
+
+               // destination browse button
+               destinationBrowseButton = new Button(destinationSelectionGroup,
+                               SWT.PUSH);
+               destinationBrowseButton.setText(ObfuscatorExportMessages
+                               .getString("ObfuscatorTransfer.browse")); //$NON-NLS-1$
+               destinationBrowseButton.addListener(SWT.Selection, this);
+               destinationBrowseButton.setFont(font);
+               setButtonLayoutData(destinationBrowseButton);
+
+               new Label(parent, SWT.NONE); // vertical spacer
+       }
+
+       /**
+        * Create the buttons in the options group.
+        */
+
+       protected void createOptionsGroupButtons(Group optionsGroup) {
+
+               Font font = optionsGroup.getFont();
+               createOverwriteExisting(optionsGroup, font);
+
+               // createDirectoryStructureOptions(optionsGroup, font);
+       }
+
+       /**
+        * Create the buttons for the group that determine if the entire or selected
+        * directory structure should be created.
+        * 
+        * @param optionsGroup
+        * @param font
+        */
+       // protected void createDirectoryStructureOptions(
+       // Group optionsGroup,
+       // Font font) {
+       // // create directory structure radios
+       // createDirectoryStructureButton =
+       // new Button(optionsGroup, SWT.RADIO | SWT.LEFT);
+       // createDirectoryStructureButton.setText(ObfuscatorExportMessages.getString("FileExport.createDirectoryStructure"));
+       // //$NON-NLS-1$
+       // createDirectoryStructureButton.setSelection(false);
+       // createDirectoryStructureButton.setFont(font);
+       //
+       // // create directory structure radios
+       // createSelectionOnlyButton =
+       // new Button(optionsGroup, SWT.RADIO | SWT.LEFT);
+       // createSelectionOnlyButton.setText(
+       // ObfuscatorExportMessages.getString(
+       // "FileExport.createSelectedDirectories"));//$NON-NLS-1$
+       // createSelectionOnlyButton.setSelection(true);
+       // createSelectionOnlyButton.setFont(font);
+       // }
+       /**
+        * Create the button for checking if we should ask if we are going to
+        * overwrite existing files.
+        * 
+        * @param optionsGroup
+        * @param font
+        */
+       protected void createOverwriteExisting(Group optionsGroup, Font font) {
+               // overwrite... checkbox
+               overwriteExistingFilesCheckbox = new Button(optionsGroup, SWT.CHECK
+                               | SWT.LEFT);
+               overwriteExistingFilesCheckbox.setText(ObfuscatorExportMessages
+                               .getString("ExportFile.overwriteExisting")); //$NON-NLS-1$
+               overwriteExistingFilesCheckbox.setFont(font);
+       }
+
+       /**
+        * Attempts to ensure that the specified directory exists on the local file
+        * system. Answers a boolean indicating success.
+        * 
+        * @return boolean
+        * @param directory
+        *            java.io.File
+        */
+       protected boolean ensureDirectoryExists(File directory) {
+               if (!directory.exists()) {
+                       if (!queryYesNoQuestion(ObfuscatorExportMessages
+                                       .getString("ObfuscatorTransfer.createTargetDirectory"))) //$NON-NLS-1$
+                               return false;
+
+                       if (!directory.mkdirs()) {
+                               displayErrorDialog(ObfuscatorExportMessages
+                                               .getString("ObfuscatorTransfer.directoryCreationError")); //$NON-NLS-1$
+                               giveFocusToDestination();
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       /**
+        * If the target for export does not exist then attempt to create it. Answer
+        * a boolean indicating whether the target exists (ie.- if it either
+        * pre-existed or this method was able to create it)
+        * 
+        * @return boolean
+        */
+       protected boolean ensureTargetIsValid(File targetDirectory) {
+               if (targetDirectory.exists() && !targetDirectory.isDirectory()) {
+                       displayErrorDialog(ObfuscatorExportMessages
+                                       .getString("FileExport.directoryExists")); //$NON-NLS-1$
+                       giveFocusToDestination();
+                       return false;
+               }
+
+               return ensureDirectoryExists(targetDirectory);
+       }
+
+       /**
+        * Set up and execute the passed Operation. Answer a boolean indicating
+        * success.
+        * 
+        * @return boolean
+        */
+       protected boolean executeExportOperation(ObfuscatorExportOperation op) {
+               // op.setCreateLeadupStructure(
+               // createDirectoryStructureButton.getSelection());
+               op.setOverwriteFiles(overwriteExistingFilesCheckbox.getSelection());
+
+               try {
+                       getContainer().run(true, true, op);
+               } catch (InterruptedException e) {
+                       return false;
+               } catch (InvocationTargetException e) {
+                       displayErrorDialog(e.getTargetException());
+                       return false;
+               }
+
+               IStatus status = op.getStatus();
+               if (!status.isOK()) {
+                       ErrorDialog.openError(getContainer().getShell(),
+                                       ObfuscatorExportMessages
+                                                       .getString("ObfuscatorTransfer.exportProblems"), //$NON-NLS-1$
+                                       null, // no special message
+                                       status);
+                       return false;
+               }
+
+               return true;
+       }
+
+       /**
+        * The Finish button was pressed. Try to do the required work now and answer
+        * a boolean indicating success. If false is returned then the wizard will
+        * not close.
+        * 
+        * @return boolean
+        */
+       public boolean finish() {
+               if (!ensureTargetIsValid(new File(getDestinationValue())))
+                       return false;
+
+               List resourcesToExport = getWhiteCheckedResources();
+
+               // Save dirty editors if possible but do not stop if not all are saved
+               saveDirtyEditors();
+               // about to invoke the operation so save our state
+               saveWidgetValues();
+
+               if (resourcesToExport.size() > 0)
+                       return executeExportOperation(new ObfuscatorExportOperation(null,
+                                       resourcesToExport, getDestinationValue(), this));
+
+               MessageDialog.openInformation(getContainer().getShell(),
+                               ObfuscatorExportMessages
+                                               .getString("ObfuscatorTransfer.information"), //$NON-NLS-1$
+                               ObfuscatorExportMessages.getString("FileExport.noneSelected")); //$NON-NLS-1$
+
+               return false;
+       }
+
+       /**
+        * Answer the string to display in self as the destination type
+        * 
+        * @return java.lang.String
+        */
+       protected String getDestinationLabel() {
+               return ObfuscatorExportMessages.getString("FileExport.toDirectory"); //$NON-NLS-1$
+       }
+
+       /**
+        * Answer the contents of self's destination specification widget
+        * 
+        * @return java.lang.String
+        */
+       protected String getDestinationValue() {
+               return destinationNameField.getText().trim();
+       }
+
+       /**
+        * Set the current input focus to self's destination entry field
+        */
+       protected void giveFocusToDestination() {
+               destinationNameField.setFocus();
+       }
+
+       /**
+        * Open an appropriate destination browser so that the user can specify a
+        * source to import from
+        */
+       protected void handleDestinationBrowseButtonPressed() {
+               DirectoryDialog dialog = new DirectoryDialog(getContainer().getShell(),
+                               SWT.SAVE);
+               dialog.setMessage(SELECT_DESTINATION_MESSAGE);
+               dialog.setText(SELECT_DESTINATION_TITLE);
+               dialog.setFilterPath(getDestinationValue());
+               String selectedDirectoryName = dialog.open();
+
+               if (selectedDirectoryName != null) {
+                       setErrorMessage(null);
+                       setDestinationValue(selectedDirectoryName);
+               }
+       }
+
+       /**
+        * Handle all events and enablements for widgets in this page
+        * 
+        * @param e
+        *            Event
+        */
+       public void handleEvent(Event e) {
+               Widget source = e.widget;
+
+               if (source == destinationBrowseButton)
+                       handleDestinationBrowseButtonPressed();
+
+               updatePageCompletion();
+       }
+
+       /**
+        * Hook method for saving widget values for restoration by the next instance
+        * of this class.
+        */
+       protected void internalSaveWidgetValues() {
+               // update directory names history
+               IDialogSettings settings = getDialogSettings();
+               if (settings != null) {
+                       String[] directoryNames = settings
+                                       .getArray(STORE_DESTINATION_NAMES_ID);
+                       if (directoryNames == null)
+                               directoryNames = new String[0];
+
+                       directoryNames = addToHistory(directoryNames, getDestinationValue());
+                       settings.put(STORE_DESTINATION_NAMES_ID, directoryNames);
+
+                       // options
+                       settings.put(STORE_OVERWRITE_EXISTING_FILES_ID,
+                                       overwriteExistingFilesCheckbox.getSelection());
+
+                       // settings.put(
+                       // STORE_CREATE_STRUCTURE_ID,
+                       // createDirectoryStructureButton.getSelection());
+
+               }
+       }
+
+       /**
+        * Hook method for restoring widget values to the values that they held last
+        * time this wizard was used to completion.
+        */
+       protected void restoreWidgetValues() {
+               IDialogSettings settings = getDialogSettings();
+               if (settings != null) {
+                       String[] directoryNames = settings
+                                       .getArray(STORE_DESTINATION_NAMES_ID);
+                       if (directoryNames == null)
+                               return; // ie.- no settings stored
+
+                       // destination
+                       setDestinationValue(directoryNames[0]);
+                       for (int i = 0; i < directoryNames.length; i++)
+                               addDestinationItem(directoryNames[i]);
+
+                       // options
+                       overwriteExistingFilesCheckbox.setSelection(settings
+                                       .getBoolean(STORE_OVERWRITE_EXISTING_FILES_ID));
+
+                       // boolean createDirectories =
+                       // settings.getBoolean(STORE_CREATE_STRUCTURE_ID);
+                       // createDirectoryStructureButton.setSelection(createDirectories);
+                       // createSelectionOnlyButton.setSelection(!createDirectories);
+               }
+       }
+
+       /**
+        * Set the contents of the receivers destination specification widget to the
+        * passed value
+        * 
+        */
+       protected void setDestinationValue(String value) {
+               destinationNameField.setText(value);
+       }
+
+       /**
+        * Answer a boolean indicating whether the receivers destination
+        * specification widgets currently all contain valid values.
+        */
+       protected boolean validateDestinationGroup() {
+               String destinationValue = getDestinationValue();
+               if (destinationValue.length() == 0) {
+                       setMessage(destinationEmptyMessage());
+                       return false;
+               }
+
+               String conflictingContainer = getConflictingContainerNameFor(destinationValue);
+               if (conflictingContainer == null)
+                       setErrorMessage(""); //$NON-NLS-1$
+               else {
+                       setErrorMessage(ObfuscatorExportMessages.format(
+                                       "FileExport.conflictingContainer", //$NON-NLS-1$
+                                       new Object[] { conflictingContainer }));
+                       giveFocusToDestination();
+                       return false;
+               }
+
+               return true;
+       }
+
+       /**
+        * Get the message used to denote an empty destination.
+        */
+       protected String destinationEmptyMessage() {
+               return ObfuscatorExportMessages
+                               .getString("FileExport.destinationEmpty"); //$NON-NLS-1$
+       }
+
+       /**
+        * Returns the name of a container with a location that encompasses
+        * targetDirectory. Returns null if there is no conflict.
+        * 
+        * @param targetDirectory
+        *            the path of the directory to check.
+        * @return the conflicting container name or <code>null</code>
+        */
+       protected String getConflictingContainerNameFor(String targetDirectory) {
+
+               IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+               IPath testPath = new Path(targetDirectory);
+
+               if (root.getLocation().isPrefixOf(testPath))
+                       return ObfuscatorExportMessages.getString("FileExport.rootName"); //$NON-NLS-1$
+
+               IProject[] projects = root.getProjects();
+
+               for (int i = 0; i < projects.length; i++) {
+                       if (projects[i].getLocation().isPrefixOf(testPath))
+                               return projects[i].getName();
+               }
+
+               return null;
+
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/phpeditor/PHPEditor.java
new file mode 100644 (file)
index 0000000..4eb14da
--- /dev/null
@@ -0,0 +1,6068 @@
+package net.sourceforge.phpeclipse.phpeditor;
+
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.core.ICompilationUnit;
+import net.sourceforge.phpdt.core.IImportContainer;
+import net.sourceforge.phpdt.core.IImportDeclaration;
+import net.sourceforge.phpdt.core.IJavaElement;
+import net.sourceforge.phpdt.core.IJavaProject;
+import net.sourceforge.phpdt.core.IMember;
+import net.sourceforge.phpdt.core.ISourceRange;
+import net.sourceforge.phpdt.core.ISourceReference;
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
+import net.sourceforge.phpdt.internal.compiler.parser.SyntaxError;
+import net.sourceforge.phpdt.internal.ui.actions.CompositeActionGroup;
+import net.sourceforge.phpdt.internal.ui.actions.FoldingActionGroup;
+import net.sourceforge.phpdt.internal.ui.actions.SelectionConverter;
+import net.sourceforge.phpdt.internal.ui.text.CustomSourceInformationControl;
+import net.sourceforge.phpdt.internal.ui.text.DocumentCharacterIterator;
+import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter;
+import net.sourceforge.phpdt.internal.ui.text.IPHPPartitions;
+import net.sourceforge.phpdt.internal.ui.text.JavaWordFinder;
+import net.sourceforge.phpdt.internal.ui.text.JavaWordIterator;
+import net.sourceforge.phpdt.internal.ui.text.PHPPairMatcher;
+import net.sourceforge.phpdt.internal.ui.text.PreferencesAdapter;
+import net.sourceforge.phpdt.internal.ui.text.java.hover.JavaExpandHover;
+import net.sourceforge.phpdt.internal.ui.viewsupport.ISelectionListenerWithAST;
+import net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider;
+import net.sourceforge.phpdt.internal.ui.viewsupport.SelectionListenerWithASTManager;
+import net.sourceforge.phpdt.ui.IContextMenuConstants;
+import net.sourceforge.phpdt.ui.JavaUI;
+import net.sourceforge.phpdt.ui.PreferenceConstants;
+import net.sourceforge.phpdt.ui.actions.GotoMatchingBracketAction;
+import net.sourceforge.phpdt.ui.actions.OpenEditorActionGroup;
+import net.sourceforge.phpdt.ui.text.JavaTextTools;
+import net.sourceforge.phpdt.ui.text.PHPSourceViewerConfiguration;
+import net.sourceforge.phpdt.ui.text.folding.IJavaFoldingStructureProvider;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.ui.editor.BrowserUtil;
+import net.sourceforge.phpeclipse.webbrowser.views.BrowserView;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.GroupMarker;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentExtension4;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ISelectionValidator;
+import org.eclipse.jface.text.ISynchronizable;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextInputListener;
+import org.eclipse.jface.text.ITextPresentationListener;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITextViewerExtension2;
+import org.eclipse.jface.text.ITextViewerExtension4;
+import org.eclipse.jface.text.ITextViewerExtension5;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.TextSelection;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.jface.text.information.IInformationProvider;
+import org.eclipse.jface.text.information.InformationPresenter;
+import org.eclipse.jface.text.link.LinkedModeModel;
+import org.eclipse.jface.text.reconciler.IReconciler;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.AnnotationRulerColumn;
+import org.eclipse.jface.text.source.CompositeRuler;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationModelExtension;
+import org.eclipse.jface.text.source.IOverviewRuler;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.ISourceViewerExtension2;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.text.source.IVerticalRulerColumn;
+import org.eclipse.jface.text.source.OverviewRuler;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.text.source.projection.ProjectionSupport;
+import org.eclipse.jface.text.source.projection.ProjectionViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.ListenerList;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IPostSelectionProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BidiSegmentEvent;
+import org.eclipse.swt.custom.BidiSegmentListener;
+import org.eclipse.swt.custom.ST;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPartService;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWindowListener;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionContext;
+import org.eclipse.ui.actions.ActionGroup;
+import org.eclipse.ui.editors.text.DefaultEncodingSupport;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.editors.text.IEncodingSupport;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.part.IShowInSource;
+import org.eclipse.ui.part.IShowInTargetList;
+import org.eclipse.ui.part.ShowInContext;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditor;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+import org.eclipse.ui.texteditor.ChainedPreferenceStore;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.IEditorStatusLine;
+import org.eclipse.ui.texteditor.ITextEditorActionConstants;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.IUpdate;
+import org.eclipse.ui.texteditor.MarkerAnnotation;
+import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
+import org.eclipse.ui.texteditor.TextEditorAction;
+import org.eclipse.ui.texteditor.TextNavigationAction;
+import org.eclipse.ui.texteditor.TextOperationAction;
+import org.eclipse.ui.views.contentoutline.ContentOutline;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import org.eclipse.ui.views.tasklist.TaskList;
+
+/**
+ * PHP specific text editor.
+ */
+public abstract class PHPEditor extends AbstractDecoratedTextEditor implements
+               IViewPartInputProvider, IShowInTargetList, IShowInSource {
+       // extends StatusTextEditor implements IViewPartInputProvider { // extends
+       // TextEditor {
+
+       /**
+        * Internal implementation class for a change listener.
+        * 
+        * @since 3.0
+        */
+       protected abstract class AbstractSelectionChangedListener implements
+                       ISelectionChangedListener {
+
+               /**
+                * Installs this selection changed listener with the given selection
+                * provider. If the selection provider is a post selection provider,
+                * post selection changed events are the preferred choice, otherwise
+                * normal selection changed events are requested.
+                * 
+                * @param selectionProvider
+                */
+               public void install(ISelectionProvider selectionProvider) {
+                       if (selectionProvider == null)
+                               return;
+
+                       if (selectionProvider instanceof IPostSelectionProvider) {
+                               IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+                               provider.addPostSelectionChangedListener(this);
+                       } else {
+                               selectionProvider.addSelectionChangedListener(this);
+                       }
+               }
+
+               /**
+                * Removes this selection changed listener from the given selection
+                * provider.
+                * 
+                * @param selectionProvider
+                *            the selection provider
+                */
+               public void uninstall(ISelectionProvider selectionProvider) {
+                       if (selectionProvider == null)
+                               return;
+
+                       if (selectionProvider instanceof IPostSelectionProvider) {
+                               IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider;
+                               provider.removePostSelectionChangedListener(this);
+                       } else {
+                               selectionProvider.removeSelectionChangedListener(this);
+                       }
+               }
+       }
+
+       /**
+        * Updates the Java outline page selection and this editor's range
+        * indicator.
+        * 
+        * @since 3.0
+        */
+       private class EditorSelectionChangedListener extends
+                       AbstractSelectionChangedListener {
+
+               /*
+                * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
+                */
+               public void selectionChanged(SelectionChangedEvent event) {
+                       // XXX: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=56161
+                       PHPEditor.this.selectionChanged();
+               }
+       }
+
+       /**
+        * "Smart" runnable for updating the outline page's selection.
+        */
+       // class OutlinePageSelectionUpdater implements Runnable {
+       //
+       // /** Has the runnable already been posted? */
+       // private boolean fPosted = false;
+       //
+       // public OutlinePageSelectionUpdater() {
+       // }
+       //
+       // /*
+       // * @see Runnable#run()
+       // */
+       // public void run() {
+       // synchronizeOutlinePageSelection();
+       // fPosted = false;
+       // }
+       //
+       // /**
+       // * Posts this runnable into the event queue.
+       // */
+       // public void post() {
+       // if (fPosted)
+       // return;
+       //
+       // Shell shell = getSite().getShell();
+       // if (shell != null & !shell.isDisposed()) {
+       // fPosted = true;
+       // shell.getDisplay().asyncExec(this);
+       // }
+       // }
+       // };
+       class SelectionChangedListener implements ISelectionChangedListener {
+               public void selectionChanged(SelectionChangedEvent event) {
+                       doSelectionChanged(event);
+               }
+       };
+
+       /**
+        * Adapts an options {@link java.util.Map}to
+        * {@link org.eclipse.jface.preference.IPreferenceStore}.
+        * <p>
+        * This preference store is read-only i.e. write access throws an
+        * {@link java.lang.UnsupportedOperationException}.
+        * </p>
+        * 
+        * @since 3.0
+        */
+       private static class OptionsAdapter implements IPreferenceStore {
+
+               /**
+                * A property change event filter.
+                */
+               public interface IPropertyChangeEventFilter {
+
+                       /**
+                        * Should the given event be filtered?
+                        * 
+                        * @param event
+                        *            The property change event.
+                        * @return <code>true</code> iff the given event should be
+                        *         filtered.
+                        */
+                       public boolean isFiltered(PropertyChangeEvent event);
+
+               }
+
+               /**
+                * Property change listener. Listens for events in the options Map and
+                * fires a {@link org.eclipse.jface.util.PropertyChangeEvent}on this
+                * adapter with arguments from the received event.
+                */
+               private class PropertyChangeListener implements IPropertyChangeListener {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       public void propertyChange(PropertyChangeEvent event) {
+                               if (getFilter().isFiltered(event))
+                                       return;
+
+                               if (event.getNewValue() == null)
+                                       fOptions.remove(event.getProperty());
+                               else
+                                       fOptions.put(event.getProperty(), event.getNewValue());
+
+                               firePropertyChangeEvent(event.getProperty(), event
+                                               .getOldValue(), event.getNewValue());
+                       }
+               }
+
+               /** Listeners on this adapter */
+               private ListenerList fListeners = new ListenerList();
+
+               /** Listener on the adapted options Map */
+               private IPropertyChangeListener fListener = new PropertyChangeListener();
+
+               /** Adapted options Map */
+               private Map fOptions;
+
+               /** Preference store through which events are received. */
+               private IPreferenceStore fMockupPreferenceStore;
+
+               /** Property event filter. */
+               private IPropertyChangeEventFilter fFilter;
+
+               /**
+                * Initialize with the given options.
+                * 
+                * @param options
+                *            The options to wrap
+                * @param mockupPreferenceStore
+                *            the mock-up preference store
+                * @param filter
+                *            the property change filter
+                */
+               public OptionsAdapter(Map options,
+                               IPreferenceStore mockupPreferenceStore,
+                               IPropertyChangeEventFilter filter) {
+                       fMockupPreferenceStore = mockupPreferenceStore;
+                       fOptions = options;
+                       setFilter(filter);
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void addPropertyChangeListener(IPropertyChangeListener listener) {
+                       if (fListeners.size() == 0)
+                               fMockupPreferenceStore.addPropertyChangeListener(fListener);
+                       fListeners.add(listener);
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void removePropertyChangeListener(
+                               IPropertyChangeListener listener) {
+                       fListeners.remove(listener);
+                       if (fListeners.size() == 0)
+                               fMockupPreferenceStore.removePropertyChangeListener(fListener);
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public boolean contains(String name) {
+                       return fOptions.containsKey(name);
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void firePropertyChangeEvent(String name, Object oldValue,
+                               Object newValue) {
+                       PropertyChangeEvent event = new PropertyChangeEvent(this, name,
+                                       oldValue, newValue);
+                       Object[] listeners = fListeners.getListeners();
+                       for (int i = 0; i < listeners.length; i++)
+                               ((IPropertyChangeListener) listeners[i]).propertyChange(event);
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public boolean getBoolean(String name) {
+                       boolean value = BOOLEAN_DEFAULT_DEFAULT;
+                       String s = (String) fOptions.get(name);
+                       if (s != null)
+                               value = s.equals(TRUE);
+                       return value;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public boolean getDefaultBoolean(String name) {
+                       return BOOLEAN_DEFAULT_DEFAULT;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public double getDefaultDouble(String name) {
+                       return DOUBLE_DEFAULT_DEFAULT;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public float getDefaultFloat(String name) {
+                       return FLOAT_DEFAULT_DEFAULT;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public int getDefaultInt(String name) {
+                       return INT_DEFAULT_DEFAULT;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public long getDefaultLong(String name) {
+                       return LONG_DEFAULT_DEFAULT;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public String getDefaultString(String name) {
+                       return STRING_DEFAULT_DEFAULT;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public double getDouble(String name) {
+                       double value = DOUBLE_DEFAULT_DEFAULT;
+                       String s = (String) fOptions.get(name);
+                       if (s != null) {
+                               try {
+                                       value = new Double(s).doubleValue();
+                               } catch (NumberFormatException e) {
+                               }
+                       }
+                       return value;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public float getFloat(String name) {
+                       float value = FLOAT_DEFAULT_DEFAULT;
+                       String s = (String) fOptions.get(name);
+                       if (s != null) {
+                               try {
+                                       value = new Float(s).floatValue();
+                               } catch (NumberFormatException e) {
+                               }
+                       }
+                       return value;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public int getInt(String name) {
+                       int value = INT_DEFAULT_DEFAULT;
+                       String s = (String) fOptions.get(name);
+                       if (s != null) {
+                               try {
+                                       value = new Integer(s).intValue();
+                               } catch (NumberFormatException e) {
+                               }
+                       }
+                       return value;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public long getLong(String name) {
+                       long value = LONG_DEFAULT_DEFAULT;
+                       String s = (String) fOptions.get(name);
+                       if (s != null) {
+                               try {
+                                       value = new Long(s).longValue();
+                               } catch (NumberFormatException e) {
+                               }
+                       }
+                       return value;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public String getString(String name) {
+                       String value = (String) fOptions.get(name);
+                       if (value == null)
+                               value = STRING_DEFAULT_DEFAULT;
+                       return value;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public boolean isDefault(String name) {
+                       return false;
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public boolean needsSaving() {
+                       return !fOptions.isEmpty();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void putValue(String name, String value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setDefault(String name, double value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setDefault(String name, float value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setDefault(String name, int value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setDefault(String name, long value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setDefault(String name, String defaultObject) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setDefault(String name, boolean value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setToDefault(String name) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setValue(String name, double value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setValue(String name, float value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setValue(String name, int value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setValue(String name, long value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setValue(String name, String value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * {@inheritDoc}
+                */
+               public void setValue(String name, boolean value) {
+                       throw new UnsupportedOperationException();
+               }
+
+               /**
+                * Returns the adapted options Map.
+                * 
+                * @return Returns the adapted options Map.
+                */
+               public Map getOptions() {
+                       return fOptions;
+               }
+
+               /**
+                * Returns the mock-up preference store, events are received through
+                * this preference store.
+                * 
+                * @return Returns the mock-up preference store.
+                */
+               public IPreferenceStore getMockupPreferenceStore() {
+                       return fMockupPreferenceStore;
+               }
+
+               /**
+                * Set the event filter to the given filter.
+                * 
+                * @param filter
+                *            The new filter.
+                */
+               public void setFilter(IPropertyChangeEventFilter filter) {
+                       fFilter = filter;
+               }
+
+               /**
+                * Returns the event filter.
+                * 
+                * @return The event filter.
+                */
+               public IPropertyChangeEventFilter getFilter() {
+                       return fFilter;
+               }
+       }
+
+       /*
+        * Link mode.
+        */
+       // class MouseClickListener implements KeyListener, MouseListener,
+       // MouseMoveListener, FocusListener, PaintListener,
+       // IPropertyChangeListener, IDocumentListener, ITextInputListener {
+       //
+       // /** The session is active. */
+       // private boolean fActive;
+       //
+       // /** The currently active style range. */
+       // private IRegion fActiveRegion;
+       //
+       // /** The currently active style range as position. */
+       // private Position fRememberedPosition;
+       //
+       // /** The hand cursor. */
+       // private Cursor fCursor;
+       //
+       // /** The link color. */
+       // private Color fColor;
+       //
+       // /** The key modifier mask. */
+       // private int fKeyModifierMask;
+       //
+       // public void deactivate() {
+       // deactivate(false);
+       // }
+       //
+       // public void deactivate(boolean redrawAll) {
+       // if (!fActive)
+       // return;
+       //
+       // repairRepresentation(redrawAll);
+       // fActive = false;
+       // }
+       //
+       // public void install() {
+       //
+       // ISourceViewer sourceViewer = getSourceViewer();
+       // if (sourceViewer == null)
+       // return;
+       //
+       // StyledText text = sourceViewer.getTextWidget();
+       // if (text == null || text.isDisposed())
+       // return;
+       //
+       // updateColor(sourceViewer);
+       //
+       // sourceViewer.addTextInputListener(this);
+       //
+       // IDocument document = sourceViewer.getDocument();
+       // if (document != null)
+       // document.addDocumentListener(this);
+       //
+       // text.addKeyListener(this);
+       // text.addMouseListener(this);
+       // text.addMouseMoveListener(this);
+       // text.addFocusListener(this);
+       // text.addPaintListener(this);
+       //
+       // updateKeyModifierMask();
+       //
+       // IPreferenceStore preferenceStore = getPreferenceStore();
+       // preferenceStore.addPropertyChangeListener(this);
+       // }
+       //
+       // private void updateKeyModifierMask() {
+       // String modifiers =
+       // getPreferenceStore().getString(BROWSER_LIKE_LINKS_KEY_MODIFIER);
+       // fKeyModifierMask = computeStateMask(modifiers);
+       // if (fKeyModifierMask == -1) {
+       // // Fallback to stored state mask
+       // fKeyModifierMask =
+       // getPreferenceStore().getInt(BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK);
+       // }
+       // ;
+       // }
+       //
+       // private int computeStateMask(String modifiers) {
+       // if (modifiers == null)
+       // return -1;
+       //
+       // if (modifiers.length() == 0)
+       // return SWT.NONE;
+       //
+       // int stateMask = 0;
+       // StringTokenizer modifierTokenizer = new StringTokenizer(modifiers,
+       // ",;.:+-*
+       // "); //$NON-NLS-1$
+       // while (modifierTokenizer.hasMoreTokens()) {
+       // int modifier =
+       // EditorUtility.findLocalizedModifier(modifierTokenizer.nextToken());
+       // if (modifier == 0 || (stateMask & modifier) == modifier)
+       // return -1;
+       // stateMask = stateMask | modifier;
+       // }
+       // return stateMask;
+       // }
+       //
+       // public void uninstall() {
+       //
+       // if (fColor != null) {
+       // fColor.dispose();
+       // fColor = null;
+       // }
+       //
+       // if (fCursor != null) {
+       // fCursor.dispose();
+       // fCursor = null;
+       // }
+       //
+       // ISourceViewer sourceViewer = getSourceViewer();
+       // if (sourceViewer == null)
+       // return;
+       //
+       // sourceViewer.removeTextInputListener(this);
+       //
+       // IDocument document = sourceViewer.getDocument();
+       // if (document != null)
+       // document.removeDocumentListener(this);
+       //
+       // IPreferenceStore preferenceStore = getPreferenceStore();
+       // if (preferenceStore != null)
+       // preferenceStore.removePropertyChangeListener(this);
+       //
+       // StyledText text = sourceViewer.getTextWidget();
+       // if (text == null || text.isDisposed())
+       // return;
+       //
+       // text.removeKeyListener(this);
+       // text.removeMouseListener(this);
+       // text.removeMouseMoveListener(this);
+       // text.removeFocusListener(this);
+       // text.removePaintListener(this);
+       // }
+       //
+       // /*
+       // * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+       // */
+       // public void propertyChange(PropertyChangeEvent event) {
+       // if (event.getProperty().equals(PHPEditor.LINK_COLOR)) {
+       // ISourceViewer viewer = getSourceViewer();
+       // if (viewer != null)
+       // updateColor(viewer);
+       // } else if (event.getProperty().equals(BROWSER_LIKE_LINKS_KEY_MODIFIER)) {
+       // updateKeyModifierMask();
+       // }
+       // }
+       //
+       // private void updateColor(ISourceViewer viewer) {
+       // if (fColor != null)
+       // fColor.dispose();
+       //
+       // StyledText text = viewer.getTextWidget();
+       // if (text == null || text.isDisposed())
+       // return;
+       //
+       // Display display = text.getDisplay();
+       // fColor = createColor(getPreferenceStore(), PHPEditor.LINK_COLOR,
+       // display);
+       // }
+       //
+       // /**
+       // * Creates a color from the information stored in the given preference
+       // store. Returns <code>null</code> if there is no such
+       // * information available.
+       // */
+       // private Color createColor(IPreferenceStore store, String key, Display
+       // display) {
+       //
+       // RGB rgb = null;
+       //
+       // if (store.contains(key)) {
+       //
+       // if (store.isDefault(key))
+       // rgb = PreferenceConverter.getDefaultColor(store, key);
+       // else
+       // rgb = PreferenceConverter.getColor(store, key);
+       //
+       // if (rgb != null)
+       // return new Color(display, rgb);
+       // }
+       //
+       // return null;
+       // }
+       //
+       // private void repairRepresentation() {
+       // repairRepresentation(false);
+       // }
+       //
+       // private void repairRepresentation(boolean redrawAll) {
+       //
+       // if (fActiveRegion == null)
+       // return;
+       //
+       // ISourceViewer viewer = getSourceViewer();
+       // if (viewer != null) {
+       // resetCursor(viewer);
+       //
+       // int offset = fActiveRegion.getOffset();
+       // int length = fActiveRegion.getLength();
+       //
+       // // remove style
+       // if (!redrawAll && viewer instanceof ITextViewerExtension2)
+       // ((ITextViewerExtension2) viewer).invalidateTextPresentation(offset,
+       // length);
+       // else
+       // viewer.invalidateTextPresentation();
+       //
+       // // remove underline
+       // if (viewer instanceof ITextViewerExtension3) {
+       // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
+       // offset = extension.modelOffset2WidgetOffset(offset);
+       // } else {
+       // offset -= viewer.getVisibleRegion().getOffset();
+       // }
+       //
+       // StyledText text = viewer.getTextWidget();
+       // try {
+       // text.redrawRange(offset, length, true);
+       // } catch (IllegalArgumentException x) {
+       // PHPeclipsePlugin.log(x);
+       // }
+       // }
+       //
+       // fActiveRegion = null;
+       // }
+       //
+       // // will eventually be replaced by a method provided by jdt.core
+       // private IRegion selectWord(IDocument document, int anchor) {
+       //
+       // try {
+       // int offset = anchor;
+       // char c;
+       //
+       // while (offset >= 0) {
+       // c = document.getChar(offset);
+       // if (!Scanner.isPHPIdentifierPart(c))
+       // break;
+       // --offset;
+       // }
+       //
+       // int start = offset;
+       //
+       // offset = anchor;
+       // int length = document.getLength();
+       //
+       // while (offset < length) {
+       // c = document.getChar(offset);
+       // if (!Scanner.isPHPIdentifierPart(c))
+       // break;
+       // ++offset;
+       // }
+       //
+       // int end = offset;
+       //
+       // if (start == end)
+       // return new Region(start, 0);
+       // else
+       // return new Region(start + 1, end - start - 1);
+       //
+       // } catch (BadLocationException x) {
+       // return null;
+       // }
+       // }
+       //
+       // IRegion getCurrentTextRegion(ISourceViewer viewer) {
+       //
+       // int offset = getCurrentTextOffset(viewer);
+       // if (offset == -1)
+       // return null;
+       //
+       // return null;
+       // // IJavaElement input= SelectionConverter.getInput(PHPEditor.this);
+       // // if (input == null)
+       // // return null;
+       // //
+       // // try {
+       // //
+       // // IJavaElement[] elements= null;
+       // // synchronized (input) {
+       // // elements= ((ICodeAssist) input).codeSelect(offset, 0);
+       // // }
+       // //
+       // // if (elements == null || elements.length == 0)
+       // // return null;
+       // //
+       // // return selectWord(viewer.getDocument(), offset);
+       // //
+       // // } catch (JavaModelException e) {
+       // // return null;
+       // // }
+       // }
+       //
+       // private int getCurrentTextOffset(ISourceViewer viewer) {
+       //
+       // try {
+       // StyledText text = viewer.getTextWidget();
+       // if (text == null || text.isDisposed())
+       // return -1;
+       //
+       // Display display = text.getDisplay();
+       // Point absolutePosition = display.getCursorLocation();
+       // Point relativePosition = text.toControl(absolutePosition);
+       //
+       // int widgetOffset = text.getOffsetAtLocation(relativePosition);
+       // if (viewer instanceof ITextViewerExtension3) {
+       // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
+       // return extension.widgetOffset2ModelOffset(widgetOffset);
+       // } else {
+       // return widgetOffset + viewer.getVisibleRegion().getOffset();
+       // }
+       //
+       // } catch (IllegalArgumentException e) {
+       // return -1;
+       // }
+       // }
+       //
+       // private void highlightRegion(ISourceViewer viewer, IRegion region) {
+       //
+       // if (region.equals(fActiveRegion))
+       // return;
+       //
+       // repairRepresentation();
+       //
+       // StyledText text = viewer.getTextWidget();
+       // if (text == null || text.isDisposed())
+       // return;
+       //
+       // // highlight region
+       // int offset = 0;
+       // int length = 0;
+       //
+       // if (viewer instanceof ITextViewerExtension3) {
+       // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
+       // IRegion widgetRange = extension.modelRange2WidgetRange(region);
+       // if (widgetRange == null)
+       // return;
+       //
+       // offset = widgetRange.getOffset();
+       // length = widgetRange.getLength();
+       //
+       // } else {
+       // offset = region.getOffset() - viewer.getVisibleRegion().getOffset();
+       // length = region.getLength();
+       // }
+       //
+       // StyleRange oldStyleRange = text.getStyleRangeAtOffset(offset);
+       // Color foregroundColor = fColor;
+       // Color backgroundColor = oldStyleRange == null ? text.getBackground() :
+       // oldStyleRange.background;
+       // StyleRange styleRange = new StyleRange(offset, length, foregroundColor,
+       // backgroundColor);
+       // text.setStyleRange(styleRange);
+       //
+       // // underline
+       // text.redrawRange(offset, length, true);
+       //
+       // fActiveRegion = region;
+       // }
+       //
+       // private void activateCursor(ISourceViewer viewer) {
+       // StyledText text = viewer.getTextWidget();
+       // if (text == null || text.isDisposed())
+       // return;
+       // Display display = text.getDisplay();
+       // if (fCursor == null)
+       // fCursor = new Cursor(display, SWT.CURSOR_HAND);
+       // text.setCursor(fCursor);
+       // }
+       //
+       // private void resetCursor(ISourceViewer viewer) {
+       // StyledText text = viewer.getTextWidget();
+       // if (text != null && !text.isDisposed())
+       // text.setCursor(null);
+       //
+       // if (fCursor != null) {
+       // fCursor.dispose();
+       // fCursor = null;
+       // }
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
+       // */
+       // public void keyPressed(KeyEvent event) {
+       //
+       // if (fActive) {
+       // deactivate();
+       // return;
+       // }
+       //
+       // if (event.keyCode != fKeyModifierMask) {
+       // deactivate();
+       // return;
+       // }
+       //
+       // fActive = true;
+       //
+       // // removed for #25871
+       // //
+       // // ISourceViewer viewer= getSourceViewer();
+       // // if (viewer == null)
+       // // return;
+       // //
+       // // IRegion region= getCurrentTextRegion(viewer);
+       // // if (region == null)
+       // // return;
+       // //
+       // // highlightRegion(viewer, region);
+       // // activateCursor(viewer);
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
+       // */
+       // public void keyReleased(KeyEvent event) {
+       //
+       // if (!fActive)
+       // return;
+       //
+       // deactivate();
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
+       // */
+       // public void mouseDoubleClick(MouseEvent e) {
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
+       // */
+       // public void mouseDown(MouseEvent event) {
+       //
+       // if (!fActive)
+       // return;
+       //
+       // if (event.stateMask != fKeyModifierMask) {
+       // deactivate();
+       // return;
+       // }
+       //
+       // if (event.button != 1) {
+       // deactivate();
+       // return;
+       // }
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
+       // */
+       // public void mouseUp(MouseEvent e) {
+       //
+       // if (!fActive)
+       // return;
+       //
+       // if (e.button != 1) {
+       // deactivate();
+       // return;
+       // }
+       //
+       // boolean wasActive = fCursor != null;
+       //
+       // deactivate();
+       //
+       // if (wasActive) {
+       // IAction action = getAction("OpenEditor"); //$NON-NLS-1$
+       // if (action != null)
+       // action.run();
+       // }
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
+       // */
+       // public void mouseMove(MouseEvent event) {
+       //
+       // if (event.widget instanceof Control && !((Control)
+       // event.widget).isFocusControl()) {
+       // deactivate();
+       // return;
+       // }
+       //
+       // if (!fActive) {
+       // if (event.stateMask != fKeyModifierMask)
+       // return;
+       // // modifier was already pressed
+       // fActive = true;
+       // }
+       //
+       // ISourceViewer viewer = getSourceViewer();
+       // if (viewer == null) {
+       // deactivate();
+       // return;
+       // }
+       //
+       // StyledText text = viewer.getTextWidget();
+       // if (text == null || text.isDisposed()) {
+       // deactivate();
+       // return;
+       // }
+       //
+       // if ((event.stateMask & SWT.BUTTON1) != 0 && text.getSelectionCount() !=
+       // 0)
+       // {
+       // deactivate();
+       // return;
+       // }
+       //
+       // IRegion region = getCurrentTextRegion(viewer);
+       // if (region == null || region.getLength() == 0) {
+       // repairRepresentation();
+       // return;
+       // }
+       //
+       // highlightRegion(viewer, region);
+       // activateCursor(viewer);
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
+       // */
+       // public void focusGained(FocusEvent e) {
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
+       // */
+       // public void focusLost(FocusEvent event) {
+       // deactivate();
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
+       // */
+       // public void documentAboutToBeChanged(DocumentEvent event) {
+       // if (fActive && fActiveRegion != null) {
+       // fRememberedPosition = new Position(fActiveRegion.getOffset(),
+       // fActiveRegion.getLength());
+       // try {
+       // event.getDocument().addPosition(fRememberedPosition);
+       // } catch (BadLocationException x) {
+       // fRememberedPosition = null;
+       // }
+       // }
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
+       // */
+       // public void documentChanged(DocumentEvent event) {
+       // if (fRememberedPosition != null && !fRememberedPosition.isDeleted()) {
+       // event.getDocument().removePosition(fRememberedPosition);
+       // fActiveRegion = new Region(fRememberedPosition.getOffset(),
+       // fRememberedPosition.getLength());
+       // }
+       // fRememberedPosition = null;
+       //
+       // ISourceViewer viewer = getSourceViewer();
+       // if (viewer != null) {
+       // StyledText widget = viewer.getTextWidget();
+       // if (widget != null && !widget.isDisposed()) {
+       // widget.getDisplay().asyncExec(new Runnable() {
+       // public void run() {
+       // deactivate();
+       // }
+       // });
+       // }
+       // }
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument,
+       // * org.eclipse.jface.text.IDocument)
+       // */
+       // public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument
+       // newInput) {
+       // if (oldInput == null)
+       // return;
+       // deactivate();
+       // oldInput.removeDocumentListener(this);
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument,
+       // * org.eclipse.jface.text.IDocument)
+       // */
+       // public void inputDocumentChanged(IDocument oldInput, IDocument newInput)
+       // {
+       // if (newInput == null)
+       // return;
+       // newInput.addDocumentListener(this);
+       // }
+       //
+       // /*
+       // * @see PaintListener#paintControl(PaintEvent)
+       // */
+       // public void paintControl(PaintEvent event) {
+       // if (fActiveRegion == null)
+       // return;
+       //
+       // ISourceViewer viewer = getSourceViewer();
+       // if (viewer == null)
+       // return;
+       //
+       // StyledText text = viewer.getTextWidget();
+       // if (text == null || text.isDisposed())
+       // return;
+       //
+       // int offset = 0;
+       // int length = 0;
+       //
+       // if (viewer instanceof ITextViewerExtension3) {
+       //
+       // ITextViewerExtension3 extension = (ITextViewerExtension3) viewer;
+       // IRegion widgetRange = extension.modelRange2WidgetRange(new Region(offset,
+       // length));
+       // if (widgetRange == null)
+       // return;
+       //
+       // offset = widgetRange.getOffset();
+       // length = widgetRange.getLength();
+       //
+       // } else {
+       //
+       // IRegion region = viewer.getVisibleRegion();
+       // if (!includes(region, fActiveRegion))
+       // return;
+       //
+       // offset = fActiveRegion.getOffset() - region.getOffset();
+       // length = fActiveRegion.getLength();
+       // }
+       //
+       // // support for bidi
+       // Point minLocation = getMinimumLocation(text, offset, length);
+       // Point maxLocation = getMaximumLocation(text, offset, length);
+       //
+       // int x1 = minLocation.x;
+       // int x2 = minLocation.x + maxLocation.x - minLocation.x - 1;
+       // int y = minLocation.y + text.getLineHeight() - 1;
+       //
+       // GC gc = event.gc;
+       // if (fColor != null && !fColor.isDisposed())
+       // gc.setForeground(fColor);
+       // gc.drawLine(x1, y, x2, y);
+       // }
+       //
+       // private boolean includes(IRegion region, IRegion position) {
+       // return position.getOffset() >= region.getOffset()
+       // && position.getOffset() + position.getLength() <= region.getOffset() +
+       // region.getLength();
+       // }
+       //
+       // private Point getMinimumLocation(StyledText text, int offset, int length)
+       // {
+       // Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
+       //
+       // for (int i = 0; i <= length; i++) {
+       // Point location = text.getLocationAtOffset(offset + i);
+       //
+       // if (location.x < minLocation.x)
+       // minLocation.x = location.x;
+       // if (location.y < minLocation.y)
+       // minLocation.y = location.y;
+       // }
+       //
+       // return minLocation;
+       // }
+       //
+       // private Point getMaximumLocation(StyledText text, int offset, int length)
+       // {
+       // Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
+       //
+       // for (int i = 0; i <= length; i++) {
+       // Point location = text.getLocationAtOffset(offset + i);
+       //
+       // if (location.x > maxLocation.x)
+       // maxLocation.x = location.x;
+       // if (location.y > maxLocation.y)
+       // maxLocation.y = location.y;
+       // }
+       //
+       // return maxLocation;
+       // }
+       // };
+       /*
+        * Link mode.
+        */
+       class MouseClickListener implements KeyListener, MouseListener,
+                       MouseMoveListener, FocusListener, PaintListener,
+                       IPropertyChangeListener, IDocumentListener, ITextInputListener,
+                       ITextPresentationListener {
+
+               /** The session is active. */
+               private boolean fActive;
+
+               /** The currently active style range. */
+               private IRegion fActiveRegion;
+
+               /** The currently active style range as position. */
+               private Position fRememberedPosition;
+
+               /** The hand cursor. */
+               private Cursor fCursor;
+
+               /** The link color. */
+               private Color fColor;
+
+               /** The key modifier mask. */
+               private int fKeyModifierMask;
+
+               public void deactivate() {
+                       deactivate(false);
+               }
+
+               public void deactivate(boolean redrawAll) {
+                       if (!fActive)
+                               return;
+
+                       repairRepresentation(redrawAll);
+                       fActive = false;
+               }
+
+               public void install() {
+                       ISourceViewer sourceViewer = getSourceViewer();
+                       if (sourceViewer == null)
+                               return;
+
+                       StyledText text = sourceViewer.getTextWidget();
+                       if (text == null || text.isDisposed())
+                               return;
+
+                       updateColor(sourceViewer);
+
+                       sourceViewer.addTextInputListener(this);
+
+                       IDocument document = sourceViewer.getDocument();
+                       if (document != null)
+                               document.addDocumentListener(this);
+
+                       text.addKeyListener(this);
+                       text.addMouseListener(this);
+                       text.addMouseMoveListener(this);
+                       text.addFocusListener(this);
+                       text.addPaintListener(this);
+
+                       ((ITextViewerExtension4) sourceViewer)
+                                       .addTextPresentationListener(this);
+
+                       updateKeyModifierMask();
+
+                       IPreferenceStore preferenceStore = getPreferenceStore();
+                       preferenceStore.addPropertyChangeListener(this);
+               }
+
+               private void updateKeyModifierMask() {
+                       String modifiers = getPreferenceStore().getString(
+                                       BROWSER_LIKE_LINKS_KEY_MODIFIER);
+                       fKeyModifierMask = computeStateMask(modifiers);
+                       if (fKeyModifierMask == -1) {
+                               // Fall back to stored state mask
+                               fKeyModifierMask = getPreferenceStore().getInt(
+                                               BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK);
+                       }
+               }
+
+               private int computeStateMask(String modifiers) {
+                       if (modifiers == null)
+                               return -1;
+
+                       if (modifiers.length() == 0)
+                               return SWT.NONE;
+
+                       int stateMask = 0;
+                       StringTokenizer modifierTokenizer = new StringTokenizer(modifiers,
+                                       ",;.:+-* "); //$NON-NLS-1$
+                       while (modifierTokenizer.hasMoreTokens()) {
+                               int modifier = EditorUtility
+                                               .findLocalizedModifier(modifierTokenizer.nextToken());
+                               if (modifier == 0 || (stateMask & modifier) == modifier)
+                                       return -1;
+                               stateMask = stateMask | modifier;
+                       }
+                       return stateMask;
+               }
+
+               public void uninstall() {
+
+                       if (fColor != null) {
+                               fColor.dispose();
+                               fColor = null;
+                       }
+
+                       if (fCursor != null) {
+                               fCursor.dispose();
+                               fCursor = null;
+                       }
+
+                       ISourceViewer sourceViewer = getSourceViewer();
+                       if (sourceViewer != null)
+                               sourceViewer.removeTextInputListener(this);
+
+                       IDocumentProvider documentProvider = getDocumentProvider();
+                       if (documentProvider != null) {
+                               IDocument document = documentProvider
+                                               .getDocument(getEditorInput());
+                               if (document != null)
+                                       document.removeDocumentListener(this);
+                       }
+
+                       IPreferenceStore preferenceStore = getPreferenceStore();
+                       if (preferenceStore != null)
+                               preferenceStore.removePropertyChangeListener(this);
+
+                       if (sourceViewer == null)
+                               return;
+
+                       StyledText text = sourceViewer.getTextWidget();
+                       if (text == null || text.isDisposed())
+                               return;
+
+                       text.removeKeyListener(this);
+                       text.removeMouseListener(this);
+                       text.removeMouseMoveListener(this);
+                       text.removeFocusListener(this);
+                       text.removePaintListener(this);
+
+                       ((ITextViewerExtension4) sourceViewer)
+                                       .removeTextPresentationListener(this);
+               }
+
+               /*
+                * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+                */
+               public void propertyChange(PropertyChangeEvent event) {
+                       if (event.getProperty().equals(PHPEditor.LINK_COLOR)) {
+                               ISourceViewer viewer = getSourceViewer();
+                               if (viewer != null)
+                                       updateColor(viewer);
+                       } else if (event.getProperty().equals(
+                                       BROWSER_LIKE_LINKS_KEY_MODIFIER)) {
+                               updateKeyModifierMask();
+                       }
+               }
+
+               private void updateColor(ISourceViewer viewer) {
+                       if (fColor != null)
+                               fColor.dispose();
+
+                       StyledText text = viewer.getTextWidget();
+                       if (text == null || text.isDisposed())
+                               return;
+
+                       Display display = text.getDisplay();
+                       fColor = createColor(getPreferenceStore(), PHPEditor.LINK_COLOR,
+                                       display);
+               }
+
+               /**
+                * Creates a color from the information stored in the given preference
+                * store.
+                * 
+                * @param store
+                *            the preference store
+                * @param key
+                *            the key
+                * @param display
+                *            the display
+                * @return the color or <code>null</code> if there is no such
+                *         information available
+                */
+               private Color createColor(IPreferenceStore store, String key,
+                               Display display) {
+
+                       RGB rgb = null;
+
+                       if (store.contains(key)) {
+
+                               if (store.isDefault(key))
+                                       rgb = PreferenceConverter.getDefaultColor(store, key);
+                               else
+                                       rgb = PreferenceConverter.getColor(store, key);
+
+                               if (rgb != null)
+                                       return new Color(display, rgb);
+                       }
+
+                       return null;
+               }
+
+               private void repairRepresentation() {
+                       repairRepresentation(false);
+               }
+
+               private void repairRepresentation(boolean redrawAll) {
+
+                       if (fActiveRegion == null)
+                               return;
+
+                       int offset = fActiveRegion.getOffset();
+                       int length = fActiveRegion.getLength();
+                       fActiveRegion = null;
+
+                       ISourceViewer viewer = getSourceViewer();
+                       if (viewer != null) {
+
+                               resetCursor(viewer);
+
+                               // Invalidate ==> remove applied text presentation
+                               if (!redrawAll && viewer instanceof ITextViewerExtension2)
+                                       ((ITextViewerExtension2) viewer)
+                                                       .invalidateTextPresentation(offset, length);
+                               else
+                                       viewer.invalidateTextPresentation();
+
+                               // Remove underline
+                               if (viewer instanceof ITextViewerExtension5) {
+                                       ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+                                       offset = extension.modelOffset2WidgetOffset(offset);
+                               } else {
+                                       offset -= viewer.getVisibleRegion().getOffset();
+                               }
+                               try {
+                                       StyledText text = viewer.getTextWidget();
+
+                                       text.redrawRange(offset, length, false);
+                               } catch (IllegalArgumentException x) {
+                                       // JavaPlugin.log(x);
+                               }
+                       }
+               }
+
+               // will eventually be replaced by a method provided by jdt.core
+               private IRegion selectWord(IDocument document, int anchor) {
+
+                       try {
+                               int offset = anchor;
+                               char c;
+
+                               while (offset >= 0) {
+                                       c = document.getChar(offset);
+                                       if (!Scanner.isPHPIdentifierPart(c) && c != '$')
+                                               break;
+                                       --offset;
+                               }
+
+                               int start = offset;
+
+                               offset = anchor;
+                               int length = document.getLength();
+
+                               while (offset < length) {
+                                       c = document.getChar(offset);
+                                       if (!Scanner.isPHPIdentifierPart(c) && c != '$')
+                                               break;
+                                       ++offset;
+                               }
+
+                               int end = offset;
+
+                               if (start == end)
+                                       return new Region(start, 0);
+                               else
+                                       return new Region(start + 1, end - start - 1);
+
+                       } catch (BadLocationException x) {
+                               return null;
+                       }
+               }
+
+               IRegion getCurrentTextRegion(ISourceViewer viewer) {
+
+                       int offset = getCurrentTextOffset(viewer);
+                       if (offset == -1)
+                               return null;
+
+                       IJavaElement input = SelectionConverter.getInput(PHPEditor.this);
+                       if (input == null)
+                               return null;
+
+                       // try {
+
+                       // IJavaElement[] elements= null;
+                       // synchronized (input) {
+                       // elements= ((ICodeAssist) input).codeSelect(offset, 0);
+                       // }
+                       //
+                       // if (elements == null || elements.length == 0)
+                       // return null;
+
+                       return selectWord(viewer.getDocument(), offset);
+
+                       // } catch (JavaModelException e) {
+                       // return null;
+                       // }
+               }
+
+               private int getCurrentTextOffset(ISourceViewer viewer) {
+
+                       try {
+                               StyledText text = viewer.getTextWidget();
+                               if (text == null || text.isDisposed())
+                                       return -1;
+
+                               Display display = text.getDisplay();
+                               Point absolutePosition = display.getCursorLocation();
+                               Point relativePosition = text.toControl(absolutePosition);
+
+                               int widgetOffset = text.getOffsetAtLocation(relativePosition);
+                               if (viewer instanceof ITextViewerExtension5) {
+                                       ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+                                       return extension.widgetOffset2ModelOffset(widgetOffset);
+                               } else {
+                                       return widgetOffset + viewer.getVisibleRegion().getOffset();
+                               }
+
+                       } catch (IllegalArgumentException e) {
+                               return -1;
+                       }
+               }
+
+               public void applyTextPresentation(TextPresentation textPresentation) {
+                       if (fActiveRegion == null)
+                               return;
+                       IRegion region = textPresentation.getExtent();
+                       if (fActiveRegion.getOffset() + fActiveRegion.getLength() >= region
+                                       .getOffset()
+                                       && region.getOffset() + region.getLength() > fActiveRegion
+                                                       .getOffset())
+                               textPresentation.mergeStyleRange(new StyleRange(fActiveRegion
+                                               .getOffset(), fActiveRegion.getLength(), fColor, null));
+               }
+
+               private void highlightRegion(ISourceViewer viewer, IRegion region) {
+
+                       if (region.equals(fActiveRegion))
+                               return;
+
+                       repairRepresentation();
+
+                       StyledText text = viewer.getTextWidget();
+                       if (text == null || text.isDisposed())
+                               return;
+
+                       // Underline
+                       int offset = 0;
+                       int length = 0;
+                       if (viewer instanceof ITextViewerExtension5) {
+                               ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+                               IRegion widgetRange = extension.modelRange2WidgetRange(region);
+                               if (widgetRange == null)
+                                       return;
+
+                               offset = widgetRange.getOffset();
+                               length = widgetRange.getLength();
+
+                       } else {
+                               offset = region.getOffset()
+                                               - viewer.getVisibleRegion().getOffset();
+                               length = region.getLength();
+                       }
+                       text.redrawRange(offset, length, false);
+
+                       // Invalidate region ==> apply text presentation
+                       fActiveRegion = region;
+                       if (viewer instanceof ITextViewerExtension2)
+                               ((ITextViewerExtension2) viewer).invalidateTextPresentation(
+                                               region.getOffset(), region.getLength());
+                       else
+                               viewer.invalidateTextPresentation();
+               }
+
+               private void activateCursor(ISourceViewer viewer) {
+                       StyledText text = viewer.getTextWidget();
+                       if (text == null || text.isDisposed())
+                               return;
+                       Display display = text.getDisplay();
+                       if (fCursor == null)
+                               fCursor = new Cursor(display, SWT.CURSOR_HAND);
+                       text.setCursor(fCursor);
+               }
+
+               private void resetCursor(ISourceViewer viewer) {
+                       StyledText text = viewer.getTextWidget();
+                       if (text != null && !text.isDisposed())
+                               text.setCursor(null);
+
+                       if (fCursor != null) {
+                               fCursor.dispose();
+                               fCursor = null;
+                       }
+               }
+
+               /*
+                * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
+                */
+               public void keyPressed(KeyEvent event) {
+
+                       if (fActive) {
+                               deactivate();
+                               return;
+                       }
+
+                       if (event.keyCode != fKeyModifierMask) {
+                               deactivate();
+                               return;
+                       }
+
+                       fActive = true;
+
+                       // removed for #25871
+                       //
+                       // ISourceViewer viewer= getSourceViewer();
+                       // if (viewer == null)
+                       // return;
+                       //
+                       // IRegion region= getCurrentTextRegion(viewer);
+                       // if (region == null)
+                       // return;
+                       //
+                       // highlightRegion(viewer, region);
+                       // activateCursor(viewer);
+               }
+
+               /*
+                * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
+                */
+               public void keyReleased(KeyEvent event) {
+
+                       if (!fActive)
+                               return;
+
+                       deactivate();
+               }
+
+               /*
+                * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
+                */
+               public void mouseDoubleClick(MouseEvent e) {
+               }
+
+               /*
+                * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
+                */
+               public void mouseDown(MouseEvent event) {
+
+                       if (!fActive)
+                               return;
+
+                       if (event.stateMask != fKeyModifierMask) {
+                               deactivate();
+                               return;
+                       }
+
+                       if (event.button != 1) {
+                               deactivate();
+                               return;
+                       }
+               }
+
+               /*
+                * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
+                */
+               public void mouseUp(MouseEvent e) {
+
+                       if (!fActive)
+                               return;
+
+                       if (e.button != 1) {
+                               deactivate();
+                               return;
+                       }
+
+                       boolean wasActive = fCursor != null;
+
+                       deactivate();
+
+                       if (wasActive) {
+                               IAction action = getAction("OpenEditor"); //$NON-NLS-1$
+                               if (action != null)
+                                       action.run();
+                       }
+               }
+
+               /*
+                * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
+                */
+               public void mouseMove(MouseEvent event) {
+
+                       if (event.widget instanceof Control
+                                       && !((Control) event.widget).isFocusControl()) {
+                               deactivate();
+                               return;
+                       }
+
+                       if (!fActive) {
+                               if (event.stateMask != fKeyModifierMask)
+                                       return;
+                               // modifier was already pressed
+                               fActive = true;
+                       }
+
+                       ISourceViewer viewer = getSourceViewer();
+                       if (viewer == null) {
+                               deactivate();
+                               return;
+                       }
+
+                       StyledText text = viewer.getTextWidget();
+                       if (text == null || text.isDisposed()) {
+                               deactivate();
+                               return;
+                       }
+
+                       if ((event.stateMask & SWT.BUTTON1) != 0
+                                       && text.getSelectionCount() != 0) {
+                               deactivate();
+                               return;
+                       }
+
+                       IRegion region = getCurrentTextRegion(viewer);
+                       if (region == null || region.getLength() == 0) {
+                               repairRepresentation();
+                               return;
+                       }
+
+                       highlightRegion(viewer, region);
+                       activateCursor(viewer);
+               }
+
+               /*
+                * @see org.eclipse.swt.events.FocusListener#focusGained(org.eclipse.swt.events.FocusEvent)
+                */
+               public void focusGained(FocusEvent e) {
+               }
+
+               /*
+                * @see org.eclipse.swt.events.FocusListener#focusLost(org.eclipse.swt.events.FocusEvent)
+                */
+               public void focusLost(FocusEvent event) {
+                       deactivate();
+               }
+
+               /*
+                * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
+                */
+               public void documentAboutToBeChanged(DocumentEvent event) {
+                       if (fActive && fActiveRegion != null) {
+                               fRememberedPosition = new Position(fActiveRegion.getOffset(),
+                                               fActiveRegion.getLength());
+                               try {
+                                       event.getDocument().addPosition(fRememberedPosition);
+                               } catch (BadLocationException x) {
+                                       fRememberedPosition = null;
+                               }
+                       }
+               }
+
+               /*
+                * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
+                */
+               public void documentChanged(DocumentEvent event) {
+                       if (fRememberedPosition != null) {
+                               if (!fRememberedPosition.isDeleted()) {
+
+                                       event.getDocument().removePosition(fRememberedPosition);
+                                       fActiveRegion = new Region(fRememberedPosition.getOffset(),
+                                                       fRememberedPosition.getLength());
+                                       fRememberedPosition = null;
+
+                                       ISourceViewer viewer = getSourceViewer();
+                                       if (viewer != null) {
+                                               StyledText widget = viewer.getTextWidget();
+                                               if (widget != null && !widget.isDisposed()) {
+                                                       widget.getDisplay().asyncExec(new Runnable() {
+                                                               public void run() {
+                                                                       deactivate();
+                                                               }
+                                                       });
+                                               }
+                                       }
+
+                               } else {
+                                       fActiveRegion = null;
+                                       fRememberedPosition = null;
+                                       deactivate();
+                               }
+                       }
+               }
+
+               /*
+                * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument,
+                *      org.eclipse.jface.text.IDocument)
+                */
+               public void inputDocumentAboutToBeChanged(IDocument oldInput,
+                               IDocument newInput) {
+                       if (oldInput == null)
+                               return;
+                       deactivate();
+                       oldInput.removeDocumentListener(this);
+               }
+
+               /*
+                * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument,
+                *      org.eclipse.jface.text.IDocument)
+                */
+               public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
+                       if (newInput == null)
+                               return;
+                       newInput.addDocumentListener(this);
+               }
+
+               /*
+                * @see PaintListener#paintControl(PaintEvent)
+                */
+               public void paintControl(PaintEvent event) {
+                       if (fActiveRegion == null)
+                               return;
+
+                       ISourceViewer viewer = getSourceViewer();
+                       if (viewer == null)
+                               return;
+
+                       StyledText text = viewer.getTextWidget();
+                       if (text == null || text.isDisposed())
+                               return;
+
+                       int offset = 0;
+                       int length = 0;
+
+                       if (viewer instanceof ITextViewerExtension5) {
+
+                               ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+                               IRegion widgetRange = extension
+                                               .modelRange2WidgetRange(fActiveRegion);
+                               if (widgetRange == null)
+                                       return;
+
+                               offset = widgetRange.getOffset();
+                               length = widgetRange.getLength();
+
+                       } else {
+
+                               IRegion region = viewer.getVisibleRegion();
+                               if (!includes(region, fActiveRegion))
+                                       return;
+
+                               offset = fActiveRegion.getOffset() - region.getOffset();
+                               length = fActiveRegion.getLength();
+                       }
+
+                       // support for bidi
+                       Point minLocation = getMinimumLocation(text, offset, length);
+                       Point maxLocation = getMaximumLocation(text, offset, length);
+
+                       int x1 = minLocation.x;
+                       int x2 = minLocation.x + maxLocation.x - minLocation.x - 1;
+                       int y = minLocation.y + text.getLineHeight() - 1;
+
+                       GC gc = event.gc;
+                       if (fColor != null && !fColor.isDisposed())
+                               gc.setForeground(fColor);
+                       gc.drawLine(x1, y, x2, y);
+               }
+
+               private boolean includes(IRegion region, IRegion position) {
+                       return position.getOffset() >= region.getOffset()
+                                       && position.getOffset() + position.getLength() <= region
+                                                       .getOffset()
+                                                       + region.getLength();
+               }
+
+               private Point getMinimumLocation(StyledText text, int offset, int length) {
+                       Point minLocation = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
+
+                       for (int i = 0; i <= length; i++) {
+                               Point location = text.getLocationAtOffset(offset + i);
+
+                               if (location.x < minLocation.x)
+                                       minLocation.x = location.x;
+                               if (location.y < minLocation.y)
+                                       minLocation.y = location.y;
+                       }
+
+                       return minLocation;
+               }
+
+               private Point getMaximumLocation(StyledText text, int offset, int length) {
+                       Point maxLocation = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
+
+                       for (int i = 0; i <= length; i++) {
+                               Point location = text.getLocationAtOffset(offset + i);
+
+                               if (location.x > maxLocation.x)
+                                       maxLocation.x = location.x;
+                               if (location.y > maxLocation.y)
+                                       maxLocation.y = location.y;
+                       }
+
+                       return maxLocation;
+               }
+       }
+
+       /**
+        * This action dispatches into two behaviours: If there is no current text
+        * hover, the javadoc is displayed using information presenter. If there is
+        * a current text hover, it is converted into a information presenter in
+        * order to make it sticky.
+        */
+       class InformationDispatchAction extends TextEditorAction {
+
+               /** The wrapped text operation action. */
+               private final TextOperationAction fTextOperationAction;
+
+               /**
+                * Creates a dispatch action.
+                */
+               public InformationDispatchAction(ResourceBundle resourceBundle,
+                               String prefix, final TextOperationAction textOperationAction) {
+                       super(resourceBundle, prefix, PHPEditor.this);
+                       if (textOperationAction == null)
+                               throw new IllegalArgumentException();
+                       fTextOperationAction = textOperationAction;
+               }
+
+               /*
+                * @see org.eclipse.jface.action.IAction#run()
+                */
+               public void run() {
+
+                       ISourceViewer sourceViewer = getSourceViewer();
+                       if (sourceViewer == null) {
+                               fTextOperationAction.run();
+                               return;
+                       }
+
+                       if (!(sourceViewer instanceof ITextViewerExtension2)) {
+                               fTextOperationAction.run();
+                               return;
+                       }
+
+                       ITextViewerExtension2 textViewerExtension2 = (ITextViewerExtension2) sourceViewer;
+
+                       // does a text hover exist?
+                       ITextHover textHover = textViewerExtension2.getCurrentTextHover();
+                       if (textHover == null) {
+                               fTextOperationAction.run();
+                               return;
+                       }
+
+                       Point hoverEventLocation = textViewerExtension2
+                                       .getHoverEventLocation();
+                       int offset = computeOffsetAtLocation(sourceViewer,
+                                       hoverEventLocation.x, hoverEventLocation.y);
+                       if (offset == -1) {
+                               fTextOperationAction.run();
+                               return;
+                       }
+
+                       try {
+                               // get the text hover content
+                               IDocument document = sourceViewer.getDocument();
+                               String contentType = document.getContentType(offset);
+
+                               final IRegion hoverRegion = textHover.getHoverRegion(
+                                               sourceViewer, offset);
+                               if (hoverRegion == null)
+                                       return;
+
+                               final String hoverInfo = textHover.getHoverInfo(sourceViewer,
+                                               hoverRegion);
+
+                               // with information provider
+                               IInformationProvider informationProvider = new IInformationProvider() {
+                                       /*
+                                        * @see org.eclipse.jface.text.information.IInformationProvider#getSubject(org.eclipse.jface.text.ITextViewer,
+                                        *      int)
+                                        */
+                                       public IRegion getSubject(ITextViewer textViewer, int offset) {
+                                               return hoverRegion;
+                                       }
+
+                                       /*
+                                        * @see org.eclipse.jface.text.information.IInformationProvider#getInformation(org.eclipse.jface.text.ITextViewer,
+                                        *      org.eclipse.jface.text.IRegion)
+                                        */
+                                       public String getInformation(ITextViewer textViewer,
+                                                       IRegion subject) {
+                                               return hoverInfo;
+                                       }
+                               };
+
+                               fInformationPresenter.setOffset(offset);
+                               fInformationPresenter.setInformationProvider(
+                                               informationProvider, contentType);
+                               fInformationPresenter.showInformation();
+
+                       } catch (BadLocationException e) {
+                       }
+               }
+
+               // modified version from TextViewer
+               private int computeOffsetAtLocation(ITextViewer textViewer, int x, int y) {
+
+                       StyledText styledText = textViewer.getTextWidget();
+                       IDocument document = textViewer.getDocument();
+
+                       if (document == null)
+                               return -1;
+
+                       try {
+                               int widgetLocation = styledText.getOffsetAtLocation(new Point(
+                                               x, y));
+                               if (textViewer instanceof ITextViewerExtension5) {
+                                       ITextViewerExtension5 extension = (ITextViewerExtension5) textViewer;
+                                       return extension.widgetOffset2ModelOffset(widgetLocation);
+                               } else {
+                                       IRegion visibleRegion = textViewer.getVisibleRegion();
+                                       return widgetLocation + visibleRegion.getOffset();
+                               }
+                       } catch (IllegalArgumentException e) {
+                               return -1;
+                       }
+
+               }
+       };
+
+       /**
+        * This action implements smart home.
+        * 
+        * Instead of going to the start of a line it does the following: - if smart
+        * home/end is enabled and the caret is after the line's first
+        * non-whitespace then the caret is moved directly before it, taking JavaDoc
+        * and multi-line comments into account. - if the caret is before the line's
+        * first non-whitespace the caret is moved to the beginning of the line - if
+        * the caret is at the beginning of the line see first case.
+        * 
+        * @since 3.0
+        */
+       protected class SmartLineStartAction extends LineStartAction {
+
+               /**
+                * Creates a new smart line start action
+                * 
+                * @param textWidget
+                *            the styled text widget
+                * @param doSelect
+                *            a boolean flag which tells if the text up to the beginning
+                *            of the line should be selected
+                */
+               public SmartLineStartAction(final StyledText textWidget,
+                               final boolean doSelect) {
+                       super(textWidget, doSelect);
+               }
+
+               /*
+                * @see org.eclipse.ui.texteditor.AbstractTextEditor.LineStartAction#getLineStartPosition(java.lang.String,
+                *      int, java.lang.String)
+                */
+               protected int getLineStartPosition(final IDocument document,
+                               final String line, final int length, final int offset) {
+
+                       String type = IDocument.DEFAULT_CONTENT_TYPE;
+                       try {
+                               type = TextUtilities.getContentType(document,
+                                               IPHPPartitions.PHP_PARTITIONING, offset, true);
+                       } catch (BadLocationException exception) {
+                               // Should not happen
+                       }
+
+                       int index = super.getLineStartPosition(document, line, length,
+                                       offset);
+                       if (type.equals(IPHPPartitions.PHP_PHPDOC_COMMENT)
+                                       || type.equals(IPHPPartitions.PHP_MULTILINE_COMMENT)) {
+                               if (index < length - 1 && line.charAt(index) == '*'
+                                               && line.charAt(index + 1) != '/') {
+                                       do {
+                                               ++index;
+                                       } while (index < length
+                                                       && Character.isWhitespace(line.charAt(index)));
+                               }
+                       } else {
+                               if (index < length - 1 && line.charAt(index) == '/'
+                                               && line.charAt(index + 1) == '/') {
+                                       index++;
+                                       do {
+                                               ++index;
+                                       } while (index < length
+                                                       && Character.isWhitespace(line.charAt(index)));
+                               }
+                       }
+                       return index;
+               }
+       }
+
+       /**
+        * Text navigation action to navigate to the next sub-word.
+        * 
+        * @since 3.0
+        */
+       protected abstract class NextSubWordAction extends TextNavigationAction {
+
+               protected JavaWordIterator fIterator = new JavaWordIterator();
+
+               /**
+                * Creates a new next sub-word action.
+                * 
+                * @param code
+                *            Action code for the default operation. Must be an action
+                *            code from
+                * @see org.eclipse.swt.custom.ST.
+                */
+               protected NextSubWordAction(int code) {
+                       super(getSourceViewer().getTextWidget(), code);
+               }
+
+               /*
+                * @see org.eclipse.jface.action.IAction#run()
+                */
+               public void run() {
+                       // Check whether we are in a java code partition and the preference
+                       // is
+                       // enabled
+                       final IPreferenceStore store = getPreferenceStore();
+                       if (!store
+                                       .getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) {
+                               super.run();
+                               return;
+                       }
+
+                       final ISourceViewer viewer = getSourceViewer();
+                       final IDocument document = viewer.getDocument();
+                       fIterator
+                                       .setText((CharacterIterator) new DocumentCharacterIterator(
+                                                       document));
+                       int position = widgetOffset2ModelOffset(viewer, viewer
+                                       .getTextWidget().getCaretOffset());
+                       if (position == -1)
+                               return;
+
+                       int next = findNextPosition(position);
+                       if (next != BreakIterator.DONE) {
+                               setCaretPosition(next);
+                               getTextWidget().showSelection();
+                               fireSelectionChanged();
+                       }
+
+               }
+
+               /**
+                * Finds the next position after the given position.
+                * 
+                * @param position
+                *            the current position
+                * @return the next position
+                */
+               protected int findNextPosition(int position) {
+                       ISourceViewer viewer = getSourceViewer();
+                       int widget = -1;
+                       while (position != BreakIterator.DONE && widget == -1) { // TODO:
+                               // optimize
+                               position = fIterator.following(position);
+                               if (position != BreakIterator.DONE)
+                                       widget = modelOffset2WidgetOffset(viewer, position);
+                       }
+                       return position;
+               }
+
+               /**
+                * Sets the caret position to the sub-word boundary given with
+                * <code>position</code>.
+                * 
+                * @param position
+                *            Position where the action should move the caret
+                */
+               protected abstract void setCaretPosition(int position);
+       }
+
+       /**
+        * Text navigation action to navigate to the next sub-word.
+        * 
+        * @since 3.0
+        */
+       protected class NavigateNextSubWordAction extends NextSubWordAction {
+
+               /**
+                * Creates a new navigate next sub-word action.
+                */
+               public NavigateNextSubWordAction() {
+                       super(ST.WORD_NEXT);
+               }
+
+               /*
+                * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
+                */
+               protected void setCaretPosition(final int position) {
+                       getTextWidget().setCaretOffset(
+                                       modelOffset2WidgetOffset(getSourceViewer(), position));
+               }
+       }
+
+       /**
+        * Text operation action to delete the next sub-word.
+        * 
+        * @since 3.0
+        */
+       protected class DeleteNextSubWordAction extends NextSubWordAction implements
+                       IUpdate {
+
+               /**
+                * Creates a new delete next sub-word action.
+                */
+               public DeleteNextSubWordAction() {
+                       super(ST.DELETE_WORD_NEXT);
+               }
+
+               /*
+                * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
+                */
+               protected void setCaretPosition(final int position) {
+                       if (!validateEditorInputState())
+                               return;
+
+                       final ISourceViewer viewer = getSourceViewer();
+                       final int caret = widgetOffset2ModelOffset(viewer, viewer
+                                       .getTextWidget().getCaretOffset());
+
+                       try {
+                               viewer.getDocument().replace(caret, position - caret, ""); //$NON-NLS-1$
+                       } catch (BadLocationException exception) {
+                               // Should not happen
+                       }
+               }
+
+               /*
+                * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#findNextPosition(int)
+                */
+               protected int findNextPosition(int position) {
+                       return fIterator.following(position);
+               }
+
+               /*
+                * @see org.eclipse.ui.texteditor.IUpdate#update()
+                */
+               public void update() {
+                       setEnabled(isEditorInputModifiable());
+               }
+       }
+
+       /**
+        * Text operation action to select the next sub-word.
+        * 
+        * @since 3.0
+        */
+       protected class SelectNextSubWordAction extends NextSubWordAction {
+
+               /**
+                * Creates a new select next sub-word action.
+                */
+               public SelectNextSubWordAction() {
+                       super(ST.SELECT_WORD_NEXT);
+               }
+
+               /*
+                * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.NextSubWordAction#setCaretPosition(int)
+                */
+               protected void setCaretPosition(final int position) {
+                       final ISourceViewer viewer = getSourceViewer();
+
+                       final StyledText text = viewer.getTextWidget();
+                       if (text != null && !text.isDisposed()) {
+
+                               final Point selection = text.getSelection();
+                               final int caret = text.getCaretOffset();
+                               final int offset = modelOffset2WidgetOffset(viewer, position);
+
+                               if (caret == selection.x)
+                                       text.setSelectionRange(selection.y, offset - selection.y);
+                               else
+                                       text.setSelectionRange(selection.x, offset - selection.x);
+                       }
+               }
+       }
+
+       /**
+        * Text navigation action to navigate to the previous sub-word.
+        * 
+        * @since 3.0
+        */
+       protected abstract class PreviousSubWordAction extends TextNavigationAction {
+
+               protected JavaWordIterator fIterator = new JavaWordIterator();
+
+               /**
+                * Creates a new previous sub-word action.
+                * 
+                * @param code
+                *            Action code for the default operation. Must be an action
+                *            code from
+                * @see org.eclipse.swt.custom.ST.
+                */
+               protected PreviousSubWordAction(final int code) {
+                       super(getSourceViewer().getTextWidget(), code);
+               }
+
+               /*
+                * @see org.eclipse.jface.action.IAction#run()
+                */
+               public void run() {
+                       // Check whether we are in a java code partition and the preference
+                       // is
+                       // enabled
+                       final IPreferenceStore store = getPreferenceStore();
+                       if (!store
+                                       .getBoolean(PreferenceConstants.EDITOR_SUB_WORD_NAVIGATION)) {
+                               super.run();
+                               return;
+                       }
+
+                       final ISourceViewer viewer = getSourceViewer();
+                       final IDocument document = viewer.getDocument();
+                       fIterator
+                                       .setText((CharacterIterator) new DocumentCharacterIterator(
+                                                       document));
+                       int position = widgetOffset2ModelOffset(viewer, viewer
+                                       .getTextWidget().getCaretOffset());
+                       if (position == -1)
+                               return;
+
+                       int previous = findPreviousPosition(position);
+                       if (previous != BreakIterator.DONE) {
+                               setCaretPosition(previous);
+                               getTextWidget().showSelection();
+                               fireSelectionChanged();
+                       }
+
+               }
+
+               /**
+                * Finds the previous position before the given position.
+                * 
+                * @param position
+                *            the current position
+                * @return the previous position
+                */
+               protected int findPreviousPosition(int position) {
+                       ISourceViewer viewer = getSourceViewer();
+                       int widget = -1;
+                       while (position != BreakIterator.DONE && widget == -1) { // TODO:
+                               // optimize
+                               position = fIterator.preceding(position);
+                               if (position != BreakIterator.DONE)
+                                       widget = modelOffset2WidgetOffset(viewer, position);
+                       }
+                       return position;
+               }
+
+               /**
+                * Sets the caret position to the sub-word boundary given with
+                * <code>position</code>.
+                * 
+                * @param position
+                *            Position where the action should move the caret
+                */
+               protected abstract void setCaretPosition(int position);
+       }
+
+       /**
+        * Text navigation action to navigate to the previous sub-word.
+        * 
+        * @since 3.0
+        */
+       protected class NavigatePreviousSubWordAction extends PreviousSubWordAction {
+
+               /**
+                * Creates a new navigate previous sub-word action.
+                */
+               public NavigatePreviousSubWordAction() {
+                       super(ST.WORD_PREVIOUS);
+               }
+
+               /*
+                * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
+                */
+               protected void setCaretPosition(final int position) {
+                       getTextWidget().setCaretOffset(
+                                       modelOffset2WidgetOffset(getSourceViewer(), position));
+               }
+       }
+
+       /**
+        * Text operation action to delete the previous sub-word.
+        * 
+        * @since 3.0
+        */
+       protected class DeletePreviousSubWordAction extends PreviousSubWordAction
+                       implements IUpdate {
+
+               /**
+                * Creates a new delete previous sub-word action.
+                */
+               public DeletePreviousSubWordAction() {
+                       super(ST.DELETE_WORD_PREVIOUS);
+               }
+
+               /*
+                * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
+                */
+               protected void setCaretPosition(final int position) {
+                       if (!validateEditorInputState())
+                               return;
+
+                       final ISourceViewer viewer = getSourceViewer();
+                       final int caret = widgetOffset2ModelOffset(viewer, viewer
+                                       .getTextWidget().getCaretOffset());
+
+                       try {
+                               viewer.getDocument().replace(position, caret - position, ""); //$NON-NLS-1$
+                       } catch (BadLocationException exception) {
+                               // Should not happen
+                       }
+               }
+
+               /*
+                * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#findPreviousPosition(int)
+                */
+               protected int findPreviousPosition(int position) {
+                       return fIterator.preceding(position);
+               }
+
+               /*
+                * @see org.eclipse.ui.texteditor.IUpdate#update()
+                */
+               public void update() {
+                       setEnabled(isEditorInputModifiable());
+               }
+       }
+
+       /**
+        * Text operation action to select the previous sub-word.
+        * 
+        * @since 3.0
+        */
+       protected class SelectPreviousSubWordAction extends PreviousSubWordAction {
+
+               /**
+                * Creates a new select previous sub-word action.
+                */
+               public SelectPreviousSubWordAction() {
+                       super(ST.SELECT_WORD_PREVIOUS);
+               }
+
+               /*
+                * @see net.sourceforge.phpdt.internal.ui.javaeditor.JavaEditor.PreviousSubWordAction#setCaretPosition(int)
+                */
+               protected void setCaretPosition(final int position) {
+                       final ISourceViewer viewer = getSourceViewer();
+
+                       final StyledText text = viewer.getTextWidget();
+                       if (text != null && !text.isDisposed()) {
+
+                               final Point selection = text.getSelection();
+                               final int caret = text.getCaretOffset();
+                               final int offset = modelOffset2WidgetOffset(viewer, position);
+
+                               if (caret == selection.x)
+                                       text.setSelectionRange(selection.y, offset - selection.y);
+                               else
+                                       text.setSelectionRange(selection.x, offset - selection.x);
+                       }
+               }
+       }
+
+       // static protected class AnnotationAccess implements IAnnotationAccess {
+       // /*
+       // * @see
+       // org.eclipse.jface.text.source.IAnnotationAccess#getType(org.eclipse.jface.text.source.Annotation)
+       // */
+       // public Object getType(Annotation annotation) {
+       // if (annotation instanceof IJavaAnnotation) {
+       // IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
+       // // if (javaAnnotation.isRelevant())
+       // // return javaAnnotation.getAnnotationType();
+       // }
+       // return null;
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.jface.text.source.IAnnotationAccess#isMultiLine(org.eclipse.jface.text.source.Annotation)
+       // */
+       // public boolean isMultiLine(Annotation annotation) {
+       // return true;
+       // }
+       //
+       // /*
+       // * @see
+       // org.eclipse.jface.text.source.IAnnotationAccess#isTemporary(org.eclipse.jface.text.source.Annotation)
+       // */
+       // public boolean isTemporary(Annotation annotation) {
+       // if (annotation instanceof IJavaAnnotation) {
+       // IJavaAnnotation javaAnnotation = (IJavaAnnotation) annotation;
+       // if (javaAnnotation.isRelevant())
+       // return javaAnnotation.isTemporary();
+       // }
+       // return false;
+       // }
+       // };
+
+       private class PropertyChangeListener implements
+                       org.eclipse.core.runtime.Preferences.IPropertyChangeListener {
+               /*
+                * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+                */
+               public void propertyChange(
+                               org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
+                       handlePreferencePropertyChanged(event);
+               }
+       };
+
+       /**
+        * Finds and marks occurrence annotations.
+        * 
+        * @since 3.0
+        */
+       class OccurrencesFinderJob extends Job {
+
+               private IDocument fDocument;
+
+               private ISelection fSelection;
+
+               private ISelectionValidator fPostSelectionValidator;
+
+               private boolean fCanceled = false;
+
+               private IProgressMonitor fProgressMonitor;
+
+               private Position[] fPositions;
+
+               public OccurrencesFinderJob(IDocument document, Position[] positions,
+                               ISelection selection) {
+                       super(PHPEditorMessages.JavaEditor_markOccurrences_job_name);
+                       fDocument = document;
+                       fSelection = selection;
+                       fPositions = positions;
+
+                       if (getSelectionProvider() instanceof ISelectionValidator)
+                               fPostSelectionValidator = (ISelectionValidator) getSelectionProvider();
+               }
+
+               // cannot use cancel() because it is declared final
+               void doCancel() {
+                       fCanceled = true;
+                       cancel();
+               }
+
+               private boolean isCanceled() {
+                       return fCanceled
+                                       || fProgressMonitor.isCanceled()
+                                       || fPostSelectionValidator != null
+                                       && !(fPostSelectionValidator.isValid(fSelection) || fForcedMarkOccurrencesSelection == fSelection)
+                                       || LinkedModeModel.hasInstalledModel(fDocument);
+               }
+
+               /*
+                * @see Job#run(org.eclipse.core.runtime.IProgressMonitor)
+                */
+               public IStatus run(IProgressMonitor progressMonitor) {
+
+                       fProgressMonitor = progressMonitor;
+
+                       if (isCanceled())
+                               return Status.CANCEL_STATUS;
+
+                       ITextViewer textViewer = getViewer();
+                       if (textViewer == null)
+                               return Status.CANCEL_STATUS;
+
+                       IDocument document = textViewer.getDocument();
+                       if (document == null)
+                               return Status.CANCEL_STATUS;
+
+                       IDocumentProvider documentProvider = getDocumentProvider();
+                       if (documentProvider == null)
+                               return Status.CANCEL_STATUS;
+
+                       IAnnotationModel annotationModel = documentProvider
+                                       .getAnnotationModel(getEditorInput());
+                       if (annotationModel == null)
+                               return Status.CANCEL_STATUS;
+
+                       // Add occurrence annotations
+                       int length = fPositions.length;
+                       Map annotationMap = new HashMap(length);
+                       for (int i = 0; i < length; i++) {
+
+                               if (isCanceled())
+                                       return Status.CANCEL_STATUS;
+
+                               String message;
+                               Position position = fPositions[i];
+
+                               // Create & add annotation
+                               try {
+                                       message = document.get(position.offset, position.length);
+                               } catch (BadLocationException ex) {
+                                       // Skip this match
+                                       continue;
+                               }
+                               annotationMap
+                                               .put(
+                                                               new Annotation(
+                                                                               "net.sourceforge.phpdt.ui.occurrences", false, message), //$NON-NLS-1$
+                                                               position);
+                       }
+
+                       if (isCanceled())
+                               return Status.CANCEL_STATUS;
+
+                       synchronized (getLockObject(annotationModel)) {
+                               if (annotationModel instanceof IAnnotationModelExtension) {
+                                       ((IAnnotationModelExtension) annotationModel)
+                                                       .replaceAnnotations(fOccurrenceAnnotations,
+                                                                       annotationMap);
+                               } else {
+                                       removeOccurrenceAnnotations();
+                                       Iterator iter = annotationMap.entrySet().iterator();
+                                       while (iter.hasNext()) {
+                                               Map.Entry mapEntry = (Map.Entry) iter.next();
+                                               annotationModel.addAnnotation((Annotation) mapEntry
+                                                               .getKey(), (Position) mapEntry.getValue());
+                                       }
+                               }
+                               fOccurrenceAnnotations = (Annotation[]) annotationMap.keySet()
+                                               .toArray(new Annotation[annotationMap.keySet().size()]);
+                       }
+
+                       return Status.OK_STATUS;
+               }
+       }
+
+       /**
+        * Cancels the occurrences finder job upon document changes.
+        * 
+        * @since 3.0
+        */
+       class OccurrencesFinderJobCanceler implements IDocumentListener,
+                       ITextInputListener {
+
+               public void install() {
+                       ISourceViewer sourceViewer = getSourceViewer();
+                       if (sourceViewer == null)
+                               return;
+
+                       StyledText text = sourceViewer.getTextWidget();
+                       if (text == null || text.isDisposed())
+                               return;
+
+                       sourceViewer.addTextInputListener(this);
+
+                       IDocument document = sourceViewer.getDocument();
+                       if (document != null)
+                               document.addDocumentListener(this);
+               }
+
+               public void uninstall() {
+                       ISourceViewer sourceViewer = getSourceViewer();
+                       if (sourceViewer != null)
+                               sourceViewer.removeTextInputListener(this);
+
+                       IDocumentProvider documentProvider = getDocumentProvider();
+                       if (documentProvider != null) {
+                               IDocument document = documentProvider
+                                               .getDocument(getEditorInput());
+                               if (document != null)
+                                       document.removeDocumentListener(this);
+                       }
+               }
+
+               /*
+                * @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
+                */
+               public void documentAboutToBeChanged(DocumentEvent event) {
+                       if (fOccurrencesFinderJob != null)
+                               fOccurrencesFinderJob.doCancel();
+               }
+
+               /*
+                * @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
+                */
+               public void documentChanged(DocumentEvent event) {
+               }
+
+               /*
+                * @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument,
+                *      org.eclipse.jface.text.IDocument)
+                */
+               public void inputDocumentAboutToBeChanged(IDocument oldInput,
+                               IDocument newInput) {
+                       if (oldInput == null)
+                               return;
+
+                       oldInput.removeDocumentListener(this);
+               }
+
+               /*
+                * @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument,
+                *      org.eclipse.jface.text.IDocument)
+                */
+               public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
+                       if (newInput == null)
+                               return;
+                       newInput.addDocumentListener(this);
+               }
+       }
+
+       /**
+        * Internal activation listener.
+        * 
+        * @since 3.0
+        */
+       private class ActivationListener implements IWindowListener {
+
+               /*
+                * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
+                * @since 3.1
+                */
+               public void windowActivated(IWorkbenchWindow window) {
+                       if (window == getEditorSite().getWorkbenchWindow()
+                                       && fMarkOccurrenceAnnotations && isActivePart()) {
+                               fForcedMarkOccurrencesSelection = getSelectionProvider()
+                                               .getSelection();
+                               SelectionListenerWithASTManager
+                                               .getDefault()
+                                               .forceSelectionChange(
+                                                               PHPEditor.this,
+                                                               (ITextSelection) fForcedMarkOccurrencesSelection);
+                       }
+               }
+
+               /*
+                * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow)
+                * @since 3.1
+                */
+               public void windowDeactivated(IWorkbenchWindow window) {
+                       if (window == getEditorSite().getWorkbenchWindow()
+                                       && fMarkOccurrenceAnnotations && isActivePart())
+                               removeOccurrenceAnnotations();
+               }
+
+               /*
+                * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow)
+                * @since 3.1
+                */
+               public void windowClosed(IWorkbenchWindow window) {
+               }
+
+               /*
+                * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow)
+                * @since 3.1
+                */
+               public void windowOpened(IWorkbenchWindow window) {
+               }
+       }
+
+       /**
+        * Updates the selection in the editor's widget with the selection of the
+        * outline page.
+        */
+       class OutlineSelectionChangedListener extends
+                       AbstractSelectionChangedListener {
+               public void selectionChanged(SelectionChangedEvent event) {
+                       doSelectionChanged(event);
+               }
+       }
+
+       /**
+        * The internal shell activation listener for updating occurrences.
+        * 
+        * @since 3.0
+        */
+       private ActivationListener fActivationListener = new ActivationListener();
+
+       private ISelectionListenerWithAST fPostSelectionListenerWithAST;
+
+       private OccurrencesFinderJob fOccurrencesFinderJob;
+
+       /** The occurrences finder job canceler */
+       private OccurrencesFinderJobCanceler fOccurrencesFinderJobCanceler;
+
+       /**
+        * Holds the current occurrence annotations.
+        * 
+        * @since 3.0
+        */
+       private Annotation[] fOccurrenceAnnotations = null;
+
+       /**
+        * Tells whether all occurrences of the element at the current caret
+        * location are automatically marked in this editor.
+        * 
+        * @since 3.0
+        */
+       private boolean fMarkOccurrenceAnnotations;
+
+       /**
+        * The selection used when forcing occurrence marking through code.
+        * 
+        * @since 3.0
+        */
+       private ISelection fForcedMarkOccurrencesSelection;
+
+       /**
+        * The document modification stamp at the time when the last occurrence
+        * marking took place.
+        * 
+        * @since 3.1
+        */
+       private long fMarkOccurrenceModificationStamp = IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
+
+       /**
+        * The region of the word under the caret used to when computing the current
+        * occurrence markings.
+        * 
+        * @since 3.1
+        */
+       private IRegion fMarkOccurrenceTargetRegion;
+
+       /**
+        * Tells whether the occurrence annotations are sticky i.e. whether they
+        * stay even if there's no valid Java element at the current caret position.
+        * Only valid if {@link #fMarkOccurrenceAnnotations} is <code>true</code>.
+        * 
+        * @since 3.0
+        */
+       private boolean fStickyOccurrenceAnnotations;
+
+       /** Preference key for showing the line number ruler */
+       // private final static String LINE_NUMBER_RULER =
+       // PreferenceConstants.EDITOR_LINE_NUMBER_RULER;
+       /** Preference key for the foreground color of the line numbers */
+       // private final static String LINE_NUMBER_COLOR =
+       // PreferenceConstants.EDITOR_LINE_NUMBER_RULER_COLOR;
+       /** Preference key for the link color */
+       private final static String LINK_COLOR = PreferenceConstants.EDITOR_LINK_COLOR;
+
+       /** Preference key for compiler task tags */
+       private final static String COMPILER_TASK_TAGS = JavaCore.COMPILER_TASK_TAGS;
+
+       // protected PHPActionGroup fActionGroups;
+       // /** The outline page */
+       // private AbstractContentOutlinePage fOutlinePage;
+       /** The outline page */
+       protected JavaOutlinePage fOutlinePage;
+
+       /** Outliner context menu Id */
+       protected String fOutlinerContextMenuId;
+
+       /**
+        * Indicates whether this editor should react on outline page selection
+        * changes
+        */
+       private int fIgnoreOutlinePageSelection;
+
+       /** The outline page selection updater */
+       // private OutlinePageSelectionUpdater fUpdater;
+       // protected PHPSyntaxParserThread fValidationThread = null;
+       // private IPreferenceStore fPHPPrefStore;
+       /** The selection changed listener */
+       // protected ISelectionChangedListener fSelectionChangedListener = new
+       // SelectionChangedListener();
+       /**
+        * The editor selection changed listener.
+        * 
+        * @since 3.0
+        */
+       private EditorSelectionChangedListener fEditorSelectionChangedListener;
+
+       /** The selection changed listener */
+       protected AbstractSelectionChangedListener fOutlineSelectionChangedListener = new OutlineSelectionChangedListener();
+
+       /** The editor's bracket matcher */
+       private PHPPairMatcher fBracketMatcher = new PHPPairMatcher(BRACKETS);
+
+       /** The line number ruler column */
+       // private LineNumberRulerColumn fLineNumberRulerColumn;
+       /** This editor's encoding support */
+       private DefaultEncodingSupport fEncodingSupport;
+
+       /** The mouse listener */
+       private MouseClickListener fMouseListener;
+
+       /**
+        * Indicates whether this editor is about to update any annotation views.
+        * 
+        * @since 3.0
+        */
+       private boolean fIsUpdatingAnnotationViews = false;
+
+       /**
+        * The marker that served as last target for a goto marker request.
+        * 
+        * @since 3.0
+        */
+       private IMarker fLastMarkerTarget = null;
+
+       protected CompositeActionGroup fActionGroups;
+
+       protected CompositeActionGroup fContextMenuGroup;
+
+       /**
+        * This editor's projection support
+        * 
+        * @since 3.0
+        */
+       private ProjectionSupport fProjectionSupport;
+
+       /**
+        * This editor's projection model updater
+        * 
+        * @since 3.0
+        */
+       private IJavaFoldingStructureProvider fProjectionModelUpdater;
+
+       /**
+        * The override and implements indicator manager for this editor.
+        * 
+        * @since 3.0
+        */
+       // protected OverrideIndicatorManager fOverrideIndicatorManager;
+       /**
+        * The action group for folding.
+        * 
+        * @since 3.0
+        */
+       private FoldingActionGroup fFoldingGroup;
+
+       /** The information presenter. */
+       private InformationPresenter fInformationPresenter;
+
+       /** The annotation access */
+       // protected IAnnotationAccess fAnnotationAccess = new AnnotationAccess();
+       /** The overview ruler */
+       protected OverviewRuler isOverviewRulerVisible;
+
+       /** The source viewer decoration support */
+       // protected SourceViewerDecorationSupport fSourceViewerDecorationSupport;
+       /** The overview ruler */
+       // protected OverviewRuler fOverviewRuler;
+       /** The preference property change listener for java core. */
+       private org.eclipse.core.runtime.Preferences.IPropertyChangeListener fPropertyChangeListener = new PropertyChangeListener();
+
+       /**
+        * Returns the most narrow java element including the given offset
+        * 
+        * @param offset
+        *            the offset inside of the requested element
+        */
+       abstract protected IJavaElement getElementAt(int offset);
+
+       /**
+        * Returns the java element of this editor's input corresponding to the
+        * given IJavaElement
+        */
+       abstract protected IJavaElement getCorrespondingElement(IJavaElement element);
+
+       /**
+        * Sets the input of the editor's outline page.
+        */
+       abstract protected void setOutlinePageInput(JavaOutlinePage page,
+                       IEditorInput input);
+
+       /**
+        * Default constructor.
+        */
+       public PHPEditor() {
+               super();
+       }
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeKeyBindingScopes()
+        */
+       protected void initializeKeyBindingScopes() {
+               setKeyBindingScopes(new String[] { "net.sourceforge.phpdt.ui.phpEditorScope" }); //$NON-NLS-1$
+       }
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#initializeEditor()
+        */
+       protected void initializeEditor() {
+               // jsurfer old code
+               // JavaTextTools textTools =
+               // PHPeclipsePlugin.getDefault().getJavaTextTools();
+               // setSourceViewerConfiguration(new
+               // PHPSourceViewerConfiguration(textTools,
+               // this, IPHPPartitions.PHP_PARTITIONING)); //,
+               // IJavaPartitions.JAVA_PARTITIONING));
+               IPreferenceStore store = createCombinedPreferenceStore(null);
+               setPreferenceStore(store);
+               JavaTextTools textTools = PHPeclipsePlugin.getDefault()
+                               .getJavaTextTools();
+               setSourceViewerConfiguration(new PHPSourceViewerConfiguration(textTools
+                               .getColorManager(), store, this,
+                               IPHPPartitions.PHP_PARTITIONING));
+
+               // TODO changed in 3.x ?
+               // setRangeIndicator(new DefaultRangeIndicator());
+               // if
+               // (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
+               // fUpdater = new OutlinePageSelectionUpdater();
+               // jsurfer end
+
+               // IPreferenceStore store= createCombinedPreferenceStore(null);
+               // setPreferenceStore(store);
+               // JavaTextTools textTools=
+               // PHPeclipsePlugin.getDefault().getJavaTextTools();
+               // setSourceViewerConfiguration(new
+               // JavaSourceViewerConfiguration(textTools.getColorManager(), store,
+               // this, IJavaPartitions.JAVA_PARTITIONING));
+               fMarkOccurrenceAnnotations = store
+                               .getBoolean(PreferenceConstants.EDITOR_MARK_OCCURRENCES);
+               fStickyOccurrenceAnnotations = store
+                               .getBoolean(PreferenceConstants.EDITOR_STICKY_OCCURRENCES);
+               // fMarkTypeOccurrences=
+               // store.getBoolean(PreferenceConstants.EDITOR_MARK_TYPE_OCCURRENCES);
+               // fMarkMethodOccurrences=
+               // store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_OCCURRENCES);
+               // fMarkConstantOccurrences=
+               // store.getBoolean(PreferenceConstants.EDITOR_MARK_CONSTANT_OCCURRENCES);
+               // fMarkFieldOccurrences=
+               // store.getBoolean(PreferenceConstants.EDITOR_MARK_FIELD_OCCURRENCES);
+               // fMarkLocalVariableypeOccurrences=
+               // store.getBoolean(PreferenceConstants.EDITOR_MARK_LOCAL_VARIABLE_OCCURRENCES);
+               // fMarkExceptions=
+               // store.getBoolean(PreferenceConstants.EDITOR_MARK_EXCEPTION_OCCURRENCES);
+               // fMarkImplementors=
+               // store.getBoolean(PreferenceConstants.EDITOR_MARK_IMPLEMENTORS);
+               // fMarkMethodExitPoints=
+               // store.getBoolean(PreferenceConstants.EDITOR_MARK_METHOD_EXIT_POINTS);
+
+       }
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractTextEditor#updatePropertyDependentActions()
+        */
+       protected void updatePropertyDependentActions() {
+               super.updatePropertyDependentActions();
+               if (fEncodingSupport != null)
+                       fEncodingSupport.reset();
+       }
+
+       /*
+        * Update the hovering behavior depending on the preferences.
+        */
+       private void updateHoverBehavior() {
+               SourceViewerConfiguration configuration = getSourceViewerConfiguration();
+               String[] types = configuration
+                               .getConfiguredContentTypes(getSourceViewer());
+
+               for (int i = 0; i < types.length; i++) {
+
+                       String t = types[i];
+
+                       int[] stateMasks = configuration.getConfiguredTextHoverStateMasks(
+                                       getSourceViewer(), t);
+
+                       ISourceViewer sourceViewer = getSourceViewer();
+                       if (sourceViewer instanceof ITextViewerExtension2) {
+                               if (stateMasks != null) {
+                                       for (int j = 0; j < stateMasks.length; j++) {
+                                               int stateMask = stateMasks[j];
+                                               ITextHover textHover = configuration.getTextHover(
+                                                               sourceViewer, t, stateMask);
+                                               ((ITextViewerExtension2) sourceViewer).setTextHover(
+                                                               textHover, t, stateMask);
+                                       }
+                               } else {
+                                       ITextHover textHover = configuration.getTextHover(
+                                                       sourceViewer, t);
+                                       ((ITextViewerExtension2) sourceViewer).setTextHover(
+                                                       textHover, t,
+                                                       ITextViewerExtension2.DEFAULT_HOVER_STATE_MASK);
+                               }
+                       } else
+                               sourceViewer.setTextHover(configuration.getTextHover(
+                                               sourceViewer, t), t);
+               }
+       }
+
+       public void updatedTitleImage(Image image) {
+               setTitleImage(image);
+       }
+
+       /*
+        * @see net.sourceforge.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
+        */
+       public Object getViewPartInput() {
+               return getEditorInput().getAdapter(IResource.class);
+       }
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractTextEditor#doSetSelection(ISelection)
+        */
+       protected void doSetSelection(ISelection selection) {
+               super.doSetSelection(selection);
+               synchronizeOutlinePageSelection();
+       }
+
+       boolean isFoldingEnabled() {
+               return PHPeclipsePlugin.getDefault().getPreferenceStore().getBoolean(
+                               PreferenceConstants.EDITOR_FOLDING_ENABLED);
+       }
+
+       /*
+        * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.
+        *      widgets.Composite)
+        */
+       public void createPartControl(Composite parent) {
+               super.createPartControl(parent);
+
+               // fSourceViewerDecorationSupport.install(getPreferenceStore());
+
+               ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer();
+
+               fProjectionSupport = new ProjectionSupport(projectionViewer,
+                               getAnnotationAccess(), getSharedColors());
+               fProjectionSupport
+                               .addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.error"); //$NON-NLS-1$
+               fProjectionSupport
+                               .addSummarizableAnnotationType("org.eclipse.ui.workbench.texteditor.warning"); //$NON-NLS-1$
+               fProjectionSupport
+                               .setHoverControlCreator(new IInformationControlCreator() {
+                                       public IInformationControl createInformationControl(
+                                                       Shell shell) {
+                                               return new CustomSourceInformationControl(shell,
+                                                               IDocument.DEFAULT_CONTENT_TYPE);
+                                       }
+                               });
+               fProjectionSupport.install();
+
+               fProjectionModelUpdater = PHPeclipsePlugin.getDefault()
+                               .getFoldingStructureProviderRegistry()
+                               .getCurrentFoldingProvider();
+               if (fProjectionModelUpdater != null)
+                       fProjectionModelUpdater.install(this, projectionViewer);
+
+               if (isFoldingEnabled())
+                       projectionViewer.doOperation(ProjectionViewer.TOGGLE);
+               Preferences preferences = PHPeclipsePlugin.getDefault()
+                               .getPluginPreferences();
+               preferences.addPropertyChangeListener(fPropertyChangeListener);
+
+               IInformationControlCreator informationControlCreator = new IInformationControlCreator() {
+                       public IInformationControl createInformationControl(Shell parent) {
+                               boolean cutDown = false;
+                               int style = cutDown ? SWT.NONE : (SWT.V_SCROLL | SWT.H_SCROLL);
+                               return new DefaultInformationControl(parent, SWT.RESIZE, style,
+                                               new HTMLTextPresenter(cutDown));
+                       }
+               };
+
+               fInformationPresenter = new InformationPresenter(
+                               informationControlCreator);
+               fInformationPresenter.setSizeConstraints(60, 10, true, true);
+               fInformationPresenter.install(getSourceViewer());
+
+               fEditorSelectionChangedListener = new EditorSelectionChangedListener();
+               fEditorSelectionChangedListener.install(getSelectionProvider());
+
+               if (isBrowserLikeLinks())
+                       enableBrowserLikeLinks();
+
+               if (PreferenceConstants.getPreferenceStore().getBoolean(
+                               PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE))
+                       enableOverwriteMode(false);
+
+               if (fMarkOccurrenceAnnotations)
+                       installOccurrencesFinder();
+
+               PlatformUI.getWorkbench().addWindowListener(fActivationListener);
+
+               setWordWrap();
+       }
+
+       private void setWordWrap() {
+               if (getSourceViewer() != null) {
+                       getSourceViewer().getTextWidget().setWordWrap(
+                                       PHPeclipsePlugin.getDefault().getPreferenceStore()
+                                                       .getBoolean(PreferenceConstants.EDITOR_WRAP_WORDS));
+               }
+       }
+
+       protected void configureSourceViewerDecorationSupport(
+                       SourceViewerDecorationSupport support) {
+
+               support.setCharacterPairMatcher(fBracketMatcher);
+               support.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS,
+                               MATCHING_BRACKETS_COLOR);
+
+               super.configureSourceViewerDecorationSupport(support);
+       }
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractTextEditor#gotoMarker(org.eclipse.core.resources.IMarker)
+        */
+       public void gotoMarker(IMarker marker) {
+               fLastMarkerTarget = marker;
+               if (!fIsUpdatingAnnotationViews) {
+                       super.gotoMarker(marker);
+               }
+       }
+
+       /**
+        * Jumps to the next enabled annotation according to the given direction. An
+        * annotation type is enabled if it is configured to be in the Next/Previous
+        * tool bar drop down menu and if it is checked.
+        * 
+        * @param forward
+        *            <code>true</code> if search direction is forward,
+        *            <code>false</code> if backward
+        */
+       public Annotation gotoAnnotation(boolean forward) {
+               ITextSelection selection = (ITextSelection) getSelectionProvider()
+                               .getSelection();
+               Position position = new Position(0, 0);
+               Annotation annotation = null;
+               if (false /* delayed - see bug 18316 */) {
+                       annotation = getNextAnnotation(selection.getOffset(), selection
+                                       .getLength(), forward, position);
+                       selectAndReveal(position.getOffset(), position.getLength());
+               } else /* no delay - see bug 18316 */{
+                       annotation = getNextAnnotation(selection.getOffset(), selection
+                                       .getLength(), forward, position);
+                       setStatusLineErrorMessage(null);
+                       setStatusLineMessage(null);
+                       if (annotation != null) {
+                               updateAnnotationViews(annotation);
+                               selectAndReveal(position.getOffset(), position.getLength());
+                               setStatusLineMessage(annotation.getText());
+                       }
+               }
+               return annotation;
+       }
+
+       /**
+        * Returns the lock object for the given annotation model.
+        * 
+        * @param annotationModel
+        *            the annotation model
+        * @return the annotation model's lock object
+        * @since 3.0
+        */
+       private Object getLockObject(IAnnotationModel annotationModel) {
+               if (annotationModel instanceof ISynchronizable)
+                       return ((ISynchronizable) annotationModel).getLockObject();
+               else
+                       return annotationModel;
+       }
+
+       /**
+        * Updates the annotation views that show the given annotation.
+        * 
+        * @param annotation
+        *            the annotation
+        */
+       private void updateAnnotationViews(Annotation annotation) {
+               IMarker marker = null;
+               if (annotation instanceof MarkerAnnotation)
+                       marker = ((MarkerAnnotation) annotation).getMarker();
+               else if (annotation instanceof IJavaAnnotation) {
+                       Iterator e = ((IJavaAnnotation) annotation).getOverlaidIterator();
+                       if (e != null) {
+                               while (e.hasNext()) {
+                                       Object o = e.next();
+                                       if (o instanceof MarkerAnnotation) {
+                                               marker = ((MarkerAnnotation) o).getMarker();
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               if (marker != null && !marker.equals(fLastMarkerTarget)) {
+                       try {
+                               boolean isProblem = marker.isSubtypeOf(IMarker.PROBLEM);
+                               IWorkbenchPage page = getSite().getPage();
+                               IViewPart view = page
+                                               .findView(isProblem ? IPageLayout.ID_PROBLEM_VIEW
+                                                               : IPageLayout.ID_TASK_LIST); //$NON-NLS-1$  //$NON-NLS-2$
+                               if (view != null) {
+                                       Method method = view
+                                                       .getClass()
+                                                       .getMethod(
+                                                                       "setSelection", new Class[] { IStructuredSelection.class, boolean.class }); //$NON-NLS-1$
+                                       method.invoke(view, new Object[] {
+                                                       new StructuredSelection(marker), Boolean.TRUE });
+                               }
+                       } catch (CoreException x) {
+                       } catch (NoSuchMethodException x) {
+                       } catch (IllegalAccessException x) {
+                       } catch (InvocationTargetException x) {
+                       }
+                       // ignore exceptions, don't update any of the lists, just set status
+                       // line
+               }
+       }
+
+       /**
+        * Returns this document's complete text.
+        * 
+        * @return the document's complete text
+        */
+       public String get() {
+               IDocument doc = this.getDocumentProvider().getDocument(
+                               this.getEditorInput());
+               return doc.get();
+       }
+
+       /**
+        * Sets the outliner's context menu ID.
+        */
+       protected void setOutlinerContextMenuId(String menuId) {
+               fOutlinerContextMenuId = menuId;
+       }
+
+       /**
+        * Returns the standard action group of this editor.
+        */
+       protected ActionGroup getActionGroup() {
+               return fActionGroups;
+       }
+
+       // public JavaOutlinePage getfOutlinePage() {
+       // return fOutlinePage;
+       // }
+
+       /**
+        * The <code>PHPEditor</code> implementation of this
+        * <code>AbstractTextEditor</code> method extend the actions to add those
+        * specific to the receiver
+        */
+       protected void createActions() {
+               super.createActions();
+
+               ActionGroup oeg, ovg, jsg, sg;
+               fActionGroups = new CompositeActionGroup(
+                               new ActionGroup[] { oeg = new OpenEditorActionGroup(this),
+                               // sg= new ShowActionGroup(this),
+                               // ovg= new OpenViewActionGroup(this),
+                               // jsg= new JavaSearchActionGroup(this)
+                               });
+               fContextMenuGroup = new CompositeActionGroup(new ActionGroup[] { oeg });
+               // , ovg, sg, jsg});
+
+               fFoldingGroup = new FoldingActionGroup(this, getViewer());
+
+               // ResourceAction resAction = new
+               // TextOperationAction(PHPEditorMessages.getResourceBundle(),
+               // "ShowJavaDoc.", this, ISourceViewer.INFORMATION, true); //$NON-NLS-1$
+               // resAction = new
+               // InformationDispatchAction(PHPEditorMessages.getResourceBundle(),
+               // "ShowJavaDoc.", (TextOperationAction) resAction); //$NON-NLS-1$
+               // resAction.setActionDefinitionId(net.sourceforge.phpdt.ui.actions.PHPEditorActionDefinitionIds.SHOW_JAVADOC);
+               // setAction("ShowJavaDoc", resAction); //$NON-NLS-1$
+
+               // WorkbenchHelp.setHelp(resAction,
+               // IJavaHelpContextIds.SHOW_JAVADOC_ACTION);
+
+               Action action = new GotoMatchingBracketAction(this);
+               action
+                               .setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_MATCHING_BRACKET);
+               setAction(GotoMatchingBracketAction.GOTO_MATCHING_BRACKET, action);
+
+               // action= new
+               // TextOperationAction(PHPEditorMessages.getResourceBundle(),"ShowOutline.",
+               // this, JavaSourceViewer.SHOW_OUTLINE, true); //$NON-NLS-1$
+               // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE);
+               // setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE, action);
+               // // WorkbenchHelp.setHelp(action,
+               // IJavaHelpContextIds.SHOW_OUTLINE_ACTION);
+               //
+               // action= new
+               // TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenStructure.",
+               // this, JavaSourceViewer.OPEN_STRUCTURE, true); //$NON-NLS-1$
+               // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE);
+               // setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_STRUCTURE,
+               // action);
+               // // WorkbenchHelp.setHelp(action,
+               // IJavaHelpContextIds.OPEN_STRUCTURE_ACTION);
+               //
+               // action= new
+               // TextOperationAction(PHPEditorMessages.getResourceBundle(),"OpenHierarchy.",
+               // this, JavaSourceViewer.SHOW_HIERARCHY, true); //$NON-NLS-1$
+               // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY);
+               // setAction(PHPEditorActionDefinitionIds.SHOW_OUTLINE.OPEN_HIERARCHY,
+               // action);
+               // // WorkbenchHelp.setHelp(action,
+               // IJavaHelpContextIds.OPEN_HIERARCHY_ACTION);
+
+               fEncodingSupport = new DefaultEncodingSupport();
+               fEncodingSupport.initialize(this);
+
+               // fSelectionHistory= new SelectionHistory(this);
+               //
+               // action= new StructureSelectEnclosingAction(this, fSelectionHistory);
+               // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_ENCLOSING);
+               // setAction(StructureSelectionAction.ENCLOSING, action);
+               //
+               // action= new StructureSelectNextAction(this, fSelectionHistory);
+               // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_NEXT);
+               // setAction(StructureSelectionAction.NEXT, action);
+               //
+               // action= new StructureSelectPreviousAction(this, fSelectionHistory);
+               // action.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_PREVIOUS);
+               // setAction(StructureSelectionAction.PREVIOUS, action);
+               //
+               // StructureSelectHistoryAction historyAction= new
+               // StructureSelectHistoryAction(this, fSelectionHistory);
+               // historyAction.setActionDefinitionId(PHPEditorActionDefinitionIds.SELECT_LAST);
+               // setAction(StructureSelectionAction.HISTORY, historyAction);
+               // fSelectionHistory.setHistoryAction(historyAction);
+               //
+               // action= GoToNextPreviousMemberAction.newGoToNextMemberAction(this);
+               // action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_NEXT_MEMBER);
+               // setAction(GoToNextPreviousMemberAction.NEXT_MEMBER, action);
+               //
+               // action=
+               // GoToNextPreviousMemberAction.newGoToPreviousMemberAction(this);
+               // action.setActionDefinitionId(PHPEditorActionDefinitionIds.GOTO_PREVIOUS_MEMBER);
+               // setAction(GoToNextPreviousMemberAction.PREVIOUS_MEMBER, action);
+               //
+               // action= new QuickFormatAction();
+               // action.setActionDefinitionId(PHPEditorActionDefinitionIds.QUICK_FORMAT);
+               // setAction(IJavaEditorActionDefinitionIds.QUICK_FORMAT, action);
+               //
+               // action= new RemoveOccurrenceAnnotations(this);
+               // action.setActionDefinitionId(PHPEditorActionDefinitionIds.REMOVE_OCCURRENCE_ANNOTATIONS);
+               // setAction("RemoveOccurrenceAnnotations", action); //$NON-NLS-1$
+
+               // add annotation actions
+               action = new JavaSelectMarkerRulerAction2(PHPEditorMessages
+                               .getResourceBundle(), "Editor.RulerAnnotationSelection.", this); //$NON-NLS-1$
+               setAction("AnnotationAction", action); //$NON-NLS-1$
+       }
+
+       private void internalDoSetInput(IEditorInput input) throws CoreException {
+               super.doSetInput(input);
+
+               if (getSourceViewer() instanceof JavaSourceViewer) {
+                       JavaSourceViewer viewer = (JavaSourceViewer) getSourceViewer();
+                       if (viewer.getReconciler() == null) {
+                               IReconciler reconciler = getSourceViewerConfiguration()
+                                               .getReconciler(viewer);
+                               if (reconciler != null) {
+                                       reconciler.install(viewer);
+                                       viewer.setReconciler(reconciler);
+                               }
+                       }
+               }
+
+               if (fEncodingSupport != null)
+                       fEncodingSupport.reset();
+
+               setOutlinePageInput(fOutlinePage, input);
+
+               if (fProjectionModelUpdater != null)
+                       fProjectionModelUpdater.initialize();
+
+               // if (isShowingOverrideIndicators())
+               // installOverrideIndicator(false);
+       }
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractTextEditor#setPreferenceStore(org.eclipse.jface.preference.IPreferenceStore)
+        * @since 3.0
+        */
+       protected void setPreferenceStore(IPreferenceStore store) {
+               super.setPreferenceStore(store);
+               if (getSourceViewerConfiguration() instanceof PHPSourceViewerConfiguration) {
+                       JavaTextTools textTools = PHPeclipsePlugin.getDefault()
+                                       .getJavaTextTools();
+                       setSourceViewerConfiguration(new PHPSourceViewerConfiguration(
+                                       textTools.getColorManager(), store, this,
+                                       IPHPPartitions.PHP_PARTITIONING));
+               }
+               if (getSourceViewer() instanceof JavaSourceViewer)
+                       ((JavaSourceViewer) getSourceViewer()).setPreferenceStore(store);
+       }
+
+       /**
+        * The <code>PHPEditor</code> implementation of this
+        * <code>AbstractTextEditor</code> method performs any extra disposal
+        * actions required by the php editor.
+        */
+       public void dispose() {
+               if (fProjectionModelUpdater != null) {
+                       fProjectionModelUpdater.uninstall();
+                       fProjectionModelUpdater = null;
+               }
+
+               if (fProjectionSupport != null) {
+                       fProjectionSupport.dispose();
+                       fProjectionSupport = null;
+               }
+               // PHPEditorEnvironment.disconnect(this);
+               if (fOutlinePage != null)
+                       fOutlinePage.setInput(null);
+
+               if (fActionGroups != null)
+                       fActionGroups.dispose();
+
+               if (isBrowserLikeLinks())
+                       disableBrowserLikeLinks();
+
+               // cancel possible running computation
+               fMarkOccurrenceAnnotations = false;
+               uninstallOccurrencesFinder();
+
+               uninstallOverrideIndicator();
+
+               if (fActivationListener != null) {
+                       PlatformUI.getWorkbench().removeWindowListener(fActivationListener);
+                       fActivationListener = null;
+               }
+
+               if (fEncodingSupport != null) {
+                       fEncodingSupport.dispose();
+                       fEncodingSupport = null;
+               }
+
+               if (fPropertyChangeListener != null) {
+                       Preferences preferences = PHPeclipsePlugin.getDefault()
+                                       .getPluginPreferences();
+                       preferences.removePropertyChangeListener(fPropertyChangeListener);
+                       fPropertyChangeListener = null;
+               }
+
+               // if (fSourceViewerDecorationSupport != null) {
+               // fSourceViewerDecorationSupport.dispose();
+               // fSourceViewerDecorationSupport = null;
+               // }
+
+               if (fBracketMatcher != null) {
+                       fBracketMatcher.dispose();
+                       fBracketMatcher = null;
+               }
+
+               if (fEditorSelectionChangedListener != null) {
+                       fEditorSelectionChangedListener.uninstall(getSelectionProvider());
+                       fEditorSelectionChangedListener = null;
+               }
+
+               super.dispose();
+       }
+
+       /**
+        * The <code>PHPEditor</code> implementation of this
+        * <code>AbstractTextEditor</code> method performs any extra revert
+        * behavior required by the php editor.
+        */
+       // public void doRevertToSaved() {
+       // super.doRevertToSaved();
+       // if (fOutlinePage != null)
+       // fOutlinePage.update();
+       // }
+       /**
+        * The <code>PHPEditor</code> implementation of this
+        * <code>AbstractTextEditor</code> method performs any extra save behavior
+        * required by the php editor.
+        */
+       // public void doSave(IProgressMonitor monitor) {
+       // super.doSave(monitor);
+       // compile or not, according to the user preferences
+       // IPreferenceStore store = getPreferenceStore();
+       // the parse on save was changed to the eclipse "builders" concept
+       // if (store.getBoolean(PHPeclipsePlugin.PHP_PARSE_ON_SAVE)) {
+       // IAction a = PHPParserAction.getInstance();
+       // if (a != null)
+       // a.run();
+       // }
+       // if (SWT.getPlatform().equals("win32")) {
+       // IAction a = ShowExternalPreviewAction.getInstance();
+       // if (a != null)
+       // a.run();
+       // }
+       // if (fOutlinePage != null)
+       // fOutlinePage.update();
+       // }
+       /**
+        * The <code>PHPEditor</code> implementation of this
+        * <code>AbstractTextEditor</code> method performs any extra save as
+        * behavior required by the php editor.
+        */
+       // public void doSaveAs() {
+       // super.doSaveAs();
+       // if (fOutlinePage != null)
+       // fOutlinePage.update();
+       // }
+       /*
+        * @see StatusTextEditor#getStatusHeader(IStatus)
+        */
+       protected String getStatusHeader(IStatus status) {
+               if (fEncodingSupport != null) {
+                       String message = fEncodingSupport.getStatusHeader(status);
+                       if (message != null)
+                               return message;
+               }
+               return super.getStatusHeader(status);
+       }
+
+       /*
+        * @see StatusTextEditor#getStatusBanner(IStatus)
+        */
+       protected String getStatusBanner(IStatus status) {
+               if (fEncodingSupport != null) {
+                       String message = fEncodingSupport.getStatusBanner(status);
+                       if (message != null)
+                               return message;
+               }
+               return super.getStatusBanner(status);
+       }
+
+       /*
+        * @see StatusTextEditor#getStatusMessage(IStatus)
+        */
+       protected String getStatusMessage(IStatus status) {
+               if (fEncodingSupport != null) {
+                       String message = fEncodingSupport.getStatusMessage(status);
+                       if (message != null)
+                               return message;
+               }
+               return super.getStatusMessage(status);
+       }
+
+       /**
+        * The <code>PHPEditor</code> implementation of this
+        * <code>AbstractTextEditor</code> method performs sets the input of the
+        * outline page after AbstractTextEditor has set input.
+        */
+       // protected void doSetInput(IEditorInput input) throws CoreException {
+       // super.doSetInput(input);
+       // if (fEncodingSupport != null)
+       // fEncodingSupport.reset();
+       // setOutlinePageInput(fOutlinePage, input);
+       // }
+       /*
+        * @see AbstractTextEditor#doSetInput
+        */
+       protected void doSetInput(IEditorInput input) throws CoreException {
+               ISourceViewer sourceViewer = getSourceViewer();
+               if (!(sourceViewer instanceof ISourceViewerExtension2)) {
+                       setPreferenceStore(createCombinedPreferenceStore(input));
+                       internalDoSetInput(input);
+                       return;
+               }
+
+               // uninstall & unregister preference store listener
+               if (isBrowserLikeLinks())
+                       disableBrowserLikeLinks();
+               getSourceViewerDecorationSupport(sourceViewer).uninstall();
+               ((ISourceViewerExtension2) sourceViewer).unconfigure();
+
+               setPreferenceStore(createCombinedPreferenceStore(input));
+
+               // install & register preference store listener
+               sourceViewer.configure(getSourceViewerConfiguration());
+               getSourceViewerDecorationSupport(sourceViewer).install(
+                               getPreferenceStore());
+               if (isBrowserLikeLinks())
+                       enableBrowserLikeLinks();
+
+               internalDoSetInput(input);
+       }
+
+       /*
+        * @see org.phpeclipse.phpdt.internal.ui.viewsupport.IViewPartInputProvider#getViewPartInput()
+        */
+       // public Object getViewPartInput() {
+       // return getEditorInput().getAdapter(IFile.class);
+       // }
+       /**
+        * The <code>PHPEditor</code> implementation of this
+        * <code>AbstractTextEditor</code> method adds any PHPEditor specific
+        * entries.
+        */
+       public void editorContextMenuAboutToShow(MenuManager menu) {
+               super.editorContextMenuAboutToShow(menu);
+               menu.appendToGroup(ITextEditorActionConstants.GROUP_UNDO,
+                               new Separator(IContextMenuConstants.GROUP_OPEN));
+               menu.insertAfter(IContextMenuConstants.GROUP_OPEN, new GroupMarker(
+                               IContextMenuConstants.GROUP_SHOW));
+
+               ActionContext context = new ActionContext(getSelectionProvider()
+                               .getSelection());
+               fContextMenuGroup.setContext(context);
+               fContextMenuGroup.fillContextMenu(menu);
+               fContextMenuGroup.setContext(null);
+               // addAction(menu, ITextEditorActionConstants.GROUP_EDIT, "Format");
+               // //$NON-NLS-1$
+               //
+               // ActionContext context =
+               // new ActionContext(getSelectionProvider().getSelection());
+               // fContextMenuGroup.setContext(context);
+               // fContextMenuGroup.fillContextMenu(menu);
+               // fContextMenuGroup.setContext(null);
+       }
+
+       /**
+        * Creates the outline page used with this editor.
+        */
+       protected JavaOutlinePage createOutlinePage() {
+               JavaOutlinePage page = new JavaOutlinePage(fOutlinerContextMenuId, this);
+               fOutlineSelectionChangedListener.install(page);
+               setOutlinePageInput(page, getEditorInput());
+               return page;
+       }
+
+       /**
+        * Informs the editor that its outliner has been closed.
+        */
+       public void outlinePageClosed() {
+               if (fOutlinePage != null) {
+                       fOutlineSelectionChangedListener.uninstall(fOutlinePage);
+                       fOutlinePage = null;
+                       resetHighlightRange();
+               }
+       }
+
+       /**
+        * Synchronizes the outliner selection with the given element position in
+        * the editor.
+        * 
+        * @param element
+        *            the java element to select
+        */
+       protected void synchronizeOutlinePage(ISourceReference element) {
+               synchronizeOutlinePage(element, true);
+       }
+
+       /**
+        * Synchronizes the outliner selection with the given element position in
+        * the editor.
+        * 
+        * @param element
+        *            the java element to select
+        * @param checkIfOutlinePageActive
+        *            <code>true</code> if check for active outline page needs to
+        *            be done
+        */
+       protected void synchronizeOutlinePage(ISourceReference element,
+                       boolean checkIfOutlinePageActive) {
+               if (fOutlinePage != null && element != null
+                               && !(checkIfOutlinePageActive && isJavaOutlinePageActive())) {
+                       fOutlineSelectionChangedListener.uninstall(fOutlinePage);
+                       fOutlinePage.select(element);
+                       fOutlineSelectionChangedListener.install(fOutlinePage);
+               }
+       }
+
+       /**
+        * Synchronizes the outliner selection with the actual cursor position in
+        * the editor.
+        */
+       public void synchronizeOutlinePageSelection() {
+               synchronizeOutlinePage(computeHighlightRangeSourceReference());
+
+               // ISourceViewer sourceViewer = getSourceViewer();
+               // if (sourceViewer == null || fOutlinePage == null)
+               // return;
+               //
+               // StyledText styledText = sourceViewer.getTextWidget();
+               // if (styledText == null)
+               // return;
+               //
+               // int caret = 0;
+               // if (sourceViewer instanceof ITextViewerExtension3) {
+               // ITextViewerExtension3 extension = (ITextViewerExtension3)
+               // sourceViewer;
+               // caret =
+               // extension.widgetOffset2ModelOffset(styledText.getCaretOffset());
+               // } else {
+               // int offset = sourceViewer.getVisibleRegion().getOffset();
+               // caret = offset + styledText.getCaretOffset();
+               // }
+               //
+               // IJavaElement element = getElementAt(caret);
+               // if (element instanceof ISourceReference) {
+               // fOutlinePage.removeSelectionChangedListener(fSelectionChangedListener);
+               // fOutlinePage.select((ISourceReference) element);
+               // fOutlinePage.addSelectionChangedListener(fSelectionChangedListener);
+               // }
+       }
+
+       protected void setSelection(ISourceReference reference, boolean moveCursor) {
+
+               ISelection selection = getSelectionProvider().getSelection();
+               if (selection instanceof TextSelection) {
+                       TextSelection textSelection = (TextSelection) selection;
+                       if (textSelection.getOffset() != 0
+                                       || textSelection.getLength() != 0)
+                               markInNavigationHistory();
+               }
+
+               if (reference != null) {
+
+                       StyledText textWidget = null;
+
+                       ISourceViewer sourceViewer = getSourceViewer();
+                       if (sourceViewer != null)
+                               textWidget = sourceViewer.getTextWidget();
+
+                       if (textWidget == null)
+                               return;
+
+                       try {
+
+                               ISourceRange range = reference.getSourceRange();
+                               if (range == null)
+                                       return;
+
+                               int offset = range.getOffset();
+                               int length = range.getLength();
+
+                               if (offset < 0 || length < 0)
+                                       return;
+
+                               textWidget.setRedraw(false);
+
+                               setHighlightRange(offset, length, moveCursor);
+
+                               if (!moveCursor)
+                                       return;
+
+                               offset = -1;
+                               length = -1;
+
+                               if (reference instanceof IMember) {
+                                       range = ((IMember) reference).getNameRange();
+                                       if (range != null) {
+                                               offset = range.getOffset();
+                                               length = range.getLength();
+                                       }
+                               }
+                               // else if (reference instanceof IImportDeclaration) {
+                               // String name= ((IImportDeclaration)
+                               // reference).getElementName();
+                               // if (name != null && name.length() > 0) {
+                               // String content= reference.getSource();
+                               // if (content != null) {
+                               // offset= range.getOffset() + content.indexOf(name);
+                               // length= name.length();
+                               // }
+                               // }
+                               // } else if (reference instanceof IPackageDeclaration) {
+                               // String name= ((IPackageDeclaration)
+                               // reference).getElementName();
+                               // if (name != null && name.length() > 0) {
+                               // String content= reference.getSource();
+                               // if (content != null) {
+                               // offset= range.getOffset() + content.indexOf(name);
+                               // length= name.length();
+                               // }
+                               // }
+                               // }
+
+                               if (offset > -1 && length > 0) {
+                                       sourceViewer.revealRange(offset, length);
+                                       sourceViewer.setSelectedRange(offset, length);
+                               }
+
+                       } catch (JavaModelException x) {
+                       } catch (IllegalArgumentException x) {
+                       } finally {
+                               if (textWidget != null)
+                                       textWidget.setRedraw(true);
+                       }
+
+               } else if (moveCursor) {
+                       resetHighlightRange();
+               }
+
+               markInNavigationHistory();
+       }
+
+       public void setSelection(IJavaElement element) {
+               if (element == null || element instanceof ICompilationUnit) { // ||
+                       // element
+                       // instanceof
+                       // IClassFile)
+                       // {
+                       /*
+                        * If the element is an ICompilationUnit this unit is either the
+                        * input of this editor or not being displayed. In both cases,
+                        * nothing should happened.
+                        * (http://dev.eclipse.org/bugs/show_bug.cgi?id=5128)
+                        */
+                       return;
+               }
+
+               IJavaElement corresponding = getCorrespondingElement(element);
+               if (corresponding instanceof ISourceReference) {
+                       ISourceReference reference = (ISourceReference) corresponding;
+                       // set highlight range
+                       setSelection(reference, true);
+                       // set outliner selection
+                       if (fOutlinePage != null) {
+                               fOutlineSelectionChangedListener.uninstall(fOutlinePage);
+                               fOutlinePage.select(reference);
+                               fOutlineSelectionChangedListener.install(fOutlinePage);
+                       }
+               }
+       }
+
+       public synchronized void editingScriptStarted() {
+               ++fIgnoreOutlinePageSelection;
+       }
+
+       public synchronized void editingScriptEnded() {
+               --fIgnoreOutlinePageSelection;
+       }
+
+       public synchronized boolean isEditingScriptRunning() {
+               return (fIgnoreOutlinePageSelection > 0);
+       }
+
+       /**
+        * The <code>PHPEditor</code> implementation of this
+        * <code>AbstractTextEditor</code> method performs gets the java content
+        * outline page if request is for a an outline page.
+        */
+       public Object getAdapter(Class required) {
+
+               if (IContentOutlinePage.class.equals(required)) {
+                       if (fOutlinePage == null)
+                               fOutlinePage = createOutlinePage();
+                       return fOutlinePage;
+               }
+
+               if (IEncodingSupport.class.equals(required))
+                       return fEncodingSupport;
+
+               if (required == IShowInTargetList.class) {
+                       return new IShowInTargetList() {
+                               public String[] getShowInTargetIds() {
+                                       return new String[] { JavaUI.ID_PACKAGES,
+                                                       IPageLayout.ID_OUTLINE, IPageLayout.ID_RES_NAV };
+                               }
+
+                       };
+               }
+               if (fProjectionSupport != null) {
+                       Object adapter = fProjectionSupport.getAdapter(getSourceViewer(),
+                                       required);
+                       if (adapter != null)
+                               return adapter;
+               }
+
+               return super.getAdapter(required);
+       }
+
+       // public Object getAdapter(Class required) {
+       // if (IContentOutlinePage.class.equals(required)) {
+       // if (fOutlinePage == null) {
+       // fOutlinePage = new PHPContentOutlinePage(getDocumentProvider(), this);
+       // if (getEditorInput() != null)
+       // fOutlinePage.setInput(getEditorInput());
+       // }
+       // return fOutlinePage;
+       // }
+       //
+       // if (IEncodingSupport.class.equals(required))
+       // return fEncodingSupport;
+       //
+       // return super.getAdapter(required);
+       // }
+
+       protected void doSelectionChanged(SelectionChangedEvent event) {
+               ISourceReference reference = null;
+
+               ISelection selection = event.getSelection();
+               Iterator iter = ((IStructuredSelection) selection).iterator();
+               while (iter.hasNext()) {
+                       Object o = iter.next();
+                       if (o instanceof ISourceReference) {
+                               reference = (ISourceReference) o;
+                               break;
+                       }
+               }
+
+               if (!isActivePart() && PHPeclipsePlugin.getActivePage() != null)
+                       PHPeclipsePlugin.getActivePage().bringToTop(this);
+
+               try {
+                       editingScriptStarted();
+                       setSelection(reference, !isActivePart());
+               } finally {
+                       editingScriptEnded();
+               }
+       }
+
+       /*
+        * @see AbstractTextEditor#adjustHighlightRange(int, int)
+        */
+       protected void adjustHighlightRange(int offset, int length) {
+
+               try {
+
+                       IJavaElement element = getElementAt(offset);
+                       while (element instanceof ISourceReference) {
+                               ISourceRange range = ((ISourceReference) element)
+                                               .getSourceRange();
+                               if (offset < range.getOffset() + range.getLength()
+                                               && range.getOffset() < offset + length) {
+
+                                       ISourceViewer viewer = getSourceViewer();
+                                       if (viewer instanceof ITextViewerExtension5) {
+                                               ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+                                               extension.exposeModelRange(new Region(
+                                                               range.getOffset(), range.getLength()));
+                                       }
+
+                                       setHighlightRange(range.getOffset(), range.getLength(),
+                                                       true);
+                                       if (fOutlinePage != null) {
+                                               fOutlineSelectionChangedListener
+                                                               .uninstall(fOutlinePage);
+                                               fOutlinePage.select((ISourceReference) element);
+                                               fOutlineSelectionChangedListener.install(fOutlinePage);
+                                       }
+
+                                       return;
+                               }
+                               element = element.getParent();
+                       }
+
+               } catch (JavaModelException x) {
+                       PHPeclipsePlugin.log(x.getStatus());
+               }
+
+               ISourceViewer viewer = getSourceViewer();
+               if (viewer instanceof ITextViewerExtension5) {
+                       ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
+                       extension.exposeModelRange(new Region(offset, length));
+               } else {
+                       resetHighlightRange();
+               }
+
+       }
+
+       protected boolean isActivePart() {
+               IWorkbenchWindow window = getSite().getWorkbenchWindow();
+               IPartService service = window.getPartService();
+               IWorkbenchPart part = service.getActivePart();
+               return part != null && part.equals(this);
+       }
+
+       // public void openContextHelp() {
+       // IDocument doc =
+       // this.getDocumentProvider().getDocument(this.getEditorInput());
+       // ITextSelection selection = (ITextSelection)
+       // this.getSelectionProvider().getSelection();
+       // int pos = selection.getOffset();
+       // String word = getFunctionName(doc, pos);
+       // openContextHelp(word);
+       // }
+       //
+       // private void openContextHelp(String word) {
+       // open(word);
+       // }
+       //
+       // public static void open(String word) {
+       // IHelp help = WorkbenchHelp.getHelpSupport();
+       // if (help != null) {
+       // IHelpResource helpResource = new PHPFunctionHelpResource(word);
+       // WorkbenchHelp.getHelpSupport().displayHelpResource(helpResource);
+       // } else {
+       // // showMessage(shell, dialogTitle, ActionMessages.getString("Open help
+       // not available"), false); //$NON-NLS-1$
+       // }
+       // }
+
+       // private String getFunctionName(IDocument doc, int pos) {
+       // Point word = PHPWordExtractor.findWord(doc, pos);
+       // if (word != null) {
+       // try {
+       // return doc.get(word.x, word.y).replace('_', '-');
+       // } catch (BadLocationException e) {
+       // }
+       // }
+       // return "";
+       // }
+
+       /*
+        * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
+        */
+       protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+
+               try {
+
+                       ISourceViewer sourceViewer = getSourceViewer();
+                       if (sourceViewer == null)
+                               return;
+
+                       String property = event.getProperty();
+
+                       if (PreferenceConstants.EDITOR_TAB_WIDTH.equals(property)) {
+                               Object value = event.getNewValue();
+                               if (value instanceof Integer) {
+                                       sourceViewer.getTextWidget().setTabs(
+                                                       ((Integer) value).intValue());
+                               } else if (value instanceof String) {
+                                       try {
+                                               sourceViewer.getTextWidget().setTabs(
+                                                               Integer.parseInt((String) value));
+                                       } catch (NumberFormatException e) {
+                                               // bug #1038071 - set default tab:
+                                               sourceViewer.getTextWidget().setTabs(80);
+                                       }
+                               }
+                               return;
+                       }
+
+                       // if (OVERVIEW_RULER.equals(property)) {
+                       // if (isOverviewRulerVisible())
+                       // showOverviewRuler();
+                       // else
+                       // hideOverviewRuler();
+                       // return;
+                       // }
+
+                       // if (LINE_NUMBER_RULER.equals(property)) {
+                       // if (isLineNumberRulerVisible())
+                       // showLineNumberRuler();
+                       // else
+                       // hideLineNumberRuler();
+                       // return;
+                       // }
+
+                       // if (fLineNumberRulerColumn != null
+                       // && (LINE_NUMBER_COLOR.equals(property) ||
+                       // PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property) ||
+                       // PREFERENCE_COLOR_BACKGROUND.equals(property))) {
+                       //
+                       // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
+                       // }
+
+                       if (isJavaEditorHoverProperty(property))
+                               updateHoverBehavior();
+
+                       if (BROWSER_LIKE_LINKS.equals(property)) {
+                               if (isBrowserLikeLinks())
+                                       enableBrowserLikeLinks();
+                               else
+                                       disableBrowserLikeLinks();
+                               return;
+                       }
+
+                       if (PreferenceConstants.EDITOR_DISABLE_OVERWRITE_MODE
+                                       .equals(property)) {
+                               if (event.getNewValue() instanceof Boolean) {
+                                       Boolean disable = (Boolean) event.getNewValue();
+                                       enableOverwriteMode(!disable.booleanValue());
+                               }
+                               return;
+                       }
+
+                       boolean newBooleanValue = false;
+                       Object newValue = event.getNewValue();
+                       if (newValue != null)
+                               newBooleanValue = Boolean.valueOf(newValue.toString())
+                                               .booleanValue();
+
+                       if (PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE
+                                       .equals(property)) {
+                               if (newBooleanValue)
+                                       selectionChanged();
+                               return;
+                       }
+
+                       if (PreferenceConstants.EDITOR_MARK_OCCURRENCES.equals(property)) {
+                               if (newBooleanValue != fMarkOccurrenceAnnotations) {
+                                       fMarkOccurrenceAnnotations = newBooleanValue;
+                                       if (!fMarkOccurrenceAnnotations)
+                                               uninstallOccurrencesFinder();
+                                       else
+                                               installOccurrencesFinder();
+                               }
+                               return;
+                       }
+
+                       if (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property)) {
+                               fStickyOccurrenceAnnotations = newBooleanValue;
+                               return;
+                       }
+                       // }
+                       // }
+                       // if
+                       // (PreferenceConstants.EDITOR_STICKY_OCCURRENCES.equals(property))
+                       // {
+                       // if (event.getNewValue() instanceof Boolean) {
+                       // boolean stickyOccurrenceAnnotations=
+                       // ((Boolean)event.getNewValue()).booleanValue();
+                       // if (stickyOccurrenceAnnotations != fStickyOccurrenceAnnotations)
+                       // {
+
+                       ((PHPSourceViewerConfiguration) getSourceViewerConfiguration())
+                                       .handlePropertyChangeEvent(event);
+
+                       // if (affectsOverrideIndicatorAnnotations(event)) {
+                       // if (isShowingOverrideIndicators()) {
+                       // if (fOverrideIndicatorManager == null)
+                       // installOverrideIndicator(true);
+                       // } else {
+                       // if (fOverrideIndicatorManager != null)
+                       // uninstallOverrideIndicator();
+                       // }
+                       // return;
+                       // }
+
+                       if (PreferenceConstants.EDITOR_FOLDING_PROVIDER.equals(property)) {
+                               if (sourceViewer instanceof ProjectionViewer) {
+                                       ProjectionViewer projectionViewer = (ProjectionViewer) sourceViewer;
+                                       if (fProjectionModelUpdater != null)
+                                               fProjectionModelUpdater.uninstall();
+                                       // either freshly enabled or provider changed
+                                       fProjectionModelUpdater = PHPeclipsePlugin.getDefault()
+                                                       .getFoldingStructureProviderRegistry()
+                                                       .getCurrentFoldingProvider();
+                                       if (fProjectionModelUpdater != null) {
+                                               fProjectionModelUpdater.install(this, projectionViewer);
+                                       }
+                               }
+                               return;
+                       }
+               } finally {
+                       super.handlePreferenceStoreChanged(event);
+               }
+       }
+
+       // /*
+       // * @see
+       // AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
+       // */
+       // protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
+       //
+       // try {
+       //
+       // ISourceViewer sourceViewer = getSourceViewer();
+       // if (sourceViewer == null)
+       // return;
+       //
+       // String property = event.getProperty();
+       //
+       // // if
+       // (JavaSourceViewerConfiguration.PREFERENCE_TAB_WIDTH.equals(property)) {
+       // // Object value= event.getNewValue();
+       // // if (value instanceof Integer) {
+       // // sourceViewer.getTextWidget().setTabs(((Integer) value).intValue());
+       // // } else if (value instanceof String) {
+       // // sourceViewer.getTextWidget().setTabs(Integer.parseInt((String)
+       // value));
+       // // }
+       // // return;
+       // // }
+       //
+       // if (IPreferenceConstants.LINE_NUMBER_RULER.equals(property)) {
+       // if (isLineNumberRulerVisible())
+       // showLineNumberRuler();
+       // else
+       // hideLineNumberRuler();
+       // return;
+       // }
+       //
+       // if (fLineNumberRulerColumn != null
+       // && (IPreferenceConstants.LINE_NUMBER_COLOR.equals(property)
+       // || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)
+       // || PREFERENCE_COLOR_BACKGROUND.equals(property))) {
+       //
+       // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
+       // }
+       //
+       // } finally {
+       // super.handlePreferenceStoreChanged(event);
+       // }
+       // }
+
+       // private boolean isJavaEditorHoverProperty(String property) {
+       // return PreferenceConstants.EDITOR_DEFAULT_HOVER.equals(property)
+       // || PreferenceConstants.EDITOR_NONE_HOVER.equals(property)
+       // || PreferenceConstants.EDITOR_CTRL_HOVER.equals(property)
+       // || PreferenceConstants.EDITOR_SHIFT_HOVER.equals(property)
+       // || PreferenceConstants.EDITOR_CTRL_ALT_HOVER.equals(property)
+       // || PreferenceConstants.EDITOR_CTRL_SHIFT_HOVER.equals(property)
+       // || PreferenceConstants.EDITOR_CTRL_ALT_SHIFT_HOVER.equals(property)
+       // || PreferenceConstants.EDITOR_ALT_SHIFT_HOVER.equals(property);
+       // }
+
+       /**
+        * Shows the line number ruler column.
+        */
+       // private void showLineNumberRuler() {
+       // IVerticalRuler v = getVerticalRuler();
+       // if (v instanceof CompositeRuler) {
+       // CompositeRuler c = (CompositeRuler) v;
+       // c.addDecorator(1, createLineNumberRulerColumn());
+       // }
+       // }
+       private boolean isJavaEditorHoverProperty(String property) {
+               return PreferenceConstants.EDITOR_TEXT_HOVER_MODIFIERS.equals(property);
+       }
+
+       /**
+        * Return whether the browser like links should be enabled according to the
+        * preference store settings.
+        * 
+        * @return <code>true</code> if the browser like links should be enabled
+        */
+       private boolean isBrowserLikeLinks() {
+               IPreferenceStore store = getPreferenceStore();
+               return store.getBoolean(BROWSER_LIKE_LINKS);
+       }
+
+       /**
+        * Enables browser like links.
+        */
+       private void enableBrowserLikeLinks() {
+               if (fMouseListener == null) {
+                       fMouseListener = new MouseClickListener();
+                       fMouseListener.install();
+               }
+       }
+
+       /**
+        * Disables browser like links.
+        */
+       private void disableBrowserLikeLinks() {
+               if (fMouseListener != null) {
+                       fMouseListener.uninstall();
+                       fMouseListener = null;
+               }
+       }
+
+       /**
+        * Handles a property change event describing a change of the java core's
+        * preferences and updates the preference related editor properties.
+        * 
+        * @param event
+        *            the property change event
+        */
+       protected void handlePreferencePropertyChanged(
+                       org.eclipse.core.runtime.Preferences.PropertyChangeEvent event) {
+               if (COMPILER_TASK_TAGS.equals(event.getProperty())) {
+                       ISourceViewer sourceViewer = getSourceViewer();
+                       if (sourceViewer != null
+                                       && affectsTextPresentation(new PropertyChangeEvent(event
+                                                       .getSource(), event.getProperty(), event
+                                                       .getOldValue(), event.getNewValue())))
+                               sourceViewer.invalidateTextPresentation();
+               }
+               if (PreferenceConstants.EDITOR_WRAP_WORDS.equals(event.getProperty())) {
+                       setWordWrap();
+               }
+       }
+
+       /**
+        * Return whether the line number ruler column should be visible according
+        * to the preference store settings.
+        * 
+        * @return <code>true</code> if the line numbers should be visible
+        */
+       // protected boolean isLineNumberRulerVisible() {
+       // IPreferenceStore store = getPreferenceStore();
+       // return store.getBoolean(LINE_NUMBER_RULER);
+       // }
+       /**
+        * Hides the line number ruler column.
+        */
+       // private void hideLineNumberRuler() {
+       // IVerticalRuler v = getVerticalRuler();
+       // if (v instanceof CompositeRuler) {
+       // CompositeRuler c = (CompositeRuler) v;
+       // try {
+       // c.removeDecorator(1);
+       // } catch (Throwable e) {
+       // }
+       // }
+       // }
+       /*
+        * @see AbstractTextEditor#handleCursorPositionChanged()
+        */
+       // protected void handleCursorPositionChanged() {
+       // super.handleCursorPositionChanged();
+       // if (!isEditingScriptRunning() && fUpdater != null)
+       // fUpdater.post();
+       // }
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractTextEditor#handleElementContentReplaced()
+        */
+       protected void handleElementContentReplaced() {
+               super.handleElementContentReplaced();
+               if (fProjectionModelUpdater != null)
+                       fProjectionModelUpdater.initialize();
+       }
+
+       /**
+        * Initializes the given line number ruler column from the preference store.
+        * 
+        * @param rulerColumn
+        *            the ruler column to be initialized
+        */
+       // protected void initializeLineNumberRulerColumn(LineNumberRulerColumn
+       // rulerColumn) {
+       // JavaTextTools textTools =
+       // PHPeclipsePlugin.getDefault().getJavaTextTools();
+       // IColorManager manager = textTools.getColorManager();
+       //
+       // IPreferenceStore store = getPreferenceStore();
+       // if (store != null) {
+       //
+       // RGB rgb = null;
+       // // foreground color
+       // if (store.contains(LINE_NUMBER_COLOR)) {
+       // if (store.isDefault(LINE_NUMBER_COLOR))
+       // rgb = PreferenceConverter.getDefaultColor(store, LINE_NUMBER_COLOR);
+       // else
+       // rgb = PreferenceConverter.getColor(store, LINE_NUMBER_COLOR);
+       // }
+       // rulerColumn.setForeground(manager.getColor(rgb));
+       //
+       // rgb = null;
+       // // background color
+       // if (!store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)) {
+       // if (store.contains(PREFERENCE_COLOR_BACKGROUND)) {
+       // if (store.isDefault(PREFERENCE_COLOR_BACKGROUND))
+       // rgb = PreferenceConverter.getDefaultColor(store,
+       // PREFERENCE_COLOR_BACKGROUND);
+       // else
+       // rgb = PreferenceConverter.getColor(store, PREFERENCE_COLOR_BACKGROUND);
+       // }
+       // }
+       // rulerColumn.setBackground(manager.getColor(rgb));
+       // }
+       // }
+       /**
+        * Creates a new line number ruler column that is appropriately initialized.
+        */
+       // protected IVerticalRulerColumn createLineNumberRulerColumn() {
+       // fLineNumberRulerColumn = new LineNumberRulerColumn();
+       // initializeLineNumberRulerColumn(fLineNumberRulerColumn);
+       // return fLineNumberRulerColumn;
+       // }
+       /*
+        * @see AbstractTextEditor#createVerticalRuler()
+        */
+       // protected IVerticalRuler createVerticalRuler() {
+       // CompositeRuler ruler = new CompositeRuler();
+       // ruler.addDecorator(0, new AnnotationRulerColumn(VERTICAL_RULER_WIDTH));
+       // if (isLineNumberRulerVisible())
+       // ruler.addDecorator(1, createLineNumberRulerColumn());
+       // return ruler;
+       // }
+       // private static IRegion getSignedSelection(ITextViewer viewer) {
+       //
+       // StyledText text = viewer.getTextWidget();
+       // int caretOffset = text.getCaretOffset();
+       // Point selection = text.getSelection();
+       //
+       // // caret left
+       // int offset, length;
+       // if (caretOffset == selection.x) {
+       // offset = selection.y;
+       // length = selection.x - selection.y;
+       //
+       // // caret right
+       // } else {
+       // offset = selection.x;
+       // length = selection.y - selection.x;
+       // }
+       //
+       // return new Region(offset, length);
+       // }
+       protected IRegion getSignedSelection(ISourceViewer sourceViewer) {
+               StyledText text = sourceViewer.getTextWidget();
+               Point selection = text.getSelectionRange();
+
+               if (text.getCaretOffset() == selection.x) {
+                       selection.x = selection.x + selection.y;
+                       selection.y = -selection.y;
+               }
+
+               selection.x = widgetOffset2ModelOffset(sourceViewer, selection.x);
+
+               return new Region(selection.x, selection.y);
+       }
+
+       /** Preference key for matching brackets */
+       protected final static String MATCHING_BRACKETS = PreferenceConstants.EDITOR_MATCHING_BRACKETS;
+
+       /** Preference key for matching brackets color */
+       protected final static String MATCHING_BRACKETS_COLOR = PreferenceConstants.EDITOR_MATCHING_BRACKETS_COLOR;
+
+       /** Preference key for highlighting current line */
+       // protected final static String CURRENT_LINE =
+       // PreferenceConstants.EDITOR_CURRENT_LINE;
+       /** Preference key for highlight color of current line */
+       // protected final static String CURRENT_LINE_COLOR =
+       // PreferenceConstants.EDITOR_CURRENT_LINE_COLOR;
+       /** Preference key for showing print marging ruler */
+       // protected final static String PRINT_MARGIN =
+       // PreferenceConstants.EDITOR_PRINT_MARGIN;
+       /** Preference key for print margin ruler color */
+       // protected final static String PRINT_MARGIN_COLOR =
+       // PreferenceConstants.EDITOR_PRINT_MARGIN_COLOR;
+       /** Preference key for print margin ruler column */
+       // protected final static String PRINT_MARGIN_COLUMN =
+       // PreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN;
+       /** Preference key for error indication */
+       // protected final static String ERROR_INDICATION =
+       // PreferenceConstants.EDITOR_PROBLEM_INDICATION;
+       /** Preference key for error color */
+       // protected final static String ERROR_INDICATION_COLOR =
+       // PreferenceConstants.EDITOR_PROBLEM_INDICATION_COLOR;
+       /** Preference key for warning indication */
+       // protected final static String WARNING_INDICATION =
+       // PreferenceConstants.EDITOR_WARNING_INDICATION;
+       /** Preference key for warning color */
+       // protected final static String WARNING_INDICATION_COLOR =
+       // PreferenceConstants.EDITOR_WARNING_INDICATION_COLOR;
+       /** Preference key for task indication */
+       protected final static String TASK_INDICATION = PreferenceConstants.EDITOR_TASK_INDICATION;
+
+       /** Preference key for task color */
+       protected final static String TASK_INDICATION_COLOR = PreferenceConstants.EDITOR_TASK_INDICATION_COLOR;
+
+       /** Preference key for bookmark indication */
+       protected final static String BOOKMARK_INDICATION = PreferenceConstants.EDITOR_BOOKMARK_INDICATION;
+
+       /** Preference key for bookmark color */
+       protected final static String BOOKMARK_INDICATION_COLOR = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_COLOR;
+
+       /** Preference key for search result indication */
+       protected final static String SEARCH_RESULT_INDICATION = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION;
+
+       /** Preference key for search result color */
+       protected final static String SEARCH_RESULT_INDICATION_COLOR = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_COLOR;
+
+       /** Preference key for unknown annotation indication */
+       protected final static String UNKNOWN_INDICATION = PreferenceConstants.EDITOR_UNKNOWN_INDICATION;
+
+       /** Preference key for unknown annotation color */
+       protected final static String UNKNOWN_INDICATION_COLOR = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_COLOR;
+
+       /** Preference key for shwoing the overview ruler */
+       protected final static String OVERVIEW_RULER = PreferenceConstants.EDITOR_OVERVIEW_RULER;
+
+       /** Preference key for error indication in overview ruler */
+       protected final static String ERROR_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_ERROR_INDICATION_IN_OVERVIEW_RULER;
+
+       /** Preference key for warning indication in overview ruler */
+       protected final static String WARNING_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_WARNING_INDICATION_IN_OVERVIEW_RULER;
+
+       /** Preference key for task indication in overview ruler */
+       protected final static String TASK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_TASK_INDICATION_IN_OVERVIEW_RULER;
+
+       /** Preference key for bookmark indication in overview ruler */
+       protected final static String BOOKMARK_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_BOOKMARK_INDICATION_IN_OVERVIEW_RULER;
+
+       /** Preference key for search result indication in overview ruler */
+       protected final static String SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER;
+
+       /** Preference key for unknown annotation indication in overview ruler */
+       protected final static String UNKNOWN_INDICATION_IN_OVERVIEW_RULER = PreferenceConstants.EDITOR_UNKNOWN_INDICATION_IN_OVERVIEW_RULER;
+
+       // /** Preference key for compiler task tags */
+       // private final static String COMPILER_TASK_TAGS=
+       // JavaCore.COMPILER_TASK_TAGS;
+       /** Preference key for browser like links */
+       private final static String BROWSER_LIKE_LINKS = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS;
+
+       /** Preference key for key modifier of browser like links */
+       private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER;
+
+       /**
+        * Preference key for key modifier mask of browser like links. The value is
+        * only used if the value of <code>EDITOR_BROWSER_LIKE_LINKS</code> cannot
+        * be resolved to valid SWT modifier bits.
+        * 
+        * @since 2.1.1
+        */
+       private final static String BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK = PreferenceConstants.EDITOR_BROWSER_LIKE_LINKS_KEY_MODIFIER_MASK;
+
+       private final static char[] BRACKETS = { '{', '}', '(', ')', '[', ']' };
+
+       private static boolean isBracket(char character) {
+               for (int i = 0; i != BRACKETS.length; ++i)
+                       if (character == BRACKETS[i])
+                               return true;
+               return false;
+       }
+
+       private static boolean isSurroundedByBrackets(IDocument document, int offset) {
+               if (offset == 0 || offset == document.getLength())
+                       return false;
+
+               try {
+                       return isBracket(document.getChar(offset - 1))
+                                       && isBracket(document.getChar(offset));
+
+               } catch (BadLocationException e) {
+                       return false;
+               }
+       }
+
+       // protected void configureSourceViewerDecorationSupport() {
+       //
+       // fSourceViewerDecorationSupport.setCharacterPairMatcher(fBracketMatcher);
+       //
+       // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+       // AnnotationType.UNKNOWN,
+       // UNKNOWN_INDICATION_COLOR,
+       // UNKNOWN_INDICATION,
+       // UNKNOWN_INDICATION_IN_OVERVIEW_RULER,
+       // 0);
+       // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+       // AnnotationType.BOOKMARK,
+       // BOOKMARK_INDICATION_COLOR,
+       // BOOKMARK_INDICATION,
+       // BOOKMARK_INDICATION_IN_OVERVIEW_RULER,
+       // 1);
+       // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+       // AnnotationType.TASK,
+       // TASK_INDICATION_COLOR,
+       // TASK_INDICATION,
+       // TASK_INDICATION_IN_OVERVIEW_RULER,
+       // 2);
+       // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+       // AnnotationType.SEARCH,
+       // SEARCH_RESULT_INDICATION_COLOR,
+       // SEARCH_RESULT_INDICATION,
+       // SEARCH_RESULT_INDICATION_IN_OVERVIEW_RULER,
+       // 3);
+       // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+       // AnnotationType.WARNING,
+       // WARNING_INDICATION_COLOR,
+       // WARNING_INDICATION,
+       // WARNING_INDICATION_IN_OVERVIEW_RULER,
+       // 4);
+       // fSourceViewerDecorationSupport.setAnnotationPainterPreferenceKeys(
+       // AnnotationType.ERROR,
+       // ERROR_INDICATION_COLOR,
+       // ERROR_INDICATION,
+       // ERROR_INDICATION_IN_OVERVIEW_RULER,
+       // 5);
+       //
+       // fSourceViewerDecorationSupport.setCursorLinePainterPreferenceKeys(CURRENT_LINE,
+       // CURRENT_LINE_COLOR);
+       // fSourceViewerDecorationSupport.setMarginPainterPreferenceKeys(PRINT_MARGIN,
+       // PRINT_MARGIN_COLOR, PRINT_MARGIN_COLUMN);
+       // fSourceViewerDecorationSupport.setMatchingCharacterPainterPreferenceKeys(MATCHING_BRACKETS,
+       // MATCHING_BRACKETS_COLOR);
+       //
+       // fSourceViewerDecorationSupport.setSymbolicFontName(getFontPropertyPreferenceKey());
+       //
+       // }
+       /**
+        * Returns the Java element wrapped by this editors input.
+        * 
+        * @return the Java element wrapped by this editors input.
+        * @since 3.0
+        */
+       abstract protected IJavaElement getInputJavaElement();
+
+       protected void updateStatusLine() {
+               ITextSelection selection = (ITextSelection) getSelectionProvider()
+                               .getSelection();
+               Annotation annotation = getAnnotation(selection.getOffset(), selection
+                               .getLength());
+               setStatusLineErrorMessage(null);
+               setStatusLineMessage(null);
+               if (annotation != null) {
+                       try {
+                               fIsUpdatingAnnotationViews = true;
+                               updateAnnotationViews(annotation);
+                       } finally {
+                               fIsUpdatingAnnotationViews = false;
+                       }
+                       if (annotation instanceof IJavaAnnotation
+                                       && ((IJavaAnnotation) annotation).isProblem())
+                               setStatusLineMessage(annotation.getText());
+               }
+       }
+
+       /**
+        * Jumps to the matching bracket.
+        */
+       public void gotoMatchingBracket() {
+
+               ISourceViewer sourceViewer = getSourceViewer();
+               IDocument document = sourceViewer.getDocument();
+               if (document == null)
+                       return;
+
+               IRegion selection = getSignedSelection(sourceViewer);
+
+               int selectionLength = Math.abs(selection.getLength());
+               if (selectionLength > 1) {
+                       setStatusLineErrorMessage(PHPEditorMessages
+                                       .getString("GotoMatchingBracket.error.invalidSelection")); //$NON-NLS-1$
+                       sourceViewer.getTextWidget().getDisplay().beep();
+                       return;
+               }
+
+               // #26314
+               int sourceCaretOffset = selection.getOffset() + selection.getLength();
+               if (isSurroundedByBrackets(document, sourceCaretOffset))
+                       sourceCaretOffset -= selection.getLength();
+
+               IRegion region = fBracketMatcher.match(document, sourceCaretOffset);
+               if (region == null) {
+                       setStatusLineErrorMessage(PHPEditorMessages
+                                       .getString("GotoMatchingBracket.error.noMatchingBracket")); //$NON-NLS-1$
+                       sourceViewer.getTextWidget().getDisplay().beep();
+                       return;
+               }
+
+               int offset = region.getOffset();
+               int length = region.getLength();
+
+               if (length < 1)
+                       return;
+
+               int anchor = fBracketMatcher.getAnchor();
+               int targetOffset = (PHPPairMatcher.RIGHT == anchor) ? offset : offset
+                               + length - 1;
+
+               boolean visible = false;
+               if (sourceViewer instanceof ITextViewerExtension5) {
+                       ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer;
+                       visible = (extension.modelOffset2WidgetOffset(targetOffset) > -1);
+               } else {
+                       IRegion visibleRegion = sourceViewer.getVisibleRegion();
+                       visible = (targetOffset >= visibleRegion.getOffset() && targetOffset < visibleRegion
+                                       .getOffset()
+                                       + visibleRegion.getLength());
+               }
+
+               if (!visible) {
+                       setStatusLineErrorMessage(PHPEditorMessages
+                                       .getString("GotoMatchingBracket.error.bracketOutsideSelectedElement")); //$NON-NLS-1$
+                       sourceViewer.getTextWidget().getDisplay().beep();
+                       return;
+               }
+
+               if (selection.getLength() < 0)
+                       targetOffset -= selection.getLength();
+
+               sourceViewer.setSelectedRange(targetOffset, selection.getLength());
+               sourceViewer.revealRange(targetOffset, selection.getLength());
+       }
+
+       /**
+        * Ses the given message as error message to this editor's status line.
+        * 
+        * @param msg
+        *            message to be set
+        */
+       protected void setStatusLineErrorMessage(String msg) {
+               IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
+               if (statusLine != null)
+                       statusLine.setMessage(true, msg, null);
+       }
+
+       /**
+        * Sets the given message as message to this editor's status line.
+        * 
+        * @param msg
+        *            message to be set
+        * @since 3.0
+        */
+       protected void setStatusLineMessage(String msg) {
+               IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class);
+               if (statusLine != null)
+                       statusLine.setMessage(false, msg, null);
+       }
+
+       /**
+        * Returns the annotation closest to the given range respecting the given
+        * direction. If an annotation is found, the annotations current position is
+        * copied into the provided annotation position.
+        * 
+        * @param offset
+        *            the region offset
+        * @param length
+        *            the region length
+        * @param forward
+        *            <code>true</code> for forwards, <code>false</code> for
+        *            backward
+        * @param annotationPosition
+        *            the position of the found annotation
+        * @return the found annotation
+        */
+       private Annotation getNextAnnotation(final int offset, final int length,
+                       boolean forward, Position annotationPosition) {
+
+               Annotation nextAnnotation = null;
+               Position nextAnnotationPosition = null;
+               Annotation containingAnnotation = null;
+               Position containingAnnotationPosition = null;
+               boolean currentAnnotation = false;
+
+               IDocument document = getDocumentProvider()
+                               .getDocument(getEditorInput());
+               int endOfDocument = document.getLength();
+               int distance = Integer.MAX_VALUE;
+
+               IAnnotationModel model = getDocumentProvider().getAnnotationModel(
+                               getEditorInput());
+               Iterator e = new JavaAnnotationIterator(model, true, true);
+               while (e.hasNext()) {
+                       Annotation a = (Annotation) e.next();
+                       if ((a instanceof IJavaAnnotation)
+                                       && ((IJavaAnnotation) a).hasOverlay()
+                                       || !isNavigationTarget(a))
+                               continue;
+
+                       Position p = model.getPosition(a);
+                       if (p == null)
+                               continue;
+
+                       if (forward && p.offset == offset || !forward
+                                       && p.offset + p.getLength() == offset + length) {// ||
+                               // p.includes(offset))
+                               // {
+                               if (containingAnnotation == null
+                                               || (forward
+                                                               && p.length >= containingAnnotationPosition.length || !forward
+                                                               && p.length >= containingAnnotationPosition.length)) {
+                                       containingAnnotation = a;
+                                       containingAnnotationPosition = p;
+                                       currentAnnotation = p.length == length;
+                               }
+                       } else {
+                               int currentDistance = 0;
+
+                               if (forward) {
+                                       currentDistance = p.getOffset() - offset;
+                                       if (currentDistance < 0)
+                                               currentDistance = endOfDocument + currentDistance;
+
+                                       if (currentDistance < distance
+                                                       || currentDistance == distance
+                                                       && p.length < nextAnnotationPosition.length) {
+                                               distance = currentDistance;
+                                               nextAnnotation = a;
+                                               nextAnnotationPosition = p;
+                                       }
+                               } else {
+                                       currentDistance = offset + length
+                                                       - (p.getOffset() + p.length);
+                                       if (currentDistance < 0)
+                                               currentDistance = endOfDocument + currentDistance;
+
+                                       if (currentDistance < distance
+                                                       || currentDistance == distance
+                                                       && p.length < nextAnnotationPosition.length) {
+                                               distance = currentDistance;
+                                               nextAnnotation = a;
+                                               nextAnnotationPosition = p;
+                                       }
+                               }
+                       }
+               }
+               if (containingAnnotationPosition != null
+                               && (!currentAnnotation || nextAnnotation == null)) {
+                       annotationPosition.setOffset(containingAnnotationPosition
+                                       .getOffset());
+                       annotationPosition.setLength(containingAnnotationPosition
+                                       .getLength());
+                       return containingAnnotation;
+               }
+               if (nextAnnotationPosition != null) {
+                       annotationPosition.setOffset(nextAnnotationPosition.getOffset());
+                       annotationPosition.setLength(nextAnnotationPosition.getLength());
+               }
+
+               return nextAnnotation;
+       }
+
+       /**
+        * Returns the annotation overlapping with the given range or
+        * <code>null</code>.
+        * 
+        * @param offset
+        *            the region offset
+        * @param length
+        *            the region length
+        * @return the found annotation or <code>null</code>
+        * @since 3.0
+        */
+       private Annotation getAnnotation(int offset, int length) {
+               IAnnotationModel model = getDocumentProvider().getAnnotationModel(
+                               getEditorInput());
+               Iterator e = new JavaAnnotationIterator(model, true, true);
+               while (e.hasNext()) {
+                       Annotation a = (Annotation) e.next();
+                       if (!isNavigationTarget(a))
+                               continue;
+
+                       Position p = model.getPosition(a);
+                       if (p != null && p.overlapsWith(offset, length))
+                               return a;
+               }
+
+               return null;
+       }
+
+       /**
+        * Returns whether the given annotation is configured as a target for the
+        * "Go to Next/Previous Annotation" actions
+        * 
+        * @param annotation
+        *            the annotation
+        * @return <code>true</code> if this is a target, <code>false</code>
+        *         otherwise
+        * @since 3.0
+        */
+       protected boolean isNavigationTarget(Annotation annotation) {
+               Preferences preferences = EditorsUI.getPluginPreferences();
+               AnnotationPreference preference = getAnnotationPreferenceLookup()
+                               .getAnnotationPreference(annotation);
+               // See bug 41689
+               // String key= forward ? preference.getIsGoToNextNavigationTargetKey() :
+               // preference.getIsGoToPreviousNavigationTargetKey();
+               String key = preference == null ? null : preference
+                               .getIsGoToNextNavigationTargetKey();
+               return (key != null && preferences.getBoolean(key));
+       }
+
+       /**
+        * Returns a segmentation of the line of the given document appropriate for
+        * bidi rendering. The default implementation returns only the string
+        * literals of a php code line as segments.
+        * 
+        * @param document
+        *            the document
+        * @param lineOffset
+        *            the offset of the line
+        * @return the line's bidi segmentation
+        * @throws BadLocationException
+        *             in case lineOffset is not valid in document
+        */
+       public static int[] getBidiLineSegments(IDocument document, int lineOffset)
+                       throws BadLocationException {
+
+               IRegion line = document.getLineInformationOfOffset(lineOffset);
+               ITypedRegion[] linePartitioning = document.computePartitioning(
+                               lineOffset, line.getLength());
+
+               List segmentation = new ArrayList();
+               for (int i = 0; i < linePartitioning.length; i++) {
+                       if (IPHPPartitions.PHP_STRING_DQ.equals(linePartitioning[i]
+                                       .getType())) {
+                               segmentation.add(linePartitioning[i]);
+                       } else if (IPHPPartitions.PHP_STRING_HEREDOC
+                                       .equals(linePartitioning[i].getType())) {
+                               segmentation.add(linePartitioning[i]);
+                       }
+               }
+
+               if (segmentation.size() == 0)
+                       return null;
+
+               int size = segmentation.size();
+               int[] segments = new int[size * 2 + 1];
+
+               int j = 0;
+               for (int i = 0; i < size; i++) {
+                       ITypedRegion segment = (ITypedRegion) segmentation.get(i);
+
+                       if (i == 0)
+                               segments[j++] = 0;
+
+                       int offset = segment.getOffset() - lineOffset;
+                       if (offset > segments[j - 1])
+                               segments[j++] = offset;
+
+                       if (offset + segment.getLength() >= line.getLength())
+                               break;
+
+                       segments[j++] = offset + segment.getLength();
+               }
+
+               if (j < segments.length) {
+                       int[] result = new int[j];
+                       System.arraycopy(segments, 0, result, 0, j);
+                       segments = result;
+               }
+
+               return segments;
+       }
+
+       /**
+        * Returns a segmentation of the given line appropriate for bidi rendering.
+        * The default implementation returns only the string literals of a php code
+        * line as segments.
+        * 
+        * @param lineOffset
+        *            the offset of the line
+        * @param line
+        *            the content of the line
+        * @return the line's bidi segmentation
+        */
+       protected int[] getBidiLineSegments(int lineOffset, String line) {
+               IDocumentProvider provider = getDocumentProvider();
+               if (provider != null && line != null && line.length() > 0) {
+                       IDocument document = provider.getDocument(getEditorInput());
+                       if (document != null)
+                               try {
+                                       return getBidiLineSegments(document, lineOffset);
+                               } catch (BadLocationException x) {
+                                       // ignore
+                               }
+               }
+               return null;
+       }
+
+       /*
+        * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler,
+        *      int)
+        */
+       // protected final ISourceViewer createSourceViewer(
+       // Composite parent,
+       // IVerticalRuler ruler,
+       // int styles) {
+       // ISourceViewer viewer = createJavaSourceViewer(parent, ruler, styles);
+       // StyledText text = viewer.getTextWidget();
+       // text.addBidiSegmentListener(new BidiSegmentListener() {
+       // public void lineGetSegments(BidiSegmentEvent event) {
+       // event.segments = getBidiLineSegments(event.lineOffset, event.lineText);
+       // }
+       // });
+       // // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
+       // return viewer;
+       // }
+       public final ISourceViewer getViewer() {
+               return getSourceViewer();
+       }
+
+       // protected void showOverviewRuler() {
+       // if (fOverviewRuler != null) {
+       // if (getSourceViewer() instanceof ISourceViewerExtension) {
+       // ((ISourceViewerExtension)
+       // getSourceViewer()).showAnnotationsOverview(true);
+       // fSourceViewerDecorationSupport.updateOverviewDecorations();
+       // }
+       // }
+       // }
+       //
+       // protected void hideOverviewRuler() {
+       // if (getSourceViewer() instanceof ISourceViewerExtension) {
+       // fSourceViewerDecorationSupport.hideAnnotationOverview();
+       // ((ISourceViewerExtension)
+       // getSourceViewer()).showAnnotationsOverview(false);
+       // }
+       // }
+
+       // protected boolean isOverviewRulerVisible() {
+       // IPreferenceStore store = getPreferenceStore();
+       // return store.getBoolean(OVERVIEW_RULER);
+       // }
+       /*
+        * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler,
+        *      int)
+        */
+       // protected ISourceViewer createJavaSourceViewer(
+       // Composite parent,
+       // IVerticalRuler ruler,
+       // IOverviewRuler overviewRuler,
+       // boolean isOverviewRulerVisible,
+       // int styles) {
+       // return new SourceViewer(parent, ruler, overviewRuler,
+       // isOverviewRulerVisible(), styles);
+       // }
+       /*
+        * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler,
+        *      int)
+        */
+       protected ISourceViewer createJavaSourceViewer(Composite parent,
+                       IVerticalRuler verticalRuler, IOverviewRuler overviewRuler,
+                       boolean isOverviewRulerVisible, int styles, IPreferenceStore store) {
+               return new JavaSourceViewer(parent, verticalRuler, getOverviewRuler(),
+                               isOverviewRulerVisible(), styles, store);
+       }
+
+       /*
+        * @see AbstractTextEditor#createSourceViewer(Composite, IVerticalRuler,
+        *      int)
+        */
+       protected final ISourceViewer createSourceViewer(Composite parent,
+                       IVerticalRuler verticalRuler, int styles) {
+
+               ISourceViewer viewer = createJavaSourceViewer(parent, verticalRuler,
+                               getOverviewRuler(), isOverviewRulerVisible(), styles,
+                               getPreferenceStore());
+
+               StyledText text = viewer.getTextWidget();
+               text.addBidiSegmentListener(new BidiSegmentListener() {
+                       public void lineGetSegments(BidiSegmentEvent event) {
+                               event.segments = getBidiLineSegments(event.lineOffset,
+                                               event.lineText);
+                       }
+               });
+
+               // JavaUIHelp.setHelp(this, text, IJavaHelpContextIds.JAVA_EDITOR);
+
+               // ensure source viewer decoration support has been created and
+               // configured
+               getSourceViewerDecorationSupport(viewer);
+
+               return viewer;
+       }
+
+       /*
+        * @see AbstractTextEditor#affectsTextPresentation(PropertyChangeEvent)
+        */
+       protected boolean affectsTextPresentation(PropertyChangeEvent event) {
+               return ((PHPSourceViewerConfiguration) getSourceViewerConfiguration())
+                               .affectsTextPresentation(event)
+                               || super.affectsTextPresentation(event);
+       }
+
+       //
+       // protected boolean affectsTextPresentation(PropertyChangeEvent event) {
+       // JavaTextTools textTools =
+       // PHPeclipsePlugin.getDefault().getJavaTextTools();
+       // return textTools.affectsBehavior(event);
+       // }
+       /**
+        * Creates and returns the preference store for this Java editor with the
+        * given input.
+        * 
+        * @param input
+        *            The editor input for which to create the preference store
+        * @return the preference store for this editor
+        * 
+        * @since 3.0
+        */
+       private IPreferenceStore createCombinedPreferenceStore(IEditorInput input) {
+               List stores = new ArrayList(3);
+
+               IJavaProject project = EditorUtility.getJavaProject(input);
+               if (project != null)
+                       stores.add(new OptionsAdapter(project.getOptions(false),
+                                       PHPeclipsePlugin.getDefault().getMockupPreferenceStore(),
+                                       new OptionsAdapter.IPropertyChangeEventFilter() {
+
+                                               public boolean isFiltered(PropertyChangeEvent event) {
+                                                       IJavaElement inputJavaElement = getInputJavaElement();
+                                                       IJavaProject javaProject = inputJavaElement != null ? inputJavaElement
+                                                                       .getJavaProject()
+                                                                       : null;
+                                                       if (javaProject == null)
+                                                               return true;
+
+                                                       return !javaProject.getProject().equals(
+                                                                       event.getSource());
+                                               }
+
+                                       }));
+
+               stores.add(PHPeclipsePlugin.getDefault().getPreferenceStore());
+               stores.add(new PreferencesAdapter(JavaCore.getPlugin()
+                               .getPluginPreferences()));
+               stores.add(EditorsUI.getPreferenceStore());
+
+               return new ChainedPreferenceStore((IPreferenceStore[]) stores
+                               .toArray(new IPreferenceStore[stores.size()]));
+       }
+
+       /**
+        * Jumps to the error next according to the given direction.
+        */
+       public void gotoError(boolean forward) {
+
+               ISelectionProvider provider = getSelectionProvider();
+
+               ITextSelection s = (ITextSelection) provider.getSelection();
+               Position errorPosition = new Position(0, 0);
+               IJavaAnnotation nextError = getNextError(s.getOffset(), forward,
+                               errorPosition);
+
+               if (nextError != null) {
+
+                       IMarker marker = null;
+                       if (nextError instanceof MarkerAnnotation)
+                               marker = ((MarkerAnnotation) nextError).getMarker();
+                       else {
+                               Iterator e = nextError.getOverlaidIterator();
+                               if (e != null) {
+                                       while (e.hasNext()) {
+                                               Object o = e.next();
+                                               if (o instanceof MarkerAnnotation) {
+                                                       marker = ((MarkerAnnotation) o).getMarker();
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+
+                       if (marker != null) {
+                               IWorkbenchPage page = getSite().getPage();
+                               IViewPart view = view = page
+                                               .findView("org.eclipse.ui.views.TaskList"); //$NON-NLS-1$
+                               if (view instanceof TaskList) {
+                                       StructuredSelection ss = new StructuredSelection(marker);
+                                       ((TaskList) view).setSelection(ss, true);
+                               }
+                       }
+
+                       selectAndReveal(errorPosition.getOffset(), errorPosition
+                                       .getLength());
+                       // setStatusLineErrorMessage(nextError.getMessage());
+
+               } else {
+
+                       setStatusLineErrorMessage(null);
+
+               }
+       }
+
+       private IJavaAnnotation getNextError(int offset, boolean forward,
+                       Position errorPosition) {
+
+               IJavaAnnotation nextError = null;
+               Position nextErrorPosition = null;
+
+               IDocument document = getDocumentProvider()
+                               .getDocument(getEditorInput());
+               int endOfDocument = document.getLength();
+               int distance = 0;
+
+               IAnnotationModel model = getDocumentProvider().getAnnotationModel(
+                               getEditorInput());
+               Iterator e = new JavaAnnotationIterator(model, false);
+               while (e.hasNext()) {
+
+                       IJavaAnnotation a = (IJavaAnnotation) e.next();
+                       if (a.hasOverlay() || !a.isProblem())
+                               continue;
+
+                       Position p = model.getPosition((Annotation) a);
+                       if (!p.includes(offset)) {
+
+                               int currentDistance = 0;
+
+                               if (forward) {
+                                       currentDistance = p.getOffset() - offset;
+                                       if (currentDistance < 0)
+                                               currentDistance = endOfDocument - offset
+                                                               + p.getOffset();
+                               } else {
+                                       currentDistance = offset - p.getOffset();
+                                       if (currentDistance < 0)
+                                               currentDistance = offset + endOfDocument
+                                                               - p.getOffset();
+                               }
+
+                               if (nextError == null || currentDistance < distance) {
+                                       distance = currentDistance;
+                                       nextError = a;
+                                       nextErrorPosition = p;
+                               }
+                       }
+               }
+
+               if (nextErrorPosition != null) {
+                       errorPosition.setOffset(nextErrorPosition.getOffset());
+                       errorPosition.setLength(nextErrorPosition.getLength());
+               }
+
+               return nextError;
+       }
+
+       protected void uninstallOverrideIndicator() {
+               // if (fOverrideIndicatorManager != null) {
+               // fOverrideIndicatorManager.removeAnnotations();
+               // fOverrideIndicatorManager= null;
+               // }
+       }
+
+       protected void installOverrideIndicator(boolean waitForReconcilation) {
+               uninstallOverrideIndicator();
+               IAnnotationModel model = getDocumentProvider().getAnnotationModel(
+                               getEditorInput());
+               final IJavaElement inputElement = getInputJavaElement();
+
+               if (model == null || inputElement == null)
+                       return;
+
+               // fOverrideIndicatorManager= new OverrideIndicatorManager(model,
+               // inputElement, null);
+               //
+               // if (provideAST) {
+               // Job job= new
+               // Job(JavaEditorMessages.getString("OverrideIndicatorManager.intallJob"))
+               // {
+               // //$NON-NLS-1$
+               // /*
+               // * @see
+               // org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+               // * @since 3.0
+               // */
+               // protected IStatus run(IProgressMonitor monitor) {
+               // CompilationUnit ast=
+               // JavaPlugin.getDefault().getASTProvider().getAST(inputElement, true,
+               // null);
+               // if (fOverrideIndicatorManager != null) // editor might have been
+               // closed
+               // in the meanwhile
+               // fOverrideIndicatorManager.reconciled(ast, true, monitor);
+               // return Status.OK_STATUS;
+               // }
+               // };
+               // job.setPriority(Job.DECORATE);
+               // job.setSystem(true);
+               // job.schedule();
+               // }
+       }
+
+       /**
+        * Tells whether override indicators are shown.
+        * 
+        * @return <code>true</code> if the override indicators are shown
+        * @since 3.0
+        */
+       // protected boolean isShowingOverrideIndicators() {
+       // AnnotationPreference preference=
+       // getAnnotationPreferenceLookup().getAnnotationPreference(OverrideIndicatorManager.ANNOTATION_TYPE);
+       // IPreferenceStore store= getPreferenceStore();
+       // return getBoolean(store, preference.getHighlightPreferenceKey())
+       // || getBoolean(store, preference.getVerticalRulerPreferenceKey())
+       // || getBoolean(store, preference.getOverviewRulerPreferenceKey())
+       // || getBoolean(store, preference.getTextPreferenceKey());
+       // }
+       /**
+        * Returns the boolean preference for the given key.
+        * 
+        * @param store
+        *            the preference store
+        * @param key
+        *            the preference key
+        * @return <code>true</code> if the key exists in the store and its value
+        *         is <code>true</code>
+        * @since 3.0
+        */
+       private boolean getBoolean(IPreferenceStore store, String key) {
+               return key != null && store.getBoolean(key);
+       }
+
+       protected boolean isPrefQuickDiffAlwaysOn() {
+               return false; // never show change ruler for the non-editable java
+                                               // editor.
+               // Overridden in subclasses like PHPUnitEditor
+       }
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractTextEditor#createNavigationActions()
+        */
+       protected void createNavigationActions() {
+               super.createNavigationActions();
+
+               final StyledText textWidget = getSourceViewer().getTextWidget();
+
+               IAction action = new SmartLineStartAction(textWidget, false);
+               action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_START);
+               setAction(ITextEditorActionDefinitionIds.LINE_START, action);
+
+               action = new SmartLineStartAction(textWidget, true);
+               action
+                               .setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_LINE_START);
+               setAction(ITextEditorActionDefinitionIds.SELECT_LINE_START, action);
+
+               action = new NavigatePreviousSubWordAction();
+               action
+                               .setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_PREVIOUS);
+               setAction(ITextEditorActionDefinitionIds.WORD_PREVIOUS, action);
+               textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_LEFT, SWT.NULL);
+
+               action = new NavigateNextSubWordAction();
+               action.setActionDefinitionId(ITextEditorActionDefinitionIds.WORD_NEXT);
+               setAction(ITextEditorActionDefinitionIds.WORD_NEXT, action);
+               textWidget.setKeyBinding(SWT.CTRL | SWT.ARROW_RIGHT, SWT.NULL);
+
+               action = new SelectPreviousSubWordAction();
+               action
+                               .setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS);
+               setAction(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS, action);
+               textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_LEFT,
+                               SWT.NULL);
+
+               action = new SelectNextSubWordAction();
+               action
+                               .setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT);
+               setAction(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT, action);
+               textWidget.setKeyBinding(SWT.CTRL | SWT.SHIFT | SWT.ARROW_RIGHT,
+                               SWT.NULL);
+       }
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createCompositeRuler()
+        */
+       // protected CompositeRuler createCompositeRuler() {
+       // if
+       // (!getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER))
+       // return super.createCompositeRuler();
+       //
+       // CompositeRuler ruler = new CompositeRuler();
+       // AnnotationRulerColumn column = new
+       // AnnotationRulerColumn(VERTICAL_RULER_WIDTH, getAnnotationAccess());
+       // column.setHover(new JavaExpandHover(ruler, getAnnotationAccess(), new
+       // IDoubleClickListener() {
+       //
+       // public void doubleClick(DoubleClickEvent event) {
+       // // for now: just invoke ruler double click action
+       // triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK);
+       // }
+       //
+       // private void triggerAction(String actionID) {
+       // IAction action = getAction(actionID);
+       // if (action != null) {
+       // if (action instanceof IUpdate)
+       // ((IUpdate) action).update();
+       // // hack to propagate line change
+       // if (action instanceof ISelectionListener) {
+       // ((ISelectionListener) action).selectionChanged(null, null);
+       // }
+       // if (action.isEnabled())
+       // action.run();
+       // }
+       // }
+       //
+       // }));
+       // ruler.addDecorator(0, column);
+       //
+       // if (isLineNumberRulerVisible())
+       // ruler.addDecorator(1, createLineNumberRulerColumn());
+       // else if (isPrefQuickDiffAlwaysOn())
+       // ruler.addDecorator(1, createChangeRulerColumn());
+       //
+       // return ruler;
+       // }
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createAnnotationRulerColumn(org.eclipse.jface.text.source.CompositeRuler)
+        * @since 3.2
+        */
+       protected IVerticalRulerColumn createAnnotationRulerColumn(
+                       CompositeRuler ruler) {
+               if (!getPreferenceStore().getBoolean(
+                               PreferenceConstants.EDITOR_ANNOTATION_ROLL_OVER))
+                       return super.createAnnotationRulerColumn(ruler);
+
+               AnnotationRulerColumn column = new AnnotationRulerColumn(
+                               VERTICAL_RULER_WIDTH, getAnnotationAccess());
+               column.setHover(new JavaExpandHover(ruler, getAnnotationAccess(),
+                               new IDoubleClickListener() {
+
+                                       public void doubleClick(DoubleClickEvent event) {
+                                               // for now: just invoke ruler double click action
+                                               triggerAction(ITextEditorActionConstants.RULER_DOUBLE_CLICK);
+                                       }
+
+                                       private void triggerAction(String actionID) {
+                                               IAction action = getAction(actionID);
+                                               if (action != null) {
+                                                       if (action instanceof IUpdate)
+                                                               ((IUpdate) action).update();
+                                                       // hack to propagate line change
+                                                       if (action instanceof ISelectionListener) {
+                                                               ((ISelectionListener) action).selectionChanged(
+                                                                               null, null);
+                                                       }
+                                                       if (action.isEnabled())
+                                                               action.run();
+                                               }
+                                       }
+
+                               }));
+
+               return column;
+       }
+
+       /**
+        * Returns the folding action group, or <code>null</code> if there is
+        * none.
+        * 
+        * @return the folding action group, or <code>null</code> if there is none
+        * @since 3.0
+        */
+       protected FoldingActionGroup getFoldingActionGroup() {
+               return fFoldingGroup;
+       }
+
+       /*
+        * @see org.eclipse.ui.texteditor.AbstractTextEditor#performRevert()
+        */
+       protected void performRevert() {
+               ProjectionViewer projectionViewer = (ProjectionViewer) getSourceViewer();
+               projectionViewer.setRedraw(false);
+               try {
+
+                       boolean projectionMode = projectionViewer.isProjectionMode();
+                       if (projectionMode) {
+                               projectionViewer.disableProjection();
+                               if (fProjectionModelUpdater != null)
+                                       fProjectionModelUpdater.uninstall();
+                       }
+
+                       super.performRevert();
+
+                       if (projectionMode) {
+                               if (fProjectionModelUpdater != null)
+                                       fProjectionModelUpdater.install(this, projectionViewer);
+                               projectionViewer.enableProjection();
+                       }
+
+               } finally {
+                       projectionViewer.setRedraw(true);
+               }
+       }
+
+       /**
+        * React to changed selection.
+        * 
+        * @since 3.0
+        */
+       protected void selectionChanged() {
+               if (getSelectionProvider() == null)
+                       return;
+               ISourceReference element = computeHighlightRangeSourceReference();
+               if (getPreferenceStore().getBoolean(
+                               PreferenceConstants.EDITOR_SYNC_OUTLINE_ON_CURSOR_MOVE))
+                       synchronizeOutlinePage(element);
+               setSelection(element, false);
+               updateStatusLine();
+       }
+
+       private boolean isJavaOutlinePageActive() {
+               IWorkbenchPart part = getActivePart();
+               return part instanceof ContentOutline
+                               && ((ContentOutline) part).getCurrentPage() == fOutlinePage;
+       }
+
+       private IWorkbenchPart getActivePart() {
+               IWorkbenchWindow window = getSite().getWorkbenchWindow();
+               IPartService service = window.getPartService();
+               IWorkbenchPart part = service.getActivePart();
+               return part;
+       }
+
+       /**
+        * Computes and returns the source reference that includes the caret and
+        * serves as provider for the outline page selection and the editor range
+        * indication.
+        * 
+        * @return the computed source reference
+        * @since 3.0
+        */
+       protected ISourceReference computeHighlightRangeSourceReference() {
+               ISourceViewer sourceViewer = getSourceViewer();
+               if (sourceViewer == null)
+                       return null;
+
+               StyledText styledText = sourceViewer.getTextWidget();
+               if (styledText == null)
+                       return null;
+
+               int caret = 0;
+               if (sourceViewer instanceof ITextViewerExtension5) {
+                       ITextViewerExtension5 extension = (ITextViewerExtension5) sourceViewer;
+                       caret = extension.widgetOffset2ModelOffset(styledText
+                                       .getCaretOffset());
+               } else {
+                       int offset = sourceViewer.getVisibleRegion().getOffset();
+                       caret = offset + styledText.getCaretOffset();
+               }
+
+               IJavaElement element = getElementAt(caret, false);
+
+               if (!(element instanceof ISourceReference))
+                       return null;
+
+               if (element.getElementType() == IJavaElement.IMPORT_DECLARATION) {
+
+                       IImportDeclaration declaration = (IImportDeclaration) element;
+                       IImportContainer container = (IImportContainer) declaration
+                                       .getParent();
+                       ISourceRange srcRange = null;
+
+                       try {
+                               srcRange = container.getSourceRange();
+                       } catch (JavaModelException e) {
+                       }
+
+                       if (srcRange != null && srcRange.getOffset() == caret)
+                               return container;
+               }
+
+               return (ISourceReference) element;
+       }
+
+       /**
+        * Returns the most narrow java element including the given offset.
+        * 
+        * @param offset
+        *            the offset inside of the requested element
+        * @param reconcile
+        *            <code>true</code> if editor input should be reconciled in
+        *            advance
+        * @return the most narrow java element
+        * @since 3.0
+        */
+       protected IJavaElement getElementAt(int offset, boolean reconcile) {
+               return getElementAt(offset);
+       }
+
+       public ShowInContext getShowInContext() {
+               FileEditorInput fei = (FileEditorInput) getEditorInput();
+               ShowInContext context = BrowserUtil.getShowInContext(fei.getFile(),
+                               false, "");
+               if (context != null) {
+                       return context;
+               }
+               return new ShowInContext(fei.getFile(), null);
+       }
+
+       public String[] getShowInTargetIds() {
+               return new String[] { BrowserView.ID_BROWSER };
+       }
+
+       /**
+        * Updates the occurrences annotations based on the current selection.
+        * 
+        * @param selection
+        *            the text selection
+        * @param astRoot
+        *            the compilation unit AST
+        * @since 3.0
+        */
+       protected void updateOccurrenceAnnotations(ITextSelection selection) {// ,
+               // CompilationUnit
+               // astRoot)
+               // {
+
+               if (fOccurrencesFinderJob != null)
+                       fOccurrencesFinderJob.cancel();
+
+               if (!fMarkOccurrenceAnnotations)
+                       return;
+
+               // if (astRoot == null || selection == null)
+               if (selection == null)
+                       return;
+
+               IDocument document = getSourceViewer().getDocument();
+               if (document == null)
+                       return;
+
+               fMarkOccurrenceTargetRegion = null;
+               if (document instanceof IDocumentExtension4) {
+                       int offset = selection.getOffset();
+                       long currentModificationStamp = ((IDocumentExtension4) document)
+                                       .getModificationStamp();
+                       if (fMarkOccurrenceTargetRegion != null
+                                       && currentModificationStamp == fMarkOccurrenceModificationStamp) {
+                               if (fMarkOccurrenceTargetRegion.getOffset() <= offset
+                                               && offset <= fMarkOccurrenceTargetRegion.getOffset()
+                                                               + fMarkOccurrenceTargetRegion.getLength())
+                                       return;
+                       }
+                       fMarkOccurrenceTargetRegion = JavaWordFinder.findWord(document,
+                                       offset);
+                       fMarkOccurrenceModificationStamp = currentModificationStamp;
+               }
+
+               if (fMarkOccurrenceTargetRegion == null
+                               || fMarkOccurrenceTargetRegion.getLength() == 0) {
+                       return;
+               }
+
+               List matches = null;
+
+               if (matches == null) {
+                       try {
+                               matches = new ArrayList();
+
+                               Scanner fScanner = new Scanner();
+                               fScanner.setSource(document.get().toCharArray());
+                               fScanner.setPHPMode(false);
+                               String wordStr;
+                               char[] word;
+
+                               wordStr = document.get(fMarkOccurrenceTargetRegion.getOffset(),
+                                               fMarkOccurrenceTargetRegion.getLength());
+                               if (wordStr != null) {
+                                       word = wordStr.toCharArray();
+                                       int fToken = ITerminalSymbols.TokenNameEOF;
+                                       try {
+                                               fToken = fScanner.getNextToken();
+                                               while (fToken != ITerminalSymbols.TokenNameEOF) { // &&
+                                                                                                                                                       // fToken
+                                                                                                                                                       // !=
+                                                       // TokenNameERROR) {
+                                                       if (fToken == ITerminalSymbols.TokenNameVariable
+                                                                       || fToken == ITerminalSymbols.TokenNameIdentifier) {
+                                                               // global variable
+                                                               if (fScanner.equalsCurrentTokenSource(word)) {
+                                                                       matches
+                                                                                       .add(new Region(
+                                                                                                       fScanner
+                                                                                                                       .getCurrentTokenStartPosition(),
+                                                                                                       fScanner
+                                                                                                                       .getCurrentTokenEndPosition()
+                                                                                                                       - fScanner
+                                                                                                                                       .getCurrentTokenStartPosition()
+                                                                                                                       + 1));
+                                                               }
+                                                       }
+                                                       fToken = fScanner.getNextToken();
+                                               }
+                                       } catch (InvalidInputException e) {
+                                               // ignore errors
+                                       } catch (SyntaxError e) {
+                                               // ignore errors
+                                       }
+                               }
+                       } catch (BadLocationException e1) {
+                               // ignore errors
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                               // ignore errors
+                       }
+
+               }
+
+               if (matches == null || matches.size() == 0) {
+                       if (!fStickyOccurrenceAnnotations)
+                               removeOccurrenceAnnotations();
+                       return;
+               }
+
+               Position[] positions = new Position[matches.size()];
+               int i = 0;
+               for (Iterator each = matches.iterator(); each.hasNext();) {
+                       IRegion currentNode = (IRegion) each.next();
+                       positions[i++] = new Position(currentNode.getOffset(), currentNode
+                                       .getLength());
+               }
+
+               fOccurrencesFinderJob = new OccurrencesFinderJob(document, positions,
+                               selection);
+               // fOccurrencesFinderJob.setPriority(Job.DECORATE);
+               // fOccurrencesFinderJob.setSystem(true);
+               // fOccurrencesFinderJob.schedule();
+               fOccurrencesFinderJob.run(new NullProgressMonitor());
+       }
+
+       protected void installOccurrencesFinder() {
+               fMarkOccurrenceAnnotations = true;
+
+               fPostSelectionListenerWithAST = new ISelectionListenerWithAST() {
+                       public void selectionChanged(IEditorPart part,
+                                       ITextSelection selection) { // ,
+                               // CompilationUnit
+                               // astRoot)
+                               // {
+                               updateOccurrenceAnnotations(selection);// , astRoot);
+                       }
+               };
+               SelectionListenerWithASTManager.getDefault().addListener(this,
+                               fPostSelectionListenerWithAST);
+               if (getSelectionProvider() != null) {
+                       fForcedMarkOccurrencesSelection = getSelectionProvider()
+                                       .getSelection();
+                       SelectionListenerWithASTManager.getDefault().forceSelectionChange(
+                                       this, (ITextSelection) fForcedMarkOccurrencesSelection);
+               }
+
+               if (fOccurrencesFinderJobCanceler == null) {
+                       fOccurrencesFinderJobCanceler = new OccurrencesFinderJobCanceler();
+                       fOccurrencesFinderJobCanceler.install();
+               }
+       }
+
+       protected void uninstallOccurrencesFinder() {
+               fMarkOccurrenceAnnotations = false;
+
+               if (fOccurrencesFinderJob != null) {
+                       fOccurrencesFinderJob.cancel();
+                       fOccurrencesFinderJob = null;
+               }
+
+               if (fOccurrencesFinderJobCanceler != null) {
+                       fOccurrencesFinderJobCanceler.uninstall();
+                       fOccurrencesFinderJobCanceler = null;
+               }
+
+               if (fPostSelectionListenerWithAST != null) {
+                       SelectionListenerWithASTManager.getDefault().removeListener(this,
+                                       fPostSelectionListenerWithAST);
+                       fPostSelectionListenerWithAST = null;
+               }
+
+               removeOccurrenceAnnotations();
+       }
+
+       protected boolean isMarkingOccurrences() {
+               return fMarkOccurrenceAnnotations;
+       }
+
+       void removeOccurrenceAnnotations() {
+               fMarkOccurrenceModificationStamp = IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
+               fMarkOccurrenceTargetRegion = null;
+
+               IDocumentProvider documentProvider = getDocumentProvider();
+               if (documentProvider == null)
+                       return;
+
+               IAnnotationModel annotationModel = documentProvider
+                               .getAnnotationModel(getEditorInput());
+               if (annotationModel == null || fOccurrenceAnnotations == null)
+                       return;
+
+               synchronized (getLockObject(annotationModel)) {
+                       if (annotationModel instanceof IAnnotationModelExtension) {
+                               ((IAnnotationModelExtension) annotationModel)
+                                               .replaceAnnotations(fOccurrenceAnnotations, null);
+                       } else {
+                               for (int i = 0, length = fOccurrenceAnnotations.length; i < length; i++)
+                                       annotationModel.removeAnnotation(fOccurrenceAnnotations[i]);
+                       }
+                       fOccurrenceAnnotations = null;
+               }
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/phpeditor/PHPTextHover.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/phpeditor/PHPTextHover.java
new file mode 100644 (file)
index 0000000..08c077e
--- /dev/null
@@ -0,0 +1,151 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+
+ Contributors:
+ IBM Corporation - Initial implementation
+ www.phpeclipse.de
+ **********************************************************************/
+package net.sourceforge.phpeclipse.phpeditor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import net.sourceforge.phpdt.internal.corext.phpdoc.PHPDocUtil;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+import net.sourceforge.phpeclipse.builder.IdentifierIndexManager;
+import net.sourceforge.phpeclipse.builder.PHPIdentifierLocation;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPElement;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPFunction;
+import net.sourceforge.phpeclipse.phpeditor.php.PHPWordExtractor;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Implementation for an <code>ITextHover</code> which hovers over PHP code.
+ */
+public class PHPTextHover implements ITextHover {
+       private static HashMap functionDescriptions = null;
+
+       private static HashMap identDescriptions = null;
+
+       /**
+        * The current project; maybe <code>null</code> for preference pages
+        */
+       private IProject fProject;
+
+       public PHPTextHover(IProject project) {
+               fProject = project;
+       }
+
+       /*
+        * (non-Javadoc) Method declared on ITextHover
+        */
+       public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
+               if (hoverRegion != null) {
+                       try {
+                               if (hoverRegion.getLength() > -1) {
+                                       String word = textViewer.getDocument().get(
+                                                       hoverRegion.getOffset(), hoverRegion.getLength());
+                                       if (functionDescriptions == null) {
+                                               functionDescriptions = new HashMap();
+                                               identDescriptions = new HashMap();
+                                               ArrayList syntaxbuffer = PHPSyntaxRdr.getSyntaxData();
+                                               PHPElement elbuffer = null;
+                                               if (syntaxbuffer != null) {
+                                                       for (int i = 0; i < syntaxbuffer.size(); i++) {
+                                                               elbuffer = (PHPElement) syntaxbuffer.get(i);
+                                                               if (elbuffer instanceof PHPFunction) {
+                                                                       functionDescriptions.put(
+                                                                                       elbuffer.getName(), elbuffer
+                                                                                                       .getHoverText());
+                                                               } else {
+                                                                       identDescriptions.put(elbuffer.getName(),
+                                                                                       elbuffer.getHoverText());
+                                                               }
+                                                       }
+                                               }
+                                               //
+                                               // while ((syntaxbuffer != null)
+                                               // && (!syntaxbuffer.isEmpty() && ((elbuffer =
+                                               // (PHPElement)
+                                               // syntaxbuffer.remove(0)) != null))) {
+                                               // functionDescriptions.put(elbuffer.getName(),
+                                               // elbuffer.getHoverText());
+                                               // }
+                                       }
+                                       String hoverInfo = (String) identDescriptions.get(word);
+                                       if (hoverInfo == null & word.length() > 0) {
+                                               hoverInfo = (String) functionDescriptions.get(word
+                                                               .toLowerCase());
+                                       }
+                                       if (hoverInfo == null && fProject != null) {
+                                               // get the possible PHPDoc information from the index
+                                               // file
+                                               IdentifierIndexManager indexManager = PHPeclipsePlugin
+                                                               .getDefault().getIndexManager(fProject);
+                                               List list = indexManager.getLocations(word);
+                                               if (list.size() > 0) {
+                                                       try {
+                                                               PHPIdentifierLocation location;
+                                                               String filename;
+                                                               StringBuffer hoverInfoBuffer = new StringBuffer();
+                                                               String workspaceLocation;
+                                                               if (fProject != null) {
+                                                                       workspaceLocation = fProject.getLocation()
+                                                                                       .toString() + '/';
+                                                               } else {
+                                                                       // should never happen?
+                                                                       workspaceLocation = PHPeclipsePlugin
+                                                                                       .getWorkspace().getRoot()
+                                                                                       .getLocation().toString();
+                                                               }
+                                                               // boolean foundPHPdoc = false;
+                                                               for (int i = 0; i < list.size(); i++) {
+                                                                       location = (PHPIdentifierLocation) list
+                                                                                       .get(i);
+                                                                       filename = workspaceLocation
+                                                                                       + location.getFilename();
+                                                                       PHPDocUtil.appendPHPDoc(hoverInfoBuffer,
+                                                                                       filename, location);
+                                                               }
+                                                               hoverInfo = hoverInfoBuffer.toString();
+                                                       } catch (Throwable e) {
+                                                               // ignore exceptions
+                                                               // e.printStackTrace();
+                                                       }
+                                               }
+                                       }
+                                       return hoverInfo;
+                               }
+                               // } catch (BadLocationException x) {
+                       } catch (Exception x) {
+                       }
+               }
+               return null;
+               // don't show this annoying text
+               // return "empty selection";
+       }
+
+       /*
+        * (non-Javadoc) Method declared on ITextHover
+        */
+       public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
+               Point selection = PHPWordExtractor.findWord(textViewer.getDocument(),
+                               offset);
+               // show the extracted word as a tooltip
+               if (selection != null && selection.x <= offset
+                               && offset < selection.x + selection.y)
+                       return new Region(selection.x, selection.y);
+               return new Region(offset, 0);
+       }
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/ui/WebUI.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/ui/WebUI.java
new file mode 100644 (file)
index 0000000..8404335
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     Christopher Lenz - initial implementation
+ *
+ * $Id: WebUI.java,v 1.7 2006-10-21 23:13:54 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.ui;
+
+import java.io.IOException;
+import java.net.URL;
+
+import net.sourceforge.phpeclipse.ui.templates.template.HTMLContextType;
+import net.sourceforge.phpeclipse.ui.templates.template.JSContextType;
+import net.sourceforge.phpeclipse.ui.templates.template.SmartyContextType;
+import net.sourceforge.phpeclipse.ui.templates.template.XMLContextType;
+
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
+import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+
+/**
+ * The web development tools UI plugin.
+ */
+public class WebUI extends AbstractUIPlugin implements IPreferenceConstants {
+       private static final String CUSTOM_TEMPLATES_KEY = "net.sourceforge.phpeclipse.ui.templates"; //$NON-NLS-1$
+
+       // Constants ---------------------------------------------------------------
+
+       public static final String ICON_OVERLAY_ERROR = "full/ovr16/error_co.gif"; //$NON-NLS-1$
+
+       public static final String ICON_OVERLAY_WARNING = "full/ovr16/warning_co.gif"; //$NON-NLS-1$
+
+       // Instance Variables ------------------------------------------------------
+
+       /** The shared instance. */
+       private static WebUI plugin;
+
+       public static IWorkbenchPage getActivePage() {
+               return getDefault().internalGetActivePage();
+       }
+
+       private IWorkbenchPage internalGetActivePage() {
+               return getWorkbench().getActiveWorkbenchWindow().getActivePage();
+       }
+
+       public static Shell getActiveWorkbenchShell() {
+               return getActiveWorkbenchWindow().getShell();
+       }
+
+       public static IWorkbenchWindow getActiveWorkbenchWindow() {
+               return getDefault().getWorkbench().getActiveWorkbenchWindow();
+       }
+
+       // Public Methods ----------------------------------------------------------
+
+       /**
+        * Returns the shared instance.
+        */
+       public static WebUI getDefault() {
+               return plugin;
+       }
+
+       /**
+        * Returns the workspace instance.
+        */
+       public static IWorkspace getWorkspace() {
+               return ResourcesPlugin.getWorkspace();
+       }
+
+       /** The context type registry. */
+       private ContributionContextTypeRegistry fRegistry;
+
+       /** The template store. */
+       private TemplateStore fStore;
+
+       // Constructors ------------------------------------------------------------
+
+       /**
+        * The constructor.
+        */
+       public WebUI() {
+               plugin = this;
+       }
+
+       /**
+        * Returns this plug-in's context type registry.
+        * 
+        * @return the context type registry for this plug-in instance
+        */
+       public ContextTypeRegistry getContextTypeRegistry() {
+               if (fRegistry == null) {
+                       // create an configure the contexts available in the editor
+                       fRegistry = new ContributionContextTypeRegistry();
+                       fRegistry.addContextType(XMLContextType.XML_CONTEXT_TYPE);
+                       fRegistry.addContextType(HTMLContextType.HTML_CONTEXT_TYPE);
+                       fRegistry.addContextType(SmartyContextType.SMARTY_CONTEXT_TYPE);
+                       fRegistry.addContextType(JSContextType.JS_CONTEXT_TYPE);
+               }
+               return fRegistry;
+       }
+
+       // Private Methods ---------------------------------------------------------
+
+       /**
+        * Returns an image descriptor for the image corresponding to the specified
+        * key (which is the name of the image file).
+        * 
+        * @param key
+        *            The key of the image
+        * @return The descriptor for the requested image, or <code>null</code> if
+        *         the image could not be found
+        */
+       private ImageDescriptor getImageDescriptor(String key) {
+               try {
+                       URL url = getBundle().getEntry("/icons/" + key); //$NON-NLS-1$
+                       return ImageDescriptor.createFromURL(url);
+               } catch (IllegalStateException e) {
+                       return null;
+               }
+       }
+
+       /**
+        * Returns this plug-in's template store.
+        * 
+        * @return the template store of this plug-in instance
+        */
+       public TemplateStore getTemplateStore() {
+               if (fStore == null) {
+                       fStore = new ContributionTemplateStore(getContextTypeRegistry(),
+                                       getDefault().getPreferenceStore(), CUSTOM_TEMPLATES_KEY);
+                       try {
+                               fStore.load();
+                       } catch (IOException e) {
+                               WebUI
+                                               .getDefault()
+                                               .getLog()
+                                               .log(
+                                                               new Status(
+                                                                               IStatus.ERROR,
+                                                                               "net.sourceforge.phpeclipse.ui", IStatus.OK, "", e)); //$NON-NLS-1$ //$NON-NLS-2$
+                       }
+               }
+               return fStore;
+       }
+
+       protected void initializeDefaultPreferences(IPreferenceStore store) {
+               store.setDefault(PHP_LOCALHOST_PREF, "http://localhost");
+               store.setDefault(PHP_DOCUMENTROOT_PREF, getWorkspace().getRoot()
+                               .getLocation().toString());
+               // store.setDefault(PHP_BOOKMARK_DEFAULT, "");
+
+               store.setDefault(PHP_AUTO_PREVIEW_DEFAULT, "true");
+               store.setDefault(PHP_BRING_TO_TOP_PREVIEW_DEFAULT, "true");
+               // store.setDefault(PHP_SHOW_HTML_FILES_LOCAL, "true");
+               // store.setDefault(PHP_SHOW_XML_FILES_LOCAL, "false");
+       }
+
+       /*
+        * @see AbstractUIPlugin#initializeImageRegistry(ImageRegistry)
+        */
+       protected void initializeImageRegistry(ImageRegistry reg) {
+               reg.put(ICON_OVERLAY_ERROR, getImageDescriptor(ICON_OVERLAY_ERROR));
+               reg.put(ICON_OVERLAY_WARNING, getImageDescriptor(ICON_OVERLAY_WARNING));
+       }
+       // private IWorkbenchPage internalGetActivePage() {
+       // IWorkbenchWindow window = getWorkbench().getActiveWorkbenchWindow();
+       // if (window != null)
+       // return window.getActivePage();
+       // return null;
+       // }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/ui/editor/ShowExternalPreviewAction.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/ui/editor/ShowExternalPreviewAction.java
new file mode 100644 (file)
index 0000000..abe117e
--- /dev/null
@@ -0,0 +1,129 @@
+package net.sourceforge.phpeclipse.ui.editor;
+
+import net.sourceforge.phpeclipse.ui.IPreferenceConstants;
+import net.sourceforge.phpeclipse.ui.WebUI;
+import net.sourceforge.phpeclipse.ui.overlaypages.ProjectPrefUtil;
+import net.sourceforge.phpeclipse.webbrowser.views.BrowserView;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.TextEditorAction;
+
+/**
+ * ClassDeclaration that defines the action for parsing the current PHP file
+ */
+public class ShowExternalPreviewAction extends TextEditorAction {
+       public final static int XML_TYPE = 1;
+
+       public final static int HTML_TYPE = 2;
+
+       public final static int SMARTY_TYPE = 3;
+
+       public final static int PHP_TYPE = 4;
+
+       private static ShowExternalPreviewAction instance = new ShowExternalPreviewAction();
+
+       /**
+        * Constructs and updates the action.
+        */
+       private ShowExternalPreviewAction() {
+               super(EditorMessages.getResourceBundle(), "ParserAction.", null); //$NON-NLS-1$
+               update();
+       }
+
+       public static ShowExternalPreviewAction getInstance() {
+               return instance;
+       }
+
+       /**
+        * Code called when the action is fired.
+        */
+       public void run() {
+               doRun(PHP_TYPE);
+       }
+
+       public void doRun(int type) {
+               IFile previewFile = getFile();
+               BrowserUtil.showPreview(previewFile, false, "");
+       }
+
+       public void refresh(int type) {
+               IFile fileToParse = getFile();
+               if (fileToParse == null) {
+                       // should never happen
+                       return;
+               }
+               boolean autoPreview = ProjectPrefUtil.getPreviewBooleanValue(
+                               fileToParse, IPreferenceConstants.PHP_AUTO_PREVIEW_DEFAULT);
+               boolean bringToTopPreview = ProjectPrefUtil.getPreviewBooleanValue(
+                               fileToParse,
+                               IPreferenceConstants.PHP_BRING_TO_TOP_PREVIEW_DEFAULT);
+
+               if (autoPreview) {
+                       IWorkbenchPage page = WebUI.getActivePage();
+                       try {
+                               IViewPart part = page.findView(BrowserView.ID_BROWSER);
+                               if (part == null) {
+                                       part = page.showView(BrowserView.ID_BROWSER);
+                               } else {
+                                       if (bringToTopPreview) {
+                                               page.bringToTop(part);
+                                       }
+                               }
+                               if (part != null) {
+                                       ((BrowserView) part).refresh();
+                               }
+                       } catch (Exception e) {
+                               // PHPeclipsePlugin.log(e);
+                       }
+               }
+       }
+
+       /**
+        * Finds the file that's currently opened in the PHP Text Editor
+        */
+       protected IFile getFile() {
+               ITextEditor editor = getTextEditor();
+               IEditorInput editorInput = null;
+               if (editor != null) {
+                       editorInput = editor.getEditorInput();
+               }
+               if (editorInput instanceof IFileEditorInput)
+                       return ((IFileEditorInput) editorInput).getFile();
+               // if nothing was found, which should never happen
+               return null;
+       }
+
+       public static String getLocalhostURL(IPreferenceStore store, IFile file) {
+               if (file != null) {
+                       if (store == null) {
+                               store = WebUI.getDefault().getPreferenceStore();
+                       }
+                       // IPath path = file.getFullPath();
+                       String localhostURL = file.getLocation().toString();
+                       String lowerCaseFileName = localhostURL.toLowerCase();
+                       // String documentRoot =
+                       // store.getString(PHPeclipsePlugin.DOCUMENTROOT_PREF);
+                       IPath documentRootPath = ProjectPrefUtil.getDocumentRoot(file
+                                       .getProject());
+                       String documentRoot = documentRootPath.toString().toLowerCase();
+                       if (lowerCaseFileName.startsWith(documentRoot)) {
+                               localhostURL = localhostURL.substring(documentRoot.length());
+                       } else {
+                               return null;
+                       }
+                       // return store.getString(PHPeclipsePlugin.LOCALHOST_PREF) +
+                       // localhostURL;
+                       return ProjectPrefUtil.getMiscProjectsPreferenceValue(file
+                                       .getProject(), IPreferenceConstants.PHP_LOCALHOST_PREF)
+                                       + localhostURL;
+               }
+               return "http://localhost";
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/webbrowser/internal/OpenWithBrowserActionDelegate.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/webbrowser/internal/OpenWithBrowserActionDelegate.java
new file mode 100644 (file)
index 0000000..18cdc65
--- /dev/null
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. ï¿½ This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ ï¿½*
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package net.sourceforge.phpeclipse.webbrowser.internal;
+
+import java.net.URL;
+import java.util.Iterator;
+
+import net.sourceforge.phpeclipse.webbrowser.WebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.WebBrowserEditorInput;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IActionDelegate;
+
+/**
+ * Action to open the Web broswer on a resource.
+ */
+public class OpenWithBrowserActionDelegate implements IActionDelegate {
+       private IResource resource;
+
+       /**
+        * OpenBrowserAction constructor comment.
+        */
+       public OpenWithBrowserActionDelegate() {
+               super();
+       }
+
+       /**
+        * Performs this action.
+        * <p>
+        * This method is called when the delegating action has been triggered.
+        * Implement this method to do the actual work.
+        * </p>
+        * 
+        * @param action
+        *            the action proxy that handles the presentation portion of the
+        *            action
+        */
+       public void run(IAction action) {
+               URL url = null;
+               try {
+                       url = new URL("file://" + resource.getLocation());
+                       WebBrowser.openURL(new WebBrowserEditorInput(url,
+                                       WebBrowserEditorInput.SHOW_ALL
+                                                       | WebBrowserEditorInput.FORCE_NEW_PAGE));
+               } catch (Exception e) {
+                       Trace.trace(Trace.SEVERE, "Error opening browser on file", e);
+               }
+       }
+
+       /**
+        * Notifies this action delegate that the selection in the workbench has
+        * changed.
+        * <p>
+        * Implementers can use this opportunity to change the availability of the
+        * action or to modify other presentation properties.
+        * </p>
+        * 
+        * @param action
+        *            the action proxy that handles presentation portion of the
+        *            action
+        * @param selection
+        *            the current selection in the workbench
+        */
+       public void selectionChanged(IAction action, ISelection sel) {
+               if (sel.isEmpty() || !(sel instanceof IStructuredSelection)) {
+                       action.setEnabled(false);
+                       return;
+               }
+
+               IStructuredSelection select = (IStructuredSelection) sel;
+               Iterator iterator = select.iterator();
+               Object selection = iterator.next();
+               if (iterator.hasNext()) { // more than one selection (should never
+                                                                       // happen)
+                       action.setEnabled(false);
+                       return;
+               }
+
+               if (!(selection instanceof IResource)) {
+                       action.setEnabled(false);
+                       return;
+               }
+
+               resource = (IResource) selection;
+               action.setEnabled(true);
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/webbrowser/internal/WebBrowserEditor.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/webbrowser/internal/WebBrowserEditor.java
new file mode 100644 (file)
index 0000000..f266e11
--- /dev/null
@@ -0,0 +1,404 @@
+/**
+ * Copyright (c) 2003 IBM Corporation and others.
+ * All rights reserved. ï¿½ This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ ï¿½*
+ * Contributors:
+ *    IBM - Initial API and implementation
+ */
+package net.sourceforge.phpeclipse.webbrowser.internal;
+
+import java.net.URL;
+
+import net.sourceforge.phpeclipse.webbrowser.IWebBrowserEditorInput;
+import net.sourceforge.phpeclipse.webbrowser.WebBrowserEditorInput;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IEditorReference;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.part.EditorPart;
+
+/**
+ * An integrated Web browser, defined as an editor to make better use of the
+ * desktop.
+ */
+public class WebBrowserEditor extends EditorPart {
+       public static final String WEB_BROWSER_EDITOR_ID = "net.sourceforge.phpeclipse.webbrowser";
+
+       protected WebBrowser webBrowser;
+
+       protected String initialURL;
+
+       protected Image image;
+
+       protected TextAction cutAction;
+
+       protected TextAction copyAction;
+
+       protected TextAction pasteAction;
+
+       protected IResourceChangeListener resourceListener;
+
+       /**
+        * WebBrowserEditor constructor comment.
+        */
+       public WebBrowserEditor() {
+               super();
+       }
+
+       /**
+        * Creates the SWT controls for this workbench part.
+        * <p>
+        * Clients should not call this method (the workbench calls this method at
+        * appropriate times).
+        * </p>
+        * <p>
+        * For implementors this is a multi-step process:
+        * <ol>
+        * <li>Create one or more controls within the parent.</li>
+        * <li>Set the parent layout as needed.</li>
+        * <li>Register any global actions with the <code>IActionService</code>.</li>
+        * <li>Register any popup menus with the <code>IActionService</code>.</li>
+        * <li>Register a selection provider with the
+        * <code>ISelectionService</code> (optional). </li>
+        * </ol>
+        * </p>
+        * 
+        * @param parent
+        *            the parent control
+        */
+       public void createPartControl(Composite parent) {
+               IWebBrowserEditorInput input = getWebBrowserEditorInput();
+
+               if (input == null || input.isToolbarVisible() == false)
+                       webBrowser = new WebBrowser(parent, false, input
+                                       .isStatusbarVisible());
+               else {
+                       webBrowser = new WebBrowser(parent, true, input
+                                       .isStatusbarVisible());
+                       cutAction = new TextAction(webBrowser, TextAction.CUT);
+                       copyAction = new TextAction(webBrowser, TextAction.COPY);
+                       pasteAction = new TextAction(webBrowser, TextAction.PASTE);
+               }
+
+               webBrowser.setURL(initialURL);
+               webBrowser.editor = this;
+       }
+
+       public void dispose() {
+               if (image != null && !image.isDisposed())
+                       image.dispose();
+               image = null;
+
+               if (resourceListener != null)
+                       ResourcesPlugin.getWorkspace().removeResourceChangeListener(
+                                       resourceListener);
+       }
+
+       /*
+        * (non-Javadoc) Saves the contents of this editor. <p> Subclasses must
+        * override this method to implement the open-save-close lifecycle for an
+        * editor. For greater details, see <code>IEditorPart</code> </p>
+        * 
+        * @see IEditorPart
+        */
+       public void doSave(IProgressMonitor monitor) {
+       }
+
+       /*
+        * (non-Javadoc) Saves the contents of this editor to another object. <p>
+        * Subclasses must override this method to implement the open-save-close
+        * lifecycle for an editor. For greater details, see <code>IEditorPart</code>
+        * </p>
+        * 
+        * @see IEditorPart
+        */
+       public void doSaveAs() {
+       }
+
+       /**
+        * Returns the copy action.
+        * 
+        * @return org.eclipse.jface.action.IAction
+        */
+       public IAction getCopyAction() {
+               return copyAction;
+       }
+
+       /**
+        * Returns the cut action.
+        * 
+        * @return org.eclipse.jface.action.IAction
+        */
+       public IAction getCutAction() {
+               return cutAction;
+       }
+
+       /**
+        * Returns the paste action.
+        * 
+        * @return org.eclipse.jface.action.IAction
+        */
+       public IAction getPasteAction() {
+               return pasteAction;
+       }
+
+       /**
+        * Returns the web editor input, if available.
+        * 
+        * @return net.sourceforge.phpeclipse.webbrowser.IWebBrowserEditorInput
+        */
+       protected IWebBrowserEditorInput getWebBrowserEditorInput() {
+               IEditorInput input = getEditorInput();
+               if (input instanceof IWebBrowserEditorInput)
+                       return (IWebBrowserEditorInput) input;
+               return null;
+       }
+
+       /*
+        * (non-Javadoc) Sets the cursor and selection state for this editor to the
+        * passage defined by the given marker. <p> Subclasses may override. For
+        * greater details, see <code>IEditorPart</code> </p>
+        * 
+        * @see IEditorPart
+        */
+       public void gotoMarker(IMarker marker) {
+       }
+
+       /*
+        * (non-Javadoc) Initializes the editor part with a site and input. <p>
+        * Subclasses of <code>EditorPart</code> must implement this method.
+        * Within the implementation subclasses should verify that the input type is
+        * acceptable and then save the site and input. Here is sample code: </p>
+        * <pre> if (!(input instanceof IFileEditorInput)) throw new
+        * PartInitException("Invalid Input: Must be IFileEditorInput");
+        * setSite(site); setInput(editorInput); </pre>
+        */
+       public void init(IEditorSite site, IEditorInput input) {
+               Trace.trace(Trace.FINEST, "Opening browser: " + input);
+               if (input instanceof IFileEditorInput) {
+                       IFileEditorInput fei = (IFileEditorInput) input;
+                       IFile file = fei.getFile();
+                       URL url = null;
+                       try {
+                               if (file != null && file.exists())
+                                       url = file.getLocation().toFile().toURL();
+                       } catch (Exception e) {
+                               Trace.trace(Trace.SEVERE, "Error getting URL to file");
+                       }
+                       addResourceListener(file);
+                       input = new WebBrowserEditorInput(url,
+                                       WebBrowserEditorInput.SHOW_ALL
+                                                       | WebBrowserEditorInput.SAVE_URL);
+               }
+               if (input instanceof IWebBrowserEditorInput) {
+                       IWebBrowserEditorInput wbei = (IWebBrowserEditorInput) input;
+                       initialURL = null;
+                       if (wbei.getURL() != null)
+                               initialURL = wbei.getURL().toExternalForm();
+                       if (webBrowser != null) {
+                               webBrowser.setURL(initialURL);
+                               site.getWorkbenchWindow().getActivePage().bringToTop(this);
+                       }
+
+                       setPartName(wbei.getName());
+                       setTitleToolTip(wbei.getToolTipText());
+
+                       Image oldImage = image;
+                       ImageDescriptor id = wbei.getImageDescriptor();
+                       image = id.createImage();
+
+                       setTitleImage(image);
+                       if (oldImage != null && !oldImage.isDisposed())
+                               oldImage.dispose();
+               }
+               setSite(site);
+               setInput(input);
+       }
+
+       /*
+        * (non-Javadoc) Returns whether the contents of this editor have changed
+        * since the last save operation. <p> Subclasses must override this method
+        * to implement the open-save-close lifecycle for an editor. For greater
+        * details, see <code>IEditorPart</code> </p>
+        * 
+        * @see IEditorPart
+        */
+       public boolean isDirty() {
+               return false;
+       }
+
+       /*
+        * (non-Javadoc) Returns whether the "save as" operation is supported by
+        * this editor. <p> Subclasses must override this method to implement the
+        * open-save-close lifecycle for an editor. For greater details, see <code>IEditorPart</code>
+        * </p>
+        * 
+        * @see IEditorPart
+        */
+       public boolean isSaveAsAllowed() {
+               return false;
+       }
+
+       /**
+        * Returns true if this editor has a toolbar.
+        * 
+        * @return boolean
+        */
+       public boolean isToolbarVisible() {
+               IWebBrowserEditorInput input = getWebBrowserEditorInput();
+               if (input == null || input.isToolbarVisible())
+                       return true;
+               else
+                       return false;
+       }
+
+       /**
+        * Open the input in the internal Web browser.
+        */
+       public static void open(IWebBrowserEditorInput input) {
+               IWorkbenchWindow workbenchWindow = WebBrowserUIPlugin.getInstance()
+                               .getWorkbench().getActiveWorkbenchWindow();
+               IWorkbenchPage page = workbenchWindow.getActivePage();
+
+               try {
+                       IEditorReference[] editors = page.getEditorReferences();
+                       int size = editors.length;
+                       for (int i = 0; i < size; i++) {
+                               if (WEB_BROWSER_EDITOR_ID.equals(editors[i].getId())) {
+                                       IEditorPart editor = editors[i].getEditor(true);
+                                       if (editor != null && editor instanceof WebBrowserEditor) {
+                                               WebBrowserEditor webEditor = (WebBrowserEditor) editor;
+                                               if (input.canReplaceInput(webEditor
+                                                               .getWebBrowserEditorInput())) {
+                                                       editor.init(editor.getEditorSite(), input);
+                                                       return;
+                                               }
+                                       }
+                               }
+                       }
+
+                       page.openEditor(input, WebBrowserEditor.WEB_BROWSER_EDITOR_ID);
+               } catch (Exception e) {
+                       Trace.trace(Trace.SEVERE, "Error opening Web browser", e);
+               }
+       }
+
+       /**
+        * Asks this part to take focus within the workbench.
+        * <p>
+        * Clients should not call this method (the workbench calls this method at
+        * appropriate times).
+        * </p>
+        */
+       public void setFocus() {
+               if (webBrowser != null) {
+                       if (webBrowser.combo != null)
+                               webBrowser.combo.setFocus();
+                       else
+                               webBrowser.browser.setFocus();
+                       webBrowser.updateHistory();
+               }
+       }
+
+       /**
+        * Update the actions.
+        */
+       protected void updateActions() {
+               if (cutAction != null)
+                       cutAction.update();
+               if (copyAction != null)
+                       copyAction.update();
+               if (pasteAction != null)
+                       pasteAction.update();
+       }
+
+       /**
+        * Close the editor correctly.
+        */
+       protected void closeEditor() {
+               Display.getDefault().asyncExec(new Runnable() {
+                       public void run() {
+                               getEditorSite().getPage().closeEditor(WebBrowserEditor.this,
+                                               false);
+                       }
+               });
+       }
+
+       /**
+        * Adds a resource change listener to see if the file is deleted.
+        */
+       protected void addResourceListener(final IResource resource) {
+               if (resource == null)
+                       return;
+
+               resourceListener = new IResourceChangeListener() {
+                       public void resourceChanged(IResourceChangeEvent event) {
+                               try {
+                                       event.getDelta().accept(new IResourceDeltaVisitor() {
+                                               public boolean visit(IResourceDelta delta) {
+                                                       IResource res = delta.getResource();
+
+                                                       if (res == null || !res.equals(resource))
+                                                               return true;
+
+                                                       if (delta.getKind() != IResourceDelta.REMOVED)
+                                                               return true;
+
+                                                       Display.getDefault().asyncExec(new Runnable() {
+                                                               public void run() {
+                                                                       String title = WebBrowserUIPlugin
+                                                                                       .getResource("%dialogResourceDeletedTitle");
+                                                                       String message = WebBrowserUIPlugin
+                                                                                       .getResource(
+                                                                                                       "%dialogResourceDeletedMessage",
+                                                                                                       resource.getName());
+                                                                       String[] labels = new String[] {
+                                                                                       WebBrowserUIPlugin
+                                                                                                       .getResource("%dialogResourceDeletedIgnore"),
+                                                                                       IDialogConstants.CLOSE_LABEL };
+                                                                       MessageDialog dialog = new MessageDialog(
+                                                                                       getEditorSite().getShell(), title,
+                                                                                       null, message,
+                                                                                       MessageDialog.INFORMATION, labels,
+                                                                                       0);
+
+                                                                       if (dialog.open() != 0)
+                                                                               closeEditor();
+                                                               }
+                                                       });
+                                                       return false;
+                                               }
+                                       });
+                               } catch (Exception e) {
+                                       Trace.trace(Trace.SEVERE,
+                                                       "Error listening for resource deletion", e);
+                               }
+                       }
+               };
+               ResourcesPlugin.getWorkspace().addResourceChangeListener(
+                               resourceListener);
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/webbrowser/views/BrowserView.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/webbrowser/views/BrowserView.java
new file mode 100644 (file)
index 0000000..92face4
--- /dev/null
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package net.sourceforge.phpeclipse.webbrowser.views;
+
+import net.sourceforge.phpeclipse.webbrowser.internal.WebBrowser;
+import net.sourceforge.phpeclipse.webbrowser.internal.WebBrowserUtil;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.swt.browser.ProgressListener;
+import org.eclipse.swt.browser.StatusTextListener;
+import org.eclipse.swt.browser.TitleListener;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.part.IShowInTarget;
+import org.eclipse.ui.part.ShowInContext;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * <code>BrowserView</code> is a simple demonstration of the SWT Browser
+ * widget. It consists of a workbench view and tab folder where each tab in the
+ * folder allows the user to interact with a control.
+ * 
+ * @see ViewPart
+ */
+public class BrowserView extends ViewPart implements IShowInTarget {
+       public final static String ID_BROWSER = "net.sourceforge.phpeclipse.webbrowser.views";
+
+       WebBrowser fInstance = null;
+
+       String fUrl = null;
+
+       /**
+        * Create the example
+        * 
+        * @see ViewPart#createPartControl
+        */
+       public void createPartControl(Composite frame) {
+               try {
+                       if (WebBrowserUtil.isInternalBrowserOperational()) {
+                               fInstance = new WebBrowser(frame, true, true);
+                       }
+               } catch (Exception e) {
+                       fInstance = null;
+               }
+       }
+
+       /**
+        * Called when we must grab focus.
+        * 
+        * @see org.eclipse.ui.part.ViewPart#setFocus
+        */
+       public void setFocus() {
+               if (fInstance != null) {
+                       fInstance.setFocus();
+               }
+       }
+
+       /**
+        * Called when the View is to be disposed
+        */
+       public void dispose() {
+               if (fInstance != null) {
+                       fInstance.dispose();
+                       fInstance = null;
+               }
+               super.dispose();
+       }
+
+       public void setUrl(final String url) {
+               if (fInstance != null) {
+                       fUrl = url;
+                       fInstance.setURL(url);
+                       // try {
+                       // ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+                       // public void run(IProgressMonitor monitor) throws CoreException {
+                       // instance.setURL(url);
+                       // }
+                       // }, null);
+                       // } catch (CoreException e) {
+                       // // TODO Auto-generated catch block
+                       // e.printStackTrace();
+                       // }
+               }
+       }
+
+       public void refresh() {
+               if (fInstance != null) {
+                       fInstance.refresh();
+                       // try {
+                       // ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
+                       // public void run(IProgressMonitor monitor) throws CoreException {
+                       // instance.refresh();
+                       // }
+                       // }, null);
+                       // } catch (CoreException e) {
+                       // // TODO Auto-generated catch block
+                       // e.printStackTrace();
+                       // }
+               }
+       }
+
+       public void refresh(String url) {
+               if (fInstance != null) {
+                       if (fUrl == null || !fUrl.equals(url)) {
+                               setUrl(url);
+                       } else {
+                               refresh();
+                       }
+               }
+       }
+
+       public void addProgressListener(ProgressListener listener) {
+               if (fInstance != null) {
+                       fInstance.addProgressListener(listener);
+               }
+       }
+
+       public void addStatusTextListener(StatusTextListener listener) {
+               if (fInstance != null) {
+                       fInstance.addStatusTextListener(listener);
+               }
+       }
+
+       public void addTitleListener(TitleListener listener) {
+               if (fInstance != null) {
+                       fInstance.addTitleListener(listener);
+               }
+       }
+
+       public boolean show(ShowInContext context) {
+               if (context instanceof ShowInContextBrowser) {
+                       ShowInContextBrowser contextBrowser = (ShowInContextBrowser) context;
+                       String localhostURL = contextBrowser.getLocalhostUrl();
+                       if (localhostURL != null) {
+                               setUrl(localhostURL);
+                               return true;
+                       }
+               }
+               if (context.getInput() instanceof IFile) {
+                       IFile file = (IFile) context.getInput();
+                       String localhostURL;
+                       localhostURL = "file:///" + file.getLocation().toString();
+                       setUrl(localhostURL);
+                       return true;
+               }
+               return false;
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/wizards/NewProjectCreationWizard.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/wizards/NewProjectCreationWizard.java
new file mode 100644 (file)
index 0000000..0601e03
--- /dev/null
@@ -0,0 +1,119 @@
+package net.sourceforge.phpeclipse.wizards;
+
+import java.lang.reflect.InvocationTargetException;
+
+import net.sourceforge.phpdt.core.JavaCore;
+import net.sourceforge.phpdt.ui.actions.OpenPHPPerspectiveAction;
+import net.sourceforge.phpeclipse.PHPeclipsePlugin;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation;
+import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
+import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
+import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
+
+public class NewProjectCreationWizard extends BasicNewResourceWizard implements
+               INewWizard, IExecutableExtension {
+       protected WizardNewProjectCreationPage projectPage;
+
+       protected IConfigurationElement configurationElement;
+
+       protected IProject newProject;
+
+       public NewProjectCreationWizard() {
+               setWindowTitle(PHPWizardMessages
+                               .getString("NewProjectCreationWizard.windowTitle"));
+       }
+
+       public boolean performFinish() {
+               IRunnableWithProgress projectCreationOperation = new WorkspaceModifyDelegatingOperation(
+                               getProjectCreationRunnable());
+
+               try {
+                       getContainer().run(false, true, projectCreationOperation);
+               } catch (Exception e) {
+                       PHPeclipsePlugin.log(e);
+                       return false;
+               }
+
+               BasicNewProjectResourceWizard.updatePerspective(configurationElement);
+               selectAndReveal(newProject);
+               // open the PHP perspective
+               new OpenPHPPerspectiveAction().run();
+               return true;
+       }
+
+       protected IRunnableWithProgress getProjectCreationRunnable() {
+               return new IRunnableWithProgress() {
+                       public void run(IProgressMonitor monitor)
+                                       throws InvocationTargetException, InterruptedException {
+                               int remainingWorkUnits = 10;
+                               monitor
+                                               .beginTask(
+                                                               PHPWizardMessages
+                                                                               .getString("NewProjectCreationWizard.projectCreationMessage"),
+                                                               remainingWorkUnits);
+
+                               IWorkspace workspace = PHPeclipsePlugin.getWorkspace();
+                               newProject = projectPage.getProjectHandle();
+
+                               IProjectDescription description = workspace
+                                               .newProjectDescription(newProject.getName());
+                               IPath path = Platform.getLocation();
+                               IPath customPath = projectPage.getLocationPath();
+                               if (!path.equals(customPath)) {
+                                       path = customPath;
+                                       description.setLocation(path);
+                               }
+
+                               try {
+                                       if (!newProject.exists()) {
+                                               newProject.create(description, new SubProgressMonitor(
+                                                               monitor, 1));
+                                               remainingWorkUnits--;
+                                       }
+                                       if (!newProject.isOpen()) {
+                                               newProject.open(new SubProgressMonitor(monitor, 1));
+                                               remainingWorkUnits--;
+                                       }
+                                       JavaCore.addPHPNature(newProject, new SubProgressMonitor(
+                                                       monitor, remainingWorkUnits));
+                               } catch (CoreException e) {
+                                       throw new InvocationTargetException(e);
+                               } finally {
+                                       monitor.done();
+                               }
+                       }
+               };
+       }
+
+       public void addPages() {
+               super.addPages();
+
+               projectPage = new WizardNewProjectCreationPage(PHPWizardMessages
+                               .getString("WizardNewProjectCreationPage.pageName"));
+               projectPage.setTitle(PHPWizardMessages
+                               .getString("WizardNewProjectCreationPage.pageTitle"));
+               projectPage.setDescription(PHPWizardMessages
+                               .getString("WizardNewProjectCreationPage.pageDescription"));
+
+               addPage(projectPage);
+       }
+
+       public void setInitializationData(IConfigurationElement config,
+                       String propertyName, Object data) throws CoreException {
+               configurationElement = config;
+       }
+
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/launching/PHPLaunchConfigurationDelegate.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/launching/PHPLaunchConfigurationDelegate.java
new file mode 100644 (file)
index 0000000..5880ca0
--- /dev/null
@@ -0,0 +1,155 @@
+/**********************************************************************
+ Copyright (c) 2000, 2002 IBM Corp. and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Common Public License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/legal/cpl-v10.html
+ Contributors:
+ IBM Corporation - Initial implementation
+ Vicente Fernando - www.alfersoft.com.ar
+ **********************************************************************/
+package net.sourceforge.phpeclipse.xdebug.php.launching;
+
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import net.sourceforge.phpeclipse.xdebug.core.IXDebugPreferenceConstants;
+import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugTarget;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.ILaunchConfigurationDelegate;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.LaunchConfigurationDelegate;
+
+public class PHPLaunchConfigurationDelegate extends LaunchConfigurationDelegate {
+
+       /**
+        * @see ILaunchConfigurationDelegate#launch(ILaunchConfiguration, String,
+        *      ILaunch, IProgressMonitor)
+        */
+       public void launch(ILaunchConfiguration configuration, String mode,
+                       ILaunch launch, IProgressMonitor monitor) throws CoreException {
+               List commandList = new ArrayList();
+
+               String phpInterpreter = configuration.getAttribute(
+                               IXDebugConstants.ATTR_PHP_INTERPRETER, (String) null);
+               boolean useDefaultInterpreter = configuration.getAttribute(
+                               IXDebugConstants.ATTR_PHP_DEFAULT_INTERPRETER, true);
+
+               if (useDefaultInterpreter)
+                       phpInterpreter = XDebugCorePlugin
+                                       .getDefault()
+                                       .getPreferenceStore()
+                                       .getString(
+                                                       IXDebugPreferenceConstants.PHP_INTERPRETER_PREFERENCE);
+
+               File exe = new File(phpInterpreter);
+               // Just to get sure that the interpreter exists
+               if (!exe.exists()) {
+                       abort(
+                                       MessageFormat
+                                                       .format(
+                                                                       "Specified PHP executable {0} does not exist. Check value of PHP-Interpreter.",
+                                                                       new String[] { phpInterpreter }), null);
+               }
+               commandList.add(phpInterpreter);
+
+               // Project name
+               String projectName = configuration.getAttribute(
+                               IXDebugConstants.ATTR_PHP_PROJECT, (String) null);
+               IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(
+                               projectName);
+               // Just to get sure that the project exists
+               if (project == null) {
+                       abort("Project does not exist.", null);
+               }
+               String fileName = configuration.getAttribute(
+                               IXDebugConstants.ATTR_PHP_FILE, (String) null);
+
+               IFile file = project.getFile(fileName);
+               // Just to get sure that the script exists
+               if (!file.exists()) {
+                       abort(MessageFormat.format("PHP-Script {0} does not exist.",
+                                       new String[] { file.getFullPath().toString() }), null);
+               }
+
+               commandList.add(file.getLocation().toOSString());
+
+               // Get de Debugport form the Launchconfiguration or from the preferences
+               int debugPort = configuration.getAttribute(
+                               IXDebugConstants.ATTR_PHP_DEBUGPORT, -1);
+               boolean useDefaultPort = configuration.getAttribute(
+                               IXDebugConstants.ATTR_PHP_DEFAULT_DEBUGPORT, true);
+               if (useDefaultPort)
+                       debugPort = XDebugCorePlugin.getDefault().getPreferenceStore()
+                                       .getInt(IXDebugPreferenceConstants.DEBUGPORT_PREFERENCE);
+               if (debugPort < 1024)
+                       debugPort = IXDebugPreferenceConstants.DEFAULT_DEBUGPORT;
+
+               String[] envp = DebugPlugin.getDefault().getLaunchManager()
+                               .getEnvironment(configuration);
+               // appends the environment to the native environment
+               if (envp == null) {
+                       Map stringVars = DebugPlugin.getDefault().getLaunchManager()
+                                       .getNativeEnvironment();
+                       int idx = 0;
+                       envp = new String[stringVars.size()];
+                       for (Iterator i = stringVars.keySet().iterator(); i.hasNext();) {
+                               String key = (String) i.next();
+                               String value = (String) stringVars.get(key);
+                               envp[idx++] = key + "=" + value;
+                       }
+               }
+               if (mode.equals(ILaunchManager.DEBUG_MODE)) {
+                       String[] env = new String[envp.length + 1];
+                       for (int i = 0; i < envp.length; i++)
+                               env[i + 1] = envp[i];
+                       env[0] = "XDEBUG_CONFIG=idekey=xdebug_test remote_enable=1";
+                       envp = env;
+               }
+
+               String[] commandLine = (String[]) commandList
+                               .toArray(new String[commandList.size()]);
+               Process process = DebugPlugin.exec(commandLine, null, envp);
+               IProcess p = DebugPlugin.newProcess(launch, process, phpInterpreter);
+               if (mode.equals(ILaunchManager.DEBUG_MODE)) {
+                       IDebugTarget target = new XDebugTarget(launch, p, debugPort);
+                       launch.addDebugTarget(target);
+               }
+       }
+
+       /**
+        * Throws an exception with a new status containing the given message and
+        * optional exception.
+        * 
+        * @param message
+        *            error message
+        * @param e
+        *            underlying exception
+        * @throws CoreException
+        */
+       private void abort(String message, Throwable e) throws CoreException {
+               // TODO: the plug-in code should be the example plug-in, not Perl debug
+               // model id
+               throw new CoreException(new Status(IStatus.ERROR,
+                               IXDebugConstants.ID_PHP_DEBUG_MODEL, 0, message, e));
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/launching/PHPSourceLookupParticipant.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/launching/PHPSourceLookupParticipant.java
new file mode 100644 (file)
index 0000000..59cdae3
--- /dev/null
@@ -0,0 +1,17 @@
+package net.sourceforge.phpeclipse.xdebug.php.launching;
+
+import net.sourceforge.phpeclipse.xdebug.php.model.XDebugStackFrame;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupParticipant;
+
+public class PHPSourceLookupParticipant extends AbstractSourceLookupParticipant {
+
+       public String getSourceName(Object object) throws CoreException {
+               if (object instanceof XDebugStackFrame) {
+                       return ((XDebugStackFrame) object).getSourceName();
+               }
+               return null;
+       }
+
+}
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/model/XDebugTarget.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xdebug/php/model/XDebugTarget.java
new file mode 100644 (file)
index 0000000..04099c4
--- /dev/null
@@ -0,0 +1,638 @@
+/**
+ * 
+ */
+package net.sourceforge.phpeclipse.xdebug.php.model;
+
+import net.sourceforge.phpeclipse.xdebug.core.Base64;
+import net.sourceforge.phpeclipse.xdebug.core.DebugConnection;
+import net.sourceforge.phpeclipse.xdebug.core.PHPDebugUtils;
+import net.sourceforge.phpeclipse.xdebug.core.XDebugCorePlugin;
+import net.sourceforge.phpeclipse.xdebug.core.DebugConnection.DebugResponse;
+import net.sourceforge.phpeclipse.xdebug.php.launching.IXDebugConstants;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.ILineBreakpoint;
+import org.eclipse.debug.core.model.IMemoryBlock;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.debug.core.model.IValue;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * @author Christian
+ * 
+ */
+public class XDebugTarget extends XDebugElement implements IDebugTarget,
+               IDebugEventSetListener {
+       // associated system process (VM)
+       private IProcess fProcess;
+
+       // containing launch object
+       private ILaunch fLaunch;
+
+       // debugPort
+       private int fDebugPort;
+
+       // program name
+       // private String fName;
+
+       // suspend state
+       private boolean fSuspended = true;
+
+       // terminated state
+       private boolean fTerminated = false;
+
+       // threads
+       private XDebugThread fThread;
+
+       private IThread[] fThreads;
+
+       // event dispatch job
+       // private EventDispatchJob fEventDispatch;
+
+       private DebugConnection fDebugConnection;
+
+       // private DebugResponse lastResponse;
+
+       /**
+        * Constructs a new debug target in the given launch for the associated PDA
+        * VM process.
+        * 
+        * @param launch
+        *            containing launch
+        * @param debugPort
+        *            port to read events from
+        * @exception CoreException
+        *                if unable to connect to host
+        */
+       public XDebugTarget(ILaunch launch, IProcess process, int debugPort)
+                       throws CoreException {
+               super(null);
+               fLaunch = launch;
+               fProcess = process;
+               fTarget = this;
+               fDebugConnection = new DebugConnection(this, debugPort);
+               fThread = new XDebugThread(this);
+               fThreads = new IThread[] { fThread };
+               DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(
+                               this);
+               DebugPlugin.getDefault().addDebugEventListener(this);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IDebugTarget#getProcess()
+        */
+       public IProcess getProcess() {
+               return fProcess;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IDebugTarget#getThreads()
+        */
+       public IThread[] getThreads() throws DebugException {
+               return fThreads;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IDebugTarget#hasThreads()
+        */
+       public boolean hasThreads() throws DebugException {
+               return (fThreads.length > 0);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IDebugTarget#getName()
+        */
+       public String getName() throws DebugException {
+               return "PHP XDebug Client at localhost:" + fDebugPort;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IDebugTarget#supportsBreakpoint(org.eclipse.debug.core.model.IBreakpoint)
+        */
+       public boolean supportsBreakpoint(IBreakpoint breakpoint) {
+               if (breakpoint.getModelIdentifier().equals(
+                               IXDebugConstants.ID_PHP_DEBUG_MODEL)) {
+                       return true;
+               }
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget()
+        */
+       public IDebugTarget getDebugTarget() {
+               return this;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IDebugElement#getLaunch()
+        */
+       public ILaunch getLaunch() {
+               return fLaunch;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.ITerminate#canTerminate()
+        */
+       public boolean canTerminate() {
+               return getProcess().canTerminate();
+               // return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.ITerminate#isTerminated()
+        */
+       public boolean isTerminated() {
+               // return getProcess().isTerminated();
+               return fTerminated;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.ITerminate#terminate()
+        */
+       public void terminate() throws DebugException {
+               fDebugConnection.sendRequest("stop");
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.ISuspendResume#canResume()
+        */
+       public boolean canResume() {
+               return !isTerminated() && isSuspended();
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.ISuspendResume#canSuspend()
+        */
+       public boolean canSuspend() {
+               return !isTerminated() && !isSuspended();
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
+        */
+       public boolean isSuspended() {
+               return fSuspended;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.ISuspendResume#resume()
+        */
+       public void resume() throws DebugException {
+               fDebugConnection.sendRequest("run");
+       }
+
+       /**
+        * Notification the target has resumed for the given reason
+        * 
+        * @param detail
+        *            reason for the resume
+        */
+       private void resumed(int detail) {
+               fSuspended = false;
+               fThread.fireResumeEvent(detail);
+       }
+
+       /**
+        * Notification the target has suspended for the given reason
+        * 
+        * @param detail
+        *            reason for the suspend
+        */
+       public void suspended(int detail) {
+               fSuspended = true;
+               fThread.fireSuspendEvent(detail);
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.ISuspendResume#suspend()
+        */
+       public void suspend() throws DebugException {
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint)
+        */
+       public void breakpointAdded(IBreakpoint breakpoint) {
+
+               if (supportsBreakpoint(breakpoint)) {
+                       try {
+                               if (breakpoint.isEnabled()) {
+                                       IMarker marker = breakpoint.getMarker();
+                                       if (marker != null) {
+                                               try {
+                                                       String fileName = PHPDebugUtils.escapeString(marker
+                                                                       .getResource().getLocation().toString());
+                                                       String arg = "-t line -f file:///"
+                                                                       + fileName
+                                                                       + " -n "
+                                                                       + ((ILineBreakpoint) breakpoint)
+                                                                                       .getLineNumber();
+                                                       int id = fDebugConnection.sendRequest(
+                                                                       "breakpoint_set", arg);
+                                                       // set the marker Attribute to make later
+                                                       // idetification possible
+                                                       // TODO: make sure that attribute is set before
+                                                       // response from debugger is beeing prosessed
+                                                       marker.setAttribute(
+                                                                       XDebugLineBreakpoint.BREAKPOINT_ID, id);
+
+                                               } catch (CoreException e) {
+                                               }
+                                       }
+                               }
+                       } catch (CoreException e) {
+
+                       }
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint,
+        *      org.eclipse.core.resources.IMarkerDelta)
+        */
+       public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) {
+               if (supportsBreakpoint(breakpoint)) {
+                       try {
+                               int id = ((XDebugLineBreakpoint) breakpoint).getID();
+                               if (id > 0)
+                                       fDebugConnection.sendRequest("breakpoint_remove", "-d "
+                                                       + id);
+                       } catch (CoreException e) {
+                       }
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint,
+        *      org.eclipse.core.resources.IMarkerDelta)
+        */
+       public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) {
+               // if (supportsBreakpoint(breakpoint)) {
+               // try {
+               // if (breakpoint.isEnabled()) {
+               // breakpointAdded(breakpoint);
+               // } else {
+               // breakpointRemoved(breakpoint, null);
+               // }
+               // } catch (CoreException e) {
+               // }
+               // }
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IDisconnect#canDisconnect()
+        */
+       public boolean canDisconnect() {
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IDisconnect#disconnect()
+        */
+       public void disconnect() throws DebugException {
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IDisconnect#isDisconnected()
+        */
+       public boolean isDisconnected() {
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#supportsStorageRetrieval()
+        */
+       public boolean supportsStorageRetrieval() {
+               return false;
+       }
+
+       /*
+        * (non-Javadoc)
+        * 
+        * @see org.eclipse.debug.core.model.IMemoryBlockRetrieval#getMemoryBlock(long,
+        *      long)
+        */
+       public IMemoryBlock getMemoryBlock(long startAddress, long length)
+                       throws DebugException {
+               return null;
+       }
+
+       /**
+        * Notification we have connected to the PHP debugger and it has started.
+        * Resume the the debugger.
+        */
+       public void started() {
+
+               fThread.setBreakpoints(null);
+               fThread.setStepping(false);
+
+               installDeferredBreakpoints();
+               try {
+                       resume();
+                       // step();
+               } catch (DebugException e) {
+               }
+       }
+
+       /**
+        * Install breakpoints that are already registered with the breakpoint
+        * manager.
+        */
+       private void installDeferredBreakpoints() {
+               IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints();
+               for (int i = 0; i < breakpoints.length; i++) {
+                       breakpointAdded(breakpoints[i]);
+               }
+       }
+
+       /**
+        * Called when this debug target terminates.
+        */
+       public void terminated() {
+               fTerminated = true;
+               fSuspended = false;
+               XDebugCorePlugin.getBreakpointManager().removeBreakpointListener(this);
+               fireTerminateEvent();
+               DebugPlugin.getDefault().removeDebugEventListener(this);
+               fThread.removeEventListeners();
+       }
+
+       /**
+        * Returns the current stack frames in the target.
+        * 
+        * @return the current stack frames in the target
+        * @throws DebugException
+        *             if unable to perform the request
+        */
+       protected IStackFrame[] getStackFrames() throws DebugException {
+               int id = fDebugConnection.sendRequest("stack_get");
+               DebugResponse lastResponse = fDebugConnection.waitforTransID(id);
+               if (lastResponse.isError())
+                       return new IStackFrame[0];
+               Node response = lastResponse.getParentNode();
+               NodeList frames = response.getChildNodes();
+               IStackFrame[] theFrames = new IStackFrame[frames.getLength()];
+               for (int i = 0; i < frames.getLength(); i++) {
+                       Node stackNode = frames.item(i);
+                       theFrames[i] = new XDebugStackFrame(fThread, stackNode, i);
+               }
+               return theFrames;
+       }
+
+       /**
+        * Single step the interpreter.
+        * 
+        * @throws DebugException
+        *             if the request fails
+        */
+       protected void step_over() throws DebugException {
+               fThread.setStepping(true);
+               resumed(DebugEvent.STEP_OVER);
+               fDebugConnection.sendRequest("step_over");
+       }
+
+       /**
+        * Single step the interpreter.
+        * 
+        * @throws DebugException
+        *             if the request fails
+        */
+       protected void step_into() throws DebugException {
+               fThread.setStepping(true);
+               resumed(DebugEvent.STEP_INTO);
+               fDebugConnection.sendRequest("step_into");
+       }
+
+       /**
+        * Single step the interpreter.
+        * 
+        * @throws DebugException
+        *             if the request fails
+        */
+       protected void step_out() throws DebugException {
+               fThread.setStepping(true);
+               resumed(DebugEvent.STEP_RETURN);
+               fDebugConnection.sendRequest("step_out");
+       }
+
+       /**
+        * Returns the current value of the given variable.
+        * 
+        * @param variable
+        * @return variable value
+        * @throws DebugException
+        *             if the request fails
+        */
+       protected IValue getVariableValue(XDebugVariable variable)
+                       throws DebugException {
+               // synchronized (fDebugSocket) {
+               // fDebugConnection.sendRequest("var","" +
+               // variable.getStackFrame().getIdentifier() + " " + variable.getName());
+               // try {
+               // String value = fDebugReader.readLine();
+               // //return new XDebugValue(this, value);
+               //                              
+               // } catch (IOException e) {
+               // abort(MessageFormat.format("Unable to retrieve value for variable
+               // {0}", new String[]{variable.getName()}), e);
+               // }
+               // }
+               return null;
+       }
+
+       /**
+        * Returns the values on the data stack (top down)
+        * 
+        * @return the values on the data stack (top down)
+        */
+       public IValue[] getDataStack() throws DebugException {
+               // synchronized (fDebugSocket) {
+               // fDebugConnection.sendRequest ("data");
+               // try {
+               // String valueString = fDebugReader.readLine();
+               // if (valueString != null && valueString.length() > 0) {
+               // String[] values = valueString.split("\\|");
+               // IValue[] theValues = new IValue[values.length];
+               // for (int i = 0; i < values.length; i++) {
+               // String value = values[values.length - i - 1];
+               // // theValues[i] = new XDebugValue(this, value);
+               // }
+               // return theValues;
+               // }
+               // } catch (IOException e) {
+               // abort("Unable to retrieve data stack", e);
+               // }
+               // }
+               return new IValue[0];
+       }
+
+       public boolean setVarValue(String name, String value) {
+               int id = -1;
+               String str = Base64.encodeBytes(value.getBytes());
+               int len = str.length();
+
+               try {
+                       id = fDebugConnection.sendRequest("property_set", "-n " + name
+                                       + " -l " + len + " -- " + str);
+               } catch (DebugException e) {
+                       // TODO Auto-generated catch block
+                       e.printStackTrace();
+               }
+               DebugResponse dr = getResponse(id);
+               if ((dr.getAttributeValue("success")).equals("1"))
+                       return true;
+
+               return false;
+       }
+
+       public DebugResponse getResponse(int id) {
+               return fDebugConnection.waitforTransID(id);
+       }
+
+       /**
+        * Sends a request to the Debugengine and waits for an OK.
+        * 
+        * @param command
+        *            debug command
+        * @throws DebugException
+        *             if the request fails
+        */
+
+       public int sendRequest(String command) throws DebugException {
+               return fDebugConnection.sendRequest(command, "");
+       }
+
+       /**
+        * Sends a request to the Debugengine and waits for an OK.
+        * 
+        * @param command
+        *            debug command
+        * @arguments arguments for the command
+        * @throws DebugException
+        *             if the request fails
+        */
+
+       public int sendRequest(String command, String arguments)
+                       throws DebugException {
+               return fDebugConnection.sendRequest(command, arguments);
+       }
+
+       /**
+        * Notification a breakpoint was encountered. Determine which breakpoint was
+        * hit and fire a suspend event.
+        * 
+        * @param event
+        *            debug event
+        */
+       public void breakpointHit(Node node) {
+               // determine which breakpoint was hit, and set the thread's breakpoint
+               Node child = node.getFirstChild();
+               if (child.getNodeName().equals("stack")) {
+                       int lineNumber = Integer.parseInt(PHPDebugUtils.getAttributeValue(
+                                       child, "lineno"));
+                       String filename = PHPDebugUtils
+                                       .getAttributeValue(child, "filename").substring(8); // remove
+                                                                                                                                               // file:///
+                       IBreakpoint[] breakpoints = XDebugCorePlugin.getBreakpoints();
+                       for (int i = 0; i < breakpoints.length; i++) {
+                               IBreakpoint breakpoint = breakpoints[i];
+                               if (supportsBreakpoint(breakpoint)) {
+                                       if (breakpoint instanceof ILineBreakpoint) {
+                                               ILineBreakpoint lineBreakpoint = (ILineBreakpoint) breakpoint;
+                                               try {
+                                                       if (breakpoint.isEnabled()) {
+                                                               IMarker marker = breakpoint.getMarker();
+                                                               if (marker != null) {
+
+                                                                       String name = marker.getResource()
+                                                                                       .getLocation().toOSString();
+                                                                       if (name.equals(PHPDebugUtils
+                                                                                       .unescapeString(filename))
+                                                                                       && (lineBreakpoint.getLineNumber() == lineNumber)) {
+                                                                               fThread
+                                                                                               .setBreakpoints(new IBreakpoint[] { breakpoint });
+                                                                               break;
+                                                                       }
+                                                               }
+
+                                                       }
+                                               } catch (CoreException e) {
+                                               }
+                                       }
+                               }
+                       }
+               }
+               suspended(DebugEvent.BREAKPOINT);
+       }
+
+       public void handleDebugEvents(DebugEvent[] events) {
+               for (int i = 0; i < events.length; i++) {
+                       DebugEvent event = events[i];
+                       if ((event.getKind() == DebugEvent.CREATE)
+                                       && (event.getSource() instanceof XDebugElement)) {
+                               if (((XDebugElement) event.getSource()).getModelIdentifier() == IXDebugConstants.ID_PHP_DEBUG_MODEL) {
+                                       if (event.getKind() == DebugEvent.CREATE)
+                                               started();
+                               }
+                       }
+               }
+
+       }
+}
\ No newline at end of file
diff --git a/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xml/core/internal/model/XMLDocument.java b/net.sourceforge.phpeclipse.32.compatibility/src/net/sourceforge/phpeclipse/xml/core/internal/model/XMLDocument.java
new file mode 100644 (file)
index 0000000..c0b5680
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2004 Christopher Lenz and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     Christopher Lenz - initial API
+ * 
+ * $Id: XMLDocument.java,v 1.2 2006-10-21 23:13:43 pombredanne Exp $
+ */
+
+package net.sourceforge.phpeclipse.xml.core.internal.model;
+
+import net.sourceforge.phpeclipse.core.model.SourceReference;
+import net.sourceforge.phpeclipse.xml.core.internal.parser.XMLParser;
+import net.sourceforge.phpeclipse.xml.core.model.IXMLDocument;
+import net.sourceforge.phpeclipse.xml.core.model.IXMLElement;
+import net.sourceforge.phpeclipse.xml.core.parser.IProblemCollector;
+import net.sourceforge.phpeclipse.xml.core.parser.IXMLParser;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+
+/**
+ * 
+ */
+public class XMLDocument extends SourceReference implements IXMLDocument,
+               IDocumentListener {
+       // Instance Variables ------------------------------------------------------
+
+       private IXMLElement root;
+
+       private String systemId;
+
+       private Object dirtyLock = new Object();
+
+       private boolean dirty = true;
+
+       // Constructors ------------------------------------------------------------
+
+       public XMLDocument(IDocument document, String systemId) {
+               super(document, 0, document.getLength());
+               this.systemId = systemId;
+       }
+
+       // IXMLDocument Implementation ---------------------------------------------
+
+       /*
+        * @see IXMLDocument#getRoot()
+        */
+       public IXMLElement getRoot() {
+               return root;
+       }
+
+       /*
+        * @see net.sourceforge.phpeclipse.xml.core.model.IXMLDocument#getSystemId()
+        */
+       public String getSystemId() {
+               return systemId;
+       }
+
+       /*
+        * @see IStyleSheet#reconcile(IProblemCollector)
+        */
+       public void reconcile(IProblemCollector problemCollector, IFile file) {
+               synchronized (dirtyLock) {
+                       if (!dirty) {
+                               return;
+                       }
+                       dirty = false;
+               }
+
+               synchronized (this) {
+                       boolean doParse = false;
+                       root = null;
+                       if (file != null) {
+                               String filename = file.getLocation().toString();
+                               int len = filename.length();
+                               if (len >= 4) {
+                                       if ((filename.charAt(len - 1) != 'l' && filename
+                                                       .charAt(len - 1) != 'L')
+                                                       || (filename.charAt(len - 2) != 'p' && filename
+                                                                       .charAt(len - 2) != 'P')
+                                                       || (filename.charAt(len - 3) != 't' && filename
+                                                                       .charAt(len - 3) != 'T')
+                                                       || (filename.charAt(len - 4) != '.')) {
+                                               if ((filename.charAt(len - 1) != 'm' && filename
+                                                               .charAt(len - 1) != 'M')
+                                                               || (filename.charAt(len - 2) != 't' && filename
+                                                                               .charAt(len - 2) != 'T')
+                                                               || (filename.charAt(len - 3) != 'h' && filename
+                                                                               .charAt(len - 3) != 'H')
+                                                               || (filename.charAt(len - 4) != '.')) {
+                                                       if (len >= 5) {
+                                                               if ((filename.charAt(len - 1) != 'l' && filename
+                                                                               .charAt(len - 1) != 'L')
+                                                                               || (filename.charAt(len - 2) != 'm' && filename
+                                                                                               .charAt(len - 2) != 'M')
+                                                                               || (filename.charAt(len - 3) != 't' && filename
+                                                                                               .charAt(len - 3) != 'T')
+                                                                               || (filename.charAt(len - 4) != 'h' && filename
+                                                                                               .charAt(len - 4) != 'H')
+                                                                               || (filename.charAt(len - 5) != '.')) {
+                                                                       doParse = true;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               } else {
+                                       doParse = true;
+                               }
+                       }
+                       if (doParse) {
+                               IXMLParser parser = new XMLParser();
+                               parser.setProblemCollector(problemCollector);
+                               parser.setSource(getDocument());
+                               parser.setSystemId(systemId);
+                               IXMLDocument model = parser.parse();
+                               if (model != null) {
+                                       root = model.getRoot();
+                               }
+                       }
+               }
+       }
+
+       // IDocumentListener Implementation ----------------------------------------
+
+       /*
+        * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent)
+        */
+       public void documentAboutToBeChanged(DocumentEvent event) {
+               // do nothing
+       }
+
+       /*
+        * @see IDocumentListener#documentChanged(DocumentEvent)
+        */
+       public void documentChanged(DocumentEvent event) {
+               synchronized (dirtyLock) {
+                       dirty = true;
+               }
+       }
+
+       // Public Methods ----------------------------------------------------------
+
+       /**
+        * Sets the root element.
+        * 
+        * @param root
+        *            the root element to set
+        */
+       public void setRoot(IXMLElement root) {
+               this.root = root;
+       }
+
+}
\ No newline at end of file