updating to eclipse 3.0 m6 (v_396)
diff --git a/org.eclipse.jdt.core/.classpath b/org.eclipse.jdt.core/.classpath
index 31497de..ca033a4 100644
--- a/org.eclipse.jdt.core/.classpath
+++ b/org.eclipse.jdt.core/.classpath
@@ -1,18 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-    <classpathentry kind="src" path="antadapter"/>
-    <classpathentry kind="src" path="batch"/>
-    <classpathentry kind="src" path="codeassist"/>
-    <classpathentry kind="src" path="compiler"/>
-    <classpathentry kind="src" path="dom"/>
-    <classpathentry kind="src" path="eval"/>
-    <classpathentry kind="src" path="formatter"/>
-    <classpathentry kind="src" path="model"/>
-    <classpathentry kind="src" path="search"/>
-    <classpathentry kind="src" path="/org.apache.xerces"/>
-    <classpathentry kind="src" path="/org.eclipse.core.resources"/>
-    <classpathentry kind="src" path="/org.eclipse.core.runtime"/>
-    <classpathentry kind="src" path="/org.apache.ant"/>
-    <classpathentry kind="output" path="bin"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry output="antbin" kind="src" path="antadapter"/>
+	<classpathentry kind="src" path="batch"/>
+	<classpathentry kind="src" path="codeassist"/>
+	<classpathentry kind="src" path="compiler"/>
+	<classpathentry kind="src" path="dom"/>
+	<classpathentry kind="src" path="eval"/>
+	<classpathentry kind="src" path="formatter"/>
+	<classpathentry kind="src" path="model"/>
+	<classpathentry kind="src" path="search"/>
+	<classpathentry kind="src" path="/org.eclipse.core.resources"/>
+	<classpathentry kind="src" path="/org.eclipse.text"/>
+	<classpathentry kind="src" path="/org.eclipse.core.runtime"/>
+	<classpathentry kind="src" path="/org.apache.ant"/>
+	<classpathentry kind="src" path="/org.eclipse.core.runtime.compatibility"/>
+	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/org.eclipse.jdt.core/.options b/org.eclipse.jdt.core/.options
index 1f8c116..5ceebe9 100644
--- a/org.eclipse.jdt.core/.options
+++ b/org.eclipse.jdt.core/.options
@@ -1,6 +1,9 @@
 # Turn on debug tracing for org.eclipse.jdt.core plugin

 org.eclipse.jdt.core/debug=true

 

+# Reports buffer manager activity

+org.eclipse.jdt.core/debug/buffermanager=false

+

 # Reports incremental builder activity : nature of build, built state reading, indictment process

 org.eclipse.jdt.core/debug/builder=false

 

@@ -34,8 +37,5 @@
 # Reports open on selection activity : recovered unit, inferred selection

 org.eclipse.jdt.core/debug/selection=false

 

-# Reports shared working copy use

-org.eclipse.jdt.core/debug/sharedworkingcopy=false

-

 # Reports access to zip and jar files through the Java model

 org.eclipse.jdt.core/debug/zipaccess=false
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/.project b/org.eclipse.jdt.core/.project
index 8778f20..d1eabac 100644
--- a/org.eclipse.jdt.core/.project
+++ b/org.eclipse.jdt.core/.project
@@ -4,9 +4,10 @@
 	<comment></comment>
 	<projects>
 		<project>org.apache.ant</project>
-		<project>org.apache.xerces</project>
 		<project>org.eclipse.core.resources</project>
 		<project>org.eclipse.core.runtime</project>
+		<project>org.eclipse.core.runtime.compatibility</project>
+		<project>org.eclipse.text</project>
 	</projects>
 	<buildSpec>
 		<buildCommand>
diff --git a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/CheckDebugAttributes.java b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/CheckDebugAttributes.java
new file mode 100644
index 0000000..c294d11
--- /dev/null
+++ b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/CheckDebugAttributes.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * 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 Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.eclipse.jdt.core.util.IClassFileReader;
+import org.eclipse.jdt.core.util.ICodeAttribute;
+import org.eclipse.jdt.core.util.IMethodInfo;
+import org.eclipse.jdt.internal.antadapter.AntAdapterMessages;
+
+public class CheckDebugAttributes extends Task {
+
+	private String file;
+	private String property;
+	
+	public void execute() throws BuildException {
+		if (this.file == null) {
+			throw new BuildException(AntAdapterMessages.getString("checkDebugAttributes.file.argument.cannot.be.null")); //$NON-NLS-1$
+		}
+		if (this.property == null) {
+			throw new BuildException(AntAdapterMessages.getString("checkDebugAttributes.property.argument.cannot.be.null")); //$NON-NLS-1$
+		}
+		try {
+			boolean hasDebugAttributes = false;
+			if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(this.file)) {
+				ZipFile jarFile = new ZipFile(this.file);
+				for (Enumeration entries = jarFile.entries(); !hasDebugAttributes && entries.hasMoreElements(); ) {
+					ZipEntry entry = (ZipEntry) entries.nextElement();
+					if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entry.getName())) {
+						IClassFileReader classFileReader = ToolFactory.createDefaultClassFileReader(this.file, entry.getName(), IClassFileReader.ALL);
+						hasDebugAttributes = checkClassFile(classFileReader);
+					}
+				}
+			} else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(this.file)) {
+				IClassFileReader classFileReader = ToolFactory.createDefaultClassFileReader(this.file, IClassFileReader.ALL);
+				hasDebugAttributes = checkClassFile(classFileReader);
+			} else {
+				throw new BuildException(AntAdapterMessages.getString("checkDebugAttributes.file.argument.must.be.a.classfile.or.a.jarfile")); //$NON-NLS-1$
+			}
+			if (hasDebugAttributes) {
+				this.project.setUserProperty(this.property, "has debug"); //$NON-NLS-1$
+			}
+		} catch (IOException e) {
+			throw new BuildException(AntAdapterMessages.getString("checkDebugAttributes.ioexception.occured") + this.file); //$NON-NLS-1$
+		}
+	}
+	
+	private boolean checkClassFile(IClassFileReader classFileReader) {
+		IMethodInfo[] methodInfos = classFileReader.getMethodInfos();
+		for (int i = 0, max = methodInfos.length; i < max; i++) {
+			ICodeAttribute codeAttribute = methodInfos[i].getCodeAttribute();
+			if (codeAttribute != null && codeAttribute.getLineNumberAttribute() != null) {
+				return true;
+			}	
+		}
+		return false;
+	}
+
+	public void setFile(String value) {
+		this.file = value;
+	}
+	
+	public void setProperty(String value) {
+		this.property = value;
+	}
+}
diff --git a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
index 85ba8f3..1dba46d 100644
--- a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
+++ b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
@@ -24,8 +24,7 @@
 import org.apache.tools.ant.types.FileSet;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.util.JavaEnvUtils;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.jdt.internal.core.Util;
+import org.eclipse.jdt.internal.antadapter.AntAdapterMessages;
 
 /**
  * Ant 1.5 compiler adapter for the Eclipse Java compiler. This adapter permits the
@@ -48,7 +47,7 @@
 	 * Performs a compile using the JDT batch compiler 
 	 */
 	public boolean execute() throws BuildException {
-		attributes.log(Util.bind("ant.jdtadapter.info.usingJdtCompiler"), Project.MSG_VERBOSE); //$NON-NLS-1$
+		attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.usingJDTCompiler"), Project.MSG_VERBOSE); //$NON-NLS-1$
 		Commandline cmd = setupJavacCommand();
 
 		try {
@@ -59,11 +58,11 @@
 			Object result = compile.invoke(batchCompilerInstance, new Object[] { cmd.getArguments()});
 			final boolean resultValue = ((Boolean) result).booleanValue();
 			if (!resultValue && verbose) {
-				System.out.println(Util.bind("ant.jdtadapter.error.compilationFailed", this.logFileName)); //$NON-NLS-1$
+				System.out.println(AntAdapterMessages.getString("ant.jdtadapter.error.compilationFailed", this.logFileName)); //$NON-NLS-1$
 			}
 			return resultValue;
 		} catch (ClassNotFoundException cnfe) {
-			throw new BuildException(Util.bind("ant.jdtadapter.error.missingJDTCompiler")); //$NON-NLS-1$
+			throw new BuildException(AntAdapterMessages.getString("ant.jdtadapter.error.cannotFindJDTCompiler")); //$NON-NLS-1$
 		} catch (Exception ex) {
 			throw new BuildException(ex);
 		}
@@ -78,21 +77,14 @@
 		 */
 		cmd.createArgument().setValue("-noExit"); //$NON-NLS-1$
 
-		cmd.createArgument().setValue("-bootclasspath"); //$NON-NLS-1$
         if (bootclasspath != null && bootclasspath.size() != 0) {
 			/*
 			 * Set the bootclasspath for the Eclipse compiler.
 			 */
+			cmd.createArgument().setValue("-bootclasspath"); //$NON-NLS-1$
 			cmd.createArgument().setPath(bootclasspath);        	
         } else {
-            /*
-             * No bootclasspath, we will add one throught the JRE_LIB variable
-             */
-			IPath jre_lib = JavaCore.getClasspathVariable("JRE_LIB"); //$NON-NLS-1$
-			if (jre_lib == null) {
-				throw new BuildException(Util.bind("ant.jdtadapter.error.missingJRELIB")); //$NON-NLS-1$
-			}
-			cmd.createArgument().setPath(new Path(null, jre_lib.toOSString()));        	
+            includeJavaRuntime = true;
         }
 
         Path classpath = new Path(project);
@@ -108,7 +100,6 @@
 		 * The java runtime is already handled, so we simply want to retrieve the
 		 * ant runtime and the compile classpath.
 		 */
-		includeJavaRuntime = false;
         classpath.append(getCompileClasspath());
 
         // For -sourcepath, use the "sourcepath" value if present.
@@ -122,17 +113,20 @@
         try {
 	        getSourcepathMethod = javacClass.getMethod("getSourcepath", null); //$NON-NLS-1$
         } catch(NoSuchMethodException e) {
+        	// if not found, then we cannot use this method (ant 1.5)
         }
-        Path compileSourcepath = null;
+        Path compileSourcePath = null;
         if (getSourcepathMethod != null) {
 	 		try {
-				compileSourcepath = (Path) getSourcepathMethod.invoke(attributes, null);
+				compileSourcePath = (Path) getSourcepathMethod.invoke(attributes, null);
 			} catch (IllegalAccessException e) {
+				// should never happen
 			} catch (InvocationTargetException e) {
+				// should never happen
 			}
         }
-        if (compileSourcepath != null) {
-            sourcepath = compileSourcepath;
+        if (compileSourcePath != null) {
+            sourcepath = compileSourcePath;
         } else {
             sourcepath = src;
         }
@@ -146,7 +140,7 @@
         String memoryParameterPrefix = JavaEnvUtils.getJavaVersion().equals(JavaEnvUtils.JAVA_1_1) ? "-J-" : "-J-X";//$NON-NLS-1$//$NON-NLS-2$
         if (memoryInitialSize != null) {
             if (!attributes.isForkedJavac()) {
-                attributes.log(Util.bind("ant.jdtadapter.error.ignoringMemoryInitialSize"), Project.MSG_WARN);//$NON-NLS-1$
+                attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.ignoringMemoryInitialSize"), Project.MSG_WARN); //$NON-NLS-1$
             } else {
                 cmd.createArgument().setValue(memoryParameterPrefix
                                               + "ms" + memoryInitialSize); //$NON-NLS-1$
@@ -155,7 +149,7 @@
 
         if (memoryMaximumSize != null) {
             if (!attributes.isForkedJavac()) {
-                attributes.log(Util.bind("ant.jdtadapter.error.ignoringMemoryMaximumSize"), Project.MSG_WARN);//$NON-NLS-1$
+                attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.ignoringMemoryMaximumSize"), Project.MSG_WARN); //$NON-NLS-1$
             } else {
                 cmd.createArgument().setValue(memoryParameterPrefix
                                               + "mx" + memoryMaximumSize); //$NON-NLS-1$
@@ -169,13 +163,17 @@
 	        try {
 		        getDebugLevelMethod = javacClass.getMethod("getDebugLevel", null); //$NON-NLS-1$
 	        } catch(NoSuchMethodException e) {
+	        	// if not found, then we cannot use this method (ant 1.5)
+	        	// debug level is only available with ant 1.5.x
 	        }
      	    String debugLevel = null;
 	        if (getDebugLevelMethod != null) {
 				try {
 					debugLevel = (String) getDebugLevelMethod.invoke(attributes, null);
 				} catch (IllegalAccessException e) {
+					// should never happen
 				} catch (InvocationTargetException e) {
+					// should never happen
 				}
         	}
 			if (debugLevel != null) {
@@ -191,29 +189,65 @@
             cmd.createArgument().setValue("-g:none"); //$NON-NLS-1$
         }
         
-		/*
-		 * Handle the nowarn option. If none, then we generate all warnings.
-		 */		
-        if (attributes.getNowarn()) {
-			if (deprecation) {
-				cmd.createArgument().setValue("-warn:allDeprecation"); //$NON-NLS-1$
-			} else {
-	            cmd.createArgument().setValue("-nowarn"); //$NON-NLS-1$
-			}
-        } else {
-			/*
-			 * deprecation option.
-			 */		
-			if (deprecation) {
-				cmd.createArgument().setValue(
-					"-warn:allDeprecation,constructorName,packageDefaultMethod,maskedCatchBlocks,unusedImports,staticReceiver"); //$NON-NLS-1$
-			} else {
-				cmd.createArgument().setValue(
-					"-warn:constructorName,packageDefaultMethod,maskedCatchBlocks,unusedImports,staticReceiver"); //$NON-NLS-1$
-			}
+       // retrieve the method getCurrentCompilerArgs() using reflect
+        // This is done to improve the compatibility to ant 1.5
+        Method getCurrentCompilerArgsMethod = null;
+        try {
+	        getCurrentCompilerArgsMethod = javacClass.getMethod("getCurrentCompilerArgs", null); //$NON-NLS-1$
+        } catch(NoSuchMethodException e) {
+        	// if not found, then we cannot use this method (ant 1.5)
+        	// debug level is only available with ant 1.5.x
         }
+ 	    String[] compilerArgs = null;
+        if (getCurrentCompilerArgsMethod != null) {
+			try {
+				compilerArgs = (String[]) getCurrentCompilerArgsMethod.invoke(attributes, null);
+			} catch (IllegalAccessException e) {
+				// should never happen
+			} catch (InvocationTargetException e) {
+				// should never happen
+			}
+    	}
+    	
+	   	if (compilerArgs == null) {
+			/*
+			 * Handle the nowarn option. If none, then we generate all warnings.
+			 */
+			if (attributes.getNowarn()) {
+				if (deprecation) {
+					cmd.createArgument().setValue("-warn:allDeprecation"); //$NON-NLS-1$
+				} else {
+					cmd.createArgument().setValue("-nowarn"); //$NON-NLS-1$
+				}
+			} else if (deprecation) {
+				cmd.createArgument().setValue("-warn:allDeprecation,constructorName,packageDefaultMethod,maskedCatchBlocks,unusedImports,staticReceiver"); //$NON-NLS-1$
+			} else {
+				cmd.createArgument().setValue("-warn:constructorName,packageDefaultMethod,maskedCatchBlocks,unusedImports,staticReceiver"); //$NON-NLS-1$
+			}
+    	} else {
+			/*
+			 * Handle the nowarn option. If none, then we generate all warnings.
+			 */
+			if (attributes.getNowarn()) {
+				if (deprecation) {
+					cmd.createArgument().setValue("-warn:allDeprecation"); //$NON-NLS-1$
+				} else {
+					cmd.createArgument().setValue("-nowarn"); //$NON-NLS-1$
+				}
+			} else if (deprecation) {
+				cmd.createArgument().setValue("-warn:allDeprecation"); //$NON-NLS-1$
+			} else if (compilerArgs.length == 0) {
+				cmd.createArgument().setValue("-warn:constructorName,packageDefaultMethod,maskedCatchBlocks,unusedImports,staticReceiver"); //$NON-NLS-1$
+			}
+	        /*
+			 * Add extra argument on the command line
+			 */
+			if (compilerArgs.length != 0) {
+		        cmd.addArguments(compilerArgs);
+			}
+	   	}
 
-		/*
+	   	/*
 		 * destDir option.
 		 */		
 		if (destDir != null) {
@@ -276,12 +310,7 @@
             cmd.createArgument().setValue(encoding);
         }
 
-		/*
-		 * extra option allowed by the Eclipse compiler
-		 */
-		cmd.createArgument().setValue("-time"); //$NON-NLS-1$
-
-		/*
+     	/*
 		 * Eclipse compiler doesn't have a -sourcepath option. This is
 		 * handled through the javac task that collects all source files in
 		 * srcdir option.
@@ -297,17 +326,17 @@
      * so that you don't have to specify them all one by one.
      * @param extdirs - Path to append files to
      */
-    private void addExtdirs(Path extdirs, Path classpath) {
-        if (extdirs == null) {
+    private void addExtdirs(Path extDirs, Path classpath) {
+        if (extDirs == null) {
             String extProp = System.getProperty("java.ext.dirs"); //$NON-NLS-1$
             if (extProp != null) {
-                extdirs = new Path(classpath.getProject(), extProp);
+                extDirs = new Path(classpath.getProject(), extProp);
             } else {
                 return;
             }
         }
 
-        String[] dirs = extdirs.list();
+        String[] dirs = extDirs.list();
         for (int i = 0; i < dirs.length; i++) {
             File dir = classpath.getProject().resolveFile(dirs[i]);
             if (dir.exists() && dir.isDirectory()) {
diff --git a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/AntAdapterMessages.java b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/AntAdapterMessages.java
new file mode 100644
index 0000000..f157c04
--- /dev/null
+++ b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/AntAdapterMessages.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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 Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.antadapter;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+public class AntAdapterMessages {
+
+	private static final String BUNDLE_NAME = "org.eclipse.jdt.internal.antadapter.messages"; //$NON-NLS-1$
+
+	private static ResourceBundle RESOURCE_BUNDLE;
+	
+	static {
+		try {
+		RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME, Locale.getDefault());
+		} catch(MissingResourceException e) {
+			System.out.println("Missing resource : " + BUNDLE_NAME.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+			throw e;
+		}
+	}
+
+	private AntAdapterMessages() {
+		// cannot be instantiated
+	}
+
+	public static String getString(String key) {
+		try {
+			return RESOURCE_BUNDLE.getString(key);
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+
+	public static String getString(String key, String argument) {
+		try {
+			String message = RESOURCE_BUNDLE.getString(key);
+			MessageFormat messageFormat = new MessageFormat(message);
+			return messageFormat.format(new String[] { argument } );
+		} catch (MissingResourceException e) {
+			return '!' + key + '!';
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties
new file mode 100644
index 0000000..f791a03
--- /dev/null
+++ b/org.eclipse.jdt.core/antadapter/org/eclipse/jdt/internal/antadapter/messages.properties
@@ -0,0 +1,21 @@
+###############################################################################
+# 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
+###############################################################################
+### ant tasks messages.
+ant.jdtadapter.info.usingJDTCompiler=Using JDT compiler
+ant.jdtadapter.error.compilationFailed=Compilation failed. Compiler errors are available in {0}
+ant.jdtadapter.error.cannotFindJDTCompiler=Cannot find the JDT compiler
+ant.jdtadapter.info.ignoringMemoryInitialSize=Since fork is false, ignoring memoryInitialSize setting
+ant.jdtadapter.info.ignoringMemoryMaximumSize=Since fork is false, ignoring memoryMaximumSize setting
+
+checkDebugAttributes.file.argument.cannot.be.null=The file argument cannot be null
+checkDebugAttributes.property.argument.cannot.be.null=The property argument cannot be null
+checkDebugAttributes.ioexception.occured=IOException occured while reading 
+checkDebugAttributes.file.argument.must.be.a.classfile.or.a.jarfile=The file argument must be a .class or a .jar file
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
index ad2ae6b..c202cc2 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathDirectory.java
@@ -15,8 +15,9 @@
 
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 
-public class ClasspathDirectory implements FileSystem.Classpath {
+public class ClasspathDirectory implements FileSystem.Classpath, SuffixConstants {
 
 String path;
 Hashtable directoryCache;
@@ -30,7 +31,7 @@
 ClasspathDirectory(File directory, String encoding, int mode) {
 	this.mode = mode;
 	this.path = directory.getAbsolutePath();
-	if (!path.endsWith(File.separator))
+	if (!this.path.endsWith(File.separator))
 		this.path += File.separator;
 	this.directoryCache = new Hashtable(11);
 	this.encoding = encoding;
@@ -41,17 +42,17 @@
 }
 
 String[] directoryList(String qualifiedPackageName) {
-	String[] dirList = (String[]) directoryCache.get(qualifiedPackageName);
-	if (dirList == missingPackageHolder) return null; // package exists in another classpath directory or jar
+	String[] dirList = (String[]) this.directoryCache.get(qualifiedPackageName);
+	if (dirList == this.missingPackageHolder) return null; // package exists in another classpath directory or jar
 	if (dirList != null) return dirList;
 
-	File dir = new File(path + qualifiedPackageName);
+	File dir = new File(this.path + qualifiedPackageName);
 	notFound : if (dir != null && dir.isDirectory()) {
 		// must protect against a case insensitive File call
 		// walk the qualifiedPackageName backwards looking for an uppercase character before the '/'
 		int index = qualifiedPackageName.length();
 		int last = qualifiedPackageName.lastIndexOf(File.separatorChar);
-		while (--index > last && !Character.isUpperCase(qualifiedPackageName.charAt(index))) {}
+		while (--index > last && !Character.isUpperCase(qualifiedPackageName.charAt(index)));
 		if (index > last) {
 			if (last == -1) {
 				if (!doesFileExist(qualifiedPackageName, ""))  //$NON-NLS-1$ 
@@ -65,10 +66,10 @@
 		}
 		if ((dirList = dir.list()) == null)
 			dirList = new String[0];
-		directoryCache.put(qualifiedPackageName, dirList);
+		this.directoryCache.put(qualifiedPackageName, dirList);
 		return dirList;
 	}
-	directoryCache.put(qualifiedPackageName, missingPackageHolder);
+	this.directoryCache.put(qualifiedPackageName, this.missingPackageHolder);
 	return null;
 }
 boolean doesFileExist(String fileName, String qualifiedPackageName) {
@@ -84,14 +85,14 @@
 	if (!isPackage(qualifiedPackageName)) return null; // most common case
 
 	String fileName = new String(typeName);
-	boolean binaryExists = ((this.mode & BINARY) != 0) && doesFileExist(fileName + ".class", qualifiedPackageName); //$NON-NLS-1$
-	boolean sourceExists = ((this.mode & SOURCE) != 0) && doesFileExist(fileName + ".java", qualifiedPackageName); //$NON-NLS-1$
+	boolean binaryExists = ((this.mode & BINARY) != 0) && doesFileExist(fileName + SUFFIX_STRING_class, qualifiedPackageName);
+	boolean sourceExists = ((this.mode & SOURCE) != 0) && doesFileExist(fileName + SUFFIX_STRING_java, qualifiedPackageName);
 	if (sourceExists) {
-		String fullSourcePath = path + qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6)  + ".java"; //$NON-NLS-1$
+		String fullSourcePath = this.path + qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6)  + SUFFIX_STRING_java;
 		if (!binaryExists)
 			return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, this.encoding));
 
-		String fullBinaryPath = path + qualifiedBinaryFileName;
+		String fullBinaryPath = this.path + qualifiedBinaryFileName;
 		long binaryModified = new File(fullBinaryPath).lastModified();
 		long sourceModified = new File(fullSourcePath).lastModified();
 		if (sourceModified > binaryModified)
@@ -99,9 +100,11 @@
 	}
 	if (binaryExists) {
 		try {
-			ClassFileReader reader = ClassFileReader.read(path + qualifiedBinaryFileName);
+			ClassFileReader reader = ClassFileReader.read(this.path + qualifiedBinaryFileName);
 			if (reader != null) return new NameEnvironmentAnswer(reader);
-		} catch (Exception e) {} // treat as if file is missing
+		} catch (Exception e) { 
+			// treat as if file is missing
+		}
 	}
 	return null;
 }
@@ -112,6 +115,6 @@
 	this.directoryCache = new Hashtable(11);
 }
 public String toString() {
-	return "ClasspathDirectory " + path; //$NON-NLS-1$
+	return "ClasspathDirectory " + this.path; //$NON-NLS-1$
 }
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
index 5009cc4..2ebb49b 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJar.java
@@ -29,7 +29,7 @@
 public ClasspathJar(File file) throws IOException {
 	this(new ZipFile(file), true);
 }
-public ClasspathJar(ZipFile zipFile, boolean closeZipFileAtEnd) throws IOException {
+public ClasspathJar(ZipFile zipFile, boolean closeZipFileAtEnd) {
 	this.zipFile = zipFile;
 	this.packageCache = null;
 	this.closeZipFileAtEnd = closeZipFileAtEnd;
@@ -39,19 +39,21 @@
 		return null; // most common case
 
 	try {
-		ClassFileReader reader = ClassFileReader.read(zipFile, qualifiedBinaryFileName);
+		ClassFileReader reader = ClassFileReader.read(this.zipFile, qualifiedBinaryFileName);
 		if (reader != null) return new NameEnvironmentAnswer(reader);
-	} catch (Exception e) {} // treat as if class file is missing
+	} catch (Exception e) {
+		// treat as if class file is missing
+	}
 	return null;
 }
 public boolean isPackage(String qualifiedPackageName) {
-	if (packageCache != null)
-		return packageCache.containsKey(qualifiedPackageName);
+	if (this.packageCache != null)
+		return this.packageCache.containsKey(qualifiedPackageName);
 
 	this.packageCache = new Hashtable(41);
-	packageCache.put("", ""); //$NON-NLS-1$ //$NON-NLS-2$
+	this.packageCache.put("", ""); //$NON-NLS-1$ //$NON-NLS-2$
 
-	nextEntry : for (Enumeration e = zipFile.entries(); e.hasMoreElements(); ) {
+	nextEntry : for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) {
 		String fileName = ((ZipEntry) e.nextElement()).getName();
 
 		// add the package name & all of its parent packages
@@ -59,21 +61,25 @@
 		while (last > 0) {
 			// extract the package name
 			String packageName = fileName.substring(0, last);
-			if (packageCache.containsKey(packageName))
+			if (this.packageCache.containsKey(packageName))
 				continue nextEntry;
-			packageCache.put(packageName, packageName);
+			this.packageCache.put(packageName, packageName);
 			last = packageName.lastIndexOf('/');
 		}
 	}
-	return packageCache.containsKey(qualifiedPackageName);
+	return this.packageCache.containsKey(qualifiedPackageName);
 }
 public void reset() {
-	if (zipFile != null && closeZipFileAtEnd) {
-		try { zipFile.close(); } catch(IOException e) {}
+	if (this.zipFile != null && this.closeZipFileAtEnd) {
+		try { 
+			this.zipFile.close(); 
+		} catch(IOException e) {
+			// ignore
+		}
 	}
 	this.packageCache = null;
 }
 public String toString() {
-	return "Classpath for jar file " + zipFile.getName(); //$NON-NLS-1$
+	return "Classpath for jar file " + this.zipFile.getName(); //$NON-NLS-1$
 }
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
index e0e8397..320f87d 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/CompilationUnit.java
@@ -49,26 +49,27 @@
 	this.encoding = encoding;
 }
 public char[] getContents() {
-	if (contents != null)
-		return contents;   // answer the cached source
+	if (this.contents != null)
+		return this.contents;   // answer the cached source
 
 	// otherwise retrieve it
 	try {
-		return Util.getFileCharContent(new File(new String(fileName)), encoding);
+		return Util.getFileCharContent(new File(new String(this.fileName)), this.encoding);
 	} catch (IOException e) {
+		// assume no content then
 	}
 	return CharOperation.NO_CHAR;
 }
 public char[] getFileName() {
-	return fileName;
+	return this.fileName;
 }
 public char[] getMainTypeName() {
-	return mainTypeName;
+	return this.mainTypeName;
 }
 public char[][] getPackageName() {
 	return null;
 }
 public String toString() {
-	return "CompilationUnit[" + new String(fileName) + "]";  //$NON-NLS-2$ //$NON-NLS-1$
+	return "CompilationUnit[" + new String(this.fileName) + "]";  //$NON-NLS-2$ //$NON-NLS-1$
 }
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java
index 5ed4025..3b68092 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileFinder.java
@@ -13,15 +13,15 @@
 import java.io.File;
 
 public class FileFinder {
-	private final int INITIAL_SIZE = 10;
+	private static final int INITIAL_SIZE = 10;
 	public String[] resultFiles = new String[INITIAL_SIZE];
-	public int counter = 0;
+	public int count = 0;
 public void find(File f, String pattern, boolean verbose) {
 	if (verbose) {
 		System.out.println(Main.bind("scanning.start",f.getAbsolutePath())); //$NON-NLS-1$
 	}
 	find0(f, pattern, verbose);
-	System.arraycopy(resultFiles, 0, (resultFiles = new String[counter]), 0, counter);
+	System.arraycopy(this.resultFiles, 0, (this.resultFiles = new String[this.count]), 0, this.count);
 }
 public void find0(File f, String pattern, boolean verbose) {
 	if (f.isDirectory()) {
@@ -34,11 +34,11 @@
 			} else {
 				if (current.getName().toUpperCase().endsWith(pattern)) {
 					int length;
-					if ((length = resultFiles.length) == counter) {
-						System.arraycopy(resultFiles, 0, (resultFiles = new String[length * 2]), 0, length);
+					if ((length = this.resultFiles.length) == this.count) {
+						System.arraycopy(this.resultFiles, 0, (this.resultFiles = new String[length * 2]), 0, length);
 					}
-					resultFiles[counter++] = current.getAbsolutePath();
-					if (verbose && (counter % 100) == 0)
+					this.resultFiles[this.count++] = current.getAbsolutePath();
+					if (verbose && (this.count % 100) == 0)
 						System.out.print('.');
 				}
 			}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
index d263782..d5c2a97 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
@@ -17,8 +17,9 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 
-public class FileSystem implements INameEnvironment  {
+public class FileSystem implements INameEnvironment, SuffixConstants {
 	Classpath[] classpaths;
 	String[] knownFileNames;
 
@@ -41,7 +42,7 @@
 }
 public FileSystem(String[] classpathNames, String[] initialFileNames, String encoding, int[] classpathDirectoryModes) {
 	int classpathSize = classpathNames.length;
-	classpaths = new Classpath[classpathSize];
+	this.classpaths = new Classpath[classpathSize];
 	String[] pathNames = new String[classpathSize];
 	int problemsOccured = 0;
 	for (int i = 0; i < classpathSize; i++) {
@@ -50,36 +51,36 @@
 			if (file.isDirectory()) {
 				if (file.exists()) {
 					if (classpathDirectoryModes == null){
-						classpaths[i] = new ClasspathDirectory(file, encoding);
+						this.classpaths[i] = new ClasspathDirectory(file, encoding);
 					} else {
-						classpaths[i] = new ClasspathDirectory(file, encoding, classpathDirectoryModes[i]);
+						this.classpaths[i] = new ClasspathDirectory(file, encoding, classpathDirectoryModes[i]);
 					}
-					pathNames[i] = ((ClasspathDirectory) classpaths[i]).path;
+					pathNames[i] = ((ClasspathDirectory) this.classpaths[i]).path;
 				}
-			} else if (classpathNames[i].endsWith(".jar") | (classpathNames[i].endsWith(".zip"))) { //$NON-NLS-2$ //$NON-NLS-1$
-				classpaths[i] = this.getClasspathJar(file); // will throw an IOException if file does not exist
+			} else if (classpathNames[i].endsWith(SUFFIX_STRING_jar) | (classpathNames[i].endsWith(SUFFIX_STRING_zip))) {
+				this.classpaths[i] = this.getClasspathJar(file); // will throw an IOException if file does not exist
 				pathNames[i] = classpathNames[i].substring(0, classpathNames[i].lastIndexOf('.'));
 			}
 		} catch (IOException e) {
-			classpaths[i] = null;
+			this.classpaths[i] = null;
 		}
-		if (classpaths[i] == null)
+		if (this.classpaths[i] == null)
 			problemsOccured++;
 	}
 	if (problemsOccured > 0) {
 		Classpath[] newPaths = new Classpath[classpathSize - problemsOccured];
 		String[] newNames = new String[classpathSize - problemsOccured];
 		for (int i = 0, current = 0; i < classpathSize; i++)
-			if (classpaths[i] != null) {
-				newPaths[current] = classpaths[i];
+			if (this.classpaths[i] != null) {
+				newPaths[current] = this.classpaths[i];
 				newNames[current++] = pathNames[i];
 			}
 		classpathSize = newPaths.length;
-		classpaths = newPaths;
+		this.classpaths = newPaths;
 		pathNames = newNames;
 	}
 
-	knownFileNames = new String[initialFileNames.length];
+	this.knownFileNames = new String[initialFileNames.length];
 	for (int i = initialFileNames.length; --i >= 0;) {
 		String fileName = initialFileNames[i];
 		String matchingPathName = null;
@@ -91,14 +92,14 @@
 			if (fileName.startsWith(pathNames[j]))
 				matchingPathName = pathNames[j];
 		if (matchingPathName == null)
-			knownFileNames[i] = fileName; // leave as is...
+			this.knownFileNames[i] = fileName; // leave as is...
 		else
-			knownFileNames[i] = fileName.substring(matchingPathName.length());
+			this.knownFileNames[i] = fileName.substring(matchingPathName.length());
 	}
 }
 public void cleanup() {
-	for (int i = 0, max = classpaths.length; i < max; i++)
-		classpaths[i].reset();
+	for (int i = 0, max = this.classpaths.length; i < max; i++)
+		this.classpaths[i].reset();
 }
 private String convertPathSeparators(String path) {
 	return File.separatorChar == '/'
@@ -106,25 +107,25 @@
 		 : path.replace('/', '\\');
 }
 private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName){
-	for (int i = 0, length = knownFileNames.length; i < length; i++)
-		if (qualifiedTypeName.equals(knownFileNames[i]))
+	for (int i = 0, length = this.knownFileNames.length; i < length; i++)
+		if (qualifiedTypeName.equals(this.knownFileNames[i]))
 			return null; // looking for a file which we know was provided at the beginning of the compilation
 
-	String qualifiedBinaryFileName = qualifiedTypeName + ".class"; //$NON-NLS-1$
+	String qualifiedBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
 	String qualifiedPackageName =
 		qualifiedTypeName.length() == typeName.length
 			? "" //$NON-NLS-1$
 			: qualifiedBinaryFileName.substring(0, qualifiedTypeName.length() - typeName.length - 1);
 	String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
 	if (qualifiedPackageName == qp2) {
-		for (int i = 0, length = classpaths.length; i < length; i++) {
-			NameEnvironmentAnswer answer = classpaths[i].findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName);
+		for (int i = 0, length = this.classpaths.length; i < length; i++) {
+			NameEnvironmentAnswer answer = this.classpaths[i].findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName);
 			if (answer != null) return answer;
 		}
 	} else {
 		String qb2 = qualifiedBinaryFileName.replace('/', File.separatorChar);
-		for (int i = 0, length = classpaths.length; i < length; i++) {
-			Classpath p = classpaths[i];
+		for (int i = 0, length = this.classpaths.length; i < length; i++) {
+			Classpath p = this.classpaths[i];
 			NameEnvironmentAnswer answer = (p instanceof ClasspathJar)
 				? p.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName)
 				: p.findClass(typeName, qp2, qb2);
@@ -154,12 +155,12 @@
 	String qualifiedPackageName = new String(CharOperation.concatWith(compoundName, packageName, '/'));
 	String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
 	if (qualifiedPackageName == qp2) {
-		for (int i = 0, length = classpaths.length; i < length; i++)
-			if (classpaths[i].isPackage(qualifiedPackageName))
+		for (int i = 0, length = this.classpaths.length; i < length; i++)
+			if (this.classpaths[i].isPackage(qualifiedPackageName))
 				return true;
 	} else {
-		for (int i = 0, length = classpaths.length; i < length; i++) {
-			Classpath p = classpaths[i];
+		for (int i = 0, length = this.classpaths.length; i < length; i++) {
+			Classpath p = this.classpaths[i];
 			if ((p instanceof ClasspathJar) ? p.isPackage(qualifiedPackageName) : p.isPackage(qp2))
 				return true;
 		}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index 1854c5c..2bce3c5 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -21,7 +21,6 @@
 import java.io.StringReader;
 import java.io.UnsupportedEncodingException;
 import java.util.Enumeration;
-import java.util.Hashtable;
 import java.util.Locale;
 import java.util.Map;
 import java.util.MissingResourceException;
@@ -37,193 +36,164 @@
 import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
-public class Main implements ProblemSeverities {
+public class Main implements ProblemSeverities, SuffixConstants {
 
-	public boolean noWarn = false;
-
-	public PrintWriter out;
-	public PrintWriter err;	
-	public boolean systemExitWhenFinished = true;
-	public boolean proceedOnError = false;
-
-	public boolean verbose = false;
-	public boolean produceRefInfo = false;
-	public boolean timer = false;
-	public boolean showProgress = false;
-	public long time = 0;
-	public long lineCount;
-	public boolean generatePackagesStructure;
-
-	public Map options;
-	public String[] filenames;
-	public String[] encodings;
-	public String[] classpaths;
-	public String destinationPath;
-	public String log;
-	public int repetitions;
-	public int globalProblemsCount;
-	public int globalErrorsCount;
-	public int globalWarningsCount;
-	public int exportedClassFilesCounter;
-
-	public static final char[] CLASS_FILE_EXTENSION = ".class".toCharArray(); //$NON-NLS-1$
-	public final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
-	public final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+	static {
+		relocalize();
+	}
 
 	/* Bundle containing messages */
 	public static ResourceBundle bundle;
 	public final static String bundleName =
 		"org.eclipse.jdt.internal.compiler.batch.messages"; 	//$NON-NLS-1$
 
-	static {
-		relocalize();
-	}
+	public final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
+	public final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+	public String[] classpaths;
+	public String destinationPath;
+	public String[] encodings;
+	public PrintWriter err;	
+	public int exportedClassFilesCounter;
+	public String[] filenames;
+	public boolean generatePackagesStructure;
+	public int globalErrorsCount;
+	public int globalProblemsCount;
+	public int globalWarningsCount;
+	public long lineCount;
+	public String log;
+
+	public boolean noWarn = false;
+
+	public Map options;
+
+	public PrintWriter out;
 
 	public boolean proceed = true;
+	public boolean proceedOnError = false;
+	public boolean produceRefInfo = false;
+	public int repetitions;
+	public boolean showProgress = false;
+	public boolean systemExitWhenFinished = true;
+	public long startTime;
+	public boolean timing = false;
+
+	public boolean verbose = false;
 
 	public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished) {
 
 		this.out = outWriter;
 		this.err = errWriter;
 		this.systemExitWhenFinished = systemExitWhenFinished;
-		exportedClassFilesCounter = 0;
-		this.options = getDefaultOptions();
+		this.options = new CompilerOptions().getMap();
 	}
 
-	/*
-	 *  Low-level API performing the actual compilation
+	/**
+	 * Lookup the message with the given ID in this catalog 
+	 * @param id
+	 * @return
 	 */
-	public boolean compile(String[] argv) {
+	public static String bind(String id) {
+		return bind(id, (String[]) null);
+	}
 
-		// decode command line arguments
+	/**
+	 * Lookup the message with the given ID in this catalog and bind its
+	 * substitution locations with the given string.
+	 * @param id
+	 * @param binding
+	 * @return
+	 */
+	public static String bind(String id, String binding) {
+		return bind(id, new String[] { binding });
+	}
+
+	/**
+	 * Lookup the message with the given ID in this catalog and bind its
+	 * substitution locations with the given strings.
+	 * @param id
+	 * @param binding1
+	 * @param binding2
+	 * @return
+	 */
+	public static String bind(String id, String binding1, String binding2) {
+		return bind(id, new String[] { binding1, binding2 });
+	}
+
+	/**
+	 * Lookup the message with the given ID in this catalog and bind its
+	 * substitution locations with the given string values.
+	 * @param id
+	 * @param bindings
+	 * @return
+	 */
+	public static String bind(String id, String[] bindings) {
+		if (id == null)
+			return "No message available"; //$NON-NLS-1$
+		String message = null;
 		try {
-			configure(argv);
-			if (proceed) {
-				if (showProgress)
-					out.println(Main.bind("progress.compiling")); //$NON-NLS-1$
-				for (int i = 0; i < repetitions; i++) {
-					globalProblemsCount = 0;
-					globalErrorsCount = 0;
-					globalWarningsCount = 0;
-					lineCount = 0;
+			message = bundle.getString(id);
+		} catch (MissingResourceException e) {
+			// If we got an exception looking for the message, fail gracefully by just returning
+			// the id we were looking for.  In most cases this is semi-informative so is not too bad.
+			return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
+		}
+		// for compatibility with MessageFormat which eliminates double quotes in original message
+		char[] messageWithNoDoubleQuotes =
+			CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
+		message = new String(messageWithNoDoubleQuotes);
 
-					if (repetitions > 1) {
-						out.flush();
-						out.println(
-							Main.bind(
-								"compile.repetition", //$NON-NLS-1$
-								String.valueOf(i + 1),
-								String.valueOf(repetitions)));
-					}
-					long startTime = System.currentTimeMillis();
-					// request compilation
-					performCompilation();
-					if (timer) {
-
-						time = System.currentTimeMillis() - startTime;
-						if (lineCount != 0) {
-							out.println(
-								Main.bind(
-									"compile.instantTime", 	//$NON-NLS-1$
-									new String[] {
-										String.valueOf(lineCount),
-										String.valueOf(time),
-										String.valueOf((((int) ((lineCount * 10000.0) / time)) / 10.0))}));
-						} else {
-							out.println(Main.bind("compile.totalTime", String.valueOf(time))); //$NON-NLS-1$
-						}
-					}
-					if (globalProblemsCount > 0) {
-						if (globalProblemsCount == 1) {
-							err.print(Main.bind("compile.oneProblem")); //$NON-NLS-1$
-						} else {
-							err.print(
-								Main.bind("compile.severalProblems", String.valueOf(globalProblemsCount))); 	//$NON-NLS-1$
-						}
-						err.print(" ("); //$NON-NLS-1$
-						if (globalErrorsCount > 0) {
-							if (globalErrorsCount == 1) {
-								err.print(Main.bind("compile.oneError")); //$NON-NLS-1$
-							} else {
-								err.print(
-									Main.bind("compile.severalErrors", String.valueOf(globalErrorsCount))); 	//$NON-NLS-1$
+		int length = message.length();
+		int start = -1;
+		int end = length;
+		StringBuffer output = null;
+		while (true) {
+			if ((end = message.indexOf('{', start)) > -1) {
+				if (output == null) output = new StringBuffer(80);
+				output.append(message.substring(start + 1, end));
+				if ((start = message.indexOf('}', end)) > -1) {
+					int index = -1;
+					try {
+						index = Integer.parseInt(message.substring(end + 1, start));
+						output.append(bindings[index]);
+					} catch (NumberFormatException nfe) { // could be nested message ID {compiler.name}
+						String argId = message.substring(end + 1, start);
+						boolean done = false;
+						if (!id.equals(argId)) {
+							String argMessage = null;
+							try {
+								argMessage = bundle.getString(argId);
+								output.append(argMessage);
+								done = true;
+							} catch (MissingResourceException e) {
+								// missing the right resource
 							}
 						}
-						if (globalWarningsCount > 0) {
-							if (globalErrorsCount > 0) {
-								err.print(", "); //$NON-NLS-1$
-							}
-							if (globalWarningsCount == 1) {
-								err.print(Main.bind("compile.oneWarning")); //$NON-NLS-1$
-							} else {
-								err.print(
-									Main.bind("compile.severalWarnings", String.valueOf(globalWarningsCount))); 	//$NON-NLS-1$
-							}
-						}
-						err.println(")"); //$NON-NLS-1$
+						if (!done) output.append(message.substring(end + 1, start + 1));
+					} catch (ArrayIndexOutOfBoundsException e) {
+						output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
 					}
-					if (exportedClassFilesCounter != 0
-						&& (this.showProgress || this.timer || this.verbose)) {
-						if (exportedClassFilesCounter == 1) {
-							out.println(Main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
-						} else {
-							out.println(
-								Main.bind(
-									"compile.severalClassFilesGenerated", //$NON-NLS-1$
-									String.valueOf(exportedClassFilesCounter)));
-						}
-					}
+				} else {
+					output.append(message.substring(end, length));
+					break;
 				}
-				if (showProgress)
-					out.println();
-			}
-			if (systemExitWhenFinished) {
-				out.flush();
-				err.flush();
-				System.exit(globalErrorsCount > 0 ? -1 : 0);
-			}
-		} catch (InvalidInputException e) {
-			err.println(e.getMessage());
-			err.println("------------------------"); //$NON-NLS-1$
-			printUsage();
-			if (systemExitWhenFinished) {
-				System.exit(-1);
-			}
-			return false;
-		} catch (ThreadDeath e) { // do not stop this one
-			throw e;
-		} catch (Throwable e) { // internal compiler error
-			if (systemExitWhenFinished) {
-				out.flush();
-				err.flush();
-				if (this.log != null) {
-					err.close();
-				}
-				System.exit(-1);
-			}
-			return false;
-			//e.printStackTrace();
-		} finally {
-			out.flush();
-			err.flush();
-			if (this.log != null) {
-				err.close();
+			} else {
+				if (output == null) return message;
+				output.append(message.substring(start + 1, length));
+				break;
 			}
 		}
-		if (globalErrorsCount == 0){
-			return true;
-		} else {
-			return false;
-		}
+		return output.toString();
 	}
 
 	/*
@@ -241,6 +211,26 @@
 
 		return new Main(outWriter, errWriter, false).compile(tokenize(commandLine));
 	}
+	
+	/*
+	 * External API
+	 */
+
+	public static void main(String[] argv) {
+		new Main(new PrintWriter(System.out), new PrintWriter(System.err), true).compile(argv);
+	}
+
+	/**
+	 * Creates a NLS catalog for the given locale.
+	 */
+	public static void relocalize() {
+		try {
+			bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
+		} catch(MissingResourceException e) {
+			System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+			throw e;
+		}
+	}
 
 	public static String[] tokenize(String commandLine) {
 
@@ -297,6 +287,81 @@
 	}
 
 	/*
+	 *  Low-level API performing the actual compilation
+	 */
+	public boolean compile(String[] argv) {
+
+		// decode command line arguments
+		try {
+			configure(argv);
+			if (this.proceed) {
+//				if (this.verbose) {
+//					System.out.println(new CompilerOptions(this.options));
+//				}
+				if (this.showProgress)
+					this.out.println(Main.bind("progress.compiling")); //$NON-NLS-1$
+				for (int i = 0; i < this.repetitions; i++) {
+					this.globalProblemsCount = 0;
+					this.globalErrorsCount = 0;
+					this.globalWarningsCount = 0;
+					this.lineCount = 0;
+					this.exportedClassFilesCounter = 0;
+
+					if (this.repetitions > 1) {
+						this.out.flush();
+						this.out.println(
+							Main.bind(
+								"compile.repetition", //$NON-NLS-1$
+								String.valueOf(i + 1),
+								String.valueOf(this.repetitions)));
+					} 
+					// request compilation
+					performCompilation();
+				}
+				if (this.showProgress)
+					this.out.println();
+			}
+			if (this.systemExitWhenFinished) {
+				this.out.flush();
+				this.err.flush();
+				System.exit(this.globalErrorsCount > 0 ? -1 : 0);
+			}
+		} catch (InvalidInputException e) {
+			this.err.println(e.getMessage());
+			this.err.println("------------------------"); //$NON-NLS-1$
+			printUsage();
+			if (this.systemExitWhenFinished) {
+				System.exit(-1);
+			}
+			return false;
+		} catch (ThreadDeath e) { // do not stop this one
+			throw e;
+		} catch (Throwable e) { // internal compiler error
+			if (this.systemExitWhenFinished) {
+				this.out.flush();
+				this.err.flush();
+				if (this.log != null) {
+					this.err.close();
+				}
+				System.exit(-1);
+			}
+			return false;
+			//e.printStackTrace();
+		} finally {
+			this.out.flush();
+			this.err.flush();
+			if (this.log != null) {
+				this.err.close();
+			}
+		}
+		if (this.globalErrorsCount == 0){
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	/*
 	Decode the command line arguments 
 	 */
 	public void configure(String[] argv) throws InvalidInputException {
@@ -320,13 +385,15 @@
 		int bootclasspathCount = 0;
 		int index = -1, filesCount = 0, argCount = argv.length;
 		int mode = Default;
-		repetitions = 0;
-		boolean versionIDRequired = false;
+		this.repetitions = 0;
 		boolean printUsageRequired = false;
-
+		boolean printVersionRequired = false;
+		
 		boolean didSpecifyCompliance = false;
 		boolean didSpecifyDefaultEncoding = false;
 		boolean didSpecifyTarget = false;
+		boolean didSpecifyDeprecation = false;
+		boolean didSpecifyWarnings = false;
 
 		String customEncoding = null;
 		String currentArg = ""; //$NON-NLS-1$
@@ -407,40 +474,40 @@
 				}
 			}
 
-			if (currentArg.endsWith(".java")) { //$NON-NLS-1$
-				if (filenames == null) {
-					filenames = new String[argCount - index];
-					encodings = new String[argCount - index];
-				} else if (filesCount == filenames.length) {
-					int length = filenames.length;
+			if (currentArg.endsWith(SUFFIX_STRING_java)) {
+				if (this.filenames == null) {
+					this.filenames = new String[argCount - index];
+					this.encodings = new String[argCount - index];
+				} else if (filesCount == this.filenames.length) {
+					int length = this.filenames.length;
 					System.arraycopy(
-						filenames,
+						this.filenames,
 						0,
-						(filenames = new String[length + argCount - index]),
+						(this.filenames = new String[length + argCount - index]),
 						0,
 						length);
 					System.arraycopy(
-						encodings,
+						this.encodings,
 						0,
-						(encodings = new String[length + argCount - index]),
+						(this.encodings = new String[length + argCount - index]),
 						0,
 						length);
 				}
-				filenames[filesCount] = currentArg;
-				encodings[filesCount++] = customEncoding;
+				this.filenames[filesCount] = currentArg;
+				this.encodings[filesCount++] = customEncoding;
 				customEncoding = null;
 				mode = Default;
 				continue;
 			}
 			if (currentArg.equals("-log")) { //$NON-NLS-1$
-				if (log != null)
+				if (this.log != null)
 					throw new InvalidInputException(
 						Main.bind("configure.duplicateLog", currentArg)); //$NON-NLS-1$
 				mode = InsideLog;
 				continue;
 			}
 			if (currentArg.equals("-repeat")) { //$NON-NLS-1$
-				if (repetitions > 0)
+				if (this.repetitions > 0)
 					throw new InvalidInputException(
 						Main.bind("configure.duplicateRepeat", currentArg)); //$NON-NLS-1$
 				mode = InsideRepetition;
@@ -460,7 +527,7 @@
 						Main.bind("configure.duplicateCompliance", currentArg));//$NON-NLS-1$
 				}
 				didSpecifyCompliance = true;
-				options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
+				this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
 				mode = Default;
 				continue;
 			}
@@ -470,22 +537,22 @@
 						Main.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
 				}
 				didSpecifyCompliance = true;
-				options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
+				this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
 				mode = Default;
 				continue;
 			}
 			if (currentArg.equals("-d")) { //$NON-NLS-1$
-				if (destinationPath != null)
+				if (this.destinationPath != null)
 					throw new InvalidInputException(
 						Main.bind("configure.duplicateOutputPath", currentArg)); //$NON-NLS-1$
 				mode = InsideDestinationPath;
-				generatePackagesStructure = true;
+				this.generatePackagesStructure = true;
 				continue;
 			}
 			if (currentArg.equals("-classpath") //$NON-NLS-1$
 				|| currentArg.equals("-cp")) { //$NON-NLS-1$ //$NON-NLS-2$
 				if (pathCount == 0) {
-					classpaths = new String[DEFAULT_SIZE_CLASSPATH];
+					this.classpaths = new String[DEFAULT_SIZE_CLASSPATH];
 				}
 				mode = InsideClasspath;
 				continue;
@@ -500,52 +567,51 @@
 			}
 			if (currentArg.equals("-progress")) { //$NON-NLS-1$
 				mode = Default;
-				showProgress = true;
+				this.showProgress = true;
 				continue;
 			}
 			if (currentArg.equals("-proceedOnError")) { //$NON-NLS-1$
 				mode = Default;
-				proceedOnError = true;
+				this.proceedOnError = true;
 				continue;
 			}
 			if (currentArg.equals("-time")) { //$NON-NLS-1$
 				mode = Default;
-				timer = true;
+				this.timing = true;
 				continue;
 			}
 			if (currentArg.equals("-version") //$NON-NLS-1$
-				|| currentArg.equals("-v")) { //$NON-NLS-1$ //$NON-NLS-2$
-				versionIDRequired = true;
-				continue;
+					|| currentArg.equals("-v")) { //$NON-NLS-1$
+				printVersion();
+				this.proceed = false;
+				return;
 			}
+			if (currentArg.equals("-showversion")) { //$NON-NLS-1$
+				printVersionRequired = true;
+				continue;
+			}			
 			if ("-deprecation".equals(currentArg)) { //$NON-NLS-1$
-				options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+				didSpecifyDeprecation = true;
+				this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
 				continue;
 			}
-			if (currentArg.equals("-help")) { //$NON-NLS-1$
+			if (currentArg.equals("-help") || currentArg.equals("-?")) { //$NON-NLS-1$ //$NON-NLS-2$
 				printUsageRequired = true;
 				continue;
 			}
-			if (currentArg.equals("-noImportError")) { //$NON-NLS-1$
-				mode = Default;
-				options.put(
-					CompilerOptions.OPTION_ReportInvalidImport,
-					CompilerOptions.WARNING);
-				continue;
-			}
 			if (currentArg.equals("-noExit")) { //$NON-NLS-1$
 				mode = Default;
-				systemExitWhenFinished = false;
+				this.systemExitWhenFinished = false;
 				continue;
 			}
 			if (currentArg.equals("-verbose")) { //$NON-NLS-1$
 				mode = Default;
-				verbose = true;
+				this.verbose = true;
 				continue;
 			}
 			if (currentArg.equals("-referenceInfo")) { //$NON-NLS-1$
 				mode = Default;
-				produceRefInfo = true;
+				this.produceRefInfo = true;
 				continue;
 			}
 			if (currentArg.startsWith("-g")) { //$NON-NLS-1$
@@ -553,25 +619,25 @@
 				String debugOption = currentArg;
 				int length = currentArg.length();
 				if (length == 2) {
-					options.put(
+					this.options.put(
 						CompilerOptions.OPTION_LocalVariableAttribute,
 						CompilerOptions.GENERATE);
-					options.put(
+					this.options.put(
 						CompilerOptions.OPTION_LineNumberAttribute,
 						CompilerOptions.GENERATE);
-					options.put(
+					this.options.put(
 						CompilerOptions.OPTION_SourceFileAttribute,
 						CompilerOptions.GENERATE);
 					continue;
 				}
 				if (length > 3) {
-					options.put(
+					this.options.put(
 						CompilerOptions.OPTION_LocalVariableAttribute,
 						CompilerOptions.DO_NOT_GENERATE);
-					options.put(
+					this.options.put(
 						CompilerOptions.OPTION_LineNumberAttribute,
 						CompilerOptions.DO_NOT_GENERATE);
-					options.put(
+					this.options.put(
 						CompilerOptions.OPTION_SourceFileAttribute,
 						CompilerOptions.DO_NOT_GENERATE);
 					if (length == 7 && debugOption.equals("-g:none")) //$NON-NLS-1$
@@ -581,15 +647,15 @@
 					while (tokenizer.hasMoreTokens()) {
 						String token = tokenizer.nextToken();
 						if (token.equals("vars")) { //$NON-NLS-1$
-							options.put(
+							this.options.put(
 								CompilerOptions.OPTION_LocalVariableAttribute,
 								CompilerOptions.GENERATE);
 						} else if (token.equals("lines")) { //$NON-NLS-1$
-							options.put(
+							this.options.put(
 								CompilerOptions.OPTION_LineNumberAttribute,
 								CompilerOptions.GENERATE);
 						} else if (token.equals("source")) { //$NON-NLS-1$
-							options.put(
+							this.options.put(
 								CompilerOptions.OPTION_SourceFileAttribute,
 								CompilerOptions.GENERATE);
 						} else {
@@ -603,17 +669,7 @@
 					Main.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
 			}
 			if (currentArg.startsWith("-nowarn")) { //$NON-NLS-1$
-				Object[] entries = options.entrySet().toArray();
-				for (int i = 0, max = entries.length; i < max; i++) {
-					Map.Entry entry = (Map.Entry) entries[i];
-					if (!(entry.getKey() instanceof String))
-						continue;
-					if (!(entry.getValue() instanceof String))
-						continue;
-					if (((String) entry.getValue()).equals(CompilerOptions.WARNING)) {
-						options.put((String) entry.getKey(), CompilerOptions.IGNORE);
-					}
-				}
+				disableWarnings();
 				mode = Default;
 				continue;
 			}
@@ -622,144 +678,178 @@
 				String warningOption = currentArg;
 				int length = currentArg.length();
 				if (length == 10 && warningOption.equals("-warn:none")) { //$NON-NLS-1$
-					Object[] entries = options.entrySet().toArray();
-					for (int i = 0, max = entries.length; i < max; i++) {
-						Map.Entry entry = (Map.Entry) entries[i];
-						if (!(entry.getKey() instanceof String))
-							continue;
-						if (!(entry.getValue() instanceof String))
-							continue;
-						if (((String) entry.getValue()).equals(CompilerOptions.WARNING)) {
-							options.put((String) entry.getKey(), CompilerOptions.IGNORE);
-						}
-					}
+					disableWarnings();
 					continue;
 				}
 				if (length < 6)
 					throw new InvalidInputException(
 						Main.bind("configure.invalidWarningConfiguration", warningOption)); //$NON-NLS-1$
+				int warnTokenStart;
+				boolean isEnabling;
+				switch (warningOption.charAt(6)) {
+					case '+' : 
+						warnTokenStart = 7;
+						isEnabling = true;
+						break;
+					case '-' :
+						warnTokenStart = 7;
+						isEnabling = false; // mentionned warnings are disabled
+						break;
+					default:
+						warnTokenStart = 6;
+						// clear default warning level
+						// but allow multiple warning option on the command line
+						if (!didSpecifyWarnings) disableWarnings();
+						isEnabling = true;
+				}
+			
 				StringTokenizer tokenizer =
-					new StringTokenizer(warningOption.substring(6, warningOption.length()), ","); //$NON-NLS-1$
+					new StringTokenizer(warningOption.substring(warnTokenStart, warningOption.length()), ","); //$NON-NLS-1$
 				int tokenCounter = 0;
 
-				options.put(
-					CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportMethodWithConstructorName,
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportDeprecation, 
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportHiddenCatchBlock,
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportUnusedLocal, 
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportUnusedParameter,
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportAssertIdentifier,
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportUnusedImport,
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportStaticAccessReceiver,
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportNoEffectAssignment,
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_ReportNoImplicitStringConversion,
-					CompilerOptions.IGNORE);				
-				options.put(
-					CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod,
-					CompilerOptions.IGNORE);				
-				options.put(
-					CompilerOptions.OPTION_ReportUnusedPrivateMember,
-					CompilerOptions.IGNORE);
-				options.put(
-					CompilerOptions.OPTION_TaskTags,
-					""); //$NON-NLS-1$
-
+				if (didSpecifyDeprecation) {  // deprecation could have also been set through -deprecation option
+					this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+				}
+				
 				while (tokenizer.hasMoreTokens()) {
 					String token = tokenizer.nextToken();
 					tokenCounter++;
 					if (token.equals("constructorName")) { //$NON-NLS-1$
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_ReportMethodWithConstructorName,
-							CompilerOptions.WARNING);
-					} else if (token.equals("packageDefaultMethod")) { //$NON-NLS-1$
-						options.put(
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("pkgDefaultMethod") || token.equals("packageDefaultMethod")/*backward compatible*/ ) { //$NON-NLS-1$ //$NON-NLS-2$
+						this.options.put(
 							CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
-							CompilerOptions.WARNING);
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.equals("maskedCatchBlock") || token.equals("maskedCatchBlocks")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_ReportHiddenCatchBlock,
-							CompilerOptions.WARNING);
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.equals("deprecation")) { //$NON-NLS-1$
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_ReportDeprecation, 
-							CompilerOptions.WARNING);
-						options.put(
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+						this.options.put(
 							CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, 
 							CompilerOptions.DISABLED);
 					} else if (token.equals("allDeprecation")) { //$NON-NLS-1$
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_ReportDeprecation, 
-							CompilerOptions.WARNING);
-						options.put(
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+						this.options.put(
 							CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode, 
-							CompilerOptions.ENABLED);
+							isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
+						this.options.put(
+							CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, 
+							isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
 					} else if (token.equals("unusedLocal") || token.equals("unusedLocals")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_ReportUnusedLocal, 
-							CompilerOptions.WARNING);
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.equals("unusedArgument") || token.equals("unusedArguments")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_ReportUnusedParameter,
-							CompilerOptions.WARNING);
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.equals("unusedImport") || token.equals("unusedImports")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_ReportUnusedImport,
-							CompilerOptions.WARNING);
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.equals("unusedPrivate")) { //$NON-NLS-1$
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_ReportUnusedPrivateMember,
-							CompilerOptions.WARNING);
-					} else if (token.equals("syntheticAccess")) { //$NON-NLS-1$
-						options.put(
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("localHiding")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportLocalVariableHiding,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("fieldHiding")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportFieldHiding,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("specialParamHiding")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportSpecialParameterHidingField,
+							isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
+					} else if (token.equals("conditionAssign")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportPossibleAccidentalBooleanAssignment,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+   					} else if (token.equals("syntheticAccess")) { //$NON-NLS-1$
+						this.options.put(
 							CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
-							CompilerOptions.WARNING);
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.equals("nls")) { //$NON-NLS-1$
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
-							CompilerOptions.WARNING);
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.equals("staticReceiver")) { //$NON-NLS-1$
-						options.put(
-							CompilerOptions.OPTION_ReportStaticAccessReceiver,
-							CompilerOptions.WARNING);
+						this.options.put(
+							CompilerOptions.OPTION_ReportNonStaticAccessToStatic,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("indirectStatic")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportIndirectStaticAccess,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.equals("noEffectAssign")) { //$NON-NLS-1$
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_ReportNoEffectAssignment,
-							CompilerOptions.WARNING);
-					} else if (token.equals("interfaceNonInherited")) { //$NON-NLS-1$
-						options.put(
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("intfNonInherited") || token.equals("interfaceNonInherited")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
+						this.options.put(
 							CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod,
-							CompilerOptions.WARNING);
-					} else if (token.equals("noImplicitStringConversion")) {//$NON-NLS-1$
-						options.put(
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("charConcat") || token.equals("noImplicitStringConversion")/*backward compatible*/) {//$NON-NLS-1$ //$NON-NLS-2$
+						this.options.put(
 							CompilerOptions.OPTION_ReportNoImplicitStringConversion,
-							CompilerOptions.WARNING);
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("semicolon")) {//$NON-NLS-1$ 
+						this.options.put(
+							CompilerOptions.OPTION_ReportSuperfluousSemicolon,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("emptyBlock")) {//$NON-NLS-1$ 
+						this.options.put(
+							CompilerOptions.OPTION_ReportUndocumentedEmptyBlock,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("uselessTypeCheck")) {//$NON-NLS-1$ 
+						this.options.put(
+							CompilerOptions.OPTION_ReportUnnecessaryTypeCheck,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("javadoc")) {//$NON-NLS-1$ 
+						this.options.put(
+							CompilerOptions.OPTION_ReportInvalidJavadoc,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+						this.options.put(
+							CompilerOptions.OPTION_ReportInvalidJavadocTags,
+							isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
+						this.options.put(
+							CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
+							isEnabling ? CompilerOptions.PRIVATE : CompilerOptions.PUBLIC);
+						this.options.put(
+							CompilerOptions.OPTION_ReportMissingJavadocTags,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+						this.options.put(
+							CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
+							isEnabling ? CompilerOptions.PRIVATE : CompilerOptions.PUBLIC);
+					} else if (token.equals("allJavadoc")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportInvalidJavadoc,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+						this.options.put(
+							CompilerOptions.OPTION_ReportInvalidJavadocTags,
+							isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
+						this.options.put(
+							CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
+							isEnabling ? CompilerOptions.PRIVATE : CompilerOptions.PUBLIC);
+						this.options.put(
+							CompilerOptions.OPTION_ReportMissingJavadocTags,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+						this.options.put(
+							CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
+							isEnabling ? CompilerOptions.PRIVATE : CompilerOptions.PUBLIC);
+						this.options.put(
+							CompilerOptions.OPTION_ReportMissingJavadocComments,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else if (token.startsWith("tasks")) { //$NON-NLS-1$
 						String taskTags = ""; //$NON-NLS-1$
 						int start = token.indexOf('(');
@@ -771,13 +861,25 @@
 						if (taskTags.length() == 0){
 							throw new InvalidInputException(Main.bind("configure.invalidTaskTag", token)); //$NON-NLS-1$
 						}
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_TaskTags,
-							taskTags);
+							isEnabling ? taskTags : "");  //$NON-NLS-1$
 					} else if (token.equals("assertIdentifier")) { //$NON-NLS-1$
-						options.put(
+						this.options.put(
 							CompilerOptions.OPTION_ReportAssertIdentifier,
-							CompilerOptions.WARNING);
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("finally")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportFinallyBlockNotCompletingNormally,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("unusedThrown")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportUnusedDeclaredThrownException,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
+					} else if (token.equals("unqualifiedField")) { //$NON-NLS-1$
+						this.options.put(
+							CompilerOptions.OPTION_ReportUnqualifiedFieldAccess,
+							isEnabling ? CompilerOptions.WARNING : CompilerOptions.IGNORE);
 					} else {
 						throw new InvalidInputException(Main.bind("configure.invalidWarning", token)); //$NON-NLS-1$
 					}
@@ -785,6 +887,7 @@
 				if (tokenCounter == 0)
 					throw new InvalidInputException(
 						Main.bind("configure.invalidWarningOption", currentArg)); //$NON-NLS-1$
+				didSpecifyWarnings = true;
 				continue;
 			}
 			if (currentArg.equals("-target")) { //$NON-NLS-1$
@@ -792,7 +895,7 @@
 				continue;
 			}
 			if (currentArg.equals("-preserveAllLocals")) { //$NON-NLS-1$
-				options.put(
+				this.options.put(
 					CompilerOptions.OPTION_PreserveUnusedLocal,
 					CompilerOptions.PRESERVE);
 				continue;
@@ -800,17 +903,17 @@
 			if (mode == TargetSetting) {
 				didSpecifyTarget = true;
 				if (currentArg.equals("1.1")) { //$NON-NLS-1$
-					options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
 				} else if (currentArg.equals("1.2")) { //$NON-NLS-1$
-					options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
 				} else if (currentArg.equals("1.3")) { //$NON-NLS-1$
-					options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3);
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3);
 				} else if (currentArg.equals("1.4")) { //$NON-NLS-1$
-					options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
-					if (didSpecifyCompliance && options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_3)) {
-						throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget14", (String)options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+					if (didSpecifyCompliance && CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) <= ClassFileConstants.JDK1_3) {
+						throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget14", (String)this.options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
 					}
-					options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
+					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
 				} else {
 					throw new InvalidInputException(Main.bind("configure.targetJDK", currentArg)); //$NON-NLS-1$
 				}
@@ -818,14 +921,14 @@
 				continue;
 			}
 			if (mode == InsideLog) {
-				log = currentArg;
+				this.log = currentArg;
 				mode = Default;
 				continue;
 			}
 			if (mode == InsideRepetition) {
 				try {
-					repetitions = Integer.parseInt(currentArg);
-					if (repetitions <= 0) {
+					this.repetitions = Integer.parseInt(currentArg);
+					if (this.repetitions <= 0) {
 						throw new InvalidInputException(Main.bind("configure.repetition", currentArg)); //$NON-NLS-1$
 					}
 				} catch (NumberFormatException e) {
@@ -836,9 +939,9 @@
 			}
 			if (mode == InsideSource) {
 				if (currentArg.equals("1.3")) { //$NON-NLS-1$
-					options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
+					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
 				} else if (currentArg.equals("1.4")) { //$NON-NLS-1$
-					options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
+					this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
 				} else {
 					throw new InvalidInputException(Main.bind("configure.source", currentArg)); //$NON-NLS-1$
 				}
@@ -856,13 +959,13 @@
 					throw new InvalidInputException(
 						Main.bind("configure.unsupportedEncoding", currentArg)); //$NON-NLS-1$
 				}
-				options.put(CompilerOptions.OPTION_Encoding, currentArg);
+				this.options.put(CompilerOptions.OPTION_Encoding, currentArg);
 				didSpecifyDefaultEncoding = true;
 				mode = Default;
 				continue;
 			}
 			if (mode == InsideDestinationPath) {
-				destinationPath = currentArg;
+				this.destinationPath = currentArg;
 				mode = Default;
 				continue;
 			}
@@ -870,15 +973,15 @@
 				StringTokenizer tokenizer = new StringTokenizer(currentArg, File.pathSeparator);
 				while (tokenizer.hasMoreTokens()) {
 					int length;
-					if ((length = classpaths.length) <= pathCount) {
+					if ((length = this.classpaths.length) <= pathCount) {
 						System.arraycopy(
-							classpaths,
+							this.classpaths,
 							0,
-							(classpaths = new String[length * 2]),
+							(this.classpaths = new String[length * 2]),
 							0,
 							length);
 					}
-					classpaths[pathCount++] = tokenizer.nextToken();
+					this.classpaths[pathCount++] = tokenizer.nextToken();
 				}
 				mode = Default;
 				continue;
@@ -911,81 +1014,74 @@
 					Main.bind("configure.directoryNotExist", currentArg)); //$NON-NLS-1$
 			FileFinder finder = new FileFinder();
 			try {
-				finder.find(dir, ".JAVA", verbose); //$NON-NLS-1$
+				finder.find(dir, SUFFIX_STRING_JAVA, this.verbose); //$NON-NLS-1$
 			} catch (Exception e) {
 				throw new InvalidInputException(Main.bind("configure.IOError", currentArg)); //$NON-NLS-1$
 			}
-			if (filenames != null) {
+			if (this.filenames != null) {
 				// some source files were specified explicitly
 				String results[] = finder.resultFiles;
 				int length = results.length;
 				System.arraycopy(
-					filenames,
+					this.filenames,
 					0,
-					(filenames = new String[length + filesCount]),
+					(this.filenames = new String[length + filesCount]),
 					0,
 					filesCount);
 				System.arraycopy(
-					encodings,
+					this.encodings,
 					0,
-					(encodings = new String[length + filesCount]),
+					(this.encodings = new String[length + filesCount]),
 					0,
 					filesCount);
-				System.arraycopy(results, 0, filenames, filesCount, length);
+				System.arraycopy(results, 0, this.filenames, filesCount, length);
 				for (int i = 0; i < length; i++) {
-					encodings[filesCount + i] = customEncoding;
+					this.encodings[filesCount + i] = customEncoding;
 				}
 				filesCount += length;
 				customEncoding = null;
 			} else {
-				filenames = finder.resultFiles;
-				filesCount = filenames.length;
-				encodings = new String[filesCount];
+				this.filenames = finder.resultFiles;
+				filesCount = this.filenames.length;
+				this.encodings = new String[filesCount];
 				for (int i = 0; i < filesCount; i++) {
-					encodings[i] = customEncoding;
+					this.encodings[i] = customEncoding;
 				}
 				customEncoding = null;
 			}
 			mode = Default;
 			continue;
 		}
-
-		/*
-		 * Standalone options
-		 */
-		if (versionIDRequired) {
-			out.println(Main.bind("configure.version", Main.bind("compiler.version"))); //$NON-NLS-1$ //$NON-NLS-2$
-			out.println();
-			proceed = false;
-			return;
-		}
-
-		if (printUsageRequired) {
+		if (printUsageRequired || filesCount == 0) {
 			printUsage();
-			proceed = false;
+			this.proceed = false;
 			return;
+		} else {
+			if (printVersionRequired) {
+				printVersion();
+			}
 		}
 
 		if (filesCount != 0)
 			System.arraycopy(
-				filenames,
+				this.filenames,
 				0,
-				(filenames = new String[filesCount]),
+				(this.filenames = new String[filesCount]),
 				0,
 				filesCount);
 		if (pathCount == 0) {
 			// no user classpath specified.
 			String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$
 			if ((classProp == null) || (classProp.length() == 0)) {
-				err.println(Main.bind("configure.noClasspath")); //$NON-NLS-1$
+				this.err.println(Main.bind("configure.noClasspath")); //$NON-NLS-1$
 				classProp = System.getProperty("user.dir"); //$NON-NLS-1$
 			}
 			StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator);
-			classpaths = new String[tokenizer.countTokens() + 1];
+			this.classpaths = new String[tokenizer.countTokens() + 1];
 			while (tokenizer.hasMoreTokens()) {
-				classpaths[pathCount++] = tokenizer.nextToken();
+				this.classpaths[pathCount++] = tokenizer.nextToken();
 			}
-			classpaths[pathCount++] = System.getProperty("user.dir");//$NON-NLS-1$
+			this.classpaths[pathCount++] = System.getProperty("user.dir");//$NON-NLS-1$
 		}
 		
 		if (bootclasspathCount == 0) {
@@ -995,8 +1091,8 @@
 			 */
 			 String javaversion = System.getProperty("java.version");//$NON-NLS-1$
 			 if (javaversion != null && javaversion.equalsIgnoreCase("1.1.8")) { //$NON-NLS-1$
-				err.println(Main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
-				proceed = false;
+				this.err.println(Main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
+				this.proceed = false;
 				return;
 			 } else {
 				 String javaVMName = System.getProperty("java.vm.name");//$NON-NLS-1$
@@ -1022,6 +1118,7 @@
 									charconv.getAbsolutePath()};
 								bootclasspathCount = 3;
 							} catch (IOException e) {
+								// cannot retrieve libraries
 							}
 				 	 	}
 				 	 }
@@ -1036,7 +1133,7 @@
 							try {
 								javaHomeFile = new File(javaHomeFile.getCanonicalPath());
 								// add all jars in the lib subdirectory
-								File[] systemLibrariesJars = getFilesFrom(new File(javaHomeFile, "lib"), ".jar");//$NON-NLS-1$//$NON-NLS-2$
+								File[] systemLibrariesJars = getFilesFrom(new File(javaHomeFile, "lib"), SUFFIX_STRING_jar);//$NON-NLS-1$
 								int length = systemLibrariesJars.length;
 								bootclasspaths = new String[length];
 								for (int i = 0; i < length; i++) {
@@ -1046,6 +1143,7 @@
 									bootclasspaths[bootclasspathCount++] = systemLibrariesJars[i].getAbsolutePath();
 								} 
 							} catch (IOException e) {
+								// cannot retrieve libraries
 							}
 				 	 	}
 				 	 }
@@ -1053,20 +1151,30 @@
 			 }
 		}
 
-		if (classpaths == null) {
-			classpaths = new String[0];
+		if (this.log != null) {
+			try {
+				this.err = new PrintWriter(new FileOutputStream(this.log, false));
+			} catch (IOException e) {
+				throw new InvalidInputException(Main.bind("configure.cannotOpenLog")); //$NON-NLS-1$
+			}
+		} else {
+			this.showProgress = false;
+		}
+
+		if (this.classpaths == null) {
+			this.classpaths = new String[0];
 		}
 		/* 
 		 * We put the bootclasspath at the beginning of the classpath entries
 		 */
 		String[] newclasspaths = null;
-		if ((pathCount + bootclasspathCount) != classpaths.length) {
+		if ((pathCount + bootclasspathCount) != this.classpaths.length) {
 			newclasspaths = new String[pathCount + bootclasspathCount];
 		} else {
-			newclasspaths = classpaths;
+			newclasspaths = this.classpaths;
 		}
 		System.arraycopy(
-			classpaths,
+			this.classpaths,
 			0,
 			newclasspaths,
 			bootclasspathCount,
@@ -1080,461 +1188,75 @@
 				0,
 				bootclasspathCount);
 		}
-		classpaths = newclasspaths;
-		for (int i = 0, max = classpaths.length; i < max; i++) {
-			File file = new File(classpaths[i]);
+		this.classpaths = newclasspaths;
+		for (int i = 0, max = this.classpaths.length; i < max; i++) {
+			File file = new File(this.classpaths[i]);
 			if (!file.exists()) { // signal missing classpath entry file
-				err.println(Main.bind("configure.incorrectClasspath", classpaths[i])); //$NON-NLS-1$
-			} /* else {
-				out.println(classpaths[i]);
-			}*/
+				this.out.println(Main.bind("configure.incorrectClasspath", this.classpaths[i])); //$NON-NLS-1$
+			}
 		}
-		if (destinationPath == null) {
-			generatePackagesStructure = false;
-		} else if ("none".equals(destinationPath)) { //$NON-NLS-1$
-			destinationPath = null;
-		}
-
-		if (filenames == null) {
-			printUsage();
-			return;
+		if (this.destinationPath == null) {
+			this.generatePackagesStructure = false;
+		} else if ("none".equals(this.destinationPath)) { //$NON-NLS-1$
+			this.destinationPath = null;
 		}
 
 		// target must be 1.4 if source is 1.4
-		if (options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)
-				&& !options.get(CompilerOptions.OPTION_TargetPlatform).equals(CompilerOptions.VERSION_1_4)
+		if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Source)) >= ClassFileConstants.JDK1_4
+				&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform)) < ClassFileConstants.JDK1_4
 				&& didSpecifyTarget){ 
-				throw new InvalidInputException(Main.bind("configure.incompatibleTargetForSource14", (String)options.get(CompilerOptions.OPTION_TargetPlatform))); //$NON-NLS-1$
+				throw new InvalidInputException(Main.bind("configure.incompatibleTargetForSource14", (String)this.options.get(CompilerOptions.OPTION_TargetPlatform))); //$NON-NLS-1$
 		}
 
 		// target cannot be 1.4 if compliance is 1.3
-		if (options.get(CompilerOptions.OPTION_TargetPlatform).equals(CompilerOptions.VERSION_1_4)
-				&& !options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)
+		if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_4
+				&& CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_TargetPlatform)) >= ClassFileConstants.JDK1_4
 				&& didSpecifyTarget){ 
-				throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget14", (String)options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
+				throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget14", (String)this.options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
 		}
 		
 		// check and set compliance/source/target compatibilities
-		if (options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)){
-			options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
-			options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
-		} else if (options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)
-			  && options.get(CompilerOptions.OPTION_TargetPlatform).equals(CompilerOptions.VERSION_1_1)) {
-			  	if (didSpecifyTarget) {
-					throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget11", (String)options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
-			  	} else {
-					options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
-			  	}
+		if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)){
+			if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
+			if (!didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
 		}
 		// compliance must be 1.4 if source is 1.4
-		if (options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)
-				&& !options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)){ 
-				throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForSource14", (String)options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
+		if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)
+				&& !this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)){ 
+				throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForSource14", (String)this.options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
 		}
 
-		if (log != null) {
-			try {
-				err = new PrintWriter(new FileOutputStream(log, false));
-			} catch (IOException e) {
-				throw new InvalidInputException(Main.bind("configure.cannotOpenLog")); //$NON-NLS-1$
-			}
-		} else {
-			showProgress = false;
-		}
-
-		if (repetitions == 0) {
-			repetitions = 1;
-		}
-	}
-	
-	private File[] getFilesFrom(File f, final String extension) {
-		return f.listFiles(new FilenameFilter() {
-			public boolean accept(File dir, String name) {
-				if (name.endsWith(extension)) {
-					return true;
-				}
-				return false;
-			}
-		});
-	}
-	
-	public Map getDefaultOptions() {
-		Map defaultOptions = new Hashtable();
-		defaultOptions.put(
-			CompilerOptions.OPTION_LocalVariableAttribute,
-			CompilerOptions.DO_NOT_GENERATE);
-		defaultOptions.put(
-			CompilerOptions.OPTION_LineNumberAttribute,
-			CompilerOptions.GENERATE);
-		defaultOptions.put(
-			CompilerOptions.OPTION_SourceFileAttribute,
-			CompilerOptions.GENERATE);
-		defaultOptions.put(
-			CompilerOptions.OPTION_PreserveUnusedLocal,
-			CompilerOptions.OPTIMIZE_OUT);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportUnreachableCode,
-			CompilerOptions.ERROR);
-		defaultOptions.put(CompilerOptions.OPTION_ReportInvalidImport, CompilerOptions.ERROR);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
-			CompilerOptions.WARNING);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportMethodWithConstructorName,
-			CompilerOptions.WARNING);
-		defaultOptions.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportHiddenCatchBlock,
-			CompilerOptions.WARNING);
-		defaultOptions.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.IGNORE);
-		defaultOptions.put(CompilerOptions.OPTION_ReportUnusedImport, CompilerOptions.WARNING);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportUnusedParameter,
-			CompilerOptions.IGNORE);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportUnusedParameterWhenImplementingAbstract,
-			CompilerOptions.DISABLED);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportUnusedParameterWhenOverridingConcrete,
-			CompilerOptions.DISABLED);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
-			CompilerOptions.IGNORE);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
-			CompilerOptions.IGNORE);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportAssertIdentifier,
-			CompilerOptions.IGNORE);
-		defaultOptions.put(
-			CompilerOptions.OPTION_Compliance,
-			CompilerOptions.VERSION_1_3);
-		defaultOptions.put(
-			CompilerOptions.OPTION_Source,
-			CompilerOptions.VERSION_1_3);
-		defaultOptions.put(
-			CompilerOptions.OPTION_TargetPlatform,
-			CompilerOptions.VERSION_1_1);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportNoImplicitStringConversion,
-			CompilerOptions.WARNING);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportStaticAccessReceiver,
-			CompilerOptions.WARNING);			
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod,
-			CompilerOptions.WARNING);
-		defaultOptions.put(
-			CompilerOptions.OPTION_ReportUnusedPrivateMember,
-			CompilerOptions.IGNORE);
-			return defaultOptions;
-	}
-	public Map getOptions() {
-		return this.options;
-	}
-	/*
-	 * Answer the component to which will be handed back compilation results from the compiler
-	 */
-	public ICompilerRequestor getBatchRequestor() {
-		return new ICompilerRequestor() {
-			int lineDelta = 0;
-			public void acceptResult(CompilationResult compilationResult) {
-				if (compilationResult.lineSeparatorPositions != null) {
-					int unitLineCount = compilationResult.lineSeparatorPositions.length;
-					lineCount += unitLineCount;
-					lineDelta += unitLineCount;
-					if (showProgress
-						&& lineDelta > 2000) { // in -log mode, dump a dot every 2000 lines compiled
-						out.print('.');
-						lineDelta = 0;
-					}
-				}
-				if (compilationResult.hasProblems() || compilationResult.hasTasks()) {
-					IProblem[] problems = compilationResult.getAllProblems();
-					int count = problems.length;
-					int localErrorCount = 0;
-					for (int i = 0; i < count; i++) {
-						if (problems[i] != null) {
-							globalProblemsCount++;
-							if (localErrorCount == 0)
-								err.println("----------"); //$NON-NLS-1$
-							err.print(
-								globalProblemsCount
-									+ ". "  //$NON-NLS-1$
-									+ (problems[i].isError()
-										? Main.bind("requestor.error")  //$NON-NLS-1$
-										: Main.bind("requestor.warning")));  //$NON-NLS-1$
-							if (problems[i].isError()) {
-								globalErrorsCount++;
-							} else {
-								globalWarningsCount++;
-							}
-							err.print(" "); //$NON-NLS-1$
-							err.print(
-								Main.bind("requestor.in", new String(problems[i].getOriginatingFileName()))); //$NON-NLS-1$
-							try {
-								err.println(
-									((DefaultProblem) problems[i]).errorReportSource(
-										compilationResult.compilationUnit));
-								err.println(problems[i].getMessage());
-							} catch (Exception e) {
-								err.println(
-									Main.bind("requestor.notRetrieveErrorMessage", problems[i].toString())); //$NON-NLS-1$
-							}
-							err.println("----------"); //$NON-NLS-1$
-							if (problems[i].isError())
-								localErrorCount++;
-						}
-					};
-					// exit?
-					if (systemExitWhenFinished && !proceedOnError && (localErrorCount > 0)) {
-						err.flush();
-						out.flush();
-						System.exit(-1);
-					}
-				}
-				outputClassFiles(compilationResult);
-			}
-		};
-	}
-	/*
-	 *  Build the set of compilation source units
-	 */
-	public CompilationUnit[] getCompilationUnits()
-		throws InvalidInputException {
-		int fileCount = filenames.length;
-		CompilationUnit[] units = new CompilationUnit[fileCount];
-		HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);
-
-		String defaultEncoding = (String) options.get(CompilerOptions.OPTION_Encoding);
-		if ("".equals(defaultEncoding)) //$NON-NLS-1$
-			defaultEncoding = null; //$NON-NLS-1$
-
-		for (int i = 0; i < fileCount; i++) {
-			char[] charName = filenames[i].toCharArray();
-			if (knownFileNames.get(charName) != null) {
-				throw new InvalidInputException(Main.bind("unit.more", filenames[i])); //$NON-NLS-1$
-			} else {
-				knownFileNames.put(charName, charName);
-			}
-			File file = new File(filenames[i]);
-			if (!file.exists())
-				throw new InvalidInputException(Main.bind("unit.missing", filenames[i])); //$NON-NLS-1$
-			String encoding = encodings[i];
-			if (encoding == null)
-				encoding = defaultEncoding;
-			units[i] = new CompilationUnit(null, filenames[i], encoding);
-		}
-		return units;
-	}
-	/*
-	 *  Low-level API performing the actual compilation
-	 */
-	public IErrorHandlingPolicy getHandlingPolicy() {
-
-		// passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)	
-		return new IErrorHandlingPolicy() {
-			public boolean stopOnFirstError() {
-				return false;
-			}
-			public boolean proceedOnErrors() {
-				return proceedOnError; // stop if there are some errors 
-			}
-		};
-	}
-	/*
-	 *  Low-level API performing the actual compilation
-	 */
-	public FileSystem getLibraryAccess() {
-
-		String defaultEncoding = (String) options.get(CompilerOptions.OPTION_Encoding);
-		if ("".equals(defaultEncoding)) //$NON-NLS-1$
-			defaultEncoding = null; //$NON-NLS-1$	
-		return new FileSystem(classpaths, filenames, defaultEncoding);
-	}
-	/*
-	 *  Low-level API performing the actual compilation
-	 */
-	public IProblemFactory getProblemFactory() {
-		return new DefaultProblemFactory(Locale.getDefault());
-	}
-	/*
-	 * External API
-	 */
-
-	public static void main(String[] argv) {
-		new Main(new PrintWriter(System.out), new PrintWriter(System.err), true).compile(argv);
-	}
-	// Dump classfiles onto disk for all compilation units that where successfull.
-
-	public void outputClassFiles(CompilationResult unitResult) {
-
-		if (!((unitResult == null) || (unitResult.hasErrors() && !proceedOnError))) {
-			Enumeration classFiles = unitResult.compiledTypes.elements();
-			if (!this.generatePackagesStructure) {
-				while (classFiles.hasMoreElements()) {
-					this.destinationPath = extractDestinationPathFromSourceFile(unitResult);
-					// retrieve the key and the corresponding classfile
-					ClassFile classFile = (ClassFile) classFiles.nextElement();
-					char[] filename = classFile.fileName();
-					int length = filename.length;
-					char[] relativeName = new char[length + 6];
-					System.arraycopy(filename, 0, relativeName, 0, length);
-					System.arraycopy(CLASS_FILE_EXTENSION, 0, relativeName, length, 6);
-					CharOperation.replace(relativeName, '/', File.separatorChar);
-					try {
-						ClassFile.writeToDisk(
-							generatePackagesStructure,
-							destinationPath,
-							new String(relativeName),
-							classFile.getBytes());
-					} catch (IOException e) {
-						String fileName = destinationPath + new String(relativeName);
-						e.printStackTrace();
-						err.println(Main.bind("output.noClassFileCreated", fileName));  //$NON-NLS-1$
-					}
-					exportedClassFilesCounter++;
-				}
-			} else if (destinationPath != null) {
-				while (classFiles.hasMoreElements()) {
-					// retrieve the key and the corresponding classfile
-					ClassFile classFile = (ClassFile) classFiles.nextElement();
-					char[] filename = classFile.fileName();
-					int length = filename.length;
-					char[] relativeName = new char[length + 6];
-					System.arraycopy(filename, 0, relativeName, 0, length);
-					System.arraycopy(CLASS_FILE_EXTENSION, 0, relativeName, length, 6);
-					CharOperation.replace(relativeName, '/', File.separatorChar);
-					try {
-						ClassFile.writeToDisk(
-							generatePackagesStructure,
-							destinationPath,
-							new String(relativeName),
-							classFile.getBytes());
-					} catch (IOException e) {
-						String fileName = destinationPath + new String(relativeName);
-						e.printStackTrace();
-						err.println(Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$
-					}
-					exportedClassFilesCounter++;
+		// set default target according to compliance & sourcelevel.
+		if (!didSpecifyTarget) {
+			if (this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_3)) {
+				this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
+			} else if (this.options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)) {
+				if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_3)) {
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
+				} else if (this.options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)) {
+					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
 				}
 			}
 		}
-	}
-	/*
-	 *  Low-level API performing the actual compilation
-	 */
-	public void performCompilation() throws InvalidInputException {
 
-		INameEnvironment environment = getLibraryAccess();
-		Compiler batchCompiler =
-			new Compiler(
-				environment,
-				getHandlingPolicy(),
-				getOptions(),
-				getBatchRequestor(),
-				getProblemFactory());
-		CompilerOptions options = batchCompiler.options;
-
-		// set the non-externally configurable options.
-		options.setVerboseMode(verbose);
-		options.produceReferenceInfo(produceRefInfo);
-		batchCompiler.compile(getCompilationUnits());
-
-		// cleanup
-		environment.cleanup();
-	}
-	public void printUsage() {
-		out.println(Main.bind("misc.usage", Main.bind("compiler.version"))); //$NON-NLS-1$ //$NON-NLS-2$
-		out.flush();
-		err.flush();
-	}
-
-	/**
-	 * Creates a NLS catalog for the given locale.
-	 */
-	public static void relocalize() {
-		try {
-			bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
-		} catch(MissingResourceException e) {
-			System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
-			throw e;
+		if (this.repetitions == 0) {
+			this.repetitions = 1;
 		}
 	}
 
-	/**
-	 * Lookup the message with the given ID in this catalog 
-	 */
-	public static String bind(String id) {
-		return bind(id, (String[]) null);
-	}
-
-	/**
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given string values.
-	 */
-	public static String bind(String id, String[] bindings) {
-		if (id == null)
-			return "No message available"; //$NON-NLS-1$
-		String message = null;
-		try {
-			message = bundle.getString(id);
-		} catch (MissingResourceException e) {
-			// If we got an exception looking for the message, fail gracefully by just returning
-			// the id we were looking for.  In most cases this is semi-informative so is not too bad.
-			return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
-		}
-		// for compatibility with MessageFormat which eliminates double quotes in original message
-		char[] messageWithNoDoubleQuotes =
-			CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
-		message = new String(messageWithNoDoubleQuotes);
-
-		if (bindings == null)
-			return message;
-
-		int length = message.length();
-		int start = -1;
-		int end = length;
-		StringBuffer output = new StringBuffer(80);
-		while (true) {
-			if ((end = message.indexOf('{', start)) > -1) {
-				output.append(message.substring(start + 1, end));
-				if ((start = message.indexOf('}', end)) > -1) {
-					int index = -1;
-					try {
-						index = Integer.parseInt(message.substring(end + 1, start));
-						output.append(bindings[index]);
-					} catch (NumberFormatException nfe) {
-						output.append(message.substring(end + 1, start + 1));
-					} catch (ArrayIndexOutOfBoundsException e) {
-						output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
-					}
-				} else {
-					output.append(message.substring(end, length));
-					break;
-				}
-			} else {
-				output.append(message.substring(start + 1, length));
-				break;
+	private void disableWarnings() {
+		Object[] entries = this.options.entrySet().toArray();
+		for (int i = 0, max = entries.length; i < max; i++) {
+			Map.Entry entry = (Map.Entry) entries[i];
+			if (!(entry.getKey() instanceof String))
+				continue;
+			if (!(entry.getValue() instanceof String))
+				continue;
+			if (((String) entry.getValue()).equals(CompilerOptions.WARNING)) {
+				this.options.put(entry.getKey(), CompilerOptions.IGNORE);
 			}
 		}
-		return output.toString();
-	}
-
-	/**
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given string.
-	 */
-	public static String bind(String id, String binding) {
-		return bind(id, new String[] { binding });
-	}
-
-	/**
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given strings.
-	 */
-	public static String bind(String id, String binding1, String binding2) {
-		return bind(id, new String[] { binding1, binding2 });
+		this.options.put(CompilerOptions.OPTION_TaskTags, ""); //$NON-NLS-1$
 	}
 
 	public String extractDestinationPathFromSourceFile(CompilationResult result) {
@@ -1549,5 +1271,290 @@
 		}
 		return System.getProperty("user.dir"); //$NON-NLS-1$
 	}
+	/*
+	 * Answer the component to which will be handed back compilation results from the compiler
+	 */
+	public ICompilerRequestor getBatchRequestor() {
+		return new ICompilerRequestor() {
+			int lineDelta = 0;
+			public void acceptResult(CompilationResult compilationResult) {
+				if (compilationResult.lineSeparatorPositions != null) {
+					int unitLineCount = compilationResult.lineSeparatorPositions.length;
+					Main.this.lineCount += unitLineCount;
+					this.lineDelta += unitLineCount;
+					if (Main.this.showProgress
+						&& this.lineDelta > 2000) { // in -log mode, dump a dot every 2000 lines compiled
+						Main.this.out.print('.');
+						this.lineDelta = 0;
+					}
+				}
+				if (compilationResult.hasProblems() || compilationResult.hasTasks()) {
+					IProblem[] problems = compilationResult.getAllProblems();
+					int count = problems.length;
+					int localErrorCount = 0;
+					char[] unitSource = compilationResult.compilationUnit.getContents();
+					for (int i = 0; i < count; i++) {
+						if (problems[i] != null) {
+							Main.this.globalProblemsCount++;
+							if (localErrorCount == 0)
+								Main.this.err.println("----------"); //$NON-NLS-1$
+							Main.this.err.print(
+								Main.this.globalProblemsCount
+									+ ". "  //$NON-NLS-1$
+									+ (problems[i].isError()
+										? Main.bind("requestor.error")  //$NON-NLS-1$
+										: Main.bind("requestor.warning")));  //$NON-NLS-1$
+							if (problems[i].isError()) {
+								Main.this.globalErrorsCount++;
+							} else {
+								Main.this.globalWarningsCount++;
+							}
+							Main.this.err.print(" "); //$NON-NLS-1$
+							Main.this.err.print(
+								Main.bind("requestor.in", new String(problems[i].getOriginatingFileName()))); //$NON-NLS-1$
+							try {
+								Main.this.err.println(
+									((DefaultProblem) problems[i]).errorReportSource(unitSource));
+								Main.this.err.println(problems[i].getMessage());
+							} catch (Exception e) {
+								Main.this.err.println(
+									Main.bind("requestor.notRetrieveErrorMessage", problems[i].toString())); //$NON-NLS-1$
+							}
+							Main.this.err.println("----------"); //$NON-NLS-1$
+							if (problems[i].isError())
+								localErrorCount++;
+						}
+					}
+					// exit?
+					if (Main.this.systemExitWhenFinished && !Main.this.proceedOnError && (localErrorCount > 0)) {
+						Main.this.printStats();
+						Main.this.err.flush();
+						Main.this.out.flush();
+						System.exit(-1);
+					}
+				}
+				outputClassFiles(compilationResult);
+			}
+		};
+	}
+	/*
+	 *  Build the set of compilation source units
+	 */
+	public CompilationUnit[] getCompilationUnits()
+		throws InvalidInputException {
+		int fileCount = this.filenames.length;
+		CompilationUnit[] units = new CompilationUnit[fileCount];
+		HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);
 
+		String defaultEncoding = (String) this.options.get(CompilerOptions.OPTION_Encoding);
+		if ("".equals(defaultEncoding)) //$NON-NLS-1$
+			defaultEncoding = null; //$NON-NLS-1$
+
+		for (int i = 0; i < fileCount; i++) {
+			char[] charName = this.filenames[i].toCharArray();
+			if (knownFileNames.get(charName) != null) {
+				throw new InvalidInputException(Main.bind("unit.more", this.filenames[i])); //$NON-NLS-1$
+			} else {
+				knownFileNames.put(charName, charName);
+			}
+			File file = new File(this.filenames[i]);
+			if (!file.exists())
+				throw new InvalidInputException(Main.bind("unit.missing", this.filenames[i])); //$NON-NLS-1$
+			String encoding = this.encodings[i];
+			if (encoding == null)
+				encoding = defaultEncoding;
+			units[i] = new CompilationUnit(null, this.filenames[i], encoding);
+		}
+		return units;
+	}
+	
+	private File[] getFilesFrom(File f, final String extension) {
+		return f.listFiles(new FilenameFilter() {
+			public boolean accept(File dir, String name) {
+				if (name.endsWith(extension)) {
+					return true;
+				}
+				return false;
+			}
+		});
+	}
+	/*
+	 *  Low-level API performing the actual compilation
+	 */
+	public IErrorHandlingPolicy getHandlingPolicy() {
+
+		// passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)	
+		return new IErrorHandlingPolicy() {
+			public boolean proceedOnErrors() {
+				return Main.this.proceedOnError; // stop if there are some errors 
+			}
+			public boolean stopOnFirstError() {
+				return false;
+			}
+		};
+	}
+	public FileSystem getLibraryAccess() {
+
+		String defaultEncoding = (String) this.options.get(CompilerOptions.OPTION_Encoding);
+		if ("".equals(defaultEncoding)) //$NON-NLS-1$
+			defaultEncoding = null; //$NON-NLS-1$	
+		return new FileSystem(this.classpaths, this.filenames, defaultEncoding);
+	}
+	/*
+	 *  Low-level API performing the actual compilation
+	 */
+	public IProblemFactory getProblemFactory() {
+		return new DefaultProblemFactory(Locale.getDefault());
+	}
+	// Dump classfiles onto disk for all compilation units that where successfull.
+
+	public void outputClassFiles(CompilationResult unitResult) {
+
+		if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) {
+			Enumeration classFiles = unitResult.compiledTypes.elements();
+			if (!this.generatePackagesStructure) {
+				while (classFiles.hasMoreElements()) {
+					this.destinationPath = extractDestinationPathFromSourceFile(unitResult);
+					// retrieve the key and the corresponding classfile
+					ClassFile classFile = (ClassFile) classFiles.nextElement();
+					char[] filename = classFile.fileName();
+					int length = filename.length;
+					char[] relativeName = new char[length + 6];
+					System.arraycopy(filename, 0, relativeName, 0, length);
+					System.arraycopy(SUFFIX_class, 0, relativeName, length, 6);
+					CharOperation.replace(relativeName, '/', File.separatorChar);
+					try {
+						ClassFile.writeToDisk(
+							this.generatePackagesStructure,
+							this.destinationPath,
+							new String(relativeName),
+							classFile.getBytes());
+					} catch (IOException e) {
+						String fileName = this.destinationPath + new String(relativeName);
+						e.printStackTrace();
+						this.err.println(Main.bind("output.noClassFileCreated", fileName));  //$NON-NLS-1$
+					}
+					this.exportedClassFilesCounter++;
+				}
+			} else if (this.destinationPath != null) {
+				while (classFiles.hasMoreElements()) {
+					// retrieve the key and the corresponding classfile
+					ClassFile classFile = (ClassFile) classFiles.nextElement();
+					char[] filename = classFile.fileName();
+					int length = filename.length;
+					char[] relativeName = new char[length + 6];
+					System.arraycopy(filename, 0, relativeName, 0, length);
+					System.arraycopy(SUFFIX_class, 0, relativeName, length, 6);
+					CharOperation.replace(relativeName, '/', File.separatorChar);
+					try {
+						ClassFile.writeToDisk(
+							this.generatePackagesStructure,
+							this.destinationPath,
+							new String(relativeName),
+							classFile.getBytes());
+					} catch (IOException e) {
+						String fileName = this.destinationPath + new String(relativeName);
+						e.printStackTrace();
+						this.err.println(Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$
+					}
+					this.exportedClassFilesCounter++;
+				}
+			}
+		}
+	}
+	/*
+	 *  Low-level API performing the actual compilation
+	 */
+	public void performCompilation() throws InvalidInputException {
+
+		this.startTime = System.currentTimeMillis();
+
+		INameEnvironment environment = getLibraryAccess();
+		Compiler batchCompiler =
+			new Compiler(
+				environment,
+				getHandlingPolicy(),
+				this.options,
+				getBatchRequestor(),
+				getProblemFactory());
+		CompilerOptions compilerOptions = batchCompiler.options;
+
+		// set the non-externally configurable options.
+		compilerOptions.setVerboseMode(this.verbose);
+		compilerOptions.produceReferenceInfo(this.produceRefInfo);
+		batchCompiler.compile(getCompilationUnits());
+
+		printStats();
+		
+		// cleanup
+		environment.cleanup();
+	}
+	
+	public void printStats() {
+		if (this.timing) {
+
+			long time = System.currentTimeMillis() - startTime;
+			if (this.lineCount != 0) {
+				this.out.println(
+					Main.bind(
+						"compile.instantTime", 	//$NON-NLS-1$
+						new String[] {
+							String.valueOf(this.lineCount),
+							String.valueOf(time),
+							String.valueOf(((int)(this.lineCount * 10000.0 / time)) / 10.0)}));
+			} else {
+				this.out.println(Main.bind("compile.totalTime", String.valueOf(time))); //$NON-NLS-1$
+			}
+		}
+		if (this.globalProblemsCount > 0) {
+			if (this.globalProblemsCount == 1) {
+				this.err.print(Main.bind("compile.oneProblem")); //$NON-NLS-1$
+			} else {
+				this.err.print(
+					Main.bind("compile.severalProblems", String.valueOf(this.globalProblemsCount))); 	//$NON-NLS-1$
+			}
+			this.err.print(" ("); //$NON-NLS-1$
+			if (this.globalErrorsCount > 0) {
+				if (this.globalErrorsCount == 1) {
+					this.err.print(Main.bind("compile.oneError")); //$NON-NLS-1$
+				} else {
+					this.err.print(
+						Main.bind("compile.severalErrors", String.valueOf(this.globalErrorsCount))); 	//$NON-NLS-1$
+				}
+			}
+			if (this.globalWarningsCount > 0) {
+				if (this.globalErrorsCount > 0) {
+					this.err.print(", "); //$NON-NLS-1$
+				}
+				if (this.globalWarningsCount == 1) {
+					this.err.print(Main.bind("compile.oneWarning")); //$NON-NLS-1$
+				} else {
+					this.err.print(
+						Main.bind("compile.severalWarnings", String.valueOf(this.globalWarningsCount))); 	//$NON-NLS-1$
+				}
+			}
+			this.err.println(")"); //$NON-NLS-1$
+		}
+		if (this.exportedClassFilesCounter != 0
+			&& (this.showProgress || this.timing || this.verbose)) {
+			if (this.exportedClassFilesCounter == 1) {
+				this.out.println(Main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
+			} else {
+				this.out.println(
+					Main.bind(
+						"compile.severalClassFilesGenerated", //$NON-NLS-1$
+						String.valueOf(this.exportedClassFilesCounter)));
+			}
+		}
+	}
+	public void printUsage() {
+		this.out.println(Main.bind("misc.usage"));  //$NON-NLS-1$
+		this.out.flush();
+		this.err.flush();
+	}
+	public void printVersion() {
+		this.out.println(Main.bind("misc.version"));  //$NON-NLS-1$
+		this.out.flush();
+		this.err.flush();
+	}
 }
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
index 0c189e9..1dcf4fa 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -10,8 +10,11 @@
 ###############################################################################
 ### JavaBatchCompiler messages.
 
-### compiler version id
-compiler.version = 0.315_R21x
+### compiler 
+compiler.name = Eclipse Java Compiler
+compiler.version = 0.396
+compiler.copyright = Copyright IBM Corp 2000, 2003. All rights reserved.
+
 ### scanning
 scanning.start = Collecting source files inside {0}
 
@@ -33,7 +36,6 @@
 
 ### configure
 configure.requiresJDK1.2orAbove = Need to use a JVM >= 1.2
-configure.noSourceFile = no source file specified
 configure.duplicateLog = duplicate log specification: {0}
 configure.duplicateRepeat = duplicate repeat specification: {0}
 configure.duplicateCompliance = duplicate compliance setting specification: {0}
@@ -52,7 +54,6 @@
 configure.repetition = repetition must be a positive integer: {0}
 configure.directoryNotExist = directory does not exist: {0}
 configure.IOError = i/o error : unable to retrieve .JAVA files in directory: {0}
-configure.version = Eclipse Java Compiler {0}, Copyright IBM Corp 2000-2002. All rights reserved.
 configure.noClasspath = no classpath defined, using default directory instead
 configure.incorrectClasspath = incorrect classpath: {0}
 configure.invalidexpansionargumentname = expansion argument file {0} doesn't exist or cannot be read
@@ -76,53 +77,85 @@
 output.noClassFileCreated = No .class file created for file named {0} because of an IOException.
 
 ### miscellaneous
-misc.usage = Eclipse Java Compiler {0}\n\
-		Copyright IBM Corp 2000, 2003. All rights reserved.\n\n\
-		Usage: <options> <source files | directories>\n\n\
-		where options include:\n\
-		-help				display this help message\n\
-		-version			only display compiler version number\n\
-		-classpath			<dir 1>;<dir 2>;...;<dir P>\n\
-		-bootclasspath		<dir 1>;<dir 2>;...;<dir P>\n\
-		-d <dir>			destination directory (if omitted, no directory is created)\n\
-		   \t-d none			no classfile is generated\n\
-		-target <ver>		set classfile target (1.1 to 1.4, default is ''1.1'')\n\
-		-1.3 				use 1.3 compliance level (default)\n\
-		-1.4 				use 1.4 compliance level\n\
-		-source <ver>		set source level (1.3 or 1.4, default matches compliance level)\n\
-		-nowarn				no warning (equivalent to ''-warn:none'')\n\
-		-warn: <level>		set warning level (e.g. ''-warn:unusedLocals,deprecation'')\n\
-		\tallDeprecation			 deprecation (including in deprecated code)\n\
-		\tassertIdentifier		 ''assert'' used as identifier\n\
-		\tconstructorName			 method with constructor name \t\t\t\t  (default) \n\
-		\tdeprecation				 deprecation (outside deprecated code) \t\t  (default)\n\
-		\tmaskedCatchBlock		 hidden catch block \t\t\t\t\t\t  (default)\n\
-		\tnls						 string literal lacking non-nls tag //$NON-NLS-<n>$\n\
-		\tpackageDefaultMethod	 attempt to override package-default method   (default)\n\
-		\tunusedArgument			 unused method argument (never read)\n\
-		\tunusedImport			 unused import declaration \t\t\t\t\t  (default)\n\
-		\tunusedLocal				 unused local variable (never read)\n\
-		\tunusedPrivate			 unused private member declaration\n\
-		\tstaticReceiver			 non-static reference to static member \t\t  (default)\n\
-		\tnoEffectAssign			 assignment without effect \t\t\t\t\t  (default)\n\
-		\tsyntheticAccess			 synthetic access for innerclass\n\
-		\tinterfaceNonInherited	 interface non-inherited method compatibility (default)\n\
-		\tnoImplicitStringConversion char[] in String concat\t\t\t\t\t  (default)\n\
-		\ttasks(<tag1>|...|<tagN>) tasks identified by tags inside comments\n\
-		-deprecation		equivalent to ''-warn:deprecation'' (default)\n\
-		-g[:<level>]		debug attributes level (default ''-g:lines,source'')\n\
-			\t-g				all debug info (''-g:lines,vars,source'')\n\
-			\t-g:none			no debug info\n\
-			\t-g:[lines,vars,source]	selective debug info\n\
-		-preserveAllLocals	preserve unused local vars for debug purpose (default is optimize out)\n\
-		-noImportError		no errors for unresolved imports (default is error)\n\
-		-encoding <enc>		specify a different default source encoding format (custom encoding can be specified on\n\
-		\t\t\t\t\ta per file basis by adding suffix ''[<enc>]'' to file/folder names\n\
-		-log <filename>		specify a log file\n\
-		-proceedOnError		keep compiling when error, dumping class files with problem methods (default is off)\n\
-		-verbose			print accessed/processed compilation units\n\
-		-referenceInfo		compute reference info\n\
-		-progress			show progress (only in -log mode)\n\
-		-time				display speed information \n\
-		-noExit				do not call System.exit(n) at end of compilation (n=0 if no error)\n\
-		-repeat <n>			repeat compilation process <n> times (perf analysis)\n
+misc.version = {compiler.name} {compiler.version}, {compiler.copyright}
+misc.usage = {compiler.name} {compiler.version}, {compiler.copyright}\n\
+\ \n\
+\ Usage: <options> <source files | directories>\n\
+\ If directories are specified, then their source contents are compiled.\n\
+\ Possible options are listed below. Options enabled by default are prefixed with ''+''\n\
+\ \n\
+\ Classpath options:\n\
+\    -cp -classpath <directories and zip/jar files separated by ;>\n\
+\                       specify location for application classes and sources\n\
+\    -bootclasspath <directories and zip/jar files separated by ;>\n\
+\                       specify location for system classes\n\
+\    -d <dir>           destination directory (if omitted, no directory is created)\n\
+\    -d none            generate no .class files\n\
+\    -encoding <enc>    specify custom encoding for all sources. Each file/directory can override it\n\
+\                       when suffixed with ''[''<enc>'']'' (e.g. X.java[utf8])\n\
+\ \n\
+\ Compliance options:\n\
+\    -1.3               use 1.3 compliance level (implicit -source 1.3 -target 1.1)\n\
+\    -1.4             + use 1.4 compliance level (implicit -source 1.3 -target 1.2)\n\
+\    -source <version>  set source level (1.3 or 1.4)\n\
+\    -target <version>  set classfile target (1.1 to 1.4)\n\
+\ \n\
+\ Warning options:\n\
+\    -deprecation     + deprecation outside deprecated code\n\
+\    -nowarn            disable all warnings\n\
+\    -warn:none         disable all warnings\n\
+\    -warn:<warnings separated by ,>    enable exactly the listed warnings\n\
+\    -warn:+<warnings separated by ,>   enable additional warnings\n\
+\    -warn:-<warnings separated by ,>   disable specific warnings\n\
+\      allDeprecation       deprecation including inside deprecated code\n\
+\      allJavadoc           invalid or missing javadoc\n\
+\      assertIdentifier   + ''assert'' used as identifier\n\
+\      charConcat         + char[] in String concat\n\
+\      conditionAssign      possible accidental boolean assignment\n\
+\      constructorName    + method with constructor name\n\
+\      deprecation        + deprecation outside deprecated code\n\
+\      emptyBlock           undocumented empty block\n\
+\      fieldHiding          field hiding another variable\n\
+\      finally            + finally block not completing normally\n\
+\      indirectStatic       indirect reference to static member\n\
+\      intfNonInherited   + interface non-inherited method compatibility\n\
+\      javadoc              invalid javadoc\n\
+\      localHiding          local variable hiding another variable\n\
+\      maskedCatchBlock   + hidden catch block\n\
+\      nls                  string literal lacking non-nls tag //$NON-NLS-<n>$\n\
+\      noEffectAssign     + assignment without effect\n\
+\      pkgDefaultMethod   + attempt to override package-default method\n\
+\      semicolon            superfluous semicolon\n\
+\      unqualifiedField     unqualified reference to field\n\
+\      unusedImport       + unused import declaration\n\
+\      unusedLocal          unread local variable\n\
+\      unusedPrivate        unused private member declaration\n\
+\      unusedThrown         unused declared thrown exception\n\
+\      uselessTypeCheck     unnecessary cast/instanceof operation\n\
+\      specialParamHiding   constructor or setter parameter hiding another field\n\
+\      staticReceiver     + non-static reference to static member\n\
+\      syntheticAccess      synthetic access for innerclass\n\
+\      tasks(<tags separated by |>) tasks identified by tags inside comments\n\
+\ \n\
+\ Debug options:\n\
+\    -g[:lines,vars,source] custom debug info\n\
+\    -g:lines,source  + both lines table and source debug info\n\
+\    -g                 all debug info\n\
+\    -g:none            no debug info\n\
+\    -preserveAllLocals preserve unused local vars for debug purpose\n\
+\ \n\
+\ Advanced options:\n\
+\    -log <file>        log to a file\n\
+\    -proceedOnError    do not stop at first error, dumping class files with problem methods\n\
+\    -verbose           enable verbose output\n\
+\    -referenceInfo     compute reference info\n\
+\    -progress          show progress (only in -log mode)\n\
+\    -time              display speed information \n\
+\    -noExit            do not call System.exit(n) at end of compilation (n==0 if no error)\n\
+\    -repeat <n>        repeat compilation process <n> times for perf analysis\n\
+\    @<file>            read command line arguments from file\n\
+\ \n\
+\    -? -help           print this help message\n\
+\    -v -version        print compiler version\n\
+\    -showversion       print compiler version and continue\n
+
diff --git a/org.eclipse.jdt.core/build.properties b/org.eclipse.jdt.core/build.properties
index 0016ed5..a3f5c3f 100644
--- a/org.eclipse.jdt.core/build.properties
+++ b/org.eclipse.jdt.core/build.properties
@@ -29,5 +29,5 @@
                      search/
 source.jdtCompilerAdapter.jar = antadapter/
 jars.compile.order=jdtcore.jar,jdtCompilerAdapter.jar
-jars.extra.classpath=../org.apache.ant/ant.jar
+jars.extra.classpath=platform:/plugin/org.apache.ant/lib/ant.jar
 src.includes=about.html,schema/
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/buildnotes_jdt-core.html b/org.eclipse.jdt.core/buildnotes_jdt-core.html
index decc540..a2cc5f9 100644
--- a/org.eclipse.jdt.core/buildnotes_jdt-core.html
+++ b/org.eclipse.jdt.core/buildnotes_jdt-core.html
@@ -15,7 +15,7 @@
 <table border=0 cellspacing=5 cellpadding=2 width="100%" >
   <tr> 
     <td align=left width="72%">
-      <font face="Verdana, Arial, Helvetica" size="+3"><b>jdt core - build notes 2.1 stream</b></font>
+      <font face="Verdana, Arial, Helvetica" size="+3"><b>jdt core - build notes 3.0 stream</b></font>
       <br><font face="Arial, Helvetica, sans-serif" size="-2" color="#8080ff">java development tooling core</font></td>
   </tr>
 	<tr><td>&nbsp;</td></tr>
@@ -24,19 +24,2344 @@
 	  <font face="Arial, Helvetica, sans-serif" size="-1">
 	  Here are the build notes for the Eclipse JDT/Core plug-in project 
 	  <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/jdt-core-home/main.html"><b>org.eclipse.jdt.core</b></a>, 
-	  describing <a href="http://bugs.eclipse.org/bugs" target=new>bug</a> resolution and substantial changes in the <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=R2_1_maintenance"><b>R2_1_maintenance</b></a> branch. 
-	  This present document covers all changes since release 2.0 (previous changes, i.e. up to release 2.0, can be found
-	  in <a href="http://dev.eclipse.org/viewcvs/index.cgi/~checkout~/org.eclipse.jdt.core/notes/R20_buildnotes_jdt-core.html?rev=1.2&content-type=text/plain&only_with_tag=R2_1_maintenance">build notes R2.0</a>).
+	  describing <a href="http://bugs.eclipse.org/bugs" target=new>bug</a> resolution and substantial changes in the <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core"><b>HEAD</b></a> branch. 
+	  This present document covers all changes since Release 2.1 (also see a summary of <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/API_changes.html">API changes</a>).
+	  Older changes which occurred up to Release 2.1 can be found in 
+	  <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/R21_buildnotes_jdt-core.html">build notes R2.1</a>.
 	  </font>
 	</td>
   </tr>
 </table>
 
+<a name="v_396"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 2.1.1 Build - 16th May 2003
-<br>Project org.eclipse.jdt.core v_315_R21x
+Eclipse SDK 3.0M6 Build - 18th December 2003 - 3.0 MILESTONE-6
+<br>Project org.eclipse.jdt.core v_396
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_396">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=49081">49081</a>
+JDT is no more using the tab character by default for indentation 
+
+<a name="v_395"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 17th December 2003
+<br>Project org.eclipse.jdt.core v_395
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_395">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48706">48706</a>
+NPE in move refactoring 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48965">48965</a>
+Javadoc problem preference settings: Use 'include' instead of 'ignore'
+
+<a name="v_394"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 16th December 2003
+<br>Project org.eclipse.jdt.core v_394
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_394">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47209">47209</a>
+Javadoc: Type references are not found in @see tag inside a method reference
+
+<a name="v_393"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 16th December 2003
+<br>Project org.eclipse.jdt.core v_393
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_393">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48818">48818</a>
+NPE in delta processor 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48711">48711</a>
+javadoc-warning if derived exception in @throws clause
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46040">46040</a>
+NPE in Eclipse console 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48725">48725</a>
+Cannot search for local vars in jars. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48749">48749</a>
+[Compiler] deprecation check in initializer fooled by trailing deprecated field decl
+
+
+<a name="v_392"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 15th December 2003
+<br>Project org.eclipse.jdt.core v_392
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_392">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Added option to avoid reporting a warning when overriding a deprecated method. By default, such
+warnings are no longer reported.
+<pre>
+ * COMPILER / Reporting Deprecation When Overriding Deprecated Method
+ *    When enabled, the compiler will signal the declaration of a method overriding a deprecated one.
+ *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.deprecation".
+ *     - option id:        "org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"
+ *     - possible values:   { "enabled", "disabled" }
+ *     - default:           "disabled"
+</pre>	 
+<li>Compiler options to signal problems with javadoc comments have been improved. User can now decide to report
+independently problems on invalid tags (syntax and references), missing tags and missing comments.
+Invalid references, missing tags or missing comments problem can be now ignored below a specific visibility level.
+Finally, user will also have the possibility to ignore missing tags and missing comments on overriding methods
+(assuming that complete Javadoc comments is done in superclass or interface declaration).
+<br>
+Here's the complete list of these options:
+<pre>
+	 * COMPILER / Reporting Invalid Javadoc Comment
+	 *    This is the generic control for the severity of Javadoc problems.
+	 *    When enabled, the compiler will issue an error or a warning for a problem in Javadoc.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadoc"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 *
+	 * COMPILER / Visibility Level For Invalid Javadoc Tags
+	 *    Set the minimum visibility level for Javadoc tag problems. Below this level problems will be ignored.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility"
+	 *     - possible values:   { "public", "protected", "default", "private" }
+	 *     - default:           "private"
+	 * 
+	 * COMPILER / Reporting Invalid Javadoc Tags
+	 *    When enabled, the compiler will signal unbound or unexpected reference tags in Javadoc.
+	 *    A 'throws' tag referencing an undeclared exception would be considered as unexpected.
+	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility".
+	 *    <br>
+	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.invalidJavadoc".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTags"
+	 *     - possible values:   { "disabled", "enabled" }
+	 *     - default:           "enabled"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Tags
+	 *    This is the generic control for the severity of Javadoc missing tag problems.
+	 *    When enabled, the compiler will issue an error or a warning when tags are missing in Javadoc comments.
+	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility".
+	 *    <br>
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTags"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
+	 * COMPILER / Visibility Level For Missing Javadoc Tags
+	 *    Set the minimum visibility level for Javadoc missing tag problems. Below this level problems will be ignored.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility"
+	 *     - possible values:   { "public", "protected", "default", "private" }
+	 *     - default:           "private"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Tags on Overriding Methods
+	 *    Specify whether the compiler will verify overriding methods in order to report Javadoc missing tag problems.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "enabled"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Comments
+	 *    This is the generic control for the severity of missing Javadoc comment problems.
+	 *    When enabled, the compiler will issue an error or a warning when Javadoc comments are missing.
+	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the expected Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility".
+	 *    <br>
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocComments"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
+	 * COMPILER / Visibility Level For Missing Javadoc Comments
+	 *    Set the minimum visibility level for missing Javadoc problems. Below this level problems will be ignored.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility"
+	 *     - possible values:   { "public", "protected", "default", "private" }
+	 *     - default:           "public"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Comments on Overriding Methods
+	 *    Specify whether the compiler will verify overriding methods in order to report missing Javadoc comment problems.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "enabled"
+	 * 
+</pre>
+Note that backward compatibility with previous options IDs: <code>"org.eclipse.jdt.core.compiler.problem.missingJavadoc"</code>
+will be supported until 3.0M7 build and removed after.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47214">47214</a>
+Cannot open declaration on a selected method of an anonymous class 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47795">47795</a>
+NPE selecting method in anonymous 2 level deep 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48335">48335</a>
+[Compiler] Need option to not report deprecation in override scenarii
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48523">48523</a>
+@throws reference incorrectly warned as not declared
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47940">47940</a>
+Unable to control level  of JavaDoc errors
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47319">47319</a>
+Compiler warns on missing Javadoc tags for private methods.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46976">46976</a>
+Do not warn about 'Missing Javadoc'  for overriding methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46854">46854</a>
+[DCR] Javadoc configuration setting needs more flexibility
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48617">48617</a>
+Error range for unresolved names in qualified references
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48333">48333</a>
+[Compiler] Implicit deprecation isn't propagated to anonymous type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46084">46084</a>
+ArrayIndexOutOfBoundsException in compiler after feeding with non-real java code 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43354">43354</a>
+CodeAssist relevance should privilege package completion over type name 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48422">48422</a>
+Calling isStructureKnown() on ILocalVaraible throws JavaModelExceptions 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48261">48261</a>
+Search does not show results 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47213">47213</a>
+Inefficient recursion while initializing classpath container 
+
+<a name="v_391"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 10th December 2003
+<br>Project org.eclipse.jdt.core v_391
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_391">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>We reverted back the behavior when using the class literal. See bugs <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=37565">37565</a> and
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48086">48086</a>. As long as javac doesn't clarify this case, we keep
+the old behavior.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48086">48086</a>
+Compiler does not resolve references in static init blocks correctly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48353">48353</a>
+Indexes deleted on shutdown 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42579">42579</a>
+Eclipse allows setting a source folder's parent as output folder, which wipes out source code
+
+<a name="v_390"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 9th December 2003
+<br>Project org.eclipse.jdt.core v_390
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_390">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>The classpath validation rules now allow an excluded directory to be used as an output location. 
+Remember that a source folder can be associated with exclusion rules so as to eliminate portions of the
+source tree. Nested source/library entries were already allowed given proper exclusion rules were specified,
+now we also enable nesting an output folder as well under the same restrictions.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47338">47338</a>
+CCE in CompletionParser
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45589">45589</a>
+Too many Util classes in JDTCore 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39539">39539</a>
+Cannot select excluded directory as output folder for class files
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48070">48070</a>
+[CodeAssist] ArrayIndexOutOfBoundsException in AssistParster
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48167">48167</a>
+Indentation/line wrapping problems with array initializers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32022">32022</a>
+Indirect static proposal: Wrong compiler positions
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48141">48141</a>
+Formatter: Java Conventions/WS/Expressions/Operators 
+<br><!-- a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48143">48143</a>
+Formatter: Line Wrapping/Conditionals
+<br --><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45157">45157</a>
+Source Formatter: Clear all Blank lines needs to have the ability to set a number of lines to keep.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44673">44673</a>
+Formatting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38523">38523</a>
+so add "Insert new line after each parameter if line is too long" checkbox to Preferences > Java > Code Formatter > New Lines
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34897">34897</a>
+Code Formatter feature request
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46937">46937</a>
+[Compiler] Marking a field deprecated still report deprecated usage
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47989">47989</a>
+Exception when searching for IPackageFragment "java.util.zip"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47997">47997</a>
+No empty line after opening brace [formatter]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=48064">48064</a>
+Javadoc: NPE during build process
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44815">44815</a>
+Continuation indent for array initializer should be customizable
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44813">44813</a>
+Option "Insert new line before an open brace" should work also for array initializers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43212">43212</a>
+catch variable not recognized by code-completion 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46060">46060</a>
+regression - content assist fails to present proposal 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47918">47918</a>
+New code Formatter 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47968">47968</a>
+Cannot find @see references in Class javadoc comment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47909">47909</a>
+Javadoc: NPE while searching a constructor references in jdt-core
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47986">47986</a>
+Formatting of 'for' initializers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47976">47976</a>
+Implementation of IField.getConstant() fails for some constants
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47886">47886</a>
+[Compiler] ACC_SUPER bit sets for interfaces
+
+<a name="v_389"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 2nd December 2003
+<br>Project org.eclipse.jdt.core v_389
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_389">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Spec and implementation for <code>ITypeBinding.getBinaryName()</code> was changed to be '.' separated:
+<pre>
+ /**
+ * Returns the binary name of this type binding.
+ * The binary name of a class is defined in the Java Language 
+ * Specification 2nd edition, section 13.1.
+ *
+ * Note that in some cases, the binary name may be unavailable.
+ * This may happen, for example, for a local type declared in 
+ * unreachable code.
+ *
+ * @return the binary name of this type, or null 
+ * if the binary name is unknown
+ * @since 3.0
+ */
+public String getBinaryName();
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47881">47881</a>
+[Compiler] x && false evaluates to "true"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47802">47802</a>
+New Code Formatter: NEXT_PER_LINE_SPLIT
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47811">47811</a>
+New Code Formatter: doesn't handle several classes per CU
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47801">47801</a>
+New Code Formatter: INSERT_SPACE_AFTER_PREFIX_OPERATOR
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47800">47800</a>
+New Code Formatter: BINARY_EXPRESSION_ALIGNMENT
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47799">47799</a>
+New Code Formatter: PUT_EMPTY_STATEMENT_ON_NEW_LINE
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47776">47776</a>
+java.lang.VerifyError / Illegal target of jump or branch compiling with 3.0 M5
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47341">47341</a>
+Javadoc problem for @see to protected method
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47339">47339</a>
+Javadoc problem while using @see tag
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47132">47132</a>
+Javadoc for method in anonymous type should not be mark as missing
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47215">47215</a>
+Javadoc: type reference in @see tag ignore the following text
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46761">46761</a>
+Search for references: misses match in Javadoc
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46675">46675</a>
+[Compiler] NullPointerException with ? operator
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35220">35220</a>
+CodeAssist - method of anonymous type should not be proposed
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47631">47631</a>
+PerThreadObject (JavaModelManager.deltaState) leaks Threads.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46470">46470</a>
+Wrong completion after a switch
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35232">35232</a>
+CodeAssist - wrong completion for static method in anonymous type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47401">47401</a>
+Wrong code assist proposals in anonymous class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47443">47443</a>
+All projects touched on startup
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44493">44493</a>
+Improve formatting of throws clauses
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44765">44765</a>
+New formatter not properly formatting long method invocation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44653">44653</a>
+// $NON-NLS-1$ comments not kept on same line of the string while formatting
+<!-- br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44642">44642</a>
+New formatter should better handle cascaded message -->
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46699">46699</a>
+IBinding.isSynthetic() returns false for compiler-generated constructor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47415">47415</a>
+[Search] package references confused with multiple fragments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38679">38679</a>
+Search for class ref shows local class containing a match on an import [search]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47049">47049</a>
+[Builder] Build output folder not getting flushed because files are not marked as derived
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46613">46613</a>
+AST nodes and string buffers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47396">47396</a>
+JAVA AST Creation failure
+
+<a name="v_388"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M6 Build - 25th November 2003
+<br>Project org.eclipse.jdt.core v_388
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_388">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47082">47082</a>
+[Compiler] Problem with final variable initialization
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47180">47180</a>
+Merge different type declarations into one class
+
+
+<a name="v_387"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 21st November 2003 - 3.0 MILESTONE-5
+<br>Project org.eclipse.jdt.core v_387
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_387">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44397">44397</a>
+Search doesn't find references to local types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46571">46571</a>
+Searching for all occurrences for method declarated in local types doesn't wor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46943">46943</a>
+refactoring: encapsulate field of local type: references from enclosing type are not replaced by setter 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47180">47180</a>
+NPE in Delta Processor 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46788">46788</a>
+Export scripts: shouldn't use variable name version
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47160">47160</a>
+ArrayIndexOutOfBoundsException from CodeSnippetParser
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47177">47177</a>
+ClassCastException during hover
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47079">47079</a>
+[Builder] suspicious side-effects during incremental compile
+
+<a name="v_386"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 20th November 2003
+<br>Project org.eclipse.jdt.core v_386
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_386">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Removed APIs that create an <code>ICompilationUnit</code> handle given a <code>WorkingCopyOwner</code>
+	 as these can be replaced with <code>ICompilationUnit.findWorkingCopy(WorkingCopyOwner)</code>:
+	 <ul>
+	 <li><code>IPackageFragment.getCompilationUnit(String, WorkingCopyOwner)</code></li>
+	 <li><code>JavaCore.create(IFile, WorkingCopyOwner)</code></li>
+	 <li><code>JavaCore.create(IResource, WorkingCopyOwner)</code></li>
+	 <li><code>JavaCore.createCompilationUnitFrom(IFile, WorkingCopyOwner)</code></li>
+	 <li><code>IDOMCompilationUnit.getCompilationUnit(IPackageFragment, WorkingCopyOwner)</code></li>
+	 </ul>
+	 <br>
+</li>
+<li>Added API on <code>ICompilationUnit</code> to find an existing working copy given a working
+	 copy owner (it replaces <code>IWorkingCopy.findSharedWorkingCopy(IBufferFactory)</code>):
+<pre>
+/**
+ * Finds the working copy for this compilation unit, given a <code>WorkingCopyOwner</code>. 
+ * If no working copy has been created for this compilation unit associated with this
+ * working copy owner, returns <code>null</code>.
+ *
+ * Users of this method must not destroy the resulting working copy. 
+ * 
+ * @param owner the given <code>WorkingCopyOwner</code>
+ * @return the found working copy for this compilation unit, <code>null</code> if none
+ * @see WorkingCopyOwner
+ * @since 3.0
+ */
+ICompilationUnit findWorkingCopy(WorkingCopyOwner owner);
+</pre>
+</li>
+<li>Added API on <code>IClassFile</code> to create a working copy on a class file (it replaces 
+	 <code>IClassFile.getWorkingCopy(IProgressMonitor, IBufferFactory)</code>):
+<pre>
+/**
+ * Returns a working copy on the source associated with this class file using the given 
+ * owner to create the buffer, or <code>null</code> if there is no source associated
+ * with the class file.
+ * 
+ * The buffer will be automatically initialized with the source of the class file
+ * upon creation.
+ * 
+ * The only valid operations on this working copy are <code>getBuffer()</code> or <code>getPrimary()</code>.
+ *
+ * @param owner the owner that creates a buffer that is used to get the content of the working copy
+ *                 or <code>null</code> if the primary owner should be used
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ *                 or <code>null</code> if no progress should be reported 
+ * @return a  a working copy on the source associated with this class file
+ * @exception JavaModelException if the source of this class file can
+ *   not be determined. Reasons include:
+ *   - This class file does not exist (ELEMENT_DOES_NOT_EXIST)
+ * @since 3.0
+ */
+ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
+</pre>
+</li>
+<li>Added API on <code>ITypeBinding</code> to get the binary name of a type binding:
+<pre>
+/**
+ * Returns the binary name (as defined in the Java Language 
+ * Specification Chapter 13 Section 1) of this type binding.
+ * It is however slash ('/') separated instead of dot ('.') separated as said
+ * in the specification.
+ * Returns <code>null</code> if the type is defined in code that is unreachable.
+ *
+ * @return the binary name of this type or <code>null</code> if this type is unreachable
+ */
+String getBinaryName();
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46012">46012</a>
+IllegalArgumentException in StringLiteral
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46769">46769</a>
+NPE in PatternLocator.qualifiedSourceName
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=47074">47074</a>
+inability to detect invalid cast between interfaces
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46057">46057</a>
+need mechanism for retrieving the name of anonymous and local classes 
+
+<a name="v_385"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 19th November 2003
+<br>Project org.eclipse.jdt.core v_385
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_385">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46964">46964</a>
+Can not set Javadoc compiler setting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46901">46901</a>
+Strange compile error in javadoc
+
+<a name="v_384"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 19th November 2003
+<br>Project org.eclipse.jdt.core v_384
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_384">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added API on <code>ICompilationUnit</code> to query whether the working copy's resource has changed 
+	 (it replaces <code>IWorkingCopy.isBasedOn(IResource)</code>):
+<pre>
+/**
+ * Returns whether the resource of this working copy has changed since the
+ * inception of this working copy.
+ * Returns <code>false</code> if this compilation unit is not in working copy mode.
+ * 
+ * @return whether the resource has changed
+ * @since 3.0
+ */
+public boolean hasResourceChanged();
+</pre>
+</li>
+<li>Added APIs on <code>IType</code> to create hierarchies using <code>ICompilationUnits</code> instead of
+     <code>IWorkingCopies</code>:
+<pre>
+/**
+ * Creates and returns a type hierarchy for this type containing
+ * this type and all of its supertypes, considering types in the given 
+ * working copies. In other words, the list of working copies will take 
+ * precedence over their original compilation units in the workspace.
+ *
+ * Note that passing an empty working copy will be as if the original compilation
+ * unit had been deleted.
+ *
+ * @param workingCopies the working copies that take precedence over their original compilation units
+ * @param monitor the given progress monitor
+ * @return a type hierarchy for this type containing this type and all of its supertypes
+ * @exception JavaModelException if this element does not exist or if an
+ *		exception occurs while accessing its corresponding resource.
+ * @since 3.0
+ */
+ITypeHierarchy newSupertypeHierarchy(ICompilationUnit[] workingCopies, IProgressMonitor monitor) throws JavaModelException;
+
+/**
+ * Creates and returns a type hierarchy for this type containing
+ * this type, all of its supertypes, and all its subtypes in the workspace, 
+ * considering types in the given working copies. In other words, the list of working 
+ * copies that will take precedence over their original compilation units in the workspace.
+ * 
+ * Note that passing an empty working copy will be as if the original compilation
+ * unit had been deleted.
+ *
+ * @param workingCopies the working copies that take precedence over their original compilation units
+ * @param monitor the given progress monitor
+ * @return a type hierarchy for this type containing
+ * this type, all of its supertypes, and all its subtypes in the workspace
+ * @exception JavaModelException if this element does not exist or if an
+ *		exception occurs while accessing its corresponding resource.
+ * @since 3.0
+ */
+ITypeHierarchy newTypeHierarchy(ICompilationUnit[] workingCopies, IProgressMonitor monitor) throws JavaModelException;
+</pre>
+<li>Added API on <code>SearchEngine</code> to create a search engine using 
+	 <code>ICompilationUnits</code> instead of <code>IWorkingCopies</code>:
+<pre>
+/**
+ * Creates a new search engine with a list of working copies that will take precedence over 
+ * their original compilation units in the subsequent search operations.
+ *
+ * Note that passing an empty working copy will be as if the original compilation
+ * unit had been deleted.
+ *
+ * Since 3.0 the given working copies take precedence over primary working copies (if any).
+ * 
+ * @param workingCopies the working copies that take precedence over their original compilation units
+ * @since 3.0
+ */
+public SearchEngine(ICompilationUnit[] workingCopies) {...}
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+
+<a name="v_383"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 18th November 2003
+<br>Project org.eclipse.jdt.core v_383
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_383">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>To avoid confusion with annotations introduced in JDK 1.5 grammar, all internal references to "annotation" (added to handle Javadoc comments) 
+got renamed into "Javadoc". As a consequence of this is that IDs for optional Javadoc problems have been updated accordingly:
+<pre>
+	 * COMPILER / Reporting Invalid Javadoc Comment
+	 *    When enabled, the compiler will issue an error or a warning when a javadoc comment is inconsistent,
+	 *    misses a tag entry or contains invalid references.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadoc"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * COMPILER / Reporting Missing Javadoc Comment
+	 *    When enabled, the compiler will signal cases where public class, interface, method, constructor or field
+	 *    (considered as part of the API) has no javadoc comment.
+	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.invalidJavadoc".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadoc"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "disabled"
+</pre>
+Note that backward compatibility with previous options IDs: <code>"org.eclipse.jdt.core.compiler.problem.invalidAnnotation"</code> and <code>"org.eclipse.jdt.core.compiler.problem.missingAnnotation"</code>
+will be supported until 3.0M6 build and removed after.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46717">46717</a>
+The code formatter does not insert a new line before /** Javadoc
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45958">45958</a>
+Compiler wrongly complains against valid @see constructor reference
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45112">45112</a>
+Use Javadoc instead of Annotation for comment compiler parsing
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46052">46052</a>
+result of ITypeHierarchy.getAllSuperTypes() does not include Object 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46192">46192</a>
+ILocalVariable.exists() always returns false 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=14103">14103</a>
+[Builder] Too many dependents found when incrementally recompiling
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39601">39601</a>
+[DOM/AST] clarify documentation of source ranges
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39739">39739</a>
+[DOM/AST] VariableDeclarationStatements aren't full statements
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46690">46690</a>
+Code formatter always inserts space after comma in multiple locals or field declarations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46689">46689</a>
+Code formatter always inserts a space in front of the '-' unary operator
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46686">46686</a>
+Code formatter doesn't indent properly statements following a switch statement
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46356">46356</a>
+[Builder] simple/qualified names list for indicting dependents should be hashed collections
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46612">46612</a>
+[DOM/AST] BodyDeclaration should provide a method getModifiers
+
+<a name="v_382"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 10th November 2003
+<br>Project org.eclipse.jdt.core v_382
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_382">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46276">46276</a>
+Search for package declarations incorrectly finds matches in clone project
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46099">46099</a>
+Batch compiler doesn't print stats if errors and not proceeding on errors
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40950">40950</a>
+[infrastructure] NPE from indexer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46150">46150</a>
+formatter failed to format
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46013">46013</a>
+IBinding.getKey() for local shouldn't return null 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46033">46033</a>
+New formatter not formatting nested constructor/methods properly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=46093">46093</a>
+[Builder] Unoptimal pre-check for not writing class files
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45847">45847</a>
+[Builder] Reading build state is slow
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45982">45982</a>
+Array out of bounds error while editing Java file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41611">41611</a>
+CreateCompilationUnitOperation.executeOperation() should probably force creation more agressively 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45113">45113</a>
+No hierarchy refresh when on region 
+
+
+<a name="v_381"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 4th November 2003
+<br>Project org.eclipse.jdt.core v_381
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_381">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45968">45968</a>
+[new formatter] Formatter introduces empty lines inside line comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44450">44450</a>
+Strange name range for anonymous classes. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43139">43139</a>
+Delete member in Outliner not working 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45944">45944</a>
+Stack trace attempting to find markers on a closed project 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44884">44884</a>
+Wrong list displayed while code completion 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45661">45661</a>
+Search for references of default package fails
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45671">45671</a>
+Need source range and getTypeSignature() for local variables 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45575">45575</a>
+Failure in nightly build of formatter tests (test325)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45783">45783</a>
+NPE in MatchLocator
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22073">22073</a>
+Each "format" adds one more level of indentation.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23709">23709</a>
+for (/*comment*/; causes indentation to misbehave 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27249">27249</a>
+incorrect formatting of empty array initialization blocks 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29473">29473</a>
+wrong formatting of if...try... catch... else 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45786">45786</a>
+No selection on method declaration in field initializer 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45721">45721</a>
+Getting wrong deltas 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45674">45674</a>
+Compiler should allow compound assignment to final in unreachable code
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43984">43984</a>
+NPE in background search
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45707">45707</a>
+Autobuild does not kick in when using classpath containers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45655">45655</a>
+exception while editing java file 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42287">42287</a>
+Should consider qualified name token positions
+
+<a name="v_380"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 28th October 2003
+<br>Project org.eclipse.jdt.core v_380
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_380">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Search is now able to find local variable references and declarations. In order to trigger such a search, the search engine must
+	be fed with an <code>ILocalVariable</code> element. Searching a local variable by its name is not supported.
+</li>
+<li>Search is now finding references in Javadoc comments. Found references are method parameters declared in <code>@param</code> tags, 
+	types of exceptions declared in <code>@throws</code>/<code>@exception</code> tags and all instance variables, methods, types or 
+	packages declared in <code>@see</code> tags.
+	<br>Note that only valid references in Javadoc comments will be reported during search. In order to ensure the integrity of your Javadoc comments,
+	you may want to enable the compiler check for Javadoc (Preferences>Java>Compiler>Style>Problem in Javadoc tags).
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45641">45641</a>
+CCE when using declarations view 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45596">45596</a>
+Wrongly complains about missing parameter javadoc entry in anonymous class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45592">45592</a>
+NPE while searching a method references in jdt-core
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45520">45520</a>
+Potential NPE
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45518">45518</a>
+Search has to find references put in javadoc comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45436">45436</a>
+Javadoc warnings: wrong errors in AST
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45198">45198</a>
+NPE from AnnotationParser
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45459">45459</a>
+JDT compiler more restrictive than javac
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35899">35899</a>
+"hierarchy of type ... inconsistent" error message wrong
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43967">43967</a>
+Search for references on local variable finds all occurances of variables of that type not just that variable. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37509">37509</a>
+Open Declaration opens class declaration for local variables 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45433">45433</a>
+Bug7 (and counting ;-): hundretAssignmentsToFinalVariable()
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45357">45357</a>
+Compiler-Bug: "The local variable oResult may not have been initialized".txt
+
+<a name="v_379"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 21st October 2003
+<br>Project org.eclipse.jdt.core v_379
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_379">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Compiler options for controlling the severity of problems for invalid imports or unreachable code got discontinued. Indeed, allowing this kind of problems to be ignored
+or treated as a warning would violate the language spec. As a consequence, <code>JavaCore#COMPILER_PB_INVALID_IMPORT</code> and
+<code>JavaCore#COMPILER_PB_UNREACHABLE_CODE</code> got deprecated, 
+further attempts to set these preferences are now ignored and import problems or unreachable code are always reported as errors.
+<li> The warning level of the batch compiler can now be configured more easily using <code>-warn:+...</code> or <code>-warn:-...</code> command line
+argument (as opposed to only existing <code>-warn:...</code> command line argument). 
+<code>-warn:+...</code> will not override the default warning level, but simply enable
+a few more specific warnings. Similarily, <code>-warn:-...</code> will only disable specific warnings.
+<br>Note, by default the batch compiler is reporting the following warnings:
+	<ul>
+	<li>'assert' used as identifier</li>
+	<li>char[] in String concat</li>
+	<li>method with constructor name</li>
+	<li>deprecation outside deprecated code</li>
+	<li>finally block not completing normally</li>
+	<li>interface non-inherited method compatibility</li>
+	<li>hidden catch block</li>
+	<li>assignment without effect</li>
+	<li>attempt to override package-default method</li>
+	<li>unused import declaration</li>
+	<li>non-static reference to static member</li>
+	</ul>
+</li>
+<li>Code select (i.e. <code>ICodeAssit.codeSelect(...)</code>) now returns an <code>ILocalVariable</code>
+     element when a local variable or an argument is selected. 
+     <br>Note that <code>ILocalVariable</code>s are pseudo-elements:
+     they are not part of the Java model (<code>exists()</code> always returns <code>false</code>), 
+     they are not returned when asking for the children of a method, and there is no other way to create such
+     an element. One can only ask for the source range (<code>ISourceReference.getSourceRange()</code>) or
+     for the name range (<code>ILocalVariable.getNameRange()</code>) of the local variable.
+     <br>Searching a local variable is not yet implemented, but it is on the plan.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35389">35389</a>
+Compiler settings can violate JLS [build path]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44869">44869</a>
+Search: no refs found to overridden method in binary subclass
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45110">45110</a>
+No constant for '..compiler.problem.missingAnnotation'
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45100">45100</a>
+[formatter] test144 fails
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45036">45036</a>
+[formatter] New formatter fails formatting multiple field declarations using K_CLASSBODY_DECLARATION kind
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45037">45037</a>
+[formatter] New formatter doesn't insert a new line before the while in a do/while
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=45014">45014</a>
+Formatter misplaces semicolon
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44757">44757</a>
+New code formatter does not format switch statements correctly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44647">44647</a>
+NPE code completion
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43754">43754</a>
+How to position this comment?
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44839">44839</a>
+New formater fails with out of memory error
+
+<a name="v_378"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M5 Build - 15th October 2003
+<br>Project org.eclipse.jdt.core v_378
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_378">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Removed dependency on Xerces.
+</li>
+<li> Remove deprecated previously added API <code>IJavaProject#forceClasspathReload(IProgressMonitor)</code>
+(see comment of <a href="#v_368">v_368</a> drop below).
+</li>
+<li>Added optional compiler problem to signal problems with javadoc annotation.
+<pre>
+	 * COMPILER / Reporting Invalid Javadoc Annotation
+	 *    When enabled, the compiler will issue an error or a warning when a javadoc annotation is inconsistent,
+	 *    misses a tag entry or contains invalid references.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidAnnotation"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * COMPILER / Reporting Missing Javadoc Annotation
+	 *    When enabled, the compiler will signal cases where public class, interface, method, constructor or field
+	 *    (considered as part of the API) has no javadoc annotation.
+	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.invalidAnnotation".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingAnnotation"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "disabled"
+	 * 
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44715">44715</a>
+NullPointerException compiling Java file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44697">44697</a>
+Bug when i search reference of 'String' in 3.0M4
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38091">38091</a>
+DCR - Generate warnings for JavaDoc missing entries
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44637">44637</a>
+NPE in Initializer.getPrimaryElement() 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42762">42762</a>
+Compiler tests should run both in 1.3 and 1.4 mode 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44580">44580</a>
+No outline when unit name is not valid
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44651">44651</a>
+Wrong formatting of multiple local variables declarations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44643">44643</a>
+Remove dependancy to xerces
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44662">44662</a>
+Should not validate unit/classfile handles upon creation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44400">44400</a>
+Unnecessary cast not being picked up
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44143">44143</a>
+[JSR202] Remove usage of jsr bytecodes in 1.5 mode
+
+<a name="v_377"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 9th October 2003 - 3.0 MILESTONE-4
+<br>Project org.eclipse.jdt.core v_377
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_377">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44576">44576</a>
+Code formatter option "Insert a new line before an opening brace" has no effect for single else
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44570">44570</a>
+Code formatter option "Insert a new line inside an empty block" has no effect
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44503">44503</a>
+Unoptimal formatting for long constructor argument
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44546">44546</a>
+New formatter unable to format
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44506">44506</a>
+Type hierarchy is missing anonymous type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44481">44481</a>
+"Insert new line between else and if" is not working as expected
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44480">44480</a>
+Formatting the formatted string should not produce edits
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44444">44444</a>
+jdt.core in trouble when project has no JRE
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44437">44437</a>
+Typo in plugin.properties
+
+<a name="v_376"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 8th October 2003
+<br>Project org.eclipse.jdt.core v_376
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_376">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44289">44289</a>
+     requires the index format to be changed. Indexes will be automatically regenerated upon
+     subsequent search queries (accounting for indexing notification in search progress dialogs).
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44308">44308</a>
+NullPointerException when searching jars
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44341">44341</a>
+NPE from  delta processor
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44119">44119</a>
+NPE while searching for references to Action#run() 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44331">44331</a>
+Need indication that removal/add was targeted to a primary working copy 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32639">32639</a>
+Missing empty fine-grain delta when reconciling 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44292">44292</a>
+IDOMType.setFlags(Flag.AccPublic) when applied to an interface having default visibility produces uncompilable code
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44293">44293</a>
+DOMFactory.createInitializer() always creates a static intializer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44289">44289</a>
+Search broken 
+
+<a name="v_374"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 7th October 2003
+<br>Project org.eclipse.jdt.core v_374
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_374">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>The new code formatter can be activated in the ui. See the work in progress section. This first release doesn't expose
+yet all the preferences of the new code formatter. This will be done after M4. However the old formatter options should be honored by 
+the new code formatter. This is a work in progress and all problems should be reported against JDT/Core.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44242">44242</a>
+Deadlock during jdt/debug test 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44066">44066</a>
+Package Explorer doesn't show new file 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44219">44219</a>
+NPE while creating TypeHierarchy for binary type "Group" 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44073">44073</a>
+Override methods action does not work for local types [code manipulation] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=16231">16231</a>
+formatter creates ugly array initializer expressions
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6284">6284</a>
+Java formatter enhancements
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6268">6268</a>
+Code formatting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44036">44036</a>
+Java code formatter wraps line too much.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43651">43651</a>
+Linewrapping of throws declarations (if many)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43545">43545</a>
+Code Formatter: Don't separate long "import" clause.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43272">43272</a>
+feature request : extend the code formatter to support blanks between method / class name and bracket.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43050">43050</a>
+Formatting long arguments not very readable
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40777">40777</a>
+Incorrect formatting for anonymous inner class with comment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39607">39607</a>
+Incorrect formatting of anonymous inner class inside if statement
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39603">39603</a>
+for-Statement not correctly formatted by Codeformatter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39357">39357</a>
+Better code formatting
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38151">38151</a>
+Code formatter adds an unwanted blank line after an abstract method with a "throws" clause.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37106">37106</a>
+Code Formatter: Option to double indent wrapped lines in if statments, etc.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37057">37057</a>
+Code Formatter: Reduce number of blank lines to 1
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36832">36832</a>
+wrong indent on Code Format of anonymous class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36455">36455</a>
+[Formatting] Too long lines look ugly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36108">36108</a>
+Code Formatter Clear Blank Lines Doesn't Work
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35799">35799</a>
+code formatter: missing space after last array initializer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35433">35433</a>
+Simple Feature Request - Code Formatter Enhancement
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35173">35173</a>
+Code formatter incorrectly formats this case:
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29110">29110</a>
+RFE: Disable line splitting in the code formatter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28098">28098</a>
+Code Formatter doesn't format JavaDoc indentation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27196">27196</a>
+Code Formatter Won't Indent Braces
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25559">25559</a>
+more code formatter options
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24200">24200</a>
+"Space inside parens & brackets" option in Code Formatter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23144">23144</a>
+formatter issues
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22528">22528</a>
+Code formatter incorrectly indents lines
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22313">22313</a>
+Formatter doesn't like some comment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21943">21943</a>
+Formatter should allow removing space after for/while/if
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20721">20721</a>
+Code formatter bug
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19999">19999</a>
+Code Formatter always clears blank lines to 1
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19811">19811</a>
+Code formatter bugs
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=17349">17349</a>
+Code Formatter incorrectly formats static initializer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=16233">16233</a>
+formatter problem with constructor, array and line-end comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=15286">15286</a>
+Code formatter: long param lists and line wrapping
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=14659">14659</a>
+Align method arguments on line break
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12456">12456</a>
+Add formatter options for controlling spaces
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12321">12321</a>
+Code formatter and comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=10052">10052</a>
+CodeFormatter - line splitting enhancement.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=7439">7439</a>
+incorrect formatting: empty inner class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=7224">7224</a>
+Formatting splits package names in ugly ways
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6747">6747</a>
+Code Formatter exchange several blank lines w/ one
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=5824">5824</a>
+Code Formatter needs to be more customizable to be useful
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3327">3327</a>
+Formatter - should ensure one empty line before a method declaration (1GHOJWD)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3276">3276</a>
+DCR: (LOW) Formatter option to not indent methods (1GE39ZO)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3181">3181</a>
+Does not format nicely anonymous type (1FRLTO1)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44085">44085</a>
+becomeWorkingCopy() should add the working copy in the model 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44052">44052</a>
+Deadlock on startup
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44092">44092</a>
+Methods to generate parser files are not correct 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44084">44084</a>
+No refresh when deleting edited unit 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41643">41643</a>
+Code assist doesn't propose all valid types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44065">44065</a>
+NPE during hot code replace 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43897">43897</a>
+No completion in cast expression
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44061">44061</a>
+CodeAssist - no completion after class literal access
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=44018">44018</a>
+Change superfluous semicolon error message
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43872">43872</a>
+Hierarchy does not update properly when local class eliminated [type hierarchy] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43294">43294</a>
+Primary working copy: No updates when changed in working copy mode 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43907">43907</a>
+Too many warnings reported by the jdt compiler adapter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43847">43847</a>
+IPackageFragment not updated after CUs have moved 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43879">43879</a>
+working copy commit outside classpath doesn't save buffer
+
+<a name="v_373"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 30th September 2003
+<br>Project org.eclipse.jdt.core v_373
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_373">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43728">43728</a>
+Optimize CompilerOptions(Map....)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43842">43842</a>
+JDTCompilerAdapter doesn't find bootclasspath 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40782">40782</a>
+Primary working copies: unnecessary deltas on save 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43300">43300</a>
+SearchEngine(IWorkingCopy[] workingCopies) not backward compatible 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43670">43670</a>
+No classpath refresh when replacing binary project with source form
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43600">43600</a>
+NPE from JDTCompilerAdapter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43636">43636</a>
+Compiler complain that class cannot be resolved when it should be only not visible
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43208">43208</a>
+ICompilation.move not supported when in workingCopyMode 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40793">40793</a>
+Primary working copies: Type search does not find type in modified CU 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43587">43587</a>
+Searching for references to default constructors reports questionable results
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36143">36143</a>
+Type hierarchy doesn't include anonymous subclasses 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=8613">8613</a>
+Outline should show anonymous inner classes 
+
+
+<a name="v_372"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 24th September 2003
+<br>Project org.eclipse.jdt.core v_372
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_372">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42692">42692</a>
+JavaCC files cause VerifyError when compiled with Eclipse
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43437">43437</a>
+Scanner does not like string literals
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43485">43485</a>
+NPE in SearchEngine
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37659">37659</a>
+[plan item] Improve shared working copies 
+
+
+<a name="v_371"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 22nd September 2003
+<br>Project org.eclipse.jdt.core v_371
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_371">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> As a consequence of migrating to background autobuild, the JavaModel will no longer broadcast deltas
+during PRE_AUTO_BUILD event notification. These were somewhat inconsistent in so far as the model wasn't
+totally up to date anyway. Now the model will only fire deltas during POST_CHANGE, or working copy reconcile
+operations.
+</li>
+<li>Part of the new support for local and anonymous types in the Java model has been released. 
+	<p>
+	This includes:
+	<ul>
+	<li>local and anonymous types are shown in the Outline view and the Package Explorer view</li>
+	<li>Java element deltas for these types are notified</li>
+	<li>handles on these types can be created (see <code>IMember.getType(String, int)</code>)</li>
+	<li><code>getChildren()</code> on a method, a field or an initializer returns the local or anonymous types defined in this element</li>
+	<li>mementos for these handles are supported</li>
+	<li>open on selection (F3) in a Java editor goes to the local type definition</li>
+	<li>type hierarchies contain anonymous and local types</li>
+	</ul>
+	<p>
+	This doesn't yet include:
+	<ul>
+	<li>search on these types</li>
+	<li>anonymous/local binary types</li>
+	</ul>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42832">42832</a>
+Cannot get rid of this error even if the compiler settings is ignore for incompatible required binaries
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41583">41583</a>
+[misc] Eclipse cannot save or compile files in non-Java project anymore
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43274">43274</a>
+Type hierarchy broken 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38931">38931</a>
+Migrate delta processor to comply to new notification scheme in 3.0
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42281">42281</a>
+"Resource *.java does not exist"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38931">38931</a>
+org.eclipse.jdt.internal.corext.dom.NodeFinder needed in API 
+
+
+<a name="v_370"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 16th September 2003
+<br>Project org.eclipse.jdt.core v_370 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_370">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43026">43026</a>
+Running jdt/core tests on Linux is failing
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43045">43045</a>
+Copy/move of package fragments with read-only subpackages fails on Linux
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43116">43116</a>
+NPE copy and pasting a method
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43089">43089</a>
+Search engine doesn't report all matches
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=43080">43080</a>
+NPE when searching in CU with incomplete method declaration 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42856">42856</a>
+CodeAssist - Does not work after an inner type reference
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42839">42839</a>
+Incorrect position in org.eclipse.jdt.core.dom.ArrayType
+
+<a name="v_369"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 9th September 2003
+<br>Project org.eclipse.jdt.core v_369 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_369">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Default compiler compliance setting got raised to 1.4 level. Default source level is 1.3, and default target level is 1.2.
+To ease the 1.4 migration, the default severity for optional problem 'assert used as identifier' got raised to warning.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42760">42760</a>
+NullPointerException in JobManager when searching 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42629">42629</a>
+javac error message with missing classpath entry when claims entry dropped from path 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42614">42614</a>
+1.3 compliant mode should select default enclosing instance
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42588">42588</a>
+Incorrect selection of current enclosing instance
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35567">35567</a>
+Classpath validation error messages should contain project name
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42443">42443</a>
+Error when inner class name has the same name than another class, but with not the same case sensitive
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42459">42459</a>
+DebugEvaluationTests don't run if target is 1.2
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39887">39887</a>
+Resource exception while indexing
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42366">42366</a>
+Classpath validation error message removed while rebuilding a project.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41680">41680</a>
+Unnecessary cast  wrongly reported
+
+<a name="v_368"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M4 Build - 1st September 2003
+<br>Project org.eclipse.jdt.core v_368 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_368">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added optional compiler problem to signal unqualified access to a non-static field. In order to improve
+code readability, qualifying field accesses is a simple way to syntactically distinguish a field access from 
+a local variable access, and thus avoid resorting to a special naming convention for fields (such as "fField").
+<pre>
+* COMPILER / Reporting Unqualified Access to Field
+*    When enabled, the compiler will issue an error or a warning when a field is access without any qualification.
+*    In order to improve code readability, it should be qualified, e.g. 'x' should rather be written 'this.x'.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+</li>
+<li>Added optional compiler problem to signal method/constructor declared thrown checked exception which
+aren't actually raised inside the method/constructor body.
+<pre>
+* COMPILER / Reporting Unused Declared Thrown Exception
+*    When enabled, the compiler will issue an error or a warning when a method or a constructor is declaring a
+*    thrown checked exception, but never actually raises it in its body.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+</li>
+<li>Added optional compiler problem to flag situations where a finally block does not complete normally.
+<pre>
+* COMPILER / Reporting Finally Blocks Not Completing Normally
+*    When enabled, the compiler will issue an error or a warning when a finally block does not complete normally.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
+</pre>
+</li>
+<li>Improved problem description for unreachable catch block problems. Message will now mention the exception type 
+name and better diagnose the cause of the problem. Also changed problem source range 
+to rather highlight the caught exception type instead of entire catch block. 
+<pre></pre>
+</li>
+<li>Added two new API methods <code>readRawClasspath()</code> and <code>readOutputLocation()</code> on <code>IJavaProject</code>
+interface so as to allow user to read classpath directly from disk (<code>.classpath</code> file contents). This is useful to configure
+a Java project before it is associated with the Java nature, or before the automatic classpath reconciliation mechanism has performed (within
+a resource modifying operation, and prior to the change notification). Note that these API additions are obsoleting the previously
+added API <code>IJavaProject#forceClasspathReload(IProgressMonitor)</code> (also see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20931">20931</a>)
+which has thus been deprecated. Forcing the classpath reload can simply be achieved by: <code>p.setRawClasspath(p.readRawClasspath(), p.readOutputLocation(), ...)</code>.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40383">40383</a>
+Search - should only special treat unsaved working copies 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40658">40658</a>
+IJavaProject.getOutputLocation/getRawClasspath require Java nature
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42196">42196</a>
+Method popup extremely slow for JOGL code 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41534">41534</a>
+incorrect shadowing reported by rename [refactoring] 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40937">40937</a>
+ISourceReference.getSource throws ArrayIndexOutOfBoundsException 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41373">41373</a>
+SourceField.getConstant() returns null for final fields set in initializer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41604">41604</a>
+Possible Compiler Bug 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22976">22976</a>
+DCR - warning for unused declarations of thrown exceptions
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40736">40736</a>
+JDT compiler fails to compile legitimate Java code.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40020">40020</a>
+Exceptions in console 
+
+<a name="v_367"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M3 Build - 22nd August 2003 - 3.0 MILESTONE-3
+<br>Project org.eclipse.jdt.core v_367
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_367">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40464">40464</a>
+Index states not saved
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41805">41805</a>
+ArrayIndexOutOfBoundsException while creating AST
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39831">39831</a>
+Search finds only "inexact" matches 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35980">35980</a>
+illegal code completion suggested (abstract methods) 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40779">40779</a>
+Primary working copies: no deltas on destroy 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36271">36271</a>
+CodeAssist should treat array.clone() as visible
+<br<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40681">40681</a>
+no warnings for some externalized strings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40584">40584</a>
+Test suite configuration should be more flexible
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41674">41674</a>
+ToolFactory.createDefaultClassFileReader does not close zipfile
+	  	
+<a name="v_366"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M3 Build - 19th August 2003
+<br>Project org.eclipse.jdt.core v_366 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_366">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>In 1.4 mode, the compiler is now JCK 1.4a compliant (previously was passing JCK1.4).
+</li>
+<li>To reduce the memory consumption and improve performance, the following new APIs were added:
+<ul>
+<li>AST.parsePartialCompilationUnit(ICompilationUnit unit, int position, boolean resolveBindings)</li>
+<li>AST.parsePartialCompilationUnit(ICompilationUnit unit, int position, boolean resolveBindings, WorkingCopyOwner owner)</li>
+</ul>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41602">41602</a>
+missing @exception in javadoc of IPackageFragment.getNonJavaResources 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38635">38635</a>
+Refactor / Rename Package doesn't allow rename to same name with different case [refactoring]
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40476">40476</a>
+refactor change method signature reports erroneous non-constant case statements
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40995">40995</a>
+NPE in ast.ExplicitConstructorCall.analyseCode
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40880">40880</a>
+Wrong error range for 'indirect static access'
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40174">40174</a>
+Performance issues with builder
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39108">39108</a>
+Numerous single type imports can slow compiler down significantly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=41019">41019</a>
+org.eclipse.jdt.core.Signature cannot resolve complex type that has package name starting with letters as any primitive type
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38633">38633</a>
+Search should not open requested types with match locator parser
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40954">40954</a>
+ArrayIndexOutOfBoundsException during sort members
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40804">40804</a>
+NPE in MethodBinding.sourceMethod()
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40474">40474</a>
+DOM/AST: Add API to parse only part of a compilation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40839">40839</a>
+Deprecation is reported even if there is an empty member declaration prior to the field declaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40606">40606</a>
+Unable to discard empty package if containing .class files 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39174">39174</a>
+NPE in type hierarchy when opening type 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40082">40082</a>
+NPE in TypeHierarchy.packageRegionContainsSamePackageFragment(TypeHierarchy.java:1314) 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40090">40090</a>
+No need to close Java model on shutdown 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=42589">42589</a>
+jck1.4a failures
+
+<a name="v_365a"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M3 Build - 24th July 2003
+<br>Project org.eclipse.jdt.core v_365a 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_365a">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40752">40752</a>
+internal compiler error: java.lang.ClassCastException: org.eclipse.jdt.internal.compiler.lookup.ArrayBinding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40594">40594</a>
+wrong location set for org.apache.ant when building jdt component with baseLocation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40715">40715</a>
+getWorkingCopy(...) should always return a new working copy for primary cus 
+
+<a name="v_365"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M3 Build - 22nd July 2003
+<br>Project org.eclipse.jdt.core v_365 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_365">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Added optional diagnosis for undocumented empty blocks
+<pre>
+* COMPILER / Reporting Undocumented Empty Block
+*    When enabled, the compiler will issue an error or a warning when an empty block is detected and it is not
+*    documented with any comment.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+</li>
+<li> Removed optional diagnosis for boolean methods throwing exception, since it proved to be useless as is.
+</li>
+<li>Fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40116">40116</a>
+     requires the index format to be changed. Indexes will be automatically regenerated upon
+     subsequent search queries (accounting for indexing notification in search progress dialogs).
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40382">40382</a>
+JavaModelException#printStackTrace should be improved 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40572">40572</a>
+Unnecessary cast warning for necessary cast
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40322">40322</a>
+Error creating new Java projects 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40421">40421</a>
+Unnecessary cast warning...true but...
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32285">32285</a>
+DCR - extra java compiler markers
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40514">40514</a>
+ArrayIndexOutOfBoundsException during detection of unnecessary casts
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40442">40442</a>
+Abstract class fails to invoke interface-defined method in 1.4 compliance mode.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40116">40116</a>
+Search for references to nested class doesn't find anything 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40334">40334</a>
+Model should be more tolerant for possible compiler failures
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36479">36479</a>
+Rename operation during refactoring fails 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39865">39865</a>
+Misleading error diagnosis on broken method signatures
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12800">12800</a>
+suboptimal error messages on mistyped 'throw/throws' keywords 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38568">38568</a>
+Search for method declarations fooled by array types 
+
+<a name="v_364b"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 18th July 2003 - 3.0 MILESTONE-2
+<br>Project org.eclipse.jdt.core v_364b 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_364b">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40495">40495</a>
+VerifyError with return statements containing a cast expression
+
+<a name="v_364a"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 17th July 2003
+<br>Project org.eclipse.jdt.core v_364a 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_364a">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40423">40423</a>
+NPE Saving a file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40288">40288</a>
+NPE while building
+
+<a name="v_364"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 16th July 2003
+<br>Project org.eclipse.jdt.core v_364 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_364">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40210">40210</a>
+ICompilationUnit#isWorkingCopy() misbehaving for discarded working copies
+
+<a name="v_363"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 15th July 2003
+<br>Project org.eclipse.jdt.core v_363 
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_363">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added flag <code>IJavaElementDelta.F_PRIMARY_WORKING_COPY</code> that signals that a compilation unit has become a
+     primary working copy, or that a primary working copy has reverted to a compilation unit (i.e. primary working copies are not notified
+     as being added/removed like other working copies, since the primary unit is only changing mode, also see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40028">40028</a>).
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40028">40028</a>
+Deltas and deleted working copies 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39823">39823</a>
+AST: Would like to have binding of Serializable and Clonable
+	  	
+<a name="v_362"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 14th July 2003 
+<br>Project org.eclipse.jdt.core v_362
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_362">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Added optional diagnosis for unnecessary cast or instanceof operations (matching problem IDs are
+<code>IProblem.UnnecessaryCast</code>, <code>IProblem.UnnecessaryArgumentCast</code>, <code>IProblem.UnnecessaryInstanceof</code>).
+<pre>
+* COMPILER / Reporting Unnecessary Type Check
+*    When enabled, the compiler will issue an error or a warning when a cast or an instanceof operation 
+*    is unnecessary.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>	 
+</li>
+<li> Changed Java element delta processing to be thread-safe.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39926">39926</a>
+deleting default package (not in source folder) does nothing 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39877">39877</a>
+Rebuild All generates extra "Unable to read classpath" entry. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39925">39925</a>
+Unnecessary instanceof checking leads to a NullPointerException
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35442">35442</a>
+flag unnecessary casts
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39841">39841</a>
+Give better explanation of why abstract class can't be instantiated
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39467">39467</a>
+Classes not implementing abstract methods compile without error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39763">39763</a>
+Non NLS string is reported and it should not
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39779">39779</a>
+End position of IType exceeds the size of CompilationUnit 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39766">39766</a>
+compilation unit cannot be saved 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39664">39664</a>
+setSuperInterfaces(String[] interfaceNames) API of org.eclipse.jdt.core.jdom.IDOMType interface does not work for an empty array parameter as Input
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39663">39663</a>
+setSuperclass(String superclassName) API of org.eclipse.jdt.core.jdom.IDOMType interface does not work for null as Input
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39736">39736</a>
+JavaModelException on copying read-only CompilationUnits 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39009">39009</a>
+NPE in Delta processor while executing JDT/UI tests 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35739">35739</a>
+Stack dump on console 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35632">35632</a>
+NPE in DeltaProcessor 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39281">39281</a>
+Unable Refacter (renaming) an inner class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38450">38450</a>
+Delete: Removing default package removes source folder 
+
+<a name="v_361"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 7th July 2003 
+<br>Project org.eclipse.jdt.core v_361
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_361">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Added optional compiler diagnosis for boolean method declaring thrown exceptions
+(matching problem ID is <code>IProblem.BooleanMethodThrowingException</code>)
+<pre>
+* COMPILER / Reporting Boolean Method Declaring Thrown Exceptions
+*    When enabled, the compiler will issue an error or a warning when a boolean method declaration 
+*    is specifying a clause for thrown exceptions. Some of them are predicates, and these should only 
+*    return a boolean value and not raise exceptions.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.booleanMethodThrowingException"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+<li> Added optional compiler diagnosis for indirect references to static members (matching problem IDs are:
+<code>IProblem.IndirectAccessToStaticField</code>, <code>IProblem.IndirectAccessToStaticMethod</code>, <code>IProblem.IndirectAccessToStaticType</code>).
+<pre>
+* COMPILER / Reporting Indirect Reference to a Static Member
+*    When enabled, the compiler will issue an error or a warning whenever a static field
+*    or method is accessed in an indirect way. A reference to a static member should
+*    preferably be qualified with its declaring type name.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.indirectStaticAccess"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+</li>
+<li> Removed method <code>Parser#grammar()</code>, which was hosting the Java grammar as a massive comment. 
+From now on, the grammar is defined in its own separate file: <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/grammar/java_1_4.g"><code>java_1_4.g</code></a>.
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39624">39624</a>
+Should warn about predicate throwing exceptions
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39168">39168</a>
+Could remove JavaElement.fLEType field 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36989">36989</a>
+Incorrect error for "super must be first statement in constructor"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3319">3319</a>
+wrong compile-time error message (1GG1LDK)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39268">39268</a>
+Optional warning for indirect static references
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39533">39533</a>
+Working copy with no corresponding file not considered by NameLookup 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39502">39502</a>
+No completion in message send
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39475">39475</a>
+Extra error diagnosis in editor from siblings
+
+<a name="v_360"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 1st July 2003 
+<br>Project org.eclipse.jdt.core v_360
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_360">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li> Plugin version ID got incremented to 3.0.0. 
+</li>
+<li> Removed tolerance for relative source attachments in <code>JavaCore.newLibraryEntry(...)</code>. Only
+allowing relative empty pathes so as to permit using classpath variables to denote the absence of a source attachment.
+<li>To finish closing the gap between compilation units and working copies 
+(see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36888">bug 36888</a>), new APIs were added to generalize
+the usage of a working copy owner (entire JavaModel is now aware of owned working copies). These new APIs are copies of existing APIs augmented with
+a <code>WorkingCopyOwner</code> parameter, that defines the working copies to consider in the operation. 
+When specifying an owner parameter, all working copies belonging to this owner will implicitly take precedence over primary ones
+(without requiring the owner to remember all its working copies, as in 2.1 era). Note that when no owned working copy is found, a primary
+unit will be considered instead, and since primary units have a built-in working copy (see <code>ICompilationUnit.becomeWorkingCopy(...)</code>),
+the primary unit may already be in working copy mode (very likely since an editor got opened on it). This means that an owner will already 
+transparently see unsaved editor contents for all units for which it has no better working copy to contribute.
+The following new APIs were added:
+	<ul>
+	<li><code>AST.parseCompilationUnit(char[] source, String unitName, IJavaProject project, WorkingCopyOwner owner)</code></li>
+	<li><code>AST.parseCompilationUnit(IClassFile classFile, boolean resolveBindings, WorkingCopyOwner owner)</code></li>
+	<li><code>AST.parseCompilationUnit(ICompilationUnit unit, boolean resolveBindings, WorkingCopyOwner owner)</code></li>
+	<li><code>IEvaluationContext.codeComplete(String codeSnippet, int position, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
+	<li><code>IEvaluationContext.codeSelect(String codeSnippet, int offset, int length, WorkingCopyOwner owner)</code></li>
+	<li><code>IDOMCompilationUnit.getCompilationUnit(IPackageFragment parent, WorkingCopyOwner owner)</code></li>
+	<li><code>ICodeAssist.codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
+	<li><code>ICodeAssist.codeSelect(int offset, int length, WorkingCopyOwner owner)</code></li>
+	<li><code>ICompilationUnit.reconcile(boolean forceProblemDetection, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IJavaProject.findElement(IPath path, WorkingCopyOwner owner)</code></li>
+	<li><code>IJavaProject.findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner)</code></li>
+	<li><code>IJavaProject.findType(String fullyQualifiedName, WorkingCopyOwner owner)</code></li>
+	<li><code>IJavaProject.newTypeHierarchy(IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IJavaProject.newTypeHierarchy(IType type, IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IPackageFragment.getCompilationUnit(String name, WorkingCopyOwner owner)</code></li>
+	<li><code>IPackageFragment.getCompilationUnits(WorkingCopyOwner owner)</code></li>
+	<li><code>IType.codeComplete(char[] snippet, int insertion, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
+	<li><code>IType.newSupertypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IType.newTypeHierarchy(IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IType.newTypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+	<li><code>IType.resolveType(String typeName, WorkingCopyOwner owner)</code></li>
+	<li><code>JavaCore.create(IFile file, WorkingCopyOwner owner)</code></li>
+	<li><code>JavaCore.create(IResource resource, WorkingCopyOwner owner)</code></li>
+	<li><code>JavaCore.create(String handleIdentifier, WorkingCopyOwner owner)</code></li>
+	<li><code>JavaCore.createCompilationUnitFrom(IFile file, WorkingCopyOwner owner)</code></li>
+	<li><code>JavaCore.getWorkingCopies(WorkingCopyOwner owner)</code></li>
+	<li><code>SearchEngine.SearchEngine(WorkingCopyOwner workingCopyOwner)</code></li>
+	<li><code>SearchEngine.createHierarchyScope(IType type, WorkingCopyOwner owner)</code></li>
+	</ul>
+</li>
+<li> Added optional problem to signal superfluous semicolons (matching problem ID is <code>IProblem.SuperfluousSemicolon</code>).
+<pre>
+* COMPILER / Reporting Superfluous Semicolon
+*    When enabled, the compiler will issue an error or a warning if a superfluous semicolon is met.
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.superfluousSemicolon"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26281">26281</a>
+error hover text indicates wrong problem
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23166">23166</a>
+Syntax error message from Java compiler is confusing. 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33213">33213</a>
+Same error reported more than once? 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36214">36214</a>
+TODOs reported twice when located at the end of the method declaration 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36232">36232</a>
+binding do not fully consider working copies 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36888">36888</a>
+Close the gap between original and working copies 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39311">39311</a>
+Outliner did not refresh after method rename (refactor) 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39259">39259</a>
+While statement has wrong source position
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39007">39007</a>
+Infinite loop trying to index a non-existing external jar
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=39172">39172</a>
+Incorrect error reported if extra semi-colon exists on a return statement
+
+
+<a name="v_359"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 23rd June 2003 
+<br>Project org.eclipse.jdt.core v_359
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_359">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added API on <code>ICompilationUnit</code> to get the primary compilation unit of a working copy 
+	 (it replaces <code>IWorkingCopy.getOriginalElement()</code>):
+<pre>
+/**
+ * Returns the primary compilation unit (whose owner is the primary owner)
+ * this working copy was created from, or this compilation unit if this a primary
+ * compilation unit.
+ * Note that the returned primary compilation unit can be in working copy mode.
+ * 
+ * @return the primary compilation unit this working copy was created from,
+ * or this compilation unit if it is primary
+ * @since 3.0
+ */
+ICompilationUnit getPrimary();
+</pre>
+</li>
+<li>Added API on <code>IJavaElement</code> to get the primary element of a working copy 
+	 element (it replaces <code>IWorkingCopy.getOriginalElement(IJavaElement)</code>):
+<pre>
+/**
+ * Returns the primary element (whose compilation unit is the primary compilation unit)
+ * this working copy element was created from, or this element if it is a descendant of a
+ * primary compilation unit or if it is not a descendant of a working copy (e.g. it is a
+ * binary member).
+ * The returned element may or may not exist.
+ * 
+ * @return the primary element this working copy element was created from, or this
+ * 	element.
+ * @since 3.0
+ */
+IJavaElement getPrimaryElement();
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38678">38678</a>
+workspace did not shutdown
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37006">37006</a>
+2 tasks in the tasks view instead of one
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38759">38759</a>
+Task Tags: should not consider text in substrings/parts of text
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36066">36066</a>
+Outliner did not refresh after field rename 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38951">38951</a>
+NPE in editor while saving contents 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35877">35877</a>
+Stack overflow in code assist
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35409">35409</a>
+RC2 Compiler produces bogus error messages
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38838">38838</a>
+SyntaxError- unoptimal syntax error message
+
+
+<a name="v_357b"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 18th June 2003 
+<br>Project org.eclipse.jdt.core v_357b
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_357b">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Backported index manager deadlock fix on top of v_357</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38901">38901</a>
+IndexManager hangs in end-less loop
+
+
+<a name="v_358"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M2 Build - 16th June 2003 
+<br>Project org.eclipse.jdt.core v_358
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_358">cvs</a>).
+
+<p><b>NOTE:</b> This version got backed out due to severe regression
+(see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38951">38951</a> NPE in editor while saving contents).
+Until subsequent version is made available (see above), integration builds will revert to previous version (v_357).
+
+<h2>
+What's new in this drop</h2>
+<ul>
+<li><code>JavaCore.newLibraryEntry(...)</code> will now allow an empty source attachment (<code>new Path("")</code>) to
+be equivalent to no source attachment (i.e. <code>null</code>). This adjustment is made necessary for
+library entries generated from classpath variables which cannot be set to <code>null</code>. Also see 
+bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38531">38531</a>.
+<pre>
+* @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, 
+*    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
+*   and will be automatically converted to <code>null</code>.
+</pre>
+</li>
+<li>Added API <code>IJavaProject#forceClasspathReload(IProgressMonitor)</code> to force reload of <code>.classpath</code> file
+before next automatic update occurs.
+<pre>
+/**
+ * Force the project to reload its <code>.classpath</code> file from disk and update the classpath accordingly.
+ * Usually, a change to the <code>.classpath</code> file is automatically noticed and reconciled at the next 
+ * resource change notification event. If required to consider such a change prior to the next automatic
+ * refresh, then this functionnality should be used to trigger a refresh. In particular, if a change to the file is performed,
+ * during an operation where this change needs to be reflected before the operation ends, then an explicit refresh is
+ * necessary.
+ * 
+ * @param monitor a progress monitor for reporting operation progress
+ * @exception JavaModelException if the classpath could not be updated. Reasons
+ * include:
+ *  - This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ *  - Two or more entries specify source roots with the same or overlapping paths (NAME_COLLISION)
+ *  - A entry of kind <code>CPE_PROJECT</code> refers to this project (INVALID_PATH)
+ *  - This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ *  - The output location path refers to a location not contained in this project (<code>PATH_OUTSIDE_PROJECT</code>)
+ *  - The output location path is not an absolute path (<code>RELATIVE_PATH</code>)
+ *  - The output location path is nested inside a package fragment root of this project (<code>INVALID_PATH</code>)
+ *  - The classpath is being modified during resource change event notification (CORE_EXCEPTION)
+ * @since 3.0
+ */
+</pre>
+</li>
+<li>In the process of closing the gap between compilation units and working copies 
+(see <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36888 ">bug 36888 </a>), the following new APIs 
+are added to <code>ICompilationUnit</code>:
+	<ul>
+	<li><pre>
+/**
+ * Changes this compilation unit handle into a working copy. A new IBuffer is
+ * created using this compilation unit handle's owner. Uses the primary owner is none was
+ * specified when this compilation unit handle was created.
+ *
+ * When switching to working copy mode, problems are reported to given 
+ * IProblemRequestor.
+ *
+ * Once in working copy mode, changes to this compilation unit or its children are done in memory.
+ * Only the new buffer is affected. Using commitWorkingCopy(boolean, IProgressMonitor)
+ * will bring the underlying resource in sync with this compilation unit.
+ *
+ * If this compilation unit was already in working copy mode, an internal counter is incremented and no
+ * other action is taken on this compilation unit. To bring this compilation unit back into the original mode 
+ * (where it reflects the underlying resource), discardWorkingCopy must be call as many 
+ * times as becomeWorkingCopy.
+ * 
+ * @param problemRequestor a requestor which will get notified of problems detected during
+ * 	reconciling as they are discovered. The requestor can be set to null indicating
+ * 	that the client is not interested in problems.
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ * 	or null if no progress should be reported 
+ * @exception JavaModelException if this compilation unit could not become a working copy.
+ * @see discardWorkingCopy
+ * @since 3.0
+ */
+void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;	
+	</pre></li>
+	<li><pre>
+/**
+ * Commits the contents of this working copy to its underlying resource.
+ *
+ * It is possible that the contents of the original resource have changed
+ * since this working copy was created, in which case there is an update conflict.
+ * The value of the force parameter effects the resolution of
+ * such a conflict:
+ * - true - in this case the contents of this working copy are applied to
+ * 	the underlying resource even though this working copy was created 
+ * 	before a subsequent change in the resource
+ * - false - in this case a JavaModelException is thrown
+ * 
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * 
+ * @param force a flag to handle the cases when the contents of the original resource have changed
+ * since this working copy was created
+ * @param monitor the given progress monitor
+ * @exception JavaModelException if this working copy could not commit. Reasons include:
+ * - A CoreException occurred while updating an underlying resource
+ * - This element is not a working copy (INVALID_ELEMENT_TYPES)
+ * - A update conflict (described above) (UPDATE_CONFLICT)
+ * @since 3.0
+ */
+void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException;	
+	</pre></li>
+	<li><pre>
+/**
+ * Changes this compilation unit in working copy mode back to its original mode.
+ *
+ * This has no effect if this compilation unit was not in working copy mode.
+ * 
+ * If becomeWorkingCopy was called several times on this
+ * compilation unit, discardWorkingCopy must be called as 
+ * many times before it switches back to the original mode.
+ * 
+ * @see becomeWorkingCopy
+ * @exception JavaModelException if this working copy could not return in its original mode.
+ * @since 3.0
+ */
+void discardWorkingCopy() throws JavaModelException;
+	</pre></li>
+	<li><pre>
+/**
+ * Returns the working copy owner of this working copy.
+ * Returns null if it is not a working copy or if it has no owner.
+ * 
+ * @return WorkingCopyOwner the owner of this working copy or null
+ * @since 3.0
+ */
+WorkingCopyOwner getOwner();
+	</pre></li>	
+	<li><pre>
+/**
+ * Returns a new working copy of this element if this element is not
+ * a working copy, or this element if this element is already a working copy.
+ * 
+ * Note: if intending to share a working copy amongst several clients, then 
+ * getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor) 
+ * should be used instead.
+ * 
+ * When the working copy instance is created, an ADDED IJavaElementDelta is 
+ * reported on this working copy.
+ * 
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * 
+* @param monitor a progress monitor used to report progress while opening this compilation unit
+ * 	or null if no progress should be reported 
+ * @exception JavaModelException if the contents of this element can
+ * 	not be determined. 
+ * @return a new working copy of this element if this element is not
+ * 	a working copy, or this element if this element is already a working copy
+ * @since 3.0
+ */
+ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException;
+	</pre></li>	
+	<li><pre>
+/**
+ * Returns a shared working copy on this element using the given working copy owner to create
+ * the buffer, or this element if this element is already a working copy.
+ * This API can only answer an already existing working copy if it is based on the same
+ * original compilation unit AND was using the same working copy owner (that is, as defined by Object.equals).	 
+ * 
+ * The life time of a shared working copy is as follows:
+ * - The first call to getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)
+ *   creates a new working copy for this element
+ * - Subsequent calls increment an internal counter.
+ * - A call to discardWorkingCopy() decrements the internal counter.
+ * - When this counter is 0, the working copy is discarded.
+ * 
+ * So users of this method must discard exactly once the working copy.
+ *
+ * Note that the working copy owner will be used for the life time of this working copy, that is if the 
+ * working copy is closed then reopened, this owner will be used.
+ * The buffer will be automatically initialized with the original's compilation unit content
+ * upon creation.
+ * 
+ * When the shared working copy instance is created, an ADDED IJavaElementDelta is reported on this
+ * working copy.
+ * 
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * 
+ * @param owner the working copy owner that creates a buffer that is used to get the content 
+ *  	of the working copy
+ * @param problemRequestor a requestor which will get notified of problems detected during
+ * 	reconciling as they are discovered. The requestor can be set to null indicating
+ * 	that the client is not interested in problems.
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ * 	or null if no progress should be reported 
+ * @exception JavaModelException if the contents of this element can
+ *  	not be determined. 
+ * @return a new working copy of this element using the given factory to create
+ * the buffer, or this element if this element is already a working copy
+ * @since 3.0
+ */
+ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;	
+	</pre></li>
+	</ul>
+And the following abstract class replaces <code>IBufferFactory</code>:
+	<pre>
+/**
+ * The owner of an ICompilationUnit handle in working copy mode. 
+ * An owner is used to identify a working copy and to create its buffer.
+ * 
+ * @see ICompilationUnit#becomeWorkingCopy
+ * @see ICompilationUnit#discardWorkingCopy
+ * @since 3.0
+ */
+public abstract class WorkingCopyOwner {
+	/**
+	 * Creates a buffer for the given working copy.
+	 * The new buffer will be initialized with the contents of the underlying file
+	 * if and only if it was not already initialized by the compilation owner (a buffer is 
+	 * uninitialized if its content is null).
+	 * 
+	 * @param workingCopy the working copy of the buffer
+	 * @return IBuffer the created buffer for the given working copy
+	 * @see IBuffer
+	 */
+	public IBuffer createBuffer(ICompilationUnit workingCopy) {
+		...
+	}
+}
+	</pre>
+	The intent for the primary owner is to use a buffer factory that would be
+	provided by the org.eclipse.text infractructure. This infrastructure not being
+	ready yet, in the meantime one can change the primary owner's 
+	<code>IBufferFactory</code> using the following internal API:
+	<pre>
+org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner.PRIMARY.factory = ...;
+	</pre>
+
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38901">38901</a>
+IndexManager hangs in end-less loop
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38908">38908</a>
+Ant script reports that the bootclasspath cannot be infer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38531">38531</a>
+IllegalArgumentException "Source attachment path should be absolute"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38424">38424</a>
+Mistake on Web site
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38732">38732</a>
+organize imports does not work with assert in source code
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38447">38447</a>
+AST: Source ranges with missing bracket
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36854">36854</a>
+NPE opening type hierarchy 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33530">33530</a>
+JavaModel synchronization model should be more optimistic 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20931">20931</a>
+Need an API to reload the classpath from the file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38393">38393</a>
+bytecode generated for evaluation with parentheses is wrong
+
+<a name="v_357"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 5th June 2003 - 3.0 MILESTONE-1
+<br>Project org.eclipse.jdt.core v_357
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_357">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37274">37274</a>
+Deadlock on plugin import
+
+
+<a name="v_356"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 4th June 2003
+<br>Project org.eclipse.jdt.core v_356
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_356">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38362">38362</a>
+Inconsistent output when using comparrisson operators
+
+
+<a name="v_355"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 3rd June 2003
+<br>Project org.eclipse.jdt.core v_355
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_355">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37111">37111</a> may issue some outgoing changes
+to .classpath file since the source attachment will be shortened into a project relative path when applicable. The .classpath file
+is still backward compatible, and will continue to accept non relative source attachments as well. </li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37111">37111</a>
+classpath file - java source attachment shouldn't hardcode project name
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38143">38143</a>
+this = null; should raise compile time error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38124">38124</a>
+Brackets around cast accepted by Eclipse but not javac
+
+
+<a name="v_354"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 26th May 2003
+<br>Project org.eclipse.jdt.core v_354
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_354">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added <code>JavaCore</code> optional problem to detect incompatible required binaries, so as to flag situations where
+some prerequisite binaries are required a JRE level higher than the project target platform; i.e. compiling against 1.4 libraries 
+when deploying for 1.1 platform is likely unwanted.
+<pre>
+* JAVACORE / Reporting Incompatible JDK Level for Required Binaries
+*    Indicate the severity of the problem reported when a project prerequisites another project 
+*    or library with an incompatible target JDK level (e.g. project targeting 1.1 vm, but compiled against 1.4 libraries).
+*     - option id:         "org.eclipse.jdt.core.incompatibleJDKLevel"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "ignore"
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37750">37750</a>
+incorrect handle identifier for IImportContainer
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36674">36674</a>
+compiler can generate Java 1.4-only bytecode regardless of compatibility settings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37962">37962</a>
+Unexpected transient problem during reconcile 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37166">37166</a>
+NPE in SearchEngine when matching type against ProblemReferenceBinding 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37438">37438</a>
+searchenging NPE in searchDeclarationsOfReferencedTypes 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37779">37779</a>
+ExceptionInInitializerError when using JDTCompilerAdapter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36307">36307</a>
+JDK1.4.2: Wrong declaring class for clone method on array class
+
+
+<a name="v_353"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 19th May 2003
+<br>Project org.eclipse.jdt.core v_353
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_353">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
@@ -45,87 +2370,184 @@
 <h3>Problem Reports Fixed</h3>
 <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37621">37621</a>
 java compiler creates class with internal inconsistency
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37646">37646</a>
+Help for JDTCompilerAdapter is dated
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36894">36894</a>
+JobManager could wait when idle
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37541">37541</a>
+Unoptimal deprecation diagnosis
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37565">37565</a>
+JACKS: Class literal should not cause class initialization
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37503">37503</a>
+Compiler does not take care of exclusion filter
 
+
+<a name="v_352"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 2.1.1 Build - 14th May 2003
-<br>Project org.eclipse.jdt.core v_314_R21x
+Eclipse SDK 3.0M1 Build - 13th May 2003
+<br>Project org.eclipse.jdt.core v_352
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_352">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
+<li>Lowered default severity of field/local variable hiding optional diagnosis to <code>"ignore"</code>.
+</li>
+<li>Lowered default severity of accidental boolean assignment optional diagnosis to <code>"ignore"</code>.
+</li>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37387">37387</a>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37501">37501</a>
+VerifyError with assert when optimizing out unused local variables
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37387">37387</a>
 Compiler generates unnecessary byte codes
-	  	
-<h3>Problem Reports Closed</h3>
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37381">37381</a>
+AST: Wrong source ranges on VariableDeclExpression
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37200">37200</a>
+"Source->Generate Delegate Methods..." fails
 
+<a name="v_351"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 2.1.1 Build - 29th April 2003
-<br>Project org.eclipse.jdt.core v_313_R21x
+Eclipse SDK 3.0M1 Build - 29th April 2003
+<br>Project org.eclipse.jdt.core v_351
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_351">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
 </ul>
 
 <h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36490">36490</a>
-Java compiler misses dependency on 'static final' class variables.
-
-<h3>Problem Reports Closed</h3>
-
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1.1 Build - 23rd April 2003
-<br>Project org.eclipse.jdt.core v_312_R21x
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Branched to R2_1_maintenance (from v_312)
-</li>
-<li> Plugin version ID got incremented to 2.1.1. 
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36718">36718</a>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=37040">37040</a>
+VerifyError "Illegal target of jump or branch"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36490">36490</a>
+Java compiler misses dependency on 'static final' class variables
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36814">36814</a>
+NaiveASTFlattener does not serialize try-finally statements correctly
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36772">36772</a>
+AST: CompilationUnit.findDeclaringNode: Spec/Impl not same
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36711">36711</a>
+Resource duplication message should list location of duplicate
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36718">36718</a>
 Compiler should not generate references to classes not on the classpath
+
+<a name="v_350"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes&nbsp;<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.0M1 Build - 22nd April 2003
+<br>Project org.eclipse.jdt.core v_350
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_350">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added new compiler optional problem to signal cases where a boolean variable is assigned
+in a condition expression. It is likely an accidental situation, where a comparison was actually meant.
+<pre>
+* COMPILER / Reporting Possible Accidental Boolean Assignment
+*    When enabled, the compiler will issue an error or a warning if a boolean assignment is acting as the condition
+*    of a control statement  (where it probably was meant to be a boolean comparison).
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
+</pre>
+</li>
+<li>Added new compiler settings to control the diagnosis of variable hiding other ones.
+<pre>
+* COMPILER / Reporting Local Variable Declaration Hiding another Variable
+*    When enabled, the compiler will issue an error or a warning whenever a local variable
+*    declaration is hiding some field or local variable (either locally, inherited or defined in enclosing type).
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.localVariableHiding"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
+*
+* COMPILER / Reporting Field Declaration Hiding another Variable
+*    When enabled, the compiler will issue an error or a warning whenever a field
+*    declaration is hiding some field or local variable (either locally, inherited or defined in enclosing type).
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.fieldHiding"
+*     - possible values:   { "error", "warning", "ignore" }
+*     - default:           "warning"
+*
+* COMPILER / Reporting Special Parameter Hiding another Field
+*    When enabled, the compiler will signal cases where a constructor or setter method parameter declaration 
+*    is hiding some field (either locally, inherited or defined in enclosing type).
+*    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.localVariableHiding".
+*     - option id:         "org.eclipse.jdt.core.compiler.problem.specialParameterHidingField"
+*     - possible values:   { "enabled", "disabled" }
+*     - default:           "disabled"
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36510">36510</a>
+Automatically attach source for source files located in a class folder 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36499">36499</a>
+exists() returns true for a source file inside a classfolder 
 <br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36438">36438</a>
 null == null causes java.lang.VerifyError
 <br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35755">35755</a>
-Search in hierarchy misses dependent projects
+Search in hierarchy misses dependent projects 
 <br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36465">36465</a>
 Unable to create multiple source folders when not using bin for output
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35649">35649</a>
-The SourceMapper instances could share the fileNamefilter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36339">36339</a>
+Try codegen issues slightly incorrect ANY exception handler
 <br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35965">35965</a>
 Source not found in source attachment 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36447">36447</a>
+Unoptimal wide conditional branch bytecode sequence
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19286">19286</a>
+Suspicious synchronized operations 
 <br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36213">36213</a>
 ArrayIndex out of bounds
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36244">36244</a>
+JDK1.4.2: Add -cp as a batch option 
 <br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35528">35528</a>
 When I check out a project from CVS, Updating takes a very long time
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35490">35490</a>
-Search doesn't work for reference of 'cursorLocation'
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36058">36058</a>
+Unknown NPE in log
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21661">21661</a>
+Compile dependency problems
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28937">28937</a>
+Compiler Problem Marker: Accidental Boolean Assignment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33831">33831</a>
+ast API: add FieldAccess.resolveFieldBinding
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35649">35649</a>
+The SourceMapper instances could share the fileNamefilter 
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34896">34896</a>
+compiler setting "unused private fields"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33751">33751</a>
+The numbering of anonymous could be optimized
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35849">35849</a>
+Incremental compilation ignores linked folders
 <br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35926">35926</a>
 Batch compiler compile should return false when the command line is incorrect
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35438">35438</a>
-CastExpression resolution departs from JLS section 6.5.1
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35421">35421</a>
+[nls] Inconsistencies between properties files and nls strings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34173">34173</a>
+Create a compiler warning when an instance variable is "re-declared" as a local variable.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21140">21140</a>
+Warning/error on shadowing definition of data member?
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35490">35490</a>
+Search doesn't work for reference of 'cursorLocation'
 <br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35338">35338</a>
 Cannot save file, "Save failed:null" error message received
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35438">35438</a>
+CastExpression resolution departs from JLS section 6.5.1
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36165">36165</a>
+[DOM/AST] Incorrect grammar rule in TypeDeclaration
 
-<h3>Problem Reports Closed</h3>
 
+<a name="v_312"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 31st March 2003
+Eclipse SDK 2.1 Build (before 3.0/2.1.1 branching) - 31st March 2003
 <br>Project org.eclipse.jdt.core v_312
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_312">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
@@ -135,3268 +2557,8 @@
 <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35831">35831</a>
 NPE navigating references using links
 
-<h3>Problem Reports Closed</h3>
-
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 27th March 2003
-<br>Project org.eclipse.jdt.core v_311 - 2.1 RELEASE (R2_1)
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35731">35731</a>
-Unable to build problem
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35754">35754</a>
-NPE in Scope.getTypeOrPackage
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35298">35298</a>
-NPE: Internal compiler error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31497">31497</a>
-Internal compiler error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35476">35476</a>
-Null pointer exception in org.eclipse.jdt.internal.compiler.lookup.Scope.getTypeOrPackage
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34962">34962</a>
-NPE in Scope.getTypeOrPackage
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35651">35651</a>
-"Unused private types, methods or fields" should recognize serialVersionUID.
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 26th March 2003
-<br>Project org.eclipse.jdt.core v_310
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24240">24240</a>
-DOC - JavaConventions.validateIdentifier: must NOT have the same spelling as ...
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35658">35658</a>
-Cannot resolve Inner Class reference
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 25th March 2003
-<br>Project org.eclipse.jdt.core v_309
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35654">35654</a>
-spec bug in CompilationUnitSorter.sort
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35561">35561</a>
-No source found if attached file contains 2 potential root paths
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35352">35352</a>
-NPE when attaching source
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35456">35456</a>
-The Eclipse compiler generates classes that throw a VerifyError
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35473">35473</a>
-NPE when exiting Eclipse
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35510">35510</a>
-Assigning code to a library that is within a jarfile
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35642">35642</a>
-NPE in index manager during shutdown
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35608">35608</a>
-NPE on shutdown
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35437">35437</a>
-can't call protected methods from derived classes in other pkg
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35396">35396</a>
-Compiler error in RC2
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 20th March 2003
-<br>Project org.eclipse.jdt.core v_308 - 2.1 RELEASE CANDIDATE 3a
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35306">35306</a>
-Index update request can be incorrectly handled
-
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 19th March 2003
-<br>Project org.eclipse.jdt.core v_307 - 2.1 RELEASE CANDIDATE 3
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34040">34040</a>
-It takes a minute to expand a project in Package explorer
-
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 18th March 2003
-<br>Project org.eclipse.jdt.core v_306 
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35237">35237</a>
-Ant adapter should say where to look for the .log file
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35132">35132</a>
-Need to reindex jar not on classpath not detected 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35131">35131</a>
-Optimize source attachment query when no source attachment available 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35128">35128</a>
-Problems with packages named "java"
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34214">34214</a>
-createPackageDeclaration on ICompilationUnit
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35098">35098</a>
-Delete compiled class files when deleting source file
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35087">35087</a>
-NPE while importing plug-ins
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34850">34850</a>
-Need better control over deprecation messages
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34322">34322</a>
-SDK hangs while building on IBM1.3.1SR2
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30418">30418</a>
-Inner classes cause compilation errors with asserts 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34789">34789</a>
-Search for references does not show subclassed methods 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33885">33885</a>
-packages with javax in their name don't import properly
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34992">34992</a>
-TODO as a substring in a comment generates a task 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34708">34708</a>
-unreliable full build/refresh using linked source folders
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35093">35093</a>
-Not only changes in working copy should refresh type hierarcy. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34851">34851</a>
-Rename Class operation hangs 
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 13th March 2003
-<br>Project org.eclipse.jdt.core v_305
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34845">34845</a>
-asserts do not need to be NLS'ed
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34658">34658</a>
-Save All failed with unhelpful error message.
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34802">34802</a>
-instanceof produce InternalCompilerError on MacOSX with JDK1.4.1
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34734">34734</a>
-internal compiler error ArrayIndexOutOfBound w/ 1.4.1 release
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34706">34706</a>
-Internal compiler error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34907">34907</a>
-ArrayIndexOutOfBoundsException after installing Java 1.4.1_01
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34029">34029</a>
-"False-positive" deprecated warning
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34813">34813</a>
-NPE from builder
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 11th March 2003
-<br>Project org.eclipse.jdt.core v_304
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33927">33927</a>
-Leak in Java Editor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33950">33950</a>
-Slow performance when changing code in a much referenced project
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34000">34000</a>
-JDK Compliance doesn't match javac generation from an IBM or SUN JDK
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34078">34078</a>
-Hierarchy: 27% of time spent reporting progress 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33998">33998</a>
-unexpected NullPointerException 
-   
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34566">34566</a>
-can't get assert to work with mac os x java 1.4.1
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34337">34337</a>
-[RC2] Searches freezes ?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33412">33412</a>
-GB18030: Can't set JRE in a path contains GB18030 characters
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34292">34292</a>
-[RC2] OutOfMemory compiling
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34130">34130</a>
-Debug statements on console
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34301">34301</a>
-Java compiler doesn't dected always unreported exception
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32927">32927</a>
-Exception while playing with type hierarchy 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=34059">34059</a>
-When adding a library that is stored in a directory containing a "(" or ")" the classes are  *not* reachable for Code Assist.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33900">33900</a>
-NPE setting output directory of a source folder
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 6th March 2003
-<br>Project org.eclipse.jdt.core v_303 - 2.1 RELEASE CANDIDATE 2
-<h2>
-What's new in this drop</h2>
-<ul>
-<li><code>IJavaProject.isOnClasspath(...)</code> no longer throws any exception, but rather consistently return <code>false</code>
-in these circumstances. Indeed, it is difficult for clients to work with predicates that throw exceptions. 
-Although this change creates a source incompatibility, the change is binary compatible with 2.0 and within the original 
-spirit of the original API contract. Include in 2.1 readme.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33990">33990</a>
-.class file time-stamps out of sync with .java files
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32665">32665</a>
-Closing element trace should hide children 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32634">32634</a>
-Improve readability of compiling progress message
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33949">33949</a>
-DOM: assert statement has wrong length
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33695">33695</a>
-project build path broken 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33475">33475</a>
-Build path seems to be lost every time Eclipse restarts 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33785">33785</a>
-Open on selection fails 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33800">33800</a>
-search: reporting too many method occurrences 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33806">33806</a>
-Code assist failure: assignment of double in for loop hides previous variables
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33754">33754</a>
-IJavaProject.isOnClasspath should answer false for working copies outside the classpath
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33918">33918</a>
-Libraries are not presented in the Package Explorer (I030227)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33843">33843</a>
-Compiler incorrectly generating static method calls
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33625">33625</a>
-Searching for field references with SearchEngine returns some incorrect results
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31610">31610</a>
-IDE does hang-up
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 4th March 2003
-<br>Project org.eclipse.jdt.core v_302a
-<h2>
-What's new in this drop</h2>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33757">33757</a>
-Problem not detected when opening a working copy 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33753">33753</a>
-Missing resource messages could be improved
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33748">33748</a>
-Cannot open working copy on .java file in simple project 
-
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 4th March 2003
-<br>Project org.eclipse.jdt.core v_302
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Generalization of working copy deltas: the creation and destruction of any working copy (regular or shared) 
-	now fires an <code>ElementChangedEvent</code> as well indicating that the working copy has been 
-	<code>ADDED</code> or <code>REMOVED</code>. 
-	Until now, only shared working copies were providing such delta notifications.
-      <br>See: 
-      <ul>
-      <li><code>IWorkingCopy.getWorkingCopy()</code></li>
-      <li><code>IWorkingCopy.getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)</code></li>
-      <li><code>IWorkingCopy.destroy()</code></li>
-      </ul>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31799">31799</a>
-Getting squigglies in Java files not on classpath
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31858">31858</a>
-NPE in log 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33371">33371</a>
-Rename method dialog: Error message should quote name 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33686">33686</a>
-Missing extension point schemas
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32981">32981</a>
-Cancel Extract Interface refactoring does not cleanup working copies 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33692">33692</a>
-Cleanup in the batch compiler default options
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33653">33653</a>
-Relevance - should privilege type not needing qualification
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33039">33039</a>
-Quick Fix: IAE n invocation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32588">32588</a>
-Error saving changed source files; all files in project deleted
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33560">33560</a>
-Workspace shows temporary problems also the compiler doesn't
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31765">31765</a>
-private recursive methods not marked as unused
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33231">33231</a>
-Deadlock performing CVS decoration while JRE initializers are invoked
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33571">33571</a>
-SearchEngine.searchAllTypeNames: NPE when passing null as progress monitor 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33035">33035</a>
-OutOfMemoryException while searching for references 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33445">33445</a>
-CodeAssist - Relevance is not correct for local class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33462">33462</a>
-NPE during shutdown
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33424">33424</a>
-No completion available in local type constructor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33225">33225</a>
-Override methods... inserts methods incorrectly if class body is as {}
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33207">33207</a>
-Reject output folder that coincidate with source folder if not equal
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33621">33621</a>
-ICompilationUnit.getElementAt(int) returns strange things when parameter is in a field declaration inside anonymous and local classes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33696">33696</a>
-Java source exclusion filter stopped working in RC1
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32250">32250</a>
-Reporting unused private methods could be improved
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33610">33610</a>
-Deltas sent while in operation executed with JavaCore.run
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33573">33573</a>
-NPE in IndexManager on shutdown
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33527">33527</a>
-Inexact match searching in java.math.BigDecimal 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33505">33505</a>
-Compiler fails on allowed inner class code
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33461">33461</a>
-NPE upon shutdown
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33466">33466</a>
-NPE on shutdown from IndexManager
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33475">33475</a>
-Build path seems to be lost every time Eclipse restarts
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 27th February 2003
-<br>Project org.eclipse.jdt.core v_301
-<h2>
-What's new in this drop</h2>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=33321">33321</a>
-NPE in IndexManager shutdown
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31764">31764</a>
-CompletionEngine doesn't feed errors to completion requestor 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32488">32488</a>
-Request to add/remove source folder to index should not look at active job 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32392">32392</a>
-NPE in SourceMapper 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32701">32701</a>
-Disassembler doesn't show actual modifiers for member types
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32919">32919</a>
-Hierarchy views progress bar is useless 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32973">32973</a>
-Codeassist relevance should privilege prefix match over need for qualification 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32629">32629</a>
-DeltaProcessor walking some binary output 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32612">32612</a>
-Saved index file names leaking names?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32376">32376</a>
-Signature.getSimpleName/Qualifier should not create an own char-array 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32628">32628</a>  
-Too much time finding out there is no source during search 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32974">32974</a>
-Invalid classpath error on ..classpath edition
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32986">32986</a>
-Stack overflow, infinate recursion in compiler 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32607">32607</a>
-Removing outer folder removes nested folder's cus from index 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32937">32937</a>
-Kind not set for empty fine-grained delta 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32909">32909</a>
-compiler error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32690">32690</a>
-Classpath error are not detected after a Check out
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32738">32738</a>
-TVT: Externalized Strings to be removed from .properties file 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32957">32957</a>
-StackOverFlowError renaming class 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32323">32323</a>
-CVS information on class-Files lost during "rebuild project"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32563">32563</a>
-IAE in org.eclipse.jdt.core.Signature.toCharArray (M5) 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32900">32900</a>
-Java out of memory problem
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25848">25848</a>
-RedHat Linux LANG=en_US.UTF-8  causes some files *NOT* to be compiled
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32579">32579</a>
-abstract protected method can't be overridden
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32545">32545</a>
-Cannot override a method that's accessible in the superclass, but inaccessible in the super-superclass
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32179">32179</a>
-Problems searching for references to selected text
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 21st February 2003
-<br>Project org.eclipse.jdt.core v_300 - 2.1 RELEASE CANDIDATE 1
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>In 1.4 compliant mode, the compiler will allow unterminated line comment (i.e. with no trailing line separator), as a consequence
-of the JLS revisal. Thus removed temporary (and unused) 2.1 API :
-<code>ToolFactory.createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean assertMode, boolean recordLineSeparator, <b>boolean strictComment</b>)</code>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32342">32342</a>
-The field type Class_A is defined in an inherited type and an enclosing scope
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32476">32476</a>
-Spec now allows line comment to end with EOF
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32339">32339</a>
-Cannot find declaration of SIGNATURE in Java text search
-
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 20th February 2003
-<br>Project org.eclipse.jdt.core v_299
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added helper method to extract problem marker arguments: <code>CorrectionEngine.getProblemArguments(IMarker problemMarker)</code>
-<li>Added 2 settings to disable classpath enhancements which could affect 2.0 clients.
-<pre>
-* JAVACORE / Enabling Usage of Classpath Exclusion Patterns
-*    When set to "disabled", no entry on a project classpath can be associated with
-*    an exclusion pattern.
-*     - option id:         "org.eclipse.jdt.core.classpath.exclusionPatterns"
-*     - possible values:   { "enabled", "disabled" }
-*     - default:           "enabled"
-* 
-* JAVACORE / Enabling Usage of Classpath Multiple Output Locations
-*    When set to "disabled", no entry on a project classpath can be associated with
-*    a specific output location, preventing thus usage of multiple output locations.
-*     - option id:         "org.eclipse.jdt.core.classpath.multipleOutputLocations"
-*     - possible values:   { "enabled", "disabled" }
-*     - default:           "enabled"
-</pre>
-<li>Removed temporary 2.1 API :
-    <ul>
-     <li><code>IPackageFragmentRoot.computeSourceAttachmentRootPath(IPath sourceAttachmentPath)</code>
-     </li>
-     <li><code>IJavaModelMarker.UNBOUND_CONTAINER</code>, use classpath problem marker ID instead (<code>IJavaModelStatusConstants.CP_CONTAINER_PATH_UNBOUND</code>).
-     </li>
-     <li><code>IJavaModelMarker.UNBOUND_VARIABLE</code>, use classpath problem marker ID instead (<code>IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND</code>).
-     </li>
-    </ul>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29578">29578</a>
-Issues with migrating shared data
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32040">32040</a>
-Multiple output folders fooling Java builder
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32217">32217</a>
-Missing JavaCore in JDT/Core project index
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32338">32338</a>
-Auto generated comments of quickfix method generation for unnamed package class is wrong
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32271">32271</a>
-Type Hierarchy Progress monitor improvements 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32267">32267</a>
-TypeHierarchy. Does not set progress monitor to done when cancelled 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32218">32218</a>
-Inexact matches found when should be exact 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31016">31016</a>
-builder exception found in log
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32225">32225</a>
-incorrect delta after deleting 2 fields 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32219">32219</a>
-JavaModel operations fail with ArrayIndexOutOfBoundsException if array empty
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32182">32182</a>
-NPE performing search 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27994">27994</a>
-Code Assist replace mode inconsistent 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32041">32041</a>
-Multiple output folders fooling Java Model 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32196">32196</a>
-Patch: correctly detect misisng .rsc file
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32111">32111</a>
-ArrayIndexOutOfBoundsException during delete of members
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32100">32100</a>
-when superpackage package empty deleting a subpackage deletes superpackage
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31646">31646</a>
-No proposal using code assist in field initializer
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32227">32227</a>
-Serialization incompatibility with Sun's 1.4 compiler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28426">28426</a>
-Content Assist displays x(String arg0, String arg1) should be x(String str, String delim)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32164">32164</a>
-Serialization methods with private or arbitrary access modifiers should be ignored by "unused private members" compiler check.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32097">32097</a>
-Regression - attached source not found when in a subdirecory of archive
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 18th February 2003
-<br>Project org.eclipse.jdt.core v_298
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31997">31997</a>
-     requires the index format to be changed. Indexes will be automatically regenerated upon
-     subsequent search queries (accounting for indexing notification in search progress dialogs).
-</li>
-<li>Unused parameter diagnosis will now ignore parameters in an abstract method,
-a main method, an implementation of an abstract method or a method overriding a
-concrete one. Additional settings got added for enabling the diagnosis of the latter
-two scenarii.
-<pre>
-* COMPILER / Reporting Unused Parameter if Implementing Abstract Method
-*    When enabled, the compiler will signal unused parameters in abstract method implementations.
-*    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.unusedParameter".
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract"
-*     - possible values:   { "enabled", "disabled" }
-*     - default:           "disabled"
-*
-* COMPILER / Reporting Unused Parameter if Overriding Concrete Method
-*    When enabled, the compiler will signal unused parameters in methods overriding concrete ones.
-*    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.unusedParameter".
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete"
-*     - possible values:   { "enabled", "disabled" }
-*     - default:           "disabled"
-</pre>
-</li>
-<li><b>Code completion enhancement:</b>
-   <ul>
-   <li>Relevance of a proposal is higher if the proposal is a variable name and this name contains a prefix.</li>
-   <li>Relevance of a proposal is higher if the proposal is a variable name and this name contains a suffix.</li>
-   </ul>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32107">32107</a>
-Index signature change isn't honoured any longer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31997">31997</a>
-Refactoring d.n. work for projects with brackets in name. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31417">31417</a>
-Where has the "Root Path" field gone? [doc] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32000">32000</a>
-IJavaModel.contains() returns true for resources copied into bin folder
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31947">31947</a>
-NPE on shutdown in BlocksIndexInput.close()
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31985">31985</a>
-NPE searching non-qualified and case insensitive type ref 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28637">28637</a>
-[Preferences] Import Preferences: Console Message: Content is not allowed in Prolog 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31748">31748</a>
-[search] search for reference is broken 2.1 M5 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31990">31990</a>
-Working copy operations should not take workspace lock 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31811">31811</a>
-VerifyError with huge switch statement
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=5783">5783</a>
-Problem counts are not accumulated
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31652">31652</a>
-NamingConvention.suggestXXNames: Put the most relevant first
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31628">31628</a>
-Redundant import need a warning (matching package declaration)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31867">31867</a>
-No unused import diagnosis on duplicate import
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31495">31495</a>
-Should writeObject/readObject be a compiler warning?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31538">31538</a>
-serialVersionUID being flagged as an "unused" field
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31757">31757</a>
-Folder with invalid pkg name should be non-Java resource 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25204">25204</a>
-Eclipse compiler option: Unused parameters (i.e. never read)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27251">27251</a>
-Compiler preferences: Unused parameters - ignore main
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31383">31383</a>
-Strange rendering of of link resources when link points to Eclipse workspace 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31756">31756</a>
-Code assist: fails inside an array which inside a function call 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31248">31248</a>
-Java Compiler progress monitor tells about probelms found
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29790">29790</a>
-OOM Exception in search cause IDE freeze
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32083">32083</a>
-overridden methods that change visibility cause compiler error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=32044">32044</a>
-Pre auto build notification fired when closing or opening a file
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31903">31903</a>
-Null pointer exception loading from respository
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31968">31968</a>
-Notifier loose nested levels
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31942">31942</a>
-Bug with Selection Statement switch()
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31916">31916</a>
-M5 Crashing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31923">31923</a>
-Source folder specific compiler settings
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31917">31917</a>
-Unused private method warning doesn't know about read/writeObject
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=8452">8452</a>
-Wrong position in FieldReference
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12797">12797</a>
-Can't add directory pointing to class-files to project classpath
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=11023">11023</a>
-Filter code assist choices based on context
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=7293">7293</a>
-Scrubbing Output Directory Can Cause Havoc
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6096">6096</a>
-Exception using code assist after package rename
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=5043">5043</a>
-Feature Request: source folders in other projects
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6488">6488</a>
-Classpath Variables (allow plugins to reserve some)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31809">31809</a>
-Eclipse reports error in task view - but it's no error!
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28319">28319</a>
-Unused parameter should be limited to current method/class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31243">31243</a>
-Warn of unused parameters: Should not warn when method overrides
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28139">28139</a>
-Highlight unused method parameters that are not inherited
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31380">31380</a>
-NPE setting classpath
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 13th February 2003
-<br>Project org.eclipse.jdt.core v_297
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>To help fixing bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31135 ">31135</a>,
-      added new flag <code>F_REORDER</code> on <code>IJavaElementDelta</code>. This flag is 
-      positioned if a member in a compilation unit has changed its position relatively to its siblings.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31476">31476</a>
-CU is on build path also it is located in a excluded folder 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31303">31303</a>
-copy of read-only package doesn't preserve read-only flag
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24045">24045</a>
-Error deleting parent folder of source folder 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31653">31653</a>
-typos in javadoc of NamingConventions 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30623">30623</a>
-Strange java delta when creating a new class 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31446">31446</a>
-Cannot cancel 'Cleaning of output foder'
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30757">30757</a>
-Out of memory exception during hierarchy scoped search 
-   
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30485">30485</a>
-ArrayOutOfBoundsException during shutdown
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30609">30609</a>
-Output folder scrubbing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31591">31591</a>
-abstract method in base class, defined in a subclass results in compile error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31605">31605</a>
-Single line comment on the last line of a file produces a syntax error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31626">31626</a>
-getJavadoc() on TypeDeclaration returning incorrect comment
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 11th February 2003
-<br>Project org.eclipse.jdt.core v_296
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31377">31377</a>
-NullPointerException on binary import 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31441">31441</a>
-Match in jar missing searching for references 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31398">31398</a>
-M5 compilation problems with package abstract methods
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31230">31230</a>
-Code assist on variable names: uses prefix and suffix together
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31440">31440</a>
-Classpath container initializer getDescription should also take a project in argument
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31242">31242</a>
-exception names should use Local Var suffix/prefix, not Method Param
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31168">31168</a>
-Trying to open Java-source file with Java editor fails with I/O Exception.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31261">31261</a>
-Strange behavior when there is more errors than max errors per compilation unit
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31450">31450</a>
-Compiler bug with overriding protected abstract methods, where a parent class has package-private abstract method
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31475">31475</a>
-class must implement the inherited abstract method, but cannot override it
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30720">30720</a>
-linked resources and exclusion filters: compiler markers not flushed
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31467">31467</a>
-spurious "Incompatible conditional operand types" on ?: when assigning to abstract
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30800">30800</a>
-Search - doesn't find declaration of field with unicode name 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31225">31225</a>
-Source attachment not found
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=31148">31148</a>
-freezes when editing a java file and adding while(st.hasMoreTokes())
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30731">30731</a>
-Class move refactoring changes the unlinked projects in the same workplace
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 6th February 2003
-<br>Project org.eclipse.jdt.core v_295 - 2.1 MILESTONE-5 (aka 2.1 RELEASE CANDIDATE 0)
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added API <code>ClasspathContainerInitializer.getDescription(IPath containerPath)</code> so as to improve readability
-of our messages involving classpath containers (e.g. unbound container classpath problems). Default implementation answers
-the original container path.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30946">30946</a>
-Deadlock in code parser
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30999">30999</a>
-Hang/Deadlock while inserting brace
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30949">30949</a>
-When compiled from eclipse, unhandled exceptions in try - finally block are not detected.
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 5th February 2003
-<br>Project org.eclipse.jdt.core v_294
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> Classpath problem markers generated for unbound variable or container will have an extra attribute
-(respectively IJavaModelMarker.UNBOUND_VARIABLE or IJavaModelMarker.UNBOUND_CONTAINER) which value is
-the unbound variable or container names. This allows clients to recognize these problems, and contribute 
-suitable recovery actions for these.
-</li>
-<li> Project cycles can now be built as soon as the compiler severity for circular
-dependencies is lowered to a warning (see Preferences>Java>Compiler>Other>Circular dependencies>Warning).
-</li>
-<li> Surfaced compiler options for reporting usage of char[] in String concatenations (default is still warning).
-<pre>
-* COMPILER / Reporting Usage of char[] Expressions in String Concatenations
-*    When enabled, the compiler will issue an error or a warning whenever a char[] expression
-*    is used in String concatenations (e.g. "hello" + new char[]{'w','o','r','l','d'}).
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "warning"
-</pre>
-</li>
-<li>Added API <code>IJavaModel.contains()</code> to find out if an <code>IResource</code> is visible in
-     the Java model.
-</li>
-<li> 2.1 API Change in org.eclipse.jdt.core.NamingConventions: deprecated 'suggestSetterName' methods removed.
-	<ul>
-	<li><code>suggestSetterName(IJavaProject,char[],int,char[][])</code>
-	</li>
-	<li><code>suggestSetterName(IJavaProject,String,int,String[])</code>
-	</li>
-	</ul>
-</li>
-<li>Added API for sorting the members of types in a compilation.
-  <ul>
-    <li><code>org.eclipse.jdt.core.util.CompilationUnitSorter</code>
-    <pre>
-public static final String RELATIVE_ORDER = "relativeOrder";
-public static void sort(ICompilationUnit compilationUnit,
-	int[] positions,
-	Comparator comparator,
-	int options,
-	IProgressMonitor monitor) throws JavaModelException;
-    </pre>
-    </li>
-  </ul>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30947">30947</a>
-CodeAssist - top level types are not proposed if type is qualified with package
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30907">30907</a>
-Code assist doesn't work in first case statement of a switch statement
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30920">30920</a>
-Stack overflow when container resolved to null
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30855">30855</a>
-Wron error message when nesting source folder in class folder 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30857">30857</a>
-IPackageFragmentRoot: copy removes source folders from classpath 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22756">22756</a>
-Reference search does not respect package fragments scope 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30860">30860</a>
-CodeAssist - Relevance is not correct for member exception
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30856">30856</a>
-1.4 compliant mode should consider abstract method matches
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30825">30825</a>
-Missing REORDERED_IN_CLASSPATH notifications 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26909">26909</a>
-NPE opening type hierarchy for binary type
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29832">29832</a>
-Bogus quickfixes after removing/adding core plugins 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30699">30699</a>
-External JAR: no refresh in JavaModel if full build occurred before 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30697">30697</a>
-Classpath marker update could trigger automatic refresh for external JARs 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30805">30805</a>
-Abstract non-visible method diagnosis fooled by intermediate declarations
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=14597">14597</a>
-rearrange source code
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30417">30417</a>
-ICodeFormatter format method should specify that the positions are sorted from the lowest to the biggest
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30709">30709</a>
-Return value of IPackageFragementRoot.getElementName() has changed
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30705">30705</a>
-Simple name should consider member types before toplevel types
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30704">30704</a>
-01e0f should be accepted as valid floating point literal
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30511">30511</a>
-IPackageFragmentRoot:move ignores FORCE flag 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30516">30516</a>
-typo in javadoc of IPackageFragmentRoot:isArchive 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30506">30506</a>
-IPackageFragmentRoot:delete does not handle external jars 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20614">20614</a>
-Failure compiling a project with cyclic dependencies
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30227">30227</a>
-compilerAdapter jar should not be include in the repo
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30274">30274</a>
-Need method to figure out if an IResource is visible through the Java Model 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27027">27027</a>
-ClassCastException from codeassist
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30503">30503</a>
-IPackageFragmentRoot:move, copy should accept null as sibling 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30496">30496</a>
-CU/classfile name validation shouldn't scan if suffix isn't the proper one
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30471">30471</a>
-AST.parseCompilationUnit(IClassFile, boolean) throws IAE even if class file has source
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30487">30487</a>
-NPE during shutdown in path canonicalization
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26912">26912</a>
-'null == null' fooling blank final analysis
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30280">30280</a>
-NullPointerException at org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression.resolveType(QualifiedAllocationExpression.java:225)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30393">30393</a>
-Its back: Core Exception [code 380] The resource tree is locked for modifications 
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=5347">5347</a>
-class files not updated 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=9838">9838</a>
-Wrong diagnosis compiling inner classes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30600">30600</a>
-incorrect code assist after 'throw new'
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30799">30799</a>
-Core dump with J2SDK 1.4.1_01 in java.util.zip.ZipFile.getNextEntry
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30739">30739</a>
-\u4100 is rejected as an identifier character
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30782">30782</a>
-Can't rename a package to the same name with different case
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30522">30522</a>
-IPackageFragmentRoot: move, copy updateClasspath semantics 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30567">30567</a>
-GB18030: Class name, method name, variable name can not contain GB18030 character in some version of Eclipse for Linux.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30629">30629</a>
-search: no occurrences to type found if type in default package in nested source folder 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27770">27770</a>
-Rebuild all doesn't follow project dependencies
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24832">24832</a>
-Recurency between projects
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27750">27750</a>
-[startup] starting javacore takes 13% of empty worspace startup
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22710">22710</a>
-simple save takes 40 seconds
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30470">30470</a>
-IJavaModelStatus.getMessage not the same as getString 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30465">30465</a>
-PDE binary project import fills log with core exceptions
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28224">28224</a>
-Invalid "Unused Imports" warning when importing inner classes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27583">27583</a>
-reconciling allocates megabytes of memory in seconds of typing
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 28th January 2003
-<br>Project org.eclipse.jdt.core v_293
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> By default, JDT/Core will consider a default task tag "TODO" (with normal priority). In the past, default was no task reported. 
-<li> Added APIs to save/restore type hierarchies. Note that the client still has to register as a <code>ITypeHierarchyChangedListener</code> once
-restoration has occurred.
-  <ul>
-     <li> <code>ITypeHierarchy.store(OutputStream, IProgressMonitor)</code> for saving a type hierarchy.
-	 </li>
-     <li> <code>IType.load(InputStream, IProgressMonitor)</code> for restoring a previously saved hierarchy.
-	 </li>
-  </ul>
-</li> 
-<li> Added APIs to manipulate package fragment roots:
-	<ul>
-	<li><code>IPackageFragmentRoot.copy(IPath, int, boolean, IClasspathEntry, IProgressMonitor)</code>
-	</li>
-	<li><code>IPackageFragmentRoot.delete(int, boolean, IProgressMonitor)</code>
-	</li>
-	<li><code>IPackageFragmentRoot.move(IPath, int, boolean, IClasspathEntry, IProgressMonitor)</code>
-	</li>
-	</ul>
-	Note that these APIs are very close to the corresponding <code>IResource</code> APIs except that
-	they filter out nested source folders, and that they update the project's classpaths if specified.
-</li>
-<li> Extended compiler optional warning for interface methods incompatible with Object
-non public methods to scenario where thrown exceptions are not compatible (problem ID:
-<code>IProblem.IncompatibleExceptionInThrowsClauseForNonInheritedInterfaceMethod</code>).
-This problem is optional, and its severity is also controlled by the <code>JavaCore</code>
-preference <code>"org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod"</code>.
-</li>
-<li> 2.1 API Change in org.eclipse.jdt.core.NamingConventions: a new boolean parameter 'isBoolean' added. The value of this parameter is <code>true</code> if the field's type is boolean.
-	<ul>
-	<li><code>suggestSetterName(IJavaProject,char[],int,char[][])</code> become <code>suggestSetterName(IJavaProject,char[],int,boolean,char[][])</code>
-	</li>
-	<li><code>suggestSetterName(IJavaProject,String,int,String[])</code> become <code>suggestSetterName(IJavaProject,String,int,boolean,String[])</code>
-	</li>
-	</ul>
-	Previous APIs got deprecated, and will be removed before 2.1.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22049">22049</a>
-Hierarchy View slow to calculate hierarchy [type hierarchy]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29411">29411</a>
-Projects rebuilt after restart of Eclipse
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30282">30282</a>
-TODO task message shouldn't be multiline
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30102">30102</a>
-NamingConvention: Tests fail 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30113">30113</a>
-Wrong positions in the outliner for a field that follows an initializer 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30224">30224</a>
-No JavaElement delta when renaming non-Java project 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30108">30108</a>
-not clear what 'modifiers' in NamingConventions means 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30099">30099</a>
-NamingConvention.suggestArgumentNames: No guess returned 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27291">27291</a>
-[Dialogs] Error dialog looks bad if status message is null 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28666">28666</a>
-Unclear error message for invalid output folder 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29366">29366</a>
-Search reporting invalid inaccurate match 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29864">29864</a>
-Unable to restore working set item - cannot instantiate item: org.eclipse.jdt.ui.PersistableJavaElementFactory 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28044">28044</a>
-weird errors not reported anywhere but in text and overview ruler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30013">30013</a>
-Project compiler setting workspace | project do not persist
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29151">29151</a>
-NPE in Surround with try/catch block [refactoring]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29969">29969</a>
-CodeAssist: too much proposals just after 'switch'
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29955">29955</a>
-Should not report incompatible throws clause for interface if Object non public ref method
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29894">29894</a>
-Path matching failure (CharOperation)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29761">29761</a>
-Regular expression pattern in exclusion filter is too greedy in M4
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29761">29803</a>
-Source path exclusion filter not relative source folder
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23134">23134</a>
-Odd behavior from code formatter
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30357">30357</a>
-Incompatibility of serialization with sun jdk
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30370">30370</a>
-Warning "import never used" in spite of use by a javadoc @link
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30209">30209</a>
-JDT compiler bytecode incompatibility with JDK bytecode  results in serialization error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27497">27497</a>
-Compile only on class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28263">28263</a>
-Better specification of source folders
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30232">30232</a>
-NullPointerException in compilation unit
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=30160">30160</a>
-CodeAssist - no completion behind jProject
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29862">29862</a>
-GB18030:Could not set a GB18030 character as workbench classpath variable.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29863">29863</a>
-GB18030: Could not create a class variable whose name contains a GB18030 character
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27616">27616</a>
-[Compiler] stack overflow while editing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23299">23299</a>
-Enhance Code completion
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29239">29239</a>  
-Refactoring throws exception if .project or .classpath read-only in 2.1 M4 
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 21st January 2003
-<br>Project org.eclipse.jdt.core v_292a
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29872">29872</a>
-ImportOrganizeTest failing due to file missing from index 
-      
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 21st January 2003
-<br>Project org.eclipse.jdt.core v_292
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> New compiler setting got added to control severity of incompatible interface method with Object non public method.
-This used to be reported incorrectly as an error by our compiler (e.g. <code>interface I { int clone(); }</code>), and
-is now an optional problem (default severity is WARNING). Corresponding problem ID is: <code>IProblem.IncompatibleReturnTypeForNonInheritedInterfaceMethod</code>.
-<pre>
-* COMPILER / Reporting Interface Method not Compatible with non-Inherited Methods
-*    When enabled, the compiler will issue an error or a warning whenever an interface
-*    defines a method incompatible with a non-inherited Object one.
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "warning"
-</pre>
-</li>
-<li> New compiler problems got added to report declarations of unused private members (field/method/type). A JavaCore setting
-got added to control the severity of these new problems (default severity is IGNORE). Note that currently only a valid local usage 
-is considered as a true usage (e.g. if a message send targets this method, but cannot see it, then the target method will still be 
-reported as unused). Corresponding problem IDs are: <code>IProblem.UnusedPrivateMethod</code>, <code>IProblem.UnusedPrivateField</code>, 
-<code>IProblem.UnusedPrivateType</code> and <code>IProblem.UnusedPrivateConstructor</code>.
-<pre>
-* COMPILER / Reporting Unused Private Members
-*    When enabled, the compiler will issue an error or a warning whenever a private 
-*    method or field is declared but never used within the same unit.
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.unusedPrivateMember"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "ignore"
-</pre>
-</li>
-<li>CodeAssist now answers keyword completions. Note that there was already an API for these: <code>ICompletionRequestor#acceptKeyword(char[] keywordName, int completionStart, int completionEnd, int relevance)</code>
-which wasn't invoked until now. There is currently no way to distinguish in between a 'synchronized' keyword used as a modifier or as a statement.
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26363">26363</a>
-[ast/dom] type bindings that return null for superclass
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22381">22381</a>
-Show unused fields and variables [refactoring] [search]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19063">19063</a>
-code assist proposals for keywords
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29771">29771</a>
-No reference found to IResource.getLocation when no case sensitive
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28236">28236</a>
-Search for refs to class in hierarchy matches class outside hierarchy 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28951">28951</a>
-Source attachment rootpath field missing in UI 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29536">29536</a>
-Check use of IResource.getLocation 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29337">29337</a>
-Poor wording in task message "This method overrides deprecated..."
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29601">29601</a>
-TypeHierarchy: Avoid to use 'isInterface' / 'isClass' 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29540">29540</a>
-Search Engine return extra results 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29524">29524</a>
-Search for declaration via patterns adds '"*" 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26260">26260</a>
-task markers: limitting the number of problems per CU limits the number of tasks/markers (in general) per CU
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29306">29306</a>
-Can't get content of CU not on classpath 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3331">3331</a>
-DCR: Code Formatter should offer cast without space (1GI74GZ)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29690">29690</a>
-Locked Resource Tree (JavaModelException) 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29585">29585</a>
-Core Exception as resource tree is locked initializing classpath container 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29487">29487</a>
-Internal compiler error: final field set in loop (in constructor)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29546">29546</a>
-Project rebuild cannot write over .class files
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29636">29636</a>
-First anonymous type should be named X$1
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29638">29638</a>
-No field initializations on Object
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27413">27413</a>
-Should we reject that code?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29211">29211</a>
-Should check the visibility of the array type before accessing its length field
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29213">29213</a>
-Should check the visibility of the array type before calling a method
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29621">29621</a>
-Wrong Delta When Adding to Filtered Folder 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29637">29637</a>
-Default debug attributes don't match with javac
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29538">29538</a>
-External jar not indexed
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28489">28489</a>
-PackageFragmentRoot.fullExclusionPatternChars() could be optimized for non-source roots 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29298">29298</a>
-Simplify AST creation for an IClassFile (minor)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29374">29374</a>
-Excluded folder on project not returned by Java Model 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27485">27485</a>
-SearchEngine returns wrong java element when searching in an archive that is included by two distinct java projects. 
- 
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23300">23300</a>
-Context sensitive Code Completion
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29541">29541</a>
-Scrubbing wipes out entire build directory
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28393">28393</a>
-Duplicate 'missing require project' marker
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25976">25976</a>
-Bug in code formatter: can't be called twice in a row...
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25896">25896</a>
-weird formatting of import declarations
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26426">26426</a>
-Add preference to sort method in the source file.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25875">25875</a>
-import splitting behavior
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23992">23992</a>
-Adding partial compilation for JAVA
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19501">19501</a>
-Found NPE in log
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=13029">13029</a>
-"Build" sometimes builds files that have not changed
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=13008">13008</a>
-Move a Java file, errors remain
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=11572">11572</a>
-Cannot refresh a jar file
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=8720">8720</a>
-include an external directory of classes in Java build path
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3359">3359</a>
-Get rid of source attachment root (1GJON3Q)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28073">28073</a>
-[startup] on startup, jCore loads launching plugins which loads debug plugins
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29652">29652</a>
-Can't attach source to some ZIP files
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29229">29229</a>
-Internal compiler error 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28801">28801</a>
-Internal compiler error 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=18239">18239</a>
-Startup takes too long with java editor open
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28819">28819</a>
-Nullpointer exception when building
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28820">28820</a>
-NullPointerException in compiler in M4
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28953">28953</a>
-internal compiler error: NullPointerException in file with inner class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28954">28954</a>
-Internal compiler error -- assert statements in inner class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28980">28980</a>
-Null-pointer exception on nested class assert 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29267">29267</a>
-NullPointerExc. occured when building project 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29088">29088</a>
-Internal compiler error compiling code in M4 edition of eclipse
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29031">29031</a>
-Internal compiler error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=5520">5520</a>
-Class files which are source not shown
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3531">3531</a>
-NewClass(Interface)Wizard - shows not-visible types (1G4GNH3)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23033">23033</a>
-[Tasks] Create seperate setting for stopping build on a circular dependency error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28076">28076</a>
-NPE during quick shutdown
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29144">29144</a>
-Missing code implementation in the compiler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29527">29527</a>
-Organize imports fails on included code
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29501">29501</a>
-Uninitialized variable warning does not analyze the program thoroughly enough
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29394">29394</a>
-suboptimal handling closing/opening projects in autobuild
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29009">29009</a>
-ClassCircularityError in RequiredPluginsInitializer
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 15th January 2003
-<br>Project org.eclipse.jdt.core v_291a
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29516">29516</a>
-SearchEngine regressions in 20030114 
-      
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 14th January 2003
-<br>Project org.eclipse.jdt.core v_291
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28545">28545</a>
-JavaProject.exists() returns true if project doesn't have Java nature 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29404">29404</a>
-JavaCore.create(IProject) returns != null for non Java Projects. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28752">28752</a>
-J Search resports non-existent Java element 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22783">22783</a>
-Unexpected null in compiler error message
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29365">29365</a>
-Syntax error inside method body is fooling NLS string detection
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29277">29277</a>
-ToolFactory.createDefaultClassFileReader: Retrieving of classfile location
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29376">29376</a>
-Remove 65k limit on static data
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29176">29176</a>  
-[DOM/AST] Statement.get/setLeadingComment should be deleted 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29274">29274</a>
-Surface non-java projects as model non-java resources 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28531">28531</a>
-Classpath Entry: Output folder can not be set to project 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28824">28824</a>
-Quick Fix: Type Mismatch -> Cast bug [quick fix]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28599">28599</a>
-validateClasspath rendering of paths 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29079">29079</a>
-Buildpath validation: No check that output folder is inside project 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29159">29159</a>
-DeltaProcessor walks removed project 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28822">28822</a>
-ClassCastException in ProblemBinding 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28596">28596</a>
-Default output folder cause of validation error even if not used 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28672">28672</a>
-Batch compiler should support argument expansion
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28617">28617</a>
-Qualified super reference cannot be surrounded with parentheses.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27298">27298</a>
-Must return result error could be more accurate
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28869">28869</a>
-Parse error with final local vars without immediate assignment
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28682">28682</a>
-org.eclipse.jdt.core.dom.ForStatement's body position is incorrect
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28622">28622</a>
-Check deprecation should handle unicodes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28559">28559</a>
-@deprecated has to be at the beginning of the comment line
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20844">20844</a>
-Indexing space usage
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26820">26820</a>
-Out of Memory indexing new plugins
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27289">27289</a>
-ClassCircularityError forces ClassNotFoundException's
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27401">27401</a>
-[startup] Review JavaCore.startup()
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28557">28557</a>
-Deprecation is not checked when subclassing a deprecated member type
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28615">28615</a>
-Cannot optimize out -0.0 in array initializers
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28750">28750</a>
-Compiler crashes with M4
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27241">27241</a>
-Missing code generation for the qualifier of a static method invocation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3173">3173</a>
-Constant field code generation (1FEWXZW)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28583">28583</a>
-Missing one unit in package view 
-   
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28934">28934</a>
-Using assert keyword in methods of nested classes causes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25980">25980</a>
-NullPointerException during Refactor/Move operation 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29343">29343</a>
-[M4] Scribbling on missing return statement needs to go on a diet
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29197">29197</a>
-NullPointerException when compiling Class with an assert in a method of an inner class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29082">29082</a>
-Can't access Inner class static field through an instance
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28675">28675</a>
-NPE in indexer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28908">28908</a>
-ClassCastException in JavaProject.computePackageFragmentRoots
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27430">27430</a>
-Java model hangs onto many ClassFile objects
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=29030">29030</a>
-Compiler Bug -- incorrect visibility of protected constructors
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28830">28830</a>
-Flexible projects cannot share output directory
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 17th December 2002 - 2.1 MILESTONE-4
-<br>Project org.eclipse.jdt.core v_290
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added new JavaCore options
-	<ul>
-	<li>CODEASSIST / Define the Prefixes for Field Name<br>
-		When the prefixes is non empty, completion for field name will begin with
-		one of the proposed prefixes.<br>
-		<ul>
-		<li>option id: "org.eclipse.jdt.core.codeComplete.fieldPrefixes"</li>
-		<li>possible values: { "&lt;prefix&gt;[,&lt;prefix&gt;]*" } where &lt;prefix&gt; is a String without any wild-card</li>
-		<li>default: ""</li>
-	 	</ul>
-	</li>
-	<li>CODEASSIST / Define the Prefixes for Static Field Name<br>
-		When the prefixes is non empty, completion for static field name will begin with
-		one of the proposed prefixes.<br>
-		<ul>
-		<li>option id: "org.eclipse.jdt.core.codeComplete.staticFieldPrefixes"</li>
-		<li>possible values: { "&lt;prefix&gt;[,&lt;prefix&gt;]*" } where &lt;prefix&gt; is a String without any wild-card</li>
-		<li>default: ""</li>
-	 	</ul>
-	</li>
-	<li>CODEASSIST / Define the Prefixes for Local Variable Name<br>
-		When the prefixes is non empty, completion for local variable name will begin with
-		one of the proposed prefixes.<br>
-		<ul>
-		<li>option id: "org.eclipse.jdt.core.codeComplete.localPrefixes"</li>
-		<li>possible values: { "&lt;prefix&gt;[,&lt;prefix&gt;]*" } where &lt;prefix&gt; is a String without any wild-card</li>
-		<li>default: ""</li>
-	 	</ul>
-	</li>
-	<li>CODEASSIST / Define the Prefixes for Argument Name<br>
-		When the prefixes is non empty, completion for argument name will begin with
-		one of the proposed prefixes.<br>
-		<ul>
-		<li>option id: "org.eclipse.jdt.core.codeComplete.argumentPrefixes"</li>
-		<li>possible values: { "&lt;prefix&gt;[,&lt;prefix&gt;]*" } where &lt;prefix&gt; is a String without any wild-card</li>
-		<li>default: ""</li>
-	 	</ul>
-	</li>
-	<li>CODEASSIST / Define the Suffixes for Field Name<br>
-		When the suffixes is non empty, completion for field name will end with
-		one of the proposed suffixes.<br>
-		<ul>
-		<li>option id: "org.eclipse.jdt.core.codeComplete.fieldSuffixes"</li>
-		<li>possible values: { "&lt;suffix&gt;[,&lt;suffix&gt;]*" } where &lt;suffix&gt; is a String without any wild-card </li>
-		<li>default: ""</li>
-	 	</ul>
-	</li>
-	<li>ODEASSIST / Define the Suffixes for Static Field Name<br>
-		When the suffixes is non empty, completion for static field name will end with
-		one of the proposed suffixes.<br>
-		<ul>
-		<li>option id: "org.eclipse.jdt.core.codeComplete.staticFieldSuffixes"</li>
-		<li>possible values: { "&lt;suffix&gt;[,&lt;suffix&gt;]*" } where &lt;suffix&gt; is a String without any wild-card </li>
-		<li>default: ""</li>
-	 	</ul>
-	</li>
-	<li>CODEASSIST / Define the Suffixes for Local Variable Name<br>
-		When the suffixes is non empty, completion for local variable name will end with
-		one of the proposed suffixes.<br>
-		<ul>
-		<li>option id: "org.eclipse.jdt.core.codeComplete.localSuffixes"</li>
-		<li>possible values: { "&lt;suffix&gt;[,&lt;suffix&gt;]*" } where &lt;suffix&gt; is a String without any wild-card </li>
-		<li>default: ""</li>
-	 	</ul>
-	</li>
-	<li>CODEASSIST / Define the Suffixes for Argument Name<br>
-		When the suffixes is non empty, completion for argument name will end with
-		one of the proposed suffixes.<br>
-		<ul>
-		<li>option id: "org.eclipse.jdt.core.codeComplete.argumentSuffixes"</li>
-		<li>possible values: { "&lt;suffix&gt;[,&lt;suffix&gt;]*" } where &lt;suffix&gt; is a String without any wild-card </li>
-		<li>default: ""</li>
-	 	</ul>
-	</li>
-	</ul>
-</li>
-<li>New API class : org.eclipse.jdt.core.NamingConventions<br>
-This class provides methods for computing Java-specific names.
-<pre>
-package org.eclipse.jdt.core;
-public final class NamingConventions {
-	public static char[] removePrefixAndSuffixForArgumentName(IJavaProject javaProject, char[] argumentName) {...}
-	public static String removePrefixAndSuffixForArgumentName(IJavaProject javaProject, String argumentName) {...}
-	public static char[] removePrefixAndSuffixForFieldName(IJavaProject javaProject, char[] fieldName, int modifiers) {...}
-	public static String removePrefixAndSuffixForFieldName(IJavaProject javaProject, String fieldName, int modifiers) {...}
-	public static char[] removePrefixAndSuffixForLocalVariableName(IJavaProject javaProject, char[] localName) {...}
-	public static String removePrefixAndSuffixForLocalVariableName(IJavaProject javaProject, String localName) {...}
-	public static char[][] suggestArgumentNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[][] excludedNames) {...}
-	public static String[] suggestArgumentNames(IJavaProject javaProject, String packageName, String qualifiedTypeName, int dim, String[] excludedNames) {...}
-	public static char[][] suggestFieldNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, int modifiers, char[][] excludedNames) {...}
-	public static String[] suggestFieldNames(IJavaProject javaProject, String packageName, String qualifiedTypeName, int dim, int modifiers, String[] excludedNames) {...}
-	public static char[][] suggestLocalVariableNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[][] excludedNames) {...}
-	public static String[] suggestLocalVariableNames(IJavaProject javaProject, String packageName, String qualifiedTypeName, int dim, String[] excludedNames) {...}
-	public static char[] suggestGetterName(IJavaProject project, char[] fieldName, int modifiers, boolean isBoolean, char[][] excludedNames) {...}
-	public static String suggestGetterName(IJavaProject project, String fieldName, int modifiers, boolean isBoolean, String[] excludedNames) {...}
-	public static char[] suggestSetterName(IJavaProject project, char[] fieldName, int modifiers, char[][] excludedNames) {...}
-	public static String suggestSetterName(IJavaProject project, String fieldName, int modifiers, String[] excludedNames) {...}
-}
-</pre>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28434">28434</a>
-Open Type broken when workspace has build path problems 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28326">28326</a>
-"Open Type" dialog could not open selected type 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28476">28476</a>
-JRE container description wrong
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28447">28447</a>
-Unreadable error message from build class path validation 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23210">23210</a>
-Member variable name proposal
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27925">27925</a>
-Openable.hasChildren is slow 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28246">28246</a>
-Class files written to custom output and default output
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27275">27275</a>
-Random craches with corupt jar in library path
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28357">28357</a>
-NPE on importing plugins
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 16th December 2002
-<br>Project org.eclipse.jdt.core v_289
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28316">28316</a>
-Missing references to constructor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28104">28104</a>
-33 Parsers and 35 Scanners created when opening a type hiearchy 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28298">28298</a>
-SANITY CHECK error when compiling a specific switch statement
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28296">28296</a>
-parser gives cast expression an incorrect length
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28000">28000</a>
-Too many deltas on startup, when resolving cp variables/containers
-
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 13th December 2002
-<br>Project org.eclipse.jdt.core v_288
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28109">28109</a>
-Excluding a source file doesn't remove its Java problems
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28115">28115</a>
-Ubiquitous resource in the JavaModel 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28064">28064</a>
-Stack overflow in java editor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28150">28150</a>  
-ClassCastException in completion
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22139">22139</a>
-Array initializer used inline causes syntax error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27941">27941</a>  
-ClassCastException in CompletionParser
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27284">27284</a>  
-misspelled variable name proposals for array with type name ending in 'y'
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27852">27852</a>  
-We should not reject a class named java if it is in the unnamed package
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28208">28208</a>
-IClasspathEntry.getExclusionPattern: String[] would be better
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28114">28114</a>
-Missing type if defined in nested source folder
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27371">27371</a>
-code assist / auto inserting "()" broken
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28087">28087</a>
-on build, findMarkers called 3 times for each project
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27992">27992</a>
-Incremental compile time = complete build time
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28095">28095</a>
-JDTCompilerAdapter references old Main constructor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23231">23231</a>  
-[resources] Ability to hide resources from the builders
-  
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 11th December 2002
-<br>Project org.eclipse.jdt.core v_287a
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=28069">28069</a>
-JDTCompilerAdapter and compiler.batch.Main out of sync in I20021210 build
-
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 10th December 2002 
-<br>Project org.eclipse.jdt.core v_287
-<h2>
-What's new in this drop</h2>
-<ul> 
-<li>Added API <code>IJavaProject.isOnClasspath(IResource)</code> that returns whether a given resource is on the 
-     classpath of the project and whether it is excluded.
-</li>
-<li>Added mechanism to allow generic container user to request updating definitions held by
-container initializers, onto <code>org.eclipse.jdt.core.ClasspathContainerInitializer</code>:
-
-<pre>
-/**
- * Returns <code>true</code> if this container initializer can be requested to perform updates 
- * on its own container values. If so, then an update request will be performed using
- * <code>ClasspathContainerInitializer#requestClasspathContainerUpdate</code>/
- * 
- * @param containerPath - the path of the container which requires to be updated
- * @param project - the project for which the container is to be updated
- * @return boolean - returns <code>true</code> if the container can be updated
- * @since 2.1
- */
-public boolean canUpdateClasspathContainer(IPath containerPath, IJavaProject project) {
-	// By default, classpath container initializers do not accept updating containers
-   	return false; 
-}</pre>
-<pre>
-/**
- * Request a registered container definition to be updated according to a container suggestion. The container suggestion 
- * only acts as a place-holder to pass along the information to update the matching container definition(s) held by the 
- * container initializer. In particular, it is not expected to store the container suggestion as is, but rather adjust 
- * the actual container definition based on suggested changes.
- * 
- * IMPORTANT: In reaction to receiving an update request, a container initializer will update the corresponding
- * container definition (after reconciling changes) at its earliest convenience, using 
- * <code>JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)</code>. 
- * Until it does so, the update will not be reflected in the Java Model.
- * 
- * In order to anticipate whether the container initializer allows to update its containers, the predicate
- * <code>JavaCore#canUpdateClasspathContainer</code> should be used.
- * 
- * @param containerPath - the path of the container which requires to be updated
- * @param project - the project for which the container is to be updated
- * @param containerSuggestion - a suggestion to update the corresponding container definition
- * @throws CoreException when <code>JavaCore#setClasspathContainer</code> would throw any.
- * @see JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)
- * @see ClasspathContainerInitializer#canUpdateClasspathContainer(IPath, IJavaProject)
- * @since 2.1
- */
-public void requestClasspathContainerUpdate(IPath containerPath, IJavaProject project, IClasspathContainer containerSuggestion) throws CoreException {
-	// By default, classpath container initializers do not accept updating containers
-}</pre>
-</li>
-<li>Added helper method to <code>org.eclipse.jdt.core.JavaCore</code> so as to retrieve a registered 
-classpath container initializer:
-<pre>/**
- * Helper method finding the classpath container initializer registered for a given classpath container ID 
- * or <code>null</code> if none was found while iterating over the contributions to extension point to
- * the extension point "org.eclipse.jdt.core.classpathContainerInitializer".
- * 
- * A containerID is the first segment of any container path, used to identify the registered container initializer.
- * 
- * @return ClasspathContainerInitializer - the registered classpath container initializer or <code>null</code> if 
- * none was found.
- * @since 2.1
- */
-public static ClasspathContainerInitializer getClasspathContainerInitializer(String containerID)</pre>
-</li>
-</ul> 
- 
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27890">27890</a>
-Batch compiler option -nowarn or -warn:none doesn't remove the warning for conversion from char[] to String
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27670">27670</a>
-ClasspathEntry.rootID allocates a lot of throw-away objects
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27595">27595</a>
-Add isOnClasspath(IResource) as API 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27652">27652</a>
-DCR - Need a way to request container initializers to update their container definitions
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27555">27555</a>
-[startup] PackageFragmentRoot - source attached too early (?) 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27861">27861</a>
-VerifyError not being caught in jdt core tests
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27914">27914</a>
-Infinite loop setting breakpoint
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27853">27853</a>
-Incorrect invalid unicode
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27840">27840</a>
-Computing non-java resources on a project should not create a NameLookup 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27690">27690</a>
-SourceElementParser doesn't parse local declarations even if it is requested
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=5295">5295</a>
-Segmented view misses field comment
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27714">27714</a>
-JavaElement.newNotPresentException 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27735">27735</a>
-CodeAssist - No completion for type
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27370">27370</a>
-code assist not working with "new .."
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27658">27658</a>
-Infinite loop when checking cycle
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27683">27683</a>
-Index should be saved right after a project was indexed 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27330">27330</a>
-Signeture should reuse Scanner object 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27294">27294</a>
-Performance - getTypeSignature should not rescan element names 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26604">26604</a>
-Forward references unilaterally dissallowed
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27532">27532</a>
-Rebuild sometimes introduces invalid errors
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27597">27597</a>
-Ant adapter on a 1.4 JVM sets the target to be 1.4
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27494">27494</a>
-Source folder output folder shown in Package explorer 
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27783">27783</a>
-Build output folder should not always be in the project subdirectories
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27600">27600</a>
-NPE while searching
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26602">26602</a>
-Incremental compile/build produces invalid header classes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25752">25752</a>
-References list displays nulls for package name parts 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26967">26967</a>
-Upon exit always receive "JVM Terminated message"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27748">27748</a>
-JUnit import fails
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27660">27660</a>
-Stack overflow causes startup crash 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27236">27236</a>
-search: references to constructors - a subclass constructor reported 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27603">27603</a>
-NPE in AbstractImageBuilder
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27448">27448</a>
-using SearchEngine the constructors, inner classes or packages are not found 
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 3rd December 2002 
-<br>Project org.eclipse.jdt.core v_286
-<h2>
-What's new in this drop</h2>
-<ul> 
-<li><b>Code completion enhancement:</b>
-   <ul>
-   <li>Relevance of a proposal is higher if the proposal is after an operator and the type of
-   proposal is compatible with the operator.
-   <br>In the following example <code>var1</code> is more relevant than <code>var2</code>.<pre>
-   public class X {
-      int var1;
-      Object var2;
-      void foo() {
-         int i = 1 + var&lt;cursor&gt;
-      }
-   }</pre>
-   </li>
-   </ul>
-</li>
-</ul> 
- 
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27487">27487</a>
-Builder doesn't handle move to nested source folder
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27499">27499</a>
-Bogus ClasspathVariableInitializer is found in JavaModel 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22039">22039</a>
-Provide facility to exclude files from compilation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26251">26251</a>
-project compiler settings : some are not set
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25538">25538</a>
-Conflict of classfolder and outputfolder not reported 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27310">27310</a>
-CompilationUnit#lineNumber(..) doc seems flawed
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27235">27235</a>  
-Bug with assignement with no effect mask
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25928">25928</a>
-Cannot nest entries in Java Build Path - Request for Feature Removal 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26806">26806</a>
-Source build path should allow subdirectories of directories already on path
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27322">27322</a>
-ClassCastException during code assist
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27247">27247</a>  
-Missing generation for the qualifier in 1.4 mode
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22407">22407</a>  
-Can't set Java project build output folder to different project
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27250">27250</a>  
-Walkback asking for a full rebuild
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27173">27173</a>  
-API: add methodInvocation.resolveMethodBinding 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24123">24123</a>
-Support for multiple output dirs
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27151">27151</a>
-NPE searching in hierarchy 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24308">24308</a>
-Performance - Optimization of search in hierarchy 
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27204">27204</a>
-AST.lineNumber(position) is not working, if the class didn't have a new line at the end of file.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27374">27374</a>
-project specific JRE settings
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27295">27295</a>
-Relevance of member type in type cast should be higher 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27254">27254</a>
-Inexact matches found when search references to UnconditionalFlowContext#maxFieldCount 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26938">26938</a>
-Build Project-command removes all from build-dir
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 26th November 2002 
-<br>Project org.eclipse.jdt.core v_285
-<h2>
-What's new in this drop</h2>
-<ul> 
-<li><b>Source attachment enhancements:</b> 
-	<ul>
-	<li><b>Source folder attachment:</b> The source attachment mechanism got generalized to all binary 
-		  package fragment root. In the past, only archives did support to carry a source attachment, in the 
-		  form of a source archive. Now, both binary folder or archive can be associated with sources, which 
-		  can be either a source archive or a source folder. In particular, mixed modes are supported (binary 
-		  archive associated to source folder and reciprocally). For more details, see 
-		  <code>IPackageFragmentRoot.attachSource(IPath, IPath, IProgressMonitor)</code> and 
-		  <code>JavaCore.newLibraryEntry(...)</code>.
-	</li>
-	<li><b>Automatic root path detection:</b> If null is specified as the root path (see 
-		  <code>JavaCore.newLibraryEntry(...)</code> and <code>IPackageFragmentRoot.attachSource(...)</code>), 
-		  then the Java Model will do its best to compute this root path automatically. The underlying algorithm 
-		  finds the first .java file, parses it, and extract the package declaration to compute the root path.
-	</li>
-	<li><b>Root path detection:</b> The new API 
-		  <code>IPackageFragmentRoot.computeSourceAttachmentRootPath(IPath sourceAttachmentPath)</code> 
-		  allows to detect the root path for a given source attachment and package fragment root.
-	</li>
-	</ul>
-</li>
-<li><b>Code completion enhancement:</b>
-   <ul>
-   <li>Relevance of a proposal is lesser if the proposal is in a variable initializer and the proposal is the variable.
-   <br>In the following example <code>var2</code> is less relevant than <code>var1</code>.<pre>
-   public class X {
-      int var1;
-      int var2 = var&lt;cursor&gt;
-   }</pre>
-   </li>
-   <li>Relevance of a proposal is lesser if the proposal is static and the qualified expression is non-static.
-   <br>In the following example <code>var2</code> is more relevant than <code>var1</code>.<pre>
-   public class X {
-      static int var1;
-      int var2;
-      void foo() {
-         this.var&lt;cursor&gt;
-      }
-   }</pre>
-   </li>
-   <li>Relevance of a proposal is higher if the completion is not qualified or is a local variable.
-   <br>In the following example the field <code>var2</code> and the parameter <code>var1</code> are more relevant
-   than field <code>var1</code>.<pre>
-   public class X {
-      int var1;
-      int var2;
-      void foo(int var1) {
-         var&lt;cursor&gt;
-      }
-   }</pre>
-   </li>
-   <li>Relevance of a proposal is higher if the proposal is equals to the current token.
-   <br>In the following example the field <code>var</code> is more relevant than field <code>varPlus</code>.<pre>
-   public class X {
-      int var;
-      int varPlus;
-      void foo() {
-         var&lt;cursor&gt;
-      }
-   }</pre>
-   </li>
-   </ul>
-</li>
-</ul> 
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24916">24916</a>
-quick fix: does not handle additional dimentions sometimes [quick fix]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26903">26903</a>
-VerifyError when casting null to an array type 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=27002">27002</a>
-Scanner  allocates new ArrayList(10) everytime it's created
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26912">26912</a>
-'null == null' fooling blank final analysis
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26817">26817</a>
-Class File Editor shows words translated which shouldn't be 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26452">26452</a>
-Wrong automatically generated import statements 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26881">26881</a>
-Yoyo in the debugger again
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26753">26753</a>
-Suspicious yoyo behavior when stepping through if condition
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25148">25148</a>
-Can't have different case package names
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26883">26883</a>
-Should report unitialized blank final field
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20932">20932</a>
-Cannot add a source directory as the source of a JAR file. 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=8719">8719</a>
-DCR - Attac h Java Source: allow un-jarred source tree? 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6912">6912</a>
-Attach Source Requires JAR/ZIP 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26255">26255</a>
-project compiler settings : cannot go back to worspace settings
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26841">26841</a>
-Compiler - Does not detect non-visible member type in import
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26784">26784</a>
-problem M3 sourcebuild, linux/gtk - build error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26706">26706</a>
-Cannot create project with comma characters in project path 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26195">26195</a>
-JDT compiler doesn't report recursive constructor invocation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26747">26747</a>
-IllegalArgumentException reading build state
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3243">3243</a>
-SourceAttachment - automatic computation of the package root does not work (1GCMTLP) 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26785">26785</a>
-Unreachable empty blocks should be reported in 1.4 compliant mode
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26664">26664</a>
-deprecated interfaces are not allways recognized
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26759">26759</a>
-Cast Compiler Error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26134">26134</a>
-JACKS - VerifyError running invalid code
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26253">26253</a>
-task tags: two tags on one line creates one task for first tag
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26677">26677</a>
-Code Assist - expected type must be qualified.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23542">23542</a>
-CodeAssist proposal should offer non-qualified ones first
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25890">25890</a>
-code assist displays static members on non-static expressions
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26025">26025</a>
-Search should not use a file based name environment 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26138">26138</a>
-JACKS - The null literal should not be considered as a constant expression
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26585">26585</a>
-Wrong code generation in conditional expression
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26588">26588</a>
-Code Assist - variable must be less relevant in initialization
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26142">26142</a>
-JACKS: Must reject invalid character after class definition
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26141">26141</a>
-JACKS: Should report unterminated comment
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26129">26129</a>
-JACKS: VerifyError, because opcode jsr_w not used
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25888">25888</a>
-Open on selection fails on private binary inner class contructor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23126">23126</a>
-allow selecting directories when attaching source to jar's 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22145">22145</a>
-Attach source directory in addition to archive file [build path] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26459">26459</a>  
-Unused NonVoidMethodRequestor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26122">26122</a>  
-JACKS: VerifyError when affecting final local in anonymous class header
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26124">26124</a>  
-JACKS - Compile error not reported when break; used in a labeled statement
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24934">24934</a>
-Move top level doesn't optimize the imports[refactoring] 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25250">25250</a>
-Scrapbook shows wrong error message
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26580">26580</a>
-java element deltas not sent out? 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21837">21837</a>
-Eclipse hangs trying to set a breakpoint 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25406">25406</a>
-Package name change disallowed  because of case insensitivity
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26885">26885</a>
-binary representation wrongly flagged as error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26526">26526</a>
-Inner class imports flagged as errors
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26652">26652</a>
-Encountered  "case statement must be constant" error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23076">23076</a>
-compilation does not create class files!!!
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24015">24015</a>
-CVS synchronize with outgoing changes only causes Java rebuild
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25478">25478</a>
-Unresolvable import statements Problem Marker malfunctioning
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26658">26658</a>
-No deprecation warning
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26132">26132</a>
-JACKS - Blank final instance must be assigned before the end of constructor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26340">26340</a>
-Using javadoc comments to generate and manage bookmarks.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=9020">9020</a>
-More intelligent code assist.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25962">25962</a>
-Output classes is scrubbed due to error in compiling a source.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26166">26166</a>
-compile single file
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25684">25684</a>
-SelectionEngine to be made API?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26454">26454</a>  
-DCR: IScanner.setSourceReader
-  
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 14th November 2002 - 2.1 MILESTONE-3
-<br>Project org.eclipse.jdt.core v_284
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26259">26259</a>  
-Errors reported on save which go aways on rebuild
-
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 13th November 2002
-<br>Project org.eclipse.jdt.core v_283
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26128">26128</a>  
-packages don't appear in package explorer view 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26044">26044</a>
-Unexpected full builds
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26098">26098</a>
-Wrong line number attribute.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24517">24517</a>
-type view does not notice when jar disappears 
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26063">26063</a>  
-MacOS X: Error saving files
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 12th November 2002
-<br>Project org.eclipse.jdt.core v_282b
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>In case someone deletes the .classpath and no corresponding classpath exists in memory,
-      a default .classpath is not automatically created any longer but a marker is created on the
-      project preventing this project from being built.
-      This covers the following scenarii:
-      <ul>
-      <li>Someone checks in a .project file with the Java nature but doesn't check in the .classpath file.
-            When the project is checked out, a marker is created indicating the .classpath file could not 
-            be read.</li>
-      <li>Someone shuts down the workbench, deletes the .classpath and restart the workspace.
-            When attempting to built the project,  a marker is created indicating the .classpath file could 
-            not be read and the project is not built.</li>
-       <li>The Java nature is added to a project without a .classpath file. A marker is created indicating 
-       		the .classpath file could not be read.
-      </ul>
-</li>
-<li><b>Selectivity API</b> - Source folders can be associated with filters allowing to exclude
-specified portions of the resource tree rooted at this source entry's path. Exclusion patterns 
-are expressed using the Ant file pattern syntax (i.e. **, *, ? wild-cards; where ** can stand for
-one or many folder names).
-   <ul>
-   <li>Added <code>JavaCore.newSourceEntry(IPath path, <b>IPath[] exclusionPatterns</b>)</code>
-   </li>
-   <li>Added <code>IClasspathEntry.getExclusionPatterns()</code>
-   </li>
-   </ul>
-   Full implementation will be available by 2.1 milestone-4.
-</li>
-<li><b>Multiple output folder API</b> - Source folders can be associated with a specific output
-location. The project output location is now corresponding to a default output location.
-   <ul>
-   <li>Added <code>JavaCore.newSourceEntry(IPath path, IPath[] exclusionPatterns, <b>IPath specificOutputLocation</b>)</code>
-   </li>
-   <li>Added <code>IClasspathEntry.getOutputLocation()</code>
-   </li>
-   </ul>
-   Full implementation will be available by 2.1 milestone-4.
-</li>
-<li>The Java builder now iterates over the resource tree, allowing to take advantage of forthcoming 
-workspace structure enhancements (in particular: linked folders). As a consequence, the Java builder
-will only consider the resources officially reflected in the resource tree (as opposed to existing 
-underlying files not yet reflected when the resource tree is out of sync).
-Note that the build state format has changed to reflect this evolution, as a consequence, if reusing an existing
-workspace, the first build action will have to be a rebuild-all projects, since incrementally it will
-not be able to re-read old build states associated with prerequisite projects (and an incremental build
-cannot tell the build manager a full rebuild is necessary). 
-</li>
-<li>An option allows to control whether the Java builder should clean the output folder(s). Since
-options can be specified on a per project basis, each individual project can be toggled for cleaning
-the output folder or not (default is to clean). Also, "scrubbing" output folder got renamed into 
-"cleaning" output folder. 
-<pre>
-* BUILDER / Cleaning Output Folder(s)
-*    Indicate whether the JavaBuilder is allowed to clean the output folders
-*    when performing full build operations.
-*     - option id:       "org.eclipse.jdt.core.builder.cleanOutputFolder"
-*     - possible values: { "clean", "ignore" }
-*     - default:         "clean"
-</pre>
-</li>
-<li>Integrated patch from Genady Beriozkin for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25092">25092</a>.
-The compiler will now optionally diagnose assignments having no effect (e.g. x = x).
-Added the following option to control this behavior.
-<pre>
-* COMPILER / Reporting Assignment with no effect
-*    When enabled, the compiler will issue an error or a warning whenever an assignment
-*    has no effect (e.g 'x = x').
-*     - option id:         "org.eclipse.jdt.core.compiler.problem.noEffectAssignment"
-*     - possible values:   { "error", "warning", "ignore" }
-*     - default:           "warning"
-</pre>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=26053">26053</a>
-builder out of order in I-20021112
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25859">25859</a>
-Error doing Java Search 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25092">25092</a>  
-Detect/Warn on possible user typos
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25894">25894</a>  
-Memory leak - Global ThisReference is leaking bindings
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25885">25885</a>  
-Code Assist - exact expected type should be more relevant than subtype
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25184">25184</a>  
-Operations on cu outside classpath should fail 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25876">25876</a>  
-Code Assist - void method are proposed in assignment
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23586">23586</a>  
-Creating a new project deletes files in the parent folder 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25815">25815</a>
-Code Assist does not propose member type.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25820">25820</a>
-NPE in Code Assist
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25811">25811</a>
-Code Assist for variable name suggestion is not perfect.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24010">24010</a>
-IType::resolveType returns null for inner types
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25735">25735</a>
-Non-NLS strings are not reported properly when the ending tag is missing
-  
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22509">22509</a>  
-Unable to start some Java application
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21864">21864</a>  
-Associate package hierarchy with top-level source directory
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12957">12957</a>  
-Copied resources out of synch
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24276">24276</a>  
-javadoc - Imports marked as unused when they are really necessary.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=18320">18320</a>  
-Compiler Warning/Error/Ignore when Assigning to a Parameter
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25994">25994</a>  
-Marker for "static method should be accessed in a static way"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25995">25995</a>  
-Marker for "static method should be accessed in a static way"
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25582">25582</a>  
-Cannot specify java source path for resource !
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25665">25665</a>  
-AST adds implicit super call (PR 22306 needed on 2.0.2 stream)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25304">25304</a>  
-Code assist and parameter assistance.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24783">24783</a>  
-method parameter name code completion 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25872">25872</a>  
-Eclipse considers the Unicode char '\u000A' an invalid character constant.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25255">25255</a>  
-ICompilationUnit::getUnderlyingResource throws an exception 
-   
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 5th November 2002
-<br>Project org.eclipse.jdt.core v_281
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Code completion enhancement:
-   <ul>
-   <li>Relevance of a proposal is higher if the proposal is in a variable initializer and its type is compatible with the variable type.
-   <br>In the following example <code>var2</code> is more relevant than <code>var1</code>.<pre>
-   public class X {
-      Object var1;
-      int var2;
-      void foo() {
-         int i = var&lt;cursor&gt;
-      }
-   }</pre>
-   </li>
-   <li>Relevance of a proposal is higher if the proposal is on the right hand side of an assignment and its type is compatible with the left hand side type.
-   <br>In the following example <code>var2</code> is more relevant than <code>var1</code>.<pre>
-   public class X {
-      Object var1;
-      int var2;
-      void foo() {
-         int i;
-         i = var&lt;cursor&gt;
-      }
-   }</pre>
-   </li>
-   </ul>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24626">24626</a>
-codeSelect - does not work in catch clause
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25688">25688</a>
-Non NLS strings improperly reported when the line separator is \r only
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25687">25687</a>
-codeSelect - fails with inner class as method parameter
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25605">25605</a>
-[API] someJavaProject.getRequiredProjectNames(); API should specify that the array is returned in ClassPath order 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25358">25358</a>
-Creating a new Java class - Browse for parent 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25495">25495</a>
-Ant compiler adapter should treat bogus imports as errors
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21957">21957</a>  
-'refactor rename' allows subpackage name to start with a space 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25591">25591</a>  
-ClassCastException in CompletionEngine
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25539">25539</a>  
-Unexpected inaccurate search results 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25578">25578</a>
-Abstract method declaration completion should be more relevant
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25221">25221</a>
-Code assist after new keyword
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25347">25347</a>
-Deprecation-Flag in Ant doesn't work with Eclipse Compiler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25551">25551</a>
-Ant javac adapter always reports build successful even if there are compiler errors
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24939">24939</a>  
-Code Assist doesn't find protected constructor for anonymous class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3717">3717</a>  
-Smoke 114: Progress reporting when switching to different default VM (1GEHXMV) 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24565">24565</a>
-CodeAssist proposing twice the same method
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25520">25520</a>
-Possible problem in JavaProject#findPackageFragmentRoots(IClasspathEntry)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24518">24518</a>
-Public flag not set for interface method 
-     
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=18212">18212</a>  
-Java Build Paths no updated correctly when checking out multiple projects 
-   
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 29th October 2002
-<br>Project org.eclipse.jdt.core v_280
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>In 1.4 compliant mode, the compiler will report errors for unterminated line comments (i.e. not closed with a line break). For backward compatibility reason,
-the stricter check isn't performed in 1.3 compliant mode. See <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23096">23096</a> for further details.
-Also note that from now on, the trailing line break is part of the line comment source range.
-</li>
-<li>The API setLeadingComment(String) on org.eclipse.jdt.core.dom.Statement class has been updated to reflect the changes made for <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23096">23096</a>.
-This API strictly fits to the JLS. It doesn't use the compliance mode settings. So a line comment needs to be closed with a line break in
-order to be valid.
-See <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25206">25206</a> for further details.</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22358">22358</a>
-[api] Would like CharOperation made API
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23207">23207</a>  
-Flags.isDeprecated(IMethod.getFlags()) doesn't work 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23984">23984</a>
-validateEdit not called when changing .classpath
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25439">25439</a>
-toString() on IBinding subclasses
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25347">25347</a>
-Deprecation-Flag in Ant doesn't work with Eclipse Compiler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25396">25396</a>
-NPE importing external plug-ins
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25433">25433</a>
-#findPackageFragmentRoots(IClasspathEntry)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25377">25377</a>
-Error location is not correct for empty array initializer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25174">25174</a>
-Wrong code generation of the eclipse java compiler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25298">25298</a>
-One out of two non-externalized strings reported
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25188">25188</a>
-Debugger won't stop on method first statement breakpoint
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25233">25233</a>
-NPE in CompletionParser.buildMoreCompletionContext
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25206">25206</a>
-DOM/AST: Statement.setLeadingComment specification is inconsistent with the JLS
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25229">25229</a>
-Compiler should not reject innerclass scenario
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25183">25183</a>
-AST: ITypeBinding of interface returns constructor
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24833">24833</a>
-TODO: not detected if there is only a comment in .java file
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24744">24744</a>
-TODO: Task not found if comment after last closing brace
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23096">23096</a>
-Compiler does not report end of line comment error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24559">24559</a>
-TODO: items disappear when there is a syntax error in a method body
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=13907">13907</a>
-Scanner does not report whitespace tokens at end of input
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25185">25185</a>
-ClassFormatError compiling a method with a compilation problem
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25124">25124</a>
-AST: IllegalArgumentException on creation
-  
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23208">23208</a>  
-The javadoc shown by Eclipse is different from what javadoc produces
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25464">25464</a>  
-NPE during import plugins
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25170">25170</a>  
-opening .java files from outside of classpath is much slower then other files 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23307">23307</a>
-Refactoring and Search are applied only on open files
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20985">20985</a>
-[GM1] REGRESSION: eclipse wants to import class already imported
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24906">24906</a>
-new non-nls strings not noticed on typing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25378">25378</a>
-Switching from jdk1.3.1 to jdk1.4.1 leaves me without CVS support
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22304">22304</a>
-JavaModel: inner Node Constructor shows syntetic argument
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25373">25373</a>
-options now with 'Map'
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25297">25297</a>
-AST: DCR: Allow subclasses of ASTNode
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20751">20751</a>
-[F3] Discrepency between light bulbs and compiler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25163">25163</a>
-AST DCR: Parameter names in IMethodBinding
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25103">25103</a>
-Formatter indentation
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 23rd October 2002
-<br>Project org.eclipse.jdt.core v_279a
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25197">25197</a>  
-NPE importing external plugins  
-
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 22nd October 2002
-<br>Project org.eclipse.jdt.core v_279
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>By default, the compiler will produce warnings for unused imports and non-static references to static members.
-</li>
-<li>Code completion enhancement:
-   <ul>
-   <li>Relevance of a proposal is higher if the proposal is in a return statement and its type is compatible with the return type.
-   <br>In the following example <code>var2</code> is more relevant than <code>var1</code>.<pre>
-   public class X {
-      Object var1;
-      int var2;
-      int foo() {
-         return var&lt;cursor&gt;
-      }
-   }</pre>
-   </li>
-   <li>Relevance of a proposal is higher if the proposal is in a cast statement and its type is in the hierachy of the cast type.
-   <br>In the following example <code>var2</code> is more relevant than <code>var1</code>.<pre>
-   public class X {
-      Object var1;
-      int var2;
-      long foo() {
-         return (int)var&lt;cursor&gt;
-      }
-   }</pre>
-   </li>
-   <li>Relevance of a proposal is higher if the proposal is an argument of a sent message and its type is compatible with the parameter type.
-   <br>In the following example <code>var2</code> is more relevant than <code>var1</code>.<pre>
-   public class X {
-      Object var1;
-      int var2;
-      void foo(int i) {
-         foo(var&lt;cursor&gt;
-      }
-   }</pre>
-   </li>
-   </ul>
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25040">25040</a>  
-getPackageFragmentRoots(CP entry) implementation doesn't match spec  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25041">25041</a>  
-IJavaElement#getUnderlyingResource - should fail if element doesn't exist  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24505">24505</a>  
-Refactoring an empty package makes it disappears  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24775">24775</a>  
-Wrong delta when replacing binary project with source project  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25018">25018</a>
-parseCompilationUnit(..) does not report a compile error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24773">24773</a>
-CompilationUnit.getProblems: not all problems?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24747">24747</a>
-incorrect compile error message
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24974">24974</a>
-Broken link in JDT Plugin-in Developer's Guide
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24691">24691</a>  
-Missing interface makes hierarchy incomplete  
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24213">24213</a>  
-[M1] dependency checking too conservative
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24671">24671</a>  
-Attaching source to JAR triggers build
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=25039">25039</a>  
-Non-existing package fragment roots should not be openable  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23311">23311</a>  
-Need a way to include external JARs in the indexer
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24956">24956</a>  
-Compiler misdiagnoses exception sequence
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24019">24019</a>  
-Jar Refresh Problem
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 15th October 2002 - 2.1 MILESTONE-2
-<br>Project org.eclipse.jdt.core v_278
-<h2>
-What's new in this drop</h2>
-<ul>
-<li> Added soft dependency on plug-in "org.eclipse.team.core" to account for fileTypes contribution
-</li>
- <li> JavaCore option added for specifying the task priorities (default is <code>""</code> meaning 
- tasks have normal priority).
-<pre>
- * COMPILER / Define the Automatic Task Priorities
- *    In parallel with the Automatic Task Tags, this list defines the priorities (high, normal or low)
- *    of the task markers issued by the compiler.
- *    If the default is specified, the priority of each task marker is "NORMAL".
- *     - option id:			"org.eclipse.jdt.core.compiler.taskPriorities"
- *     - possible values:	{ "priority[,priority]*" } where priority is one of "HIGH", "NORMAL" or "LOW"
- *     - default:			""
-</pre>	 
- </li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23272">23272</a>  
-Plugin dependence problem
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24741">24741</a>  
-Search does not find patterned type reference in binary project  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23812">23812</a>  
-Configurable (TODO) Markers priority in takslist  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22840">22840</a>  
-Refactor->Move doesn't update Local History  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24685">24685</a>  
-Inner package fragments gets deleted - model out of synch  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24498">24498</a>  
-Duplicate entries on classpath cause CP marker to no longer refresh  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24630">24630</a>
-NPE in MethodBinding
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24622">24622</a>
-ast: problems with missing ParenthesizedExpression nodes #2
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24529">24529</a>
-compiler must accept empty source files
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24502">24502</a>
-AST: No binding for type accesses to a non-visible type
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24511">24511</a>
-AST: Resolve on non-visible import
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24501">24501</a>
-AST: No binding for fields accesses of non-visible fields
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24500">24500</a>
-AST: No binding for field instance access in constructor invocation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24499">24499</a>  
-AST: No binding for instance access in constructor invocation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=17104">17104</a>  
-Compiler does not complain but "Quick Fix" ??? complains  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21893">21893</a>
-IType::isMember works the other way round
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22581">22581</a>
-Ignore unreachable code for unread variables
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21175">21175</a>  
-Incorrectly identified: Catch block is hidden by another one in the same try statement
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23523">23523</a>  
-Ouliner not updated after catch-up from repository  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24230">24230</a>  
-search: does not find a references to constructor in anonymous type creations nodes  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24522">24522</a>  
-New Class Dialog: No interface method stubs generated for nested class  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24567">24567</a>  
-problem with hierarchy in working copy  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21901">21901</a>
-JavaCore.setClasspathContainer is not generic enough
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24623">24623</a>
-AST: No method body when abstract modifier is existing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24558">24558</a>
-compiler error, method declaration in interface -> NullPointerException
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24621">24621</a>
-Cannot specified JRE for each project separely ...
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24600">24600</a>
-ECLIPSE_HOME not set
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=14194">14194</a>
-Java source files shouldn't show errors when in src dir, but not java resource
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24514">24514</a>
-dependency analyzer is broken
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24400">24400</a>
-Compiler bug or java 'feature' ?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24243">24243</a>
-Heuristic to differ between internal JAR and external JAR.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23769">23769</a>
-java.lang.OutOfMemoryError
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 8th October 2002
-<br>Project org.eclipse.jdt.core v_277
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Search for constructor references now finds implicit constructor calls. Indexes in old workspaces are recomputed when restarted which may result in longer startup times. 
-</li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24449">24449</a>
-AST: Resolve on field access
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24453">24453</a>
-ast: problems with missing ParenthesizedExpression nodes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23112">23112</a>  
-search: need a way to search for references to the implicit non-arg constructor  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24440">24440</a>
-NPE when complete qualified allocation expression
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24406">24406</a>
-AST: Resolve on method invocation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24376">24376</a>  
-Attempt to change resource while tree locked during container initialization
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24346">24346</a>  
-Method declaration not found in field initializer  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=13939">13939</a>
-DBCS: no error message to DBCS whitespace in java source
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23829">23829</a>  
-IType::resolveType incorrectly returns null  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22541">22541</a>  
-JDT core test suites should be on dev.eclipse.org  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=2857">2857</a>  
-Renaming .java class with errors to .txt leaves errors in Task list (1GK06R3)  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24245">24245</a>  
-IJavaSearchScope.enclosingProjectsAndJars doc misleading, hard to use  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24140">24140</a>  
-Searching for references to a private field within heirarchy seems very slow  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24268">24268</a>
-DOM: NPE in NaiveASTFlattener#visit(SwitchCase node)
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23644">23644</a>  
-hierarchy: getAllSuperTypes does not include all superinterfaces?  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23593">23593</a>  
-search: strange method reference match found  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=8489">8489</a>
-space instead of tab
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24370">24370</a>  
-SerialUID
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24205">24205</a>  
-TypeHierarchy omits subtypes  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24375">24375</a>
-Casting of primitive final fields to its own type causes VerifyError
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22548">22548</a>
-IndexOutOfBoundsException during jdt indexing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24347">24347</a>
-AST: Resolve on type name qualifier
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23211">23211</a>  
-Bug with search/reference !  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22894">22894</a>  
-Improperly formed ICompilationUnit?  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24324">24324</a>  
-AST: IVariableBinding.getModifiers not same as in source
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23930">23930</a>
-Eclipse crash when a rebuild project !???
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21905">21905</a>
-Class file editor should indicate that .class file is missing debug attributes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21741">21741</a>
-Error while Build and doesn't allow to create ServerProject also
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22376">22376</a>
-Parent of JarEntryFile
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24274">24274</a>
-ArrayIndexOutOfBoundsException from source mapper  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23677">23677</a>
-java.lang.OutOfMemoryError when setting class path
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24233">24233</a>
-Impossible to compile projects - followinf of BUG 22509
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24233">24233</a>
-Installed JRE detection doesnt work correctly
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 1st October 2002
-<br>Project org.eclipse.jdt.core v_276
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Registered classpath variable initializers are now taking precedence on values persisted during previous session. This allows
-initializers to rebind their variables when restarting a workspace, and thus fix up their values. </li>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23594">23594</a>  
-code resolve: incorrectly resolving method invocation
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21763">21763</a>  
-Problem in Java search [search]  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22846">22846</a>  
-Cannot add in a new classpath entry  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20197">20197</a>  
-Classpath Variables pref page does not refresh with latest variables [build path]  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24134">24134</a>
-JDTCompilertAdapter doesn't throw BuildException on compile error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24001">24001</a>
-Classpath variable/container initializer should activate 
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23656">23656</a>  
-hierarchy: type hierarchy on interfaces does not contain Object  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23890">23890</a>  
-Changing Package Declarations triggers full project rebuild
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24172">24172</a>  
-Strange behavior with wrong package declaration
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24093">24093</a>
-NPE in Java Builder
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22445">22445</a>
-Compiler inconsistent with javac when code returns from inside a finally {} block
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24189">24189</a>
-need a way to  verify that a string can be a type name
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23925">23925</a>
-Class path vars missing
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24210">24210</a>
-NPE renaming project
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24164">24164</a>
-Cannot use a specif rt.jar for a specific Java project
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23989">23989</a>
-Build Path page reports cycle even if there is none
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22754">22754</a>
-JRE-Settings independent for each project
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 26th September 2002
-<br>Project org.eclipse.jdt.core v_275
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=24083">24083</a>
-NPE accessing JavaProject preferences
-
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 24th September 2002
-<br>Project org.eclipse.jdt.core v_274
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added new API findDeclaringNode(String) on CompilationUnit. This new method should be used to retrieve ASTNode
-declared in another compilation unit. See javadoc for further details or bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23734">23734</a>.
-</li>
-<li> New APIs added onto IJavaProject to enable project custom options. Project custom options are persisted into a file ".jprefs" 
-located inside the project metadata JDT/Core plugin location. Project can be specified custom options, and inherit global ones from JavaCore.
-At this point, it is unclear whether we will attempt to share these custom properties (like .classpath file).
-	<ul>
-		<li>
-<pre>
-	/**
-	 * Helper method for returning one option value only. Equivalent to <code>(String)this.getOptions(inheritJavaCoreOptions).get(optionName)</code>
-	 * Note that it may answer <code>null</code> if this option does not exist, or if there is no custom value for it.
-	 * <p>
-	 * For a complete description of the configurable options, see <code>JavaCore#getDefaultOptions</code>.
-	 * </p>
-	 * @param optionName the name of an option
-	 * @param inheritJavaCoreOptions - boolean indicating whether JavaCore options should be inherited as well
-	 * @return the String value of a given option
-	 * @see JavaCore#getDefaultOptions
-	 * @since 2.1
-	 */
-	String getOption(String optionName, boolean inheritJavaCoreOptions);
-</pre>		
-		</li>
-		<li>
-<pre>
-	/**
-	 * Returns the table of the current custom options for this project. Projects remember their custom options,
-	 * i.e. only the options different from the the JavaCore global options for the workspace.
-	 * A boolean argument allows to directly merge the project options with global ones from <code>JavaCore</code>.
-	 * <p>
-	 * For a complete description of the configurable options, see <code>JavaCore#getDefaultOptions</code>.
-	 * </p>
-	 * 
-	 * @param inheritJavaCoreOptions - boolean indicating whether JavaCore options should be inherited as well
-	 * @return table of current settings of all options 
-	 *   (key type: <code>String</code>; value type: <code>String</code>)
-	 * @see JavaCore#getDefaultOptions
-	 * @since 2.1
-	 */
-	Map getOptions(boolean inheritJavaCoreOptions);
-</pre>
-		</li>		
-		<li>
-<pre>
-	/**
-	 * Sets the project custom options. All and only the options explicitly included in the given table 
-	 * are remembered; all previous option settings are forgotten, including ones not explicitly
-	 * mentioned.
-	 * <p>
-	 * For a complete description of the configurable options, see <code>JavaCore#getDefaultOptions</code>.
-	 * </p>
-	 * 
-	 * @param newOptions the new options (key type: <code>String</code>; value type: <code>String</code>),
-	 *   or <code>null</code> to flush all custom options (clients will automatically get the global JavaCore options).
-	 * @see JavaCore#getDefaultOptions
-	 * @since 2.1
-	 */
-	void setOptions(Map newOptions);
-</pre>
-		</li>		
-	</ul>
-</li>
-	<li>Added <code>JavaCore.run(IWorkspaceRunnable, IProgressMonitor)</code> that allows batching
-		  of java model operations. Only one Java element changed event is reported at the end of the batch.
-		  For example the following code snippet notifies listeners twice:
-	<pre>
-	ICompilationUnit unit = ...;
-	unit.createType("class B {}", null, false, monitor);
-	unit.getType("A").createField("int i;", null, false, monitor);
-	</pre>
-		  To be notified only once, use the following:
-	<pre>
-	JavaCore.run(
-		new IWorkspaceRunnable() {
-			public void run(IProgressMonitor monitor) throws CoreException {
-				ICompilationUnit unit = ...;
-				unit.createType("class B {}", null, false, monitor);
-				unit.getType("A").createField("int i;", null, false, monitor);
-			}
-		},
-		monitor);
-	</pre>
-	</li>
-</ul>
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23977">23977</a>
-.classpath corruption
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23734">23734</a>
-AST: CompilationUnit.findDeclaringNode only finds bindings from its own ast
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23979">23979</a>
-Build Path page reports cycle even if there is none
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20881">20881</a>
-"organize imports" does not find an import statement "add import" does. [code manipulation]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=7091">7091</a>
-turn off the debug info on a project by project basis
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=19663">19663</a>
-Java|Compiler|Other|Filtered resources needs to be project/team specific
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=14062">14062</a>
-JDK Compliance against a project
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22289">22289</a>
-To have file encoding by project
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=7395">7395</a>
-Set the compiler options per project instead of per workspace
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23894">23894</a>
-Extra (TODO) Markers : There is no todo task when there is no error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23162">23162</a>
-DOM: clients should be able to control if bindings are available even if AST is modified
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23901">23901</a>
-CCE in DefaultBindingResolver
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23597">23597</a>
-cannot resolve a call to a protected superclass method
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23573">23573</a>
-AST: clone &amp; source locations
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22618">22618</a>
-incorrect warning about unread vars
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3239">3239</a>
-CodeFormatter: need to be able to set linedelimiter used (1GC0LFK)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22979">22979</a>
-using IScanner inside comments
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23550">23550</a>
-Micro-java, embedded java
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23833">23833</a>  
-Java source attachment does not work
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23402">23402</a>  
-Cancel on compile has no effect
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23635">23635</a>  
-Compilation Errors Inconsistent
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21520">21520</a>  
-'Errors during build: org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding' error
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22148">22148</a>  
-Qlfd. vs. unqlfd. Name from IField.getTypeSignature  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21475">21475</a>
-No source for classes without debug information [general issue]
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 19th September 2002 - 2.1 MILESTONE-1
-<br>Project org.eclipse.jdt.core v_273a
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23558">23558</a>  
-Extremly slow startup  
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23788">23788</a>  
-Java compiler doesn't properly flag invalid protected access (for javac 1.4 compatibility)
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 16th September 2002
-<br>Project org.eclipse.jdt.core v_273
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>The source lookup for .class files inside jar files has been improved. Before it worked only if the .class files
-had a source file attribute. This was too limiting in case of the usage of a library which has not been compiled in
-debug mode. Now in case there is no such source file attribute, an heuristic is used to create the proper entry. We
-assume that a class named A in a package p has been compiled from a class A.java in a folder p. For .class files
-that correspond to member or local classes the source mapping is using the top level class name in which the class is defined.
-The only limitiation that still exists is that it is not possible to retrieve the source for secondary types (types
-that are defined in a file which doesn't have the same name). See bug <A HREF="http://dev.eclipse.org/bugs/show_bug.cgi?id=21475">21475</a>
-for further details.</li>
-</ul>
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21475">21475</a>
-Attaching Source-Code to a library which is not compiled with debug info
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23466">23466</a>
-Compiler violates JLS 8.3.2
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21022">21022</a>
-warning on imports while typing and warning on unused imports is on
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23329">23329</a>  
-search: incorrect range for type references in brackets  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23284">23284</a>
-AST: SingleVariableDeclaration needs extra dimensions?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23464">23464</a>
-ast: (Super)ConstructorInvocation should be wrapped in ExpressionStatement
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22560">22560</a>
-"Add return type" correction could be smarter [quick fix]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23492">23492</a>
-[DOM/AST] lazy init should not count as a modification
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23292">23292</a>  
-Must restart Eclipse after debug of source in .zip is updated  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22306">22306</a>
-AST: Constructor contains syntetic SuperConstructorCall
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22832">22832</a>
-select does not work when caret is at the begining of an identifier
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23242">23242</a>
-Bad line number info when multiple statements on same line
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23362">23362</a>
-DOM: incorrect length for InfixExpression.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23357">23357</a>  
-Build not triggered on build path change
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21954">21954</a>  
-compile / debug VM mismatch
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23558">23558</a>  
-Extremly slow startup
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21952">21952</a>  
-Circular Dependencies Message - Error vs. Warning Message  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23375">23375</a>  
-cycle detection algorithm is O(pow(n - 1, n - 1))
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22900">22900</a>
-import of a.b.C fails if package a exists
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 10th September 2002
-<br>Project org.eclipse.jdt.core v_272
-<h2>
-What's new in this drop</h2>
-<ul>
-  <li>JavaCore option added for the error level (warning or error) of incomplete classpath or projects involved
-        in a cycle.
-        <pre>
-* JAVACORE / Reporting Incomplete Classpath
-*    An entry on the classpath doesn't exist or is not visible (e.g. a referenced project is closed).
-*     - option id:			"org.eclipse.jdt.core.incompleteClasspath"
-*     - possible values:	{ "error", "warning"}
-*     - default:			"error"
-* 
-* JAVACORE / Reporting Classpath Cycle
-*    A project is involved in a cycle.
-*     - option id:			"org.eclipse.jdt.core.circularClasspath"
-*     - possible values:	{ "error", "warning" }
-*     - default:			"error"
-        </pre>
-  </li>
-<li>New option -bootclasspath is added for the batch compiler. This option allows you to override the location of bootstrap
-class files. If omitted, the batch compiler will retrieve the libraries used by its JVM. So there is no more need to specify the
-rt.jar file using the -classpath option. The batch compiler also retrieves the contents of the property "java.class.path" if no 
--classpath option is specified.
-</li>
-<li> Deprecation warning inside deprecated code are now ignored by default. A new JavaCore option
-allows to report them all.
-<pre>
-*	COMPILER / Reporting Deprecation Inside Deprecated Code
-*		When enabled, the compiler will signal use of deprecated API inside deprecated code.
-*     The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.deprecation".
-*     		- option id:		"org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode"
-*     		- possible values:	{ "enabled", "disabled" }
-*     		- default:			"disabled"
-</pre>
-</li>
-<li> Compiler can now optionally collect tasks from the source code. Occurrences of
-a given task tag are looked for inside any type of comments, and reported as custom task markers
-(<code>"org.eclipse.jdt.core.task"</code>).
- <ul>
- <li> New problem ID got created: <code>org.eclipse.jdt.core.compiler.IProblem#Task</code>. Note that
- clients of <code>IProblemRequestor</code> will get detected tasks as warnings with this new ID, they
- can be filtered out if needed.
- </li>
- <li> JavaCore option added for specifying the task tag values (default is <code>""</code> meaning no
- task is detected).
-<pre>
-* COMPILER / Define the Automatic Task Tags
-*    When the tag is non empty, the compiler will issue a task marker whenever it encounters
-*    one of the corresponding tag inside any comment in Java source code.
-*    Generated task messages will include the tag, and range until the next line separator or comment ending, and will be trimmed.
-*     - option id:			"org.eclipse.jdt.core.taskTags"
-*     - possible values:	{ "&lt;tag&gt;[,&lt;tag&gt;]*" } where &lt;tag&gt; is a String without any wild-card 
-*     - default:			""
-</pre>	 
- </li>
- </ul>
-</li>
-<li> Creating a working copy on a non-existing ICompilationUnit is now allowed. 
-       Such a working copy will have its contents initialized to an empty string.
-       Commiting this working copy creates the underlying compilation unit.
-</li>
-</ul> 
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23257">23257</a>
-IInitializer::getNameRange returns incorrect result
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23318">23318</a>  
-Resolution of Circular Dep. preference/error message filtering  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23113">23113</a>
-Request to enrich messages provided by AST with errors defined in IProblem
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22154">22154</a>
-Proposed method for org.eclipse.jdt.core.dom.ITypeBinding
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23181">23181</a>
-IScanner returns incorrect whitespaces
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23259">23259</a>
-AST: SwitchCase wrong length
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23117">23117</a>
-DOM: no error message for method with wrong return type
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20215">20215</a>
-Batch compiler ignores the CLASSPATH env variable
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23054">23054</a>
-DOM - TypeDeclaration.getJavadoc() can find incorrect javadoc
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22054">22054</a>
-Can't extract local variable from super send [refactoring]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22161">22161</a>
-AST: Innerclass name: Positions wrong
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22526">22526</a>
-Warning given when implementing deprecated methods
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23050">23050</a>
-DOM - IVariableBinding.getModifiers() doesn't give final modifier for local variables
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22939">22939</a>
-ast: incorrect range for a name in brackets
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22458">22458</a>  
-Refactoring a package does not move the package's directory  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=6976">6976</a>
-Auto collect tasks from code
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23052">23052</a>
-DOM - CCE calling resolveBinding on an on-demand import from a type
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22635">22635</a>
-recompile doesn't happen
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23118">23118</a>
-AST: BreakStatement &amp; ContinueStatement: wrong length
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23048">23048</a>
-DOM - lazy initialization of empty loop bodies causes binding resolution to fail
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22203">22203</a>
-More dependencies increase GUI waiting time [build path]
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=11529">11529</a>
-ast: missing (?) binding on simpleName in VariableDeclaration 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=8921">8921</a>  
-DCR - Need a way to create a working copy ignoring existing files  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22673">22673</a>  
-VerifyError in char cast of static final char referenced through instance
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23075">23075</a>  
-Wrong compiling of inner classes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23077">23077</a>  
-search: does not find type references in some imports 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22942">22942</a>  
-JavaProject.exists returns true when it should not  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22517">22517</a>  
-Cannot create type X in project Test if d:\test\X.java exists  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=18684">18684</a>  
-Organize Imports doesn't work on external Jars  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22946">22946</a>  
-search: NPE  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22637">22637</a>  
-AST: Typos in Javadoc Assignment.Operator
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=17210">17210</a>  
-No match found when query contains '?'  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21420">21420</a>  
-Changing .classpath doesn't update JDT  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21485">21485</a>  
-NPE when doing a reference search to a package  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22428">22428</a>
-Compiler 1.4 - should report visibility issue for shadowed protected method
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22418">22418</a>
-Should not complain about package for empty units
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22102">22102</a>  
-Not all implementors found for IPartListener  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20631">20631</a>  
-Declaration of local binary type not found  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20435">20435</a>  
-NPE when searching java method  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22334">22334</a>
-Compiler generates corrupt classes
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22361">22361</a>
-Error in javadoc for JavaCore.getResolvedClasspathEntry
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21749">21749</a>
-Exported libraries and source folders
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22830">22830</a>
-Subtle visibility problem: class declaration resolved improperly
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23264">23264</a>
-ast: incorrect node hierarchy
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23116">23116</a>
-DCR: ModifierNode
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=23055">23055</a>
-DOM - SuperMethodInvocation.resolveTypeBinding() returns null 
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21843">21843</a>  
-Qualifier in "Type Hierarchy" View  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21158">21158</a>  
-Deadlock on startup  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22883">22883</a>  
-IJavaProject::find(String) returns null for non-primary top-level types  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22123">22123</a>  
-Inability to put a classpath var pointing to a dir inside the project which is one dir up from output dir  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=12496">12496</a>  
-Creating a type hierarchy should not populate java model cache  
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22453">22453</a>
-Compiler Problem
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22149">22149</a>
-jdk compiles but eclipse does not
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.0 Build - 1st August 2002
-<br>Project org.eclipse.jdt.core v_270
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul> 
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22093">22093</a>
-VerifyError due to duplicate access method
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21916">21916</a>
-VariableDeclarationExpression
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21911">21911</a>
-NPE in the compiler
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=7517">7517</a>
-No control of formatting fo do {} while blocks
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22078">22078</a>
-Incorrect error message
-
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 30th July 2002
-<br>Project org.eclipse.jdt.core v_269
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Add a new API getRawTokenSource() on org.eclipse.jdt.core.compiler.IScanner. It should be used if the user doesn't
-want the Unicode characters to be processed, otherwise use getCurrentTokenSource().</li>
-</ul> 
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21912">21912</a>
-Compiler probleme: continue statement with label identifier
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21358">21358</a>
-DOM/AST: setLeadingComment and setJavadocComment doesn't support Unicode
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21828">21828</a>
-Possible problem in DoStatement#accept0(...)
-  
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3458">3458</a>
-Resource folders containing source (1G4CKG9)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21627">21627</a>
-Compiled class error on iSeries
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21723">21723</a>
-Getting java.lang.OutOfMemoryError
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=16176">16176</a>
-References to private fields could be optimized
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21109">21109</a>
-Have option for compiler warning on use of static field/method through reference
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=3357">3357</a>
-DCR - Add compiler option (1GJJQAD)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21879">21879</a>
-Search could be optimized based on visibility
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21868">21868</a>
-No return statement for code with infinite loop
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20820">20820</a>
-Squiggly line is at a bad place for missing return statement
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.0 Build - 23rd July 2002
-<br>Project org.eclipse.jdt.core v_268
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Added optional compiler problem for signalling non-static invocations of static field/methods
-(see <code>JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER()</code>)
-</li>
-<li>Compilation problem descriptions are now shortened (qualified type arguments
-are dequalified in the problem message, problem arguments are left fully qualified).
-</li>
-</ul> 
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20402">20402</a>
-Error Description too long, should not list full class name
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21778">21778</a>
-ClassFileReader fails on Gnome Twain class
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21787">21787</a>
-Provide compiler warning of using static method via non-static style.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21768">21768</a>
-ast: incorrect length of SimpleName in MethodDeclaration
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21757">21757</a>
-ast: incorrect range for Name in TypeDeclaration
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21754">21754</a>
-typo in IType::getSuperInterfaceNames javadoc
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21672">21672</a>
-Wrong location for the last 'return' bytecode command
-
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 22nd July 2002
-<br>Project org.eclipse.jdt.core v_267
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul> 
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21606">21606</a>
-ImageBuilder deletes &amp; adds rather than overwriting
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21282">21282</a>
-IType.getFullyQualifiedName() problems
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21182">21182</a>
-unimplemented method error after implementing in super
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21682">21682</a>
-marking a method deprecated doesn't eleminate deprecated warning
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21556">21556</a>
-"Missing code implementation in the compiler"
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.0 Build - 15th July 2002
-<br>Project org.eclipse.jdt.core v_266
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul> 
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21580">21580</a>
-VerifyError in 1.4 compliant mode
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21557">21557</a>
-VM bug prevents valid Java code to be executed on VM &lt; 1.3.1
-
-<h3>Problem Reports Closed</h3>
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 12th July 2002
-<br>Project org.eclipse.jdt.core v_265
-<h2>
-What's new in this drop</h2>
-<ul>
-<li>Changed ASCII/binary property for entire project.</li>
-</ul> 
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21230">21230</a>
-Rebuilding project fails with ContextStackOverflow (CompilationResult.quickPrioritize)
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21203">21203</a>
-Compile time NullPointerException in catch blocks
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21447">21447</a>
-Wrong method invoked at runtime
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21482">21482</a>
-Error in generated byte code
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21480">21480</a>
-Bytecode disassembler doesn't handle #invokespecial correctly
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20725">20725</a>
-JavaBuilder.toString can throw NPE
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20865">20865</a>
-nullPointerException being thrown by Class Type.resolveBinding()
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21116">21116</a>  
-Can't compile because eclipse says that the method is not visible
-
-<h3>Problem Reports Closed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21049">21049</a>  
-Save (Build / Compile?) performance
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20961">20961</a>  
-Can't get complete classpath for project.
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=21428">21428</a>  
-DOM/AST: AST class unnecessarily plug-in dependent?
-<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=20059">20059</a>  
-project.isOnClassPath(project) result random  
-
 <p><hr>
-For earlier build notes, also see <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/R20_buildnotes_jdt-core.html">build notes up to Release 2.0</a>.
+For earlier build notes, also see <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/R21_buildnotes_jdt-core.html">build notes up to Release 2.1</a>.
 
 <br>&nbsp;
 </body>
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index a85bd9c..66ca644 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -28,13 +28,13 @@
 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
 import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.env.*;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
 import org.eclipse.jdt.internal.core.*;
@@ -48,7 +48,9 @@
  */
 public final class CompletionEngine
 	extends Engine
-	implements ISearchRequestor, TypeConstants , TerminalTokens , RelevanceConstants {
+	implements ISearchRequestor, TypeConstants , TerminalTokens , RelevanceConstants, SuffixConstants {
+	
+	public HashtableOfObject typeCache;
 	
 	public static boolean DEBUG = false;
 
@@ -78,7 +80,8 @@
 	ICompletionRequestor requestor;
 	ProblemReporter problemReporter;
 	char[] source;
-	char[] token;
+	char[] completionToken;
+	char[] qualifiedCompletionToken;
 	boolean resolvingImports = false;
 	boolean insideQualifiedReference = false;
 	boolean noProposal = true;
@@ -127,6 +130,7 @@
 		
 	static final char[] classField = "class".toCharArray();  //$NON-NLS-1$
 	static final char[] lengthField = "length".toCharArray();  //$NON-NLS-1$
+	static final char[] cloneMethod = "clone".toCharArray();  //$NON-NLS-1$
 	static final char[] THIS = "this".toCharArray();  //$NON-NLS-1$
 	static final char[] THROWS = "throws".toCharArray();  //$NON-NLS-1$
 	
@@ -165,6 +169,7 @@
 		this.javaProject = javaProject;
 		this.requestor = requestor;
 		this.nameEnvironment = nameEnvironment;
+		this.typeCache = new HashtableOfObject(5);
 
 		problemReporter = new ProblemReporter(
 				DefaultErrorHandlingPolicies.proceedWithAllProblems(),
@@ -178,43 +183,43 @@
 						String[] problemArguments,
 						String[] messageArguments,
 						int severity,
-						int startPosition,
-						int endPosition,
+						int start,
+						int end,
 						int lineNumber) {
 						
-						IProblem problem = super.createProblem(
+						IProblem pb = super.createProblem(
 							originatingFileName,
 							problemId,
 							problemArguments,
 							messageArguments,
 							severity,
-							startPosition,
-							endPosition,
+							start,
+							end,
 							lineNumber);
-						
-						if(actualCompletionPosition > startPosition
-							&& lastErrorStart < startPosition
-							&& problem.isError()
-							&& (problem.getID() & IProblem.Syntax) == 0) {
+						// TODO (david) problems could be detected in other units which got requested (see CompilationUnitProblemFinder)
+						if(actualCompletionPosition > start
+							&& lastErrorStart < start
+							&& pb.isError()
+							&& (pb.getID() & IProblem.Syntax) == 0) {
 								
-							CompletionEngine.this.problem = problem;
-							lastErrorStart = startPosition;
+							CompletionEngine.this.problem = pb;
+							lastErrorStart = start;
 						}
 						
-						return problem;
+						return pb;
 					}
 
 				});
-		this.parser =
-			new CompletionParser(problemReporter, this.compilerOptions.sourceLevel >= CompilerOptions.JDK1_4);
 		this.lookupEnvironment =
 			new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment);
+		this.parser =
+			new CompletionParser(problemReporter);
 		this.nameScanner =
 			new Scanner(
 				false /*comment*/, 
 				false /*whitespace*/, 
 				false /*nls*/, 
-				this.compilerOptions.sourceLevel >= CompilerOptions.JDK1_4 /*assert*/, 
+				this.compilerOptions.sourceLevel, 
 				null /*taskTags*/, 
 				null/*taskPriorities*/);
 	}
@@ -241,19 +246,17 @@
 		relevance += computeRelevanceForInterestingProposal();
 		if (resolvingImports) {
 			completionName = CharOperation.concat(completionName, SEMICOLON);
-			relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
+			relevance += computeRelevanceForCaseMatching(completionToken, fullyQualifiedName);
 		} else {
-			if (!insideQualifiedReference) {
-				if (mustQualifyType(packageName, className)) {
-					if (packageName == null || packageName.length == 0)
-						if (unitScope != null && unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
-							return; // ignore types from the default package from outside it
-				} else {
-					completionName = className;
-					isQualified = false;
-				}
+			if (mustQualifyType(packageName, className)) {
+				if (packageName == null || packageName.length == 0)
+					if (unitScope != null && unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
+						return; // ignore types from the default package from outside it
+			} else {
+				completionName = className;
+				isQualified = false;
 			}
-			relevance += computeRelevanceForCaseMatching(token, className);
+			relevance += computeRelevanceForCaseMatching(completionToken, className);
 			relevance += computeRelevanceForExpectingType(packageName, className);
 			relevance += computeRelevanceForClass();
 			relevance += computeRelevanceForException(className);
@@ -296,19 +299,17 @@
 		relevance += computeRelevanceForInterestingProposal();
 		if (resolvingImports) {
 			completionName = CharOperation.concat(completionName, new char[] { ';' });
-			relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
+			relevance += computeRelevanceForCaseMatching(completionToken, fullyQualifiedName);
 		} else {
-			if (!insideQualifiedReference) {
-				if (mustQualifyType(packageName, interfaceName)) {
-					if (packageName == null || packageName.length == 0)
-						if (unitScope != null && unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
-							return; // ignore types from the default package from outside it
-				} else {
-					completionName = interfaceName;
-					isQualified = false;
-				}
+			if (mustQualifyType(packageName, interfaceName)) {
+				if (packageName == null || packageName.length == 0)
+					if (unitScope != null && unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
+						return; // ignore types from the default package from outside it
+			} else {
+				completionName = interfaceName;
+				isQualified = false;
 			}
-			relevance += computeRelevanceForCaseMatching(token, interfaceName);
+			relevance += computeRelevanceForCaseMatching(completionToken, interfaceName);
 			relevance += computeRelevanceForExpectingType(packageName, interfaceName);
 			relevance += computeRelevanceForInterface();
 			relevance += computeRelevanceForQualification(isQualified);
@@ -340,8 +341,9 @@
 		
 		int relevance = computeBaseRelevance();
 		relevance += computeRelevanceForInterestingProposal();
-		relevance += computeRelevanceForCaseMatching(token, packageName);
-
+		relevance += computeRelevanceForCaseMatching(qualifiedCompletionToken == null ? completionToken : qualifiedCompletionToken, packageName);
+		relevance += computeRelevanceForQualification(true);
+		
 		noProposal = false;
 		requestor.acceptPackage(
 			packageName,
@@ -375,19 +377,17 @@
 		relevance += computeRelevanceForInterestingProposal();
 		if (resolvingImports) {
 			completionName = CharOperation.concat(completionName, new char[] { ';' });
-			relevance += computeRelevanceForCaseMatching(token, fullyQualifiedName);
+			relevance += computeRelevanceForCaseMatching(completionToken, fullyQualifiedName);
 		} else {
-			if (!insideQualifiedReference) {
-				if (mustQualifyType(packageName, typeName)) {
-					if (packageName == null || packageName.length == 0)
-						if (unitScope != null && unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
-							return; // ignore types from the default package from outside it
-				} else {
-					completionName = typeName;
-					isQualified = false;
-				}
+			if (mustQualifyType(packageName, typeName)) {
+				if (packageName == null || packageName.length == 0)
+					if (unitScope != null && unitScope.fPackage.compoundName != CharOperation.NO_CHAR_CHAR)
+						return; // ignore types from the default package from outside it
+			} else {
+				completionName = typeName;
+				isQualified = false;
 			}
-			relevance += computeRelevanceForCaseMatching(token, typeName);
+			relevance += computeRelevanceForCaseMatching(completionToken, typeName);
 			relevance += computeRelevanceForExpectingType(packageName, typeName);
 			relevance += computeRelevanceForQualification(isQualified);
 		}
@@ -402,7 +402,7 @@
 			relevance);
 	}
 
-	private void complete(AstNode astNode, AstNode astNodeParent, Binding qualifiedBinding, Scope scope) {
+	private void complete(ASTNode astNode, ASTNode astNodeParent, Binding qualifiedBinding, Scope scope) {
 
 		setSourceRange(astNode.sourceStart, astNode.sourceEnd);
 		
@@ -415,46 +415,46 @@
 
 			CompletionOnFieldType field = (CompletionOnFieldType) astNode;
 			CompletionOnSingleTypeReference type = (CompletionOnSingleTypeReference) field.type;
-			token = type.token;
+			completionToken = type.token;
 			setSourceRange(type.sourceStart, type.sourceEnd);
 			
-			findTypesAndPackages(token, scope);
-			findKeywordsForMember(token, field.modifiers);
+			findTypesAndPackages(completionToken, scope);
+			findKeywordsForMember(completionToken, field.modifiers);
 			
 			if(!field.isLocalVariable && field.modifiers == CompilerModifiers.AccDefault) {
-				findMethods(token,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false);
+				findMethods(completionToken,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false, false);
 			}
 		} else {
 			if(astNode instanceof CompletionOnMethodReturnType) {
 				
 				CompletionOnMethodReturnType method = (CompletionOnMethodReturnType) astNode;
 				SingleTypeReference type = (CompletionOnSingleTypeReference) method.returnType;
-				token = type.token;
+				completionToken = type.token;
 				setSourceRange(type.sourceStart, type.sourceEnd);
-				findTypesAndPackages(token, scope);
-				findKeywordsForMember(token, method.modifiers);
+				findTypesAndPackages(completionToken, scope);
+				findKeywordsForMember(completionToken, method.modifiers);
 			
 				if(method.modifiers == CompilerModifiers.AccDefault) {
-					findMethods(token,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false);
+					findMethods(completionToken,null,scope.enclosingSourceType(),scope,new ObjectVector(),false,false,true,null,null,false,false);
 				}
 			} else {
 				
 				if (astNode instanceof CompletionOnSingleNameReference) {
 					CompletionOnSingleNameReference singleNameReference = (CompletionOnSingleNameReference) astNode;
-					token = singleNameReference.token;
+					completionToken = singleNameReference.token;
 					findVariablesAndMethods(
-						token,
+						completionToken,
 						scope,
 						(CompletionOnSingleNameReference) astNode,
 						scope);
 					// can be the start of a qualified type name
-					findTypesAndPackages(token, scope);
-					findKeywords(token, singleNameReference.possibleKeywords);
+					findTypesAndPackages(completionToken, scope);
+					findKeywords(completionToken, singleNameReference.possibleKeywords);
 					if(singleNameReference.canBeExplicitConstructor){
-						if(CharOperation.prefixEquals(token, Keywords.THIS, false)) {
+						if(CharOperation.prefixEquals(completionToken, Keywords.THIS, false)) {
 							ReferenceBinding ref = scope.enclosingSourceType();
 							findExplicitConstructors(Keywords.THIS, ref, (MethodScope)scope, singleNameReference);
-						} else if(CharOperation.prefixEquals(token, Keywords.SUPER, false)) {
+						} else if(CharOperation.prefixEquals(completionToken, Keywords.SUPER, false)) {
 							ReferenceBinding ref = scope.enclosingSourceType();
 							findExplicitConstructors(Keywords.SUPER, ref.superclass(), (MethodScope)scope, singleNameReference);
 						}
@@ -463,7 +463,7 @@
 	
 					if (astNode instanceof CompletionOnSingleTypeReference) {
 	
-						token = ((CompletionOnSingleTypeReference) astNode).token;
+						completionToken = ((CompletionOnSingleTypeReference) astNode).token;
 						
 						assistNodeIsClass = astNode instanceof CompletionOnClassReference;
 						assistNodeIsException = astNode instanceof CompletionOnExceptionReference;
@@ -471,10 +471,10 @@
 	
 						// can be the start of a qualified type name
 						if (qualifiedBinding == null) {
-							findTypesAndPackages(token, scope);
+							findTypesAndPackages(completionToken, scope);
 							} else {
 								findMemberTypes(
-								token,
+								completionToken,
 								(ReferenceBinding) qualifiedBinding,
 								scope,
 								scope.enclosingSourceType());
@@ -486,7 +486,7 @@
 							insideQualifiedReference = true;
 							CompletionOnQualifiedNameReference ref =
 								(CompletionOnQualifiedNameReference) astNode;
-							token = ref.completionIdentifier;
+							completionToken = ref.completionIdentifier;
 							long completionPosition = ref.sourcePositions[ref.sourcePositions.length - 1];
 	
 							if (qualifiedBinding instanceof VariableBinding) {
@@ -494,7 +494,7 @@
 								setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
 								TypeBinding receiverType = ((VariableBinding) qualifiedBinding).type;
 								if (receiverType != null) {
-									findFieldsAndMethods(token, receiverType, scope, ref, scope,false);
+									findFieldsAndMethods(completionToken, receiverType, scope, ref, scope,false,false);
 								}
 	
 							} else {
@@ -504,18 +504,18 @@
 									ReferenceBinding receiverType = (ReferenceBinding) qualifiedBinding;
 									setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
 	
-									findMemberTypes(token, receiverType, scope, scope.enclosingSourceType());
+									findMemberTypes(completionToken, receiverType, scope, scope.enclosingSourceType());
 	
-									findClassField(token, (TypeBinding) qualifiedBinding, scope);
+									findClassField(completionToken, (TypeBinding) qualifiedBinding, scope);
 									
 									MethodScope methodScope = null;
 									if((scope instanceof MethodScope && !((MethodScope)scope).isStatic)
 										|| ((methodScope = scope.enclosingMethodScope()) != null && !methodScope.isStatic)) {
-										findKeywords(token, new char[][]{Keywords.THIS});
+										findKeywords(completionToken, new char[][]{Keywords.THIS});
 									}
 	
 									findFields(
-										token,
+										completionToken,
 										receiverType,
 										scope,
 										new ObjectVector(),
@@ -526,7 +526,7 @@
 										false);
 	
 									findMethods(
-										token,
+										completionToken,
 										null,
 										receiverType,
 										scope,
@@ -536,6 +536,7 @@
 										false,
 										ref,
 										scope,
+										false,
 										false);
 	
 								} else {
@@ -544,7 +545,7 @@
 	
 										setSourceRange(astNode.sourceStart, (int) completionPosition);
 										// replace to the end of the completion identifier
-										findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
+										findTypesAndSubpackages(completionToken, (PackageBinding) qualifiedBinding);
 									}
 								}
 							}
@@ -561,7 +562,7 @@
 								
 								CompletionOnQualifiedTypeReference ref =
 									(CompletionOnQualifiedTypeReference) astNode;
-								token = ref.completionIdentifier;
+								completionToken = ref.completionIdentifier;
 								long completionPosition = ref.sourcePositions[ref.tokens.length];
 	
 								// get the source positions of the completion identifier
@@ -569,7 +570,7 @@
 	
 									setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
 									findMemberTypes(
-										token,
+										completionToken,
 										(ReferenceBinding) qualifiedBinding,
 										scope,
 										scope.enclosingSourceType());
@@ -580,7 +581,7 @@
 	
 										setSourceRange(astNode.sourceStart, (int) completionPosition);
 										// replace to the end of the completion identifier
-										findTypesAndSubpackages(token, (PackageBinding) qualifiedBinding);
+										findTypesAndSubpackages(completionToken, (PackageBinding) qualifiedBinding);
 									}
 								}
 	
@@ -592,17 +593,18 @@
 									long completionPosition = access.nameSourcePosition;
 									setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
 					
-									token = access.token;
+									completionToken = access.token;
 									
-									findKeywords(token, new char[][]{Keywords.NEW});
+									findKeywords(completionToken, new char[][]{Keywords.NEW});
 									
 									findFieldsAndMethods(
-										token,
+										completionToken,
 										(TypeBinding) qualifiedBinding,
 										scope,
 										access,
 										scope,
-										false);
+										false,
+										access.receiver instanceof SuperReference);
 	
 								} else {
 	
@@ -612,14 +614,14 @@
 										CompletionOnMessageSend messageSend = (CompletionOnMessageSend) astNode;
 										TypeBinding[] argTypes =
 											computeTypes(messageSend.arguments, (BlockScope) scope);
-										token = messageSend.selector;
+										completionToken = messageSend.selector;
 										if (qualifiedBinding == null) {
 											
-											findImplicitMessageSends(token, argTypes, scope, messageSend, scope);
+											findImplicitMessageSends(completionToken, argTypes, scope, messageSend, scope);
 										} else {
 	
 											findMethods(
-												token,
+												completionToken,
 												argTypes,
 												(ReferenceBinding) qualifiedBinding,
 												scope,
@@ -629,7 +631,8 @@
 												false,
 												messageSend,
 												scope,
-												false);
+												false,
+												messageSend.receiver instanceof SuperReference);
 										}
 	
 									} else {
@@ -683,9 +686,9 @@
 													CompletionOnClassLiteralAccess access = (CompletionOnClassLiteralAccess) astNode;
 													setSourceRange(access.classStart, access.sourceEnd);
 									
-													token = access.completionIdentifier;
+													completionToken = access.completionIdentifier;
 									
-													findClassField(token, (TypeBinding) qualifiedBinding, scope);
+													findClassField(completionToken, (TypeBinding) qualifiedBinding, scope);
 												} else {
 													if(astNode instanceof CompletionOnMethodName) {
 														CompletionOnMethodName method = (CompletionOnMethodName) astNode;
@@ -698,9 +701,9 @@
 															excludeNames[i] = fields[i].name;
 														}
 														
-														token = method.selector;
+														completionToken = method.selector;
 														
-														findVariableNames(token, method.returnType, excludeNames, FIELD, method.modifiers);
+														findVariableNames(completionToken, method.returnType, excludeNames, FIELD, method.modifiers);
 													} else {
 														if (astNode instanceof CompletionOnFieldName) {
 															CompletionOnFieldName field = (CompletionOnFieldName) astNode;
@@ -711,7 +714,7 @@
 																excludeNames[i] = fields[i].name;
 															}
 															
-															token = field.realName;
+															completionToken = field.realName;
 															
 															findVariableNames(field.realName, field.type, excludeNames, FIELD, field.modifiers);
 														} else {
@@ -730,12 +733,12 @@
 																System.arraycopy(excludeNames, 0, excludeNames = new char[localCount][], 0, localCount);
 																
 																if(variable instanceof CompletionOnLocalName){
-																	token = ((CompletionOnLocalName) variable).realName;
-																	findVariableNames(token, variable.type, excludeNames, LOCAL, variable.modifiers);
+																	completionToken = ((CompletionOnLocalName) variable).realName;
+																	findVariableNames(completionToken, variable.type, excludeNames, LOCAL, variable.modifiers);
 																} else {
 																	CompletionOnArgumentName arg = (CompletionOnArgumentName) variable;
-																	token = arg.realName;
-																	findVariableNames(token, variable.type, excludeNames, arg.isCatchArgument ? LOCAL : ARGUMENT, variable.modifiers);
+																	completionToken = arg.realName;
+																	findVariableNames(completionToken, variable.type, excludeNames, arg.isCatchArgument ? LOCAL : ARGUMENT, variable.modifiers);
 																}
 															} else {
 																if(astNode instanceof CompletionOnKeyword) {
@@ -765,11 +768,12 @@
 			topLevelType = topLevelType.getDeclaringType();
 		}
 		
-		CompilationResult compilationResult = new CompilationResult((topLevelType.getElementName() + ".java").toCharArray(), 1, 1, this.compilerOptions.maxProblemsPerUnit); //$NON-NLS-1$
+		CompilationResult compilationResult = new CompilationResult((topLevelType.getElementName() + SUFFIX_STRING_java).toCharArray(), 1, 1, this.compilerOptions.maxProblemsPerUnit);
 	
 		CompilationUnitDeclaration compilationUnit = new CompilationUnitDeclaration(problemReporter, compilationResult, 0);
 	
 		try {
+			//TODO (david) should be instead be using SourceTypeConverter?
 			TypeDeclaration typeDeclaration = TypeConverter.buildTypeDeclaration(type, compilationUnit, compilationResult);
 		
 			if(typeDeclaration != null) {	
@@ -822,7 +826,7 @@
 		}
 		prefix.append("{\n"); //$NON-NLS-1$
 		for (int i = 0; i < localVariableTypeNames.length; i++) {
-			prefix.append(AstNode.modifiersString(localVariableModifiers[i]));
+			ASTNode.printModifiers(localVariableModifiers[i], prefix);
 			prefix.append(' ');
 			prefix.append(localVariableTypeNames[i]);
 			prefix.append(' ');
@@ -845,7 +849,7 @@
 		CompilationResult fakeResult = new CompilationResult(fakeUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
 		CompilationUnitDeclaration fakeAST = parser.dietParse(fakeUnit, fakeResult, actualCompletionPosition);
 		
-		parseMethod(fakeAST, actualCompletionPosition);
+		parseBlockStatements(fakeAST, actualCompletionPosition);
 		
 		return (Initializer)fakeAST.types[0].fields[0];
 	}
@@ -864,7 +868,7 @@
 	 *      a position in the source where the completion is taking place. 
 	 *      This position is relative to the source provided.
 	 */
-	public void complete(ICompilationUnit sourceUnit, int completionPosition, int offset) {
+	public void complete(ICompilationUnit sourceUnit, int completionPosition, int pos) {
 
 		if(DEBUG) {
 			System.out.print("COMPLETION IN "); //$NON-NLS-1$
@@ -876,7 +880,7 @@
 		}
 		try {
 			actualCompletionPosition = completionPosition - 1;
-			this.offset = offset;
+			this.offset = pos;
 			// for now until we can change the UI.
 			CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
 			CompilationUnitDeclaration parsedUnit = parser.dietParse(sourceUnit, result, actualCompletionPosition);
@@ -927,7 +931,7 @@
 							source = sourceUnit.getContents();
 							lookupEnvironment.completeTypeBindings(parsedUnit, true);
 							parsedUnit.scope.faultInTypes();
-							parseMethod(parsedUnit, actualCompletionPosition);
+							parseBlockStatements(parsedUnit, actualCompletionPosition);
 							if(DEBUG) {
 								System.out.println("COMPLETION - AST :"); //$NON-NLS-1$
 								System.out.println(parsedUnit.toString());
@@ -1045,7 +1049,7 @@
 				CharOperation.NO_CHAR,
 				CharOperation.NO_CHAR,
 				classField,
-				CompilerModifiers.AccStatic | CompilerModifiers.AccPublic,
+				IConstants.AccStatic | IConstants.AccPublic,
 				startPosition - offset,
 				endPosition - offset,
 				relevance);
@@ -1095,7 +1099,7 @@
 					
 					int relevance = computeBaseRelevance();
 					relevance += computeRelevanceForInterestingProposal();
-					relevance += computeRelevanceForCaseMatching(token, name);
+					relevance += computeRelevanceForCaseMatching(completionToken, name);
 					
 					noProposal = false;
 					requestor.acceptMethod(
@@ -1218,6 +1222,7 @@
 		Scope invocationScope,
 		boolean implicitCall) {
 
+		ObjectVector newFieldsFound = new ObjectVector();
 		// Inherited fields which are hidden by subclasses are filtered out
 		// No visibility checks can be performed without the scope & invocationSite
 		
@@ -1273,7 +1278,7 @@
 				}
 			}
 			
-			fieldsFound.add(new Object[]{field, receiverType});
+			newFieldsFound.add(new Object[]{field, receiverType});
 			
 			char[] completion = field.name;
 			
@@ -1302,6 +1307,8 @@
 			field.modifiers, startPosition - offset, endPosition - offset,
 			relevance);
 		}
+		
+		fieldsFound.addAll(newFieldsFound);
 	}
 
 	private void findFields(
@@ -1411,14 +1418,17 @@
 		Scope scope,
 		InvocationSite invocationSite,
 		Scope invocationScope,
-		boolean implicitCall) {
+		boolean implicitCall,
+		boolean superCall) {
 
 		if (token == null)
 			return;
 
 		if (receiverType.isBaseType())
 			return; // nothing else is possible with base types
-
+		
+		ObjectVector methodsFound = new ObjectVector();
+		
 		if (receiverType.isArrayType()) {
 			if (token.length <= lengthField.length
 				&& CharOperation.prefixEquals(token, lengthField, false /* ignore case */
@@ -1437,11 +1447,50 @@
 					CharOperation.NO_CHAR,
 					CharOperation.NO_CHAR,
 					lengthField,
-					CompilerModifiers.AccPublic,
+					IConstants.AccPublic,
 					startPosition - offset,
 					endPosition - offset,
 					relevance);
 			}
+			if (token.length <= cloneMethod.length
+				&& CharOperation.prefixEquals(token, cloneMethod, false /* ignore case */
+			)) {
+				ReferenceBinding objectRef = scope.getJavaLangObject();
+				
+				int relevance = computeBaseRelevance();
+				relevance += computeRelevanceForInterestingProposal();
+				relevance += computeRelevanceForCaseMatching(token, cloneMethod);
+				relevance += computeRelevanceForExpectingType(objectRef);
+				relevance += computeRelevanceForStatic(false, false);
+				relevance += computeRelevanceForQualification(false);
+				
+				char[] completion;
+				if (source != null
+					&& source.length > endPosition
+					&& source[endPosition] == '(') {
+					completion = cloneMethod;
+					} else {
+					completion = CharOperation.concat(cloneMethod, new char[] { '(', ')' });
+				}
+				noProposal = false;
+				requestor.acceptMethod(
+					CharOperation.NO_CHAR,
+					CharOperation.NO_CHAR,
+					cloneMethod,
+					CharOperation.NO_CHAR_CHAR,
+					CharOperation.NO_CHAR_CHAR,
+					CharOperation.NO_CHAR_CHAR,
+					CharOperation.concat(JAVA, LANG, '.'),
+					OBJECT,
+					completion,
+					IConstants.AccPublic,
+					startPosition - offset,
+					endPosition - offset,
+					relevance);
+					
+				methodsFound.add(new Object[]{objectRef.getMethods(cloneMethod)[0], objectRef});
+			}
+			
 			receiverType = scope.getJavaLangObject();
 		}
 
@@ -1461,13 +1510,14 @@
 			null,
 			(ReferenceBinding) receiverType,
 			scope,
-			new ObjectVector(),
+			methodsFound,
 			false,
 			false,
 			false,
 			invocationSite,
 			invocationScope,
-			implicitCall);
+			implicitCall,
+			superCall);
 	}
 
 	private void findImports(CompletionOnImportReference importReference) {
@@ -1487,7 +1537,7 @@
 			importReference.sourceStart,
 			importReference.declarationSourceEnd);
 			
-		token =  importName;
+		completionToken =  importName;
 		// want to replace the existing .*;
 		nameEnvironment.findPackages(importName, this);
 		nameEnvironment.findTypes(importName, this);
@@ -1518,73 +1568,73 @@
 		int count = 0;
 				
 		// visibility
-		if((modifiers & CompilerModifiers.AccPrivate) == 0
-			&& (modifiers & CompilerModifiers.AccProtected) == 0
-			&& (modifiers & CompilerModifiers.AccPublic) == 0) {
+		if((modifiers & IConstants.AccPrivate) == 0
+			&& (modifiers & IConstants.AccProtected) == 0
+			&& (modifiers & IConstants.AccPublic) == 0) {
 			keywords[count++] = Keywords.PROTECTED;
 			keywords[count++] = Keywords.PUBLIC;
-			if((modifiers & CompilerModifiers.AccAbstract) == 0) {
+			if((modifiers & IConstants.AccAbstract) == 0) {
 				keywords[count++] = Keywords.PRIVATE;
 			}
 		}
 		
-		if((modifiers & CompilerModifiers.AccAbstract) == 0) {
+		if((modifiers & IConstants.AccAbstract) == 0) {
 			// abtract
-			if((modifiers & ~(CompilerModifiers.AccVisibilityMASK | CompilerModifiers.AccStatic)) == 0) {
-				keywords[count++] = Keywords.ABSTARCT;
+			if((modifiers & ~(CompilerModifiers.AccVisibilityMASK | IConstants.AccStatic)) == 0) {
+				keywords[count++] = Keywords.ABSTRACT;
 			}
 			
 			// final
-			if((modifiers & CompilerModifiers.AccFinal) == 0) {
+			if((modifiers & IConstants.AccFinal) == 0) {
 				keywords[count++] = Keywords.FINAL;
 			}
 			
 			// static
-			if((modifiers & CompilerModifiers.AccStatic) == 0) {
+			if((modifiers & IConstants.AccStatic) == 0) {
 				keywords[count++] = Keywords.STATIC;
 			}
 			
 			boolean canBeField = true;
 			boolean canBeMethod = true;
 			boolean canBeType = true;
-			if((modifiers & CompilerModifiers.AccNative) != 0
-				|| (modifiers & CompilerModifiers.AccStrictfp) != 0
-				|| (modifiers & CompilerModifiers.AccSynchronized) != 0) {
+			if((modifiers & IConstants.AccNative) != 0
+				|| (modifiers & IConstants.AccStrictfp) != 0
+				|| (modifiers & IConstants.AccSynchronized) != 0) {
 				canBeField = false;
 				canBeType = false;
 			}
 			
-			if((modifiers & CompilerModifiers.AccTransient) != 0
-				|| (modifiers & CompilerModifiers.AccVolatile) != 0) {
+			if((modifiers & IConstants.AccTransient) != 0
+				|| (modifiers & IConstants.AccVolatile) != 0) {
 				canBeMethod = false;
 				canBeType = false;
 			}
 			
 			if(canBeField) {
 				// transient
-				if((modifiers & CompilerModifiers.AccTransient) == 0) {
+				if((modifiers & IConstants.AccTransient) == 0) {
 					keywords[count++] = Keywords.TRANSIENT;
 				}
 				
 				// volatile
-				if((modifiers & CompilerModifiers.AccVolatile) == 0) {
+				if((modifiers & IConstants.AccVolatile) == 0) {
 					keywords[count++] = Keywords.VOLATILE;
 				}
 			}
 			
 			if(canBeMethod) {
 				// native
-				if((modifiers & CompilerModifiers.AccNative) == 0) {
+				if((modifiers & IConstants.AccNative) == 0) {
 					keywords[count++] = Keywords.NATIVE;
 				}
 	
 				// strictfp
-				if((modifiers & CompilerModifiers.AccStrictfp) == 0) {
+				if((modifiers & IConstants.AccStrictfp) == 0) {
 					keywords[count++] = Keywords.STRICTFP;
 				}
 				
 				// synchronized
-				if((modifiers & CompilerModifiers.AccSynchronized) == 0) {
+				if((modifiers & IConstants.AccSynchronized) == 0) {
 					keywords[count++] = Keywords.SYNCHRONIZED;
 				}
 			}
@@ -1801,7 +1851,8 @@
 		boolean isCompletingDeclaration,
 		InvocationSite invocationSite,
 		Scope invocationScope,
-		boolean implicitCall) {
+		boolean implicitCall,
+		boolean superCall) {
 
 		if (selector == null)
 			return;
@@ -1847,7 +1898,8 @@
 									receiverType,
 									invocationSite,
 									invocationScope,
-									implicitCall);
+									implicitCall,
+									superCall);
 							}
 						}
 
@@ -1916,7 +1968,8 @@
 						false,
 						invocationSite,
 						invocationScope,
-						true);
+						true,
+						false);
 					staticsOnly |= enclosingType.isStatic();
 					break;
 
@@ -1939,8 +1992,10 @@
 		ReferenceBinding receiverType,
 		InvocationSite invocationSite,
 		Scope invocationScope,
-		boolean implicitCall) {
+		boolean implicitCall,
+		boolean superCall) {
 
+		ObjectVector newMethodsFound =  new ObjectVector();
 		// Inherited methods which are hidden by subclasses are filtered out
 		// No visibility checks can be performed without the scope & invocationSite
 
@@ -1956,13 +2011,19 @@
 
 			if (method.isConstructor()) continue next;
 
-			if (expectedTypesPtr > -1 && method.returnType == BaseTypes.VoidBinding) continue next;
+			//TODO (david) perhaps the relevance of a void method must be lesser than other methods
+			//if (expectedTypesPtr > -1 && method.returnType == BaseTypes.VoidBinding) continue next;
 			
 			if (onlyStaticMethods && !method.isStatic()) continue next;
 
 			if (options.checkVisibility
 				&& !method.canBeSeenBy(receiverType, invocationSite, scope)) continue next;
 
+			if(superCall && method.isAbstract()) {
+				methodsFound.add(new Object[]{method, receiverType});
+				continue next;
+			}
+
 			if (exactMatch) {
 				if (!CharOperation.equals(methodName, method.selector, false /* ignore case */
 					))
@@ -2008,7 +2069,7 @@
 						if(method.declaringClass == scope.getJavaLangObject())
 							continue next;
 						
-						if (method
+						if (!superCall && method
 							.declaringClass
 							.implementsInterface(otherMethod.declaringClass, true))
 							continue next;
@@ -2019,11 +2080,16 @@
 							.declaringClass
 							.implementsInterface(method.declaringClass,true))
 							continue next;
-					prefixRequired = true;
+						
+					if(receiverType.isAnonymousType()) continue next;
+					
+					if(!superCall) {
+						prefixRequired = true;
+					}
 				}
 			}
 
-			methodsFound.add(new Object[]{method, receiverType});
+			newMethodsFound.add(new Object[]{method, receiverType});
 			int length = method.parameters.length;
 			char[][] parameterPackageNames = new char[length][];
 			char[][] parameterTypeNames = new char[length][];
@@ -2084,6 +2150,8 @@
 				relevance);
 			startPosition = previousStartPosition;
 		}
+		
+		methodsFound.addAll(newMethodsFound);
 	}
 	
 	int computeRelevanceForCaseMatching(char[] token, char[] proposalName){
@@ -2110,9 +2178,13 @@
 		return 0;
 	}
 	private int computeRelevanceForQualification(boolean prefixRequired) {
-		if(!prefixRequired) {
+		if(!prefixRequired && !insideQualifiedReference) {
 			return R_UNQUALIFIED;
 		}
+		
+		if(prefixRequired && insideQualifiedReference) {
+			return R_QUALIFIED;
+		}
 		return 0;
 	}
 	private int computeRelevanceForStatic(boolean onlyStatic, boolean isStatic) {
@@ -2121,6 +2193,9 @@
 		}
 		return 0;
 	}
+	private int computeRelevanceForStaticOveride(boolean isStatic) {
+		return isStatic ? 0 : R_NON_STATIC_OVERIDE;
+	}
 	private int computeRelevanceForException(char[] proposalName){
 		
 		if(assistNodeIsException &&
@@ -2173,7 +2248,7 @@
 		}
 		return R_INTERESTING;
 	}
-	private void computeUninterestingBindings(AstNode parent, Scope scope){
+	private void computeUninterestingBindings(ASTNode parent, Scope scope){
 		if(parent instanceof LocalDeclaration) {
 			addUninterestingBindings(((LocalDeclaration)parent).binding);
 		} else if (parent instanceof FieldDeclaration) {
@@ -2191,6 +2266,7 @@
 		boolean exactMatch,
 		ReferenceBinding receiverType) {
 
+		ObjectVector newMethodsFound =  new ObjectVector();
 		// Inherited methods which are hidden by subclasses are filtered out
 		// No visibility checks can be performed without the scope & invocationSite
 		int methodLength = methodName.length;
@@ -2206,7 +2282,15 @@
 			if (method.isFinal()) continue next;
 
 			//		if (noVoidReturnType && method.returnType == BaseTypes.VoidBinding) continue next;
-			if (onlyStaticMethods && !method.isStatic()) continue next;
+			if(method.isStatic()) {
+				if(receiverType.isAnonymousType()) continue next;
+				
+				if(receiverType.isMemberType() && !receiverType.isStatic()) continue next;
+				
+				if(receiverType.isLocalType()) continue next;
+			} else  {
+				if(onlyStaticMethods) continue next;
+			}
 
 			if (options.checkVisibility
 				&& !method.canBeSeenBy(receiverType, FakeInvocationSite , scope)) continue next;
@@ -2238,7 +2322,7 @@
 				}
 			}
 
-			methodsFound.add(method);
+			newMethodsFound.add(method);
 			
 			int length = method.parameters.length;
 			char[][] parameterPackageNames = new char[length][];
@@ -2254,11 +2338,11 @@
 			
 			StringBuffer completion = new StringBuffer(10);
 			// flush uninteresting modifiers
-			int insertedModifiers = method.modifiers & ~(CompilerModifiers.AccNative | CompilerModifiers.AccAbstract);
+			int insertedModifiers = method.modifiers & ~(IConstants.AccNative | IConstants.AccAbstract);
 
 			if (!exactMatch) {
 				if(insertedModifiers != CompilerModifiers.AccDefault){
-					completion.append(AstNode.modifiersString(insertedModifiers));
+					ASTNode.printModifiers(insertedModifiers, completion);
 				}
 				char[] returnPackageName = method.returnType.qualifiedPackageName();
 				char[] returnTypeName = method.returnType.qualifiedSourceName();
@@ -2317,6 +2401,7 @@
 			int relevance = computeBaseRelevance();
 			relevance += computeRelevanceForInterestingProposal();
 			relevance += computeRelevanceForCaseMatching(methodName, method.selector);
+			relevance += computeRelevanceForStaticOveride(method.isStatic());
 			if(method.isAbstract()) relevance += R_ABSTRACT_METHOD;
 
 			noProposal = false;
@@ -2335,6 +2420,7 @@
 				endPosition - offset,
 				relevance);
 		}
+		methodsFound.addAll(newMethodsFound);
 	}
 	private void findMethods(
 		char[] selector,
@@ -2347,7 +2433,8 @@
 		boolean isCompletingDeclaration,
 		InvocationSite invocationSite,
 		Scope invocationScope,
-		boolean implicitCall) {
+		boolean implicitCall,
+		boolean superCall) {
 		if (selector == null)
 			return;
 		
@@ -2377,7 +2464,8 @@
 					isCompletingDeclaration,
 					invocationSite,
 					invocationScope,
-					implicitCall);
+					implicitCall,
+					superCall);
 			} else {
 				findIntefacesMethods(
 					selector,
@@ -2391,7 +2479,8 @@
 					isCompletingDeclaration,
 					invocationSite,
 					invocationScope,
-					implicitCall);
+					implicitCall,
+					superCall);
 			}
 			
 			currentType = scope.getJavaLangObject();
@@ -2409,7 +2498,8 @@
 					isCompletingDeclaration,
 					invocationSite,
 					invocationScope,
-					implicitCall);
+					implicitCall,
+					superCall);
 				
 				currentType = receiverType.superclass();
 			}
@@ -2440,7 +2530,8 @@
 						receiverType,
 						invocationSite,
 						invocationScope,
-						implicitCall);
+						implicitCall,
+						superCall);
 				}
 			}
 			
@@ -2457,7 +2548,8 @@
 					isCompletingDeclaration,
 					invocationSite,
 					invocationScope,
-					implicitCall);
+					implicitCall,
+					superCall);
 			} else {
 				hasPotentialDefaultAbstractMethods = false;
 			}
@@ -2497,25 +2589,36 @@
 		}
 		// look into the model		
 		if(parameterNames == null){
-			NameEnvironmentAnswer answer = nameEnvironment.findType(bindingType.compoundName);
+			char[] compoundName = CharOperation.concatWith(bindingType.compoundName, '.');
+			Object type = typeCache.get(compoundName);
+			
+			ISourceType sourceType = null;
+			if(type != null) {
+				if(type instanceof ISourceType) {
+					sourceType = (ISourceType) type;
+				}
+			} else {
+				NameEnvironmentAnswer answer = nameEnvironment.findType(bindingType.compoundName);
+				if(answer != null && answer.isSourceType()) {
+					sourceType = answer.getSourceTypes()[0];
+					typeCache.put(compoundName, sourceType);
+				}
+			}
+			
+			if(sourceType != null) {
+				ISourceMethod[] sourceMethods = sourceType.getMethods();
+				int len = sourceMethods == null ? 0 : sourceMethods.length;
+				for(int i = 0; i < len ; i++){
+					ISourceMethod sourceMethod = sourceMethods[i];
+					char[][] argTypeNames = sourceMethod.getArgumentTypeNames();
 
-			if(answer != null){
-				if(answer.isSourceType()) {
-					ISourceType sourceType = answer.getSourceTypes()[0];
-					ISourceMethod[] sourceMethods = sourceType.getMethods();
-					int len = sourceMethods == null ? 0 : sourceMethods.length;
-					for(int i = 0; i < len ; i++){
-						ISourceMethod sourceMethod = sourceMethods[i];
-						char[][] argTypeNames = sourceMethod.getArgumentTypeNames();
-
-						if(argTypeNames != null &&
-							CharOperation.equals(method.selector,sourceMethod.getSelector()) &&
-							CharOperation.equals(argTypeNames,parameterTypeNames)){
-							parameterNames = sourceMethod.getArgumentNames();
-							break;
-						}
+					if(argTypeNames != null &&
+						CharOperation.equals(method.selector,sourceMethod.getSelector()) &&
+						CharOperation.equals(argTypeNames,parameterTypeNames)){
+						parameterNames = sourceMethod.getArgumentNames();
+						break;
 					}
-				} 
+				}
 			}
 		}
 		return parameterNames;
@@ -2538,7 +2641,7 @@
 				case Scope.BLOCK_SCOPE :
 					BlockScope blockScope = (BlockScope) scope;
 
-					next : for (int i = 0, length = blockScope.scopeIndex; i < length; i++) {
+					next : for (int i = 0, length = blockScope.subscopeCount; i < length; i++) {
 
 						if (blockScope.subscopes[i] instanceof ClassScope) {
 							SourceTypeBinding localType =
@@ -2589,12 +2692,12 @@
 
 	private void findPackages(CompletionOnPackageReference packageStatement) {
 
-		token = CharOperation.concatWith(packageStatement.tokens, '.');
-		if (token.length == 0)
+		completionToken = CharOperation.concatWith(packageStatement.tokens, '.');
+		if (completionToken.length == 0)
 			return;
 
 		setSourceRange(packageStatement.sourceStart, packageStatement.sourceEnd);
-		nameEnvironment.findPackages(CharOperation.toLowerCase(token), this);
+		nameEnvironment.findPackages(CharOperation.toLowerCase(completionToken), this);
 	}
 
 	private void findTypesAndPackages(char[] token, Scope scope) {
@@ -2735,6 +2838,8 @@
 			qualifiedName[length] = '.';
 		}
 		
+		this.qualifiedCompletionToken = qualifiedName;
+		
 		if (unitScope != null) {
 			int typeLength = qualifiedName.length;
 			SourceTypeBinding[] types = unitScope.topLevelTypes;
@@ -2744,7 +2849,8 @@
 	
 				char[] qualifiedSourceTypeName = CharOperation.concatWith(sourceType.compoundName, '.');
 				
-				if (typeLength > qualifiedSourceTypeName.length)	continue;
+				if (typeLength > qualifiedSourceTypeName.length) continue;
+				if (!(packageBinding == sourceType.getPackage())) continue;
 				if (!CharOperation.prefixEquals(qualifiedName, qualifiedSourceTypeName, false))	continue;
 
 				int relevance = computeBaseRelevance();
@@ -2908,7 +3014,8 @@
 						false,
 						invocationSite,
 						invocationScope,
-						true);
+						true,
+						false);
 					staticsOnly |= enclosingType.isStatic();
 					//				}
 					break;
@@ -3023,7 +3130,7 @@
 
 		if(type != null &&
 			type.resolvedType != null &&
-			type.resolvedType.problemId() == Binding.NoError){
+			type.resolvedType.problemId() == ProblemReasons.NoError){
 			TypeBinding tb = type.resolvedType;
 			findVariableName(
 				name,
@@ -3074,7 +3181,7 @@
 	int computeBaseRelevance(){
 		return R_DEFAULT;
 	}
-	private void computeExpectedTypes(AstNode parent, Scope scope){
+	private void computeExpectedTypes(ASTNode parent, Scope scope){
 		
 		// default filter
 		expectedTypesFilter = SUBTYPE;
@@ -3148,7 +3255,7 @@
 					allocationExpression);
 			}
 		} else if(parent instanceof OperatorExpression) {
-			int operator = (parent.bits & AstNode.OperatorMASK) >> AstNode.OperatorSHIFT;
+			int operator = (parent.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
 			if(parent instanceof ConditionalExpression) {
 				// for future use
 			} else if(parent instanceof InstanceOfExpression) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
index 38de531..922d863 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/RelevanceConstants.java
@@ -24,10 +24,11 @@
 	int R_ABSTRACT_METHOD = 20;
 	int R_NON_STATIC = 10;
 	int R_UNQUALIFIED = 3;
+	int R_QUALIFIED = 2;
 	int R_NAME_FIRST_PREFIX = 6;
 	int R_NAME_PREFIX = 5;
 	int R_NAME_FIRST_SUFFIX = 4;
 	int R_NAME_SUFFIX = 3;
-	
+	int R_NON_STATIC_OVERIDE = 3;
 	
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
index 85c34b3..9c461d7 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java
@@ -12,6 +12,7 @@
 
 import java.util.*;
 
+import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.internal.codeassist.impl.*;
 import org.eclipse.jdt.internal.codeassist.select.*;
@@ -22,6 +23,9 @@
 import org.eclipse.jdt.internal.compiler.parser.*;
 import org.eclipse.jdt.internal.compiler.problem.*;
 import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.core.SelectionRequestor;
+import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
+import org.eclipse.jdt.internal.core.util.ASTNodeFinder;
 
 /**
  * The selection engine is intended to infer the nature of a selected name in some
@@ -96,9 +100,9 @@
 				int problemStartPosition,
 				int problemEndPosition,
 				int lineNumber,
-				ReferenceContext referenceContext,
+				ReferenceContext refContext,
 				CompilationResult unitResult) {
-				IProblem problem =  super.createProblem(
+				IProblem pb =  super.createProblem(
 					fileName,
 					problemId,
 					problemArguments,
@@ -107,18 +111,18 @@
 					problemStartPosition,
 					problemEndPosition,
 					lineNumber,
-					referenceContext,
+					refContext,
 					unitResult);
-					if(SelectionEngine.this.problem == null && problem.isError() && (problem.getID() & IProblem.Syntax) == 0) {
-						SelectionEngine.this.problem = problem;
+					if(SelectionEngine.this.problem == null && pb.isError() && (pb.getID() & IProblem.Syntax) == 0) {
+						SelectionEngine.this.problem = pb;
 					}
 
-					return problem;
+					return pb;
 			}
 		};
-		this.parser = new SelectionParser(problemReporter, this.compilerOptions.sourceLevel >= CompilerOptions.JDK1_4);
 		this.lookupEnvironment =
 			new LookupEnvironment(this, this.compilerOptions, problemReporter, nameEnvironment);
+		this.parser = new SelectionParser(problemReporter);
 	}
 
 	/**
@@ -162,7 +166,7 @@
 					packageName,
 					className,
 					false);
-				acceptedAnswer = true;
+				this.acceptedAnswer = true;
 			}
 		}
 	}
@@ -205,11 +209,11 @@
 				
 			} else {
 				noProposal = false;
-				requestor.acceptInterface(
+				this.requestor.acceptInterface(
 					packageName,
 					interfaceName,
 					false);
-				acceptedAnswer = true;
+				this.acceptedAnswer = true;
 			}
 		}
 	}
@@ -223,14 +227,15 @@
 	 *    The default package is represented by an empty array.
 	 */
 	public void acceptPackage(char[] packageName) {
+		// implementation of interface method
 	}
 
 	private void acceptQualifiedTypes() {
 		if(acceptedClasses != null){
-			acceptedAnswer = true;
+			this.acceptedAnswer = true;
 			for (int i = 0; i < acceptedClassesCount; i++) {
 				noProposal = false;
-				requestor.acceptClass(
+				this.requestor.acceptClass(
 					acceptedClasses[i][0],
 					acceptedClasses[i][1],
 					true);
@@ -239,10 +244,10 @@
 			acceptedClassesCount = 0;
 		}
 		if(acceptedInterfaces != null){
-			acceptedAnswer = true;
+			this.acceptedAnswer = true;
 			for (int i = 0; i < acceptedInterfacesCount; i++) {
 				noProposal = false;
-				requestor.acceptInterface(
+				this.requestor.acceptInterface(
 					acceptedInterfaces[i][0],
 					acceptedInterfaces[i][1],
 					true);
@@ -399,6 +404,19 @@
 		return parser;
 	}
 
+	/*
+	 * Returns whether the given binding is a local/anonymous reference binding, or if its declaring class is
+	 * local.
+	 */
+	private boolean isLocal(ReferenceBinding binding) {
+		if (!(binding instanceof SourceTypeBinding)) return false;
+		if (binding instanceof LocalTypeBinding) return true;
+		if (binding instanceof MemberTypeBinding) {
+			return isLocal(((MemberTypeBinding)binding).enclosingType);
+		}
+		return false;
+	}
+
 	/**
 	 * Ask the engine to compute the selection at the specified position
 	 * of the given compilation unit.
@@ -430,7 +448,7 @@
 		if (!checkSelection(source, selectionSourceStart, selectionSourceEnd))
 			return;
 		try {
-			acceptedAnswer = false;
+			this.acceptedAnswer = false;
 			CompilationResult result = new CompilationResult(sourceUnit, 1, 1, this.compilerOptions.maxProblemsPerUnit);
 			CompilationUnitDeclaration parsedUnit =
 				parser.dietParse(sourceUnit, result, actualSelectionStart, actualSelectionEnd);
@@ -483,12 +501,15 @@
 							lookupEnvironment.completeTypeBindings(parsedUnit, true);
 							parsedUnit.scope.faultInTypes();
 							selectDeclaration(parsedUnit);
-							parseMethod(parsedUnit, selectionSourceStart);
+							ASTNode node = parseBlockStatements(parsedUnit, selectionSourceStart);
 							if(DEBUG) {
 								System.out.println("SELECTION - AST :"); //$NON-NLS-1$
 								System.out.println(parsedUnit.toString());
 							}
 							parsedUnit.resolve();
+							if (node != null) {
+								selectLocalDeclaration(node);
+							}
 						} catch (SelectionNodeFound e) {
 							if (e.binding != null) {
 								if(DEBUG) {
@@ -496,7 +517,7 @@
 									System.out.println(e.binding.toString());
 								}
 								// if null then we found a problem in the selection node
-								selectFrom(e.binding);
+								selectFrom(e.binding, parsedUnit);
 							}
 						}
 					}
@@ -522,7 +543,7 @@
 		}
 	}
 
-	private void selectFrom(Binding binding) {
+	private void selectFrom(Binding binding, CompilationUnitDeclaration parsedUnit) {
 		if (binding instanceof ReferenceBinding) {
 			ReferenceBinding typeBinding = (ReferenceBinding) binding;
 			if (qualifiedSelection != null
@@ -531,30 +552,44 @@
 			}
 			if (typeBinding.isInterface()) {
 				noProposal = false;
-				requestor.acceptInterface(
-					typeBinding.qualifiedPackageName(),
-					typeBinding.qualifiedSourceName(),
-					false);
-			} else if(typeBinding instanceof ProblemReferenceBinding){
-				ProblemReferenceBinding problemBinding = (ProblemReferenceBinding)typeBinding;
-				if(problemBinding.original == null
-					|| !(problemBinding.original instanceof ReferenceBinding)) {
-					return;
+				if (isLocal(typeBinding) && this.requestor instanceof SelectionRequestor) {
+					((SelectionRequestor)this.requestor).acceptLocalType(
+						(SourceTypeBinding)typeBinding,
+						parsedUnit);
+				} else {
+					this.requestor.acceptInterface(
+						typeBinding.qualifiedPackageName(),
+						typeBinding.qualifiedSourceName(),
+						false);
 				}
-				ReferenceBinding original = (ReferenceBinding) problemBinding.original;
+			} else if(typeBinding instanceof ProblemReferenceBinding){
+				ReferenceBinding original = ((ProblemReferenceBinding) typeBinding).original;
+				if(original == null) return;
 				noProposal = false;
-				requestor.acceptClass(
-					original.qualifiedPackageName(),
-					original.qualifiedSourceName(),
-					false);
+				if (isLocal(original) && this.requestor instanceof SelectionRequestor) {
+					((SelectionRequestor)this.requestor).acceptLocalType(
+						(SourceTypeBinding)original,
+						parsedUnit);
+				} else {
+					this.requestor.acceptClass(
+						original.qualifiedPackageName(),
+						original.qualifiedSourceName(),
+						false);
+				}
 			} else {
 				noProposal = false;
-				requestor.acceptClass(
-					typeBinding.qualifiedPackageName(),
-					typeBinding.qualifiedSourceName(),
-					false);
+				if (isLocal(typeBinding) && this.requestor instanceof SelectionRequestor) {
+					((SelectionRequestor)this.requestor).acceptLocalType(
+						(SourceTypeBinding)typeBinding,
+						parsedUnit);
+				} else {
+					this.requestor.acceptClass(
+						typeBinding.qualifiedPackageName(),
+						typeBinding.qualifiedSourceName(),
+						false);
+				}
 			}
-			acceptedAnswer = true;
+			this.acceptedAnswer = true;
 		} else
 			if (binding instanceof MethodBinding) {
 				MethodBinding methodBinding = (MethodBinding) binding;
@@ -567,46 +602,141 @@
 					parameterTypeNames[i] = parameterTypes[i].qualifiedSourceName();
 				}
 				noProposal = false;
-				requestor.acceptMethod(
-					methodBinding.declaringClass.qualifiedPackageName(),
-					methodBinding.declaringClass.qualifiedSourceName(),
-					methodBinding.isConstructor()
-						? methodBinding.declaringClass.sourceName()
-						: methodBinding.selector,
-					parameterPackageNames,
-					parameterTypeNames,
-					methodBinding.isConstructor());
-				acceptedAnswer = true;
+				ReferenceBinding declaringClass = methodBinding.declaringClass;
+				if (isLocal(declaringClass) && this.requestor instanceof SelectionRequestor) {
+					((SelectionRequestor)this.requestor).acceptLocalMethod(
+						(SourceTypeBinding)declaringClass,
+						methodBinding.isConstructor()
+							? declaringClass.sourceName()
+							: methodBinding.selector,
+						parameterPackageNames,
+						parameterTypeNames,
+						methodBinding.isConstructor(),
+						parsedUnit);
+				} else {
+					this.requestor.acceptMethod(
+						declaringClass.qualifiedPackageName(),
+						declaringClass.qualifiedSourceName(),
+						methodBinding.isConstructor()
+							? declaringClass.sourceName()
+							: methodBinding.selector,
+						parameterPackageNames,
+						parameterTypeNames,
+						methodBinding.isConstructor());
+				}
+				this.acceptedAnswer = true;
 			} else
 				if (binding instanceof FieldBinding) {
 					FieldBinding fieldBinding = (FieldBinding) binding;
-					if (fieldBinding.declaringClass != null) { // arraylength
+					ReferenceBinding declaringClass = fieldBinding.declaringClass;
+					if (declaringClass != null) { // arraylength
 						noProposal = false;
-						requestor.acceptField(
-							fieldBinding.declaringClass.qualifiedPackageName(),
-							fieldBinding.declaringClass.qualifiedSourceName(),
-							fieldBinding.name);
-						acceptedAnswer = true;
+						if (isLocal(declaringClass) && this.requestor instanceof SelectionRequestor) {
+							((SelectionRequestor)this.requestor).acceptLocalField(
+								(SourceTypeBinding)declaringClass,
+								fieldBinding.name,
+								parsedUnit);
+						} else {
+							this.requestor.acceptField(
+								declaringClass.qualifiedPackageName(),
+								declaringClass.qualifiedSourceName(),
+								fieldBinding.name);
+						}
+						this.acceptedAnswer = true;
 					}
 				} else
 					if (binding instanceof LocalVariableBinding) {
-						selectFrom(((LocalVariableBinding) binding).type);
-						// open on the type of the variable
+						if (this.requestor instanceof SelectionRequestor) {
+							((SelectionRequestor)this.requestor).acceptLocalVariable(
+								(LocalVariableBinding)binding,
+								parsedUnit);
+							this.acceptedAnswer = true;
+						} else {
+							// open on the type of the variable
+							selectFrom(((LocalVariableBinding) binding).type, parsedUnit);
+						}
 					} else
 						if (binding instanceof ArrayBinding) {
-							selectFrom(((ArrayBinding) binding).leafComponentType);
+							selectFrom(((ArrayBinding) binding).leafComponentType, parsedUnit);
 							// open on the type of the array
 						} else
 							if (binding instanceof PackageBinding) {
 								PackageBinding packageBinding = (PackageBinding) binding;
 								noProposal = false;
 								requestor.acceptPackage(packageBinding.readableName());
-								acceptedAnswer = true;
+								this.acceptedAnswer = true;
 							} else
 								if(binding instanceof BaseTypeBinding) {
-									acceptedAnswer = true;
+									this.acceptedAnswer = true;
 								}
 	}
+	
+	/*
+	 * Checks if a local declaration got selected in this method/initializer/field.
+	 */
+	private void selectLocalDeclaration(ASTNode node) {
+		// the selected identifier is not identical to the parser one (equals but not identical),
+		// for traversing the parse tree, the parser assist identifier is necessary for identitiy checks
+		final char[] assistIdentifier = this.getParser().assistIdentifier();
+		if (assistIdentifier == null) return;
+		
+		class Visitor extends ASTVisitor {
+			public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
+				if (constructorDeclaration.selector == assistIdentifier){
+					if (constructorDeclaration.binding != null) {
+						throw new SelectionNodeFound(constructorDeclaration.binding);
+					} else {
+						if (constructorDeclaration.scope != null) {
+							throw new SelectionNodeFound(new MethodBinding(constructorDeclaration.modifiers, constructorDeclaration.selector, null, null, null, constructorDeclaration.scope.referenceType().binding));
+						}
+					}
+				}
+				return true;
+			}
+			public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+				if (fieldDeclaration.name == assistIdentifier){
+					throw new SelectionNodeFound(fieldDeclaration.binding);
+				}
+				return true;
+			}
+			public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+				if (localTypeDeclaration.name == assistIdentifier) {
+					throw new SelectionNodeFound(localTypeDeclaration.binding);
+				}
+				return true;
+			}
+			public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
+				if (memberTypeDeclaration.name == assistIdentifier) {
+					throw new SelectionNodeFound(memberTypeDeclaration.binding);
+				}
+				return true;
+			}
+			public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
+				if (methodDeclaration.selector == assistIdentifier){
+					if (methodDeclaration.binding != null) {
+						throw new SelectionNodeFound(methodDeclaration.binding);
+					} else {
+						if (methodDeclaration.scope != null) {
+							throw new SelectionNodeFound(new MethodBinding(methodDeclaration.modifiers, methodDeclaration.selector, null, null, null, methodDeclaration.scope.referenceType().binding));
+						}
+					}
+				}
+				return true;
+			}
+			public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
+				if (typeDeclaration.name == assistIdentifier) {
+					throw new SelectionNodeFound(typeDeclaration.binding);
+				}
+				return true;
+			}
+		}
+		
+		if (node instanceof AbstractMethodDeclaration) {
+			((AbstractMethodDeclaration)node).traverse(new Visitor(), (ClassScope)null);
+		} else {
+			((FieldDeclaration)node).traverse(new Visitor(), (MethodScope)null);
+		}
+	}
 
 	/**
 	 * Asks the engine to compute the selection of the given type
@@ -627,7 +757,7 @@
 	 */
 	public void selectType(ISourceType sourceType, char[] typeName, ISourceType[] topLevelTypes, boolean searchInEnvironment) {
 		try {
-			acceptedAnswer = false;
+			this.acceptedAnswer = false;
 
 			// find the outer most type
 			ISourceType outerType = sourceType;
@@ -641,9 +771,9 @@
 			CompilationUnitDeclaration parsedUnit =
 				SourceTypeConverter.buildCompilationUnit(
 						topLevelTypes,
-						false, // no need for field and methods
-						true, // need member types
-						false, // no need for field initialization
+						// no need for field and methods
+						SourceTypeConverter.MEMBER_TYPE, // need member types
+						// no need for field initialization
 						this.parser.problemReporter(), 
 						result);
 
@@ -653,19 +783,10 @@
 					System.out.println(parsedUnit.toString());
 				}
 				// find the type declaration that corresponds to the original source type
-				char[] packageName = sourceType.getPackageName();
-				char[] sourceTypeName = sourceType.getQualifiedName();
-				// the fully qualified name without the package name
-				if (packageName != null) {
-					// remove the package name if necessary
-					sourceTypeName =
-						CharOperation.subarray(
-							sourceType.getQualifiedName(),
-							packageName.length + 1,
-							sourceTypeName.length);
-				};
-				TypeDeclaration typeDecl =
-					parsedUnit.declarationOfType(CharOperation.splitOn('.', sourceTypeName));
+				if (!(sourceType instanceof SourceTypeElementInfo)) return;
+				IType typeHandle = ((SourceTypeElementInfo)sourceType).getHandle();
+				TypeDeclaration typeDecl = new ASTNodeFinder(parsedUnit).findType(typeHandle);
+
 				if (typeDecl != null) {
 
 					// add fake field with the type we're looking for
@@ -708,7 +829,7 @@
 									System.out.println(e.binding.toString());
 								}
 								// if null then we found a problem in the selection node
-								selectFrom(e.binding);
+								selectFrom(e.binding, parsedUnit);
 							}
 						}
 					}
@@ -752,7 +873,7 @@
 
 	// Check if a declaration got selected in this type
 	private void selectDeclaration(TypeDeclaration typeDeclaration, char[] assistIdentifier){
-
+	
 		if (typeDeclaration.name == assistIdentifier){
 			throw new SelectionNodeFound(typeDeclaration.binding);
 		}
@@ -777,7 +898,7 @@
 						throw new SelectionNodeFound(new MethodBinding(method.modifiers, method.selector, null, null, null, method.scope.referenceType().binding));
 					}
 				}
-		}
+			}
 		}
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
index 6538fa4..84ae288 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
@@ -17,12 +17,12 @@
 /**
  * Detect the presence of a node in expression
  */
-public class CompletionNodeDetector extends AbstractSyntaxTreeVisitorAdapter {
-	private AstNode searchedNode;
-	private AstNode parent;
+public class CompletionNodeDetector extends ASTVisitor {
+	private ASTNode searchedNode;
+	private ASTNode parent;
 	private boolean result;
 	
-	public CompletionNodeDetector(AstNode searchedNode, AstNode visitedAst){
+	public CompletionNodeDetector(ASTNode searchedNode, ASTNode visitedAst){
 		this.searchedNode = searchedNode;
 		this.result = false;
 		
@@ -35,7 +35,7 @@
 		return result;
 	}
 	
-	public AstNode getCompletionNodeParent() {
+	public ASTNode getCompletionNodeParent() {
 		return parent;
 	}
 	public void endVisit(AllocationExpression allocationExpression, BlockScope scope) {
@@ -243,7 +243,7 @@
 		return this.visit(unaryExpression);
 	}
 	
-	private void endVisit(AstNode astNode) {
+	private void endVisit(ASTNode astNode) {
 		if(result && parent == null && astNode != searchedNode) {
 			if(!(astNode instanceof AllocationExpression && ((AllocationExpression) astNode).type == searchedNode)
 				&& !(astNode instanceof ConditionalExpression && ((ConditionalExpression) astNode).valueIfTrue == searchedNode)
@@ -252,7 +252,7 @@
 			}
 		}
 	}
-	private boolean visit(AstNode astNode) {
+	private boolean visit(ASTNode astNode) {
 		if(astNode == searchedNode) {
 			result = true;
 		}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
index 651a625..cb1d5f3 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeFound.java
@@ -10,23 +10,23 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.codeassist.complete;
 
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 
 public class CompletionNodeFound extends RuntimeException {
-	public AstNode astNode;
+	public ASTNode astNode;
 	public Binding qualifiedBinding;
 	public Scope scope;
 public CompletionNodeFound() {
 	this(null, null, null); // we found a problem in the completion node
 }
-public CompletionNodeFound(AstNode astNode, Binding qualifiedBinding, Scope scope) {
+public CompletionNodeFound(ASTNode astNode, Binding qualifiedBinding, Scope scope) {
 	this.astNode = astNode;
 	this.qualifiedBinding = qualifiedBinding;
 	this.scope = scope;
 }
-public CompletionNodeFound(AstNode astNode, Scope scope) {
+public CompletionNodeFound(ASTNode astNode, Scope scope) {
 	this(astNode, null, scope);
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnArgumentName.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnArgumentName.java
index 5ccacad..724f26b 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnArgumentName.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnArgumentName.java
@@ -19,33 +19,40 @@
 
 
 public class CompletionOnArgumentName extends Argument {
+
 	private static final char[] FAKENAMESUFFIX = " ".toCharArray(); //$NON-NLS-1$
 	public char[] realName;
 	public boolean isCatchArgument = false;
+
 	public CompletionOnArgumentName(char[] name , long posNom , TypeReference tr , int modifiers){
+
 		super(CharOperation.concat(name, FAKENAMESUFFIX), posNom, tr, modifiers);
 		this.realName = name;
 	}
 	
+	public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
+
+		super.bind(scope, typeBinding, used);
+		throw new CompletionNodeFound(this, scope);
+	}
+	
+	public StringBuffer print(int indent, StringBuffer output) {
+		
+		printIndent(indent, output);
+		output.append("<CompleteOnArgumentName:"); //$NON-NLS-1$
+		if (type != null) type.print(0, output).append(' ');
+		output.append(this.realName);
+		if (initialization != null) {
+			output.append(" = "); //$NON-NLS-1$
+			initialization.printExpression(0, output);
+		}
+		return output.append('>');
+	}	
+
 	public void resolve(BlockScope scope) {
+
 		super.resolve(scope);
 		throw new CompletionNodeFound(this, scope);
 	}
-	
-	public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
-		super.bind(scope, typeBinding, used);
-		
-		throw new CompletionNodeFound(this, scope);
-	}
-	
-	public String toString(int tab) {
-		String s = tabString(tab);
-		s += "<CompleteOnArgumentName:"; //$NON-NLS-1$
-		if (type != null) s += type.toString() + " "; //$NON-NLS-1$
-		s += new String(realName);
-		if (initialization != null) s += " = " + initialization.toStringExpression(); //$NON-NLS-1$
-		s += ">"; //$NON-NLS-1$
-		return s;
-	}	
 }
 
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java
index e798863..dd6e5c4 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassLiteralAccess.java
@@ -35,25 +35,27 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class CompletionOnClassLiteralAccess extends ClassLiteralAccess {
+	
 	public char[] completionIdentifier;
 	public int classStart;
 	
-public CompletionOnClassLiteralAccess(long pos, TypeReference t) {
-	super((int)pos, t);
-	this.classStart = (int) (pos >>> 32);
-}
-public TypeBinding resolveType(BlockScope scope) {
-	if (super.resolveType(scope) == null)
-		throw new CompletionNodeFound();
-	else
-		throw new CompletionNodeFound(this, targetType, scope);
-}
-public String toStringExpression() {
-	StringBuffer result = new StringBuffer("<CompleteOnClassLiteralAccess:"); //$NON-NLS-1$
-	result.append(type.toString());
-	result.append("."); //$NON-NLS-1$
-	result.append(completionIdentifier);
-	result.append(">"); //$NON-NLS-1$
-	return result.toString();
-}
+	public CompletionOnClassLiteralAccess(long pos, TypeReference t) {
+		
+		super((int)pos, t);
+		this.classStart = (int) (pos >>> 32);
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		
+		output.append("<CompleteOnClassLiteralAccess:"); //$NON-NLS-1$
+		return type.print(0, output).append('.').append(completionIdentifier).append('>');
+	}
+	
+	public TypeBinding resolveType(BlockScope scope) {
+		
+		if (super.resolveType(scope) == null)
+			throw new CompletionNodeFound();
+		else
+			throw new CompletionNodeFound(this, targetType, scope);
+	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassReference.java
index b7b9a00..e10dbed 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassReference.java
@@ -11,10 +11,14 @@
 package org.eclipse.jdt.internal.codeassist.complete;
 
 public class CompletionOnClassReference extends CompletionOnSingleTypeReference {
+
 	public CompletionOnClassReference(char[] source, long pos) {
+
 		super(source, pos);
 	}
-	public String toStringExpression(int tab) {
-		return "<CompleteOnClass:" + new String(token) + ">"; //$NON-NLS-2$ //$NON-NLS-1$
+
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		
+		return output.append("<CompleteOnClass:").append(token).append('>'); //$NON-NLS-1$
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
index 62ce069..e5bea7e 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
@@ -37,10 +37,14 @@
  * which should be replaced by the completion.
  */
 public class CompletionOnExceptionReference extends CompletionOnSingleTypeReference {
-public CompletionOnExceptionReference(char[] source, long pos) {
-	super(source, pos);
-}
-public String toStringExpression(int tab) {
-	return "<CompleteOnException:" + new String(token) + ">"; //$NON-NLS-2$ //$NON-NLS-1$
-}
+
+	public CompletionOnExceptionReference(char[] source, long pos) {
+
+		super(source, pos);
+	}
+
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		
+		return output.append("<CompleteOnException:").append(token).append('>'); //$NON-NLS-1$
+	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java
index 89b5048..969f7b2 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExplicitConstructorCall.java
@@ -36,47 +36,48 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class CompletionOnExplicitConstructorCall extends ExplicitConstructorCall {
-public CompletionOnExplicitConstructorCall(int accessMode) {
-	super(accessMode);
-}
-public void resolve(BlockScope scope) {
-	ReferenceBinding receiverType = scope.enclosingSourceType();
+
+	public CompletionOnExplicitConstructorCall(int accessMode) {
+		super(accessMode);
+	}
 	
-	if (arguments != null) {
-		int argsLength = arguments.length;
-		for (int a = argsLength; --a >= 0;)
-			arguments[a].resolveType(scope);
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+		
+		printIndent(tab, output);
+		output.append("<CompleteOnExplicitConstructorCall:"); //$NON-NLS-1$
+		if (qualification != null) qualification.printExpression(0, output).append('.');
+		if (accessMode == This) {
+			output.append("this("); //$NON-NLS-1$
+		} else {
+			output.append("super("); //$NON-NLS-1$
+		}
+		if (arguments != null) {
+			for (int i = 0; i < arguments.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				arguments[i].printExpression(0, output);
+			}
+		}
+		return output.append(")>;"); //$NON-NLS-1$
 	}
 
-	if (accessMode != This && receiverType != null) {
-		if (receiverType.isHierarchyInconsistent())
+	public void resolve(BlockScope scope) {
+
+		ReferenceBinding receiverType = scope.enclosingSourceType();
+		
+		if (arguments != null) {
+			int argsLength = arguments.length;
+			for (int a = argsLength; --a >= 0;)
+				arguments[a].resolveType(scope);
+		}
+	
+		if (accessMode != This && receiverType != null) {
+			if (receiverType.isHierarchyInconsistent())
+				throw new CompletionNodeFound();
+			receiverType = receiverType.superclass();
+		}
+		if (receiverType == null)
 			throw new CompletionNodeFound();
-		receiverType = receiverType.superclass();
+		else
+			throw new CompletionNodeFound(this, receiverType, scope);
 	}
-	if (receiverType == null)
-		throw new CompletionNodeFound();
-	else
-		throw new CompletionNodeFound(this, receiverType, scope);
-}
-public String toString(int tab) {
-	String s = tabString(tab);
-	s += "<CompleteOnExplicitConstructorCall:"; //$NON-NLS-1$
-	if (qualification != null)
-		s = s + qualification.toStringExpression() + "."; //$NON-NLS-1$
-	if (accessMode == This) {
-		s = s + "this("; //$NON-NLS-1$
-	} else {
-		s = s + "super("; //$NON-NLS-1$
-	}
-	if (arguments != null) {
-		for (int i = 0; i < arguments.length; i++) {
-			s += arguments[i].toStringExpression();
-			if (i != arguments.length - 1) {
-				s += ", "; //$NON-NLS-1$
-			}
-		};
-	}
-	s += ")>"; //$NON-NLS-1$
-	return s;
-}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldName.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldName.java
index 6b2a24e..7ce7778 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldName.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldName.java
@@ -11,32 +11,33 @@
 package org.eclipse.jdt.internal.codeassist.complete;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
 
 public class CompletionOnFieldName extends FieldDeclaration {
 	private static final char[] FAKENAMESUFFIX = " ".toCharArray(); //$NON-NLS-1$
 	public char[] realName;
-	public CompletionOnFieldName(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
-		super(initialization, CharOperation.concat(name, FAKENAMESUFFIX), sourceStart, sourceEnd); //$NON-NLS-1$
+	public CompletionOnFieldName(char[] name, int sourceStart, int sourceEnd) {
+		super(CharOperation.concat(name, FAKENAMESUFFIX), sourceStart, sourceEnd); //$NON-NLS-1$
 		this.realName = name;
 	}
 	
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+		
+		printIndent(tab, output).append("<CompleteOnFieldName:"); //$NON-NLS-1$
+		if (type != null) type.print(0, output).append(' ');
+		output.append(realName);
+		if (initialization != null) {
+			output.append(" = "); //$NON-NLS-1$
+			initialization.printExpression(0, output); 
+		}
+		return output.append(">;"); //$NON-NLS-1$
+	}	
+
 	public void resolve(MethodScope initializationScope) {
 		super.resolve(initializationScope);
 		
 		throw new CompletionNodeFound(this, initializationScope);
 	}
-	
-	public String toString(int tab) {
-		String s = tabString(tab);
-		s += "<CompleteOnFieldName:"; //$NON-NLS-1$
-		if (type != null) s += type.toString() + " "; //$NON-NLS-1$
-		s += new String(realName);
-		if (initialization != null) s += " = " + initialization.toStringExpression(); //$NON-NLS-1$
-		s += ">"; //$NON-NLS-1$
-		return s;
-	}	
 }
 
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldType.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldType.java
index be4ed62..c4b2c83 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldType.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnFieldType.java
@@ -52,8 +52,8 @@
 	else // handle the qualified type ref directly
 		return type.getTypeBinding(scope);
 }
-public String toString(int tab) {
+public StringBuffer printStatement(int tab, StringBuffer output) {
 
-	return type.toString(tab);
+	return type.print(tab, output).append(';'); 
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnImportReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnImportReference.java
index cabdfe9..31dea4c 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnImportReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnImportReference.java
@@ -36,20 +36,16 @@
 
 public class CompletionOnImportReference extends ImportReference {
 
-public CompletionOnImportReference(char[][] tokens , long[] positions) {
-	super(tokens, positions, false);
+public CompletionOnImportReference(char[][] tokens , long[] positions, int modifiers) {
+	super(tokens, positions, false, modifiers);
 }
-public String toString(int tab, boolean withOnDemand) {
+public StringBuffer print(int indent, StringBuffer output, boolean withOnDemand) {
 
-	StringBuffer buffer = new StringBuffer(tabString(tab));
-	buffer.	append("<CompleteOnImport:"); //$NON-NLS-1$
+	printIndent(indent, output).append("<CompleteOnImport:"); //$NON-NLS-1$
 	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		if (i < (tokens.length - 1)) {
-			buffer.append("."); //$NON-NLS-1$
-		}
+		if (i > 0) output.append('.');
+		output.append(tokens[i]);
 	}
-	buffer.append(">"); //$NON-NLS-1$
-	return buffer.toString();
+	return output.append('>');
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnInterfaceReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnInterfaceReference.java
index 1f03c17..d44d5cd 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnInterfaceReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnInterfaceReference.java
@@ -14,7 +14,7 @@
 	public CompletionOnInterfaceReference(char[] source, long pos) {
 		super(source, pos);
 	}
-	public String toStringExpression(int tab) {
-		return "<CompleteOnInterface:" + new String(token) + ">"; //$NON-NLS-2$ //$NON-NLS-1$
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		return output.append("<CompleteOnInterface:").append(token).append('>');//$NON-NLS-1$
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword.java
index 4eaa384..a8974b4 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.codeassist.complete;
 
 public interface CompletionOnKeyword {
+	
 	char[] getToken();
 	char[][] getPossibleKeywords();
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword1.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword1.java
index fc58f0f..8d0745a 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword1.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword1.java
@@ -35,7 +35,8 @@
 	public TypeBinding getTypeBinding(Scope scope) {
 		throw new CompletionNodeFound(this, scope);
 	}
-	public String toStringExpression(int tab){
-		return "<CompleteOnKeyword:"+new String(token)+">";  //$NON-NLS-1$  //$NON-NLS-2$
+	public StringBuffer printExpression(int indent, StringBuffer output){
+		
+		return output.append("<CompleteOnKeyword:").append(token).append('>');  //$NON-NLS-1$ 
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword2.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword2.java
index 6fa6cb7..6b84425 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword2.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword2.java
@@ -14,12 +14,10 @@
 
 public class CompletionOnKeyword2 extends ImportReference implements CompletionOnKeyword {
 	private char[] token;
-	private long pos;
 	private char[][] possibleKeywords;
 	public CompletionOnKeyword2(char[] token, long pos, char[][] possibleKeywords) {
-		super(new char[][]{token}, new long[]{pos}, false);
+		super(new char[][]{token}, new long[]{pos}, false, AccDefault);
 		this.token = token;
-		this.pos = pos;
 		this.possibleKeywords = possibleKeywords;
 	}
 	public char[] getToken() {
@@ -28,7 +26,8 @@
 	public char[][] getPossibleKeywords() {
 		return possibleKeywords;
 	}
-	public String toString(int tab, boolean withOnDemand) {
-		return "<CompleteOnKeyword:" + new String(token) + ">"; //$NON-NLS-1$ //$NON-NLS-2$
+	public StringBuffer print(int indent, StringBuffer output, boolean withOnDemand) {
+		
+		return printIndent(indent, output).append("<CompleteOnKeyword:").append(token).append('>'); //$NON-NLS-1$
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword3.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword3.java
index a0fa00b..913ed20 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword3.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnKeyword3.java
@@ -15,8 +15,6 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 
 public class CompletionOnKeyword3 extends SingleNameReference implements CompletionOnKeyword{
-	private char[] token;
-	private long pos;
 	private char[][] possibleKeywords;
 	public CompletionOnKeyword3(char[] token, long pos, char[] possibleKeyword) {
 		this(token, pos, new char[][]{possibleKeyword});
@@ -24,7 +22,6 @@
 	public CompletionOnKeyword3(char[] token, long pos, char[][] possibleKeywords) {
 		super(token, pos);
 		this.token = token;
-		this.pos = pos;
 		this.possibleKeywords = possibleKeywords;
 	}
 	public char[] getToken() {
@@ -33,10 +30,11 @@
 	public char[][] getPossibleKeywords() {
 		return possibleKeywords;
 	}
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		
+		return output.append("<CompleteOnKeyword:").append(token).append('>'); //$NON-NLS-1$
+	}
 	public TypeBinding resolveType(BlockScope scope) {
 		throw new CompletionNodeFound(this, scope);
 	}
-	public String toStringExpression() {
-		return "<CompleteOnKeyword:" + new String(token) + ">"; //$NON-NLS-1$ //$NON-NLS-2$
-	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnLocalName.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnLocalName.java
index ecf1d40..9f57e81 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnLocalName.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnLocalName.java
@@ -11,7 +11,6 @@
 package org.eclipse.jdt.internal.codeassist.complete;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 
@@ -19,24 +18,30 @@
 public class CompletionOnLocalName extends LocalDeclaration {
 	private static final char[] FAKENAMESUFFIX = " ".toCharArray(); //$NON-NLS-1$
 	public char[] realName;
-	public CompletionOnLocalName(Expression expr,char[] name, int sourceStart, int sourceEnd){
-		super(expr, CharOperation.concat(name, FAKENAMESUFFIX), sourceStart, sourceEnd);
+
+	public CompletionOnLocalName(char[] name, int sourceStart, int sourceEnd){
+
+		super(CharOperation.concat(name, FAKENAMESUFFIX), sourceStart, sourceEnd);
 		this.realName = name;
 	}
 	
 	public void resolve(BlockScope scope) {
-		super.resolve(scope);
 		
+		super.resolve(scope);
 		throw new CompletionNodeFound(this, scope);
 	}
-	public String toString(int tab) {
-		String s = tabString(tab);
-		s += "<CompleteOnLocalName:"; //$NON-NLS-1$
-		if (type != null) s += type.toString() + " "; //$NON-NLS-1$
-		s += new String(realName);
-		if (initialization != null) s += " = " + initialization.toStringExpression(); //$NON-NLS-1$
-		s += ">"; //$NON-NLS-1$
-		return s;
+
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+
+		printIndent(indent, output);
+		output.append("<CompleteOnLocalName:"); //$NON-NLS-1$
+		if (type != null)  type.print(0, output).append(' ');
+		output.append(this.realName);
+		if (initialization != null) {
+			output.append(" = "); //$NON-NLS-1$
+			initialization.printExpression(0, output); 
+		}
+		return output.append(">;"); //$NON-NLS-1$
 	}	
 }
 
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java
index 2e8f6fa..1ae7545 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMemberAccess.java
@@ -38,21 +38,23 @@
 public class CompletionOnMemberAccess extends FieldReference {
 	
 	public CompletionOnMemberAccess(char[] source, long pos) {
+		
 		super(source, pos);
 	}
 	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		output.append("<CompleteOnMemberAccess:"); //$NON-NLS-1$
+		return super.printExpression(0, output).append('>'); 
+	}
+
 	public TypeBinding resolveType(BlockScope scope) {
-		TypeBinding receiverType = receiver.resolveType(scope);
-		if (receiverType == null || receiverType.isBaseType())
+		
+		this.receiverType = receiver.resolveType(scope);
+		if (this.receiverType == null || this.receiverType.isBaseType())
 			throw new CompletionNodeFound();
 		else
-			throw new CompletionNodeFound(this, receiverType, scope);
+			throw new CompletionNodeFound(this, this.receiverType, scope);
 		// array types are passed along to find the length field
 	}
-	
-	public String toStringExpression() {
-
-		return "<CompleteOnMemberAccess:" //$NON-NLS-1$
-						+ super.toStringExpression() + ">"; //$NON-NLS-1$
-	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java
index cff6067..39386c3 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMessageSend.java
@@ -47,30 +47,26 @@
 		if (receiver.isImplicitThis())
 			throw new CompletionNodeFound(this, null, scope);
 
-		TypeBinding receiverType = receiver.resolveType(scope);
-		if (receiverType == null || receiverType.isBaseType())
+		this.receiverType = receiver.resolveType(scope);
+		if (this.receiverType == null || this.receiverType.isBaseType())
 			throw new CompletionNodeFound();
 
-		if (receiverType.isArrayType())
-			receiverType = scope.getJavaLangObject();
-		throw new CompletionNodeFound(this, receiverType, scope);
+		if (this.receiverType.isArrayType())
+			this.receiverType = scope.getJavaLangObject();
+		throw new CompletionNodeFound(this, this.receiverType, scope);
 	}
 
-	public String toStringExpression() {
+	public StringBuffer printExpression(int indent, StringBuffer output) {
 
-		String s = "<CompleteOnMessageSend:"; //$NON-NLS-1$
-		if (!receiver.isImplicitThis())
-			s = s + receiver.toStringExpression() + "."; //$NON-NLS-1$
-		s = s + new String(selector) + "("; //$NON-NLS-1$
+		output.append("<CompleteOnMessageSend:"); //$NON-NLS-1$
+		if (!receiver.isImplicitThis()) receiver.printExpression(0, output).append('.'); //$NON-NLS-1$
+		output.append(selector).append('('); //$NON-NLS-1$
 		if (arguments != null) {
 			for (int i = 0; i < arguments.length; i++) {
-				s += arguments[i].toStringExpression();
-				if (i != arguments.length - 1) {
-					s += ", "; //$NON-NLS-1$
-				}
-			};
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				arguments[i].printExpression(0, output);
+			}
 		}
-		s = s + ")>"; //$NON-NLS-1$
-		return s;
+		return output.append(")>"); //$NON-NLS-1$
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMethodName.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMethodName.java
index 25c0fd6..6c0717a 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMethodName.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMethodName.java
@@ -21,41 +21,33 @@
 		super(compilationResult);
 	}
 	
+	public StringBuffer print(int indent, StringBuffer output) {
+
+		printIndent(indent, output);
+		output.append("<CompletionOnMethodName:"); //$NON-NLS-1$
+		printModifiers(this.modifiers, output);
+		printReturnType(0, output);
+		output.append(selector).append('(');
+		if (arguments != null) {
+			for (int i = 0; i < arguments.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				arguments[i].print(0, output);
+			}
+		}
+		output.append(')');
+		if (thrownExceptions != null) {
+			output.append(" throws "); //$NON-NLS-1$
+			for (int i = 0; i < thrownExceptions.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				thrownExceptions[i].print(0, output);
+			}
+		}
+		return output.append('>');
+	}
+	
 	public void resolve(ClassScope upperScope) {
 		
 		super.resolve(upperScope);
 		throw new CompletionNodeFound(this, upperScope);
 	}
-
-	public String toString(int tab) {
-
-		String s = tabString(tab);
-		s += "<CompletionOnMethodName:"; //$NON-NLS-1$
-
-		if (modifiers != AccDefault) {
-			s += modifiersString(modifiers);
-		}
-
-		s += returnTypeToString(0);
-		s += new String(selector) + "("; //$NON-NLS-1$
-		if (arguments != null) {
-			for (int i = 0; i < arguments.length; i++) {
-				s += arguments[i].toString(0);
-				if (i != (arguments.length - 1))
-					s = s + ", "; //$NON-NLS-1$
-			};
-		};
-		s += ")"; //$NON-NLS-1$
-		if (thrownExceptions != null) {
-			s += " throws "; //$NON-NLS-1$
-			for (int i = 0; i < thrownExceptions.length; i++) {
-				s += thrownExceptions[i].toString(0);
-				if (i != (thrownExceptions.length - 1))
-					s = s + ", "; //$NON-NLS-1$
-			};
-		};
-
-		s += ">"; //$NON-NLS-1$
-		return s;
-	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMethodReturnType.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMethodReturnType.java
index 206726d..b0ec1c3 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMethodReturnType.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnMethodReturnType.java
@@ -26,8 +26,8 @@
 			throw new CompletionNodeFound(this, this.scope);
 	}
 	
-	public String toString(int tab) {
-		return returnType.toString(tab);
+	public StringBuffer print(int tab, StringBuffer output) {
+		return returnType.print(tab, output);
 	}
 
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnPackageReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnPackageReference.java
index 1edde4f..555b08e 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnPackageReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnPackageReference.java
@@ -36,18 +36,15 @@
 
 public class CompletionOnPackageReference extends ImportReference {
 public CompletionOnPackageReference(char[][] tokens , long[] positions) {
-	super(tokens, positions, true);
+	super(tokens, positions, true, AccDefault);
 }
-public String toString(int tab, boolean withOnDemand) {
-	StringBuffer buffer = new StringBuffer(tabString(tab));
-	buffer.	append("<CompleteOnPackage:"); //$NON-NLS-1$
+public StringBuffer print(int indent, StringBuffer output, boolean withOnDemand) {
+	
+	printIndent(indent, output).append("<CompleteOnPackage:"); //$NON-NLS-1$
 	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		if (i < (tokens.length - 1)) {
-			buffer.append("."); //$NON-NLS-1$
-		}
+		if (i > 0) output.append('.');
+		output.append(tokens[i]);
 	}
-	buffer.append(">"); //$NON-NLS-1$
-	return buffer.toString();
+	return output.append('>'); 
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java
index 30ebd68..9ba3e1b 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedAllocationExpression.java
@@ -63,11 +63,11 @@
 
 	throw new CompletionNodeFound(this, this.resolvedType, scope);
 }
-public String toStringExpression(int tab) {
-	return 
-		((this.enclosingInstance == null) ? 
-			"<CompleteOnAllocationExpression:" :  //$NON-NLS-1$
-			"<CompleteOnQualifiedAllocationExpression:") +  //$NON-NLS-1$
-		super.toStringExpression(tab) + ">"; //$NON-NLS-1$
+public StringBuffer printExpression(int indent, StringBuffer output) {
+	if (this.enclosingInstance == null) 
+		output.append("<CompleteOnAllocationExpression:" );  //$NON-NLS-1$
+	else 
+		output.append("<CompleteOnQualifiedAllocationExpression:");  //$NON-NLS-1$
+	return super.printExpression(indent, output).append('>'); 
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedClassReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedClassReference.java
index 298b06f..0bf445e 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedClassReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedClassReference.java
@@ -14,15 +14,14 @@
 public CompletionOnQualifiedClassReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
 	super(previousIdentifiers, completionIdentifier, positions);
 }
-public String toStringExpression(int tab) {
+public StringBuffer printExpression(int indent, StringBuffer output) {
 
-	StringBuffer buffer = new StringBuffer();
-	buffer. append("<CompleteOnClass:"); //$NON-NLS-1$
+	output.append("<CompleteOnClass:"); //$NON-NLS-1$
 	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		buffer.append("."); //$NON-NLS-1$
+		output.append(tokens[i]);
+		output.append('.');
 	}
-	buffer.append(completionIdentifier).append(">"); //$NON-NLS-1$
-	return buffer.toString();
+	output.append(completionIdentifier).append('>');
+	return output;
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
index f13341b..30e40e0 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
@@ -41,15 +41,14 @@
 public CompletionOnQualifiedExceptionReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
 	super(previousIdentifiers, completionIdentifier, positions);
 }
-public String toStringExpression(int tab) {
+public StringBuffer printExpression(int indent, StringBuffer output) {
 
-	StringBuffer buffer = new StringBuffer();
-	buffer. append("<CompleteOnException:"); //$NON-NLS-1$
+	output.append("<CompleteOnException:"); //$NON-NLS-1$
 	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		buffer.append("."); //$NON-NLS-1$
+		output.append(tokens[i]);
+		output.append('.'); 
 	}
-	buffer.append(completionIdentifier).append(">"); //$NON-NLS-1$
-	return buffer.toString();
+	output.append(completionIdentifier).append('>');
+	return output;
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedInterfaceReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedInterfaceReference.java
index f4f3870..8147ab1 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedInterfaceReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedInterfaceReference.java
@@ -14,15 +14,14 @@
 public CompletionOnQualifiedInterfaceReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
 	super(previousIdentifiers, completionIdentifier, positions);
 }
-public String toStringExpression(int tab) {
+public StringBuffer printExpression(int indent, StringBuffer output) {
 
-	StringBuffer buffer = new StringBuffer();
-	buffer. append("<CompleteOnInterface:"); //$NON-NLS-1$
+	output.append("<CompleteOnInterface:"); //$NON-NLS-1$
 	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		buffer.append("."); //$NON-NLS-1$
+		output.append(tokens[i]);
+		output.append('.'); 
 	}
-	buffer.append(completionIdentifier).append(">"); //$NON-NLS-1$
-	return buffer.toString();
+	output.append(completionIdentifier).append('>'); 
+	return output;
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedNameReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedNameReference.java
index 257da1e..834a122 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedNameReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedNameReference.java
@@ -38,16 +38,19 @@
 
 public class CompletionOnQualifiedNameReference extends QualifiedNameReference {
 	public char[] completionIdentifier;
-	public long[] sourcePositions; // positions of each token, the last one being the positions of the completion identifier
 public CompletionOnQualifiedNameReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
-	super(previousIdentifiers, (int) (positions[0] >>> 32), (int) positions[positions.length - 1]);
+	super(previousIdentifiers, positions, (int) (positions[0] >>> 32), (int) positions[positions.length - 1]);
 	this.completionIdentifier = completionIdentifier;
-	this.sourcePositions = positions;
 }
-public CompletionOnQualifiedNameReference(char[][] previousIdentifiers, char[] completionIdentifier, int sourceStart, int sourceEnd) {
-	super(previousIdentifiers, sourceStart, sourceEnd);
-	this.completionIdentifier = completionIdentifier;
-	this.sourcePositions = new long[] {((long)sourceStart << 32) + sourceEnd};
+public StringBuffer printExpression(int indent, StringBuffer output) {
+
+	output.append("<CompleteOnName:"); //$NON-NLS-1$
+	for (int i = 0; i < tokens.length; i++) {
+		output.append(tokens[i]);
+		output.append('.'); //$NON-NLS-1$
+	}
+	output.append(completionIdentifier).append('>'); 
+	return output;
 }
 public TypeBinding resolveType(BlockScope scope) {
 	// it can be a package, type, member type, local variable or field
@@ -65,14 +68,4 @@
 
 	throw new CompletionNodeFound(this, binding, scope);
 }
-public String toStringExpression() {
-
-	StringBuffer buffer = new StringBuffer("<CompleteOnName:"); //$NON-NLS-1$
-	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		buffer.append("."); //$NON-NLS-1$
-	}
-	buffer.append(completionIdentifier).append(">"); //$NON-NLS-1$
-	return buffer.toString();
-}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
index 78469c3..0630057 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
@@ -52,15 +52,14 @@
 
 	throw new CompletionNodeFound(this, binding, scope);
 }
-public String toStringExpression(int tab) {
+public StringBuffer printExpression(int indent, StringBuffer output) {
 
-	StringBuffer buffer = new StringBuffer();
-	buffer.append("<CompleteOnType:"); //$NON-NLS-1$
+	output.append("<CompleteOnType:"); //$NON-NLS-1$
 	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		buffer.append("."); //$NON-NLS-1$
+		output.append(tokens[i]);
+		output.append('.'); 
 	}
-	buffer.append(completionIdentifier).append(">"); //$NON-NLS-1$
-	return buffer.toString();
+	output.append(completionIdentifier).append('>');
+	return output;
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleNameReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleNameReference.java
index 7c7b9d7..105dcd8 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleNameReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleNameReference.java
@@ -35,20 +35,27 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
  
 public class CompletionOnSingleNameReference extends SingleNameReference {
-public char[][] possibleKeywords;
-public boolean canBeExplicitConstructor;
-public CompletionOnSingleNameReference(char[] source, long pos) {
-	this(source, pos, null, false);
-}
-public CompletionOnSingleNameReference(char[] source, long pos, char[][] possibleKeywords, boolean canBeExplicitConstructor) {
-	super(source, pos);
-	this.possibleKeywords = possibleKeywords;
-	this.canBeExplicitConstructor = canBeExplicitConstructor;
-}
-public TypeBinding resolveType(BlockScope scope) {
-	throw new CompletionNodeFound(this, scope);
-}
-public String toStringExpression() {
-	return "<CompleteOnName:" + super.toStringExpression() + ">"; //$NON-NLS-2$ //$NON-NLS-1$
-}
+
+	public char[][] possibleKeywords;
+	public boolean canBeExplicitConstructor;
+
+	public CompletionOnSingleNameReference(char[] source, long pos) {
+		this(source, pos, null, false);
+	}
+
+	public CompletionOnSingleNameReference(char[] source, long pos, char[][] possibleKeywords, boolean canBeExplicitConstructor) {
+		super(source, pos);
+		this.possibleKeywords = possibleKeywords;
+		this.canBeExplicitConstructor = canBeExplicitConstructor;
+	}
+
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		
+		output.append("<CompleteOnName:"); //$NON-NLS-1$
+		return super.printExpression(0, output).append('>');
+	}
+
+	public TypeBinding resolveType(BlockScope scope) {
+		throw new CompletionNodeFound(this, scope);
+	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
index 1891e70..a31f191 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
@@ -49,6 +49,9 @@
 		return super.getTypeBinding(scope);
 	}
 }
+public StringBuffer printExpression(int indent, StringBuffer output){
+	return output.append("<CompleteOnType:").append(token).append('>'); //$NON-NLS-1$
+}
 public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
 	if(isCompletionNode) {
 		throw new CompletionNodeFound(this, enclosingType, scope);
@@ -56,11 +59,4 @@
 		return super.resolveTypeEnclosing(scope, enclosingType);
 	}
 }
-public String toStringExpression(int tab){
-
-	return "<CompleteOnType:" + new String(token) + ">" ; //$NON-NLS-2$ //$NON-NLS-1$
-}
-public String toStringExpression(){
-	return this.toStringExpression(0);
-}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
index 7bc1be5..ad455ab 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
@@ -67,7 +67,7 @@
 	/* public fields */
 
 	public int cursorLocation;
-	public AstNode assistNodeParent; // the parent node of assist node
+	public ASTNode assistNodeParent; // the parent node of assist node
 	/* the following fields are internal flags */
 	
 	// block kind
@@ -79,7 +79,6 @@
 	static final int FOR = 6;
 	static final int DO = 7;
 	static final int SYNCHRONIZED = 8;
-	static final int METHOD = 9;
 	
 	// label kind
 	static final int DEFAULT = 1;
@@ -115,8 +114,9 @@
 	static final int YES = 2;
 	
 	
-public CompletionParser(ProblemReporter problemReporter, boolean assertMode) {
-	super(problemReporter, assertMode);
+public CompletionParser(ProblemReporter problemReporter) {
+	super(problemReporter);
+	this.reportSyntaxErrorIsRequired = false;
 }
 public char[] assistIdentifier(){
 	return ((CompletionScanner)scanner).completionIdentifier;
@@ -125,7 +125,7 @@
 	if(assistNode == null) return;
 	
 	if (this.isOrphanCompletionNode) {
-		AstNode orphan = this.assistNode;
+		ASTNode orphan = this.assistNode;
 		this.isOrphanCompletionNode = false;
 		
 		if (currentElement instanceof RecoveredUnit){
@@ -243,7 +243,7 @@
 					call.sourceEnd = expression.sourceEnd;
 					assistNodeParent = call;
 				} else {
-					int invocationType = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER,1);
+					int invocType = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER,1);
 					int qualifierExprPtr = info;
 					
 					// find arguments
@@ -253,7 +253,7 @@
 					if(expressionLengthPtr > 0 && length == 1) {
 						int start = (int) (identifierPositionStack[selector] >>> 32);
 						if(this.expressionStack[expressionPtr-1] != null && this.expressionStack[expressionPtr-1].sourceStart > start) {
-							length += expressionLengthStack[expressionLengthPtr-1];;	
+							length += expressionLengthStack[expressionLengthPtr-1];
 						}
 
 					}
@@ -264,15 +264,15 @@
 						expressionPtr -= length;
 						System.arraycopy(expressionStack, expressionPtr + 1, arguments, 0, length-1);
 						arguments[length-1] = expression;
-					};
+					}
 					
-					if(invocationType != ALLOCATION && invocationType != QUALIFIED_ALLOCATION) {
+					if(invocType != ALLOCATION && invocType != QUALIFIED_ALLOCATION) {
 						MessageSend messageSend = new MessageSend();
 						messageSend.selector = identifierStack[selector];
 						messageSend.arguments = arguments;
 	
 						// find receiver
-						switch (invocationType) {
+						switch (invocType) {
 							case NO_RECEIVER:
 								messageSend.receiver = ThisReference.implicitThis();
 								break;
@@ -300,7 +300,7 @@
 						}
 						assistNodeParent = messageSend;
 					} else {
-						if(invocationType == ALLOCATION) {
+						if(invocType == ALLOCATION) {
 							AllocationExpression allocationExpr = new AllocationExpression();
 							allocationExpr.arguments = arguments;
 							allocationExpr.type = getTypeReference(0);
@@ -399,7 +399,7 @@
 
 					allocationExpression.initializer = arrayInitializer;
 					assistNodeParent = allocationExpression;
-				} else if(currentElement instanceof RecoveredField) {
+				} else if(currentElement instanceof RecoveredField && !(currentElement instanceof RecoveredInitializer)) {
 					RecoveredField recoveredField = (RecoveredField) currentElement;
 					if(recoveredField.fieldDeclaration.type.dimensions() == 0) {
 						Block block = new Block(0);
@@ -490,7 +490,7 @@
 	if(assistNodeParent != null) {
 		currentElement = currentElement.add((Statement)assistNodeParent, 0);
 	} else {
-		if(currentElement instanceof RecoveredField
+		if(currentElement instanceof RecoveredField && !(currentElement instanceof RecoveredInitializer)
 			&& ((RecoveredField) currentElement).fieldDeclaration.initialization == null) {
 			
 			assistNodeParent = ((RecoveredField) currentElement).fieldDeclaration;
@@ -616,7 +616,7 @@
 			this.identifierLengthPtr--; // it can only be a simple identifier (so its length is one)
 			
 			// get the type reference
-			TypeReference typeRef = getTypeReference(this.intPtr--);
+			TypeReference typeRef = getTypeReference(this.intStack[this.intPtr--]);
 			
 			// build the completion on class literal access node
 			CompletionOnClassLiteralAccess access = new CompletionOnClassLiteralAccess(pos, typeRef);
@@ -665,8 +665,8 @@
 			}
 			if((lastModifiers & AccAbstract) == 0
 				&& (lastModifiers & AccFinal) == 0
-				&& CharOperation.prefixEquals(identifierStack[index], Keywords.ABSTARCT)) {
-				keywords[count++] = Keywords.ABSTARCT;
+				&& CharOperation.prefixEquals(identifierStack[index], Keywords.ABSTRACT)) {
+				keywords[count++] = Keywords.ABSTRACT;
 			}
 			if((lastModifiers & AccAbstract) == 0
 				&& (lastModifiers & AccFinal) == 0
@@ -736,7 +736,7 @@
 		}
 
 		// find receiver and qualifier
-		int invocationType = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1);
+		int invocType = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, 1);
 		int qualifierExprPtr = topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER);
 
 		// find arguments
@@ -757,11 +757,11 @@
 		}
 
 		// build ast node
-		if (invocationType != ALLOCATION && invocationType != QUALIFIED_ALLOCATION) {
+		if (invocType != ALLOCATION && invocType != QUALIFIED_ALLOCATION) {
 			// creates completion on message send	
 			CompletionOnMessageSend messageSend = new CompletionOnMessageSend();
 			messageSend.arguments = arguments;
-			switch (invocationType) {
+			switch (invocType) {
 				case NO_RECEIVER:
 					// implicit this
 					messageSend.receiver = ThisReference.implicitThis();
@@ -810,7 +810,7 @@
 				CompletionOnExplicitConstructorCall call = new CompletionOnExplicitConstructorCall(
 					(selectorPtr == THIS_CONSTRUCTOR) ? ExplicitConstructorCall.This : ExplicitConstructorCall.Super);
 				call.arguments = arguments;
-				if (invocationType == QUALIFIED_ALLOCATION) {
+				if (invocType == QUALIFIED_ALLOCATION) {
 					call.qualification = this.expressionStack[qualifierExprPtr];
 				}
 		
@@ -828,7 +828,7 @@
 				CompletionOnQualifiedAllocationExpression allocExpr = new CompletionOnQualifiedAllocationExpression();
 				allocExpr.arguments = arguments;
 				allocExpr.type = super.getTypeReference(0); // we don't want a completion node here, so call super
-				if (invocationType == QUALIFIED_ALLOCATION) {
+				if (invocType == QUALIFIED_ALLOCATION) {
 					allocExpr.enclosingInstance = this.expressionStack[qualifierExprPtr];
 				}
 				// no source is going to be replaced
@@ -967,31 +967,28 @@
 	}
 
 	// check for different scenarii
-	try {
-		// no need to go further if we found a non empty completion node
-		// (we still need to store labels though)
-		if (this.assistNode != null) {
-			// however inside an invocation, the completion identifier may already have been consumed into an empty name 
-			// completion, so this check should be before we check that we are at the cursor location
-			if (!isEmptyNameCompletion() || checkInvocation()) return;
-		}
-
-		// no need to check further if we are not at the cursor location
-		if (this.indexOfAssistIdentifier() < 0) return;
-
-		if (checkClassInstanceCreation()) return;
-		if (checkCatchClause()) return;
-		if (checkMemberAccess()) return;
-		if (checkClassLiteralAccess()) return;
-		if (checkInstanceofKeyword()) return;
-		
-		// if the completion was not on an empty name, it can still be inside an invocation (eg. this.fred("abc"[cursor])
-		// (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack)
-		if (checkInvocation()) return;
-
-		if (checkNameCompletion()) return;
-	} finally {
+	// no need to go further if we found a non empty completion node
+	// (we still need to store labels though)
+	if (this.assistNode != null) {
+		// however inside an invocation, the completion identifier may already have been consumed into an empty name 
+		// completion, so this check should be before we check that we are at the cursor location
+		if (!isEmptyNameCompletion() || checkInvocation()) return;
 	}
+
+	// no need to check further if we are not at the cursor location
+	if (this.indexOfAssistIdentifier() < 0) return;
+
+	if (checkClassInstanceCreation()) return;
+	if (checkCatchClause()) return;
+	if (checkMemberAccess()) return;
+	if (checkClassLiteralAccess()) return;
+	if (checkInstanceofKeyword()) return;
+	
+	// if the completion was not on an empty name, it can still be inside an invocation (eg. this.fred("abc"[cursor])
+	// (NB: Put this check before checkNameCompletion() because the selector of the invocation can be on the identifier stack)
+	if (checkInvocation()) return;
+
+	if (checkNameCompletion()) return;
 }
 protected void consumeArrayCreationExpressionWithInitializer() {
 	super.consumeArrayCreationExpressionWithInitializer();
@@ -1001,6 +998,9 @@
 	super.consumeArrayCreationExpressionWithoutInitializer();
 	popElement(K_ARRAY_CREATION);
 }
+protected void consumeArrayCreationHeader() {
+	// nothing to do
+}
 protected void consumeAssignment() {
 	popElement(K_ASSISGNMENT_OPERATOR);
 	super.consumeAssignment();
@@ -1070,7 +1070,7 @@
 				
 				TypeDeclaration type = recoveredType.typeDeclaration;
 				if(type.superInterfaces == null) {
-					if(type.superclass == null) {;
+					if(type.superclass == null) {
 						keywords[count++] = Keywords.EXTENDS;
 					}
 					keywords[count++] = Keywords.IMPLEMENTS;
@@ -1159,6 +1159,10 @@
 	}
 	pushOnElementStack(K_SWITCH_LABEL, DEFAULT);
 }
+protected void consumeDimWithOrWithOutExpr() {
+	// DimWithOrWithOutExpr ::= '[' ']'
+	pushOnExpressionStack(null);
+}
 protected void consumeEnterAnonymousClassBody() {
 	popElement(K_SELECTOR_QUALIFIER);
 	popElement(K_SELECTOR_INVOCATION_TYPE);
@@ -1270,6 +1274,7 @@
 
 	// potential receiver is being poped, so reset potential receiver
 	this.invocationType = NO_RECEIVER;
+	this.qualifier = -1;
 
 	if (this.indexOfAssistIdentifier() < 0) {
 		super.consumeFieldAccess(isSuperAccess);
@@ -1289,13 +1294,13 @@
 	} else {
 
 		identifierLengthPtr--;
-		char[] name = identifierStack[identifierPtr];
+		char[] identifierName = identifierStack[identifierPtr];
 		long namePositions = identifierPositionStack[identifierPtr--];
 		TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
 		intPtr -= 2;
 		CompletionOnArgumentName arg = 
 			new CompletionOnArgumentName(
-				name, 
+				identifierName, 
 				namePositions, 
 				type, 
 				intStack[intPtr + 1] & ~AccDeprecated); // modifiers
@@ -1406,11 +1411,11 @@
 				((CompletionOnSingleTypeReference)type).isCompletionNode = false;
 				//modifiers
 				int declarationSourceStart = intStack[intPtr--];
-				int modifiers = intStack[intPtr--];
+				int mod = intStack[intPtr--];
 				
 				if(scanner.getLineNumber(type.sourceStart) != scanner.getLineNumber((int) (selectorSource >>> 32))) {
 					FieldDeclaration completionFieldDecl = new CompletionOnFieldType(type, false);
-					completionFieldDecl.modifiers = modifiers;
+					completionFieldDecl.modifiers = mod;
 					assistNode = completionFieldDecl;
 					lastCheckPoint = type.sourceEnd + 1;
 					currentElement = currentElement.add(completionFieldDecl, 0);
@@ -1419,13 +1424,16 @@
 					CompletionOnMethodReturnType md = new CompletionOnMethodReturnType(type, this.compilationUnit.compilationResult);
 					md.selector = selector;
 					md.declarationSourceStart = declarationSourceStart;
-					md.modifiers = modifiers;
+					md.modifiers = mod;
 					md.bodyStart = lParenPos+1;
 					listLength = 0; // initialize listLength before reading parameters/throws
 					assistNode = md;
 					this.lastCheckPoint = md.bodyStart;
 					currentElement = currentElement.add(md, 0);
 					lastIgnoredToken = -1;
+					// javadoc
+					md.javadoc = this.javadoc;
+					this.javadoc = null;
 				}
 			}
 		}
@@ -1436,11 +1444,15 @@
 		//name
 		md.selector = identifierStack[identifierPtr];
 		long selectorSource = identifierPositionStack[identifierPtr--];
+		identifierLengthPtr--;
 		//type
 		md.returnType = getTypeReference(intStack[intPtr--]);
 		//modifiers
 		md.declarationSourceStart = intStack[intPtr--];
 		md.modifiers = intStack[intPtr--];
+		// javadoc
+		md.javadoc = this.javadoc;
+		this.javadoc = null;
 	
 		//highlight starts at selector start
 		md.sourceStart = (int) (selectorSource >>> 32);
@@ -1481,20 +1493,22 @@
 		/* check if current awaiting identifier is the completion identifier */
 		if ((index = this.indexOfAssistIdentifier()) > -1) {
 
-			RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
-			/* filter out cases where scanner is still inside type header */
-			if (!recoveredMethod.foundOpeningBrace) {
-				AbstractMethodDeclaration method = recoveredMethod.methodDeclaration;
-				if(method.thrownExceptions == null
-					&& CharOperation.prefixEquals(identifierStack[index], Keywords.THROWS)) {
-					CompletionOnKeyword1 completionOnKeyword = new CompletionOnKeyword1(
-						identifierStack[index],
-						identifierPositionStack[index],
-						Keywords.THROWS);
-					method.thrownExceptions = new TypeReference[]{completionOnKeyword};
-					recoveredMethod.foundOpeningBrace = true;
-					this.assistNode = completionOnKeyword;
-					this.lastCheckPoint = completionOnKeyword.sourceEnd + 1;
+			if (currentElement instanceof RecoveredMethod){
+				RecoveredMethod recoveredMethod = (RecoveredMethod)currentElement;
+				/* filter out cases where scanner is still inside type header */
+				if (!recoveredMethod.foundOpeningBrace) {
+					AbstractMethodDeclaration method = recoveredMethod.methodDeclaration;
+					if(method.thrownExceptions == null
+						&& CharOperation.prefixEquals(identifierStack[index], Keywords.THROWS)) {
+						CompletionOnKeyword1 completionOnKeyword = new CompletionOnKeyword1(
+							identifierStack[index],
+							identifierPositionStack[index],
+							Keywords.THROWS);
+						method.thrownExceptions = new TypeReference[]{completionOnKeyword};
+						recoveredMethod.foundOpeningBrace = true;
+						this.assistNode = completionOnKeyword;
+						this.lastCheckPoint = completionOnKeyword.sourceEnd + 1;
+					}
 				}
 			}
 		}
@@ -1546,6 +1560,14 @@
 	this.lastModifiersStart = intStack[intPtr];
 	this.lastModifiers = 	intStack[intPtr-1];
 }
+protected void consumeReferenceType() {
+	if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
+		// potential receiver is being poped, so reset potential receiver
+		this.invocationType = NO_RECEIVER;
+		this.qualifier = -1;
+	}
+	super.consumeReferenceType();
+}
 protected void consumeRestoreDiet() {
 	super.consumeRestoreDiet();
 	if (isInsideMethod()) {
@@ -1556,12 +1578,20 @@
 	super.consumeStatementSwitch();
 	if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SWITCH_LABEL) {
 		popElement(K_SWITCH_LABEL);
+		popElement(K_BLOCK_DELIMITER);
 	}
 }
 protected void consumeNestedMethod() {
 	super.consumeNestedMethod();
 	if(!(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BLOCK_DELIMITER)) pushOnElementStack(K_BLOCK_DELIMITER);
 }
+protected void consumePrimaryNoNewArrayName() {
+	// this is class literal access, so reset potential receiver
+	this.invocationType = NO_RECEIVER;
+	this.qualifier = -1;
+	
+	super.consumePrimaryNoNewArrayName();
+}
 protected void consumePushPosition() {
 	super.consumePushPosition();
 	if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_BINARY_OPERATOR) {
@@ -1582,7 +1612,7 @@
 	}
 	
 	int previous = this.previousToken;
-	int previousIdentifierPtr = this.previousIdentifierPtr;
+	int prevIdentifierPtr = this.previousIdentifierPtr;
 	
 	if (isInsideMethod() || isInsideFieldInitialization()) {
 		switch(token) {
@@ -1638,7 +1668,7 @@
 						break;
 					case TokenNameIdentifier: // eg. bar[.]fred()
 						if (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_BETWEEN_NEW_AND_LEFT_BRACKET) {
-							if (this.identifierPtr != previousIdentifierPtr) { // if identifier has been consumed, eg. this.x[.]fred()
+							if (this.identifierPtr != prevIdentifierPtr) { // if identifier has been consumed, eg. this.x[.]fred()
 								this.invocationType = EXPLICIT_RECEIVER;
 							} else {
 								this.invocationType = NAME_RECEIVER;
@@ -1693,6 +1723,7 @@
 							this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, this.invocationType);
 							this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier);
 						}
+						this.qualifier = -1;
 						this.invocationType = NO_RECEIVER;
 						break;
 					case TokenNamethis: // explicit constructor invocation, eg. this[(]1, 2)
@@ -1700,6 +1731,7 @@
 							this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION);
 							this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier);
 						}
+						this.qualifier = -1;
 						this.invocationType = NO_RECEIVER;
 						break;
 					case TokenNamesuper: // explicit constructor invocation, eg. super[(]1, 2)
@@ -1707,6 +1739,7 @@
 							this.pushOnElementStack(K_SELECTOR_INVOCATION_TYPE, (this.invocationType == QUALIFIED_ALLOCATION) ? QUALIFIED_ALLOCATION : ALLOCATION);
 							this.pushOnElementStack(K_SELECTOR_QUALIFIER, this.qualifier);
 						}
+						this.qualifier = -1;
 						this.invocationType = NO_RECEIVER;
 						break;
 				}
@@ -1760,6 +1793,11 @@
 			case TokenNameLBRACKET:
 				if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) != K_ARRAY_CREATION) {
 					pushOnElementStack(K_BETWEEN_LEFT_AND_RIGHT_BRACKET);
+				} else {
+					if(previous == TokenNameIdentifier) {
+						invocationType = NO_RECEIVER;
+						qualifier = -1;
+					}
 				}
 				this.bracketDepth++;
 				break; 
@@ -1964,47 +2002,47 @@
 	}
 }
 
-public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
-	return new CompletionOnImportReference(tokens, positions);
+public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){
+	return new CompletionOnImportReference(tokens, positions, mod);
 }
 public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
 	return new CompletionOnPackageReference(tokens, positions);
 }
-public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
+public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
 	return new CompletionOnQualifiedNameReference(
 					previousIdentifiers, 
-					name, 
+					assistName, 
 					positions); 	
 }
-public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
+public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
 	switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
 		case K_NEXT_TYPEREF_IS_EXCEPTION :
-			return new CompletionOnQualifiedExceptionReference(previousIdentifiers, name, positions);
+			return new CompletionOnQualifiedExceptionReference(previousIdentifiers, assistName, positions);
 		case K_NEXT_TYPEREF_IS_CLASS :
-			return new CompletionOnQualifiedClassReference(previousIdentifiers, name, positions);
+			return new CompletionOnQualifiedClassReference(previousIdentifiers, assistName, positions);
 		case K_NEXT_TYPEREF_IS_INTERFACE :
-			return new CompletionOnQualifiedInterfaceReference(previousIdentifiers, name, positions);
+			return new CompletionOnQualifiedInterfaceReference(previousIdentifiers, assistName, positions);
 		default :
-			return new CompletionOnQualifiedTypeReference(previousIdentifiers, name, positions); 
+			return new CompletionOnQualifiedTypeReference(previousIdentifiers, assistName, positions); 
 	}
 }
-public NameReference createSingleAssistNameReference(char[] name, long position) {
+public NameReference createSingleAssistNameReference(char[] assistName, long position) {
 	int kind = topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
 	if(!isInsideMethod()) {
-		return new CompletionOnSingleNameReference(name, position);
+		return new CompletionOnSingleNameReference(assistName, position);
 	} else {
 		boolean canBeExplicitConstructorCall = false;
 		if(kind == K_BLOCK_DELIMITER
 			&& previousKind == K_BLOCK_DELIMITER
 			&& previousInfo == DO) {
-			return new CompletionOnKeyword3(name, position, Keywords.WHILE);
+			return new CompletionOnKeyword3(assistName, position, Keywords.WHILE);
 		} else if(kind == K_BLOCK_DELIMITER
 			&& previousKind == K_BLOCK_DELIMITER
 			&& previousInfo == TRY) {
-			return new CompletionOnKeyword3(name, position, new char[][]{Keywords.CATCH, Keywords.FINALLY});
+			return new CompletionOnKeyword3(assistName, position, new char[][]{Keywords.CATCH, Keywords.FINALLY});
 		} else if(kind == K_BLOCK_DELIMITER
 			&& topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == SWITCH) {
-			return new CompletionOnKeyword3(name, position, new char[][]{Keywords.CASE, Keywords.DEFAULT});
+			return new CompletionOnKeyword3(assistName, position, new char[][]{Keywords.CASE, Keywords.DEFAULT});
 		} else {
 			char[][] keywords = new char[Keywords.COUNT][];
 			int count = 0;
@@ -2066,28 +2104,28 @@
 			}
 			System.arraycopy(keywords, 0 , keywords = new char[count][], 0, count);
 			
-			return new CompletionOnSingleNameReference(name, position, keywords, canBeExplicitConstructorCall);
+			return new CompletionOnSingleNameReference(assistName, position, keywords, canBeExplicitConstructorCall);
 		}
 	}
 }
-public TypeReference createSingleAssistTypeReference(char[] name, long position) {
+public TypeReference createSingleAssistTypeReference(char[] assistName, long position) {
 	switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
 		case K_NEXT_TYPEREF_IS_EXCEPTION :
-			return new CompletionOnExceptionReference(name, position) ;
+			return new CompletionOnExceptionReference(assistName, position) ;
 		case K_NEXT_TYPEREF_IS_CLASS :
-			return new CompletionOnClassReference(name, position);
+			return new CompletionOnClassReference(assistName, position);
 		case K_NEXT_TYPEREF_IS_INTERFACE :
-			return new CompletionOnInterfaceReference(name, position);
+			return new CompletionOnInterfaceReference(assistName, position);
 		default :
-			return new CompletionOnSingleTypeReference(name, position); 
+			return new CompletionOnSingleTypeReference(assistName, position); 
 	}
 }
-public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLoc) {
 
-	this.cursorLocation = cursorLocation;
+	this.cursorLocation = cursorLoc;
 	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
 	completionScanner.completionIdentifier = null;
-	completionScanner.cursorLocation = cursorLocation;
+	completionScanner.cursorLocation = cursorLoc;
 	return this.dietParse(sourceUnit, compilationResult);
 }
 /*
@@ -2106,6 +2144,7 @@
 	if (this.identifierLengthStack[this.identifierLengthPtr] > 1) { // reducing a qualified name
 		// potential receiver is being poped, so reset potential receiver
 		this.invocationType = NO_RECEIVER;
+		this.qualifier = -1;
 	}
 	return super.getUnspecifiedReferenceOptimized();
 }
@@ -2128,7 +2167,7 @@
 	}
 }
 public void initializeScanner(){
-	this.scanner = new CompletionScanner(this.assertMode);
+	this.scanner = new CompletionScanner(this.options.sourceLevel);
 }
 /**
  * Returns whether the completion is just after an array type
@@ -2225,12 +2264,12 @@
 	}
 	return false;
 }
-public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLocation) {
+public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLoc) {
 
-	this.cursorLocation = cursorLocation;
+	this.cursorLocation = cursorLoc;
 	CompletionScanner completionScanner = (CompletionScanner)this.scanner;
 	completionScanner.completionIdentifier = null;
-	completionScanner.cursorLocation = cursorLocation;
+	completionScanner.cursorLocation = cursorLoc;
 	return this.parse(sourceUnit, compilationResult);
 }
 public void parseBlockStatements(
@@ -2329,14 +2368,6 @@
 			break;
 	}
 }
-protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
-
-	/* Intercept error state on EOF inside method bodies, due to 
-	   cursor location being used as an EOF position.
-	*/
-	if (!diet && currentToken == TokenNameEOF) return;
-	super.reportSyntaxError(act, currentKind, stateStackTop);
-}
 /*
  * Reset internal state after completion is over
  */
@@ -2367,7 +2398,8 @@
 			the end of the method body or compilation unit */
 		if ((scanner.eofPosition == cursorLocation+1)
 			&& (!(referenceContext instanceof CompilationUnitDeclaration) 
-				|| isIndirectlyInsideFieldInitialization())) {
+			|| isIndirectlyInsideFieldInitialization()
+			|| assistNodeParent instanceof FieldDeclaration && !(assistNodeParent instanceof Initializer))) {
 
 			/*	disabled since does not handle possible field/message refs, that is, Obj[ASSIST HERE]ect.registerNatives()		    
 			// consume extra tokens which were part of the qualified reference
@@ -2417,12 +2449,12 @@
 	s = s + "elementKindStack : int[] = {"; //$NON-NLS-1$
 	for (int i = 0; i <= elementPtr; i++) {
 		s = s + String.valueOf(elementKindStack[i]) + ","; //$NON-NLS-1$ //$NON-NLS-2$
-	};
+	}
 	s = s + "}\n"; //$NON-NLS-1$
 	s = s + "elementInfoStack : int[] = {"; //$NON-NLS-1$
 	for (int i = 0; i <= elementPtr; i++) {
 		s = s + String.valueOf(elementInfoStack[i]) + ","; //$NON-NLS-1$ //$NON-NLS-2$
-	};
+	}
 	s = s + "}\n"; //$NON-NLS-1$
 	return s + super.toString();
 }
@@ -2454,22 +2486,22 @@
 	this.recoveryExitFromVariable();
 }
 
-protected LocalDeclaration createLocalDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
+protected LocalDeclaration createLocalDeclaration(char[] assistName, int sourceStart, int sourceEnd) {
 	if (this.indexOfAssistIdentifier() < 0) {
-		return super.createLocalDeclaration(initialization, name, sourceStart, sourceEnd);
+		return super.createLocalDeclaration(assistName, sourceStart, sourceEnd);
 	} else {
-		CompletionOnLocalName local = new CompletionOnLocalName(initialization, name, sourceStart, sourceEnd);
+		CompletionOnLocalName local = new CompletionOnLocalName(assistName, sourceStart, sourceEnd);
 		this.assistNode = local;
 		this.lastCheckPoint = sourceEnd + 1;
 		return local;
 	}
 }
 
-protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
+protected FieldDeclaration createFieldDeclaration(char[] assistName, int sourceStart, int sourceEnd) {
 	if (this.indexOfAssistIdentifier() < 0 || (currentElement instanceof RecoveredUnit && ((RecoveredUnit)currentElement).typeCount == 0)) {
-		return super.createFieldDeclaration(initialization, name, sourceStart, sourceEnd);
+		return super.createFieldDeclaration(assistName, sourceStart, sourceEnd);
 	} else {
-		CompletionOnFieldName field = new CompletionOnFieldName(initialization, name, sourceStart, sourceEnd);
+		CompletionOnFieldName field = new CompletionOnFieldName(assistName, sourceStart, sourceEnd);
 		this.assistNode = field;
 		this.lastCheckPoint = sourceEnd + 1;
 		return field;
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
index 71991c8..cc86980 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
@@ -38,12 +38,12 @@
 	public int completedIdentifierEnd = -1;
 
 	public static final char[] EmptyCompletionIdentifier = {};
-public CompletionScanner(boolean assertMode) {
+public CompletionScanner(long sourceLevel) {
 	super(
 		false /*comment*/, 
 		false /*whitespace*/, 
 		false /*nls*/, 
-		assertMode /*assert*/, 
+		sourceLevel, 
 		null /*taskTags*/, 
 		null/*taskPriorities*/);
 }
@@ -208,7 +208,7 @@
 					// compute end of empty identifier.
 					// if the empty identifier is at the start of a next token the end of
 					// empty identifier is the end of the next token (eg. "<empty token>next").
-				 	while(getNextCharAsJavaIdentifierPart()) {}
+				 	while(getNextCharAsJavaIdentifierPart());
 				 	endOfEmptyToken = currentPosition - 1;
 					currentPosition = startPosition; // for being detected as empty free identifier
 					return TokenNameIdentifier;
@@ -565,7 +565,7 @@
 							}
 							break;
 						}
-						if (test > 0) { //traditional and annotation comment
+						if (test > 0) { //traditional and javadoc comment
 							boolean isJavadoc = false, star = false;
 							// consume next character
 							unicodeAsBackSlash = false;
@@ -684,6 +684,7 @@
 		}
 	} //-----------------end switch while try--------------------
 	catch (IndexOutOfBoundsException e) {
+		// eof reached
 	}
 	/* might be completing at very end of file (e.g. behind a dot) */
 	if (completionIdentifier == null && 
@@ -697,7 +698,7 @@
  * In case we actually read a keyword, but the cursor is located inside,
  * we pretend we read an identifier.
  */
-public int scanIdentifierOrKeyword() throws InvalidInputException {
+public int scanIdentifierOrKeyword() {
 
 	int id = super.scanIdentifierOrKeyword();
 
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
index 83615b0..bf0e0c8 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
@@ -10,7 +10,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.codeassist.impl;
 
-import java.util.Iterator;
 import java.util.Map;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
@@ -57,6 +56,7 @@
 	 * Initializing the assist options with default settings
 	 */
 	public AssistOptions() {
+		// Initializing the assist options with default settings
 	}
 
 	/** 
@@ -66,89 +66,103 @@
 		if (settings == null)
 			return;
 
-		// filter options which are related to the assist component
-		Iterator entries = settings.entrySet().iterator();
-		while (entries.hasNext()) {
-			Map.Entry entry = (Map.Entry)entries.next();
-			if (!(entry.getKey() instanceof String))
-				continue;
-			if (!(entry.getValue() instanceof String))
-				continue;
-			String optionID = (String) entry.getKey();
-			String optionValue = (String) entry.getValue();
+		set(settings);
+	}
+	public void set(Map optionsMap) {
 
-			if (optionID.equals(OPTION_PerformVisibilityCheck)) {
-				if (optionValue.equals(ENABLED)) {
-					this.checkVisibility = true;
-				} else
-					if (optionValue.equals(DISABLED)) {
-						this.checkVisibility = false;
-					}
-				continue;
-			} else if (optionID.equals(OPTION_ForceImplicitQualification)) {
-				if (optionValue.equals(ENABLED)) {
-					this.forceImplicitQualification = true;
-				} else
-					if (optionValue.equals(DISABLED)) {
-						this.forceImplicitQualification = false;
-					}
-				continue;
-			} else if(optionID.equals(OPTION_FieldPrefixes)){
-				if (optionValue.length() == 0) {
+		Object optionValue;
+		if ((optionValue = optionsMap.get(OPTION_PerformVisibilityCheck)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.checkVisibility = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.checkVisibility = false;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ForceImplicitQualification)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.forceImplicitQualification = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.forceImplicitQualification = false;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_FieldPrefixes)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() > 0){
+					this.fieldPrefixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				} else {
 					this.fieldPrefixes = null;
-				} else {
-					this.fieldPrefixes = CharOperation.splitAndTrimOn(',', optionValue.toCharArray());
 				}
-				continue;
-			} else if(optionID.equals(OPTION_StaticFieldPrefixes)){
-				if (optionValue.length() == 0) {
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_StaticFieldPrefixes)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() > 0){
+					this.staticFieldPrefixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				} else {
 					this.staticFieldPrefixes = null;
-				} else {
-					this.staticFieldPrefixes = CharOperation.splitAndTrimOn(',', optionValue.toCharArray());
 				}
-				continue;
-			} else if(optionID.equals(OPTION_LocalPrefixes)){
-				if (optionValue.length() == 0) {
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_LocalPrefixes)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() > 0){
+					this.localPrefixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				} else {
 					this.localPrefixes = null;
-				} else {
-					this.localPrefixes = CharOperation.splitAndTrimOn(',', optionValue.toCharArray());
 				}
-				continue;
-			} else if(optionID.equals(OPTION_ArgumentPrefixes)){
-				if (optionValue.length() == 0) {
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ArgumentPrefixes)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() > 0){
+					this.argumentPrefixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				} else {
 					this.argumentPrefixes = null;
-				} else {
-					this.argumentPrefixes = CharOperation.splitAndTrimOn(',', optionValue.toCharArray());
 				}
-				continue;
-			} else if(optionID.equals(OPTION_FieldSuffixes)){
-				if (optionValue.length() == 0) {
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_FieldSuffixes)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() > 0){
+					this.fieldSuffixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				} else {
 					this.fieldSuffixes = null;
-				} else {
-					this.fieldSuffixes = CharOperation.splitAndTrimOn(',', optionValue.toCharArray());
 				}
-				continue;
-			} else if(optionID.equals(OPTION_StaticFieldSuffixes)){
-				if (optionValue.length() == 0) {
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_StaticFieldSuffixes)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() > 0){
+					this.staticFieldSuffixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				} else {
 					this.staticFieldSuffixes = null;
-				} else {
-					this.staticFieldSuffixes = CharOperation.splitAndTrimOn(',', optionValue.toCharArray());
 				}
-				continue;
-			} else if(optionID.equals(OPTION_LocalSuffixes)){
-				if (optionValue.length() == 0) {
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_LocalSuffixes)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() > 0){
+					this.localSuffixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				} else {
 					this.localSuffixes = null;
-				} else {
-					this.localSuffixes = CharOperation.splitAndTrimOn(',', optionValue.toCharArray());
 				}
-				continue;
-			} else if(optionID.equals(OPTION_ArgumentSuffixes)){
-				if (optionValue.length() == 0) {
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ArgumentSuffixes)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() > 0){
+					this.argumentSuffixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				} else {
 					this.argumentSuffixes = null;
-				} else {
-					this.argumentSuffixes = CharOperation.splitAndTrimOn(',', optionValue.toCharArray());
 				}
-				continue;
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
index 99a1287..3bdc3af 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
@@ -15,8 +15,9 @@
  *
  */
 
+import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Block;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
@@ -41,7 +42,7 @@
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 
 public abstract class AssistParser extends Parser {
-	public AstNode assistNode;
+	public ASTNode assistNode;
 	public boolean isOrphanCompletionNode;
 		
 	/* recovery */
@@ -76,12 +77,13 @@
 	
 	protected boolean isFirst = false;
 
-public AssistParser(ProblemReporter problemReporter, boolean assertMode) {
-	super(problemReporter, true, assertMode);
+public AssistParser(ProblemReporter problemReporter) {
+	super(problemReporter, true);
+	this.javadocParser.checkJavadoc = false;
 }
 public abstract char[] assistIdentifier();
 public int bodyEnd(AbstractMethodDeclaration method){
-	return method.declarationSourceEnd;
+	return method.bodyEnd;
 }
 public int bodyEnd(Initializer initializer){
 	return initializer.declarationSourceEnd;
@@ -117,7 +119,7 @@
 						&& field.declarationSourceStart <= scanner.initialPosition
 						&& scanner.initialPosition <= field.declarationSourceEnd
 						&& scanner.eofPosition <= field.declarationSourceEnd+1){
-					element = new RecoveredInitializer((Initializer) field, null, 1, this);
+					element = new RecoveredInitializer(field, null, 1, this);
 					lastCheckPoint = field.declarationSourceStart;					
 					break;
 				}
@@ -135,7 +137,7 @@
 	int blockIndex = 1;	// ignore first block start, since manually rebuilt here
 
 	for(int i = 0; i <= astPtr; i++){
-		AstNode node = astStack[i];
+		ASTNode node = astStack[i];
 
 		/* check for intermediate block creation, so recovery can properly close them afterwards */
 		int nodeStart = node.sourceStart;
@@ -181,7 +183,7 @@
 			Initializer initializer = (Initializer) node;
 			if (initializer.declarationSourceEnd == 0){
 				element = element.add(initializer, 1);
-				lastCheckPoint = initializer.bodyStart;				
+				lastCheckPoint = initializer.sourceStart;				
 			} else {
 				element = element.add(initializer, 0);
 				lastCheckPoint = initializer.declarationSourceEnd + 1;
@@ -367,8 +369,8 @@
 	}
 	//endPosition is just before the ;
 	reference.declarationSourceStart = intStack[intPtr--];
-	// flush annotations defined prior to import statements
-	reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
+	// flush comments defined prior to import statements
+	reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
 
 	// recovery
 	if (currentElement != null){
@@ -411,7 +413,7 @@
 		length); 
 
 	/* build specific assist node on import statement */
-	ImportReference reference = this.createAssistImportReference(subset, positions);
+	ImportReference reference = this.createAssistImportReference(subset, positions, AccDefault);
 	assistNode = reference;
 	this.lastCheckPoint = reference.sourceEnd + 1;
 
@@ -424,8 +426,8 @@
 	}
 	//endPosition is just before the ;
 	reference.declarationSourceStart = intStack[intPtr--];
-	// flush annotations defined prior to import statements
-	reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
+	// flush comments defined prior to import statements
+	reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
 
 	// recovery
 	if (currentElement != null){
@@ -509,7 +511,7 @@
 		length); 
 
 	/* build specific assist node on import statement */
-	ImportReference reference = this.createAssistImportReference(subset, positions);
+	ImportReference reference = this.createAssistImportReference(subset, positions, AccDefault);
 	reference.onDemand = true;
 	assistNode = reference;
 	this.lastCheckPoint = reference.sourceEnd + 1;
@@ -523,8 +525,8 @@
 	}
 	//endPosition is just before the ;
 	reference.declarationSourceStart = intStack[intPtr--];
-	// flush annotations defined prior to import statements
-	reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
+	// flush comments defined prior to import statements
+	reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
 
 	// recovery
 	if (currentElement != null){
@@ -534,12 +536,12 @@
 		restartRecovery = true; // used to avoid branching back into the regular automaton		
 	}
 }
-public abstract ImportReference createAssistImportReference(char[][] tokens, long[] positions);
+public abstract ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod);
 public abstract ImportReference createAssistPackageReference(char[][] tokens, long[] positions);
-public abstract NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions);
-public abstract TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions);
-public abstract NameReference createSingleAssistNameReference(char[] name, long position);
-public abstract TypeReference createSingleAssistTypeReference(char[] name, long position);
+public abstract NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
+public abstract TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions);
+public abstract NameReference createSingleAssistNameReference(char[] assistName, long position);
+public abstract TypeReference createSingleAssistTypeReference(char[] assistName, long position);
 /*
  * Flush parser/scanner state regarding to code assist
  */
@@ -634,8 +636,8 @@
 	} else {
 		/* completion inside subsequent identifier */
 		reference = this.createQualifiedAssistNameReference(subset, assistIdentifier(), positions);
-	};
-	reference.bits &= ~AstNode.RestrictiveFlagMASK;
+	}
+	reference.bits &= ~ASTNode.RestrictiveFlagMASK;
 	reference.bits |= LOCAL | FIELD;
 	
 	assistNode = reference;
@@ -643,19 +645,7 @@
 	return reference;
 }
 public void goForBlockStatementsopt() {
-	//tells the scanner to go for block statements opt parsing
-
-	firstToken = TokenNameTWIDDLE;
-	scanner.recordLineSeparator = false;
-	
-	isFirst = true;
-}
-public void goForConstructorBlockStatementsopt() {
-	//tells the scanner to go for constructor block statements opt parsing
-
-	firstToken = TokenNameNOT;
-	scanner.recordLineSeparator = false;
-	
+	super.goForBlockStatementsopt();
 	isFirst = true;
 }
 public void goForHeaders(){
@@ -666,8 +656,8 @@
 	super.goForCompilationUnit();
 	isFirst = true;
 }
-public void goForBlockStatementsOrMethodHeaders() {
-	super.goForBlockStatementsOrMethodHeaders();
+public void goForBlockStatementsOrCatchHeader() {
+	super.goForBlockStatementsOrCatchHeader();
 	isFirst = true;
 }
 /*
@@ -819,7 +809,7 @@
 	initialize();
 	
 	// simulate goForConstructorBody except that we don't want to balance brackets because they are not going to be balanced
-	goForConstructorBlockStatementsopt();
+	goForBlockStatementsopt();
 
 	referenceContext = cd;
 	compilationUnit = unit;
@@ -831,13 +821,53 @@
 	} catch (AbortCompilation ex) {
 		lastAct = ERROR_ACTION;
 	}
+	
+	if (lastAct == ERROR_ACTION) {
+		return;
+	}
+
+	// attach the statements as we might be searching for a reference to a local type
+	cd.explicitDeclarations = realBlockStack[realBlockPtr--];
+	int length;
+	if ((length = astLengthStack[astLengthPtr--]) != 0) {
+		astPtr -= length;
+		if (astStack[astPtr + 1] instanceof ExplicitConstructorCall)
+			//avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
+			{
+			System.arraycopy(
+				astStack, 
+				astPtr + 2, 
+				cd.statements = new Statement[length - 1], 
+				0, 
+				length - 1); 
+			cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
+		} else { //need to add explicitly the super();
+			System.arraycopy(
+				astStack, 
+				astPtr + 1, 
+				cd.statements = new Statement[length], 
+				0, 
+				length); 
+			cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+		}
+	} else {
+		cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+		if (!containsComment(cd.bodyStart, cd.bodyEnd)) {
+			cd.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+		}		
+	}
+
+	if (cd.constructorCall.sourceEnd == 0) {
+		cd.constructorCall.sourceEnd = cd.sourceEnd;
+		cd.constructorCall.sourceStart = cd.sourceStart;
+	}
 }
 /**
  * Parse the block statements inside the given initializer and try to complete at the
  * cursor location.
  */
 public void parseBlockStatements(
-	Initializer ini,
+	Initializer initializer,
 	TypeDeclaration type, 
 	CompilationUnitDeclaration unit) {
 
@@ -849,7 +879,7 @@
 	referenceContext = type;
 	compilationUnit = unit;
 
-	scanner.resetTo(ini.sourceStart, bodyEnd(ini)); // just after the beginning {
+	scanner.resetTo(initializer.sourceStart, bodyEnd(initializer)); // just after the beginning {
 	consumeNestedMethod();
 	try {
 		parse();
@@ -858,6 +888,27 @@
 	} finally {
 		nestedMethod[nestedType]--;
 	}
+	
+	if (lastAct == ERROR_ACTION) {
+		return;
+	}
+
+	// attach the statements as we might be searching for a reference to a local type
+	initializer.block.explicitDeclarations = realBlockStack[realBlockPtr--];
+	int length;
+	if ((length = astLengthStack[astLengthPtr--]) > 0) {
+		System.arraycopy(astStack, (astPtr -= length) + 1, initializer.block.statements = new Statement[length], 0, length); 
+	} else {
+		// check whether this block at least contains some comment in it
+		if (!containsComment(initializer.block.sourceStart, initializer.block.sourceEnd)) {
+			initializer.block.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+		}
+	}
+	
+	// mark initializer with local type if one was found during parsing
+	if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
+		initializer.bits |= ASTNode.HasLocalTypeMASK;
+	}	
 }
 /**
  * Parse the block statements inside the given method declaration and try to complete at the
@@ -893,6 +944,27 @@
 	} finally {
 		nestedMethod[nestedType]--;		
 	}
+	
+	if (lastAct == ERROR_ACTION) {
+		return;
+	}
+
+	// attach the statements as we might be searching for a reference to a local type
+	md.explicitDeclarations = realBlockStack[realBlockPtr--];
+	int length;
+	if ((length = astLengthStack[astLengthPtr--]) != 0) {
+		System.arraycopy(
+			astStack, 
+			(astPtr -= length) + 1, 
+			md.statements = new Statement[length], 
+			0, 
+			length); 
+	} else {
+		if (!containsComment(md.bodyStart, md.bodyEnd)) {
+			md.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+		}
+	}
+
 }
 protected void popElement(int kind){
 	if(elementPtr < 0 || elementKindStack[elementPtr] != kind) return;
@@ -1058,7 +1130,7 @@
 			this.assistNode == null
 			){ 
 			this.prepareForBlockStatements();
-			goForBlockStatementsOrMethodHeaders();
+			goForBlockStatementsOrCatchHeader();
 		} else {
 			this.prepareForHeaders();
 			goForHeaders();
@@ -1074,7 +1146,7 @@
 			goForHeaders();
 		} else {
 			this.prepareForBlockStatements();
-			goForBlockStatementsOrMethodHeaders();
+			goForBlockStatementsOrCatchHeader();
 		}
 		return true;
 	}
@@ -1115,7 +1187,7 @@
  * then wrap it with a fake constructor call.
  * Returns the wrapped completion node or the completion node itself.
  */
-protected AstNode wrapWithExplicitConstructorCallIfNeeded(AstNode ast) {
+protected ASTNode wrapWithExplicitConstructorCallIfNeeded(ASTNode ast) {
 	int selector;
 	if (ast != null && topKnownElementKind(ASSIST_PARSER) == K_SELECTOR && ast instanceof Expression &&
 			(((selector = topKnownElementInfo(ASSIST_PARSER)) == THIS_CONSTRUCTOR) ||
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
index c33a748..dc6eb6a 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Engine.java
@@ -66,9 +66,9 @@
 		CompilationUnitDeclaration unit =
 			SourceTypeConverter.buildCompilationUnit(
 				sourceTypes,//sourceTypes[0] is always toplevel here
-				true, // need field and methods
-				true, // need member types
-				false, // no need for field initialization
+				SourceTypeConverter.FIELD_AND_METHOD // need field and methods
+				| SourceTypeConverter.MEMBER_TYPE, // need member types
+				// no need for field initialization
 				lookupEnvironment.problemReporter,
 				result);
 
@@ -126,7 +126,12 @@
 		return true;
 	}
 
-	protected void parseMethod(CompilationUnitDeclaration unit, int position) {
+	/*
+	 * Find the node (a field, a method or an initializer) at the given position 
+	 * and parse its block statements if it is a method or an initializer.
+	 * Returns the node or null if not found
+	 */
+	protected ASTNode parseBlockStatements(CompilationUnitDeclaration unit, int position) {
 		int length = unit.types.length;
 		for (int i = 0; i < length; i++) {
 			TypeDeclaration type = unit.types[i];
@@ -134,13 +139,13 @@
 				&& type.declarationSourceEnd >= position) {
 				getParser().scanner.setSource(
 					unit.compilationResult.compilationUnit.getContents());
-				parseMethod(type, unit, position);
-				return;
+				return parseBlockStatements(type, unit, position);
 			}
 		}
+		return null;
 	}
 
-	private void parseMethod(
+	private ASTNode parseBlockStatements(
 		TypeDeclaration type,
 		CompilationUnitDeclaration unit,
 		int position) {
@@ -153,8 +158,7 @@
 				if (memberType.bodyStart > position)
 					continue;
 				if (memberType.declarationSourceEnd >= position) {
-					parseMethod(memberType, unit, position);
-					return;
+					return parseBlockStatements(memberType, unit, position);
 				}
 			}
 		}
@@ -168,7 +172,7 @@
 					continue;
 				if (method.declarationSourceEnd >= position) {
 					getParser().parseBlockStatements(method, unit);
-					return;
+					return method;
 				}
 			}
 		}
@@ -177,17 +181,18 @@
 		if (fields != null) {
 			int length = fields.length;
 			for (int i = 0; i < length; i++) {
-				if (!(fields[i] instanceof Initializer))
+				FieldDeclaration field = fields[i];
+				if (field.sourceStart > position)
 					continue;
-				Initializer initializer = (Initializer) fields[i];
-				if (initializer.bodyStart > position)
-					continue;
-				if (initializer.declarationSourceEnd >= position) {
-					getParser().parseBlockStatements(initializer, type, unit);
-					return;
+				if (field.declarationSourceEnd >= position) {
+					if (field instanceof Initializer) {
+						getParser().parseBlockStatements((Initializer)field, type, unit);
+					}
+					return field;
 				}
 			}
 		}
+		return null;
 	}
 
 	protected void reset() {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java
index 97a94be..be79f4a 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/Keywords.java
@@ -13,7 +13,7 @@
 public interface Keywords {
 	int COUNT = 41;
 	
-	char[] ABSTARCT = "abstract".toCharArray(); //$NON-NLS-1$
+	char[] ABSTRACT = "abstract".toCharArray(); //$NON-NLS-1$
 	char[] ASSERT = "assert".toCharArray(); //$NON-NLS-1$
 	char[] BREAK = "break".toCharArray(); //$NON-NLS-1$
 	char[] CASE = "case".toCharArray(); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnArgumentName.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnArgumentName.java
index 3f75e96..d6071d7 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnArgumentName.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnArgumentName.java
@@ -17,28 +17,34 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 
 public class SelectionOnArgumentName extends Argument {
+	
 	public SelectionOnArgumentName(char[] name , long posNom , TypeReference tr , int modifiers){
+
 		super(name, posNom, tr, modifiers);
 	}
 	
+	public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
+
+		super.bind(scope, typeBinding, used);
+		throw new SelectionNodeFound(binding);
+	}
+	
+	public StringBuffer print(int indent, StringBuffer output) {
+		
+		printIndent(indent, output);
+		output.append("<SelectionOnArgumentName:"); //$NON-NLS-1$
+		if (type != null) type.print(0, output).append(' ');
+		output.append(name);
+		if (initialization != null) {
+			output.append(" = ");//$NON-NLS-1$
+			initialization.printExpression(0, output); 
+		}
+		return output.append('>');
+	}
+
 	public void resolve(BlockScope scope) {
+		
 		super.resolve(scope);
 		throw new SelectionNodeFound(binding);
 	}
-	
-	public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
-		super.bind(scope, typeBinding, used);
-		
-		throw new SelectionNodeFound(binding);
-	}
-	
-	public String toString(int tab) {
-		String s = tabString(tab);
-		s += "<SelectionOnArgumentName:"; //$NON-NLS-1$
-		if (type != null) s += type.toString() + " "; //$NON-NLS-1$
-		s += new String(name());
-		if (initialization != null) s += " = " + initialization.toStringExpression(); //$NON-NLS-1$
-		s += ">"; //$NON-NLS-1$
-		return s;
-	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnExplicitConstructorCall.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnExplicitConstructorCall.java
index ffe252f..f71f3fe 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnExplicitConstructorCall.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnExplicitConstructorCall.java
@@ -33,39 +33,41 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class SelectionOnExplicitConstructorCall extends ExplicitConstructorCall {
-public SelectionOnExplicitConstructorCall(int accessMode) {
-	super(accessMode);
-}
-public void resolve(BlockScope scope) {
-	super.resolve(scope);
 
-	// tolerate some error cases
-	if (binding == null || 
-			!(binding.isValidBinding() ||
-				binding.problemId() == ProblemReasons.NotVisible))
-		throw new SelectionNodeFound();
-	else
-		throw new SelectionNodeFound(binding);
-}
-public String toString(int tab) {
-	String s = tabString(tab);
-	s += "<SelectOnExplicitConstructorCall:"; //$NON-NLS-1$
-	if (qualification != null)
-		s = s + qualification.toStringExpression() + "."; //$NON-NLS-1$
-	if (accessMode == This) {
-		s = s + "this("; //$NON-NLS-1$
-	} else {
-		s = s + "super("; //$NON-NLS-1$
+	public SelectionOnExplicitConstructorCall(int accessMode) {
+
+		super(accessMode);
 	}
-	if (arguments != null) {
-		for (int i = 0; i < arguments.length; i++) {
-			s += arguments[i].toStringExpression();
-			if (i != arguments.length - 1) {
-				s += ", "; //$NON-NLS-1$
+
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+
+		printIndent(tab, output);
+		output.append("<SelectOnExplicitConstructorCall:"); //$NON-NLS-1$
+		if (qualification != null) qualification.printExpression(0, output).append('.');
+		if (accessMode == This) {
+			output.append("this("); //$NON-NLS-1$
+		} else {
+			output.append("super("); //$NON-NLS-1$
+		}
+		if (arguments != null) {
+			for (int i = 0; i < arguments.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				arguments[i].printExpression(0, output);
 			}
-		};
+		}
+		return output.append(")>;"); //$NON-NLS-1$
 	}
-	s += ")>"; //$NON-NLS-1$
-	return s;
-}
+
+	public void resolve(BlockScope scope) {
+
+		super.resolve(scope);
+	
+		// tolerate some error cases
+		if (binding == null || 
+				!(binding.isValidBinding() ||
+					binding.problemId() == ProblemReasons.NotVisible))
+			throw new SelectionNodeFound();
+		else
+			throw new SelectionNodeFound(binding);
+	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnFieldReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnFieldReference.java
index aecc5fd..c7d934f 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnFieldReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnFieldReference.java
@@ -35,12 +35,21 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 
 public class SelectionOnFieldReference extends FieldReference {
-public SelectionOnFieldReference(char[] source , long pos) {
-	super(source, pos);
-}
-public TypeBinding resolveType(BlockScope scope) {
-	super.resolveType(scope);
+	
+	public SelectionOnFieldReference(char[] source , long pos) {
 
+		super(source, pos);
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output){
+		
+		output.append("<SelectionOnFieldReference:");  //$NON-NLS-1$
+		return super.printExpression(0, output).append('>');
+	}
+	
+	public TypeBinding resolveType(BlockScope scope) {
+
+		super.resolveType(scope);
 		// tolerate some error cases
 		if (binding == null || 
 				!(binding.isValidBinding() || 
@@ -48,13 +57,8 @@
 					|| binding.problemId() == ProblemReasons.InheritedNameHidesEnclosingName
 					|| binding.problemId() == ProblemReasons.NonStaticReferenceInConstructorInvocation
 					|| binding.problemId() == ProblemReasons.NonStaticReferenceInStaticContext))
-		throw new SelectionNodeFound();
-	else
-		throw new SelectionNodeFound(binding);
-}
-public String toStringExpression(){
-	return 	"<SelectionOnFieldReference:"  //$NON-NLS-1$
-			+ super.toStringExpression() 
-			+ ">"; //$NON-NLS-1$
-}
+			throw new SelectionNodeFound();
+		else
+			throw new SelectionNodeFound(binding);
+	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnFieldType.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnFieldType.java
index cb76584..f21ddf4 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnFieldType.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnFieldType.java
@@ -22,7 +22,7 @@
 		this.type = type;
 		this.name = CharOperation.NO_CHAR;
 	}
-	public String toString(int tab) {
-		return type.toString(tab);
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+		return type.print(tab, output).append(';'); 
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnImportReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnImportReference.java
index 3c99952..d8a9bb0 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnImportReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnImportReference.java
@@ -33,20 +33,16 @@
 
 public class SelectionOnImportReference extends ImportReference {
 
-public SelectionOnImportReference(char[][] tokens , long[] positions) {
-	super(tokens, positions, false);
+public SelectionOnImportReference(char[][] tokens , long[] positions, int modifiers) {
+	super(tokens, positions, false, modifiers);
 }
-public String toString(int tab, boolean withOnDemand) {
+public StringBuffer print(int indent, StringBuffer output, boolean withOnDemand) {
 
-	StringBuffer buffer = new StringBuffer(tabString(tab));
-	buffer.	append("<SelectOnImport:"); //$NON-NLS-1$
+	printIndent(indent, output).append("<SelectOnImport:"); //$NON-NLS-1$
 	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		if (i < (tokens.length - 1)) {
-			buffer.append("."); //$NON-NLS-1$
-		}
+		if (i > 0) output.append('.');
+		output.append(tokens[i]);
 	}
-	buffer.append(">"); //$NON-NLS-1$
-	return buffer.toString();
+	return output.append('>');
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnLocalName.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnLocalName.java
index fbb137a..2c1f9aa 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnLocalName.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnLocalName.java
@@ -10,29 +10,32 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.codeassist.select;
 
-import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 
 public class SelectionOnLocalName extends LocalDeclaration{
-	public SelectionOnLocalName(Expression expr, char[] name,	int sourceStart, int sourceEnd) {
-		super(expr, name, sourceStart, sourceEnd);
+	
+	public SelectionOnLocalName(char[] name,	int sourceStart, int sourceEnd) {
+
+		super(name, sourceStart, sourceEnd);
 	}
 	
 	public void resolve(BlockScope scope) {
+
 		super.resolve(scope);
 		throw new SelectionNodeFound(binding);
 	}
 	
-	public String toString(int tab) {
-		String s = tabString(tab);
-		s += "<SelectionOnLocalName:"; //$NON-NLS-1$
-		if (modifiers != AccDefault) {
-			s += modifiersString(modifiers);
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+		
+		printIndent(tab, output);
+		output.append("<SelectionOnLocalName:"); //$NON-NLS-1$
+		printModifiers(this.modifiers, output);
+		 type.print(0, output).append(' ').append(this.name);
+		if (initialization != null) {
+			output.append(" = "); //$NON-NLS-1$
+			initialization.printExpression(0, output);
 		}
-		s += type.toString(0) + " " + new String(name()); //$NON-NLS-1$
-		if (initialization != null) s += " = " + initialization.toStringExpression(); //$NON-NLS-1$
-		s+= ">";//$NON-NLS-1$
-		return s;	
+		return output.append(">;"); //$NON-NLS-1$
 	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java
index eb73dc2..7a2f74e 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnMessageSend.java
@@ -43,9 +43,9 @@
 	 * Cannot answer default abstract match, iterate in superinterfaces of declaring class
 	 * for a better match (default abstract match came from scope lookups).
 	 */
-	private MethodBinding findNonDefaultAbstractMethod(MethodBinding binding) {
+	private MethodBinding findNonDefaultAbstractMethod(MethodBinding methodBinding) {
 
-		ReferenceBinding[] itsInterfaces = binding.declaringClass.superInterfaces();
+		ReferenceBinding[] itsInterfaces = methodBinding.declaringClass.superInterfaces();
 		if (itsInterfaces != NoSuperInterfaces) {
 			ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
 			int lastPosition = 0;
@@ -61,10 +61,10 @@
 						// if interface as not already been visited
 						currentType.tagBits |= TagBits.InterfaceVisited;
 
-						MethodBinding[] methods = currentType.getMethods(binding.selector);;
+						MethodBinding[] methods = currentType.getMethods(methodBinding.selector);
 						if(methods != null) {
 							for (int k = 0; k < methods.length; k++) {
-								if(binding.areParametersEqual(methods[k])) {
+								if(methodBinding.areParametersEqual(methods[k])) {
 									return methods[k];
 								}
 							}
@@ -86,7 +86,21 @@
 				}
 			}
 		}
-		return binding;
+		return methodBinding;
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		output.append("<SelectOnMessageSend:"); //$NON-NLS-1$
+		if (!receiver.isImplicitThis()) receiver.printExpression(0, output).append('.');
+		output.append(this.selector).append('(');
+		if (arguments != null) {
+			for (int i = 0; i < arguments.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				arguments[i].printExpression(0, output);
+			}
+		}
+		return output.append(")>"); //$NON-NLS-1$
 	}
 	
 	public TypeBinding resolveType(BlockScope scope) {
@@ -109,22 +123,4 @@
 			}
 		}
 	}
-	
-	public String toStringExpression() {
-
-		String s = "<SelectOnMessageSend:"; //$NON-NLS-1$
-		if (!receiver.isImplicitThis())
-			s = s + receiver.toStringExpression() + "."; //$NON-NLS-1$
-		s = s + new String(selector) + "("; //$NON-NLS-1$
-		if (arguments != null) {
-			for (int i = 0; i < arguments.length; i++) {
-				s += arguments[i].toStringExpression();
-				if (i != arguments.length - 1) {
-					s += ", "; //$NON-NLS-1$
-				}
-			};
-		}
-		s = s + ")>"; //$NON-NLS-1$
-		return s;
-	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnPackageReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnPackageReference.java
index a7c3587..97513ca 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnPackageReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnPackageReference.java
@@ -33,18 +33,14 @@
 
 public class SelectionOnPackageReference extends ImportReference {
 public SelectionOnPackageReference(char[][] tokens , long[] positions) {
-	super(tokens, positions, true);
+	super(tokens, positions, true, AccDefault);
 }
-public String toString(int tab, boolean withOnDemand) {
-	StringBuffer buffer = new StringBuffer(tabString(tab));
-	buffer.	append("<SelectOnPackage:"); //$NON-NLS-1$
+public StringBuffer print(int tab, StringBuffer output, boolean withOnDemand) {
+	printIndent(tab, output).append("<SelectOnPackage:"); //$NON-NLS-1$
 	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		if (i < (tokens.length - 1)) {
-			buffer.append("."); //$NON-NLS-1$
-		}
+		if (i > 0) output.append('.');
+		output.append(tokens[i]);
 	}
-	buffer.append(">"); //$NON-NLS-1$
-	return buffer.toString();
+	return output.append('>'); 
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java
index c0dcb4f..9bb38eb 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedAllocationExpression.java
@@ -31,47 +31,53 @@
  *
  */
 
-import org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
  
 public class SelectionOnQualifiedAllocationExpression extends QualifiedAllocationExpression {
-public SelectionOnQualifiedAllocationExpression() {
-}
-public SelectionOnQualifiedAllocationExpression(AnonymousLocalTypeDeclaration anonymous) {
-	anonymousType = anonymous ;
-}
-public TypeBinding resolveType(BlockScope scope) {
-	super.resolveType(scope);
 
-	// tolerate some error cases
-	if (binding == null || 
-			!(binding.isValidBinding() || 
-				binding.problemId() == ProblemReasons.NotVisible))
-		throw new SelectionNodeFound();
-	if (anonymousType == null)
-		throw new SelectionNodeFound(binding);
-
-	// if selecting a type for an anonymous type creation, we have to
-	// find its target super constructor (if extending a class) or its target 
-	// super interface (if extending an interface)
-	if (anonymousType.binding.superInterfaces == NoSuperInterfaces) {
-		// find the constructor binding inside the super constructor call
-		ConstructorDeclaration constructor = (ConstructorDeclaration) anonymousType.declarationOf(binding);
-		throw new SelectionNodeFound(constructor.constructorCall.binding);
-	} else {
-		// open on the only superinterface
-		throw new SelectionNodeFound(anonymousType.binding.superInterfaces[0]);
+	public SelectionOnQualifiedAllocationExpression() {
+		// constructor without argument
 	}
-}
-public String toStringExpression(int tab) {
-	return 
-		((this.enclosingInstance == null) ? 
-			"<SelectOnAllocationExpression:" :  //$NON-NLS-1$
-			"<SelectOnQualifiedAllocationExpression:") +  //$NON-NLS-1$
-		super.toStringExpression(tab) + ">"; //$NON-NLS-1$
-}
+	
+	public SelectionOnQualifiedAllocationExpression(TypeDeclaration anonymous) {
+		anonymousType = anonymous ;
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		if (this.enclosingInstance == null)
+			output.append("<SelectOnAllocationExpression:");  //$NON-NLS-1$
+		else 
+			output.append("<SelectOnQualifiedAllocationExpression:"); //$NON-NLS-1$
+
+		return super.printExpression(indent, output).append('>'); 
+	}
+	
+	public TypeBinding resolveType(BlockScope scope) {
+		super.resolveType(scope);
+	
+		// tolerate some error cases
+		if (binding == null || 
+				!(binding.isValidBinding() || 
+					binding.problemId() == ProblemReasons.NotVisible))
+			throw new SelectionNodeFound();
+		if (anonymousType == null)
+			throw new SelectionNodeFound(binding);
+	
+		// if selecting a type for an anonymous type creation, we have to
+		// find its target super constructor (if extending a class) or its target 
+		// super interface (if extending an interface)
+		if (anonymousType.binding.superInterfaces == NoSuperInterfaces) {
+			// find the constructor binding inside the super constructor call
+			ConstructorDeclaration constructor = (ConstructorDeclaration) anonymousType.declarationOf(binding);
+			throw new SelectionNodeFound(constructor.constructorCall.binding);
+		} else {
+			// open on the only superinterface
+			throw new SelectionNodeFound(anonymousType.binding.superInterfaces[0]);
+		}
+	}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedNameReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedNameReference.java
index 6212773..629b50e 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedNameReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedNameReference.java
@@ -41,13 +41,22 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 
 public class SelectionOnQualifiedNameReference extends QualifiedNameReference {
-	public long[] sourcePositions; // positions of each token, the last one being the positions of the completion identifier
+
 public SelectionOnQualifiedNameReference(char[][] previousIdentifiers, char[] selectionIdentifier, long[] positions) {
 	super(
 		CharOperation.arrayConcat(previousIdentifiers, selectionIdentifier),
+		positions,
 		(int) (positions[0] >>> 32),
 		(int) positions[positions.length - 1]);
-	this.sourcePositions = positions;
+}
+public StringBuffer printExpression(int indent, StringBuffer output) {
+
+	output.append("<SelectOnName:"); //$NON-NLS-1$
+	for (int i = 0, length = tokens.length; i < length; i++) {
+		if (i > 0) output.append('.');
+		output.append(tokens[i]);
+	}
+	return output.append('>'); 
 }
 public TypeBinding resolveType(BlockScope scope) {
 	// it can be a package, type, member type, local variable or field
@@ -75,15 +84,4 @@
 	}
 	throw new SelectionNodeFound(binding);
 }
-public String toStringExpression() {
-
-	StringBuffer buffer = new StringBuffer("<SelectOnName:"); //$NON-NLS-1$
-	for (int i = 0, length = tokens.length; i < length; i++) {
-		buffer.append(tokens[i]);
-		if (i != length - 1)
-			buffer.append("."); //$NON-NLS-1$
-	}
-	buffer.append(">"); //$NON-NLS-1$
-	return buffer.toString();
-}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java
index eb1cb41..dcced34 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedSuperReference.java
@@ -42,6 +42,12 @@
 public SelectionOnQualifiedSuperReference(TypeReference name, int pos, int sourceEnd) {
 	super(name, pos, sourceEnd);
 }
+public StringBuffer printExpression(int indent, StringBuffer output) {
+
+	output.append("<SelectOnQualifiedSuper:"); //$NON-NLS-1$
+	return super.printExpression(0, output).append('>');
+}
+
 public TypeBinding resolveType(BlockScope scope) {
 	TypeBinding binding = super.resolveType(scope);
 
@@ -50,11 +56,4 @@
 	else
 		throw new SelectionNodeFound(binding);
 }
-public String toStringExpression(){
-	
-	StringBuffer buffer = new StringBuffer("<SelectOnQualifiedSuper:"); //$NON-NLS-1$
-	buffer.append(super.toStringExpression());
-	buffer.append(">"); //$NON-NLS-1$
-	return buffer.toString();
-}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java
index 79bee2a..7d0ba39 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnQualifiedTypeReference.java
@@ -52,16 +52,13 @@
 
 	throw new SelectionNodeFound(binding);
 }
-public String toStringExpression(int tab) {
+public StringBuffer printExpression(int indent, StringBuffer output) {
 
-	StringBuffer buffer = new StringBuffer();
-	buffer.append("<SelectOnType:"); //$NON-NLS-1$
+	output.append("<SelectOnType:"); //$NON-NLS-1$
 	for (int i = 0, length = tokens.length; i < length; i++) {
-		buffer.append(tokens[i]);
-		if (i != length - 1)
-			buffer.append("."); //$NON-NLS-1$
+		if (i > 0) output.append('.');
+		output.append(tokens[i]);
 	}
-	buffer.append(">"); //$NON-NLS-1$
-	return buffer.toString();
+	return output.append('>'); 
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleNameReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleNameReference.java
index e2c89c5..36975ea 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleNameReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleNameReference.java
@@ -43,7 +43,7 @@
 }
 public TypeBinding resolveType(BlockScope scope) {
 	// it can be a package, type, member type, local variable or field
-	binding = scope.getBinding(token, VARIABLE | TYPE | PACKAGE, this);
+	binding = scope.getBinding(token, VARIABLE | TYPE | PACKAGE, this, true /*resolve*/);
 	if (!binding.isValidBinding()) {
 		if (binding instanceof ProblemFieldBinding) {
 			// tolerate some error cases
@@ -68,7 +68,8 @@
 
 	throw new SelectionNodeFound(binding);
 }
-public String toStringExpression() {
-	return "<SelectOnName:" + super.toStringExpression() + ">"; //$NON-NLS-2$ //$NON-NLS-1$
+public StringBuffer printExpression(int indent, StringBuffer output) {
+	output.append("<SelectOnName:"); //$NON-NLS-1$
+	return super.printExpression(0, output).append('>');
 }
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleTypeReference.java
index a42533a..f925b35 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSingleTypeReference.java
@@ -47,6 +47,10 @@
 
 	throw new SelectionNodeFound(binding);
 }
+public StringBuffer printExpression(int indent, StringBuffer output) {
+
+	return output.append("<SelectOnType:").append(token).append('>');//$NON-NLS-1$
+}
 public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
 	super.resolveTypeEnclosing(scope, enclosingType);
 
@@ -58,8 +62,4 @@
 	else
 		throw new SelectionNodeFound(this.resolvedType);
 }
-public String toStringExpression(int tab){
-
-	return "<SelectOnType:" + new String(token) + ">" ; //$NON-NLS-2$ //$NON-NLS-1$
-}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java
index 37cb3d1..2139e06 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnSuperReference.java
@@ -42,6 +42,11 @@
 public SelectionOnSuperReference(int pos, int sourceEnd) {
 	super(pos, sourceEnd);
 }
+public StringBuffer printExpression(int indent, StringBuffer output){
+
+	output.append("<SelectOnSuper:"); //$NON-NLS-1$
+	return super.printExpression(0, output).append('>');
+}
 public TypeBinding resolveType(BlockScope scope) {
 	TypeBinding binding = super.resolveType(scope);
 
@@ -50,9 +55,4 @@
 	else
 		throw new SelectionNodeFound(binding);
 }
-public String toStringExpression(){
-
-	return "<SelectOnSuper:"+super.toStringExpression()+">"; //$NON-NLS-2$ //$NON-NLS-1$
-	
-}
 }
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
index 3b6abbd..5416a39 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
@@ -40,15 +40,15 @@
 	public static final char[] SUPER = "super".toCharArray(); //$NON-NLS-1$
 	public static final char[] THIS = "this".toCharArray(); //$NON-NLS-1$
 	
-public SelectionParser(ProblemReporter problemReporter, boolean assertMode) {
-	super(problemReporter, assertMode);
+public SelectionParser(ProblemReporter problemReporter) {
+	super(problemReporter);
 }
 public char[] assistIdentifier(){
 	return ((SelectionScanner)scanner).selectionIdentifier;
 }
 protected void attachOrphanCompletionNode(){
 	if (isOrphanCompletionNode){
-		AstNode orphan = this.assistNode;
+		ASTNode orphan = this.assistNode;
 		isOrphanCompletionNode = false;
 		
 		
@@ -182,10 +182,10 @@
 		return;
 	}
 	QualifiedAllocationExpression alloc;
-	AnonymousLocalTypeDeclaration anonymousType = 
-		new AnonymousLocalTypeDeclaration(this.compilationUnit.compilationResult); 
-	alloc = 
-		anonymousType.allocation = new SelectionOnQualifiedAllocationExpression(anonymousType); 
+	TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult); 
+		anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+		anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
+		alloc = anonymousType.allocation = new SelectionOnQualifiedAllocationExpression(anonymousType); 
 	markEnclosingMemberWithLocalType();
 	pushOnAstStack(anonymousType);
 
@@ -255,9 +255,10 @@
 	int start = variable.initialization.sourceStart;
 	int end =  variable.initialization.sourceEnd;
 	if ((selectionStart < start) &&  (selectionEnd < start) ||
-		(selectionStart > end) && (selectionEnd > end)) {
+			(selectionStart > end) && (selectionEnd > end)) {
 		variable.initialization = null;
 	}
+
 }
 
 protected void consumeFieldAccess(boolean isSuperAccess) {
@@ -305,16 +306,18 @@
 	} else {
 
 		identifierLengthPtr--;
-		char[] name = identifierStack[identifierPtr];
+		char[] identifierName = identifierStack[identifierPtr];
 		long namePositions = identifierPositionStack[identifierPtr--];
 		TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
-		intPtr -= 2;
+		int modifierPositions = intStack[intPtr--];
+		intPtr--;
 		Argument arg = 
 			new SelectionOnArgumentName(
-				name, 
+				identifierName, 
 				namePositions, 
 				type, 
 				intStack[intPtr + 1] & ~AccDeprecated); // modifiers
+		arg.declarationSourceStart = modifierPositions;
 		pushOnAstStack(arg);
 		
 		assistNode = arg;
@@ -341,6 +344,19 @@
 		this.lastIgnoredToken = -1;
 	}
 }
+protected void consumeLocalVariableDeclarationStatement() {
+	super.consumeLocalVariableDeclarationStatement();
+	
+	// force to restart in recovery mode if the declaration contains the selection
+	if (!this.diet) {
+		LocalDeclaration localDeclaration = (LocalDeclaration) this.astStack[this.astPtr];
+		if ((this.selectionStart >= localDeclaration.sourceStart) 
+				&&  (this.selectionEnd <= localDeclaration.sourceEnd)) {
+			this.restartRecovery	= true;	
+			this.lastIgnoredToken = -1;	
+		}
+	}
+}
 protected void consumeMethodInvocationName() {
 	// MethodInvocation ::= Name '(' ArgumentListopt ')'
 
@@ -381,6 +397,9 @@
 				constructorCall.resolve(scope);
 				return null;
 			}
+			public StringBuffer printExpression(int indent, StringBuffer output) {
+				return output; 
+			}
 		});
 	}
 	this.assistNode = constructorCall;	
@@ -427,6 +446,9 @@
 				constructorCall.resolve(scope);
 				return null;
 			}
+			public StringBuffer printExpression(int indent, StringBuffer output) {
+				return output; 
+			}
 		});
 	}
 	
@@ -461,7 +483,7 @@
 		length); 
 
 	/* build specific assist node on import statement */
-	ImportReference reference = this.createAssistImportReference(subset, positions);
+	ImportReference reference = this.createAssistImportReference(subset, positions, AccDefault);
 	reference.onDemand = true;
 	assistNode = reference;
 	this.lastCheckPoint = reference.sourceEnd + 1;
@@ -475,8 +497,8 @@
 	}
 	//endPosition is just before the ;
 	reference.declarationSourceStart = intStack[intPtr--];
-	// flush annotations defined prior to import statements
-	reference.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(reference.declarationSourceEnd);
+	// flush comments defined prior to import statements
+	reference.declarationSourceEnd = this.flushCommentsDefinedPriorTo(reference.declarationSourceEnd);
 
 	// recovery
 	if (currentElement != null){
@@ -486,52 +508,48 @@
 		restartRecovery = true; // used to avoid branching back into the regular automaton		
 	}
 }
-public ImportReference createAssistImportReference(char[][] tokens, long[] positions){
-	return new SelectionOnImportReference(tokens, positions);
+public ImportReference createAssistImportReference(char[][] tokens, long[] positions, int mod){
+	return new SelectionOnImportReference(tokens, positions, mod);
 }
 public ImportReference createAssistPackageReference(char[][] tokens, long[] positions){
 	return new SelectionOnPackageReference(tokens, positions);
 }
-protected LocalDeclaration createLocalDeclaration(Expression initialization,char[] name,int sourceStart,int sourceEnd) {
+protected LocalDeclaration createLocalDeclaration(char[] assistName,int sourceStart,int sourceEnd) {
 	if (this.indexOfAssistIdentifier() < 0) {
-		return super.createLocalDeclaration(initialization, name, sourceStart, sourceEnd);
+		return super.createLocalDeclaration(assistName, sourceStart, sourceEnd);
 	} else {
-		SelectionOnLocalName local = new SelectionOnLocalName(initialization, name, sourceStart, sourceEnd);
+		SelectionOnLocalName local = new SelectionOnLocalName(assistName, sourceStart, sourceEnd);
 		this.assistNode = local;
 		this.lastCheckPoint = sourceEnd + 1;
-		if (!diet){
-			this.restartRecovery	= true;	// force to restart in recovery mode
-			this.lastIgnoredToken = -1;	
-		}
 		return local;
 	}
 }
-public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] name, long[] positions){
+public NameReference createQualifiedAssistNameReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
 	return new SelectionOnQualifiedNameReference(
 					previousIdentifiers, 
-					name, 
+					assistName, 
 					positions); 	
 }
-public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] name, long[] positions){
+public TypeReference createQualifiedAssistTypeReference(char[][] previousIdentifiers, char[] assistName, long[] positions){
 	return new SelectionOnQualifiedTypeReference(
 					previousIdentifiers, 
-					name, 
+					assistName, 
 					positions); 	
 }
-public NameReference createSingleAssistNameReference(char[] name, long position) {
-	return new SelectionOnSingleNameReference(name, position);
+public NameReference createSingleAssistNameReference(char[] assistName, long position) {
+	return new SelectionOnSingleNameReference(assistName, position);
 }
-public TypeReference createSingleAssistTypeReference(char[] name, long position) {
-	return new SelectionOnSingleTypeReference(name, position);
+public TypeReference createSingleAssistTypeReference(char[] assistName, long position) {
+	return new SelectionOnSingleTypeReference(assistName, position);
 }
-public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
 
-	this.selectionStart = selectionStart;
-	this.selectionEnd = selectionEnd;	
+	this.selectionStart = start;
+	this.selectionEnd = end;	
 	SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
 	selectionScanner.selectionIdentifier = null;
-	selectionScanner.selectionStart = selectionStart;
-	selectionScanner.selectionEnd = selectionEnd;	
+	selectionScanner.selectionStart = start;
+	selectionScanner.selectionEnd = end;	
 	return this.dietParse(sourceUnit, compilationResult);
 }
 protected NameReference getUnspecifiedReference() {
@@ -622,7 +640,7 @@
 	return reference;
 }
 public void initializeScanner(){
-	this.scanner = new SelectionScanner(this.assertMode);
+	this.scanner = new SelectionScanner(this.options.sourceLevel);
 }
 protected MessageSend newMessageSend() {
 	// '(' ArgumentListopt ')'
@@ -642,7 +660,7 @@
 			messageSend.arguments = new Expression[length], 
 			0, 
 			length); 
-	};
+	}
 	assistNode = messageSend;
 	if (!diet){
 		this.restartRecovery	= true;	// force to restart in recovery mode
@@ -652,15 +670,17 @@
 	this.isOrphanCompletionNode = true;
 	return messageSend;
 }
-public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int selectionStart, int selectionEnd) {
+public CompilationUnitDeclaration parse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int start, int end) {
 
-	this.selectionStart = selectionStart;
-	this.selectionEnd = selectionEnd;	
+	if (end == -1) return super.parse(sourceUnit, compilationResult, start, end);
+	
+	this.selectionStart = start;
+	this.selectionEnd = end;	
 	SelectionScanner selectionScanner = (SelectionScanner)this.scanner;
 	selectionScanner.selectionIdentifier = null;
-	selectionScanner.selectionStart = selectionStart;
-	selectionScanner.selectionEnd = selectionEnd;	
-	return this.parse(sourceUnit, compilationResult);
+	selectionScanner.selectionStart = start;
+	selectionScanner.selectionEnd = end;	
+	return super.parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
 }
 /*
  * Reset context so as to resume to regular parse loop
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionScanner.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionScanner.java
index aab9afd..d237ec6 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionScanner.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionScanner.java
@@ -16,7 +16,6 @@
  *
  * Source positions are zero-based and inclusive.
  */
-import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 
 public class SelectionScanner extends Scanner {
@@ -29,8 +28,8 @@
  *
  */
  
-public SelectionScanner(boolean assertMode) {
-	super(false /*comment*/, false /*whitespace*/, false /*nls*/, assertMode /*assert*/, null /*taskTags*/, null/*taskPriorities*/);
+public SelectionScanner(long sourceLevel) {
+	super(false /*comment*/, false /*whitespace*/, false /*nls*/, sourceLevel, null /*taskTags*/, null/*taskPriorities*/);
 }
 
 public char[] getCurrentIdentifierSource() {
@@ -53,7 +52,7 @@
  * In case we actually read a keyword which corresponds to the selected
  * range, we pretend we read an identifier.
  */
-public int scanIdentifierOrKeyword() throws InvalidInputException {
+public int scanIdentifierOrKeyword() {
 
 	int id = super.scanIdentifierOrKeyword();
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
index fb39484..4defca1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
@@ -163,6 +163,37 @@
 		System.arraycopy(second, 0, result, length1, length2);
 		return result;
 	}
+	/**
+	 * Returns the char arrays as an array of Strings
+	 * 
+	 * @param charArrays the char array to convert
+	 * @return the char arrays as an array of Strings or null if the given char arrays is null.
+	 * @since 3.0
+	 */
+	public static String[] charArrayToStringArray(char[][] charArrays) {
+		if (charArrays == null) {
+			return null;
+		}
+		String[] strings= new String[charArrays.length];
+		for (int i= 0; i < charArrays.length; i++) {
+			strings[i]= new String(charArrays[i]);
+		}
+		return strings;
+	}
+	/**
+	 * Returns the char array as a String
+
+	 * @param charArray the char array to convert
+	 * @return the char array as a String or null if the given char array is null.
+	 * @since 3.0
+	 */
+	public static String charToString(char[] charArray) {
+		if (charArray == null) {
+			return null;
+		} else {
+			return new String(charArray);
+		}
+	}
 
 	/**
 	 * Answers a new array adding the second array at the end of first array.
@@ -1063,6 +1094,67 @@
 				return false;
 		return true;
 	}
+	
+	/**
+	 * Answers true if the first array is identical character by character to a portion of the second array
+	 * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false.
+	 * The equality is case sensitive.
+	 * <br>
+	 * <br>
+	 * For example:
+	 * <ol>
+	 * <li><pre>
+	 *    first = null
+	 *    second = null
+	 *    secondStart = 0
+	 *    secondEnd = 0
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { }
+	 *    second = null
+	 *    secondStart = 0
+	 *    secondEnd = 0
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'a' }
+	 *    second = { 'a' }
+	 *    secondStart = 0
+	 *    secondEnd = 1
+	 *    result => true
+	 * </pre>
+	 * </li>
+	 * <li><pre>
+	 *    first = { 'a' }
+	 *    second = { 'A' }
+	 *    secondStart = 0
+	 *    secondEnd = 1
+	 *    result => false
+	 * </pre>
+	 * </li>
+	 * </ol>
+	 * @param first the first array
+	 * @param second the second array
+	 * @param secondStart inclusive start position in the second array to compare
+	 * @param secondEnd exclusive end position in the second array to compare
+	 * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false
+	 */
+	public static final boolean equals(char[] first, char[] second, int secondStart, int secondEnd) {
+		if (first == second)
+			return true;
+		if (first == null || second == null)
+			return false;
+		if (first.length != secondEnd - secondStart)
+			return false;
+
+		for (int i = first.length; --i >= 0;)
+			if (first[i] != second[i+secondStart])
+				return false;
+		return true;
+	}
 
 	/**
 	 * If isCaseSensite is true, answers true if the two arrays are identical character
@@ -1689,9 +1781,8 @@
 	 * conventions, also see "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes").
 	 * Path pattern matching is enhancing regular pattern matching in supporting extra rule where '**' represent
 	 * any folder combination.
-	 * Special rules: 
+	 * Special rule: 
 	 * - foo\  is equivalent to foo\**   
-	 * - *.java is equivalent to **\*.java
 	 * When not case sensitive, the pattern is assumed to already be lowercased, the
 	 * name will be lowercased character per character as comparing.
 	 * 
@@ -1712,17 +1803,9 @@
 		if (pattern == null)
 			return true; // null pattern is equivalent to '*'
 
-		// special case: pattern foo is equivalent to **\foo (not absolute)
-		boolean freeLeadingDoubleStar;
-
 		// offsets inside pattern
-		int pSegmentStart, pLength = pattern.length;
-
-		if (freeLeadingDoubleStar = pattern[0] != pathSeparator){
-			pSegmentStart = 0;
-		} else {
-			pSegmentStart = 1;
-		}
+		int pSegmentStart = pattern[0] == pathSeparator ? 1 : 0;
+		int pLength = pattern.length;
 		int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart+1);
 		if (pSegmentEnd < 0) pSegmentEnd = pLength;
 
@@ -1744,7 +1827,6 @@
 
 		// first segments
 		while (pSegmentStart < pLength
-			&& !freeLeadingDoubleStar
 			&& !(pSegmentEnd == pLength && freeTrailingDoubleStar
 					|| (pSegmentEnd == pSegmentStart + 2
 							&& pattern[pSegmentStart] == '*'
@@ -2588,4 +2670,11 @@
 		char[] result = concatWith(array, '.');
 		return new String(result);
 	}
+	final static public String[] toStrings(char[][] array) {
+		int length = array.length;
+		String[] result = new String[length];
+		for (int i = 0; i < length; i++)
+			result[i] = new String(array[i]);
+		return result;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index 195517d..fffc3f1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -8,20 +8,20 @@
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *     IBM Corporation - added the following constants
- *                                 NonStaticAccessToStaticField
- *                                 NonStaticAccessToStaticMethod
- *                                 Task
- * 								   ExpressionShouldBeAVariable
- * 								   AssignmentHasNoEffect
+ *								   NonStaticAccessToStaticField
+ *								   NonStaticAccessToStaticMethod
+ *								   Task
+ *								   ExpressionShouldBeAVariable
+ *								   AssignmentHasNoEffect
  *     IBM Corporation - added the following constants
- * 								   TooManySyntheticArgumentSlots
- * 								   TooManyArrayDimensions
- * 								   TooManyBytesForStringConstant
- * 								   TooManyMethods
- * 								   TooManyFields
- * 								   NonBlankFinalLocalAssignment
- * 								   ObjectCannotHaveSuperTypes
- * 								   MissingSemiColon
+ *								   TooManySyntheticArgumentSlots
+ *								   TooManyArrayDimensions
+ *								   TooManyBytesForStringConstant
+ *								   TooManyMethods
+ *								   TooManyFields
+ *								   NonBlankFinalLocalAssignment
+ *								   ObjectCannotHaveSuperTypes
+ *								   MissingSemiColon
  *								   InvalidParenthesizedExpression
  *								   EnclosingInstanceInConstructorCall
  *								   BytecodeExceeds64KLimitForConstructor
@@ -31,7 +31,24 @@
  *								   UnusedPrivateType
  *								   UnusedPrivateField
  *								   IncompatibleExceptionInThrowsClauseForNonInheritedInterfaceMethod
- *******************************************************************************/
+ *								   InvalidExplicitConstructorCall
+ *     IBM Corporation - added the following constants
+ *								   PossibleAccidentalBooleanAssignment
+ *								   SuperfluousSemicolon
+ *								   IndirectAccessToStaticField
+ *								   IndirectAccessToStaticMethod
+ *								   IndirectAccessToStaticType
+ *								   BooleanMethodThrowingException
+ *								   UnnecessaryCast
+ *								   UnnecessaryArgumentCast
+ *								   UnnecessaryInstanceof
+ *								   FinallyMustCompleteNormally
+ *								   UnusedMethodDeclaredThrownException
+ *								   UnusedConstructorDeclaredThrownException
+ *								   InvalidCatchBlockSequence
+ *								   UnqualifiedFieldAccess
+ *								   Javadoc
+ ****************************************************************************/
 package org.eclipse.jdt.core.compiler;
  
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
@@ -137,7 +154,7 @@
 	 * Set the start position of the problem (inclusive), or -1 if unknown.
 	 * Used for shifting problem positions.
 	 * 
-	 * @param the given start position
+	 * @param sourceStart the given start position
 	 */
 	void setSourceStart(int sourceStart);
 	
@@ -158,7 +175,10 @@
 	int ConstructorRelated = 0x08000000;
 	int ImportRelated = 0x10000000;
 	int Internal = 0x20000000;
-	int Syntax =  0x40000000;
+	int Syntax = 0x40000000;
+	int Javadoc = 0x80000000;
+	/** @deprecated */
+	int Annotation = 0x80000000;
 	
 	/**
 	 * Mask to use in order to filter out the category portion of the problem ID.
@@ -177,7 +197,7 @@
 	int Unclassified = 0;
 
 	/**
-	 * Generic type related problems
+	 * General type related problems
 	 */
 	int ObjectHasNoSuperclass = TypeRelated + 1;
 	int UndefinedType = TypeRelated + 2;
@@ -191,7 +211,9 @@
 	int IncompatibleTypesInEqualityOperator = TypeRelated + 15;
 	int IncompatibleTypesInConditionalOperator = TypeRelated + 16;
 	int TypeMismatch = TypeRelated + 17;
-
+	/** @since 3.0 */
+	int IndirectAccessToStaticType = Internal + TypeRelated + 18;
+	
 	/**
 	 * Inner types related problems
 	 */
@@ -220,6 +242,7 @@
 	int DuplicateFinalLocalInitialization = Internal + 57;
 	/** @since 2.1 */
 	int NonBlankFinalLocalAssignment = Internal + 58;
+	
 	int FinalOuterLocalAssignment = Internal + 60;
 	int LocalVariableIsNeverUsed = Internal + 61;
 	int ArgumentIsNeverUsed = Internal + 62;
@@ -245,12 +268,53 @@
 	int NonStaticAccessToStaticField = Internal + FieldRelated + 76;
 	/** @since 2.1 */
 	int UnusedPrivateField = Internal + FieldRelated + 77;
+	/** @since 3.0 */
+	int IndirectAccessToStaticField = Internal + FieldRelated + 78;
+	/** @since 3.0 */
+	int UnqualifiedFieldAccess = Internal + FieldRelated + 79;
 	
 	// blank final fields
 	int FinalFieldAssignment = FieldRelated + 80;
 	int UninitializedBlankFinalField = FieldRelated + 81;
 	int DuplicateBlankFinalFieldInitialization = FieldRelated + 82;
 
+	// variable hiding
+	/**
+	 * The local variable {0} is hiding another local variable defined in an enclosing type scope 
+	 * @since 3.0
+	 */
+	int LocalVariableHidingLocalVariable = Internal + 90;		
+
+	/**
+	 * The local variable {0} is hiding the field {1}.{2} 
+	 * @since 3.0
+	 */
+	int LocalVariableHidingField = Internal + FieldRelated + 91;		
+	 
+	/**
+	 * The field {0}.{1} is hiding another local variable defined in an enclosing type scope
+	 * @since 3.0 
+	 */
+	int FieldHidingLocalVariable = Internal + FieldRelated + 92;		
+
+	/**
+	 * The field {0}.{1} is hiding the field {2}.{3}
+	 * @since 3.0 
+	 */
+	int FieldHidingField = Internal + FieldRelated + 93;		
+
+	/**
+	 * The argument {0} is hiding another local variable defined in an enclosing type scope
+	 * @since 3.0 
+	 */
+	int ArgumentHidingLocalVariable = Internal + 94;		
+
+	/**
+	 * The argument {0} is hiding the field {2}.{3}
+	 * @since 3.0 
+	 */
+	int ArgumentHidingField = Internal + 95;		
+
 	// methods
 	int UndefinedMethod = MethodRelated + 100;
 	int NotVisibleMethod = MethodRelated + 101;
@@ -272,6 +336,9 @@
     int NonStaticAccessToStaticMethod = Internal + MethodRelated + 117;
 	/** @since 2.1 */
 	int UnusedPrivateMethod = Internal + MethodRelated + 118;
+	/** @since 3.0 */
+	int IndirectAccessToStaticMethod = Internal + MethodRelated + 119;
+
 	    
 	// constructors
 	int UndefinedConstructor = ConstructorRelated + 130;
@@ -285,6 +352,8 @@
 	int InstanceMethodDuringConstructorInvocation = ConstructorRelated + 136;
 	int RecursiveConstructorInvocation = ConstructorRelated + 137;
 	int ThisSuperDuringConstructorInvocation = ConstructorRelated + 138;
+	/** @since 3.0 */
+	int InvalidExplicitConstructorCall = ConstructorRelated + Syntax + 139;
 	// implicit constructor calls
 	int UndefinedConstructorInDefaultConstructor = ConstructorRelated + 140;
 	int NotVisibleConstructorInDefaultConstructor = ConstructorRelated + 141;
@@ -314,7 +383,6 @@
 	int CodeCannotBeReached = Internal + 161;
 	int CannotReturnInInitializer = Internal + 162;
 	int InitializerMustCompleteNormally = Internal + 163;
-	
 	// assert
 	int InvalidVoidExpression = Internal + 164;
 	// try
@@ -338,7 +406,25 @@
 	// assignment
 	/** @since 2.1 */
 	int AssignmentHasNoEffect = Internal + 178;
-	
+	/** @since 3.0 */
+	int PossibleAccidentalBooleanAssignment = Internal + 179;
+	/** @since 3.0 */
+	int SuperfluousSemicolon = Internal + 180;
+	/** @since 3.0 */
+	int UnnecessaryCast = Internal + TypeRelated + 181;
+	/** @since 3.0 */
+	int UnnecessaryArgumentCast = Internal + TypeRelated + 182;
+	/** @since 3.0 */
+	int UnnecessaryInstanceof = Internal + TypeRelated + 183;	
+	/** @since 3.0 */
+	int FinallyMustCompleteNormally = Internal + 184;	
+	/** @since 3.0 */
+	int UnusedMethodDeclaredThrownException = Internal + 185;	
+	/** @since 3.0 */
+	int UnusedConstructorDeclaredThrownException = Internal + 186;	
+	/** @since 3.0 */
+	int InvalidCatchBlockSequence = Internal + TypeRelated + 187;	
+
 	// inner emulation
 	int NeedToEmulateFieldReadAccess = FieldRelated + 190;
 	int NeedToEmulateFieldWriteAccess = FieldRelated + 191;
@@ -374,6 +460,33 @@
 	int MissingSemiColon = Syntax + Internal + 224;
 	/** @since 2.1 */
 	int InvalidParenthesizedExpression = Syntax + Internal + 225;
+	
+	/** @since 3.0 */
+	int ParsingErrorInsertTokenBefore = Syntax + Internal + 230;
+	/** @since 3.0 */
+	int ParsingErrorInsertTokenAfter = Syntax + Internal + 231;
+	/** @since 3.0 */
+    int ParsingErrorDeleteToken = Syntax + Internal + 232;
+    /** @since 3.0 */
+    int ParsingErrorDeleteTokens = Syntax + Internal + 233;
+    /** @since 3.0 */
+    int ParsingErrorMergeTokens = Syntax + Internal + 234;
+    /** @since 3.0 */
+    int ParsingErrorInvalidToken = Syntax + Internal + 235;
+    /** @since 3.0 */
+    int ParsingErrorMisplacedConstruct = Syntax + Internal + 236;
+    /** @since 3.0 */
+    int ParsingErrorReplaceTokens = Syntax + Internal + 237;
+    /** @since 3.0 */
+    int ParsingErrorNoSuggestionForTokens = Syntax + Internal + 238;
+    /** @since 3.0 */
+    int ParsingErrorUnexpectedEOF = Syntax + Internal + 239;
+    /** @since 3.0 */
+    int ParsingErrorInsertToComplete = Syntax + Internal + 240;
+    /** @since 3.0 */
+    int ParsingErrorInsertToCompleteScope = Syntax + Internal + 241;
+    /** @since 3.0 */
+    int ParsingErrorInsertToCompletePhrase = Syntax + Internal + 242;
     
 	// scanner errors
 	int EndOfSource = Syntax + Internal + 250;
@@ -501,7 +614,6 @@
 	int ImportInternalNameProvided =  ImportRelated + 389 + ProblemReasons.InternalNameProvided; // ImportRelated + 393
 	int ImportInheritedNameHidesEnclosingName =  ImportRelated + 389 + ProblemReasons.InheritedNameHidesEnclosingName; // ImportRelated + 394
 
-	
 	// local variable related problems
 	int DuplicateModifierForVariable = MethodRelated + 395;
 	int IllegalModifierForVariable = MethodRelated + 396;
@@ -549,4 +661,85 @@
 	// detected task
 	/** @since 2.1 */
 	int Task = Internal + 450;
+	
+	// block
+	/** @since 3.0 */
+	int UndocumentedEmptyBlock = Internal + 460;
+		
+	/*
+	 * Javadoc comments
+	 */
+	/** @since 3.0 */
+	int JavadocUnexpectedTag = Javadoc + Internal + 470;
+	/** @since 3.0 */
+	int JavadocMissingParamTag = Javadoc + Internal + 471;
+	/** @since 3.0 */
+	int JavadocMissingParamName = Javadoc + Internal + 472;
+	/** @since 3.0 */
+	int JavadocDuplicateParamName = Javadoc + Internal + 473;
+	/** @since 3.0 */
+	int JavadocInvalidParamName = Javadoc + Internal + 474;
+	/** @since 3.0 */
+	int JavadocMissingReturnTag = Javadoc + Internal + 475;
+	/** @since 3.0 */
+	int JavadocDuplicateReturnTag = Javadoc + Internal + 476;
+	/** @since 3.0 */
+	int JavadocMissingThrowsTag = Javadoc + Internal + 477;
+	/** @since 3.0 */
+	int JavadocMissingThrowsClassName = Javadoc + Internal + 478;
+	/** @since 3.0 */
+	int JavadocInvalidThrowsClass = Javadoc + Internal + 479;
+	/** @since 3.0 */
+	int JavadocDuplicateThrowsClassName = Javadoc + Internal + 480;
+	/** @since 3.0 */
+	int JavadocInvalidThrowsClassName = Javadoc + Internal + 481;
+	/** @since 3.0 */
+	int JavadocMissingSeeReference = Javadoc + Internal + 482;
+	/** @since 3.0 */
+	int JavadocInvalidSeeReference = Javadoc + Internal + 483;
+	/** @since 3.0 */
+	int JavadocInvalidSeeHref = Javadoc + Internal + 484;
+	/** @since 3.0 */
+	int JavadocInvalidSeeArgs = Javadoc + Internal + 485;
+	/** @since 3.0 */
+	int JavadocMissing = Javadoc + Internal + 486;
+	/** @since 3.0 */
+	int JavadocMessagePrefix = Internal + 489;
+
+	/**@deprecated */
+	int AnnotationUnexpectedTag = JavadocUnexpectedTag;
+	/**@deprecated */
+	int AnnotationMissingParamTag = JavadocMissingParamTag;
+	/**@deprecated */
+	int AnnotationMissingParamName = JavadocMissingParamName;
+	/**@deprecated */
+	int AnnotationDuplicateParamName = JavadocDuplicateParamName;
+	/**@deprecated */
+	int AnnotationInvalidParamName = JavadocInvalidParamName;
+	/**@deprecated */
+	int AnnotationMissingReturnTag = JavadocMissingReturnTag;
+	/**@deprecated */
+	int AnnotationDuplicateReturnTag = JavadocDuplicateReturnTag;
+	/**@deprecated */
+	int AnnotationMissingThrowsTag = JavadocMissingThrowsTag;
+	/**@deprecated */
+	int AnnotationMissingThrowsClassName = JavadocMissingThrowsClassName;
+	/**@deprecated */
+	int AnnotationInvalidThrowsClass = JavadocInvalidThrowsClass;
+	/**@deprecated */
+	int AnnotationDuplicateThrowsClassName = JavadocDuplicateThrowsClassName;
+	/**@deprecated */
+	int AnnotationInvalidThrowsClassName = JavadocInvalidThrowsClassName;
+	/**@deprecated */
+	int AnnotationMissingSeeReference = JavadocMissingSeeReference;
+	/**@deprecated */
+	int AnnotationInvalidSeeReference = JavadocInvalidSeeReference;
+	/**@deprecated */
+	int AnnotationInvalidSeeHref = JavadocInvalidSeeHref;
+	/**@deprecated */
+	int AnnotationInvalidSeeArgs = JavadocInvalidSeeArgs;
+	/**@deprecated */
+	int AnnotationMissing = JavadocMissing;
+	/**@deprecated */
+	int AnnotationMessagePrefix = JavadocMessagePrefix;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java
new file mode 100644
index 0000000..7ebc57c
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ASTVisitor.java
@@ -0,0 +1,616 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler;
+
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.internal.compiler.ast.*; 
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/** 
+ * A visitor for iterating through the parse tree.
+ */
+public abstract class ASTVisitor {
+
+	public void acceptProblem(IProblem problem) {
+		// do nothing by default
+	}
+	public void endVisit(
+		AllocationExpression allocationExpression,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(AND_AND_Expression and_and_Expression, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocArgumentExpression expression, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocFieldReference fieldRef, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocMessageSend messageSend, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocReturnStatement statement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocSingleNameReference argument, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(Argument argument, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		ArrayAllocationExpression arrayAllocationExpression,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ArrayInitializer arrayInitializer, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+		ClassScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ArrayReference arrayReference, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(Assignment assignment, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(AssertStatement assertStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(BinaryExpression binaryExpression, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(Block block, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(BreakStatement breakStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(CaseStatement caseStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(CastExpression castExpression, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(CharLiteral charLiteral, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ClassLiteralAccess classLiteral, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(Clinit clinit, ClassScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		CompilationUnitDeclaration compilationUnitDeclaration,
+		CompilationUnitScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(CompoundAssignment compoundAssignment, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		ConditionalExpression conditionalExpression,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		ConstructorDeclaration constructorDeclaration,
+		ClassScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ContinueStatement continueStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(DoStatement doStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(DoubleLiteral doubleLiteral, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(EqualExpression equalExpression, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		ExplicitConstructorCall explicitConstructor,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		ExtendedStringLiteral extendedStringLiteral,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(FalseLiteral falseLiteral, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(FieldReference fieldReference, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(FloatLiteral floatLiteral, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(EmptyStatement emptyStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ForStatement forStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(IfStatement ifStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ImportReference importRef, CompilationUnitScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(Initializer initializer, MethodScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		InstanceOfExpression instanceOfExpression,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(IntLiteral intLiteral, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(IteratorForStatement forStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(LabeledStatement labeledStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(LocalDeclaration localDeclaration, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(LongLiteral longLiteral, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(MessageSend messageSend, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(NullLiteral nullLiteral, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(PostfixExpression postfixExpression, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(PrefixExpression prefixExpression, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		QualifiedAllocationExpression qualifiedAllocationExpression,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		QualifiedNameReference qualifiedNameReference,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		QualifiedSuperReference qualifiedSuperReference,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		QualifiedThisReference qualifiedThisReference,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		QualifiedTypeReference qualifiedTypeReference,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		QualifiedTypeReference qualifiedTypeReference,
+		ClassScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ReturnStatement returnStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		SingleNameReference singleNameReference,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		SingleTypeReference singleTypeReference,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		SingleTypeReference singleTypeReference,
+		ClassScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(StringLiteral stringLiteral, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(SuperReference superReference, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(SwitchStatement switchStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		SynchronizedStatement synchronizedStatement,
+		BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ThisReference thisReference, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(ThrowStatement throwStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(TrueLiteral trueLiteral, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(TryStatement tryStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		TypeDeclaration localTypeDeclaration,
+		BlockScope scope) {
+		// do nothing by default
+	}	
+	public void endVisit(
+		TypeDeclaration memberTypeDeclaration,
+		ClassScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(
+		TypeDeclaration typeDeclaration,
+		CompilationUnitScope scope) {
+		// do nothing by default
+	}	
+	public void endVisit(UnaryExpression unaryExpression, BlockScope scope) {
+		// do nothing by default
+	}
+	public void endVisit(WhileStatement whileStatement, BlockScope scope) {
+		// do nothing by default
+	}
+	public boolean visit(
+		AllocationExpression allocationExpression,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+		// do nothing by default
+	}
+	public boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocArgumentExpression expression, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocFieldReference fieldRef, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocMessageSend messageSend, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocReturnStatement statement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocSingleNameReference argument, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(Argument argument, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		ArrayAllocationExpression arrayAllocationExpression,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+		ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ArrayReference arrayReference, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(Assignment assignment, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(AssertStatement assertStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(Block block, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(BreakStatement breakStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(CaseStatement caseStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(CastExpression castExpression, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(CharLiteral charLiteral, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ClassLiteralAccess classLiteral, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(Clinit clinit, ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		CompilationUnitDeclaration compilationUnitDeclaration,
+		CompilationUnitScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(CompoundAssignment compoundAssignment, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		ConditionalExpression conditionalExpression,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		ConstructorDeclaration constructorDeclaration,
+		ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ContinueStatement continueStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(DoStatement doStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(EqualExpression equalExpression, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(EmptyStatement emptyStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		ExplicitConstructorCall explicitConstructor,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		ExtendedStringLiteral extendedStringLiteral,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(FalseLiteral falseLiteral, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(FieldReference fieldReference, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(FloatLiteral floatLiteral, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ForStatement forStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(IfStatement ifStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ImportReference importRef, CompilationUnitScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(Initializer initializer, MethodScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		InstanceOfExpression instanceOfExpression,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(IntLiteral intLiteral, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(IteratorForStatement forStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(LongLiteral longLiteral, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(MessageSend messageSend, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(NullLiteral nullLiteral, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(PostfixExpression postfixExpression, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(PrefixExpression prefixExpression, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		QualifiedAllocationExpression qualifiedAllocationExpression,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		QualifiedNameReference qualifiedNameReference,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		QualifiedSuperReference qualifiedSuperReference,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		QualifiedThisReference qualifiedThisReference,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		QualifiedTypeReference qualifiedTypeReference,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		QualifiedTypeReference qualifiedTypeReference,
+		ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ReturnStatement returnStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		SingleNameReference singleNameReference,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		SingleTypeReference singleTypeReference,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		SingleTypeReference singleTypeReference,
+		ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(SuperReference superReference, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(SwitchStatement switchStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		SynchronizedStatement synchronizedStatement,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ThisReference thisReference, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(ThrowStatement throwStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(TrueLiteral trueLiteral, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(TryStatement tryStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		TypeDeclaration localTypeDeclaration,
+		BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(
+		TypeDeclaration memberTypeDeclaration,
+		ClassScope scope) {
+		return true; // do nothing by default, keep traversing
+	}	
+	public boolean visit(
+		TypeDeclaration typeDeclaration,
+		CompilationUnitScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+	public boolean visit(WhileStatement whileStatement, BlockScope scope) {
+		return true; // do nothing by default, keep traversing
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/AbstractSyntaxTreeVisitorAdapter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/AbstractSyntaxTreeVisitorAdapter.java
deleted file mode 100644
index 80be5f6..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/AbstractSyntaxTreeVisitorAdapter.java
+++ /dev/null
@@ -1,495 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.compiler;
-
-import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-/**
- * An adapter class for interating through the parse tree.
- */
-
-public class AbstractSyntaxTreeVisitorAdapter implements IAbstractSyntaxTreeVisitor {
-
-	public void acceptProblem(IProblem problem) {}
-	public void endVisit(
-		AllocationExpression allocationExpression,
-		BlockScope scope) {
-	}
-	public void endVisit(AND_AND_Expression and_and_Expression, BlockScope scope) {
-	}
-	public void endVisit(
-		AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
-		BlockScope scope) {
-	}
-	public void endVisit(Argument argument, BlockScope scope) {
-	}
-	public void endVisit(
-		ArrayAllocationExpression arrayAllocationExpression,
-		BlockScope scope) {
-	}
-	public void endVisit(ArrayInitializer arrayInitializer, BlockScope scope) {
-	}
-	public void endVisit(
-		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
-		BlockScope scope) {
-	}
-	public void endVisit(
-		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
-		ClassScope scope) {
-	}
-	public void endVisit(ArrayReference arrayReference, BlockScope scope) {
-	}
-	public void endVisit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
-	}
-	public void endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
-	}
-	public void endVisit(Assignment assignment, BlockScope scope) {
-	}
-	public void endVisit(AssertStatement assertStatement, BlockScope scope) {
-	}
-	public void endVisit(BinaryExpression binaryExpression, BlockScope scope) {
-	}
-	public void endVisit(Block block, BlockScope scope) {
-	}
-	public void endVisit(Break breakStatement, BlockScope scope) {
-	}
-	public void endVisit(Case caseStatement, BlockScope scope) {
-	}
-	public void endVisit(CastExpression castExpression, BlockScope scope) {
-	}
-	public void endVisit(CharLiteral charLiteral, BlockScope scope) {
-	}
-	public void endVisit(ClassLiteralAccess classLiteral, BlockScope scope) {
-	}
-	public void endVisit(Clinit clinit, ClassScope scope) {
-	}
-	public void endVisit(
-		CompilationUnitDeclaration compilationUnitDeclaration,
-		CompilationUnitScope scope) {
-	}
-	public void endVisit(CompoundAssignment compoundAssignment, BlockScope scope) {
-	}
-	public void endVisit(
-		ConditionalExpression conditionalExpression,
-		BlockScope scope) {
-	}
-	public void endVisit(
-		ConstructorDeclaration constructorDeclaration,
-		ClassScope scope) {
-	}
-	public void endVisit(Continue continueStatement, BlockScope scope) {
-	}
-	public void endVisit(DefaultCase defaultCaseStatement, BlockScope scope) {
-	}
-	public void endVisit(DoStatement doStatement, BlockScope scope) {
-	}
-	public void endVisit(DoubleLiteral doubleLiteral, BlockScope scope) {
-	}
-	public void endVisit(EqualExpression equalExpression, BlockScope scope) {
-	}
-	public void endVisit(
-		ExplicitConstructorCall explicitConstructor,
-		BlockScope scope) {
-	}
-	public void endVisit(
-		ExtendedStringLiteral extendedStringLiteral,
-		BlockScope scope) {
-	}
-	public void endVisit(FalseLiteral falseLiteral, BlockScope scope) {
-	}
-	public void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope) {
-	}
-	public void endVisit(FieldReference fieldReference, BlockScope scope) {
-	}
-	public void endVisit(FloatLiteral floatLiteral, BlockScope scope) {
-	}
-	public void endVisit(EmptyStatement emptyStatement, BlockScope scope) {
-	}
-	public void endVisit(ForStatement forStatement, BlockScope scope) {
-	}
-	public void endVisit(IfStatement ifStatement, BlockScope scope) {
-	}
-	public void endVisit(ImportReference importRef, CompilationUnitScope scope) {
-	}
-	public void endVisit(Initializer initializer, MethodScope scope) {
-	}
-	public void endVisit(
-		InstanceOfExpression instanceOfExpression,
-		BlockScope scope) {
-	}
-	public void endVisit(IntLiteral intLiteral, BlockScope scope) {
-	}
-	public void endVisit(LabeledStatement labeledStatement, BlockScope scope) {
-	}
-	public void endVisit(LocalDeclaration localDeclaration, BlockScope scope) {
-	}
-	public void endVisit(LongLiteral longLiteral, BlockScope scope) {
-	}
-	public void endVisit(
-		MemberTypeDeclaration memberTypeDeclaration,
-		ClassScope scope) {
-	}
-	public void endVisit(MessageSend messageSend, BlockScope scope) {
-	}
-	public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) {
-	}
-	public void endVisit(NullLiteral nullLiteral, BlockScope scope) {
-	}
-	public void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope) {
-	}
-	public void endVisit(PostfixExpression postfixExpression, BlockScope scope) {
-	}
-	public void endVisit(PrefixExpression prefixExpression, BlockScope scope) {
-	}
-	public void endVisit(
-		QualifiedAllocationExpression qualifiedAllocationExpression,
-		BlockScope scope) {
-	}
-	public void endVisit(
-		QualifiedNameReference qualifiedNameReference,
-		BlockScope scope) {
-	}
-	public void endVisit(
-		QualifiedSuperReference qualifiedSuperReference,
-		BlockScope scope) {
-	}
-	public void endVisit(
-		QualifiedThisReference qualifiedThisReference,
-		BlockScope scope) {
-	}
-	public void endVisit(
-		QualifiedTypeReference qualifiedTypeReference,
-		BlockScope scope) {
-	}
-	public void endVisit(
-		QualifiedTypeReference qualifiedTypeReference,
-		ClassScope scope) {
-	}
-	public void endVisit(ReturnStatement returnStatement, BlockScope scope) {
-	}
-	public void endVisit(
-		SingleNameReference singleNameReference,
-		BlockScope scope) {
-	}
-	public void endVisit(
-		SingleTypeReference singleTypeReference,
-		BlockScope scope) {
-	}
-	public void endVisit(
-		SingleTypeReference singleTypeReference,
-		ClassScope scope) {
-	}
-	public void endVisit(StringLiteral stringLiteral, BlockScope scope) {
-	}
-	public void endVisit(SuperReference superReference, BlockScope scope) {
-	}
-	public void endVisit(SwitchStatement switchStatement, BlockScope scope) {
-	}
-	public void endVisit(
-		SynchronizedStatement synchronizedStatement,
-		BlockScope scope) {
-	}
-	public void endVisit(ThisReference thisReference, BlockScope scope) {
-	}
-	public void endVisit(ThrowStatement throwStatement, BlockScope scope) {
-	}
-	public void endVisit(TrueLiteral trueLiteral, BlockScope scope) {
-	}
-	public void endVisit(TryStatement tryStatement, BlockScope scope) {
-	}
-	public void endVisit(
-		TypeDeclaration typeDeclaration,
-		CompilationUnitScope scope) {
-	}
-	public void endVisit(UnaryExpression unaryExpression, BlockScope scope) {
-	}
-	public void endVisit(WhileStatement whileStatement, BlockScope scope) {
-	}
-	public boolean visit(
-		AllocationExpression allocationExpression,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(Argument argument, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		ArrayAllocationExpression arrayAllocationExpression,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
-		ClassScope scope) {
-		return true;
-	}
-	public boolean visit(ArrayReference arrayReference, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
-		return true;
-	}
-	public boolean visit(Assignment assignment, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(AssertStatement assertStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(Block block, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(Break breakStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(Case caseStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(CastExpression castExpression, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(CharLiteral charLiteral, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(ClassLiteralAccess classLiteral, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(Clinit clinit, ClassScope scope) {
-		return true;
-	}
-	public boolean visit(
-		CompilationUnitDeclaration compilationUnitDeclaration,
-		CompilationUnitScope scope) {
-		return true;
-	}
-	public boolean visit(CompoundAssignment compoundAssignment, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		ConditionalExpression conditionalExpression,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		ConstructorDeclaration constructorDeclaration,
-		ClassScope scope) {
-		return true;
-	}
-	public boolean visit(Continue continueStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(DefaultCase defaultCaseStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(DoStatement doStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(EqualExpression equalExpression, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(EmptyStatement emptyStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		ExplicitConstructorCall explicitConstructor,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		ExtendedStringLiteral extendedStringLiteral,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(FalseLiteral falseLiteral, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
-		return true;
-	}
-	public boolean visit(FieldReference fieldReference, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(FloatLiteral floatLiteral, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(ForStatement forStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(IfStatement ifStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(ImportReference importRef, CompilationUnitScope scope) {
-		return true;
-	}
-	public boolean visit(Initializer initializer, MethodScope scope) {
-		return true;
-	}
-	public boolean visit(
-		InstanceOfExpression instanceOfExpression,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(IntLiteral intLiteral, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(LongLiteral longLiteral, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		MemberTypeDeclaration memberTypeDeclaration,
-		ClassScope scope) {
-		return true;
-	}
-	public boolean visit(MessageSend messageSend, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
-		return true;
-	}
-	public boolean visit(NullLiteral nullLiteral, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(PostfixExpression postfixExpression, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(PrefixExpression prefixExpression, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		QualifiedAllocationExpression qualifiedAllocationExpression,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		QualifiedNameReference qualifiedNameReference,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		QualifiedSuperReference qualifiedSuperReference,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		QualifiedThisReference qualifiedThisReference,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		QualifiedTypeReference qualifiedTypeReference,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		QualifiedTypeReference qualifiedTypeReference,
-		ClassScope scope) {
-		return true;
-	}
-	public boolean visit(ReturnStatement returnStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		SingleNameReference singleNameReference,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		SingleTypeReference singleTypeReference,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		SingleTypeReference singleTypeReference,
-		ClassScope scope) {
-		return true;
-	}
-	public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(SuperReference superReference, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(SwitchStatement switchStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		SynchronizedStatement synchronizedStatement,
-		BlockScope scope) {
-		return true;
-	}
-	public boolean visit(ThisReference thisReference, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(ThrowStatement throwStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(TrueLiteral trueLiteral, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(TryStatement tryStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		TypeDeclaration typeDeclaration,
-		CompilationUnitScope scope) {
-		return true;
-	}
-	public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(WhileStatement whileStatement, BlockScope scope) {
-		return true;
-	}
-	public boolean visit(
-		LocalTypeDeclaration localTypeDeclaration,
-		BlockScope scope) {
-		return true;
-	}
-	public void endVisit(
-		LocalTypeDeclaration localTypeDeclaration,
-		BlockScope scope) {
-	}
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index d01f2cc..d4b9a6e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -16,12 +16,13 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.impl.StringConstant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 /**
@@ -73,6 +74,7 @@
 	 * This methods creates a new instance of the receiver.
 	 */
 	public ClassFile() {
+		// default constructor for subclasses
 	}
 
 	/**
@@ -94,35 +96,15 @@
 		header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
 		header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
 		header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
-		switch(((SourceTypeBinding) referenceBinding).scope.environment().options.targetJDK) {
-			case CompilerOptions.JDK1_4 :
-				// Compatible with JDK 1.4
-				header[headerOffset++] = 0;
-				header[headerOffset++] = 0;
-				header[headerOffset++] = 0;
-				header[headerOffset++] = 48;
-				break;
-			case CompilerOptions.JDK1_3 :
-				// Compatible with JDK 1.3
-				header[headerOffset++] = 0;
-				header[headerOffset++] = 0;
-				header[headerOffset++] = 0;
-				header[headerOffset++] = 47;
-				break;
-			case CompilerOptions.JDK1_2 :
-				// Compatible with JDK 1.2
-				header[headerOffset++] = 0;
-				header[headerOffset++] = 0;
-				header[headerOffset++] = 0;
-				header[headerOffset++] = 46;
-				break;
-			case CompilerOptions.JDK1_1 :
-				// Compatible with JDK 1.1
-				header[headerOffset++] = 0;
-				header[headerOffset++] = 3;
-				header[headerOffset++] = 0;
-				header[headerOffset++] = 45;
-		}
+		
+		long targetJDK = referenceBinding.scope.environment().options.targetJDK;
+		// TODO[1.5]  until a 1.5 VM is released (accepting 49.0 files), will instead generate 1.4 (48.0) classfiles
+		if (targetJDK == ClassFileConstants.JDK1_5) targetJDK = ClassFileConstants.JDK1_4;
+		header[headerOffset++] = (byte) (targetJDK >> 8); // minor high
+		header[headerOffset++] = (byte) (targetJDK >> 0); // minor low
+		header[headerOffset++] = (byte) (targetJDK >> 24); // major high
+		header[headerOffset++] = (byte) (targetJDK >> 16); // major low
+
 		constantPoolOffset = headerOffset;
 		headerOffset += 2;
 		constantPool = new ConstantPool(this);
@@ -146,7 +128,9 @@
 					| AccNative);
 					
 		// set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
-		accessFlags |= AccSuper;
+		if (aType.isClass()) {
+			accessFlags |= AccSuper;
+		}
 		
 		this.enclosingClassFile = enclosingClassFile;
 		// innerclasses get their names computed at code gen time
@@ -171,19 +155,12 @@
 		int interfacesCount = superInterfacesBinding.length;
 		contents[contentsOffset++] = (byte) (interfacesCount >> 8);
 		contents[contentsOffset++] = (byte) interfacesCount;
-		if (superInterfacesBinding != null) {
-			for (int i = 0; i < interfacesCount; i++) {
-				int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
-				contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
-				contents[contentsOffset++] = (byte) interfaceIndex;
-			}
+		for (int i = 0; i < interfacesCount; i++) {
+			int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
+			contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
+			contents[contentsOffset++] = (byte) interfaceIndex;
 		}
-		produceDebugAttributes =
-			((SourceTypeBinding) referenceBinding)
-				.scope
-				.environment()
-				.options
-				.produceDebugAttributes;
+		produceDebugAttributes = referenceBinding.scope.environment().options.produceDebugAttributes;
 		innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
 		this.creatingProblemType = creatingProblemType;
 		codeStream = new CodeStream(this);
@@ -577,10 +554,10 @@
 	 * have to be generated for the inner classes attributes.
 	 * @param referenceBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding 
 	 */
-	public void addInnerClasses(ReferenceBinding referenceBinding) {
+	public void addInnerClasses(ReferenceBinding refBinding) {
 		// check first if that reference binding is there
 		for (int i = 0; i < numberOfInnerClasses; i++) {
-			if (innerClassesBindings[i] == referenceBinding)
+			if (innerClassesBindings[i] == refBinding)
 				return;
 		}
 		int length = innerClassesBindings.length;
@@ -592,7 +569,7 @@
 				0,
 				length);
 		}
-		innerClassesBindings[numberOfInnerClasses++] = referenceBinding;
+		innerClassesBindings[numberOfInnerClasses++] = refBinding;
 	}
 
 	/**
@@ -674,7 +651,6 @@
 		attributeNumber++;
 		int codeAttributeOffset = contentsOffset;
 		generateCodeAttributeHeader();
-		final ProblemReporter problemReporter = method.scope.problemReporter();
 		codeStream.reset(method, this);
 		String problemString = "" ; //$NON-NLS-1$
 		if (problems != null) {
@@ -747,7 +723,7 @@
 		MethodBinding methodBinding,
 		IProblem[] problems) {
 		if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
-			method.abort(AbstractMethodDeclaration.AbortType);
+			method.abort(ProblemSeverities.AbortType);
 		}
 		// always clear the strictfp/native/abstract bit for a problem method
 		methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
@@ -761,7 +737,6 @@
 		
 		int codeAttributeOffset = contentsOffset;
 		generateCodeAttributeHeader();
-		final ProblemReporter problemReporter = method.scope.problemReporter();
 		codeStream.reset(method, this);
 		String problemString = "" ; //$NON-NLS-1$
 		if (problems != null) {
@@ -922,7 +897,6 @@
 		String problemString = buffer.toString();
 		this.problemLine = problem.getSourceLineNumber();
 		
-		final ProblemReporter problemReporter = methodDeclaration.scope.problemReporter();
 		codeStream.init(this);
 		codeStream.preserveUnusedLocals = true;
 		codeStream.initializeMaxLocals(methodBinding);
@@ -970,6 +944,7 @@
 				0,
 				contentsLength);
 		}
+
 		localContents[localContentsOffset++] = 0;
 		localContents[localContentsOffset++] = 0;
 		// debug attributes
@@ -1321,7 +1296,7 @@
 				localContents[localContentsOffset++] = 0;
 			} else {
 				int nameIndex;
-				if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
+				if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
 					/* represents ClassNotFoundException, see class literal access*/
 					nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
 				} else {
@@ -1448,7 +1423,7 @@
 						if (endPC == -1) {
 							localVariable.declaringScope.problemReporter().abortDueToInternalError(
 								Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
-								(AstNode) localVariable.declaringScope.methodScope().referenceContext);
+								(ASTNode) localVariable.declaringScope.methodScope().referenceContext);
 						}
 						if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
 							System.arraycopy(
@@ -1592,7 +1567,7 @@
 				localContents[localContentsOffset++] = 0;
 			} else {
 				int nameIndex;
-				if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
+				if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
 					/* represents denote ClassNotFoundException, see class literal access*/
 					nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
 				} else {
@@ -1697,7 +1672,7 @@
 							if (endPC == -1) {
 								localVariable.declaringScope.problemReporter().abortDueToInternalError(
 									Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
-									(AstNode) localVariable.declaringScope.methodScope().referenceContext);
+									(ASTNode) localVariable.declaringScope.methodScope().referenceContext);
 							}
 							if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
 								System.arraycopy(
@@ -1812,6 +1787,7 @@
 		// write the exception table
 		localContents[localContentsOffset++] = 0;
 		localContents[localContentsOffset++] = 0;
+
 		// debug attributes
 		int codeAttributeAttributeOffset = localContentsOffset;
 		int attributeNumber = 0; // leave two bytes for the attribute_length
@@ -1939,9 +1915,10 @@
 				0,
 				contentsLength);
 		}
+
+		// write the exception table
 		localContents[localContentsOffset++] = 0;
 		localContents[localContentsOffset++] = 0;
-		
 		// debug attributes
 		int codeAttributeAttributeOffset = localContentsOffset;
 		int attributeNumber = 0; // leave two bytes for the attribute_length
@@ -2099,8 +2076,8 @@
 						localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
 						localContents[localContentsOffset++] = (byte) descriptorIndex;
 						int resolvedPosition = argSize;
-						if ((argumentBinding == TypeBinding.LongBinding)
-							|| (argumentBinding == TypeBinding.DoubleBinding))
+						if ((argumentBinding == BaseTypes.LongBinding)
+							|| (argumentBinding == BaseTypes.DoubleBinding))
 							argSize += 2;
 						else
 							argSize++;
@@ -2249,7 +2226,7 @@
 						if (endPC == -1) {
 							localVariable.declaringScope.problemReporter().abortDueToInternalError(
 								Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
-								(AstNode) localVariable.declaringScope.methodScope().referenceContext);
+								(ASTNode) localVariable.declaringScope.methodScope().referenceContext);
 						}
 						if (localContentsOffset + 10 > (contentsLength = contents.length)) {
 							System.arraycopy(
@@ -2338,8 +2315,8 @@
 		SourceTypeBinding typeBinding = typeDeclaration.binding;
 		ClassFile classFile = new ClassFile(typeBinding, null, true);
 
-		// TODO: (olivier) handle cases where a field cannot be generated (name too long)
-		// TODO: (olivier) handle too many methods
+		// TODO (olivier) handle cases where a field cannot be generated (name too long)
+		// TODO (olivier) handle too many methods
 		// inner attributes
 		if (typeBinding.isMemberType())
 			classFile.recordEnclosingTypeAttributes(typeBinding);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
index 3bcbacd..e9f03b1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
@@ -115,18 +115,18 @@
 
 	
 	public IProblem[] getAllProblems() {
-		IProblem[] problems = this.getProblems();
-		int problemCount = problems != null ? problems.length : 0;
-		IProblem[] tasks = this.getTasks();
-		int taskCount = tasks != null ? tasks.length : 0;
-		if (taskCount == 0) {
-			return problems;
+		IProblem[] onlyProblems = this.getProblems();
+		int onlyProblemCount = onlyProblems != null ? onlyProblems.length : 0;
+		IProblem[] onlyTasks = this.getTasks();
+		int onlyTaskCount = onlyTasks != null ? onlyTasks.length : 0;
+		if (onlyTaskCount == 0) {
+			return onlyProblems;
 		}
-		if (problemCount == 0) {
-			return tasks;
+		if (onlyProblemCount == 0) {
+			return onlyTasks;
 		}
 
-		int totalNumberOfProblem = problemCount + taskCount;
+		int totalNumberOfProblem = onlyProblemCount + onlyTaskCount;
 		IProblem[] allProblems = new IProblem[totalNumberOfProblem];
 		int allProblemIndex = 0;
 		int taskIndex = 0;
@@ -134,11 +134,11 @@
 		while (taskIndex + problemIndex < totalNumberOfProblem) {
 			IProblem nextTask = null;
 			IProblem nextProblem = null;
-			if (taskIndex < taskCount) {
-				nextTask = tasks[taskIndex];
+			if (taskIndex < onlyTaskCount) {
+				nextTask = onlyTasks[taskIndex];
 			}
-			if (problemIndex < problemCount) {
-				nextProblem = problems[problemIndex];
+			if (problemIndex < onlyProblemCount) {
+				nextProblem = onlyProblems[problemIndex];
 			}
 			// select the next problem
 			IProblem currentProblem = null;
@@ -195,16 +195,16 @@
 	 */
 	public IProblem[] getErrors() {
 	
-		IProblem[] problems = getProblems();
+		IProblem[] reportedProblems = getProblems();
 		int errorCount = 0;
 		for (int i = 0; i < this.problemCount; i++) {
-			if (problems[i].isError()) errorCount++;
+			if (reportedProblems[i].isError()) errorCount++;
 		}
-		if (errorCount == this.problemCount) return problems;
+		if (errorCount == this.problemCount) return reportedProblems;
 		IProblem[] errors = new IProblem[errorCount];
 		int index = 0;
 		for (int i = 0; i < this.problemCount; i++) {
-			if (problems[i].isError()) errors[index++] = problems[i];
+			if (reportedProblems[i].isError()) errors[index++] = reportedProblems[i];
 		}
 		return errors;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
index 607a993..09642e9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
@@ -109,11 +109,7 @@
 			new ProblemReporter(policy, this.options, problemFactory);
 		this.lookupEnvironment =
 			new LookupEnvironment(this, options, problemReporter, environment);
-		this.parser =
-			new Parser(
-				problemReporter, 
-				this.options.parseLiteralExpressionsAsConstants, 
-				options.sourceLevel >= CompilerOptions.JDK1_4);
+		initializeParser();
 	}
 	
 	/**
@@ -176,15 +172,9 @@
 				}
 			};
 		}
-		this.problemReporter =
-			new ProblemReporter(policy, this.options, problemFactory);
-		this.lookupEnvironment =
-			new LookupEnvironment(this, options, problemReporter, environment);
-		this.parser =
-			new Parser(
-				problemReporter, 
-				parseLiteralExpressionsAsConstants, 
-				this.options.sourceLevel >= CompilerOptions.JDK1_4);
+		this.problemReporter = new ProblemReporter(policy, this.options, problemFactory);
+		this.lookupEnvironment = new LookupEnvironment(this, options, problemReporter, environment);
+		initializeParser();
 	}
 	
 	/**
@@ -245,7 +235,7 @@
 	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
 		problemReporter.abortDueToInternalError(
 			Util.bind(
-				"abort.againstSourceModel " , //$NON-NLS-1$
+				"abort.againstSourceModel" , //$NON-NLS-1$
 				String.valueOf(sourceTypes[0].getName()),
 				String.valueOf(sourceTypes[0].getFileName())));
 	}
@@ -371,27 +361,6 @@
 		}
 	}
 
-	protected void getMethodBodies(CompilationUnitDeclaration unit, int place) {
-		//fill the methods bodies in order for the code to be generated
-
-		if (unit.ignoreMethodBodies) {
-			unit.ignoreFurtherInvestigation = true;
-			return;
-			// if initial diet parse did not work, no need to dig into method bodies.
-		}
-
-		if (place < parseThreshold)
-			return; //work already done ...
-
-		//real parse of the method....
-		parser.scanner.setSource(
-			unit.compilationResult.compilationUnit.getContents());
-		if (unit.types != null) {
-			for (int i = unit.types.length; --i >= 0;)
-				unit.types[i].parseMethod(parser, unit);
-		}
-	}
-
 	/*
 	 * Compiler crash recovery in case of unexpected runtime exceptions
 	 */
@@ -400,9 +369,6 @@
 		CompilationUnitDeclaration unit,
 		CompilationResult result) {
 
-		/* dump a stack trace to the console */
-		internalException.printStackTrace();
-
 		/* find a compilation result */
 		if ((unit != null)) // basing result upon the current unit if available
 			result = unit.compilationResult; // current unit being processed ?
@@ -410,6 +376,7 @@
 			result = unitsToProcess[totalUnits - 1].compilationResult;
 		// last unit in beginToCompile ?
 
+		boolean needToPrint = true;
 		if (result != null) {
 			/* create and record a compilation problem */
 			StringWriter stringWriter = new StringWriter();
@@ -441,8 +408,13 @@
 			/* hand back the compilation result */
 			if (!result.hasBeenAccepted) {
 				requestor.acceptResult(result.tagAsAccepted());
+				needToPrint = false;
 			}
 		}
+		if (needToPrint) {
+			/* dump a stack trace to the console */
+			internalException.printStackTrace();
+		}
 	}
 
 	/*
@@ -519,12 +491,17 @@
 		}
 	}
 
+	public void initializeParser() {
+
+		this.parser = new Parser(this.problemReporter, this.options.parseLiteralExpressionsAsConstants);
+	}
+	
 	/**
 	 * Process a compilation unit already parsed and build.
 	 */
 	public void process(CompilationUnitDeclaration unit, int i) {
 
-		getMethodBodies(unit, i);
+		this.parser.getMethodBodies(unit);
 
 		// fault in fields & methods
 		if (unit.scope != null)
@@ -561,19 +538,27 @@
 	 * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
 	 */
 	public CompilationUnitDeclaration resolve(
+			CompilationUnitDeclaration unit, 
 			ICompilationUnit sourceUnit, 
 			boolean verifyMethods,
 			boolean analyzeCode,
 			boolean generateCode) {
 				
-		CompilationUnitDeclaration unit = null;
 		try {
-			// build and record parsed units
-			parseThreshold = 0; // will request a full parse
-			beginToCompile(new ICompilationUnit[] { sourceUnit });
-			// process all units (some more could be injected in the loop by the lookup environment)
-			unit = unitsToProcess[0];
-			getMethodBodies(unit, 0);
+			if (unit == null) {
+				// build and record parsed units
+				parseThreshold = 0; // will request a full parse
+				beginToCompile(new ICompilationUnit[] { sourceUnit });
+				// process all units (some more could be injected in the loop by the lookup environment)
+				unit = unitsToProcess[0];
+			} else {
+				// initial type binding creation
+				lookupEnvironment.buildTypeBindings(unit);
+
+				// binding resolution
+				lookupEnvironment.completeTypeBindings();
+			}
+			this.parser.getMethodBodies(unit);
 			if (unit.scope != null) {
 				// fault in fields & methods
 				unit.scope.faultInTypes();
@@ -591,7 +576,7 @@
 				// code generation
 				if (generateCode) unit.generateCode();
 			}
-			unitsToProcess[0] = null; // release reference to processed unit declaration
+			if (unitsToProcess != null) unitsToProcess[0] = null; // release reference to processed unit declaration
 			requestor.acceptResult(unit.compilationResult.tagAsAccepted());
 			return unit;
 		} catch (AbortCompilation e) {
@@ -613,4 +598,20 @@
 			// this.reset();
 		}
 	}
+	/**
+	 * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+	 */
+	public CompilationUnitDeclaration resolve(
+			ICompilationUnit sourceUnit, 
+			boolean verifyMethods,
+			boolean analyzeCode,
+			boolean generateCode) {
+				
+		return resolve(
+			null,
+			sourceUnit,
+			verifyMethods,
+			analyzeCode,
+			generateCode);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
index 24b6163..343b80b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
@@ -62,14 +62,14 @@
 			requestor.acceptProblem(problem);
 		}
 	},
-	false,
-	options.sourceLevel >= CompilerOptions.JDK1_4);
+	false);
 	this.requestor = requestor;
 	intArrayStack = new int[30][];
 	this.options = options;
+	this.javadocParser.checkJavadoc = false;
 }
 
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -83,33 +83,30 @@
  * Additionally, before investigating for @deprecated, retrieve the positions
  * of the JavaDoc comments so as to notify requestor with them.
  */
-public void checkAnnotation() {
+public void checkComment() {
 
 	/* persisting javadoc positions */
 	pushOnIntArrayStack(this.getJavaDocPositions());
 	boolean deprecated = false;
-	int lastAnnotationIndex = -1;
+	int lastCommentIndex = -1;
 	int commentPtr = scanner.commentPtr;
 
 	//since jdk1.2 look only in the last java doc comment...
-	nextComment : for (lastAnnotationIndex = scanner.commentPtr; lastAnnotationIndex >= 0; lastAnnotationIndex--){
+	nextComment : for (lastCommentIndex = scanner.commentPtr; lastCommentIndex >= 0; lastCommentIndex--){
 		//look for @deprecated into the first javadoc comment preceeding the declaration
-		int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
+		int commentSourceStart = scanner.commentStarts[lastCommentIndex];
 		// javadoc only (non javadoc comment have negative end positions.)
 		if (modifiersSourceStart != -1 && modifiersSourceStart < commentSourceStart) {
 			continue nextComment;
 		}
-		if (scanner.commentStops[lastAnnotationIndex] < 0) {
+		if (scanner.commentStops[lastCommentIndex] < 0) {
 			continue nextComment;
 		}
-		int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1; //stop is one over
-		char[] comment = scanner.source;
-
+		int commentSourceEnd = scanner.commentStops[lastCommentIndex] - 1; //stop is one over
 		deprecated =
-			checkDeprecation(
+			this.javadocParser.checkDeprecation(
 				commentSourceStart,
-				commentSourceEnd,
-				comment);
+				commentSourceEnd);
 		break nextComment;
 	}
 	if (deprecated) {
@@ -120,7 +117,7 @@
 		declarationSourceStart = scanner.commentStarts[0];
 	}
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -140,7 +137,7 @@
 		initializer.block.sourceStart,
 		initializer.block.sourceEnd);
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -154,7 +151,7 @@
 	requestor.exitClass(endStatementPosition, // '}' is the end of the body 
 	 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -225,16 +222,14 @@
 }
 protected void consumeClassHeaderName() {
 	// ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
-	TypeDeclaration typeDecl;
+	TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
 	if (nestedMethod[nestedType] == 0) {
 		if (nestedType != 0) {
-			typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
-		} else {
-			typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+			typeDecl.bits |= ASTNode.IsMemberTypeMASK;
 		}
 	} else {
 		// Record that the block has a declaration for local types
-		typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+		typeDecl.bits |= ASTNode.IsLocalTypeMASK;
 		markEnclosingMemberWithLocalType();
 		blockReal();
 	}
@@ -250,16 +245,19 @@
 	// 'class' and 'interface' push an int position
 	typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
 	intPtr--;
-	int declarationSourceStart = intStack[intPtr--];
+	int declSourceStart = intStack[intPtr--];
 	typeDecl.modifiersSourceStart = intStack[intPtr--];
 	typeDecl.modifiers = intStack[intPtr--];
-	if (typeDecl.declarationSourceStart > declarationSourceStart) {
-		typeDecl.declarationSourceStart = declarationSourceStart;
+	if (typeDecl.declarationSourceStart > declSourceStart) {
+		typeDecl.declarationSourceStart = declSourceStart;
 	}
 	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
 	pushOnAstStack(typeDecl);
+	// javadoc
+	typeDecl.javadoc = this.javadoc;
+	this.javadoc = null;
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -267,7 +265,7 @@
 	// CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
 	requestor.exitCompilationUnit(scanner.source.length - 1);
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -281,7 +279,7 @@
 	ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
 	requestor.exitConstructor(endStatementPosition, cd.declarationSourceEnd);
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -372,6 +370,9 @@
 	cd.declarationSourceStart = intStack[intPtr--];
 	cd.modifiersSourceStart = intStack[intPtr--];
 	cd.modifiers = intStack[intPtr--];
+	// javadoc
+	cd.javadoc = this.javadoc;
+	this.javadoc = null;
 
 	//highlight starts at the selector starts
 	cd.sourceStart = (int) (selectorSourcePositions >>> 32);
@@ -381,7 +382,7 @@
 	cd.bodyStart = lParenPos + 1;
 }
 protected void consumeDefaultModifiers() {
-	checkAnnotation(); // might update modifiers with AccDeprecated
+	checkComment(); // might update modifiers with AccDeprecated
 	pushOnIntStack(modifiers); // modifiers
 	pushOnIntStack(-1);
 	pushOnIntStack(
@@ -396,7 +397,7 @@
 	 */
 	pushOnIntArrayStack(this.getJavaDocPositions());	
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -404,7 +405,7 @@
 	// EnterCompilationUnit ::= $empty
 	requestor.enterCompilationUnit();
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -414,7 +415,7 @@
 	if (!isLocalDeclaration && (variablesCounter[nestedType] != 0)) {
 		requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
 	}
-	char[] name = identifierStack[identifierPtr];
+	char[] varName = identifierStack[identifierPtr];
 	long namePosition = identifierPositionStack[identifierPtr--];
 	int extendedTypeDimension = intStack[intPtr--];
 
@@ -422,11 +423,11 @@
 	if (nestedMethod[nestedType] != 0) {
 		// create the local variable declarations
 		declaration = 
-			new LocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition); 
+			new LocalDeclaration(varName, (int) (namePosition >>> 32), (int) namePosition); 
 	} else {
 		// create the field declaration
 		declaration = 
-			new FieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition); 
+			new FieldDeclaration(varName, (int) (namePosition >>> 32), (int) namePosition); 
 	}
 	identifierLengthPtr--;
 	TypeReference type;
@@ -492,14 +493,14 @@
 				type.sourceStart, 
 				type.sourceEnd, 
 				typeDims, 
-				name, 
+				varName, 
 				(int) (namePosition >>> 32), 
 				(int) namePosition, 
 				extendedTypeDimension, 
 				extendedTypeDimension == 0 ? -1 : endPosition); 
 	}
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -520,7 +521,7 @@
 	lastFieldEndPosition = scanner.currentPosition - 1;
 	lastFieldBodyEndPosition = scanner.startPosition - 1;
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -551,20 +552,20 @@
 	*/
 
 	identifierLengthPtr--;
-	char[] name = identifierStack[identifierPtr];
+	char[] parameterName = identifierStack[identifierPtr];
 	long namePositions = identifierPositionStack[identifierPtr--];
 	TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
 	intPtr -= 3;
 	Argument arg = 
 		new Argument(
-			name, 
+			parameterName, 
 			namePositions, 
 			type, 
 			intStack[intPtr + 1]); // modifiers
 	pushOnAstStack(arg);
 	intArrayPtr--;
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -578,7 +579,7 @@
 	requestor.exitInterface(endStatementPosition, // the '}' is the end of the body
 	 ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -628,16 +629,14 @@
 }
 protected void consumeInterfaceHeaderName() {
 	// InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
-	TypeDeclaration typeDecl;
+	TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
 	if (nestedMethod[nestedType] == 0) {
 		if (nestedType != 0) {
-			typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
-		} else {
-			typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+			typeDecl.bits |= ASTNode.IsMemberTypeMASK;
 		}
 	} else {
 		// Record that the block has a declaration for local types
-		typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+		typeDecl.bits |= ASTNode.IsLocalTypeMASK;
 		markEnclosingMemberWithLocalType();
 		blockReal();
 	}
@@ -653,16 +652,19 @@
 	// 'class' and 'interface' push an int position
 	typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
 	intPtr--;
-	int declarationSourceStart = intStack[intPtr--];
+	int declSourceStart = intStack[intPtr--];
 	typeDecl.modifiersSourceStart = intStack[intPtr--];
 	typeDecl.modifiers = intStack[intPtr--];
-	if (typeDecl.declarationSourceStart > declarationSourceStart) {
-		typeDecl.declarationSourceStart = declarationSourceStart;
+	if (typeDecl.declarationSourceStart > declSourceStart) {
+		typeDecl.declarationSourceStart = declSourceStart;
 	}
 	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
 	pushOnAstStack(typeDecl);
+	// javadoc
+	typeDecl.javadoc = this.javadoc;
+	this.javadoc = null;
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -673,7 +675,7 @@
 	super.consumeLocalVariableDeclaration();
 	intArrayPtr--;
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -688,7 +690,7 @@
 	MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
 	requestor.exitMethod(endStatementPosition, md.declarationSourceEnd);
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -814,6 +816,9 @@
 	md.declarationSourceStart = intStack[intPtr--];
 	md.modifiersSourceStart = intStack[intPtr--];
 	md.modifiers = intStack[intPtr--];
+	// javadoc
+	md.javadoc = this.javadoc;
+	this.javadoc = null;
 
 	//highlight starts at selector start
 	md.sourceStart = (int) (selectorSourcePositions >>> 32);
@@ -821,14 +826,14 @@
 	md.bodyStart = scanner.currentPosition-1;
 }
 protected void consumeModifiers() {
-	checkAnnotation(); // might update modifiers with AccDeprecated
+	checkComment(); // might update modifiers with AccDeprecated
 	pushOnIntStack(modifiers); // modifiers
 	pushOnIntStack(modifiersSourceStart);
 	pushOnIntStack(
 		declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
 	resetModifiers();
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -847,7 +852,7 @@
 		importReference.sourceStart);
 }
 protected void consumePushModifiers() {
-	checkAnnotation(); // might update modifiers with AccDeprecated
+	checkComment(); // might update modifiers with AccDeprecated
 	pushOnIntStack(modifiers); // modifiers
 	if (modifiersSourceStart < 0) {
 		pushOnIntStack(-1);
@@ -860,7 +865,7 @@
 	}
 	resetModifiers();
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -880,7 +885,7 @@
 		importReference.sourceStart,
 		false);
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -901,15 +906,16 @@
 }
 protected void consumeStaticOnly() {
 	// StaticOnly ::= 'static'
-	checkAnnotation(); // might update declaration source start
+	checkComment(); // might update declaration source start
 	pushOnIntStack(modifiersSourceStart);
+	pushOnIntStack(scanner.currentPosition);
 	pushOnIntStack(
 		declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart); 
 	jumpOverMethodBody();
 	nestedMethod[nestedType]++;
 	resetModifiers();
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -936,9 +942,9 @@
 	return super.endParse(act);
 }
 /*
- * Flush annotations defined prior to a given positions.
+ * Flush javadocs defined prior to a given positions.
  *
- * Note: annotations are stacked in syntactical order
+ * Note: javadocs are stacked in syntactical order
  *
  * Either answer given <position>, or the end position of a comment line 
  * immediately following the <position> (same line)
@@ -948,9 +954,9 @@
  * } // end of method foo
  */
  
-public int flushAnnotationsDefinedPriorTo(int position) {
+public int flushCommentsDefinedPriorTo(int position) {
 
-	return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
+	return lastFieldEndPosition = super.flushCommentsDefinedPriorTo(position);
 }
 protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
 This variable is a type reference and dim will be its dimensions*/
@@ -1000,7 +1006,7 @@
 				ref.sourceEnd = endPosition;
 			}
 		}
-	};
+	}
 	return ref;
 }
 public void initialize() {
@@ -1009,7 +1015,7 @@
 	super.initialize();
 	intArrayPtr = -1;
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -1042,6 +1048,7 @@
 		scanner.setSource(regionSource);
 		parse();
 	} catch (AbortCompilation ex) {
+		// ignore this exception
 	}
 }
 /*
@@ -1062,6 +1069,7 @@
 		scanner.setSource(regionSource);
 		parse();
 	} catch (AbortCompilation ex) {
+		// ignore this exception
 	}
 }
 /*
@@ -1082,6 +1090,7 @@
 		scanner.setSource(regionSource);
 		parse();
 	} catch (AbortCompilation ex) {
+		// ignore this exception
 	}
 
 }
@@ -1103,6 +1112,7 @@
 		scanner.setSource(regionSource);
 		parse();
 	} catch (AbortCompilation ex) {
+		// ignore this exception
 	}
 
 }
@@ -1127,6 +1137,7 @@
 		scanner.setSource(regionSource);
 		parse();
 	} catch (AbortCompilation ex) {
+		// ignore this exception
 	}
 
 }
@@ -1148,6 +1159,7 @@
 		scanner.setSource(regionSource);
 		parse();
 	} catch (AbortCompilation ex) {
+		// ignore this exception
 	}
 
 }
@@ -1169,6 +1181,7 @@
 		scanner.setSource(regionSource);
 		parse();
 	} catch (AbortCompilation ex) {
+		// ignore this exception
 	}
 
 }
@@ -1190,6 +1203,7 @@
 		scanner.setSource(regionSource);
 		parse();
 	} catch (AbortCompilation ex) {
+		// ignore this exception
 	}
 
 }
@@ -1197,6 +1211,8 @@
  * 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.
+ * 
+ * @return ProblemReporter
  */
 public ProblemReporter problemReporter() {
 	problemReporter.referenceContext = referenceContext;
@@ -1253,7 +1269,8 @@
 	buffer.append(super.toString());
 	return buffer.toString();
 }
-/**
+/*
+ * 
  * INTERNAL USE ONLY
  */
 protected TypeReference typeReference(
@@ -1308,7 +1325,7 @@
 			else
 				ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
 		}
-	};
+	}
 	return ref;
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/IAbstractSyntaxTreeVisitor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/IAbstractSyntaxTreeVisitor.java
deleted file mode 100644
index d70291c..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/IAbstractSyntaxTreeVisitor.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.compiler;
-
-import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.internal.compiler.ast.*; 
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-/**
- * A visitor interface for interating through the parse tree.
- */
-public interface IAbstractSyntaxTreeVisitor {
-	void acceptProblem(IProblem problem);
-	void endVisit(AllocationExpression allocationExpression, BlockScope scope);
-	void endVisit(AND_AND_Expression and_and_Expression, BlockScope scope);
-	void endVisit(AnonymousLocalTypeDeclaration anonymousTypeDeclaration, BlockScope scope);
-	void endVisit(Argument argument, BlockScope scope);
-	void endVisit(ArrayAllocationExpression arrayAllocationExpression, BlockScope scope);
-	void endVisit(ArrayInitializer arrayInitializer, BlockScope scope);
-	void endVisit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, BlockScope scope);
-	void endVisit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, ClassScope scope);
-	void endVisit(ArrayReference arrayReference, BlockScope scope);
-	void endVisit(ArrayTypeReference arrayTypeReference, BlockScope scope);
-	void endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope);
-	void endVisit(AssertStatement assertStatement, BlockScope scope);
-	void endVisit(Assignment assignment, BlockScope scope);
-	void endVisit(BinaryExpression binaryExpression, BlockScope scope);
-	void endVisit(Block block, BlockScope scope);
-	void endVisit(Break breakStatement, BlockScope scope);
-	void endVisit(Case caseStatement, BlockScope scope);
-	void endVisit(CastExpression castExpression, BlockScope scope);
-	void endVisit(CharLiteral charLiteral, BlockScope scope);
-	void endVisit(ClassLiteralAccess classLiteral, BlockScope scope);
-	void endVisit(Clinit clinit, ClassScope scope);
-	void endVisit(CompilationUnitDeclaration compilationUnitDeclaration, CompilationUnitScope scope);
-	void endVisit(CompoundAssignment compoundAssignment, BlockScope scope);
-	void endVisit(ConditionalExpression conditionalExpression, BlockScope scope);
-	void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope scope);
-	void endVisit(Continue continueStatement, BlockScope scope);
-	void endVisit(DefaultCase defaultCaseStatement, BlockScope scope);
-	void endVisit(DoStatement doStatement, BlockScope scope);
-	void endVisit(DoubleLiteral doubleLiteral, BlockScope scope);
-	void endVisit(EqualExpression equalExpression, BlockScope scope);
-	void endVisit(EmptyStatement statement, BlockScope scope);
-	void endVisit(ExplicitConstructorCall explicitConstructor, BlockScope scope);
-	void endVisit(ExtendedStringLiteral extendedStringLiteral, BlockScope scope);
-	void endVisit(FalseLiteral falseLiteral, BlockScope scope);
-	void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope);
-	void endVisit(FieldReference fieldReference, BlockScope scope);
-	void endVisit(FloatLiteral floatLiteral, BlockScope scope);
-	void endVisit(ForStatement forStatement, BlockScope scope);
-	void endVisit(IfStatement ifStatement, BlockScope scope);
-	void endVisit(ImportReference importRef, CompilationUnitScope scope);
-	void endVisit(Initializer initializer, MethodScope scope);
-	void endVisit(InstanceOfExpression instanceOfExpression, BlockScope scope);
-	void endVisit(IntLiteral intLiteral, BlockScope scope);
-	void endVisit(LabeledStatement labeledStatement, BlockScope scope);
-	void endVisit(LocalDeclaration localDeclaration, BlockScope scope);
-	void endVisit(LocalTypeDeclaration localTypeDeclaration, BlockScope scope);
-	void endVisit(LongLiteral longLiteral, BlockScope scope);
-	void endVisit(MemberTypeDeclaration memberTypeDeclaration, ClassScope scope);
-	void endVisit(MessageSend messageSend, BlockScope scope);
-	void endVisit(MethodDeclaration methodDeclaration, ClassScope scope);
-	void endVisit(NullLiteral nullLiteral, BlockScope scope);
-	void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope);
-	void endVisit(PostfixExpression postfixExpression, BlockScope scope);
-	void endVisit(PrefixExpression prefixExpression, BlockScope scope);
-	void endVisit(QualifiedAllocationExpression qualifiedAllocationExpression, BlockScope scope);
-	void endVisit(QualifiedNameReference qualifiedNameReference, BlockScope scope);
-	void endVisit(QualifiedSuperReference qualifiedSuperReference, BlockScope scope);
-	void endVisit(QualifiedThisReference qualifiedThisReference, BlockScope scope);
-	void endVisit(QualifiedTypeReference qualifiedTypeReference, BlockScope scope);
-	void endVisit(QualifiedTypeReference qualifiedTypeReference, ClassScope scope);
-	void endVisit(ReturnStatement returnStatement, BlockScope scope);
-	void endVisit(SingleNameReference singleNameReference, BlockScope scope);
-	void endVisit(SingleTypeReference singleTypeReference, BlockScope scope);
-	void endVisit(SingleTypeReference singleTypeReference, ClassScope scope);
-	void endVisit(StringLiteral stringLiteral, BlockScope scope);
-	void endVisit(SuperReference superReference, BlockScope scope);
-	void endVisit(SwitchStatement switchStatement, BlockScope scope);
-	void endVisit(SynchronizedStatement synchronizedStatement, BlockScope scope);
-	void endVisit(ThisReference thisReference, BlockScope scope);
-	void endVisit(ThrowStatement throwStatement, BlockScope scope);
-	void endVisit(TrueLiteral trueLiteral, BlockScope scope);
-	void endVisit(TryStatement tryStatement, BlockScope scope);
-	void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope scope);
-	void endVisit(UnaryExpression unaryExpression, BlockScope scope);
-	void endVisit(WhileStatement whileStatement, BlockScope scope);
-	boolean visit(AllocationExpression allocationExpression, BlockScope scope);
-	boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope);
-	boolean visit(AnonymousLocalTypeDeclaration anonymousTypeDeclaration, BlockScope scope);
-	boolean visit(Argument argument, BlockScope scope);
-	boolean visit(ArrayAllocationExpression arrayAllocationExpression, BlockScope scope);
-	boolean visit(ArrayInitializer arrayInitializer, BlockScope scope);
-	boolean visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, BlockScope scope);
-	boolean visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, ClassScope scope);
-	boolean visit(ArrayReference arrayReference, BlockScope scope);
-	boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope);
-	boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope);
-	boolean visit(AssertStatement assertStatement, BlockScope scope);
-	boolean visit(Assignment assignment, BlockScope scope);
-	boolean visit(BinaryExpression binaryExpression, BlockScope scope);
-	boolean visit(Block block, BlockScope scope);
-	boolean visit(Break breakStatement, BlockScope scope);
-	boolean visit(Case caseStatement, BlockScope scope);
-	boolean visit(CastExpression castExpression, BlockScope scope);
-	boolean visit(CharLiteral charLiteral, BlockScope scope);
-	boolean visit(ClassLiteralAccess classLiteral, BlockScope scope);
-	boolean visit(Clinit clinit, ClassScope scope);
-	boolean visit(CompilationUnitDeclaration compilationUnitDeclaration, CompilationUnitScope scope);
-	boolean visit(CompoundAssignment compoundAssignment, BlockScope scope);
-	boolean visit(ConditionalExpression conditionalExpression, BlockScope scope);
-	boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope);
-	boolean visit(Continue continueStatement, BlockScope scope);
-	boolean visit(DefaultCase defaultCaseStatement, BlockScope scope);
-	boolean visit(DoStatement doStatement, BlockScope scope);
-	boolean visit(DoubleLiteral doubleLiteral, BlockScope scope);
-	boolean visit(EqualExpression equalExpression, BlockScope scope);
-	boolean visit(EmptyStatement statement, BlockScope scope);
-	boolean visit(ExplicitConstructorCall explicitConstructor, BlockScope scope);
-	boolean visit(ExtendedStringLiteral extendedStringLiteral, BlockScope scope);
-	boolean visit(FalseLiteral falseLiteral, BlockScope scope);
-	boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope);
-	boolean visit(FieldReference fieldReference, BlockScope scope);
-	boolean visit(FloatLiteral floatLiteral, BlockScope scope);
-	boolean visit(ForStatement forStatement, BlockScope scope);
-	boolean visit(IfStatement ifStatement, BlockScope scope);
-	boolean visit(ImportReference importRef, CompilationUnitScope scope);
-	boolean visit(Initializer initializer, MethodScope scope);
-	boolean visit(InstanceOfExpression instanceOfExpression, BlockScope scope);
-	boolean visit(IntLiteral intLiteral, BlockScope scope);
-	boolean visit(LabeledStatement labeledStatement, BlockScope scope);
-	boolean visit(LocalDeclaration localDeclaration, BlockScope scope);
-	boolean visit(LocalTypeDeclaration localTypeDeclaration, BlockScope scope);
-	boolean visit(LongLiteral longLiteral, BlockScope scope);
-	boolean visit(MemberTypeDeclaration memberTypeDeclaration, ClassScope scope);
-	boolean visit(MessageSend messageSend, BlockScope scope);
-	boolean visit(MethodDeclaration methodDeclaration, ClassScope scope);
-	boolean visit(NullLiteral nullLiteral, BlockScope scope);
-	boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope);
-	boolean visit(PostfixExpression postfixExpression, BlockScope scope);
-	boolean visit(PrefixExpression prefixExpression, BlockScope scope);
-	boolean visit(QualifiedAllocationExpression qualifiedAllocationExpression, BlockScope scope);
-	boolean visit(QualifiedNameReference qualifiedNameReference, BlockScope scope);
-	boolean visit(QualifiedSuperReference qualifiedSuperReference, BlockScope scope);
-	boolean visit(QualifiedThisReference qualifiedThisReference, BlockScope scope);
-	boolean visit(QualifiedTypeReference qualifiedTypeReference, BlockScope scope);
-	boolean visit(QualifiedTypeReference qualifiedTypeReference, ClassScope scope);
-	boolean visit(ReturnStatement returnStatement, BlockScope scope);
-	boolean visit(SingleNameReference singleNameReference, BlockScope scope);
-	boolean visit(SingleTypeReference singleTypeReference, BlockScope scope);
-	boolean visit(SingleTypeReference singleTypeReference, ClassScope scope);
-	boolean visit(StringLiteral stringLiteral, BlockScope scope);
-	boolean visit(SuperReference superReference, BlockScope scope);
-	boolean visit(SwitchStatement switchStatement, BlockScope scope);
-	boolean visit(SynchronizedStatement synchronizedStatement, BlockScope scope);
-	boolean visit(ThisReference thisReference, BlockScope scope);
-	boolean visit(ThrowStatement throwStatement, BlockScope scope);
-	boolean visit(TrueLiteral trueLiteral, BlockScope scope);
-	boolean visit(TryStatement tryStatement, BlockScope scope);
-	boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope);
-	boolean visit(UnaryExpression unaryExpression, BlockScope scope);
-	boolean visit(WhileStatement whileStatement, BlockScope scope);
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
index 01d4c02..a3f0769 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
@@ -50,12 +50,14 @@
  * @param name This is the name of the import like specified in the source including the dots. The '.*'
  *             is never included in the name.
  * @param onDemand set to true if the import is an import on demand (e.g. import java.io.*). False otherwise.
+ * @param modifiers can be set to static from 1.5 on.
  */
 void acceptImport(
 	int declarationStart,
 	int declarationEnd,
 	char[] name,
-	boolean onDemand);
+	boolean onDemand,
+	int modifiers);
 /*
  * Table of line separator position. This table is passed once at the end
  * of the parse action, so as to allow computation of normalized ranges.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java
index ad174a0..6ce2b05 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/SourceElementParser.java
@@ -10,6 +10,14 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler;
 
+import org.eclipse.jdt.internal.compiler.env.*;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+
 /**
  * A source element parser extracts structural and reference information
  * from a piece of source.
@@ -28,21 +36,10 @@
  *
  * Any (parsing) problem encountered is also provided.
  */
-
-import org.eclipse.jdt.internal.compiler.env.*;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-
 public class SourceElementParser extends Parser {
 	
 	ISourceElementRequestor requestor;
 	int fieldCount;
-	int localIntPtr;
-	int lastFieldEndPosition;
 	ISourceType sourceType;
 	boolean reportReferenceInfo;
 	char[][] typeNames;
@@ -57,18 +54,12 @@
 /**
  * An ast visitor that visits local type declarations.
  */
-public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
-	public boolean visit(
-			AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
-			BlockScope scope) {
-		notifySourceElementRequestor(anonymousTypeDeclaration, sourceType == null);
-		return false; // don't visit members as this was done during notifySourceElementRequestor(...)
-	}
-	public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
+public class LocalDeclarationVisitor extends ASTVisitor {
+	public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
 		notifySourceElementRequestor(typeDeclaration, sourceType == null);
 		return false; // don't visit members as this was done during notifySourceElementRequestor(...)
 	}
-	public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
+	public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
 		notifySourceElementRequestor(typeDeclaration, sourceType == null);
 		return false; // don't visit members as this was done during notifySourceElementRequestor(...)
 	}
@@ -85,13 +76,12 @@
 		DefaultErrorHandlingPolicies.exitAfterAllProblems(),
 		options, 
 		problemFactory) {
-		public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
-			unitResult.record(problem, referenceContext);
+		public void record(IProblem problem, CompilationResult unitResult, ReferenceContext context) {
+			unitResult.record(problem, context); // TODO (jerome) clients are trapping problems either through factory or requestor... is result storing needed?
 			requestor.acceptProblem(problem);
 		}
 	},
-	true,
-	options.sourceLevel >= CompilerOptions.JDK1_4);
+	true);
 	this.requestor = requestor;
 	typeNames = new char[4][];
 	superTypeNames = new char[4][];
@@ -99,13 +89,6 @@
 	this.options = options;
 }
 
-/** @deprecated use SourceElementParser(ISourceElementRequestor, IProblemFactory, CompilerOptions) */
-public SourceElementParser(
-	final ISourceElementRequestor requestor, 
-	IProblemFactory problemFactory) {
-		this(requestor, problemFactory, new CompilerOptions());
-}
-
 public SourceElementParser(
 	final ISourceElementRequestor requestor, 
 	IProblemFactory problemFactory,
@@ -117,17 +100,57 @@
 		}
 }
 
-public void checkAnnotation() {
-	int firstCommentIndex = scanner.commentPtr;
+public void checkComment() {
+	super.checkComment();
+	if (this.reportReferenceInfo && this.javadocParser.checkJavadoc && this.javadoc != null) {
+		// Report reference info in javadoc comment @throws/@exception tags
+		TypeReference[] thrownExceptions = this.javadoc.thrownExceptions;
+		int throwsTagsNbre = thrownExceptions == null ? 0 : thrownExceptions.length;
+		for (int i = 0; i < throwsTagsNbre; i++) {
+			TypeReference typeRef = thrownExceptions[i];
+			if (typeRef instanceof JavadocSingleTypeReference) {
+				JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef;
+				this.requestor.acceptTypeReference(singleRef.token, singleRef.sourceStart);
+			} else if (typeRef instanceof JavadocQualifiedTypeReference) {
+				JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) typeRef;
+				this.requestor.acceptTypeReference(qualifiedRef.tokens, qualifiedRef.sourceStart, qualifiedRef.sourceEnd);
+			}
+		}
 
-	super.checkAnnotation();
-
-	// modify the modifier source start to point at the first comment
-	if (firstCommentIndex >= 0) {
-		modifiersSourceStart = scanner.commentStarts[0]; 
+		// Report reference info in javadoc comment @see tags
+		Expression[] references = this.javadoc.references;
+		int seeTagsNbre = references == null ? 0 : references.length;
+		for (int i = 0; i < seeTagsNbre; i++) {
+			Expression reference = references[i];
+			acceptJavadocTypeReference(reference);
+			if (reference instanceof JavadocFieldReference) {
+				JavadocFieldReference fieldRef = (JavadocFieldReference) reference;
+				this.requestor.acceptFieldReference(fieldRef.token, fieldRef.sourceStart);
+				acceptJavadocTypeReference(fieldRef.receiver);
+			} else if (reference instanceof JavadocMessageSend) {
+				JavadocMessageSend messageSend = (JavadocMessageSend) reference;
+				int argCount = messageSend.arguments == null ? 0 : messageSend.arguments.length;
+				this.requestor.acceptMethodReference(messageSend.selector, argCount, messageSend.sourceStart);
+				acceptJavadocTypeReference(messageSend.receiver);
+			} else if (reference instanceof JavadocAllocationExpression) {
+				JavadocAllocationExpression constructor = (JavadocAllocationExpression) reference;
+				int argCount = constructor.arguments == null ? 0 : constructor.arguments.length;
+				char[][] compoundName = constructor.type.getTypeName();
+				this.requestor.acceptConstructorReference(compoundName[compoundName.length-1], argCount, constructor.sourceStart);
+				acceptJavadocTypeReference(constructor.type);
+			}
+		}
 	}
 }
-
+private void acceptJavadocTypeReference(Expression expression) {
+	if (expression instanceof JavadocSingleTypeReference) {
+		JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) expression;
+		this.requestor.acceptTypeReference(singleRef.token, singleRef.sourceStart);
+	} else if (expression instanceof JavadocQualifiedTypeReference) {
+		JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) expression;
+		this.requestor.acceptTypeReference(qualifiedRef.tokens, qualifiedRef.sourceStart, qualifiedRef.sourceEnd);
+	}
+}
 protected void classInstanceCreation(boolean alwaysQualified) {
 
 	boolean previousFlag = reportReferenceInfo;
@@ -166,6 +189,9 @@
 	//modifiers
 	cd.declarationSourceStart = intStack[intPtr--];
 	cd.modifiers = intStack[intPtr--];
+	// javadoc
+	cd.javadoc = this.javadoc;
+	this.javadoc = null;
 
 	//highlight starts at the selector starts
 	cd.sourceStart = (int) (selectorSourcePositions >>> 32);
@@ -186,7 +212,7 @@
 		}
 	}	
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -207,7 +233,7 @@
 		return;
 	((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -233,6 +259,9 @@
 	//modifiers
 	md.declarationSourceStart = intStack[intPtr--];
 	md.modifiers = intStack[intPtr--];
+	// javadoc
+	md.javadoc = this.javadoc;
+	this.javadoc = null;
 
 	//highlight starts at selector start
 	md.sourceStart = (int) (selectorSourcePositions >>> 32);
@@ -257,7 +286,7 @@
 		}
 	}		
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -275,7 +304,7 @@
 			(int)(messageSend.nameSourcePosition >>> 32));
 	}
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -290,7 +319,7 @@
 			(int)(messageSend.nameSourcePosition >>> 32));
 	}
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -328,8 +357,28 @@
 		requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
 	}
 }
-protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
-	return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
+public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, CompilationResult compilationResult) {
+	SourceMethodDeclaration m = new SourceMethodDeclaration(compilationResult);
+	m.sourceStart = c.sourceStart;
+	m.sourceEnd = c.sourceEnd;
+	m.bodyStart = c.bodyStart;
+	m.bodyEnd = c.bodyEnd;
+	m.declarationSourceEnd = c.declarationSourceEnd;
+	m.declarationSourceStart = c.declarationSourceStart;
+	m.selector = c.selector;
+	m.statements = c.statements;
+	m.modifiers = c.modifiers;
+	m.arguments = c.arguments;
+	m.thrownExceptions = c.thrownExceptions;
+	m.explicitDeclarations = c.explicitDeclarations;
+	m.returnType = null;
+	if (c instanceof SourceConstructorDeclaration) {
+		m.selectorSourceEnd = ((SourceConstructorDeclaration)c).selectorSourceEnd;
+	}
+	return m;
+}
+protected FieldDeclaration createFieldDeclaration(char[] fieldName, int sourceStart, int sourceEnd) {
+	return new SourceFieldDeclaration(fieldName, sourceStart, sourceEnd);
 }
 protected CompilationUnitDeclaration endParse(int act) {
 	if (sourceType != null) {
@@ -346,23 +395,6 @@
 		return null;
 	}		
 }
-/*
- * Flush annotations defined prior to a given positions.
- *
- * Note: annotations are stacked in syntactical order
- *
- * Either answer given <position>, or the end position of a comment line 
- * immediately following the <position> (same line)
- *
- * e.g.
- * void foo(){
- * } // end of method foo
- */
- 
-public int flushAnnotationsDefinedPriorTo(int position) {
-
-	return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
-}
 public TypeReference getTypeReference(int dim) {
 	/* build a Reference on a variable that may be qualified or not
 	 * This variable is a type reference and dim will be its dimensions
@@ -453,9 +485,12 @@
 		char[][] tokens = new char[length][];
 		identifierPtr -= length;
 		System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+		long[] positions = new long[length];
+		System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
 		QualifiedNameReference ref = 
 			new QualifiedNameReference(
 				tokens, 
+				positions,
 				(int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
 				(int) identifierPositionStack[identifierPtr + length]); // sourceEnd
 		if (reportReferenceInfo) {
@@ -479,7 +514,7 @@
 			new SingleNameReference(
 				identifierStack[identifierPtr], 
 				identifierPositionStack[identifierPtr--]); 
-		ref.bits &= ~AstNode.RestrictiveFlagMASK;
+		ref.bits &= ~ASTNode.RestrictiveFlagMASK;
 		ref.bits |= LOCAL | FIELD;
 		if (reportReferenceInfo) {
 			this.addUnknownRef(ref);
@@ -496,20 +531,23 @@
 	char[][] tokens = new char[length][];
 	identifierPtr -= length;
 	System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+	long[] positions = new long[length];
+	System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
 	QualifiedNameReference ref = 
 		new QualifiedNameReference(
 			tokens, 
+			positions,
 			(int) (identifierPositionStack[identifierPtr + 1] >> 32), 
 	// sourceStart
 	 (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
-	ref.bits &= ~AstNode.RestrictiveFlagMASK;
+	ref.bits &= ~ASTNode.RestrictiveFlagMASK;
 	ref.bits |= LOCAL | FIELD;
 	if (reportReferenceInfo) {
 		this.addUnknownRef(ref);
 	}
 	return ref;
 }
-/**
+/*
  *
  * INTERNAL USE-ONLY
  */
@@ -546,7 +584,7 @@
 	}
 	// collect the top level ast nodes
 	int length = 0;
-	AstNode[] nodes = null;
+	ASTNode[] nodes = null;
 	if (sourceType == null){
 		if (isInRange) {
 			requestor.enterCompilationUnit();
@@ -558,7 +596,7 @@
 			(currentPackage == null ? 0 : 1) 
 			+ (imports == null ? 0 : imports.length)
 			+ (types == null ? 0 : types.length);
-		nodes = new AstNode[length];
+		nodes = new ASTNode[length];
 		int index = 0;
 		if (currentPackage != null) {
 			nodes[index++] = currentPackage;
@@ -577,7 +615,7 @@
 		TypeDeclaration[] types = parsedUnit.types;
 		if (types != null) {
 			length = types.length;
-			nodes = new AstNode[length];
+			nodes = new ASTNode[length];
 			for (int i = 0, max = types.length; i < max; i++) {
 				nodes[i] = types[i];
 			}
@@ -588,7 +626,7 @@
 	if (nodes != null && length > 0) {
 		quickSort(nodes, 0, length-1);
 		for (int i=0;i<length;i++) {
-			AstNode node = nodes[i];
+			ASTNode node = nodes[i];
 			if (node instanceof ImportReference) {
 				ImportReference importRef = (ImportReference)node;
 				if (node == parsedUnit.currentPackage) {
@@ -758,11 +796,11 @@
 			((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd; 
 	}
 	if (isInRange) {
-		int modifiers = methodDeclaration.modifiers;
-		boolean deprecated = (modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+		int currentModifiers = methodDeclaration.modifiers;
+		boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
 		requestor.enterMethod(
 			methodDeclaration.declarationSourceStart, 
-			deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag, 
+			deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag, 
 			returnTypeName(((MethodDeclaration) methodDeclaration).returnType), 
 			methodDeclaration.selector, 
 			methodDeclaration.sourceStart, 
@@ -797,11 +835,11 @@
 			}
 		}
 		if (isInRange) {
-			int modifiers = fieldDeclaration.modifiers;
-			boolean deprecated = (modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+			int currentModifiers = fieldDeclaration.modifiers;
+			boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
 			requestor.enterField(
 				fieldDeclaration.declarationSourceStart, 
-				deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag, 
+				deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag, 
 				returnTypeName(fieldDeclaration.type), 
 				fieldDeclaration.name, 
 				fieldDeclaration.sourceStart, 
@@ -851,7 +889,8 @@
 			importReference.declarationSourceStart, 
 			importReference.declarationSourceEnd, 
 			CharOperation.concatWith(importReference.getImportName(), '.'), 
-			importReference.onDemand); 
+			importReference.onDemand,
+			importReference.modifiers); 
 	}
 }
 public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
@@ -863,10 +902,10 @@
 	
 	FieldDeclaration[] fields = typeDeclaration.fields;
 	AbstractMethodDeclaration[] methods = typeDeclaration.methods;
-	MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
-	int fieldCount = fields == null ? 0 : fields.length;
-	int methodCount = methods == null ? 0 : methods.length;
-	int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
+	TypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
+	int fieldCounter = fields == null ? 0 : fields.length;
+	int methodCounter = methods == null ? 0 : methods.length;
+	int memberTypeCounter = memberTypes == null ? 0 : memberTypes.length;
 	int fieldIndex = 0;
 	int methodIndex = 0;
 	int memberTypeIndex = 0;
@@ -880,11 +919,11 @@
 			superInterfacesLength = superInterfaces.length;
 			interfaceNames = new char[superInterfacesLength][];
 		} else {
-			if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
+			if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
 				// see PR 3442
-				QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation;
+				QualifiedAllocationExpression alloc = typeDeclaration.allocation;
 				if (alloc != null && alloc.type != null) {
-					superInterfaces = new TypeReference[] { ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation.type};
+					superInterfaces = new TypeReference[] { typeDeclaration.allocation.type};
 					superInterfacesLength = 1;
 					interfaceNames = new char[1][];
 				}
@@ -898,14 +937,14 @@
 		}
 		if (isInterface) {
 			if (isInRange){
-				int modifiers = typeDeclaration.modifiers;
-				boolean deprecated = (modifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
+				int currentModifiers = typeDeclaration.modifiers;
+				boolean deprecated = (currentModifiers & AccDeprecated) != 0; // remember deprecation so as to not lose it below
 				requestor.enterInterface(
 					typeDeclaration.declarationSourceStart, 
-					deprecated ? (modifiers & AccJustFlag) | AccDeprecated : modifiers & AccJustFlag, 
+					deprecated ? (currentModifiers & AccJustFlag) | AccDeprecated : currentModifiers & AccJustFlag, 
 					typeDeclaration.name, 
 					typeDeclaration.sourceStart, 
-					typeDeclaration.sourceEnd, 
+					sourceEnd(typeDeclaration), 
 					interfaceNames);
 			}
 			if (nestedTypeIndex == typeNames.length) {
@@ -924,7 +963,7 @@
 						typeDeclaration.modifiers, 
 						typeDeclaration.name, 
 						typeDeclaration.sourceStart, 
-						typeDeclaration.sourceEnd, 
+						sourceEnd(typeDeclaration), 
 						null, 
 						interfaceNames); 
 				}
@@ -935,7 +974,7 @@
 						typeDeclaration.modifiers, 
 						typeDeclaration.name, 
 						typeDeclaration.sourceStart, 
-						typeDeclaration.sourceEnd, 
+						sourceEnd(typeDeclaration), 
 						CharOperation.concatWith(superclass.getTypeName(), '.'), 
 						interfaceNames); 
 				}
@@ -949,30 +988,30 @@
 			superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
 		}
 	}
-	while ((fieldIndex < fieldCount)
-		|| (memberTypeIndex < memberTypeCount)
-		|| (methodIndex < methodCount)) {
+	while ((fieldIndex < fieldCounter)
+		|| (memberTypeIndex < memberTypeCounter)
+		|| (methodIndex < methodCounter)) {
 		FieldDeclaration nextFieldDeclaration = null;
 		AbstractMethodDeclaration nextMethodDeclaration = null;
 		TypeDeclaration nextMemberDeclaration = null;
 
 		int position = Integer.MAX_VALUE;
 		int nextDeclarationType = -1;
-		if (fieldIndex < fieldCount) {
+		if (fieldIndex < fieldCounter) {
 			nextFieldDeclaration = fields[fieldIndex];
 			if (nextFieldDeclaration.declarationSourceStart < position) {
 				position = nextFieldDeclaration.declarationSourceStart;
 				nextDeclarationType = 0; // FIELD
 			}
 		}
-		if (methodIndex < methodCount) {
+		if (methodIndex < methodCounter) {
 			nextMethodDeclaration = methods[methodIndex];
 			if (nextMethodDeclaration.declarationSourceStart < position) {
 				position = nextMethodDeclaration.declarationSourceStart;
 				nextDeclarationType = 1; // METHOD
 			}
 		}
-		if (memberTypeIndex < memberTypeCount) {
+		if (memberTypeIndex < memberTypeCounter) {
 			nextMemberDeclaration = memberTypes[memberTypeIndex];
 			if (nextMemberDeclaration.declarationSourceStart < position) {
 				position = nextMemberDeclaration.declarationSourceStart;
@@ -1004,15 +1043,23 @@
 		nestedTypeIndex--;
 	}
 }
+private int sourceEnd(TypeDeclaration typeDeclaration) {
+	if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+		return typeDeclaration.allocation.type.sourceEnd;
+	} else {
+		return typeDeclaration.sourceEnd;
+	}
+}
+
 public void parseCompilationUnit(
 	ICompilationUnit unit, 
 	int start, 
 	int end, 
-	boolean needReferenceInfo) {
+	boolean fullParse) {
 
-	reportReferenceInfo = needReferenceInfo;
+	this.reportReferenceInfo = fullParse;
 	boolean old = diet;
-	if (needReferenceInfo) {
+	if (fullParse) {
 		unknownRefs = new NameReference[10];
 		unknownRefsCounter = 0;
 	}
@@ -1024,29 +1071,31 @@
 		if (scanner.recordLineSeparator) {
 			requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
 		}
-		if (this.localDeclarationVisitor != null || needReferenceInfo){
+		if (this.localDeclarationVisitor != null || fullParse){
 			diet = false;
 			this.getMethodBodies(parsedUnit);
 		}		
 		this.scanner.resetTo(start, end);
 		notifySourceElementRequestor(parsedUnit);
 	} catch (AbortCompilation e) {
+		// ignore this exception
 	} finally {
 		diet = old;
 	}
 }
-public void parseCompilationUnit(
+public CompilationUnitDeclaration parseCompilationUnit(
 	ICompilationUnit unit, 
-	boolean needReferenceInfo) {
+	boolean fullParse) {
+		
 	boolean old = diet;
-	if (needReferenceInfo) {
+	if (fullParse) {
 		unknownRefs = new NameReference[10];
 		unknownRefsCounter = 0;
 	}
 
 	try {
 		diet = true;
-		reportReferenceInfo = needReferenceInfo;
+		this.reportReferenceInfo = fullParse;
 		CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
 		CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult);
 		if (scanner.recordLineSeparator) {
@@ -1054,19 +1103,22 @@
 		}
 		int initialStart = this.scanner.initialPosition;
 		int initialEnd = this.scanner.eofPosition;
-		if (this.localDeclarationVisitor != null || needReferenceInfo){
+		if (this.localDeclarationVisitor != null || fullParse){
 			diet = false;
 			this.getMethodBodies(parsedUnit);
 		}
 		this.scanner.resetTo(initialStart, initialEnd);
 		notifySourceElementRequestor(parsedUnit);
+		return parsedUnit;
 	} catch (AbortCompilation e) {
+		// ignore this exception
 	} finally {
 		diet = old;
 	}
+	return null;
 }
 public void parseTypeMemberDeclarations(
-	ISourceType sourceType, 
+	ISourceType type, 
 	ICompilationUnit sourceUnit, 
 	int start, 
 	int end, 
@@ -1084,15 +1136,16 @@
 			new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit); 
 		CompilationUnitDeclaration unit = 
 			SourceTypeConverter.buildCompilationUnit(
-				new ISourceType[]{sourceType}, 
-				false, // no need for field and methods
-				false, // no need for member types
-				false, // no need for field initialization
+				new ISourceType[]{type}, 
+				// no need for field and methods
+				// no need for member types
+				// no need for field initialization
+				SourceTypeConverter.NONE,
 				problemReporter(), 
 				compilationUnitResult); 
 		if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
 			return;
-		this.sourceType = sourceType;
+		this.sourceType = type;
 		try {
 			/* automaton initialization */
 			initialize();
@@ -1113,6 +1166,7 @@
 			compilationUnit = null; // reset parser
 		}
 	} catch (AbortCompilation e) {
+		// ignore this exception
 	} finally {
 		if (scanner.recordLineSeparator) {
 			requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
@@ -1150,17 +1204,18 @@
 		parse();
 		notifySourceElementRequestor((CompilationUnitDeclaration)null);
 	} catch (AbortCompilation e) {
+		// ignore this exception
 	} finally {
 		diet = old;
 	}
 }
-/**
+/*
  * Sort the given ast nodes by their positions.
  */
-private static void quickSort(AstNode[] sortedCollection, int left, int right) {
+private static void quickSort(ASTNode[] sortedCollection, int left, int right) {
 	int original_left = left;
 	int original_right = right;
-	AstNode mid = sortedCollection[ (left + right) / 2];
+	ASTNode mid = sortedCollection[ (left + right) / 2];
 	do {
 		while (sortedCollection[left].sourceStart < mid.sourceStart) {
 			left++;
@@ -1169,7 +1224,7 @@
 			right--;
 		}
 		if (left <= right) {
-			AstNode tmp = sortedCollection[left];
+			ASTNode tmp = sortedCollection[left];
 			sortedCollection[left] = sortedCollection[right];
 			sortedCollection[right] = tmp;
 			left++;
@@ -1222,7 +1277,7 @@
 
 private void visitIfNeeded(AbstractMethodDeclaration method) {
 	if (this.localDeclarationVisitor != null 
-		&& (method.bits & AstNode.HasLocalTypeMASK) != 0) {
+		&& (method.bits & ASTNode.HasLocalTypeMASK) != 0) {
 			if (method.statements != null) {
 				int statementsLength = method.statements.length;
 				for (int i = 0; i < statementsLength; i++)
@@ -1233,7 +1288,7 @@
 
 private void visitIfNeeded(FieldDeclaration field) {
 	if (this.localDeclarationVisitor != null 
-		&& (field.bits & AstNode.HasLocalTypeMASK) != 0) {
+		&& (field.bits & ASTNode.HasLocalTypeMASK) != 0) {
 			if (field.initialization != null) {
 				field.initialization.traverse(this.localDeclarationVisitor, null);
 			}
@@ -1242,16 +1297,10 @@
 
 private void visitIfNeeded(Initializer initializer) {
 	if (this.localDeclarationVisitor != null 
-		&& (initializer.bits & AstNode.HasLocalTypeMASK) != 0) {
+		&& (initializer.bits & ASTNode.HasLocalTypeMASK) != 0) {
 			if (initializer.block != null) {
 				initializer.block.traverse(this.localDeclarationVisitor, null);
 			}
 	}
 }
-
-protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
-	if (compilationUnit == null) return;
-	super.reportSyntaxError(act, currentKind,stateStackTop);
-}
-
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
index aeeed19..0447a97 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/SourceElementRequestorAdapter.java
@@ -21,28 +21,33 @@
 		char[] typeName,
 		int argCount,
 		int sourcePosition) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#acceptFieldReference(char[], int)
 	 */
 	public void acceptFieldReference(char[] fieldName, int sourcePosition) {
+		// default implementation: do nothing
 	}
 
 	/*
-	 * @see ISourceElementRequestor#acceptImport(int, int, char[], boolean)
+	 * @see ISourceElementRequestor#acceptImport(int, int, char[], boolean, int)
 	 */
 	public void acceptImport(
 		int declarationStart,
 		int declarationEnd,
 		char[] name,
-		boolean onDemand) {
+		boolean onDemand,
+		int modifiers) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#acceptLineSeparatorPositions(int[])
 	 */
 	public void acceptLineSeparatorPositions(int[] positions) {
+		// default implementation: do nothing
 	}
 
 	/*
@@ -52,6 +57,7 @@
 		char[] methodName,
 		int argCount,
 		int sourcePosition) {
+		// default implementation: do nothing
 	}
 
 	/*
@@ -61,12 +67,14 @@
 		int declarationStart,
 		int declarationEnd,
 		char[] name) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#acceptProblem(IProblem)
 	 */
 	public void acceptProblem(IProblem problem) {
+		// default implementation: do nothing
 	}
 
 	/*
@@ -76,12 +84,14 @@
 		char[][] typeName,
 		int sourceStart,
 		int sourceEnd) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#acceptTypeReference(char[], int)
 	 */
 	public void acceptTypeReference(char[] typeName, int sourcePosition) {
+		// default implementation: do nothing
 	}
 
 	/*
@@ -91,12 +101,14 @@
 		char[][] name,
 		int sourceStart,
 		int sourceEnd) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#acceptUnknownReference(char[], int)
 	 */
 	public void acceptUnknownReference(char[] name, int sourcePosition) {
+		// default implementation: do nothing
 	}
 
 	/*
@@ -110,12 +122,14 @@
 		int nameSourceEnd,
 		char[] superclass,
 		char[][] superinterfaces) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#enterCompilationUnit()
 	 */
 	public void enterCompilationUnit() {
+		// default implementation: do nothing
 	}
 
 	/*
@@ -130,6 +144,7 @@
 		char[][] parameterTypes,
 		char[][] parameterNames,
 		char[][] exceptionTypes) {
+		// default implementation: do nothing
 	}
 
 	/*
@@ -142,12 +157,14 @@
 		char[] name,
 		int nameSourceStart,
 		int nameSourceEnd) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#enterInitializer(int, int)
 	 */
 	public void enterInitializer(int declarationStart, int modifiers) {
+		// default implementation: do nothing
 	}
 
 	/*
@@ -160,6 +177,7 @@
 		int nameSourceStart,
 		int nameSourceEnd,
 		char[][] superinterfaces) {
+		// default implementation: do nothing
 	}
 
 	/*
@@ -175,48 +193,56 @@
 		char[][] parameterTypes,
 		char[][] parameterNames,
 		char[][] exceptionTypes) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#exitClass(int)
 	 */
 	public void exitClass(int declarationEnd) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#exitCompilationUnit(int)
 	 */
 	public void exitCompilationUnit(int declarationEnd) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#exitConstructor(int)
 	 */
 	public void exitConstructor(int declarationEnd) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#exitField(int)
 	 */
 	public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#exitInitializer(int)
 	 */
 	public void exitInitializer(int declarationEnd) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#exitInterface(int)
 	 */
 	public void exitInterface(int declarationEnd) {
+		// default implementation: do nothing
 	}
 
 	/*
 	 * @see ISourceElementRequestor#exitMethod(int)
 	 */
 	public void exitMethod(int declarationEnd) {
+		// default implementation: do nothing
 	}
 
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
index d018e1e..e0344ad 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -26,10 +26,7 @@
 		super(left, right, operator);
 	}
 
-	public FlowInfo analyseCode(
-		BlockScope currentScope,
-		FlowContext flowContext,
-		FlowInfo flowInfo) {
+	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
 
 		Constant cst = this.left.optimizedBooleanConstant();
 		boolean isLeftOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
@@ -37,50 +34,45 @@
 
 		if (isLeftOptimizedTrue) {
 			// TRUE && anything
-			 // need to be careful of scenario:
-			//		(x && y) && !z, if passing the left info to the right, it would be swapped by the !
-			FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); 
+			// need to be careful of scenario:
+			//  (x && y) && !z, if passing the left info to the right, it would
+			// be swapped by the !
+			FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo)
+					.unconditionalInits();
 			mergedInfo = right.analyseCode(currentScope, flowContext, mergedInfo);
-			mergedInitStateIndex =
-				currentScope.methodScope().recordInitializationStates(mergedInfo);
+			mergedInitStateIndex = currentScope.methodScope()
+					.recordInitializationStates(mergedInfo);
 			return mergedInfo;
 		}
-		
+
 		FlowInfo leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
-		 // need to be careful of scenario:
-		//		(x && y) && !z, if passing the left info to the right, it would be swapped by the !
+		// need to be careful of scenario:
+		//  (x && y) && !z, if passing the left info to the right, it would be
+		// swapped by the !
 		FlowInfo rightInfo = leftInfo.initsWhenTrue().unconditionalInits().copy();
-		rightInitStateIndex =
-			currentScope.methodScope().recordInitializationStates(rightInfo);
+		rightInitStateIndex = currentScope.methodScope().recordInitializationStates(rightInfo);
 
 		int previousMode = rightInfo.reachMode();
-		if (isLeftOptimizedFalse){
-			rightInfo.setReachMode(FlowInfo.UNREACHABLE); 
+		if (isLeftOptimizedFalse) {
+			rightInfo.setReachMode(FlowInfo.UNREACHABLE);
 		}
 		rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
 		FlowInfo trueMergedInfo = rightInfo.initsWhenTrue().copy();
 		rightInfo.setReachMode(previousMode); // reset after trueMergedInfo got extracted
-		
-		FlowInfo mergedInfo = 
-			FlowInfo.conditional(
-				trueMergedInfo,
+		FlowInfo mergedInfo = FlowInfo.conditional(
+				trueMergedInfo, 
 				leftInfo.initsWhenFalse().copy().unconditionalInits().mergedWith(
 						rightInfo.initsWhenFalse().copy().unconditionalInits()));
-		mergedInitStateIndex =
-			currentScope.methodScope().recordInitializationStates(mergedInfo);
+		mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
 		return mergedInfo;
 	}
 
 	/**
 	 * Code generation for a binary operation
 	 */
-	public void generateCode(
-		BlockScope currentScope,
-		CodeStream codeStream,
-		boolean valueRequired) {
-			
+	public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
 		int pc = codeStream.position;
-		Label falseLabel, endLabel;
 		if (constant != Constant.NotAConstant) {
 			// inlined value
 			if (valueRequired)
@@ -88,210 +80,178 @@
 			codeStream.recordPositionsFrom(pc, this.sourceStart);
 			return;
 		}
-		bits |= OnlyValueRequiredMASK;
-		generateOptimizedBoolean(
-			currentScope,
-			codeStream,
-			null,
-			(falseLabel = new Label(codeStream)),
-			valueRequired);
-		/* improving code gen for such a case: boolean b = i < 0 && false
-		 * since the label has never been used, we have the inlined value on the stack. */
-		if (falseLabel.hasForwardReferences()) {
-			if (valueRequired) {
-				codeStream.iconst_1();
-				if ((bits & ValueForReturnMASK) != 0) {
-					codeStream.ireturn();
-					falseLabel.place();
-					codeStream.iconst_0();
-				} else {
-					codeStream.goto_(endLabel = new Label(codeStream));
-					codeStream.decrStackSize(1);
-					falseLabel.place();
-					codeStream.iconst_0();
-					endLabel.place();
-				}
+		Constant cst = right.constant;
+		if (cst != NotAConstant) {
+			// <expr> && true --> <expr>
+			if (cst.booleanValue() == true) {
+				this.left.generateCode(currentScope, codeStream, valueRequired);
 			} else {
-				falseLabel.place();
+				// <expr> && false --> false
+				this.left.generateCode(currentScope, codeStream, false);
+				if (valueRequired) codeStream.iconst_0();
 			}
-		}
-		if (valueRequired) {
+			if (mergedInitStateIndex != -1) {
+				codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+			}			
 			codeStream.generateImplicitConversion(implicitConversion);
+			codeStream.updateLastRecordedEndPC(codeStream.position);
+			codeStream.recordPositionsFrom(pc, this.sourceStart);
+			return;
 		}
-		// reposition the endPC
-		codeStream.updateLastRecordedEndPC(codeStream.position);		
-	}
+		
+		Label falseLabel = new Label(codeStream), endLabel;
+		cst = left.optimizedBooleanConstant();
+		boolean leftIsConst = cst != NotAConstant;
+		boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
 
-	/**
-	 * Boolean operator code generation
-	 *	Optimized operations are: &&
-	 */
-	public void generateOptimizedBoolean(
-		BlockScope currentScope,
-		CodeStream codeStream,
-		Label trueLabel,
-		Label falseLabel,
-		boolean valueRequired) {
-			
-		if (constant != Constant.NotAConstant) {
-			super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
-			return;
-		}
-		Constant condConst;
-		if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
-			if (condConst.booleanValue() == true) {
-				// <something equivalent to true> && x
-				left.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					trueLabel,
-					falseLabel,
-					false);
-				if (rightInitStateIndex != -1) {
-					codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
-				}
-				if ((bits & OnlyValueRequiredMASK) != 0) {
-					right.generateCode(currentScope, codeStream, valueRequired);
-				} else {
-					right.generateOptimizedBoolean(
-						currentScope,
-						codeStream,
-						trueLabel,
-						falseLabel,
-						valueRequired);
+		cst = right.optimizedBooleanConstant();
+		boolean rightIsConst = cst != NotAConstant;
+		boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
+
+		generateOperands : {
+			if (leftIsConst) {
+				left.generateCode(currentScope, codeStream, false);
+				if (!leftIsTrue) {
+					break generateOperands; // no need to generate right operand
 				}
 			} else {
-				// <something equivalent to false> && x
-				left.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					trueLabel,
-					falseLabel,
-					false);
-				if (valueRequired) {
-					if ((bits & OnlyValueRequiredMASK) != 0) {
-						codeStream.iconst_0();
-					} else {
-						if (falseLabel != null) {
-							// implicit falling through the TRUE case
-							codeStream.goto_(falseLabel);
-						}
-					}
-				}
-				// reposition the endPC
-				codeStream.updateLastRecordedEndPC(codeStream.position);
+				left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true); 
+				// need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1 
 			}
-			if (mergedInitStateIndex != -1) {
-				codeStream.removeNotDefinitelyAssignedVariables(
-					currentScope,
-					mergedInitStateIndex);
+			if (rightInitStateIndex != -1) {
+				codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
 			}
-			return;
-		}
-		if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
-			if (condConst.booleanValue() == true) {
-				// x && <something equivalent to true>
-				if ((bits & OnlyValueRequiredMASK) != 0) {
-					left.generateCode(currentScope, codeStream, valueRequired);
-				} else {
-					left.generateOptimizedBoolean(
-						currentScope,
-						codeStream,
-						trueLabel,
-						falseLabel,
-						valueRequired);
-				}
-				if (rightInitStateIndex != -1) {
-					codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
-				}
-				right.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					trueLabel,
-					falseLabel,
-					false);
+			if (rightIsConst) {
+				right.generateCode(currentScope, codeStream, false);
 			} else {
-				// x && <something equivalent to false>
-				Label internalTrueLabel = new Label(codeStream);
-				left.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					internalTrueLabel, // will be false in the end
-					null,
-					false);
-				if (rightInitStateIndex != -1) {
-					codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
-				}
-				internalTrueLabel.place();
-				right.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					trueLabel,
-					falseLabel,
-					false);
-				if (valueRequired) {
-					if ((bits & OnlyValueRequiredMASK) != 0) {
-						codeStream.iconst_0();
-					} else {
-						if (falseLabel != null) {
-							// implicit falling through the TRUE case
-							codeStream.goto_(falseLabel);
-						}
-					}
-				}
-				// reposition the endPC
-				codeStream.updateLastRecordedEndPC(codeStream.position);
-			}
-			if (mergedInitStateIndex != -1) {
-				codeStream.removeNotDefinitelyAssignedVariables(
-					currentScope,
-					mergedInitStateIndex);
-			}
-			return;
-		}
-		// default case
-		if (falseLabel == null) {
-			if (trueLabel != null) {
-				// implicit falling through the FALSE case
-				Label internalFalseLabel = new Label(codeStream);
-				left.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					null,
-					internalFalseLabel,
-					true);
-				if (rightInitStateIndex != -1) {
-					codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
-				}
-				right.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					trueLabel,
-					null,
-					valueRequired);
-				internalFalseLabel.place();
-			}
-		} else {
-			// implicit falling through the TRUE case
-			if (trueLabel == null) {
-				left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true);
-				if (rightInitStateIndex != -1) {
-					codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
-				}
-				right.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					null,
-					falseLabel,
-					valueRequired);
-			} else {
-				// no implicit fall through TRUE/FALSE --> should never occur
+				right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired);
 			}
 		}
 		if (mergedInitStateIndex != -1) {
-			codeStream.removeNotDefinitelyAssignedVariables(
-				currentScope,
-				mergedInitStateIndex);
+			codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+		}
+		/*
+		 * improving code gen for such a case: boolean b = i < 0 && false since
+		 * the label has never been used, we have the inlined value on the
+		 * stack.
+		 */
+		if (valueRequired) {
+			if (leftIsConst && !leftIsTrue) {
+				codeStream.iconst_0();
+				codeStream.updateLastRecordedEndPC(codeStream.position);
+			} else {
+				if (rightIsConst && !rightIsTrue) {
+					codeStream.iconst_0();
+					codeStream.updateLastRecordedEndPC(codeStream.position);
+				} else {
+					codeStream.iconst_1();
+				}
+				if (falseLabel.hasForwardReferences()) {
+					if ((bits & ValueForReturnMASK) != 0) {
+						codeStream.ireturn();
+						falseLabel.place();
+						codeStream.iconst_0();
+					} else {
+						codeStream.goto_(endLabel = new Label(codeStream));
+						codeStream.decrStackSize(1);
+						falseLabel.place();
+						codeStream.iconst_0();
+						endLabel.place();
+					}
+				} else {
+					falseLabel.place();
+				}
+			}
+			codeStream.generateImplicitConversion(implicitConversion);
+			codeStream.updateLastRecordedEndPC(codeStream.position);
+		} else {
+			falseLabel.place();
+		}
+	}
+
+	/**
+	 * Boolean operator code generation Optimized operations are: &&
+	 */
+	public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream,
+			Label trueLabel, Label falseLabel, boolean valueRequired) {
+
+		if (constant != Constant.NotAConstant) {
+			super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel,
+					valueRequired);
+			return;
+		}
+
+		// <expr> && true --> <expr>
+		Constant cst = right.constant;
+		if (cst != NotAConstant && cst.booleanValue() == true) {
+			int pc = codeStream.position;
+			this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+			if (mergedInitStateIndex != -1) {
+				codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+			}			
+			codeStream.recordPositionsFrom(pc, this.sourceStart);
+			return;
+		}
+		cst = left.optimizedBooleanConstant();
+		boolean leftIsConst = cst != NotAConstant;
+		boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
+
+		cst = right.optimizedBooleanConstant();
+		boolean rightIsConst = cst != NotAConstant;
+		boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
+
+		// default case
+		generateOperands : {
+			if (falseLabel == null) {
+				if (trueLabel != null) {
+					// implicit falling through the FALSE case
+					Label internalFalseLabel = new Label(codeStream);
+					left.generateOptimizedBoolean(currentScope, codeStream, null,
+							internalFalseLabel, !leftIsConst); 
+					// need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1
+					if (leftIsConst && !leftIsTrue) {
+						internalFalseLabel.place();
+						break generateOperands; // no need to generate right operand
+					}
+					if (rightInitStateIndex != -1) {
+						codeStream
+								.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+					}
+					right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null,
+							valueRequired && !rightIsConst);
+					if (valueRequired && rightIsConst && rightIsTrue) {
+						codeStream.goto_(trueLabel);
+						codeStream.updateLastRecordedEndPC(codeStream.position);
+					}
+					internalFalseLabel.place();
+				}
+			} else {
+				// implicit falling through the TRUE case
+				if (trueLabel == null) {
+					left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, !leftIsConst); 
+					// need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1
+					if (leftIsConst && !leftIsTrue) {
+						codeStream.goto_(falseLabel);
+						codeStream.updateLastRecordedEndPC(codeStream.position);
+						break generateOperands; // no need to generate right operand
+					}
+					if (rightInitStateIndex != -1) {
+						codeStream
+								.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+					}
+					right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel,
+							valueRequired && !rightIsConst);
+					if (valueRequired && rightIsConst && !rightIsTrue) {
+						codeStream.goto_(falseLabel);
+						codeStream.updateLastRecordedEndPC(codeStream.position);
+					}
+				} else {
+					// no implicit fall through TRUE/FALSE --> should never occur
+				}
+			}
+		}
+		if (mergedInitStateIndex != -1) {
+			codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
 		}
 	}
 
@@ -299,11 +259,11 @@
 		return false;
 	}
 
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		if (visitor.visit(this, scope)) {
 			left.traverse(visitor, scope);
 			right.traverse(visitor, scope);
 		}
 		visitor.endVisit(this, scope);
 	}
-}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
new file mode 100644
index 0000000..98f3a81
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+
+public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConstants, TypeIds {
+	
+	public int sourceStart, sourceEnd;
+
+	//some global provision for the hierarchy
+	public final static Constant NotAConstant = Constant.NotAConstant;
+
+	// storage for internal flags (32 bits)						BIT USAGE
+	public final static int Bit1 = 0x1; 						// return type (operator) | name reference kind (name ref) | add assertion (type decl) | useful empty statement (empty statement)
+	public final static int Bit2 = 0x2; 						// return type (operator) | name reference kind (name ref) | has local type (type, method, field decl)
+	public final static int Bit3 = 0x4; 						// return type (operator) | name reference kind (name ref) | implicit this (this ref)
+	public final static int Bit4 = 0x8; 						// return type (operator) | first assignment to local (local decl) | undocumented empty block (block, type and method decl)
+	public final static int Bit5 = 0x10; 					// value for return (expression) | has all method bodies (unit)
+	public final static int Bit6 = 0x20; 					// depth (name ref, msg) | only value required (binary expression) | ignore need cast check (cast expression)
+	public final static int Bit7 = 0x40; 					// depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression)
+	public final static int Bit8 = 0x80; 					// depth (name ref, msg) | operator (operator) 
+	public final static int Bit9 = 0x100; 				// depth (name ref, msg) | operator (operator) | is local type (type decl)
+	public final static int Bit10= 0x200; 				// depth (name ref, msg) | operator (operator) | is anonymous type (type decl)
+	public final static int Bit11 = 0x400; 				// depth (name ref, msg) | operator (operator) | is member type (type decl)
+	public final static int Bit12 = 0x800; 				// depth (name ref, msg) | operator (operator)
+	public final static int Bit13 = 0x1000; 			// depth (name ref, msg) 
+	public final static int Bit14 = 0x2000; 			// assigned (reference lhs)
+	public final static int Bit15 = 0x4000; 			// is unnecessary cast (expression)
+	public final static int Bit16 = 0x8000; 			// in javadoc comment (name ref, type ref, msg)
+	public final static int Bit17 = 0x10000; 
+	public final static int Bit18 = 0x20000; 
+	public final static int Bit19 = 0x40000; 
+	public final static int Bit20 = 0x80000; 
+	public final static int Bit21 = 0x100000; 		
+	public final static int Bit22 = 0x200000; 		// parenthesis count (expression)
+	public final static int Bit23 = 0x400000; 		// parenthesis count (expression)
+	public final static int Bit24 = 0x800000; 		// parenthesis count (expression)
+	public final static int Bit25 = 0x1000000; 	// parenthesis count (expression)
+	public final static int Bit26 = 0x2000000; 	// parenthesis count (expression)
+	public final static int Bit27 = 0x4000000; 	// parenthesis count (expression)
+	public final static int Bit28 = 0x8000000; 	// parenthesis count (expression)
+	public final static int Bit29 = 0x10000000; 	// parenthesis count (expression)
+	public final static int Bit30 = 0x20000000; 	// assignment with no effect (assignment)
+	public final static int Bit31 = 0x40000000; 	// local declaration reachable (local decl)
+	public final static int Bit32 = 0x80000000; 	// reachable (statement)
+
+	public int bits = IsReachableMASK; 				// reachable by default
+
+	// for operators 
+	public static final int ReturnTypeIDMASK = Bit1|Bit2|Bit3|Bit4; 
+	public static final int OperatorSHIFT = 6;	// Bit7 -> Bit12
+	public static final int OperatorMASK = Bit7|Bit8|Bit9|Bit10|Bit11|Bit12; // 6 bits for operator ID
+
+	// for binary expressions
+	public static final int ValueForReturnMASK = Bit5; 
+	public static final int OnlyValueRequiredMASK = Bit6; 
+
+	// for cast expressions
+	public static final int UnnecessaryCastMask = Bit15;
+	public static final int NeedRuntimeCheckCastMASK = Bit7;
+	public static final int IgnoreNeedForCastCheckMASK = Bit6;
+	
+	// for name references 
+	public static final int RestrictiveFlagMASK = Bit1|Bit2|Bit3;	
+	public static final int FirstAssignmentToLocalMASK = Bit4;
+	
+	// for this reference
+	public static final int IsImplicitThisMask = Bit3; 
+
+	// for single name references
+	public static final int DepthSHIFT = 5;	// Bit6 -> Bit13
+	public static final int DepthMASK = Bit6|Bit7|Bit8|Bit9|Bit10|Bit11|Bit12|Bit13; // 8 bits for actual depth value (max. 255)
+
+	// for statements 
+	public static final int IsReachableMASK = Bit32; 
+	public static final int IsLocalDeclarationReachableMASK = Bit31; 
+
+	// for type declaration
+	public static final int AddAssertionMASK = Bit1;
+	public static final int IsLocalTypeMASK = Bit9;
+	public static final int IsAnonymousTypeMASK = Bit10; // used to test for anonymous 
+	public static final int AnonymousAndLocalMask = IsAnonymousTypeMASK | IsLocalTypeMASK; // used to set anonymous marker
+	public static final int IsMemberTypeMASK = Bit11; // local member do not know it is local at parse time (need to look at binding)
+	
+	// for type, method and field declarations 
+	public static final int HasLocalTypeMASK = Bit2; // cannot conflict with AddAssertionMASK
+
+	// for expression 
+	public static final int ParenthesizedSHIFT = 21; // Bit22 -> Bit29
+	public static final int ParenthesizedMASK = Bit22|Bit23|Bit24|Bit25|Bit26|Bit27|Bit28|Bit29; // 8 bits for parenthesis count value (max. 255)
+
+	// for assignment
+	public static final int IsAssignmentWithNoEffectMASK = Bit30;	
+	
+	// for references on lhs of assignment (set only for true assignments, as opposed to compound ones)
+	public static final int IsStrictlyAssignedMASK = Bit14;
+
+	// for empty statement
+	public static final int IsUsefulEmptyStatementMASK = Bit1;
+
+	// for block and method declaration
+	public static final int UndocumentedEmptyBlockMASK = Bit4;
+
+	// for compilation unit
+	public static final int HasAllMethodBodies = Bit5;
+	
+	// for references in Javadoc comments
+	public static final int InsideJavadoc = Bit16;
+	
+	public ASTNode() {
+
+		super();
+	}
+
+	public ASTNode concreteStatement() {
+		return this;
+	}
+
+	/* Answer true if the field use is considered deprecated.
+	* An access in the same compilation unit is allowed.
+	*/
+	public final boolean isFieldUseDeprecated(FieldBinding field, Scope scope, boolean isStrictlyAssigned) {
+
+		if (!isStrictlyAssigned && field.isPrivate() && !scope.isDefinedInField(field)) {
+			// ignore cases where field is used from within inside itself 
+			field.modifiers |= AccPrivateUsed;
+		}
+
+		if (!field.isViewedAsDeprecated()) return false;
+
+		// inside same unit - no report
+		if (scope.isDefinedInSameUnit(field.declaringClass)) return false;
+		
+		// if context is deprecated, may avoid reporting
+		if (!scope.environment().options.reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false;
+		return true;
+	}
+
+	public boolean isImplicitThis() {
+		
+		return false;
+	}
+	
+	/* Answer true if the method use is considered deprecated.
+	* An access in the same compilation unit is allowed.
+	*/
+	public final boolean isMethodUseDeprecated(MethodBinding method, Scope scope) {
+
+		if (method.isPrivate() && !scope.isDefinedInMethod(method)) {
+			// ignore cases where method is used from within inside itself (e.g. direct recursions)
+			method.modifiers |= AccPrivateUsed;
+		}
+		
+		if (!method.isViewedAsDeprecated()) return false;
+
+		// inside same unit - no report
+		if (scope.isDefinedInSameUnit(method.declaringClass)) return false;
+		
+		// if context is deprecated, may avoid reporting
+		if (!scope.environment().options.reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false;
+		return true;
+	}
+
+	public boolean isSuper() {
+
+		return false;
+	}
+
+	public boolean isThis() {
+
+		return false;
+	}
+
+	/* Answer true if the type use is considered deprecated.
+	* An access in the same compilation unit is allowed.
+	*/
+	public final boolean isTypeUseDeprecated(TypeBinding type, Scope scope) {
+
+		if (type.isArrayType())
+			type = ((ArrayBinding) type).leafComponentType;
+		if (type.isBaseType())
+			return false;
+
+		ReferenceBinding refType = (ReferenceBinding) type;
+
+		if (refType.isPrivate() && !scope.isDefinedInType(refType)) {
+			// ignore cases where type is used from within inside itself 
+			refType.modifiers |= AccPrivateUsed;
+		}
+
+		if (!refType.isViewedAsDeprecated()) return false;
+		
+		// inside same unit - no report
+		if (scope.isDefinedInSameUnit(refType)) return false;
+		
+		// if context is deprecated, may avoid reporting
+		if (!scope.environment().options.reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false;
+		return true;
+	}
+
+	public abstract StringBuffer print(int indent, StringBuffer output);
+
+	public static StringBuffer printIndent(int indent, StringBuffer output) {
+
+		for (int i = indent; i > 0; i--) output.append("  "); //$NON-NLS-1$
+		return output;
+	}
+
+	public static StringBuffer printModifiers(int modifiers, StringBuffer output) {
+
+		if ((modifiers & AccPublic) != 0)
+			output.append("public "); //$NON-NLS-1$
+		if ((modifiers & AccPrivate) != 0)
+			output.append("private "); //$NON-NLS-1$
+		if ((modifiers & AccProtected) != 0)
+			output.append("protected "); //$NON-NLS-1$
+		if ((modifiers & AccStatic) != 0)
+			output.append("static "); //$NON-NLS-1$
+		if ((modifiers & AccFinal) != 0)
+			output.append("final "); //$NON-NLS-1$
+		if ((modifiers & AccSynchronized) != 0)
+			output.append("synchronized "); //$NON-NLS-1$
+		if ((modifiers & AccVolatile) != 0)
+			output.append("volatile "); //$NON-NLS-1$
+		if ((modifiers & AccTransient) != 0)
+			output.append("transient "); //$NON-NLS-1$
+		if ((modifiers & AccNative) != 0)
+			output.append("native "); //$NON-NLS-1$
+		if ((modifiers & AccAbstract) != 0)
+			output.append("abstract "); //$NON-NLS-1$
+		return output;
+	}
+
+	public String toString() {
+
+		return print(0, new StringBuffer(30)).toString();
+	}
+
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		// do nothing by default
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index e69c864..fcaa755 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -21,7 +21,7 @@
 import org.eclipse.jdt.internal.compiler.parser.*;
 
 public abstract class AbstractMethodDeclaration
-	extends AstNode
+	extends ASTNode
 	implements ProblemSeverities, ReferenceContext {
 		
 	public MethodScope scope;
@@ -40,10 +40,14 @@
 	public boolean ignoreFurtherInvestigation = false;
 	public boolean needFreeReturn = false;
 	
+	public Javadoc javadoc;
+	
 	public int bodyStart;
 	public int bodyEnd = -1;
 	public CompilationResult compilationResult;
 	
+	public boolean errorInSignature = false; 
+	
 	AbstractMethodDeclaration(CompilationResult compilationResult){
 		this.compilationResult = compilationResult;
 	}
@@ -53,40 +57,33 @@
 	 */
 	public void abort(int abortLevel) {
 
-		if (scope == null) {
-			throw new AbortCompilation(); // cannot do better
-		}
-
-		CompilationResult compilationResult =
-			scope.referenceCompilationUnit().compilationResult;
-
 		switch (abortLevel) {
 			case AbortCompilation :
-				throw new AbortCompilation(compilationResult);
+				throw new AbortCompilation(this.compilationResult);
 			case AbortCompilationUnit :
-				throw new AbortCompilationUnit(compilationResult);
+				throw new AbortCompilationUnit(this.compilationResult);
 			case AbortType :
-				throw new AbortType(compilationResult);
+				throw new AbortType(this.compilationResult);
 			default :
-				throw new AbortMethod(compilationResult);
+				throw new AbortMethod(this.compilationResult);
 		}
 	}
 
-	public abstract void analyseCode(ClassScope scope, InitializationFlowContext initializationContext, FlowInfo info);
+	public abstract void analyseCode(ClassScope classScope, InitializationFlowContext initializationContext, FlowInfo info);
 
 		/**
 	 * Bind and add argument's binding into the scope of the method
 	 */
 	public void bindArguments() {
 
-		if (arguments != null) {
+		if (this.arguments != null) {
 			// by default arguments in abstract/native methods are considered to be used (no complaint is expected)
-			boolean used = binding == null || binding.isAbstract() || binding.isNative();
+			boolean used = this.binding == null || this.binding.isAbstract() || this.binding.isNative();
 
-			int length = arguments.length;
+			int length = this.arguments.length;
 			for (int i = 0; i < length; i++) {
-				TypeBinding argType = binding == null ? null : binding.parameters[i];
-				arguments[i].bind(scope, argType, used);
+				TypeBinding argType = this.binding == null ? null : this.binding.parameters[i];
+				this.arguments[i].bind(this.scope, argType, used);
 			}
 		}
 	}
@@ -138,21 +135,23 @@
 	
 	/**
 	 * Bytecode generation for a method
+	 * @param classScope
+	 * @param classFile
 	 */
 	public void generateCode(ClassScope classScope, ClassFile classFile) {
 		
 		int problemResetPC = 0;
 		classFile.codeStream.wideMode = false; // reset wideMode to false
-		if (ignoreFurtherInvestigation) {
+		if (this.ignoreFurtherInvestigation) {
 			// method is known to have errors, dump a problem method
 			if (this.binding == null)
 				return; // handle methods with invalid signature or duplicates
 			int problemsLength;
 			IProblem[] problems =
-				scope.referenceCompilationUnit().compilationResult.getProblems();
+				this.scope.referenceCompilationUnit().compilationResult.getProblems();
 			IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
 			System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
-			classFile.addProblemMethod(this, binding, problemsCopy);
+			classFile.addProblemMethod(this, this.binding, problemsCopy);
 			return;
 		}
 		// regular code generation
@@ -172,53 +171,53 @@
 				} catch (AbortMethod e2) {
 					int problemsLength;
 					IProblem[] problems =
-						scope.referenceCompilationUnit().compilationResult.getAllProblems();
+						this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
 					IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
 					System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
-					classFile.addProblemMethod(this, binding, problemsCopy, problemResetPC);
+					classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
 				}
 			} else {
 				// produce a problem method accounting for this fatal error
 				int problemsLength;
 				IProblem[] problems =
-					scope.referenceCompilationUnit().compilationResult.getAllProblems();
+					this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
 				IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
 				System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
-				classFile.addProblemMethod(this, binding, problemsCopy, problemResetPC);
+				classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
 			}
 		}
 	}
 
 	private void generateCode(ClassFile classFile) {
 
-		classFile.generateMethodInfoHeader(binding);
+		classFile.generateMethodInfoHeader(this.binding);
 		int methodAttributeOffset = classFile.contentsOffset;
-		int attributeNumber = classFile.generateMethodInfoAttribute(binding);
-		if ((!binding.isNative()) && (!binding.isAbstract())) {
+		int attributeNumber = classFile.generateMethodInfoAttribute(this.binding);
+		if ((!this.binding.isNative()) && (!this.binding.isAbstract())) {
 			int codeAttributeOffset = classFile.contentsOffset;
 			classFile.generateCodeAttributeHeader();
 			CodeStream codeStream = classFile.codeStream;
 			codeStream.reset(this, classFile);
 			// initialize local positions
-			this.scope.computeLocalVariablePositions(binding.isStatic() ? 0 : 1, codeStream);
+			this.scope.computeLocalVariablePositions(this.binding.isStatic() ? 0 : 1, codeStream);
 
 			// arguments initialization for local variable debug attributes
-			if (arguments != null) {
-				for (int i = 0, max = arguments.length; i < max; i++) {
+			if (this.arguments != null) {
+				for (int i = 0, max = this.arguments.length; i < max; i++) {
 					LocalVariableBinding argBinding;
-					codeStream.addVisibleLocalVariable(argBinding = arguments[i].binding);
+					codeStream.addVisibleLocalVariable(argBinding = this.arguments[i].binding);
 					argBinding.recordInitializationStartPC(0);
 				}
 			}
-			if (statements != null) {
-				for (int i = 0, max = statements.length; i < max; i++)
-					statements[i].generateCode(scope, codeStream);
+			if (this.statements != null) {
+				for (int i = 0, max = this.statements.length; i < max; i++)
+					this.statements[i].generateCode(this.scope, codeStream);
 			}
 			if (this.needFreeReturn) {
 				codeStream.return_();
 			}
 			// local variable attributes
-			codeStream.exitUserScope(scope);
+			codeStream.exitUserScope(this.scope);
 			codeStream.recordPositionsFrom(0, this.declarationSourceEnd);
 			classFile.completeCodeAttribute(codeAttributeOffset);
 			attributeNumber++;
@@ -228,13 +227,13 @@
 		classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);
 
 		// if a problem got reported during code gen, then trigger problem method creation
-		if (ignoreFurtherInvestigation) {
-			throw new AbortMethod(scope.referenceCompilationUnit().compilationResult);
+		if (this.ignoreFurtherInvestigation) {
+			throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult);
 		}
 	}
 
 	private void checkArgumentsSize() {
-		TypeBinding[] parameters = binding.parameters;
+		TypeBinding[] parameters = this.binding.parameters;
 		int size = 1; // an abstact method or a native method cannot be static
 		for (int i = 0, max = parameters.length; i < max; i++) {
 			TypeBinding parameter = parameters[i];
@@ -244,7 +243,7 @@
 				size++;
 			}
 			if (size > 0xFF) {
-				scope.problemReporter().noMoreAvailableSpaceForArgument(scope.locals[i], scope.locals[i].declaration);
+				this.scope.problemReporter().noMoreAvailableSpaceForArgument(this.scope.locals[i], this.scope.locals[i].declaration);
 			}
 		}
 	}
@@ -255,9 +254,9 @@
 
 	public boolean isAbstract() {
 
-		if (binding != null)
-			return binding.isAbstract();
-		return (modifiers & AccAbstract) != 0;
+		if (this.binding != null)
+			return this.binding.isAbstract();
+		return (this.modifiers & AccAbstract) != 0;
 	}
 
 	public boolean isClinit() {
@@ -282,109 +281,119 @@
 
 	public boolean isNative() {
 
-		if (binding != null)
-			return binding.isNative();
-		return (modifiers & AccNative) != 0;
+		if (this.binding != null)
+			return this.binding.isNative();
+		return (this.modifiers & AccNative) != 0;
 	}
 
 	public boolean isStatic() {
 
-		if (binding != null)
-			return binding.isStatic();
-		return (modifiers & AccStatic) != 0;
+		if (this.binding != null)
+			return this.binding.isStatic();
+		return (this.modifiers & AccStatic) != 0;
 	}
 
 	/**
 	 * Fill up the method body with statement
+	 * @param parser
+	 * @param unit
 	 */
 	public abstract void parseStatements(
 		Parser parser,
 		CompilationUnitDeclaration unit);
 
+	public StringBuffer print(int tab, StringBuffer output) {
+
+		printIndent(tab, output);
+		printModifiers(this.modifiers, output);
+		printReturnType(0, output).append(this.selector).append('(');
+		if (this.arguments != null) {
+			for (int i = 0; i < this.arguments.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				this.arguments[i].print(0, output);
+			}
+		}
+		output.append(')');
+		if (this.thrownExceptions != null) {
+			output.append(" throws "); //$NON-NLS-1$
+			for (int i = 0; i < this.thrownExceptions.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				this.thrownExceptions[i].print(0, output);
+			}
+		}
+		printBody(tab + 1, output);
+		return output;
+	}
+
+	public StringBuffer printBody(int indent, StringBuffer output) {
+
+		if (isAbstract() || (this.modifiers & AccSemicolonBody) != 0) 
+			return output.append(';');
+
+		output.append(" {"); //$NON-NLS-1$
+		if (this.statements != null) {
+			for (int i = 0; i < this.statements.length; i++) {
+				output.append('\n');
+				this.statements[i].printStatement(indent, output); 
+			}
+		}
+		output.append('\n'); //$NON-NLS-1$
+		printIndent(indent == 0 ? 0 : indent - 1, output).append('}');
+		return output;
+	}
+
+	public StringBuffer printReturnType(int indent, StringBuffer output) {
+		
+		return output;
+	}
+
 	public void resolve(ClassScope upperScope) {
 
-		if (binding == null) {
-			ignoreFurtherInvestigation = true;
+		if (this.binding == null) {
+			this.ignoreFurtherInvestigation = true;
 		}
 
 		try {
 			bindArguments(); 
 			bindThrownExceptions();
 			resolveStatements();
+			resolveJavadoc();
 		} catch (AbortMethod e) {	// ========= abort on fatal error =============
 			this.ignoreFurtherInvestigation = true;
 		} 
 	}
 
-	public void resolveStatements() {
-
-		if (statements != null) {
-			int i = 0, length = statements.length;
-			while (i < length)
-				statements[i++].resolve(scope);
+	public void resolveJavadoc() {
+		
+		if (this.binding == null) return;
+		if (this.javadoc != null) {
+			this.javadoc.resolve(this.scope);
+			return;
+		}
+		if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
+			this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
 		}
 	}
 
-	public String returnTypeToString(int tab) {
+	public void resolveStatements() {
 
-		return ""; //$NON-NLS-1$
+		if (this.statements != null) {
+			for (int i = 0, length = this.statements.length; i < length; i++) {
+				this.statements[i].resolve(this.scope);
+			}
+		} else if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
+			this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd+1);
+		}
 	}
 
 	public void tagAsHavingErrors() {
 
-		ignoreFurtherInvestigation = true;
-	}
-
-	public String toString(int tab) {
-
-		String s = tabString(tab);
-		if (modifiers != AccDefault) {
-			s += modifiersString(modifiers);
-		}
-
-		s += returnTypeToString(0);
-		s += new String(selector) + "("; //$NON-NLS-1$
-		if (arguments != null) {
-			for (int i = 0; i < arguments.length; i++) {
-				s += arguments[i].toString(0);
-				if (i != (arguments.length - 1))
-					s = s + ", "; //$NON-NLS-1$
-			};
-		};
-		s += ")"; //$NON-NLS-1$
-		if (thrownExceptions != null) {
-			s += " throws "; //$NON-NLS-1$
-			for (int i = 0; i < thrownExceptions.length; i++) {
-				s += thrownExceptions[i].toString(0);
-				if (i != (thrownExceptions.length - 1))
-					s = s + ", "; //$NON-NLS-1$
-			};
-		};
-
-		s += toStringStatements(tab + 1);
-		return s;
-	}
-
-	public String toStringStatements(int tab) {
-
-		if (isAbstract() || (this.modifiers & AccSemicolonBody) != 0)
-			return ";"; //$NON-NLS-1$
-
-		String s = " {"; //$NON-NLS-1$
-		if (statements != null) {
-			for (int i = 0; i < statements.length; i++) {
-				s = s + "\n" + statements[i].toString(tab); //$NON-NLS-1$
-				if (!(statements[i] instanceof Block)) {
-					s += ";"; //$NON-NLS-1$
-				}
-			}
-		}
-		s += "\n" + tabString(tab == 0 ? 0 : tab - 1) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
-		return s;
+		this.ignoreFurtherInvestigation = true;
 	}
 
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		ClassScope classScope) {
+		// default implementation: subclass will define it
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
index 65cddf5..04af929 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
@@ -13,38 +13,75 @@
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 
-public abstract class AbstractVariableDeclaration extends Statement {
-	public int modifiers;
-
-	public TypeReference type;
+public abstract class AbstractVariableDeclaration extends Statement implements InvocationSite {
+	public int declarationEnd;
+	public int declarationSourceEnd;
+	public int declarationSourceStart;
+	public int hiddenVariableDepth; // used to diagnose hiding scenarii
 	public Expression initialization;
+	public int modifiers;
+	public int modifiersSourceStart;
 
 	public char[] name;
-	public int declarationEnd;
-	public int declarationSourceStart;
-	public int declarationSourceEnd;
-	public int modifiersSourceStart;
-	
-	public AbstractVariableDeclaration() {}
 
+	public TypeReference type;
+	
 	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
 		return flowInfo;
 	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
+	 */
+	public boolean isSuperAccess() {
+		return false;
+	}
 
-	public abstract String name();
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isTypeAccess()
+	 */
+	public boolean isTypeAccess() {
+		return false;
+	}
 
-	public void resolve(BlockScope scope) {}
-		
-	public String toString(int tab) {
+	
+	public StringBuffer printStatement(int indent, StringBuffer output) {
 
-		String s = tabString(tab);
-		if (modifiers != AccDefault) {
-			s += modifiersString(modifiers);
+		printIndent(indent, output);
+		printModifiers(this.modifiers, output);
+		type.print(0, output).append(' ').append(this.name); 
+		if (initialization != null) {
+			output.append(" = "); //$NON-NLS-1$
+			initialization.printExpression(indent, output);
 		}
-		s += type.toString(0) + " " + new String(name()); //$NON-NLS-1$
-		if (initialization != null)
-			s += " = " + initialization.toStringExpression(tab); //$NON-NLS-1$
-		return s;
+		return output.append(';');
+	}
+
+	public void resolve(BlockScope scope) {
+		// do nothing by default (redefined for local variables)
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#setActualReceiverType(org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding)
+	 */
+	public void setActualReceiverType(ReferenceBinding receiverType) {
+		// do nothing by default
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#setDepth(int)
+	 */
+	public void setDepth(int depth) {
+
+		this.hiddenVariableDepth = depth;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#setFieldIndex(int)
+	 */
+	public void setFieldIndex(int depth) {
+		// do nothing by default
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 14b9884..b182014 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -25,9 +25,6 @@
 
 	MethodBinding syntheticAccessor;
 
-	public AllocationExpression() {
-	}
-
 	public FlowInfo analyseCode(
 		BlockScope currentScope,
 		FlowContext flowContext,
@@ -55,8 +52,8 @@
 				flowInfo,
 				currentScope);
 		}
-		manageEnclosingInstanceAccessIfNecessary(currentScope);
-		manageSyntheticAccessIfNecessary(currentScope);
+		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+		manageSyntheticAccessIfNecessary(currentScope, flowInfo);
 		
 		return flowInfo;
 	}
@@ -154,8 +151,9 @@
 	 * types, since by the time we reach them, we might not yet know their
 	 * exact need.
 	 */
-	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
+	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
+		if (!flowInfo.isReachable()) return;
 		ReferenceBinding allocatedType;
 
 		// perform some emulation work in case there is some and we are inside a local type only
@@ -173,8 +171,9 @@
 		}
 	}
 
-	public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
+	public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
+		if (!flowInfo.isReachable()) return;
 		if (binding.isPrivate()
 			&& (currentScope.enclosingSourceType() != binding.declaringClass)) {
 
@@ -192,6 +191,20 @@
 		}
 	}
 
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		output.append("new "); //$NON-NLS-1$
+		type.printExpression(0, output); 
+		output.append('(');
+		if (arguments != null) {
+			for (int i = 0; i < arguments.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				arguments[i].printExpression(0, output);
+			}
+		}
+		return output.append(')');
+	}
+	
 	public TypeBinding resolveType(BlockScope scope) {
 
 		// Propagate the type checking to the arguments, and check if the constructor is defined.
@@ -200,16 +213,25 @@
 		// will check for null after args are resolved
 
 		// buffering the arguments' types
+		boolean argsContainCast = false;
 		TypeBinding[] argumentTypes = NoParameters;
 		if (arguments != null) {
 			boolean argHasError = false;
 			int length = arguments.length;
 			argumentTypes = new TypeBinding[length];
-			for (int i = 0; i < length; i++)
-				if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
+			for (int i = 0; i < length; i++) {
+				Expression argument = this.arguments[i];
+				if (argument instanceof CastExpression) {
+					argument.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+					argsContainCast = true;
+				}
+				if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
 					argHasError = true;
-			if (argHasError)
+				}
+			}
+			if (argHasError) {
 				return this.resolvedType;
+			}
 		}
 		if (this.resolvedType == null)
 			return null;
@@ -218,21 +240,26 @@
 			scope.problemReporter().cannotInstantiate(type, this.resolvedType);
 			return this.resolvedType;
 		}
-		ReferenceBinding allocatedType = (ReferenceBinding) this.resolvedType;
-		if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this))
+		ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType;
+		if (!(binding = scope.getConstructor(allocationType, argumentTypes, this))
 			.isValidBinding()) {
 			if (binding.declaringClass == null)
-				binding.declaringClass = allocatedType;
+				binding.declaringClass = allocationType;
 			scope.problemReporter().invalidConstructor(this, binding);
 			return this.resolvedType;
 		}
 		if (isMethodUseDeprecated(binding, scope))
 			scope.problemReporter().deprecatedMethod(binding, this);
 
-		if (arguments != null)
-			for (int i = 0; i < arguments.length; i++)
+		if (arguments != null) {
+			for (int i = 0; i < arguments.length; i++) {
 				arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
-		return allocatedType;
+			}
+			if (argsContainCast) {
+				CastExpression.checkNeedForArgumentCasts(scope, null, allocationType, binding, this.arguments, argumentTypes, this);
+			}
+		}
+		return allocationType;
 	}
 
 	public void setActualReceiverType(ReferenceBinding receiverType) {
@@ -247,25 +274,7 @@
 		// ignored
 	}
 
-	public String toStringExpression() {
-
-		String s = "new " + type.toString(0); //$NON-NLS-1$
-		if (arguments == null)
-			s = s + "()"; //$NON-NLS-1$
-		else {
-			s = s + "("; //$NON-NLS-1$
-			for (int i = 0; i < arguments.length; i++) {
-				s = s + arguments[i].toStringExpression();
-				if (i == (arguments.length - 1))
-					s = s + ")"; //$NON-NLS-1$
-				else
-					s = s + ", "; //$NON-NLS-1$
-			}
-		}
-		return s;
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
 			int argumentsLength;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AnonymousLocalTypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AnonymousLocalTypeDeclaration.java
deleted file mode 100644
index 4b05879..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AnonymousLocalTypeDeclaration.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.compiler.ast;
-
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-
-public class AnonymousLocalTypeDeclaration extends LocalTypeDeclaration {
-
-	public static final char[] ANONYMOUS_EMPTY_NAME = new char[] {};
-	public QualifiedAllocationExpression allocation;
-
-	public AnonymousLocalTypeDeclaration(CompilationResult compilationResult) {
-		super(compilationResult);
-		modifiers = AccDefault;
-		name = ANONYMOUS_EMPTY_NAME;
-	} 
-	
-	// use a default name in order to th name lookup 
-	// to operate just like a regular type (which has a name)
-	//without checking systematically if the naem is null .... 
-	public MethodBinding createsInternalConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
-
-		//Add to method'set, the default constuctor that just recall the
-		//super constructor with the same arguments
-		String baseName = "$anonymous"; //$NON-NLS-1$
-		TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
-		int argumentsLength = argumentTypes.length;
-		//the constructor
-		ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationResult);
-		cd.selector = new char[] { 'x' }; //no maining
-		cd.sourceStart = sourceStart;
-		cd.sourceEnd = sourceEnd;
-		cd.modifiers = modifiers & AccVisibilityMASK;
-		cd.isDefaultConstructor = true;
-
-		if (argumentsLength > 0) {
-			Argument[] arguments = (cd.arguments = new Argument[argumentsLength]);
-			for (int i = argumentsLength; --i >= 0;) {
-				arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, AccDefault);
-			}
-		}
-
-		//the super call inside the constructor
-		cd.constructorCall = SuperReference.implicitSuperConstructorCall();
-		cd.constructorCall.sourceStart = sourceStart;
-		cd.constructorCall.sourceEnd = sourceEnd;
-
-		if (argumentsLength > 0) {
-			Expression[] args;
-			args = cd.constructorCall.arguments = new Expression[argumentsLength];
-			for (int i = argumentsLength; --i >= 0;) {
-				args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
-			}
-		}
-
-		//adding the constructor in the methods list
-		if (methods == null) {
-			methods = new AbstractMethodDeclaration[] { cd };
-		} else {
-			AbstractMethodDeclaration[] newMethods;
-			System.arraycopy(
-				methods,
-				0,
-				newMethods = new AbstractMethodDeclaration[methods.length + 1],
-				1,
-				methods.length);
-			newMethods[0] = cd;
-			methods = newMethods;
-		}
-
-		//============BINDING UPDATE==========================
-		cd.binding = new MethodBinding(
-				cd.modifiers, //methodDeclaration
-				argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
-				inheritedConstructorBinding.thrownExceptions, //exceptions
-				binding); //declaringClass
-				
-		cd.scope = new MethodScope(scope, cd, true);
-		cd.bindArguments();
-		cd.constructorCall.resolve(cd.scope);
-
-		if (binding.methods == null) {
-			binding.methods = new MethodBinding[] { cd.binding };
-		} else {
-			MethodBinding[] newMethods;
-			System.arraycopy(
-				binding.methods,
-				0,
-				newMethods = new MethodBinding[binding.methods.length + 1],
-				1,
-				binding.methods.length);
-			newMethods[0] = cd.binding;
-			binding.methods = newMethods;
-		}
-		//===================================================
-
-		return cd.binding;
-
-	}
-	public void resolve(BlockScope scope) {
-
-		if (binding != null) {
-			// remember local types binding for innerclass emulation propagation
-			scope.referenceCompilationUnit().record((LocalTypeBinding)binding);
-		}
-		// scope and binding are provided in updateBindingSuperclass 
-		resolve();
-		updateMaxFieldCount();
-	}
-
-	public String toString(int tab) {
-
-		return toStringBody(tab);
-	}
-
-	/**
-	 *	Iteration for a local anonymous innertype
-	 *
-	 */
-	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
-		BlockScope blockScope) {
-
-		if (ignoreFurtherInvestigation)
-			return;
-		try {
-			if (visitor.visit(this, blockScope)) {
-
-				int fieldsLength;
-				int methodsLength;
-				int memberTypesLength;
-
-				// <superclass> is bound to the actual type from the allocation expression
-				// therefore it has already been iterated at this point.
-
-				if (memberTypes != null) {
-					memberTypesLength = memberTypes.length;
-					for (int i = 0; i < memberTypesLength; i++)
-						memberTypes[i].traverse(visitor, scope);
-				}
-				if (fields != null) {
-					fieldsLength = fields.length;
-					for (int i = 0; i < fieldsLength; i++) {
-						FieldDeclaration field;
-						if ((field = fields[i]).isStatic()) {
-							// local type cannot have static fields
-						} else {
-							field.traverse(visitor, initializerScope);
-						}
-					}
-				}
-				if (methods != null) {
-					methodsLength = methods.length;
-					for (int i = 0; i < methodsLength; i++)
-						methods[i].traverse(visitor, scope);
-				}
-			}
-			visitor.endVisit(this, blockScope);
-		} catch (AbortType e) {
-		}
-	}
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
index cca9639..e2f2171 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
@@ -10,14 +10,18 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class Argument extends LocalDeclaration {
 	
+	// prefix for setter method (to recognize special hiding argument)
+	private final static char[] SET = "set".toCharArray(); //$NON-NLS-1$
+
 	public Argument(char[] name, long posNom, TypeReference tr, int modifiers) {
 
-		super(null, name, (int) (posNom >>> 32), (int) posNom);
+		super(name, (int) (posNom >>> 32), (int) posNom);
 		this.declarationSourceEnd = (int) posNom;
 		this.modifiers = modifiers;
 		type = tr;
@@ -30,21 +34,55 @@
 			this.type.resolvedType = typeBinding;
 		// record the resolved type into the type reference
 		int modifierFlag = this.modifiers;
-		if ((this.binding = scope.duplicateName(this.name)) != null) {
-			//the name already exist....may carry on with the first binding ....
-			scope.problemReporter().redefineArgument(this);
-		} else {
-			scope.addLocalVariable(
-				this.binding =
-					new LocalVariableBinding(this, typeBinding, modifierFlag, true));
-			//true stand for argument instead of just local
-			if (typeBinding != null && isTypeUseDeprecated(typeBinding, scope))
-				scope.problemReporter().deprecatedType(typeBinding, this.type);
-			this.binding.declaration = this;
-			this.binding.useFlag = used ? LocalVariableBinding.USED : LocalVariableBinding.UNUSED;
+
+		Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+		if (existingVariable != null && existingVariable.isValidBinding()){
+			if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
+				scope.problemReporter().redefineArgument(this);
+				return;
+			} else {
+				boolean isSpecialArgument = false;
+				if (existingVariable instanceof FieldBinding) {
+					if (scope.isInsideConstructor()) {
+						isSpecialArgument = true; // constructor argument
+					} else {
+						AbstractMethodDeclaration methodDecl = scope.referenceMethod();
+						if (methodDecl != null && CharOperation.prefixEquals(SET, methodDecl.selector)) {
+							isSpecialArgument = true; // setter argument
+						}
+					}
+				}
+				scope.problemReporter().localVariableHiding(this, existingVariable, isSpecialArgument);
+			}
 		}
+
+		scope.addLocalVariable(
+			this.binding =
+				new LocalVariableBinding(this, typeBinding, modifierFlag, true));
+		//true stand for argument instead of just local
+		if (typeBinding != null && isTypeUseDeprecated(typeBinding, scope))
+			scope.problemReporter().deprecatedType(typeBinding, this.type);
+		this.binding.declaration = this;
+		this.binding.useFlag = used ? LocalVariableBinding.USED : LocalVariableBinding.UNUSED;
 	}
 
+	public StringBuffer print(int indent, StringBuffer output) {
+
+		printIndent(indent, output);
+		printModifiers(this.modifiers, output);
+		if (type == null) {
+			output.append("<no type> "); //$NON-NLS-1$
+		} else {
+			type.print(0, output).append(' '); 
+		}
+		return output.append(this.name);
+	}
+
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+
+		return print(indent, output).append(';');
+	}	
+
 	public TypeBinding resolveForCatch(BlockScope scope) {
 
 		// resolution on an argument of a catch clause
@@ -54,33 +92,24 @@
 		TypeBinding tb = type.resolveTypeExpecting(scope, scope.getJavaLangThrowable());
 		if (tb == null)
 			return null;
-		if ((binding = scope.duplicateName(name)) != null) {
-			// the name already exists....may carry on with the first binding ....
-			scope.problemReporter().redefineArgument(this);
-			return null;
+
+		Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+		if (existingVariable != null && existingVariable.isValidBinding()){
+			if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
+				scope.problemReporter().redefineArgument(this);
+				return null;
+			} else {
+				scope.problemReporter().localVariableHiding(this, existingVariable, false);
+			}
 		}
+
 		binding = new LocalVariableBinding(this, tb, modifiers, false); // argument decl, but local var  (where isArgument = false)
 		scope.addLocalVariable(binding);
 		binding.constant = NotAConstant;
 		return tb;
 	}
 
-	public String toString(int tab) {
-
-		String s = ""; //$NON-NLS-1$
-		if (modifiers != AccDefault) {
-			s += modifiersString(modifiers);
-		}
-		if (type == null) {
-			s += "<no type> "; //$NON-NLS-1$
-		} else {
-			s += type.toString(tab) + " "; //$NON-NLS-1$
-		}
-		s += new String(name);
-		return s;
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		
 		if (visitor.visit(this, scope)) {
 			if (type != null)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
index f4429a3..9de22da 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -89,6 +89,24 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
+
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		output.append("new "); //$NON-NLS-1$
+		type.print(0, output); 
+		for (int i = 0; i < dimensions.length; i++) {
+			if (dimensions[i] == null)
+				output.append("[]"); //$NON-NLS-1$
+			else {
+				output.append('[');
+				dimensions[i].printExpression(0, output);
+				output.append(']');
+			}
+		} 
+		if (initializer != null) initializer.printExpression(0, output);
+		return output;
+	}
+	
 	public TypeBinding resolveType(BlockScope scope) {
 
 		// Build an array type reference using the current dimensions
@@ -152,21 +170,8 @@
 		return this.resolvedType;
 	}
 
-	public String toStringExpression() {
 
-		String s = "new " + type.toString(0); //$NON-NLS-1$
-		for (int i = 0; i < dimensions.length; i++) {
-			if (dimensions[i] == null)
-				s = s + "[]"; //$NON-NLS-1$
-			else
-				s = s + "[" + dimensions[i].toStringExpression() + "]"; //$NON-NLS-2$ //$NON-NLS-1$
-		} 
-		if (initializer != null)
-			s = s + initializer.toStringExpression();
-		return s;
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
 			int dimensionsLength = dimensions.length;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
index 1187de6..2805b2e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
@@ -10,186 +10,200 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class ArrayInitializer extends Expression {
+		
 	public Expression[] expressions;
 	public ArrayBinding binding; //the type of the { , , , }
+	
+	/**
+	 * ArrayInitializer constructor comment.
+	 */
+	public ArrayInitializer() {
 
-/**
- * ArrayInitializer constructor comment.
- */
-public ArrayInitializer() {
-	super();
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-	if (expressions != null) {
-		for (int i = 0, max = expressions.length; i < max; i++) {
-			flowInfo = expressions[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
-		}
+		super();
 	}
-	return flowInfo;
-}
-/**
- * Code generation for a array initializer
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
-	// Flatten the values and compute the dimensions, by iterating in depth into nested array initializers
 
-	int pc = codeStream.position;
-	int expressionLength = (expressions == null) ? 0: expressions.length;
-	codeStream.generateInlinedValue(expressionLength);
-	codeStream.newArray(currentScope, binding);
-	if (expressions != null) {
-		// binding is an ArrayType, so I can just deal with the dimension
-		int elementsTypeID = binding.dimensions > 1 ? -1 : binding.leafComponentType.id;
-		for (int i = 0; i < expressionLength; i++) {
-			Expression expr;
-			if ((expr = expressions[i]).constant != NotAConstant) {
-				switch (elementsTypeID) { // filter out initializations to default values
-					case T_int :
-					case T_short :
-					case T_byte :
-					case T_char :
-					case T_long :
-						if (expr.constant.longValue() != 0) {
-							codeStream.dup();
-							codeStream.generateInlinedValue(i);
-							expr.generateCode(currentScope, codeStream, true);
-							codeStream.arrayAtPut(elementsTypeID, false);
-						}
-						break;
-					case T_float :
-					case T_double :
-						double constantValue = expr.constant.doubleValue();
-						if (constantValue == -0.0 || constantValue != 0) {
-							codeStream.dup();
-							codeStream.generateInlinedValue(i);
-							expr.generateCode(currentScope, codeStream, true);
-							codeStream.arrayAtPut(elementsTypeID, false);
-						}
-						break;
-					case T_boolean :
-						if (expr.constant.booleanValue() != false) {
-							codeStream.dup();
-							codeStream.generateInlinedValue(i);
-							expr.generateCode(currentScope, codeStream, true);
-							codeStream.arrayAtPut(elementsTypeID, false);
-						}
-						break;
-					default :
-						if (!(expr instanceof NullLiteral)) {
-							codeStream.dup();
-							codeStream.generateInlinedValue(i);
-							expr.generateCode(currentScope, codeStream, true);
-							codeStream.arrayAtPut(elementsTypeID, false);
-						}
-				}
-			} else if (!(expr instanceof NullLiteral)) {
-				codeStream.dup();
-				codeStream.generateInlinedValue(i);
-				expr.generateCode(currentScope, codeStream, true);
-				codeStream.arrayAtPut(elementsTypeID, false);
+	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+		if (expressions != null) {
+			for (int i = 0, max = expressions.length; i < max; i++) {
+				flowInfo = expressions[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
 			}
 		}
+		return flowInfo;
 	}
-	if (!valueRequired) {
-		codeStream.pop();
+
+	/**
+	 * Code generation for a array initializer
+	 */
+	public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
+		// Flatten the values and compute the dimensions, by iterating in depth into nested array initializers
+		int pc = codeStream.position;
+		int expressionLength = (expressions == null) ? 0: expressions.length;
+		codeStream.generateInlinedValue(expressionLength);
+		codeStream.newArray(currentScope, binding);
+		if (expressions != null) {
+			// binding is an ArrayType, so I can just deal with the dimension
+			int elementsTypeID = binding.dimensions > 1 ? -1 : binding.leafComponentType.id;
+			for (int i = 0; i < expressionLength; i++) {
+				Expression expr;
+				if ((expr = expressions[i]).constant != NotAConstant) {
+					switch (elementsTypeID) { // filter out initializations to default values
+						case T_int :
+						case T_short :
+						case T_byte :
+						case T_char :
+						case T_long :
+							if (expr.constant.longValue() != 0) {
+								codeStream.dup();
+								codeStream.generateInlinedValue(i);
+								expr.generateCode(currentScope, codeStream, true);
+								codeStream.arrayAtPut(elementsTypeID, false);
+							}
+							break;
+						case T_float :
+						case T_double :
+							double constantValue = expr.constant.doubleValue();
+							if (constantValue == -0.0 || constantValue != 0) {
+								codeStream.dup();
+								codeStream.generateInlinedValue(i);
+								expr.generateCode(currentScope, codeStream, true);
+								codeStream.arrayAtPut(elementsTypeID, false);
+							}
+							break;
+						case T_boolean :
+							if (expr.constant.booleanValue() != false) {
+								codeStream.dup();
+								codeStream.generateInlinedValue(i);
+								expr.generateCode(currentScope, codeStream, true);
+								codeStream.arrayAtPut(elementsTypeID, false);
+							}
+							break;
+						default :
+							if (!(expr instanceof NullLiteral)) {
+								codeStream.dup();
+								codeStream.generateInlinedValue(i);
+								expr.generateCode(currentScope, codeStream, true);
+								codeStream.arrayAtPut(elementsTypeID, false);
+							}
+					}
+				} else if (!(expr instanceof NullLiteral)) {
+					codeStream.dup();
+					codeStream.generateInlinedValue(i);
+					expr.generateCode(currentScope, codeStream, true);
+					codeStream.arrayAtPut(elementsTypeID, false);
+				}
+			}
+		}
+		if (!valueRequired) {
+			codeStream.pop();
+		}
+		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
-	codeStream.recordPositionsFrom(pc, this.sourceStart);
-}
-public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedTb) {
-	// Array initializers can only occur on the right hand side of an assignment
-	// expression, therefore the expected type contains the valid information
-	// concerning the type that must be enforced by the elements of the array initializer.
 
-	// this method is recursive... (the test on isArrayType is the stop case)
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+	
+		output.append('{');
+		if (expressions != null) { 	
+			int j = 20 ; 
+			for (int i = 0 ; i < expressions.length ; i++) {	
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				expressions[i].printExpression(0, output);
+				j -- ;
+				if (j == 0) {
+					output.append('\n');
+					printIndent(indent+1, output);
+					j = 20;
+				}
+			}
+		}
+		return output.append('}');
+	}
 
-	constant = NotAConstant;
-	if (expectedTb.isArrayType()) {
-		binding = (ArrayBinding) expectedTb;
-		if (expressions == null)
+	public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedTb) {
+		// Array initializers can only occur on the right hand side of an assignment
+		// expression, therefore the expected type contains the valid information
+		// concerning the type that must be enforced by the elements of the array initializer.
+	
+		// this method is recursive... (the test on isArrayType is the stop case)
+	
+		constant = NotAConstant;
+		if (expectedTb.isArrayType()) {
+			binding = (ArrayBinding) expectedTb;
+			if (expressions == null)
+				return binding;
+			TypeBinding expectedElementsTb = binding.elementsType(scope);
+			if (expectedElementsTb.isBaseType()) {
+				for (int i = 0, length = expressions.length; i < length; i++) {
+					Expression expression = expressions[i];
+					TypeBinding expressionTb =
+						(expression instanceof ArrayInitializer)
+							? expression.resolveTypeExpecting(scope, expectedElementsTb)
+							: expression.resolveType(scope);
+					if (expressionTb == null)
+						return null;
+	
+					// Compile-time conversion required?
+					if (expression.isConstantValueOfTypeAssignableToType(expressionTb, expectedElementsTb)) {
+						expression.implicitWidening(expectedElementsTb, expressionTb);
+					} else if (BaseTypeBinding.isWidening(expectedElementsTb.id, expressionTb.id)) {
+						expression.implicitWidening(expectedElementsTb, expressionTb);
+					} else {
+						scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionTb, expectedElementsTb);
+						return null;
+					}
+				}
+			} else {
+				for (int i = 0, length = expressions.length; i < length; i++)
+					if (expressions[i].resolveTypeExpecting(scope, expectedElementsTb) == null)
+						return null;
+			}
 			return binding;
-		TypeBinding expectedElementsTb = binding.elementsType(scope);
-		if (expectedElementsTb.isBaseType()) {
-			for (int i = 0, length = expressions.length; i < length; i++) {
-				Expression expression = expressions[i];
-				TypeBinding expressionTb =
-					(expression instanceof ArrayInitializer)
-						? expression.resolveTypeExpecting(scope, expectedElementsTb)
-						: expression.resolveType(scope);
-				if (expressionTb == null)
-					return null;
-
-				// Compile-time conversion required?
-				if (expression.isConstantValueOfTypeAssignableToType(expressionTb, expectedElementsTb)) {
-					expression.implicitWidening(expectedElementsTb, expressionTb);
-				} else if (BaseTypeBinding.isWidening(expectedElementsTb.id, expressionTb.id)) {
-					expression.implicitWidening(expectedElementsTb, expressionTb);
-				} else {
-					scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionTb, expectedElementsTb);
-					return null;
-				}
-			}
-		} else {
-			for (int i = 0, length = expressions.length; i < length; i++)
-				if (expressions[i].resolveTypeExpecting(scope, expectedElementsTb) == null)
-					return null;
 		}
-		return binding;
+		
+		// infer initializer type for error reporting based on first element
+		TypeBinding leafElementType = null;
+		int dim = 1;
+		if (expressions == null) {
+			leafElementType = scope.getJavaLangObject();
+		} else {
+			Expression currentExpression = expressions[0];
+			while(currentExpression != null && currentExpression instanceof ArrayInitializer) {
+				dim++;
+				Expression[] subExprs = ((ArrayInitializer) currentExpression).expressions;
+				if (subExprs == null){
+					leafElementType = scope.getJavaLangObject();
+					currentExpression = null;
+					break;
+				}
+				currentExpression = ((ArrayInitializer) currentExpression).expressions[0];
+			}
+			if (currentExpression != null) {
+				leafElementType = currentExpression.resolveType(scope);
+			}
+		}
+		if (leafElementType != null) {
+			TypeBinding probableTb = scope.createArray(leafElementType, dim);
+			scope.problemReporter().typeMismatchErrorActualTypeExpectedType(this, probableTb, expectedTb);
+		}
+		return null;
 	}
 	
-	// infer initializer type for error reporting based on first element
-	TypeBinding leafElementType = null;
-	int dim = 1;
-	if (expressions == null) {
-		leafElementType = scope.getJavaLangObject();
-	} else {
-		Expression currentExpression = expressions[0];
-		while(currentExpression != null && currentExpression instanceof ArrayInitializer) {
-			dim++;
-			Expression[] subExprs = ((ArrayInitializer) currentExpression).expressions;
-			if (subExprs == null){
-				leafElementType = scope.getJavaLangObject();
-				currentExpression = null;
-				break;
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+		if (visitor.visit(this, scope)) {
+			if (expressions != null) {
+				int expressionsLength = expressions.length;
+				for (int i = 0; i < expressionsLength; i++)
+					expressions[i].traverse(visitor, scope);
 			}
-			currentExpression = ((ArrayInitializer) currentExpression).expressions[0];
 		}
-		if (currentExpression != null) {
-			leafElementType = currentExpression.resolveType(scope);
-		}
+		visitor.endVisit(this, scope);
 	}
-	if (leafElementType != null) {
-		TypeBinding probableTb = scope.createArray(leafElementType, dim);
-		scope.problemReporter().typeMismatchErrorActualTypeExpectedType(this, probableTb, expectedTb);
-	}
-	return null;
-}
-public String toStringExpression() {
-
-	String s = "{" ; //$NON-NLS-1$
-	if (expressions != null)
-	{ 	int j = 20 ; 
-		for (int i = 0 ; i < expressions.length ; i++)
-		{	s = s + expressions[i].toStringExpression() + "," ; //$NON-NLS-1$
-			j -- ;
-			if (j == 0)
-			{	s = s + "\n                "; j = 20;}}}; //$NON-NLS-1$
-	s = s + "}"; //$NON-NLS-1$
-	return s;}
-
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	if (visitor.visit(this, scope)) {
-		if (expressions != null) {
-			int expressionsLength = expressions.length;
-			for (int i = 0; i < expressionsLength; i++)
-				expressions[i].traverse(visitor, scope);
-		}
-	}
-	visitor.endVisit(this, scope);
-}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
index 254e44e..a95741e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
@@ -10,45 +10,57 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
 	int dimensions;
-public ArrayQualifiedTypeReference(char[][] sources , int dim, long[] poss) {
-	super( sources , poss);
-	dimensions = dim ;
-}
-public ArrayQualifiedTypeReference(char[][] sources , TypeBinding tb, int dim, long[] poss) {
-	super( sources , tb, poss);
-	dimensions = dim ;
-}
-public int dimensions() {
-	return dimensions;
-}
-public TypeBinding getTypeBinding(Scope scope) {
-	if (this.resolvedType != null)
-		return this.resolvedType;
-	if (dimensions > 255) {
-		scope.problemReporter().tooManyDimensions(this);
+	
+	public ArrayQualifiedTypeReference(char[][] sources , int dim, long[] poss) {
+		
+		super( sources , poss);
+		dimensions = dim ;
 	}
-	return scope.createArray(scope.getType(tokens), dimensions);
-}
-public String toStringExpression(int tab){
-	/* slow speed */
-
-	String s = super.toStringExpression(tab)  ;
-	if (dimensions == 1 ) return s + "[]" ; //$NON-NLS-1$
-	for (int i=1 ; i <= dimensions ; i++)
-		s = s + "[]" ; //$NON-NLS-1$
-	return s ;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
+	
+	public ArrayQualifiedTypeReference(char[][] sources , TypeBinding tb, int dim, long[] poss) {
+		
+		super( sources , tb, poss);
+		dimensions = dim ;
+	}
+	
+	public int dimensions() {
+		
+		return dimensions;
+	}
+	
+	public TypeBinding getTypeBinding(Scope scope) {
+		
+		if (this.resolvedType != null)
+			return this.resolvedType;
+		if (dimensions > 255) {
+			scope.problemReporter().tooManyDimensions(this);
+		}
+		return scope.createArray(scope.getType(tokens), dimensions);
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output){
+		
+		super.printExpression(indent, output);
+		for (int i = 0 ; i < dimensions ; i++) {
+			output.append("[]"); //$NON-NLS-1$
+		}
+		return output;
+	}
+	
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+	
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
index 677fe96..5489e9f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -158,6 +158,12 @@
 		codeStream.arrayAtPut(this.resolvedType.id, false);
 	}
 
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		receiver.printExpression(0, output).append('[');
+		return position.printExpression(0, output).append(']');
+	} 
+
 	public TypeBinding resolveType(BlockScope scope) {
 
 		constant = Constant.NotAConstant;
@@ -176,13 +182,7 @@
 		return this.resolvedType;
 	}
 
-	public String toStringExpression() {
-
-		return receiver.toStringExpression() + "[" //$NON-NLS-1$
-		+position.toStringExpression() + "]"; //$NON-NLS-1$
-	} 
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		
 		if (visitor.visit(this, scope)) {
 			receiver.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
index 413d713..f4fbb98 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
@@ -10,46 +10,57 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class ArrayTypeReference extends SingleTypeReference {
 	public int dimensions;
-/**
- * ArrayTypeReference constructor comment.
- * @param source char[]
- * @param dim int
- * @param pos int
- */
-public ArrayTypeReference(char[] source, int dim, long pos) {
-	super(source, pos);
-	dimensions = dim ;
-}
-public ArrayTypeReference(char[] source, TypeBinding tb, int dim, long pos) {
-	super(source, tb, pos);
-	dimensions = dim ;}
-public int dimensions() {
-	return dimensions;
-}
-public TypeBinding getTypeBinding(Scope scope) {
-	if (this.resolvedType != null)
-		return this.resolvedType;
-	if (dimensions > 255) {
-		scope.problemReporter().tooManyDimensions(this);
+
+	/**
+	 * ArrayTypeReference constructor comment.
+	 * @param source char[]
+	 * @param dim int
+	 * @param pos int
+	 */
+	public ArrayTypeReference(char[] source, int dimensions, long pos) {
+		
+		super(source, pos);
+		this.dimensions = dimensions ;
 	}
-	return scope.createArray(scope.getType(token), dimensions);
-
-}
-public String toStringExpression(int tab){
-
-	String s = super.toStringExpression(tab)  ;
-	if (dimensions == 1 ) return s + "[]" ; //$NON-NLS-1$
-	for (int i=1 ; i <= dimensions ; i++)
-		s = s + "[]" ; //$NON-NLS-1$
-	return s ;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
+	
+	public ArrayTypeReference(char[] source, TypeBinding tb, int dimensions, long pos) {
+		
+		super(source, tb, pos);
+		this.dimensions = dimensions ;
+	}
+	
+	public int dimensions() {
+		
+		return dimensions;
+	}
+	
+	public TypeBinding getTypeBinding(Scope scope) {
+		
+		if (this.resolvedType != null) return this.resolvedType;
+		if (dimensions > 255) {
+			scope.problemReporter().tooManyDimensions(this);
+		}
+		return scope.createArray(scope.getType(token), dimensions);
+	
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output){
+	
+		super.printExpression(indent, output)  ;
+		for (int i= 0 ; i < dimensions ; i++) {
+			output.append("[]"); //$NON-NLS-1$
+		}
+		return output;
+	}
+	
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
index 65ebf9a..c26461e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
@@ -14,7 +14,7 @@
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 
 public class AssertStatement extends Statement {
 	
@@ -73,7 +73,7 @@
 		}
 		
 		// add the assert support in the clinit
-		manageSyntheticAccessIfNecessary(currentScope);
+		manageSyntheticAccessIfNecessary(currentScope, flowInfo);
 		if (isOptimizedFalseAssertion) {
 			return flowInfo; // if assertions are enabled, the following code will be unreachable
 		} else {
@@ -92,18 +92,25 @@
 			Label assertionActivationLabel = new Label(codeStream);
 			codeStream.getstatic(this.assertionSyntheticFieldBinding);
 			codeStream.ifne(assertionActivationLabel);
-			Label falseLabel = new Label(codeStream);
-			assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new Label(codeStream)), null , true);
-			codeStream.newJavaLangAssertionError();
-			codeStream.dup();
-			if (exceptionArgument != null) {
-				exceptionArgument.generateCode(currentScope, codeStream, true);
-				codeStream.invokeJavaLangAssertionErrorConstructor(exceptionArgument.implicitConversion & 0xF);
+			
+			Constant cst = this.assertExpression.optimizedBooleanConstant();		
+			boolean isOptimizedTrueAssertion = cst != NotAConstant && cst.booleanValue() == true;
+			if (isOptimizedTrueAssertion) {
+				this.assertExpression.generateCode(currentScope, codeStream, false);
 			} else {
-				codeStream.invokeJavaLangAssertionErrorDefaultConstructor();
-			}
-			codeStream.athrow();
-			falseLabel.place();
+				Label falseLabel = new Label(codeStream);
+				this.assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new Label(codeStream)), null , true);
+				codeStream.newJavaLangAssertionError();
+				codeStream.dup();
+				if (exceptionArgument != null) {
+					exceptionArgument.generateCode(currentScope, codeStream, true);
+					codeStream.invokeJavaLangAssertionErrorConstructor(exceptionArgument.implicitConversion & 0xF);
+				} else {
+					codeStream.invokeJavaLangAssertionErrorDefaultConstructor();
+				}
+				codeStream.athrow();
+				falseLabel.place();
+			}			
 			assertionActivationLabel.place();
 		}
 		
@@ -128,7 +135,7 @@
 		}
 	}
 	
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
 			assertExpression.traverse(visitor, scope);
@@ -139,8 +146,10 @@
 		visitor.endVisit(this, scope);
 	}	
 	
-	public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
+	public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
+		if (!flowInfo.isReachable()) return;
+		
 		// need assertion flag: $assertionsDisabled on outer most source clas
 		// (in case of static member of interface, will use the outermost static member - bug 22334)
 		SourceTypeBinding outerMostClass = currentScope.enclosingSourceType();
@@ -158,23 +167,22 @@
 		for (int i = 0, max = methods.length; i < max; i++) {
 			AbstractMethodDeclaration method = methods[i];
 			if (method.isClinit()) {
-				((Clinit) method).addSupportForAssertion(assertionSyntheticFieldBinding);
+				((Clinit) method).setAssertionSupport(assertionSyntheticFieldBinding);
 				break;
 			}
 		}
 	}
 
-	public String toString(int tab) {
+	public StringBuffer printStatement(int tab, StringBuffer output) {
 
-		StringBuffer buffer = new StringBuffer(tabString(tab));
-		buffer.append("assert "); //$NON-NLS-1$
-		buffer.append(this.assertExpression);
+		printIndent(tab, output);
+		output.append("assert "); //$NON-NLS-1$
+		this.assertExpression.printExpression(0, output);
 		if (this.exceptionArgument != null) {
-			buffer.append(":"); //$NON-NLS-1$
-			buffer.append(this.exceptionArgument);
-			buffer.append(";"); //$NON-NLS-1$
+			output.append(": "); //$NON-NLS-1$
+			this.exceptionArgument.printExpression(0, output);
 		}
-		return buffer.toString();
+		return output.append(';');
 	}
 	
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index 8bdbbda..601ec74 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -11,7 +11,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -89,13 +89,38 @@
 		}
 		return null;
 	}
+	public StringBuffer print(int indent, StringBuffer output) {
+
+		//no () when used as a statement 
+		printIndent(indent, output);
+		return printExpressionNoParenthesis(indent, output);
+	}
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		//subclass redefine printExpressionNoParenthesis()
+		output.append('(');
+		return printExpressionNoParenthesis(0, output).append(')');
+	} 
+
+	public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+
+		lhs.printExpression(indent, output).append(" = "); //$NON-NLS-1$
+		return expression.printExpression(0, output);
+	}
+	
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+
+		//no () when used as a statement 
+		return print(indent, output).append(';');
+	}
 
 	public TypeBinding resolveType(BlockScope scope) {
 
 		// due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference
 		constant = NotAConstant;
-		if (!(this.lhs instanceof Reference)) {
+		if (!(this.lhs instanceof Reference) || this.lhs.isThis()) {
 			scope.problemReporter().expressionShouldBeAVariable(this.lhs);
+			return null;
 		}
 		this.resolvedType = lhs.resolveType(scope); // expressionType contains the assignment type (lhs Type)
 		TypeBinding rhsType = expression.resolveType(scope);
@@ -118,29 +143,25 @@
 			this.resolvedType);
 		return this.resolvedType;
 	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveTypeExpecting(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+	 */
+	public TypeBinding resolveTypeExpecting(
+			BlockScope scope,
+			TypeBinding expectedType) {
 
-	public String toString(int tab) {
+		TypeBinding type = super.resolveTypeExpecting(scope, expectedType);
+		// signal possible accidental boolean assignment (instead of using '==' operator)
+		if (expectedType == BooleanBinding 
+				&& this.lhs.resolvedType == BooleanBinding 
+				&& (this.lhs.bits & IsStrictlyAssignedMASK) != 0) {
+			scope.problemReporter().possibleAccidentalBooleanAssignment(this);
+		}
 
-		//no () when used as a statement 
-		return tabString(tab) + toStringExpressionNoParenthesis();
+		return type;
 	}
 
-	public String toStringExpression() {
-
-		//subclass redefine toStringExpressionNoParenthesis()
-		return "(" + toStringExpressionNoParenthesis() + ")"; //$NON-NLS-2$ //$NON-NLS-1$
-	} 
-	
-	public String toStringExpressionNoParenthesis() {
-
-		return lhs.toStringExpression() + " " //$NON-NLS-1$
-			+ "=" //$NON-NLS-1$
-			+ ((expression.constant != null) && (expression.constant != NotAConstant)
-				? " /*cst:" + expression.constant.toString() + "*/ " //$NON-NLS-1$ //$NON-NLS-2$
-				: " ")  //$NON-NLS-1$
-			+ expression.toStringExpression();
-	}
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		
 		if (visitor.visit(this, scope)) {
 			lhs.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AstNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AstNode.java
deleted file mode 100644
index 76a45e3..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AstNode.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.compiler.ast;
-
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-
-public abstract class AstNode implements BaseTypes, CompilerModifiers, TypeConstants, TypeIds {
-	
-	public int sourceStart, sourceEnd;
-
-	//some global provision for the hierarchy
-	public final static Constant NotAConstant = Constant.NotAConstant;
-
-	// storage for internal flags (32 bits)			BIT USAGE
-	public final static int Bit1 = 0x1; 			// return type (operators) | name reference kind (name ref) | add assertion (type decl)
-	public final static int Bit2 = 0x2; 			// return type (operators) | name reference kind (name ref) | has local type (type, method, field decl)
-	public final static int Bit3 = 0x4; 			// return type (operators) | name reference kind (name ref) | implicit this (this ref)
-	public final static int Bit4 = 0x8; 			// return type (operators) | first assignment to local (local decl)
-	public final static int Bit5 = 0x10; 			// value for return (binary expression) | 
-	public final static int Bit6 = 0x20; 			// depth (name ref, msg) | only value required (binary expression)
-	public final static int Bit7 = 0x40; 			// depth (name ref, msg) | operator (operators)
-	public final static int Bit8 = 0x80; 			// depth (name ref, msg) | operator (operators) 
-	public final static int Bit9 = 0x100; 			// depth (name ref, msg) | operator (operators)
-	public final static int Bit10= 0x200; 			// depth (name ref, msg) | operator (operators)
-	public final static int Bit11 = 0x400; 			// depth (name ref, msg) | operator (operators)
-	public final static int Bit12 = 0x800; 			// depth (name ref, msg) | operator (operators)
-	public final static int Bit13 = 0x1000; 		// depth (name ref, msg) 
-	public final static int Bit14 = 0x2000; 		// assigned (reference lhs)
-	public final static int Bit15 = 0x4000; 
-	public final static int Bit16 = 0x8000; 
-	public final static int Bit17 = 0x10000; 
-	public final static int Bit18 = 0x20000; 
-	public final static int Bit19 = 0x40000; 
-	public final static int Bit20 = 0x80000; 
-	public final static int Bit21 = 0x100000; 		
-	public final static int Bit22 = 0x200000; 		// parenthesis count (expression)
-	public final static int Bit23 = 0x400000; 		// parenthesis count (expression)
-	public final static int Bit24 = 0x800000; 		// parenthesis count (expression)
-	public final static int Bit25 = 0x1000000; 		// parenthesis count (expression)
-	public final static int Bit26 = 0x2000000; 		// parenthesis count (expression)
-	public final static int Bit27 = 0x4000000; 		// parenthesis count (expression)
-	public final static int Bit28 = 0x8000000; 		// parenthesis count (expression)
-	public final static int Bit29 = 0x10000000; 	// parenthesis count (expression)
-	public final static int Bit30 = 0x20000000; 	// assignment with no effect (assignment)
-	public final static int Bit31 = 0x40000000; 	// local declaration reachable (local decl)
-	public final static int Bit32 = 0x80000000; 	// reachable (statement)
-
-	public int bits = IsReachableMASK; 				// reachable by default
-
-	// for operators 
-	public static final int ReturnTypeIDMASK = Bit1|Bit2|Bit3|Bit4; 
-	public static final int OperatorSHIFT = 6;	// Bit7 -> Bit12
-	public static final int OperatorMASK = Bit7|Bit8|Bit9|Bit10|Bit11|Bit12; // 6 bits for operator ID
-
-	// for binary expressions
-	public static final int ValueForReturnMASK = Bit5; 
-	public static final int OnlyValueRequiredMASK = Bit6; 
-
-	// for name references 
-	public static final int RestrictiveFlagMASK = Bit1|Bit2|Bit3;	
-	public static final int FirstAssignmentToLocalMASK = Bit4;
-	
-	// for this reference
-	public static final int IsImplicitThisMask = Bit3; 
-
-	// for single name references
-	public static final int DepthSHIFT = 5;	// Bit6 -> Bit13
-	public static final int DepthMASK = Bit6|Bit7|Bit8|Bit9|Bit10|Bit11|Bit12|Bit13; // 8 bits for actual depth value (max. 255)
-
-	// for statements 
-	public static final int IsReachableMASK = Bit32; 
-	public static final int IsLocalDeclarationReachableMASK = Bit31; 
-
-	// for type declaration
-	public static final int AddAssertionMASK = Bit1;
-
-	// for type, method and field declarations 
-	public static final int HasLocalTypeMASK = Bit2; // cannot conflict with AddAssertionMASK
-
-	// for expression 
-	public static final int ParenthesizedSHIFT = 21; // Bit22 -> Bit29
-	public static final int ParenthesizedMASK = Bit22|Bit23|Bit24|Bit25|Bit26|Bit27|Bit28|Bit29; // 8 bits for parenthesis count value (max. 255)
-
-	// for assignment
-	public static final int IsAssignmentWithNoEffectMASK = Bit30;	
-	
-	// for references on lhs of assignment (set only for true assignments, as opposed to compound ones)
-	public static final int IsStrictlyAssignedMASK = Bit14;
-	
-	public AstNode() {
-
-		super();
-	}
-
-	public boolean cannotReturn() {
-		return false;
-	}
-
-	public AstNode concreteStatement() {
-		return this;
-	}
-
-	/* Answer true if the field use is considered deprecated.
-	* An access in the same compilation unit is allowed.
-	*/
-	public final boolean isFieldUseDeprecated(FieldBinding field, Scope scope) {
-
-		if (field.isPrivate() && !scope.isDefinedInField(field)) {
-			// ignore cases where field is used from within inside itself 
-			field.modifiers |= AccPrivateUsed;
-		}
-
-		if (!field.isViewedAsDeprecated()) return false;
-
-		// inside same unit - no report
-		if (scope.isDefinedInSameUnit(field.declaringClass)) return false;
-		
-		// if context is deprecated, may avoid reporting
-		if (!scope.environment().options.reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false;
-		return true;
-	}
-
-	public boolean isImplicitThis() {
-		
-		return false;
-	}
-	
-	/* Answer true if the method use is considered deprecated.
-	* An access in the same compilation unit is allowed.
-	*/
-	public final boolean isMethodUseDeprecated(MethodBinding method, Scope scope) {
-
-		if (method.isPrivate() && !scope.isDefinedInMethod(method)) {
-			// ignore cases where method is used from within inside itself (e.g. direct recursions)
-			method.modifiers |= AccPrivateUsed;
-		}
-		
-		if (!method.isViewedAsDeprecated()) return false;
-
-		// inside same unit - no report
-		if (scope.isDefinedInSameUnit(method.declaringClass)) return false;
-		
-		// if context is deprecated, may avoid reporting
-		if (!scope.environment().options.reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false;
-		return true;
-	}
-
-	public boolean isSuper() {
-
-		return false;
-	}
-
-	public boolean isThis() {
-
-		return false;
-	}
-
-	/* Answer true if the type use is considered deprecated.
-	* An access in the same compilation unit is allowed.
-	*/
-	public final boolean isTypeUseDeprecated(TypeBinding type, Scope scope) {
-
-		if (type.isArrayType())
-			type = ((ArrayBinding) type).leafComponentType;
-		if (type.isBaseType())
-			return false;
-
-		ReferenceBinding refType = (ReferenceBinding) type;
-
-		if (refType.isPrivate() && !scope.isDefinedInType(refType)) {
-			// ignore cases where type is used from within inside itself 
-			refType.modifiers |= AccPrivateUsed;
-		}
-
-		if (!refType.isViewedAsDeprecated()) return false;
-		
-		// inside same unit - no report
-		if (scope.isDefinedInSameUnit(refType)) return false;
-		
-		// if context is deprecated, may avoid reporting
-		if (!scope.environment().options.reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false;
-		return true;
-	}
-
-	public static String modifiersString(int modifiers) {
-
-		String s = ""; //$NON-NLS-1$
-		if ((modifiers & AccPublic) != 0)
-			s = s + "public "; //$NON-NLS-1$
-		if ((modifiers & AccPrivate) != 0)
-			s = s + "private "; //$NON-NLS-1$
-		if ((modifiers & AccProtected) != 0)
-			s = s + "protected "; //$NON-NLS-1$
-		if ((modifiers & AccStatic) != 0)
-			s = s + "static "; //$NON-NLS-1$
-		if ((modifiers & AccFinal) != 0)
-			s = s + "final "; //$NON-NLS-1$
-		if ((modifiers & AccSynchronized) != 0)
-			s = s + "synchronized "; //$NON-NLS-1$
-		if ((modifiers & AccVolatile) != 0)
-			s = s + "volatile "; //$NON-NLS-1$
-		if ((modifiers & AccTransient) != 0)
-			s = s + "transient "; //$NON-NLS-1$
-		if ((modifiers & AccNative) != 0)
-			s = s + "native "; //$NON-NLS-1$
-		if ((modifiers & AccAbstract) != 0)
-			s = s + "abstract "; //$NON-NLS-1$
-		return s;
-	}
-
-	/** 
-	 * @deprecated - use field instead
-	*/
-	public int sourceEnd() {
-		return sourceEnd;
-	}
-	
-	/** 
-	 * @deprecated - use field instead
-	*/
-	public int sourceStart() {
-		return sourceStart;
-	}
-
-	public static String tabString(int tab) {
-
-		String s = ""; //$NON-NLS-1$
-		for (int i = tab; i > 0; i--)
-			s = s + "  "; //$NON-NLS-1$
-		return s;
-	}
-
-	public String toString() {
-
-		return toString(0);
-	}
-
-	public String toString(int tab) {
-
-		return "****" + super.toString() + "****";  //$NON-NLS-2$ //$NON-NLS-1$
-	}
-	
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	}
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
index c047dfb..e6ecad0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -1180,12 +1180,14 @@
 						trueLabel,
 						falseLabel,
 						false);
+					Label internalTrueLabel = new Label(codeStream);
 					right.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
 						trueLabel,
 						falseLabel,
 						false);
+					internalTrueLabel.place();
 					if (valueRequired) {
 						if ((bits & OnlyValueRequiredMASK) != 0) {
 							codeStream.iconst_0();
@@ -1222,12 +1224,14 @@
 						false);
 				} else {
 					// x & <something equivalent to false>
+					Label internalTrueLabel = new Label(codeStream);
 					left.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
-						trueLabel,
+						internalTrueLabel,
 						falseLabel,
 						false);
+					internalTrueLabel.place();
 					right.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
@@ -1296,12 +1300,14 @@
 						trueLabel,
 						falseLabel,
 						false);
+					Label internalFalseLabel = new Label(codeStream);
 					right.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
 						trueLabel,
-						falseLabel,
+						internalFalseLabel,
 						false);
+					internalFalseLabel.place();
 					if (valueRequired) {
 						if ((bits & OnlyValueRequiredMASK) != 0) {
 							codeStream.iconst_1();
@@ -1337,12 +1343,14 @@
 			if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
 				if (condConst.booleanValue() == true) {
 					// x | <something equivalent to true>
+					Label internalFalseLabel = new Label(codeStream);
 					left.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
 						trueLabel,
-						falseLabel,
+						internalFalseLabel,
 						false);
+					internalFalseLabel.place();
 					right.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
@@ -1641,59 +1649,67 @@
 				}
 		}
 	}
-	
+
+	public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+
+		left.printExpression(indent, output).append(' ').append(operatorToString()).append(' ');
+		return right.printExpression(0, output);
+	}
+		
 	public TypeBinding resolveType(BlockScope scope) {
 
+		boolean leftIsCast, rightIsCast;
+		if ((leftIsCast = left instanceof CastExpression) == true) left.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+		TypeBinding leftType = left.resolveType(scope);
+
+		if ((rightIsCast = right instanceof CastExpression) == true) right.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+		TypeBinding rightType = right.resolveType(scope);
+
 		// use the id of the type to navigate into the table
-		TypeBinding leftTb = left.resolveType(scope);
-		TypeBinding rightTb = right.resolveType(scope);
-		if (leftTb == null || rightTb == null) {
+		if (leftType == null || rightType == null) {
 			constant = Constant.NotAConstant;
 			return null;
 		}
-		int leftId = leftTb.id;
-		int rightId = rightTb.id;
-		if (leftId > 15
-			|| rightId > 15) { // must convert String + Object || Object + String
-			if (leftId == T_String) {
-				rightId = T_Object;
-			} else if (rightId == T_String) {
-				leftId = T_Object;
+		int leftTypeId = leftType.id;
+		int rightTypeId = rightType.id;
+		if (leftTypeId > 15
+			|| rightTypeId > 15) { // must convert String + Object || Object + String
+			if (leftTypeId == T_String) {
+				rightTypeId = T_Object;
+			} else if (rightTypeId == T_String) {
+				leftTypeId = T_Object;
 			} else {
 				constant = Constant.NotAConstant;
-				scope.problemReporter().invalidOperator(this, leftTb, rightTb);
+				scope.problemReporter().invalidOperator(this, leftType, rightType);
 				return null;
 			}
 		}
 		if (((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) {
-			if (leftId == T_String
-				&& rightTb.isArrayType()
-				&& ((ArrayBinding) rightTb).elementsType(scope) == CharBinding)
-				scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(
-					right);
-			else if (
-				rightId == T_String
-					&& leftTb.isArrayType()
-					&& ((ArrayBinding) leftTb).elementsType(scope) == CharBinding)
-				scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(
-					left);
+			if (leftTypeId == T_String
+					&& rightType.isArrayType()
+					&& ((ArrayBinding) rightType).elementsType(scope) == CharBinding) {
+				scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(right);
+					} else if (rightTypeId == T_String
+							&& leftType.isArrayType()
+							&& ((ArrayBinding) leftType).elementsType(scope) == CharBinding) {
+				scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(left);
+			}
 		}
 
 		// the code is an int
-		// (cast)  left   Op (cast)  rigth --> result
+		// (cast)  left   Op (cast)  right --> result
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       <<0
 
 		// Don't test for result = 0. If it is zero, some more work is done.
 		// On the one hand when it is not zero (correct code) we avoid doing the test	
-		int result =
-			ResolveTypeTables[(bits & OperatorMASK) >> OperatorSHIFT][(leftId << 4)
-				+ rightId];
-		left.implicitConversion = result >>> 12;
-		right.implicitConversion = (result >>> 4) & 0x000FF;
+		int operator = (bits & OperatorMASK) >> OperatorSHIFT;
+		int operatorSignature = OperatorSignatures[operator][(leftTypeId << 4) + rightTypeId];
+		left.implicitConversion = operatorSignature >>> 12;
+		right.implicitConversion = (operatorSignature >>> 4) & 0x000FF;
 
-		bits |= result & 0xF;
-		switch (result & 0xF) { // record the current ReturnTypeID
+		bits |= operatorSignature & 0xF;
+		switch (operatorSignature & 0xF) { // record the current ReturnTypeID
 			// only switch on possible result type.....
 			case T_boolean :
 				this.resolvedType = BooleanBinding;
@@ -1721,23 +1737,20 @@
 				break;
 			default : //error........
 				constant = Constant.NotAConstant;
-				scope.problemReporter().invalidOperator(this, leftTb, rightTb);
+				scope.problemReporter().invalidOperator(this, leftType, rightType);
 				return null;
 		}
 
+		// check need for operand cast
+		if (leftIsCast || rightIsCast) {
+			CastExpression.checkNeedForArgumentCasts(scope, operator, operatorSignature, left, leftTypeId, leftIsCast, right, rightTypeId, rightIsCast);
+		}
 		// compute the constant when valid
-		computeConstant(scope, leftId, rightId);
+		computeConstant(scope, leftTypeId, rightTypeId);
 		return this.resolvedType;
 	}
-	
-	public String toStringExpressionNoParenthesis() {
 
-		return left.toStringExpression() + " " + //$NON-NLS-1$
-		operatorToString() + " " + //$NON-NLS-1$
-		right.toStringExpression();
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		
 		if (visitor.visit(this, scope)) {
 			left.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
index dd8316a..18fa9f9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -21,7 +21,6 @@
 	public int explicitDeclarations;
 	// the number of explicit declaration , used to create scope
 	public BlockScope scope;
-	public static final Block None = new Block(0);
 	
 	public Block(int explicitDeclarations) {
 		this.explicitDeclarations = explicitDeclarations;
@@ -36,8 +35,8 @@
 		if (statements == null)	return flowInfo;
 		boolean didAlreadyComplain = false;
 		for (int i = 0, max = statements.length; i < max; i++) {
-			Statement stat;
-			if (!flowInfo.complainIfUnreachable(stat = statements[i], scope, didAlreadyComplain)) {
+			Statement stat = statements[i];
+			if (!stat.complainIfUnreachable(flowInfo, scope, didAlreadyComplain)) {
 				flowInfo = stat.analyseCode(scope, flowContext, flowInfo);
 			} else {
 				didAlreadyComplain = true;
@@ -45,16 +44,6 @@
 		}
 		return flowInfo;
 	}
-
-	public static final Block EmptyWith(int sourceStart, int sourceEnd) {
-
-		//return an empty block which position is s and e
-		Block bk = new Block(0);
-		bk.sourceStart = sourceStart;
-		bk.sourceEnd = sourceEnd;
-		return bk;
-	}
-
 	/**
 	 * Code generation for a block
 	 */
@@ -80,70 +69,61 @@
 		return statements == null;
 	}
 
+	public StringBuffer printBody(int indent, StringBuffer output) {
+
+		if (this.statements == null) return output;
+		for (int i = 0; i < statements.length; i++) {
+			statements[i].printStatement(indent + 1, output);
+			output.append('\n'); 
+		}
+		return output;
+	}
+
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+
+		printIndent(indent, output);
+		output.append("{\n"); //$NON-NLS-1$
+		printBody(indent, output);
+		return printIndent(indent, output).append('}');
+	}
+
 	public void resolve(BlockScope upperScope) {
 
+		if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
+			upperScope.problemReporter().undocumentedEmptyBlock(this.sourceStart, this.sourceEnd);
+		}
 		if (statements != null) {
 			scope =
 				explicitDeclarations == 0
 					? upperScope
 					: new BlockScope(upperScope, explicitDeclarations);
-			int i = 0, length = statements.length;
-			while (i < length)
-				statements[i++].resolve(scope);
+			for (int i = 0, length = statements.length; i < length; i++) {
+				statements[i].resolve(scope);
+			}
 		}
 	}
 
 	public void resolveUsing(BlockScope givenScope) {
 
+		if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
+			givenScope.problemReporter().undocumentedEmptyBlock(this.sourceStart, this.sourceEnd);
+		}
 		// this optimized resolve(...) is sent only on none empty blocks
 		scope = givenScope;
 		if (statements != null) {
-			int i = 0, length = statements.length;
-			while (i < length)
-				statements[i++].resolve(scope);
-		}
-	}
-
-	public String toString(int tab) {
-
-		String s = tabString(tab);
-		if (this.statements == null) {
-			s += "{\n"; //$NON-NLS-1$
-			s += tabString(tab);
-			s += "}"; //$NON-NLS-1$
-			return s;
-		}
-		s += "{\n"; //$NON-NLS-1$
-		s += this.toStringStatements(tab);
-		s += tabString(tab);
-		s += "}"; //$NON-NLS-1$
-		return s;
-	}
-
-	public String toStringStatements(int tab) {
-
-		if (this.statements == null)
-			return ""; //$NON-NLS-1$
-		StringBuffer buffer = new StringBuffer();
-		for (int i = 0; i < statements.length; i++) {
-			buffer.append(statements[i].toString(tab + 1));
-			if (statements[i] instanceof Block) {
-				buffer.append("\n"); //$NON-NLS-1$
-			} else {
-				buffer.append(";\n"); //$NON-NLS-1$
+			for (int i = 0, length = statements.length; i < length; i++) {
+				statements[i].resolve(scope);
 			}
-		};
-		return buffer.toString();
+		}
 	}
 
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
 			if (statements != null) {
-				int statementLength = statements.length;
-				for (int i = 0; i < statementLength; i++)
+				for (int i = 0, length = statements.length; i < length; i++)
 					statements[i].traverse(visitor, scope);
 			}
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
index 8466836..661b345 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
@@ -16,7 +16,7 @@
 public abstract class BranchStatement extends Statement {
 	public char[] label;
 	public Label targetLabel;
-	public AstNode[] subroutines;
+	public SubRoutineStatement[] subroutines;
 /**
  * BranchStatement constructor comment.
  */
@@ -41,24 +41,19 @@
 	// blocks in sequence
 	if (subroutines != null){
 		for (int i = 0, max = subroutines.length; i < max; i++){
-			AstNode sub;
-			if ((sub = subroutines[i]) instanceof SynchronizedStatement){
-				codeStream.load(((SynchronizedStatement)sub).synchroVariable);
-				codeStream.monitorexit(); 
-			} else {
-				TryStatement trySub = (TryStatement) sub;
-				if (trySub.subRoutineCannotReturn)	{
-					codeStream.goto_(trySub.subRoutineStartLabel);
+			SubRoutineStatement sub = subroutines[i];
+			sub.generateSubRoutineInvocation(currentScope, codeStream);
+			if (sub.isSubRoutineEscaping()) {
 					codeStream.recordPositionsFrom(pc, this.sourceStart);
+					SubRoutineStatement.reenterExceptionHandlers(subroutines, i, codeStream);
 					return;
-				} else {
-					codeStream.jsr(trySub.subRoutineStartLabel);
-				}
 			}
+			sub.exitAnyExceptionHandler();
 		}
 	}
 	codeStream.goto_(targetLabel);
 	codeStream.recordPositionsFrom(pc, this.sourceStart);
+	SubRoutineStatement.reenterExceptionHandlers(subroutines, -1, codeStream);
 }
 public void resetStateForCodeGeneration() {
 	if (this.targetLabel != null) {
@@ -67,6 +62,7 @@
 }
 
 public void resolve(BlockScope scope) {
+	// nothing to do during name resolution
 }
 
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Break.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
similarity index 77%
rename from org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Break.java
rename to org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
index 8c685db..e43db5f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Break.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
@@ -10,13 +10,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
-public class Break extends BranchStatement {
+public class BreakStatement extends BranchStatement {
 	
-	public Break(char[] label, int sourceStart, int e) {
+	public BreakStatement(char[] label, int sourceStart, int e) {
 		super(label, sourceStart, e);
 	}
 
@@ -45,22 +45,22 @@
 		targetLabel = targetContext.breakLabel();
 		FlowContext traversedContext = flowContext;
 		int subIndex = 0, maxSub = 5;
-		subroutines = new AstNode[maxSub];
+		subroutines = new SubRoutineStatement[maxSub];
 		
 		do {
-			AstNode sub;
+			SubRoutineStatement sub;
 			if ((sub = traversedContext.subRoutine()) != null) {
 				if (subIndex == maxSub) {
-					System.arraycopy(subroutines, 0, (subroutines = new AstNode[maxSub*=2]), 0, subIndex); // grow
+					System.arraycopy(subroutines, 0, (subroutines = new SubRoutineStatement[maxSub*=2]), 0, subIndex); // grow
 				}
 				subroutines[subIndex++] = sub;
-				if (sub.cannotReturn()) {
+				if (sub.isSubRoutineEscaping()) {
 					break;
 				}
 			}
 			traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
 
-			AstNode node;
+			ASTNode node;
 			if ((node = traversedContext.associatedNode) instanceof TryStatement) {
 				TryStatement tryStatement = (TryStatement) node;
 				flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits			
@@ -73,22 +73,20 @@
 		
 		// resize subroutines
 		if (subIndex != maxSub) {
-			System.arraycopy(subroutines, 0, (subroutines = new AstNode[subIndex]), 0, subIndex);
+			System.arraycopy(subroutines, 0, (subroutines = new SubRoutineStatement[subIndex]), 0, subIndex);
 		}
 		return FlowInfo.DEAD_END;
 	}
 	
-	public String toString(int tab) {
+	public StringBuffer printStatement(int tab, StringBuffer output) {
 
-		String s = tabString(tab);
-		s += "break "; //$NON-NLS-1$
-		if (label != null)
-			s += new String(label);
-		return s;
+		printIndent(tab, output).append("break "); //$NON-NLS-1$
+		if (label != null) output.append(label);
+		return output.append(';');
 	}
 	
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockscope) {
 
 		visitor.visit(this, blockscope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Case.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
similarity index 62%
rename from org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Case.java
rename to org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
index a571c54..052d52f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Case.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
@@ -10,19 +10,19 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
-public class Case extends Statement {
+public class CaseStatement extends Statement {
 	
 	public Expression constantExpression;
 	public CaseLabel targetLabel;
-	public Case(int sourceStart, Expression constantExpression) {
+	public CaseStatement(Expression constantExpression, int sourceEnd, int sourceStart) {
 		this.constantExpression = constantExpression;
-		this.sourceEnd = constantExpression.sourceEnd;
+		this.sourceEnd = sourceEnd;
 		this.sourceStart = sourceStart;
 	}
 
@@ -31,13 +31,27 @@
 		FlowContext flowContext,
 		FlowInfo flowInfo) {
 
-		if (constantExpression.constant == NotAConstant)
-			currentScope.problemReporter().caseExpressionMustBeConstant(constantExpression);
-
-		this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
+		if (constantExpression != null) {
+			if (constantExpression.constant == NotAConstant) {
+				currentScope.problemReporter().caseExpressionMustBeConstant(constantExpression);
+			}
+			this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
+		}
 		return flowInfo;
 	}
 
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+
+		printIndent(tab, output);
+		if (constantExpression == null) {
+			output.append("default : "); //$NON-NLS-1$
+		} else {
+			output.append("case "); //$NON-NLS-1$
+			constantExpression.printExpression(0, output).append(" : "); //$NON-NLS-1$
+		}
+		return output.append(';');
+	}
+	
 	/**
 	 * Case code generation
 	 *
@@ -56,6 +70,7 @@
 	 * No-op : should use resolveCase(...) instead.
 	 */
 	public void resolve(BlockScope scope) {
+		// no-op : should use resolveCase(...) instead.
 	}
 
 	public Constant resolveCase(
@@ -63,11 +78,19 @@
 		TypeBinding switchType,
 		SwitchStatement switchStatement) {
 
+		if (constantExpression == null) {
+			// remember the default case into the associated switch statement
+			if (switchStatement.defaultCase != null)
+				scope.problemReporter().duplicateDefaultCase(this);
+	
+			// on error the last default will be the selected one .... (why not) ....	
+			switchStatement.defaultCase = this;
+			return null;
+		}
 		// add into the collection of cases of the associated switch statement
 		switchStatement.cases[switchStatement.caseCount++] = this;
 		TypeBinding caseType = constantExpression.resolveType(scope);
-		if (caseType == null || switchType == null)
-			return null;
+		if (caseType == null || switchType == null) return null;
 		if (constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchType))
 			return constantExpression.constant;
 		if (caseType.isCompatibleWith(switchType))
@@ -79,19 +102,13 @@
 		return null;
 	}
 
-	public String toString(int tab) {
-
-		String s = tabString(tab);
-		s = s + "case " + constantExpression.toStringExpression() + " : "; //$NON-NLS-1$ //$NON-NLS-2$
-		return s;
-	}
 
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
-			constantExpression.traverse(visitor, blockScope);
+			if (constantExpression != null) constantExpression.traverse(visitor, blockScope);
 		}
 		visitor.endVisit(this, blockScope);
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index 2ad3c74..0e03565 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -7,32 +7,32 @@
  * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752)
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 
 public class CastExpression extends Expression {
 
 	public Expression expression;
 	public Expression type;
-	public boolean needRuntimeCheckcast;
-
+	
 	//expression.implicitConversion holds the cast for baseType casting 
-	public CastExpression(Expression e, Expression t) {
-		expression = e;
-		type = t;
+	public CastExpression(Expression expression, Expression type) {
+		this.expression = expression;
+		this.type = type;
 
 		//due to the fact an expression may start with ( and that a cast also start with (
 		//the field is an expression....it can be a TypeReference OR a NameReference Or
 		//an expression <--this last one is invalid.......
 
-		// :-( .............
-
 		//if (type instanceof TypeReference )
 		//	flag = IsTypeReference ;
 		//else
@@ -53,21 +53,23 @@
 			.unconditionalInits();
 	}
 
-	public final void areTypesCastCompatible(
+	/**
+	 * Returns false if the cast is unnecessary
+	 */
+	public final boolean checkCastTypesCompatibility(
 		BlockScope scope,
 		TypeBinding castType,
 		TypeBinding expressionType) {
-
+	
 		// see specifications 5.5
 		// handle errors and process constant when needed
-
+	
 		// if either one of the type is null ==>
 		// some error has been already reported some where ==>
 		// we then do not report an obvious-cascade-error.
-
-		needRuntimeCheckcast = false;
-		if (castType == null || expressionType == null) return;
-
+	
+		if (castType == null || expressionType == null) return true;
+	
 		// identity conversion cannot be performed upfront, due to side-effects
 		// like constant propagation
 				
@@ -76,120 +78,128 @@
 				if (expressionType == castType) {
 					expression.implicitWidening(castType, expressionType);
 					constant = expression.constant; //use the same constant
-					return;
+					return false;
 				}
+				boolean necessary = false;
 				if (expressionType.isCompatibleWith(castType)
-					|| BaseTypeBinding.isNarrowing(castType.id, expressionType.id)) {
+						|| (necessary = BaseTypeBinding.isNarrowing(castType.id, expressionType.id))) {
 					expression.implicitConversion = (castType.id << 4) + expressionType.id;
-					if (expression.constant != Constant.NotAConstant)
+					if (expression.constant != Constant.NotAConstant) {
 						constant = expression.constant.castTo(expression.implicitConversion);
-					return;
+					}
+					return necessary;
+					
 				}
 			}
 			scope.problemReporter().typeCastError(this, castType, expressionType);
-			return;
+			return true;
 		}
-
+	
 		//-----------cast to something which is NOT a base type--------------------------	
 		if (expressionType == NullBinding) {
 			//	if (castType.isArrayType()){ // 26903 - need checkcast when casting null to array type
 			//		needRuntimeCheckcast = true;
 			//	}
-			return; //null is compatible with every thing
+			return false; //null is compatible with every thing
 		}
 		if (expressionType.isBaseType()) {
 			scope.problemReporter().typeCastError(this, castType, expressionType);
-			return;
+			return true;
 		}
-
+	
 		if (expressionType.isArrayType()) {
-			if (castType == expressionType) return; // identity conversion
-
+			if (castType == expressionType) return false; // identity conversion
+	
 			if (castType.isArrayType()) {
 				//------- (castType.isArray) expressionType.isArray -----------
 				TypeBinding exprElementType = ((ArrayBinding) expressionType).elementsType(scope);
 				if (exprElementType.isBaseType()) {
 					// <---stop the recursion------- 
-					if (((ArrayBinding) castType).elementsType(scope) == exprElementType)
-						needRuntimeCheckcast = true;
-					else
+					if (((ArrayBinding) castType).elementsType(scope) == exprElementType) {
+						this.bits |= NeedRuntimeCheckCastMASK;
+					} else {
 						scope.problemReporter().typeCastError(this, castType, expressionType);
-					return;
+					}
+					return true;
 				}
 				// recursively on the elements...
-				areTypesCastCompatible(
+				return checkCastTypesCompatibility(
 					scope,
 					((ArrayBinding) castType).elementsType(scope),
 					exprElementType);
-				return;
 			} else if (
 				castType.isClass()) {
 				//------(castType.isClass) expressionType.isArray ---------------	
-				if (scope.isJavaLangObject(castType))
-					return;
+				if (scope.isJavaLangObject(castType)) {
+					return false;
+				}
 			} else { //------- (castType.isInterface) expressionType.isArray -----------
 				if (scope.isJavaLangCloneable(castType) || scope.isJavaIoSerializable(castType)) {
-					needRuntimeCheckcast = true;
-					return;
+					this.bits |= NeedRuntimeCheckCastMASK;
+					return true;
 				}
 			}
 			scope.problemReporter().typeCastError(this, castType, expressionType);
-			return;
+			return true;
 		}
-
+	
 		if (expressionType.isClass()) {
 			if (castType.isArrayType()) {
 				// ---- (castType.isArray) expressionType.isClass -------
 				if (scope.isJavaLangObject(expressionType)) { // potential runtime error
-					needRuntimeCheckcast = true;
-					return;
+					this.bits |= NeedRuntimeCheckCastMASK;
+					return true;
 				}
 			} else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isClass ------
 				if (expressionType.isCompatibleWith(castType)){ // no runtime error
 					if (castType.id == T_String) constant = expression.constant; // (String) cst is still a constant
-					return;
+					return false;
 				}
 				if (castType.isCompatibleWith(expressionType)) {
 					// potential runtime  error
-					needRuntimeCheckcast = true;
-					return;
+					this.bits |= NeedRuntimeCheckCastMASK;
+					return true;
 				}
 			} else { // ----- (castType.isInterface) expressionType.isClass -------  
 				if (((ReferenceBinding) expressionType).isFinal()) {
 					// no subclass for expressionType, thus compile-time check is valid
 					if (expressionType.isCompatibleWith(castType)) 
-						return;
+						return false;
 				} else { // a subclass may implement the interface ==> no check at compile time
-					needRuntimeCheckcast = true;
-					return;
+					this.bits |= NeedRuntimeCheckCastMASK;
+					return true;
 				}
 			}
 			scope.problemReporter().typeCastError(this, castType, expressionType);
-			return;
+			return true;
 		}
-
+	
 		//	if (expressionType.isInterface()) { cannot be anything else
 		if (castType.isArrayType()) {
 			// ----- (castType.isArray) expressionType.isInterface ------
 			if (scope.isJavaLangCloneable(expressionType)
-				|| scope.isJavaIoSerializable(expressionType)) // potential runtime error
-				needRuntimeCheckcast = true;
-			else
+					|| scope.isJavaIoSerializable(expressionType)) {// potential runtime error
+				this.bits |= NeedRuntimeCheckCastMASK;
+			} else {
 				scope.problemReporter().typeCastError(this, castType, expressionType);
-			return;
+			}
+			return true;
 		} else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isInterface --------
-			if (scope.isJavaLangObject(castType)) // no runtime error
-				return;
+			if (scope.isJavaLangObject(castType)) { // no runtime error
+				return false;
+			}
 			if (((ReferenceBinding) castType).isFinal()) {
 				// no subclass for castType, thus compile-time check is valid
 				if (!castType.isCompatibleWith(expressionType)) {
 					// potential runtime error
 					scope.problemReporter().typeCastError(this, castType, expressionType);
-					return;
+					return true;
 				}
 			}
 		} else { // ----- (castType.isInterface) expressionType.isInterface -------
-			if (castType == expressionType) return; // identity conversion
+			if (castType == expressionType) { 
+				return false; // identity conversion
+			}
 			if (Scope.compareTypes(castType, expressionType) == NotRelated) {
 				MethodBinding[] castTypeMethods = ((ReferenceBinding) castType).methods();
 				MethodBinding[] expressionTypeMethods =
@@ -198,18 +208,207 @@
 				for (int i = 0, castMethodsLength = castTypeMethods.length; i < castMethodsLength; i++)
 					for (int j = 0; j < exprMethodsLength; j++) {
 						if ((castTypeMethods[i].returnType != expressionTypeMethods[j].returnType)
-								&& (castTypeMethods[i].selector == expressionTypeMethods[j].selector)
+								&& (CharOperation.equals(castTypeMethods[i].selector, expressionTypeMethods[j].selector))
 								&& castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
 							scope.problemReporter().typeCastError(this, castType, expressionType);
 						}
 					}
 			}
 		}
-		needRuntimeCheckcast = true;
-		return;
+		this.bits |= NeedRuntimeCheckCastMASK;
+		return true;
 	}
 
 	/**
+	 * Casting an enclosing instance will considered as useful if removing it would actually bind to a different type
+	 */
+	public static void checkNeedForEnclosingInstanceCast(BlockScope scope, Expression enclosingInstance, TypeBinding enclosingInstanceType, TypeBinding memberType) {
+	
+		if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return;
+		
+		TypeBinding castedExpressionType = ((CastExpression)enclosingInstance).expression.resolvedType;
+		if (castedExpressionType == null) return; // cannot do better
+		// obvious identity cast
+		if (castedExpressionType == enclosingInstanceType) { 
+			scope.problemReporter().unnecessaryCast((CastExpression)enclosingInstance);
+		} else if (castedExpressionType == NullBinding){
+			return; // tolerate null enclosing instance cast
+		} else {
+			TypeBinding alternateEnclosingInstanceType = castedExpressionType; 
+			if (castedExpressionType.isBaseType() || castedExpressionType.isArrayType()) return; // error case
+			if (memberType == scope.getMemberType(memberType.sourceName(), (ReferenceBinding) alternateEnclosingInstanceType)) {
+				scope.problemReporter().unnecessaryCast((CastExpression)enclosingInstance);
+			}
+		}
+	}
+
+	/**
+	 * Only complain for identity cast, since other type of casts may be useful: e.g.  ~((~(long) 0) << 32)  is different from: ~((~0) << 32) 
+	 */
+	public static void checkNeedForArgumentCast(BlockScope scope, int operator, int operatorSignature, Expression expression, int expressionTypeId) {
+	
+		if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return;
+	
+		// check need for left operand cast
+		int alternateLeftTypeId = expressionTypeId;
+		if ((expression.bits & UnnecessaryCastMask) == 0 && expression.resolvedType.isBaseType()) {
+			// narrowing conversion on base type may change value, thus necessary
+			return;
+		} else  {
+			TypeBinding alternateLeftType = ((CastExpression)expression).expression.resolvedType;
+			if (alternateLeftType == null) return; // cannot do better
+			if ((alternateLeftTypeId = alternateLeftType.id) == expressionTypeId) { // obvious identity cast
+				scope.problemReporter().unnecessaryCast((CastExpression)expression); 
+				return;
+			} else if (alternateLeftTypeId == T_null) {
+				alternateLeftTypeId = expressionTypeId;  // tolerate null argument cast
+				return;
+			}
+		}
+/*		tolerate widening cast in unary expressions, as may be used when combined in binary expressions (41680)
+		int alternateOperatorSignature = OperatorExpression.OperatorSignatures[operator][(alternateLeftTypeId << 4) + alternateLeftTypeId];
+		// (cast)  left   Op (cast)  right --> result
+		//  1111   0000       1111   0000     1111
+		//  <<16   <<12       <<8    <<4       <<0
+		final int CompareMASK = (0xF<<16) + (0xF<<8) + 0xF; // mask hiding compile-time types
+		if ((operatorSignature & CompareMASK) == (alternateOperatorSignature & CompareMASK)) { // same promotions and result
+			scope.problemReporter().unnecessaryCastForArgument((CastExpression)expression,  TypeBinding.wellKnownType(scope, expression.implicitConversion >> 4)); 
+		}
+*/		
+	}
+		
+	/**
+	 * Cast expressions will considered as useful if removing them all would actually bind to a different method
+	 * (no fine grain analysis on per casted argument basis, simply separate widening cast from narrowing ones)
+	 */
+	public static void checkNeedForArgumentCasts(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding binding, Expression[] arguments, TypeBinding[] argumentTypes, final InvocationSite invocationSite) {
+	
+		if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return;
+		
+		int length = argumentTypes.length;
+
+		// iterate over arguments, and retrieve original argument types (before cast)
+		TypeBinding[] rawArgumentTypes = argumentTypes;
+		for (int i = 0; i < length; i++) {
+			Expression argument = arguments[i];
+			if (argument instanceof CastExpression) {
+ 				// narrowing conversion on base type may change value, thus necessary
+				if ((argument.bits & UnnecessaryCastMask) == 0 && argument.resolvedType.isBaseType()) {
+					continue;
+				}		
+				TypeBinding castedExpressionType = ((CastExpression)argument).expression.resolvedType;
+				if (castedExpressionType == null) return; // cannot do better
+				// obvious identity cast
+				if (castedExpressionType == argumentTypes[i]) { 
+					scope.problemReporter().unnecessaryCast((CastExpression)argument);
+				} else if (castedExpressionType == NullBinding){
+					continue; // tolerate null argument cast
+				} else {
+					if (rawArgumentTypes == argumentTypes) {
+						System.arraycopy(rawArgumentTypes, 0, rawArgumentTypes = new TypeBinding[length], 0, length);
+					}
+					// retain original argument type
+					rawArgumentTypes[i] = castedExpressionType; 
+				}
+			}				
+		}
+		// perform alternate lookup with original types
+		if (rawArgumentTypes != argumentTypes) {
+			checkAlternateBinding(scope, receiver, receiverType, binding, arguments, argumentTypes, rawArgumentTypes, invocationSite);
+		}
+	}
+
+	/**
+	 * Check binary operator casted arguments 
+	 */
+	public static void checkNeedForArgumentCasts(BlockScope scope, int operator, int operatorSignature, Expression left, int leftTypeId, boolean leftIsCast, Expression right, int rightTypeId, boolean rightIsCast) {
+
+		if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return;
+
+		// check need for left operand cast
+		int alternateLeftTypeId = leftTypeId;
+		if (leftIsCast) {
+			if ((left.bits & UnnecessaryCastMask) == 0 && left.resolvedType.isBaseType()) {
+ 				// narrowing conversion on base type may change value, thus necessary
+ 				leftIsCast = false;
+			} else  {
+				TypeBinding alternateLeftType = ((CastExpression)left).expression.resolvedType;
+				if (alternateLeftType == null) return; // cannot do better
+				if ((alternateLeftTypeId = alternateLeftType.id) == leftTypeId) { // obvious identity cast
+					scope.problemReporter().unnecessaryCast((CastExpression)left); 
+					leftIsCast = false;
+				} else if (alternateLeftTypeId == T_null) {
+					alternateLeftTypeId = leftTypeId;  // tolerate null argument cast
+					leftIsCast = false;
+				}
+			}
+		}
+		// check need for right operand cast
+		int alternateRightTypeId = rightTypeId;
+		if (rightIsCast) {
+			if ((right.bits & UnnecessaryCastMask) == 0 && right.resolvedType.isBaseType()) {
+ 				// narrowing conversion on base type may change value, thus necessary
+ 				rightIsCast = false;
+			} else {
+				TypeBinding alternateRightType = ((CastExpression)right).expression.resolvedType;
+				if (alternateRightType == null) return; // cannot do better
+				if ((alternateRightTypeId = alternateRightType.id) == rightTypeId) { // obvious identity cast
+					scope.problemReporter().unnecessaryCast((CastExpression)right); 
+					rightIsCast = false;
+				} else if (alternateRightTypeId == T_null) {
+					alternateRightTypeId = rightTypeId;  // tolerate null argument cast
+					rightIsCast = false;
+				}
+			}	
+		}
+		if (leftIsCast || rightIsCast) {
+			if (alternateLeftTypeId > 15 || alternateRightTypeId > 15) { // must convert String + Object || Object + String
+				if (alternateLeftTypeId == T_String) {
+					alternateRightTypeId = T_Object;
+				} else if (alternateRightTypeId == T_String) {
+					alternateLeftTypeId = T_Object;
+				} else {
+					return; // invalid operator
+				}
+			}
+			int alternateOperatorSignature = OperatorExpression.OperatorSignatures[operator][(alternateLeftTypeId << 4) + alternateRightTypeId];
+			// (cast)  left   Op (cast)  right --> result
+			//  1111   0000       1111   0000     1111
+			//  <<16   <<12       <<8    <<4       <<0
+			final int CompareMASK = (0xF<<16) + (0xF<<8) + 0xF; // mask hiding compile-time types
+			if ((operatorSignature & CompareMASK) == (alternateOperatorSignature & CompareMASK)) { // same promotions and result
+				if (leftIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)left,  TypeBinding.wellKnownType(scope, left.implicitConversion >> 4)); 
+				if (rightIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)right, TypeBinding.wellKnownType(scope,  right.implicitConversion >> 4));
+			}
+		}
+	}
+
+	private static void checkAlternateBinding(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding binding, Expression[] arguments, TypeBinding[] originalArgumentTypes, TypeBinding[] alternateArgumentTypes, final InvocationSite invocationSite) {
+
+			InvocationSite fakeInvocationSite = new InvocationSite(){	
+				public boolean isSuperAccess(){ return invocationSite.isSuperAccess(); }
+				public boolean isTypeAccess() { return invocationSite.isTypeAccess(); }
+				public void setActualReceiverType(ReferenceBinding actualReceiverType) { /* ignore */}
+				public void setDepth(int depth) { /* ignore */}
+				public void setFieldIndex(int depth){ /* ignore */}
+			};	
+			MethodBinding bindingIfNoCast;
+			if (binding.isConstructor()) {
+				bindingIfNoCast = scope.getConstructor((ReferenceBinding)receiverType, alternateArgumentTypes, fakeInvocationSite);
+			} else {
+				bindingIfNoCast = receiver.isImplicitThis()
+					? scope.getImplicitMethod(binding.selector, alternateArgumentTypes, fakeInvocationSite)
+					: scope.getMethod(receiverType, binding.selector, alternateArgumentTypes, fakeInvocationSite); 	
+			}
+			if (bindingIfNoCast == binding) {
+				for (int i = 0, length = originalArgumentTypes.length; i < length; i++) {
+					if (originalArgumentTypes[i] != alternateArgumentTypes[i]) {
+						scope.problemReporter().unnecessaryCastForArgument((CastExpression)arguments[i], binding.parameters[i]);
+					}
+				}
+			}	
+	}
+	/**
 	 * Cast expression code generation
 	 *
 	 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
@@ -222,9 +421,9 @@
 		boolean valueRequired) {
 
 		int pc = codeStream.position;
+		boolean needRuntimeCheckcast = (this.bits & NeedRuntimeCheckCastMASK) != 0;
 		if (constant != NotAConstant) {
-			if (valueRequired
-				|| needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check
+			if (valueRequired || needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check
 				codeStream.generateConstant(constant, implicitConversion);
 				if (needRuntimeCheckcast) {
 					codeStream.checkcast(this.resolvedType);
@@ -258,6 +457,13 @@
 		return current;
 	}
 
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		output.append('(');
+		type.print(0, output).append(") "); //$NON-NLS-1$
+		return expression.printExpression(0, output);
+	}
+
 	public TypeBinding resolveType(BlockScope scope) {
 		// compute a new constant if the cast is effective
 
@@ -267,29 +473,32 @@
 
 		constant = Constant.NotAConstant;
 		implicitConversion = T_undefined;
-		if ((type instanceof TypeReference) || (type instanceof NameReference)) {
+
+		if ((type instanceof TypeReference) || (type instanceof NameReference)
+				&& ((type.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) { // no extra parenthesis around type: ((A))exp
+
 			this.resolvedType = type.resolveType(scope);
-			TypeBinding castedExpressionType = expression.resolveType(scope);
-			if (this.resolvedType != null && castedExpressionType != null) {
-				areTypesCastCompatible(scope, this.resolvedType, castedExpressionType);
+			TypeBinding expressionType = expression.resolveType(scope);
+			if (this.resolvedType != null && expressionType != null) {
+				boolean necessary = checkCastTypesCompatibility(scope, this.resolvedType, expressionType);
+				if (!necessary && this.expression.resolvedType != null) { // cannot do better if expression is not bound
+					this.bits |= UnnecessaryCastMask;
+					if ((this.bits & IgnoreNeedForCastCheckMASK) == 0) {
+						scope.problemReporter().unnecessaryCast(this);
+					}
+				}
 			}
 			return this.resolvedType;
 		} else { // expression as a cast !!!!!!!!
-			TypeBinding castedExpressionType = expression.resolveType(scope);
-			if (castedExpressionType == null) return null;
+			TypeBinding expressionType = expression.resolveType(scope);
+			if (expressionType == null) return null;
 			scope.problemReporter().invalidTypeReference(type);
 			return null;
 		}
 	}
 
-	public String toStringExpression() {
-
-		return "(" + type.toString(0) + ") " + //$NON-NLS-2$ //$NON-NLS-1$
-		expression.toStringExpression();
-	}
-
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java
index 2bb8c57..912c041 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -68,7 +68,7 @@
 			else {
 				constant = Constant.fromValue(value = (char) number);
 				break;
-			};
+			}
 			if ((digit = source[4]) != '\'')
 				number = (number * 8) + Character.getNumericValue(digit);
 			value = (char) number;
@@ -94,7 +94,7 @@
 public TypeBinding literalType(BlockScope scope) {
 	return CharBinding;
 }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+public void traverse(ASTVisitor visitor, BlockScope blockScope) {
 	visitor.visit(this, blockScope);
 	visitor.endVisit(this, blockScope);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
index 10428c9..7b92623 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -62,6 +62,11 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		return type.print(0, output).append(".class"); //$NON-NLS-1$
+	}
+
 	public TypeBinding resolveType(BlockScope scope) {
 
 		constant = NotAConstant;
@@ -77,15 +82,8 @@
 		return this.resolvedType = scope.getJavaLangClass();
 	}
 
-	public String toStringExpression() {
-
-		String s = ""; //$NON-NLS-1$
-		s = s + type.toString(0) + ".class"; //$NON-NLS-1$
-		return s;
-	}
-
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java
index be32a5f..fdb8b58 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -215,22 +215,20 @@
 		//the clinit is filled by hand .... 
 	}
 
-	public void resolve(ClassScope scope) {
+	public StringBuffer print(int tab, StringBuffer output) {
 
-		this.scope = new MethodScope(scope, scope.referenceContext, true);
+		printIndent(tab, output).append("<clinit>()"); //$NON-NLS-1$
+		printBody(tab + 1, output);
+		return output;
 	}
 
-	public String toString(int tab) {
+	public void resolve(ClassScope classScope) {
 
-		String s = ""; //$NON-NLS-1$
-		s = s + tabString(tab);
-		s = s + "<clinit>()"; //$NON-NLS-1$
-		s = s + toStringStatements(tab + 1);
-		return s;
+		this.scope = new MethodScope(classScope, classScope.referenceContext, true);
 	}
 
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		ClassScope classScope) {
 
 		visitor.visit(this, classScope);
@@ -238,7 +236,7 @@
 	}
 
 	// 1.4 feature
-	public void addSupportForAssertion(FieldBinding assertionSyntheticFieldBinding) {
+	public void setAssertionSupport(FieldBinding assertionSyntheticFieldBinding) {
 
 		this.assertionSyntheticFieldBinding = assertionSyntheticFieldBinding;
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
index 7b7bfa3..2cdd3bd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
@@ -17,13 +17,12 @@
 import org.eclipse.jdt.internal.compiler.problem.*;
 
 public class CompilationUnitDeclaration
-	extends AstNode
+	extends ASTNode
 	implements ProblemSeverities, ReferenceContext {
 		
 	public ImportReference currentPackage;
 	public ImportReference[] imports;
 	public TypeDeclaration[] types;
-	//public char[][] name;
 
 	public boolean ignoreFurtherInvestigation = false;	// once pointless to investigate due to errors
 	public boolean ignoreMethodBodies = false;
@@ -31,8 +30,8 @@
 	public ProblemReporter problemReporter;
 	public CompilationResult compilationResult;
 
-	private LocalTypeBinding[] localTypes;
-	int localTypeCount = 0;
+	public LocalTypeBinding[] localTypes;
+	public int localTypeCount = 0;
 	
 	public boolean isPropagatingInnerClassEmulation;
 
@@ -57,11 +56,11 @@
 
 		switch (abortLevel) {
 			case AbortType :
-				throw new AbortType(compilationResult);
+				throw new AbortType(this.compilationResult);
 			case AbortMethod :
-				throw new AbortMethod(compilationResult);
+				throw new AbortMethod(this.compilationResult);
 			default :
-				throw new AbortCompilationUnit(compilationResult);
+				throw new AbortCompilationUnit(this.compilationResult);
 		}
 	}
 
@@ -177,6 +176,7 @@
 					types[i].generateCode(scope);
 			}
 		} catch (AbortCompilationUnit e) {
+			// ignore
 		}
 	}
 
@@ -213,6 +213,26 @@
 		return this.ignoreFurtherInvestigation;
 	}
 
+	public StringBuffer print(int indent, StringBuffer output) {
+
+		if (currentPackage != null) {
+			printIndent(indent, output).append("package "); //$NON-NLS-1$
+			currentPackage.print(0, output, false).append(";\n"); //$NON-NLS-1$
+		}
+		if (imports != null)
+			for (int i = 0; i < imports.length; i++) {
+				printIndent(indent, output).append("import "); //$NON-NLS-1$
+				imports[i].print(0, output).append(";\n"); //$NON-NLS-1$ 
+			}
+
+		if (types != null) {
+			for (int i = 0; i < types.length; i++) {
+				types[i].print(indent, output).append("\n"); //$NON-NLS-1$
+			}
+		}
+		return output;
+	}
+	
 	/*
 	 * Force inner local types to update their innerclass emulation
 	 */
@@ -262,50 +282,33 @@
 		ignoreFurtherInvestigation = true;
 	}
 
-	public String toString(int tab) {
-
-		String s = ""; //$NON-NLS-1$
-		if (currentPackage != null)
-			s = tabString(tab) + "package " + currentPackage.toString(0, false) + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
-
-		if (imports != null)
-			for (int i = 0; i < imports.length; i++) {
-				s += tabString(tab) + "import " + imports[i].toString() + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
-			};
-
-		if (types != null)
-			for (int i = 0; i < types.length; i++) {
-				s += types[i].toString(tab) + "\n"; //$NON-NLS-1$
-			}
-		return s;
-	}
-
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
-		CompilationUnitScope scope) {
+		ASTVisitor visitor,
+		CompilationUnitScope unitScope) {
 
 		if (ignoreFurtherInvestigation)
 			return;
 		try {
-			if (visitor.visit(this, scope)) {
+			if (visitor.visit(this, this.scope)) {
 				if (currentPackage != null) {
-					currentPackage.traverse(visitor, scope);
+					currentPackage.traverse(visitor, this.scope);
 				}
 				if (imports != null) {
 					int importLength = imports.length;
 					for (int i = 0; i < importLength; i++) {
-						imports[i].traverse(visitor, scope);
+						imports[i].traverse(visitor, this.scope);
 					}
 				}
 				if (types != null) {
 					int typesLength = types.length;
 					for (int i = 0; i < typesLength; i++) {
-						types[i].traverse(visitor, scope);
+						types[i].traverse(visitor, this.scope);
 					}
 				}
 			}
-			visitor.endVisit(this, scope);
+			visitor.endVisit(this, this.scope);
 		} catch (AbortCompilationUnit e) {
+			// ignore
 		}
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
index 5dfd3c3..5c7bc4e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -22,124 +22,135 @@
 	//  var op exp is equivalent to var = (varType) var op exp
 	// assignmentImplicitConversion stores the cast needed for the assignment
 
-public CompoundAssignment(Expression lhs, Expression expression,int operator, int sourceEnd) {
-	//lhs is always a reference by construction ,
-	//but is build as an expression ==> the checkcast cannot fail
-
-	super(lhs, expression, sourceEnd);
-	lhs.bits &= ~IsStrictlyAssignedMASK; // tag lhs as NON assigned - it is also a read access
-	this.operator = operator ;
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-	// record setting a variable: various scenarii are possible, setting an array reference, 
-	// a field reference, a blank final field reference, a field of an enclosing instance or 
-	// just a local variable.
-
-	return  ((Reference) lhs).analyseAssignment(currentScope, flowContext, flowInfo, this, true).unconditionalInits();
-}
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
-
-	// various scenarii are possible, setting an array reference, 
-	// a field reference, a blank final field reference, a field of an enclosing instance or 
-	// just a local variable.
-
-	int pc = codeStream.position;
-	 ((Reference) lhs).generateCompoundAssignment(currentScope, codeStream, expression, operator, assignmentImplicitConversion, valueRequired);
-	if (valueRequired) {
-		codeStream.generateImplicitConversion(implicitConversion);
+	public CompoundAssignment(Expression lhs, Expression expression,int operator, int sourceEnd) {
+		//lhs is always a reference by construction ,
+		//but is build as an expression ==> the checkcast cannot fail
+	
+		super(lhs, expression, sourceEnd);
+		lhs.bits &= ~IsStrictlyAssignedMASK; // tag lhs as NON assigned - it is also a read access
+		this.operator = operator ;
 	}
-	codeStream.recordPositionsFrom(pc, this.sourceStart);
-}
-public String operatorToString() {
-	switch (operator) {
-		case PLUS :
-			return "+="; //$NON-NLS-1$
-		case MINUS :
-			return "-="; //$NON-NLS-1$
-		case MULTIPLY :
-			return "*="; //$NON-NLS-1$
-		case DIVIDE :
-			return "/="; //$NON-NLS-1$
-		case AND :
-			return "&="; //$NON-NLS-1$
-		case OR :
-			return "|="; //$NON-NLS-1$
-		case XOR :
-			return "^="; //$NON-NLS-1$
-		case REMAINDER :
-			return "%="; //$NON-NLS-1$
-		case LEFT_SHIFT :
-			return "<<="; //$NON-NLS-1$
-		case RIGHT_SHIFT :
-			return ">>="; //$NON-NLS-1$
-		case UNSIGNED_RIGHT_SHIFT :
-			return ">>>="; //$NON-NLS-1$
-	};
-	return "unknown operator"; //$NON-NLS-1$
-}
-public TypeBinding resolveType(BlockScope scope) {
-	constant = NotAConstant;
-	if (!(this.lhs instanceof Reference)) {
-		scope.problemReporter().expressionShouldBeAVariable(this.lhs);
+	
+	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+		// record setting a variable: various scenarii are possible, setting an array reference, 
+		// a field reference, a blank final field reference, a field of an enclosing instance or 
+		// just a local variable.
+	
+		return  ((Reference) lhs).analyseAssignment(currentScope, flowContext, flowInfo, this, true).unconditionalInits();
 	}
-	TypeBinding lhsType = lhs.resolveType(scope);
-	TypeBinding expressionType = expression.resolveType(scope);
-	if (lhsType == null || expressionType == null)
-		return null;
-
-	int lhsId = lhsType.id;
-	int expressionId = expressionType.id;
-	if (restrainUsageToNumericTypes() && !lhsType.isNumericType()) {
-		scope.problemReporter().operatorOnlyValidOnNumericType(this, lhsType, expressionType);
-		return null;
+	
+	public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+	
+		// various scenarii are possible, setting an array reference, 
+		// a field reference, a blank final field reference, a field of an enclosing instance or 
+		// just a local variable.
+	
+		int pc = codeStream.position;
+		 ((Reference) lhs).generateCompoundAssignment(currentScope, codeStream, expression, operator, assignmentImplicitConversion, valueRequired);
+		if (valueRequired) {
+			codeStream.generateImplicitConversion(implicitConversion);
+		}
+		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
-	if (lhsId > 15 || expressionId > 15) {
-		if (lhsId != T_String) { // String += Object is valid wheraas Object -= String is not
+	
+	public String operatorToString() {
+		switch (operator) {
+			case PLUS :
+				return "+="; //$NON-NLS-1$
+			case MINUS :
+				return "-="; //$NON-NLS-1$
+			case MULTIPLY :
+				return "*="; //$NON-NLS-1$
+			case DIVIDE :
+				return "/="; //$NON-NLS-1$
+			case AND :
+				return "&="; //$NON-NLS-1$
+			case OR :
+				return "|="; //$NON-NLS-1$
+			case XOR :
+				return "^="; //$NON-NLS-1$
+			case REMAINDER :
+				return "%="; //$NON-NLS-1$
+			case LEFT_SHIFT :
+				return "<<="; //$NON-NLS-1$
+			case RIGHT_SHIFT :
+				return ">>="; //$NON-NLS-1$
+			case UNSIGNED_RIGHT_SHIFT :
+				return ">>>="; //$NON-NLS-1$
+		}
+		return "unknown operator"; //$NON-NLS-1$
+	}
+	
+	public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+	
+		lhs.printExpression(indent, output).append(' ').append(operatorToString()).append(' ');
+		return expression.printExpression(0, output) ; 
+	}
+	
+	public TypeBinding resolveType(BlockScope scope) {
+		constant = NotAConstant;
+		if (!(this.lhs instanceof Reference) || this.lhs.isThis()) {
+			scope.problemReporter().expressionShouldBeAVariable(this.lhs);
+			return null;
+		}
+		TypeBinding lhsType = lhs.resolveType(scope);
+		TypeBinding expressionType = expression.resolveType(scope);
+		if (lhsType == null || expressionType == null)
+			return null;
+	
+		int lhsId = lhsType.id;
+		int expressionId = expressionType.id;
+		if (restrainUsageToNumericTypes() && !lhsType.isNumericType()) {
+			scope.problemReporter().operatorOnlyValidOnNumericType(this, lhsType, expressionType);
+			return null;
+		}
+		if (lhsId > 15 || expressionId > 15) {
+			if (lhsId != T_String) { // String += Thread is valid whereas Thread += String  is not
+				scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+				return null;
+			}
+			expressionId = T_Object; // use the Object has tag table
+		}
+	
+		// the code is an int
+		// (cast)  left   Op (cast)  rigth --> result 
+		//  0000   0000       0000   0000      0000
+		//  <<16   <<12       <<8     <<4        <<0
+	
+		// the conversion is stored INTO the reference (info needed for the code gen)
+		int result = OperatorExpression.OperatorSignatures[operator][ (lhsId << 4) + expressionId];
+		if (result == T_undefined) {
 			scope.problemReporter().invalidOperator(this, lhsType, expressionType);
 			return null;
 		}
-		expressionId = T_Object; // use the Object has tag table
-	}
-
-	// the code is an int
-	// (cast)  left   Op (cast)  rigth --> result 
-	//  0000   0000       0000   0000      0000
-	//  <<16   <<12       <<8     <<4        <<0
-
-	// the conversion is stored INTO the reference (info needed for the code gen)
-	int result = OperatorExpression.ResolveTypeTables[operator][ (lhsId << 4) + expressionId];
-	if (result == T_undefined) {
-		scope.problemReporter().invalidOperator(this, lhsType, expressionType);
-		return null;
-	}
-	if (operator == PLUS){
-		if(scope.isJavaLangObject(lhsType)) {
-			// <Object> += <String> is illegal
-			scope.problemReporter().invalidOperator(this, lhsType, expressionType);
-			return null;
-		} else if ((lhsType.isNumericType() || lhsId == T_boolean) && !expressionType.isNumericType()){
-			// <int | boolean> += <String> is illegal
-			scope.problemReporter().invalidOperator(this, lhsType, expressionType);
-			return null;
+		if (operator == PLUS){
+			if(lhsId == T_JavaLangObject) {
+				// <Object> += <String> is illegal (39248)
+				scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+				return null;
+			} else {
+				// <int | boolean> += <String> is illegal
+				if ((lhsType.isNumericType() || lhsId == T_boolean) && !expressionType.isNumericType()){
+					scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+					return null;
+				}
+			}
 		}
+		lhs.implicitConversion = result >>> 12;
+		expression.implicitConversion = (result >>> 4) & 0x000FF;
+		assignmentImplicitConversion = (lhsId << 4) + (result & 0x0000F);
+		return this.resolvedType = lhsType;
 	}
-	lhs.implicitConversion = result >>> 12;
-	expression.implicitConversion = (result >>> 4) & 0x000FF;
-	assignmentImplicitConversion = (lhsId << 4) + (result & 0x0000F);
-	return this.resolvedType = lhsType;
-}
-public boolean restrainUsageToNumericTypes(){
-	return false ;}
-public String toStringExpressionNoParenthesis() {
-
-	return 	lhs.toStringExpression() + " " + //$NON-NLS-1$
-			operatorToString() + " " + //$NON-NLS-1$
-			expression.toStringExpression() ; }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	if (visitor.visit(this, scope)) {
-		lhs.traverse(visitor, scope);
-		expression.traverse(visitor, scope);
+	
+	public boolean restrainUsageToNumericTypes(){
+		return false ;
 	}
-	visitor.endVisit(this, scope);
-}
+	
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		if (visitor.visit(this, scope)) {
+			lhs.traverse(visitor, scope);
+			expression.traverse(visitor, scope);
+		}
+		visitor.endVisit(this, scope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index c7edf5e..2d0608d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -23,8 +23,6 @@
 	public Constant optimizedIfTrueConstant;
 	public Constant optimizedIfFalseConstant;
 	
-	private int returnTypeSlotSize = 1;
-
 	// for local variables table attributes
 	int trueInitStateIndex = -1;
 	int falseInitStateIndex = -1;
@@ -76,7 +74,6 @@
 		} else if (isConditionOptimizedFalse) {
 			mergedInfo = falseFlowInfo.addPotentialInitializationsFrom(trueFlowInfo);
 		} else {
-			// merge using a conditional info -  1GK2BLM
 			// if ((t && (v = t)) ? t : t && (v = f)) r = v;  -- ok
 			cst = this.optimizedIfTrueConstant;
 			boolean isValueIfTrueOptimizedTrue = cst != null && cst != NotAConstant && cst.booleanValue() == true;
@@ -164,7 +161,7 @@
 				codeStream.updateLastRecordedEndPC(position);
 				// Tune codestream stack size
 				if (valueRequired) {
-					codeStream.decrStackSize(returnTypeSlotSize);
+					codeStream.decrStackSize(this.resolvedType == LongBinding || this.resolvedType == DoubleBinding ? 2 : 1);
 				}
 			}
 		}
@@ -274,12 +271,24 @@
 		return this.optimizedBooleanConstant == null ? this.constant : this.optimizedBooleanConstant;
 	}
 	
+	public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+		
+		condition.printExpression(indent, output).append(" ? "); //$NON-NLS-1$
+		valueIfTrue.printExpression(0, output).append(" : "); //$NON-NLS-1$
+		return valueIfFalse.printExpression(0, output);
+	}
+
 	public TypeBinding resolveType(BlockScope scope) {
 		// specs p.368
 		constant = NotAConstant;
 		TypeBinding conditionType = condition.resolveTypeExpecting(scope, BooleanBinding);
+		
+		if (valueIfTrue instanceof CastExpression) valueIfTrue.bits |= IgnoreNeedForCastCheckMASK; // will check later on
 		TypeBinding valueIfTrueType = valueIfTrue.resolveType(scope);
+
+		if (valueIfFalse instanceof CastExpression) valueIfFalse.bits |= IgnoreNeedForCastCheckMASK; // will check later on
 		TypeBinding valueIfFalseType = valueIfFalse.resolveType(scope);
+
 		if (conditionType == null || valueIfTrueType == null || valueIfFalseType == null)
 			return null;
 
@@ -295,20 +304,18 @@
 		if (valueIfTrueType == valueIfFalseType) { // harmed the implicit conversion 
 			valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
 			valueIfFalse.implicitConversion = valueIfTrue.implicitConversion;
-			if (valueIfTrueType == LongBinding || valueIfTrueType == DoubleBinding) {
-				returnTypeSlotSize = 2;
-			}
-
 			if (valueIfTrueType == BooleanBinding) {
 				this.optimizedIfTrueConstant = valueIfTrue.optimizedBooleanConstant();
 				this.optimizedIfFalseConstant = valueIfFalse.optimizedBooleanConstant();
-			
-				// Propagate the optimized boolean constant if possible
-				if ((condConstant = condition.optimizedBooleanConstant()) != NotAConstant) {
-					
+				if (this.optimizedIfTrueConstant != NotAConstant 
+						&& this.optimizedIfFalseConstant != NotAConstant
+						&& this.optimizedIfTrueConstant.booleanValue() == this.optimizedIfFalseConstant.booleanValue()) {
+					// a ? true : true  /   a ? false : false
+					this.optimizedBooleanConstant = optimizedIfTrueConstant;
+				} else if ((condConstant = condition.optimizedBooleanConstant()) != NotAConstant) { // Propagate the optimized boolean constant if possible
 					this.optimizedBooleanConstant = condConstant.booleanValue()
-						? optimizedIfTrueConstant
-						: optimizedIfFalseConstant;
+						? this.optimizedIfTrueConstant
+						: this.optimizedIfFalseConstant;
 				}
 			}
 			return this.resolvedType = valueIfTrueType;
@@ -321,64 +328,55 @@
 				|| (valueIfTrueType == ShortBinding && valueIfFalseType == ByteBinding)) {
 				valueIfTrue.implicitWidening(ShortBinding, valueIfTrueType);
 				valueIfFalse.implicitWidening(ShortBinding, valueIfFalseType);
-				this.resolvedType = ShortBinding;
-				return ShortBinding;
+				return this.resolvedType = ShortBinding;
 			}
 			// <Byte|Short|Char> x constant(Int)  ---> <Byte|Short|Char>   and reciprocally
 			if ((valueIfTrueType == ByteBinding || valueIfTrueType == ShortBinding || valueIfTrueType == CharBinding)
-				&& (valueIfFalseType == IntBinding
-					&& valueIfFalse.isConstantValueOfTypeAssignableToType(valueIfFalseType, valueIfTrueType))) {
+					&& (valueIfFalseType == IntBinding
+						&& valueIfFalse.isConstantValueOfTypeAssignableToType(valueIfFalseType, valueIfTrueType))) {
 				valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
 				valueIfFalse.implicitWidening(valueIfTrueType, valueIfFalseType);
-				this.resolvedType = valueIfTrueType;
-				return valueIfTrueType;
+				return this.resolvedType = valueIfTrueType;
 			}
 			if ((valueIfFalseType == ByteBinding
-				|| valueIfFalseType == ShortBinding
-				|| valueIfFalseType == CharBinding)
-				&& (valueIfTrueType == IntBinding
-					&& valueIfTrue.isConstantValueOfTypeAssignableToType(valueIfTrueType, valueIfFalseType))) {
+					|| valueIfFalseType == ShortBinding
+					|| valueIfFalseType == CharBinding)
+					&& (valueIfTrueType == IntBinding
+						&& valueIfTrue.isConstantValueOfTypeAssignableToType(valueIfTrueType, valueIfFalseType))) {
 				valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
 				valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
-				this.resolvedType = valueIfFalseType;
-				return valueIfFalseType;
+				return this.resolvedType = valueIfFalseType;
 			}
 			// Manual binary numeric promotion
 			// int
 			if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_int)
-				&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_int)) {
+					&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_int)) {
 				valueIfTrue.implicitWidening(IntBinding, valueIfTrueType);
 				valueIfFalse.implicitWidening(IntBinding, valueIfFalseType);
-				this.resolvedType = IntBinding;
-				return IntBinding;
+				return this.resolvedType = IntBinding;
 			}
 			// long
 			if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_long)
-				&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_long)) {
+					&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_long)) {
 				valueIfTrue.implicitWidening(LongBinding, valueIfTrueType);
 				valueIfFalse.implicitWidening(LongBinding, valueIfFalseType);
-				returnTypeSlotSize = 2;
-				this.resolvedType = LongBinding;
-				return LongBinding;
+				return this.resolvedType = LongBinding;
 			}
 			// float
 			if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_float)
-				&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_float)) {
+					&& BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_float)) {
 				valueIfTrue.implicitWidening(FloatBinding, valueIfTrueType);
 				valueIfFalse.implicitWidening(FloatBinding, valueIfFalseType);
-				this.resolvedType = FloatBinding;
-				return FloatBinding;
+				return this.resolvedType = FloatBinding;
 			}
 			// double
 			valueIfTrue.implicitWidening(DoubleBinding, valueIfTrueType);
 			valueIfFalse.implicitWidening(DoubleBinding, valueIfFalseType);
-			returnTypeSlotSize = 2;
-			this.resolvedType = DoubleBinding;
-			return DoubleBinding;
+			return this.resolvedType = DoubleBinding;
 		}
 		// Type references (null null is already tested)
 		if ((valueIfTrueType.isBaseType() && valueIfTrueType != NullBinding)
-			|| (valueIfFalseType.isBaseType() && valueIfFalseType != NullBinding)) {
+				|| (valueIfFalseType.isBaseType() && valueIfFalseType != NullBinding)) {
 			scope.problemReporter().conditionalArgumentsIncompatibleTypes(
 				this,
 				valueIfTrueType,
@@ -388,14 +386,12 @@
 		if (valueIfFalseType.isCompatibleWith(valueIfTrueType)) {
 			valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
 			valueIfFalse.implicitWidening(valueIfTrueType, valueIfFalseType);
-			this.resolvedType = valueIfTrueType;
-			return valueIfTrueType;
+			return this.resolvedType = valueIfTrueType;
 		}
 		if (valueIfTrueType.isCompatibleWith(valueIfFalseType)) {
 			valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
 			valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
-			this.resolvedType = valueIfFalseType;
-			return valueIfFalseType;
+			return this.resolvedType = valueIfFalseType;
 		}
 		scope.problemReporter().conditionalArgumentsIncompatibleTypes(
 			this,
@@ -404,13 +400,7 @@
 		return null;
 	}
 	
-	public String toStringExpressionNoParenthesis() {
-		return condition.toStringExpression() + " ? " + //$NON-NLS-1$
-		valueIfTrue.toStringExpression() + " : " + //$NON-NLS-1$
-		valueIfFalse.toStringExpression();
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		if (visitor.visit(this, scope)) {
 			condition.traverse(visitor, scope);
 			valueIfTrue.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
index 373f023..43d7dd0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
@@ -14,9 +14,9 @@
 
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.parser.*;
 import org.eclipse.jdt.internal.compiler.problem.*;
@@ -95,8 +95,8 @@
 			if (statements != null) {
 				boolean didAlreadyComplain = false;
 				for (int i = 0, count = statements.length; i < count; i++) {
-					Statement stat;
-					if (!flowInfo.complainIfUnreachable(stat = statements[i], scope, didAlreadyComplain)) {
+					Statement stat = statements[i];
+					if (!stat.complainIfUnreachable(flowInfo, scope, didAlreadyComplain)) {
 						flowInfo = stat.analyseCode(scope, constructorContext, flowInfo);
 					} else {
 						didAlreadyComplain = true;
@@ -118,10 +118,12 @@
 						&& (!flowInfo.isDefinitelyAssigned(fields[i]))) {
 						scope.problemReporter().uninitializedBlankFinalField(
 							field,
-							isDefaultConstructor ? (AstNode) scope.referenceType() : this);
+							isDefaultConstructor ? (ASTNode) scope.referenceType() : this);
 					}
 				}
 			}
+			// check unreachable catch blocks
+			constructorContext.complainIfUnusedExceptionHandlers(this);
 		} catch (AbortMethod e) {
 			this.ignoreFurtherInvestigation = true;
 		}
@@ -182,7 +184,7 @@
 	}
 
 	public void generateSyntheticFieldInitializationsIfNecessary(
-		MethodScope scope,
+		MethodScope methodScope,
 		CodeStream codeStream,
 		ReferenceBinding declaringClass) {
 			
@@ -261,7 +263,7 @@
 			boolean needFieldInitializations = constructorCall == null || constructorCall.accessMode != ExplicitConstructorCall.This;
 
 			// post 1.4 source level, synthetic initializations occur prior to explicit constructor call
-			boolean preInitSyntheticFields = scope.environment().options.targetJDK >= CompilerOptions.JDK1_4;
+			boolean preInitSyntheticFields = scope.environment().options.targetJDK >= ClassFileConstants.JDK1_4;
 
 			if (needFieldInitializations && preInitSyntheticFields){
 				generateSyntheticFieldInitializationsIfNecessary(scope, codeStream, declaringClass);
@@ -315,7 +317,7 @@
 
 	public boolean isDefaultConstructor() {
 
-		return isDefaultConstructor;
+		return this.isDefaultConstructor;
 	}
 
 	public boolean isInitializationMethod() {
@@ -327,6 +329,9 @@
 	 * Returns true if the constructor is directly involved in a cycle.
 	 * Given most constructors aren't, we only allocate the visited list
 	 * lazily.
+	 * 
+	 * @param visited
+	 * @return
 	 */
 	public boolean isRecursive(ArrayList visited) {
 
@@ -368,6 +373,33 @@
 
 	}
 
+	public StringBuffer printBody(int indent, StringBuffer output) {
+
+		output.append(" {"); //$NON-NLS-1$
+		if (constructorCall != null) {
+			output.append('\n');
+			constructorCall.printStatement(indent, output); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		if (statements != null) {
+			for (int i = 0; i < statements.length; i++) {
+				output.append('\n');
+				statements[i].printStatement(indent, output); //$NON-NLS-1$
+			}
+		}
+		output.append('\n');
+		printIndent(indent == 0 ? 0 : indent - 1, output).append('}');
+		return output;
+	}
+	
+	public void resolveJavadoc() {
+		
+		if (this.binding == null || this.javadoc != null) {
+			super.resolveJavadoc();
+		} else if (!isDefaultConstructor) {
+			this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
+		}
+	}
+
 	/*
 	 * Type checking for constructor, just another method, except for special check
 	 * for recursive constructor invocations.
@@ -396,27 +428,8 @@
 		super.resolveStatements();
 	}
 
-	public String toStringStatements(int tab) {
-
-		String s = " {"; //$NON-NLS-1$
-		if (constructorCall != null) {
-			s = s + "\n" + constructorCall.toString(tab) + ";"; //$NON-NLS-1$ //$NON-NLS-2$
-		}
-		if (statements != null) {
-			for (int i = 0; i < statements.length; i++) {
-				s = s + "\n" + statements[i].toString(tab); //$NON-NLS-1$
-				if (!(statements[i] instanceof Block)) {
-					s += ";"; //$NON-NLS-1$
-				}
-			}
-		}
-		s += "\n" + tabString(tab == 0 ? 0 : tab - 1) + "}"; //$NON-NLS-1$ //$NON-NLS-2$
-		//$NON-NLS-2$ //$NON-NLS-1$
-		return s;
-	}
-
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		ClassScope classScope) {
 
 		if (visitor.visit(this, classScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Continue.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java
similarity index 78%
rename from org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Continue.java
rename to org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java
index 7c827e1..1b0ec26 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Continue.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java
@@ -10,13 +10,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
-public class Continue extends BranchStatement {
+public class ContinueStatement extends BranchStatement {
 
-	public Continue(char[] l, int s, int e) {
+	public ContinueStatement(char[] l, int s, int e) {
 		
 		super(l, s, e);
 	}
@@ -50,22 +50,22 @@
 		targetLabel = targetContext.continueLabel();
 		FlowContext traversedContext = flowContext;
 		int subIndex = 0, maxSub = 5;
-		subroutines = new AstNode[maxSub];
+		subroutines = new SubRoutineStatement[maxSub];
 
 		do {
-			AstNode sub;
+			SubRoutineStatement sub;
 			if ((sub = traversedContext.subRoutine()) != null) {
 				if (subIndex == maxSub) {
-					System.arraycopy(subroutines, 0, (subroutines = new AstNode[maxSub*=2]), 0, subIndex); // grow
+					System.arraycopy(subroutines, 0, (subroutines = new SubRoutineStatement[maxSub*=2]), 0, subIndex); // grow
 				}
 				subroutines[subIndex++] = sub;
-				if (sub.cannotReturn()) {
+				if (sub.isSubRoutineEscaping()) {
 					break;
 				}
 			}
 			traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
 
-			AstNode node;
+			ASTNode node;
 			if ((node = traversedContext.associatedNode) instanceof TryStatement) {
 				TryStatement tryStatement = (TryStatement) node;
 				flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits			
@@ -78,22 +78,20 @@
 		
 		// resize subroutines
 		if (subIndex != maxSub) {
-			System.arraycopy(subroutines, 0, (subroutines = new AstNode[subIndex]), 0, subIndex);
+			System.arraycopy(subroutines, 0, (subroutines = new SubRoutineStatement[subIndex]), 0, subIndex);
 		}
 		return FlowInfo.DEAD_END;
 	}
 
-	public String toString(int tab) {
+	public StringBuffer printStatement(int tab, StringBuffer output) {
 
-		String s = tabString(tab);
-		s += "continue "; //$NON-NLS-1$
-		if (label != null)
-			s += new String(label);
-		return s;
+		printIndent(tab, output).append("continue "); //$NON-NLS-1$
+		if (label != null) output.append(label);
+		return output.append(';');
 	}
 
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		visitor.visit(this, blockScope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DefaultCase.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DefaultCase.java
deleted file mode 100644
index 250e327..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DefaultCase.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.compiler.ast;
-
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
-import org.eclipse.jdt.internal.compiler.codegen.*;
-import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-
-public class DefaultCase extends Statement {
-
-	public CaseLabel targetLabel;
-	/**
-	 * DefautCase constructor comment.
-	 */
-	public DefaultCase(int sourceEnd, int sourceStart) {
-
-		this.sourceStart = sourceStart;
-		this.sourceEnd = sourceEnd;
-	}
-
-	public FlowInfo analyseCode(
-		BlockScope currentScope,
-		FlowContext flowContext,
-		FlowInfo flowInfo) {
-
-		return flowInfo;
-	}
-
-	/**
-	 * Default case code generation
-	 *
-	 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
-	 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
-	 */
-	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-
-		if ((bits & IsReachableMASK) == 0) {
-			return;
-		}
-		int pc = codeStream.position;
-		targetLabel.place();
-		codeStream.recordPositionsFrom(pc, this.sourceStart);
-
-	}
-	/**
-	 * No-op : should use resolveCase(...) instead.
-	 */
-	public void resolve(BlockScope scope) {
-	}
-
-	public Constant resolveCase(
-		BlockScope scope,
-		TypeBinding testType,
-		SwitchStatement switchStatement) {
-
-		// remember the default case into the associated switch statement
-		if (switchStatement.defaultCase != null)
-			scope.problemReporter().duplicateDefaultCase(this);
-
-		// on error the last default will be the selected one .... (why not) ....	
-		switchStatement.defaultCase = this;
-		resolve(scope);
-		return null;
-	}
-
-	public String toString(int tab) {
-
-		String s = tabString(tab);
-		s = s + "default : "; //$NON-NLS-1$
-		return s;
-	}
-
-	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
-		BlockScope blockScope) {
-
-		visitor.visit(this, blockScope);
-		visitor.endVisit(this, blockScope);
-	}
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
index e9e4ec6..e79d021 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -32,6 +32,8 @@
 		this.sourceEnd = e;
 		this.condition = condition;
 		this.action = action;
+		// remember useful empty statement
+		if (action instanceof EmptyStatement) action.bits |= IsUsefulEmptyStatementMASK;
 	}
 
 	public FlowInfo analyseCode(
@@ -83,22 +85,14 @@
 			loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
 		}
 
-		// infinite loop
-		FlowInfo mergedInfo;
-		if (isConditionTrue) {
-			mergedInfo = loopingContext.initsOnBreak;
-			if (!mergedInfo.isReachable()) mergedInfo.addPotentialInitializationsFrom(flowInfo.initsWhenFalse());
-		} else {
-			// end of loop: either condition false or break
-			mergedInfo =
-				flowInfo.initsWhenFalse().unconditionalInits().mergedWith(
-					loopingContext.initsOnBreak);
-			if (isConditionOptimizedTrue && !loopingContext.initsOnBreak.isReachable()) {
-				mergedInfo.setReachMode(FlowInfo.UNREACHABLE);
-			}
-		}
-		mergedInitStateIndex =
-			currentScope.methodScope().recordInitializationStates(mergedInfo);
+		// end of loop
+		FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
+				loopingContext.initsOnBreak, 
+				isConditionOptimizedTrue, 
+				flowInfo.initsWhenFalse(), 
+				false, // never consider opt false case for DO loop, since break can always occur (47776)
+				!isConditionTrue /*do{}while(true); unreachable(); */);
+		mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
 		return mergedInfo;
 	}
 
@@ -147,6 +141,19 @@
 
 	}
 
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+
+		printIndent(indent, output).append("do"); //$NON-NLS-1$
+		if (action == null)
+			output.append(" ;\n"); //$NON-NLS-1$
+		else {
+			output.append('\n');
+			action.printStatement(indent + 1, output).append('\n');
+		}
+		output.append("while ("); //$NON-NLS-1$
+		return condition.printExpression(0, output).append(");"); //$NON-NLS-1$
+	}
+
 	public void resetStateForCodeGeneration() {
 		if (this.breakLabel != null) {
 			this.breakLabel.resetStateForCodeGeneration();
@@ -164,22 +171,7 @@
 			action.resolve(scope);
 	}
 
-	public String toString(int tab) {
-
-		String inFront, s = tabString(tab);
-		inFront = s;
-		s = s + "do"; //$NON-NLS-1$
-		if (action == null)
-			s = s + " {}\n"; //$NON-NLS-1$
-		else if (action instanceof Block)
-			s = s + "\n" + action.toString(tab + 1) + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
-		else
-			s = s + " {\n" + action.toString(tab + 1) + ";}\n"; //$NON-NLS-1$ //$NON-NLS-2$
-		s = s + inFront + "while (" + condition.toStringExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
-		return s;
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
 			if (action != null) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java
index 24228cf..33a1f58 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -64,7 +64,7 @@
 public TypeBinding literalType(BlockScope scope) {
 	return DoubleBinding;
 }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+public void traverse(ASTVisitor visitor, BlockScope blockScope) {
 	visitor.visit(this, blockScope);
 	visitor.endVisit(this, blockScope);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java
index c7b7cac..462cbec 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java
@@ -11,10 +11,11 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 
 public class EmptyStatement extends Statement {
 
@@ -27,20 +28,35 @@
 		return flowInfo;
 	}
 
+	// Report an error if necessary
+	public boolean complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, boolean didAlreadyComplain) {
+		
+		// before 1.4, empty statements are tolerated anywhere
+		if (scope.environment().options.complianceLevel < ClassFileConstants.JDK1_4) {
+			return false;
+		}
+		return super.complainIfUnreachable(flowInfo, scope, didAlreadyComplain);
+	}
+	
 	public void generateCode(BlockScope currentScope, CodeStream codeStream){
 		// no bytecode, no need to check for reachability or recording source positions
 	}
 	
-	public void resolve(BlockScope scope) {
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+		return printIndent(tab, output).append(';');
 	}
-	
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+		
+	public void resolve(BlockScope scope) {
+		if ((bits & IsUsefulEmptyStatementMASK) == 0) {
+			scope.problemReporter().superfluousSemicolon(this.sourceStart, this.sourceEnd);
+		}
+	}
+
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		visitor.visit(this, scope);
 		visitor.endVisit(this, scope);
 	}
 	
-	public String toString(int tab) {
-		return tabString(tab) + ";"; //$NON-NLS-1$ 
-	}
+
 }
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
index 8ab409f..60015bb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
@@ -10,7 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -177,7 +178,7 @@
 				int expressionTbMethodsLength = expressionTbMethods.length;
 				for (int i = 0; i < castTbMethodsLength; i++) {
 					for (int j = 0; j < expressionTbMethodsLength; j++) {
-						if (castTbMethods[i].selector == expressionTbMethods[j].selector) {
+						if (CharOperation.equals(castTbMethods[i].selector, expressionTbMethods[j].selector)) {
 							if (castTbMethods[i].returnType != expressionTbMethods[j].returnType) {
 								if (castTbMethods[i].areParametersEqual(expressionTbMethods[j])) {
 									return false;
@@ -498,9 +499,15 @@
 	return false;
 }
 public TypeBinding resolveType(BlockScope scope) {
+
+		boolean leftIsCast, rightIsCast;
+		if ((leftIsCast = left instanceof CastExpression) == true) left.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+		TypeBinding leftType = left.resolveType(scope);
+
+		if ((rightIsCast = right instanceof CastExpression) == true) right.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+		TypeBinding rightType = right.resolveType(scope);
+
 	// always return BooleanBinding
-	TypeBinding leftType = left.resolveType(scope);
-	TypeBinding rightType = right.resolveType(scope);
 	if (leftType == null || rightType == null){
 		constant = NotAConstant;		
 		return null;
@@ -509,43 +516,60 @@
 	// both base type
 	if (leftType.isBaseType() && rightType.isBaseType()) {
 		// the code is an int
-		// (cast)  left   == (cast)  rigth --> result
+		// (cast)  left   == (cast)  right --> result
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       <<0
-		int result = ResolveTypeTables[EQUAL_EQUAL][ (leftType.id << 4) + rightType.id];
-		left.implicitConversion = result >>> 12;
-		right.implicitConversion = (result >>> 4) & 0x000FF;
-		bits |= result & 0xF;		
-		if ((result & 0x0000F) == T_undefined) {
+		int operatorSignature = OperatorSignatures[EQUAL_EQUAL][ (leftType.id << 4) + rightType.id];
+		left.implicitConversion = operatorSignature >>> 12;
+		right.implicitConversion = (operatorSignature >>> 4) & 0x000FF;
+		bits |= operatorSignature & 0xF;		
+		if ((operatorSignature & 0x0000F) == T_undefined) {
 			constant = Constant.NotAConstant;
 			scope.problemReporter().invalidOperator(this, leftType, rightType);
 			return null;
 		}
+		// check need for operand cast
+		if (leftIsCast || rightIsCast) {
+			CastExpression.checkNeedForArgumentCasts(scope, EQUAL_EQUAL, operatorSignature, left, leftType.id, leftIsCast, right, rightType.id, rightIsCast);
+		}
 		computeConstant(leftType, rightType);
-		this.resolvedType = BooleanBinding;
-		return BooleanBinding;
+		return this.resolvedType = BooleanBinding;
 	}
 
 	// Object references 
 	// spec 15.20.3
 	if (areTypesCastCompatible(scope, rightType, leftType) || areTypesCastCompatible(scope, leftType, rightType)) {
 		// (special case for String)
-		if ((rightType.id == T_String) && (leftType.id == T_String))
+		if ((rightType.id == T_String) && (leftType.id == T_String)) {
 			computeConstant(leftType, rightType);
-		else
+		} else {
 			constant = NotAConstant;
-		if (rightType.id == T_String)
+		}
+		if (rightType.id == T_String) {
 			right.implicitConversion = String2String;
-		if (leftType.id == T_String)
+		}
+		if (leftType.id == T_String) {
 			left.implicitConversion = String2String;
-		this.resolvedType = BooleanBinding;
-		return BooleanBinding;
+		}
+		// check need for operand cast
+		boolean unnecessaryLeftCast = (left.bits & UnnecessaryCastMask) != 0;
+		boolean unnecessaryRightCast = (right.bits & UnnecessaryCastMask) != 0;
+		if (unnecessaryLeftCast || unnecessaryRightCast) {
+			TypeBinding alternateLeftType = unnecessaryLeftCast ? ((CastExpression)left).expression.resolvedType : leftType;
+			TypeBinding alternateRightType = unnecessaryRightCast ? ((CastExpression)right).expression.resolvedType : rightType;
+			if (areTypesCastCompatible(scope, alternateLeftType, alternateRightType)
+					|| areTypesCastCompatible(scope, alternateRightType, alternateLeftType)) {
+				if (unnecessaryLeftCast) scope.problemReporter().unnecessaryCast((CastExpression)left); 
+				if (unnecessaryRightCast) scope.problemReporter().unnecessaryCast((CastExpression)right);
+			}
+		}
+		return this.resolvedType = BooleanBinding;
 	}
 	constant = NotAConstant;
 	scope.problemReporter().notCompatibleTypesError(this, leftType, rightType);
 	return null;
 }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+public void traverse(ASTVisitor visitor, BlockScope scope) {
 	if (visitor.visit(this, scope)) {
 		left.traverse(visitor, scope);
 		right.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
index e9dca4c..cf9c90b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -71,13 +71,13 @@
 				flowContext.checkExceptionHandlers(
 					thrownExceptions,
 					(accessMode == ImplicitSuper)
-						? (AstNode) currentScope.methodScope().referenceContext
-						: (AstNode) this,
+						? (ASTNode) currentScope.methodScope().referenceContext
+						: (ASTNode) this,
 					flowInfo,
 					currentScope);
 			}
-			manageEnclosingInstanceAccessIfNecessary(currentScope);
-			manageSyntheticAccessIfNecessary(currentScope);
+			manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+			manageSyntheticAccessIfNecessary(currentScope, flowInfo);
 			return flowInfo;
 		} finally {
 			((MethodScope) currentScope).isConstructorCall = false;
@@ -165,9 +165,10 @@
 	 * types, since by the time we reach them, we might not yet know their
 	 * exact need.
 	 */
-	void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
+	void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 		ReferenceBinding superType;
 
+		if (!flowInfo.isReachable()) return;
 		// perform some emulation work in case there is some and we are inside a local type only
 		if ((superType = binding.declaringClass).isNestedType()
 			&& currentScope.enclosingSourceType().isLocalType()) {
@@ -181,8 +182,9 @@
 		}
 	}
 
-	public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
+	public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
+		if (!flowInfo.isReachable()) return;
 		// perform some emulation work in case there is some and we are inside a local type only
 		if (binding.isPrivate() && (accessMode != This)) {
 
@@ -200,14 +202,40 @@
 		}
 	}
 
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+
+		printIndent(indent, output);
+		if (qualification != null) qualification.printExpression(0, output).append('.');
+		if (accessMode == This) {
+			output.append("this("); //$NON-NLS-1$
+		} else {
+			output.append("super("); //$NON-NLS-1$
+		}
+		if (arguments != null) {
+			for (int i = 0; i < arguments.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				arguments[i].printExpression(0, output);
+			}
+		}
+		return output.append(");"); //$NON-NLS-1$
+	}
+	
 	public void resolve(BlockScope scope) {
 		// the return type should be void for a constructor.
 		// the test is made into getConstructor
 
 		// mark the fact that we are in a constructor call.....
 		// unmark at all returns
+		MethodScope methodScope = scope.methodScope();
 		try {
-			((MethodScope) scope).isConstructorCall = true;
+			AbstractMethodDeclaration methodDeclaration = methodScope.referenceMethod();
+			if (methodDeclaration == null 
+					|| !methodDeclaration.isConstructor()
+					|| ((ConstructorDeclaration) methodDeclaration).constructorCall != this) {
+				scope.problemReporter().invalidExplicitConstructorCall(this);
+				return;
+			}
+			methodScope.isConstructorCall = true;
 			ReferenceBinding receiverType = scope.enclosingSourceType();
 			if (accessMode != This)
 				receiverType = receiverType.superclass();
@@ -236,19 +264,27 @@
 			}
 
 			// arguments buffering for the method lookup
-			TypeBinding[] argTypes = NoParameters;
+			TypeBinding[] argumentTypes = NoParameters;
+			boolean argsContainCast = false;
 			if (arguments != null) {
 				boolean argHasError = false; // typeChecks all arguments
 				int length = arguments.length;
-				argTypes = new TypeBinding[length];
-				for (int i = 0; i < length; i++)
-					if ((argTypes[i] = arguments[i].resolveType(scope)) == null)
+				argumentTypes = new TypeBinding[length];
+				for (int i = 0; i < length; i++) {
+					Expression argument = this.arguments[i];
+					if (argument instanceof CastExpression) {
+						argument.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+						argsContainCast = true;
+					}
+					if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
 						argHasError = true;
-				if (argHasError)
+					}
+				}
+				if (argHasError) {
 					return;
+				}
 			}
-			if ((binding = scope.getConstructor(receiverType, argTypes, this))
-				.isValidBinding()) {
+			if ((binding = scope.getConstructor(receiverType, argumentTypes, this)).isValidBinding()) {
 				if (isMethodUseDeprecated(binding, scope))
 					scope.problemReporter().deprecatedMethod(binding, this);
 
@@ -256,8 +292,12 @@
 				if (arguments != null) {
 					int length = arguments.length;
 					TypeBinding[] paramTypes = binding.parameters;
-					for (int i = 0; i < length; i++)
-						arguments[i].implicitWidening(paramTypes[i], argTypes[i]);
+					for (int i = 0; i < length; i++) {
+						arguments[i].implicitWidening(paramTypes[i], argumentTypes[i]);
+					}
+					if (argsContainCast) {
+						CastExpression.checkNeedForArgumentCasts(scope, null, receiverType, binding, this.arguments, argumentTypes, this);
+					}
 				}
 				if (binding.isPrivate()) {
 					binding.modifiers |= AccPrivateUsed;
@@ -268,7 +308,7 @@
 				scope.problemReporter().invalidConstructor(this, binding);
 			}
 		} finally {
-			((MethodScope) scope).isConstructorCall = false;
+			methodScope.isConstructorCall = false;
 		}
 	}
 
@@ -284,36 +324,15 @@
 		// ignore for here
 	}
 
-	public String toString(int tab) {
-
-		String s = tabString(tab);
-		if (qualification != null)
-			s = s + qualification.toStringExpression() + "."; //$NON-NLS-1$
-		if (accessMode == This) {
-			s = s + "this("; //$NON-NLS-1$
-		} else {
-			s = s + "super("; //$NON-NLS-1$
-		}
-		if (arguments != null)
-			for (int i = 0; i < arguments.length; i++) {
-				s = s + arguments[i].toStringExpression();
-				if (i != arguments.length - 1)
-					s = s + ", "; //$NON-NLS-1$
-			}
-		s = s + ")"; //$NON-NLS-1$
-		return s;
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
-			if (qualification != null) {
-				qualification.traverse(visitor, scope);
+			if (this.qualification != null) {
+				this.qualification.traverse(visitor, scope);
 			}
-			if (arguments != null) {
-				int argumentLength = arguments.length;
-				for (int i = 0; i < argumentLength; i++)
-					arguments[i].traverse(visitor, scope);
+			if (this.arguments != null) {
+				for (int i = 0, argumentLength = this.arguments.length; i < argumentLength; i++)
+					this.arguments[i].traverse(visitor, scope);
 			}
 		}
 		visitor.endVisit(this, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
index 3357d28..801e92d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -19,7 +19,7 @@
 
 public abstract class Expression extends Statement {
 	
-	//some expression may not be used - from a java semantic point
+	//Some expression may not be used - from a java semantic point
 	//of view only - as statements. Other may. In order to avoid the creation
 	//of wrappers around expression in order to tune them as expression
 	//Expression is a subclass of Statement. See the message isValidJavaStatement()
@@ -48,10 +48,9 @@
 	 * since it is not strictly equivalent to the definition of constant expressions.
 	 * In particular, some side-effects may be required to occur (only the end value
 	 * is known).
-	 * Constant is known to be of boolean type
+	 * @return Constant known to be of boolean type
 	 */ 
 	public Constant optimizedBooleanConstant() {
-
 		return this.constant;
 	}
 
@@ -250,6 +249,11 @@
 
 	/**
 	 * Default generation of a boolean value
+	 * @param currentScope
+	 * @param codeStream
+	 * @param trueLabel
+	 * @param falseLabel
+	 * @param valueRequired
 	 */
 	public void generateOptimizedBoolean(
 		BlockScope currentScope,
@@ -318,6 +322,9 @@
 		org.eclipse.jdt.internal.compiler.codegen.CodeStream codeStream,
 		int typeID) {
 
+		if (typeID == T_String && this.constant != NotAConstant && this.constant.stringValue().length() == 0) {
+			return; // optimize str + ""
+		}
 		generateCode(blockScope, codeStream, true);
 		codeStream.invokeStringBufferAppendForType(typeID);
 	}
@@ -346,7 +353,12 @@
 		codeStream.dup();
 		if (typeID == T_String || typeID == T_null) {
 			if (constant != NotAConstant) {
-				codeStream.ldc(constant.stringValue());
+				String stringValue = constant.stringValue();
+				if (stringValue.length() == 0) {  // optimize ""+<str> 
+					codeStream.invokeStringBufferDefaultConstructor();
+					return;
+				}
+				codeStream.ldc(stringValue);
 			} else {
 				generateCode(blockScope, codeStream, true);
 				codeStream.invokeStringValueOf(T_Object);
@@ -440,6 +452,11 @@
 		return null;
 	}
 
+	public TypeBinding resolveType(ClassScope classScope) {
+		// by default... subclasses should implement a better TB if required.
+		return null;
+	}
+
 	public TypeBinding resolveTypeExpecting(
 		BlockScope scope,
 		TypeBinding expectedType) {
@@ -455,30 +472,15 @@
 		return expressionType;
 	}
 
-	public String toString(int tab) {
-
-		//Subclass re-define toStringExpression
-		String s = tabString(tab);
-		if (constant != null)
-			//before TC has runned
-			if (constant != NotAConstant)
-				//after the TC has runned
-				s += " /*cst:" + constant.toString() + "*/ "; //$NON-NLS-1$ //$NON-NLS-2$
-		return s + toStringExpression(tab);
+	public StringBuffer print(int indent, StringBuffer output) {
+		printIndent(indent, output);
+		return printExpression(indent, output);
 	}
 
-	//Subclass re-define toStringExpression
-	//This method is abstract and should never be called
-	//but we provide some code that is running.....just in case
-	//of developpement time (while every  thing is not built)
-	public String toStringExpression() {
-
-		return super.toString(0);
-	}
-
-	public String toStringExpression(int tab) {
-		// default is regular toString expression (qualified allocation expressions redifine this method)
-		return this.toStringExpression();
+	public abstract StringBuffer printExpression(int indent, StringBuffer output);
+	
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+		return print(indent, output).append(";"); //$NON-NLS-1$
 	}
 
 	public Expression toTypeReference() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExtendedStringLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExtendedStringLiteral.java
index e79212d..7e9b9df 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExtendedStringLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExtendedStringLiteral.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 
 public class ExtendedStringLiteral extends StringLiteral {
@@ -66,13 +66,12 @@
 		return this;
 	}
 
-	public String toStringExpression() {
+	public StringBuffer printExpression(int indent, StringBuffer output) {
 
-		String str = "ExtendedStringLiteral{" + new String(source) + "}";	//$NON-NLS-2$ //$NON-NLS-1$
-		return str;
+		return output.append("ExtendedStringLiteral{").append(source).append('}'); //$NON-NLS-1$
 	}
 
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		visitor.visit(this, scope);
 		visitor.endVisit(this, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java
index f805141..c181a53 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -60,7 +60,7 @@
 public char[] source() {
 	return source;
 }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+public void traverse(ASTVisitor visitor, BlockScope scope) {
 	visitor.visit(this, scope);
 	visitor.endVisit(this, scope);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
index 1dd18cd..c18541c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -19,6 +19,7 @@
 public class FieldDeclaration extends AbstractVariableDeclaration {
 	public FieldBinding binding;
 	boolean hasBeenResolved = false;
+	public Javadoc javadoc;
 
 	//allows to retrieve both the "type" part of the declaration (part1)
 	//and also the part that decribe the name and the init and optionally
@@ -32,15 +33,14 @@
 	public int endPart2Position;
 
 	public FieldDeclaration() {
+		// for subtypes or conversion
 	}
 
 	public FieldDeclaration(
-		Expression initialization,
 		char[] name,
 		int sourceStart,
 		int sourceEnd) {
 
-		this.initialization = initialization;
 		this.name = name;
 
 		//due to some declaration like 
@@ -61,24 +61,24 @@
 			}
 		}
 		// cannot define static non-constant field inside nested class
-		if (binding != null
-			&& binding.isValidBinding()
-			&& binding.isStatic()
-			&& binding.constant == NotAConstant
-			&& binding.declaringClass.isNestedType()
-			&& binding.declaringClass.isClass()
-			&& !binding.declaringClass.isStatic()) {
+		if (this.binding != null
+			&& this.binding.isValidBinding()
+			&& this.binding.isStatic()
+			&& this.binding.constant == NotAConstant
+			&& this.binding.declaringClass.isNestedType()
+			&& this.binding.declaringClass.isClass()
+			&& !this.binding.declaringClass.isStatic()) {
 			initializationScope.problemReporter().unexpectedStaticModifierForField(
-				(SourceTypeBinding) binding.declaringClass,
+				(SourceTypeBinding) this.binding.declaringClass,
 				this);
 		}
 
-		if (initialization != null) {
+		if (this.initialization != null) {
 			flowInfo =
-				initialization
+				this.initialization
 					.analyseCode(initializationScope, flowContext, flowInfo)
 					.unconditionalInits();
-			flowInfo.markAsDefinitelyAssigned(binding);
+			flowInfo.markAsDefinitelyAssigned(this.binding);
 		}
 		return flowInfo;
 	}
@@ -92,25 +92,25 @@
 	 */
 	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
 
-		if ((bits & IsReachableMASK) == 0) {
+		if ((this.bits & IsReachableMASK) == 0) {
 			return;
 		}
 		// do not generate initialization code if final and static (constant is then
 		// recorded inside the field itself).
 		int pc = codeStream.position;
 		boolean isStatic;
-		if (initialization != null
-			&& !((isStatic = binding.isStatic()) && binding.constant != NotAConstant)) {
+		if (this.initialization != null
+			&& !((isStatic = this.binding.isStatic()) && this.binding.constant != NotAConstant)) {
 			// non-static field, need receiver
 			if (!isStatic)
 				codeStream.aload_0();
 			// generate initialization value
-			initialization.generateCode(currentScope, codeStream, true);
+			this.initialization.generateCode(currentScope, codeStream, true);
 			// store into field
 			if (isStatic) {
-				codeStream.putstatic(binding);
+				codeStream.putstatic(this.binding);
 			} else {
-				codeStream.putfield(binding);
+				codeStream.putfield(this.binding);
 			}
 		}
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
@@ -118,7 +118,7 @@
 
 	public TypeBinding getTypeBinding(Scope scope) {
 
-		return type.getTypeBinding(scope);
+		return this.type.getTypeBinding(scope);
 	}
 
 	public boolean isField() {
@@ -128,14 +128,9 @@
 
 	public boolean isStatic() {
 
-		if (binding != null)
-			return binding.isStatic();
-		return (modifiers & AccStatic) != 0;
-	}
-
-	public String name() {
-
-		return String.valueOf(name);
+		if (this.binding != null)
+			return this.binding.isStatic();
+		return (this.modifiers & AccStatic) != 0;
 	}
 
 	public void resolve(MethodScope initializationScope) {
@@ -145,36 +140,59 @@
 		// existence is not at all the same. See comment for the second one.
 
 		//--------------------------------------------------------
-		if (!this.hasBeenResolved && binding != null && this.binding.isValidBinding()) {
+		if (!this.hasBeenResolved && this.binding != null && this.binding.isValidBinding()) {
 
 			this.hasBeenResolved = true;
 
-			if (isTypeUseDeprecated(this.binding.type, initializationScope))
-				initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
-
+			// check if field is hiding some variable - issue is that field binding already got inserted in scope
+			ClassScope classScope = initializationScope.enclosingClassScope();
+			if (classScope != null) {
+				SourceTypeBinding declaringType = classScope.enclosingSourceType();
+				boolean checkLocal = true;
+				if (declaringType.superclass != null) {
+					Binding existingVariable = classScope.findField(declaringType.superclass, this.name, this, true /*resolve*/);
+					if (existingVariable != null && existingVariable.isValidBinding()) {
+						initializationScope.problemReporter().fieldHiding(this, existingVariable);
+						checkLocal = false; // already found a matching field
+					}
+				}
+				if (checkLocal) {
+					Scope outerScope = classScope.parent;
+					Binding existingVariable = outerScope.getBinding(this.name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+					if (existingVariable != null && existingVariable.isValidBinding()){
+						initializationScope.problemReporter().fieldHiding(this, existingVariable);
+					}
+				}
+			}
+			
 			this.type.resolvedType = this.binding.type; // update binding for type reference
 
-			// the resolution of the initialization hasn't been done
-			if (this.initialization == null) {
-				this.binding.constant = Constant.NotAConstant;
-			} else {
-				int previous = initializationScope.fieldDeclarationIndex;
-				try {
-					initializationScope.fieldDeclarationIndex = this.binding.id;
+			FieldBinding previousField = initializationScope.initializedField;
+			int previousFieldID = initializationScope.lastVisibleFieldID;
+			try {
+				initializationScope.initializedField = this.binding;
+				initializationScope.lastVisibleFieldID = this.binding.id;
 
+				if (isTypeUseDeprecated(this.binding.type, initializationScope)) {
+					initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
+				}
+				// the resolution of the initialization hasn't been done
+				if (this.initialization == null) {
+					this.binding.constant = Constant.NotAConstant;
+				} else {
 					// break dead-lock cycles by forcing constant to NotAConstant
 					this.binding.constant = Constant.NotAConstant;
 					
 					TypeBinding typeBinding = this.binding.type;
 					TypeBinding initializationTypeBinding;
 					
-					if (initialization instanceof ArrayInitializer) {
+					if (this.initialization instanceof ArrayInitializer) {
 
 						if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
 							((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
 							this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
 						}
-					} else if ((initializationTypeBinding = initialization.resolveType(initializationScope)) != null) {
+					} else if ((initializationTypeBinding = this.initialization.resolveType(initializationScope)) != null) {
 
 						if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
 							|| (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
@@ -195,21 +213,33 @@
 					} else {
 						this.binding.constant = NotAConstant;
 					}
-				} finally {
-					initializationScope.fieldDeclarationIndex = previous;
-					if (this.binding.constant == null)
-						this.binding.constant = Constant.NotAConstant;
 				}
+				// Resolve Javadoc comment if one is present
+				if (this.javadoc != null) {
+					/*
+					if (classScope != null) {
+						this.javadoc.resolve(classScope);
+					}
+					*/
+					this.javadoc.resolve(initializationScope);
+				} else if (this.binding != null && this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
+					initializationScope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
+				}
+			} finally {
+				initializationScope.initializedField = previousField;
+				initializationScope.lastVisibleFieldID = previousFieldID;
+				if (this.binding.constant == null)
+					this.binding.constant = Constant.NotAConstant;
 			}
 		}
 	}
 
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, MethodScope scope) {
+	public void traverse(ASTVisitor visitor, MethodScope scope) {
 
 		if (visitor.visit(this, scope)) {
-			type.traverse(visitor, scope);
-			if (initialization != null)
-				initialization.traverse(visitor, scope);
+			this.type.traverse(visitor, scope);
+			if (this.initialization != null)
+				this.initialization.traverse(visitor, scope);
 		}
 		visitor.endVisit(this, scope);
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
index e499034..adb2d40 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
@@ -10,8 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -52,7 +53,7 @@
 				currentScope.problemReporter().uninitializedBlankFinalField(binding, this);
 				// we could improve error msg here telling "cannot use compound assignment on final blank field"
 			}
-			manageSyntheticReadAccessIfNecessary(currentScope);
+			manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
 		}
 		flowInfo =
 			receiver
@@ -65,7 +66,7 @@
 					.analyseCode(currentScope, flowContext, flowInfo)
 					.unconditionalInits();
 		}
-		manageSyntheticWriteAccessIfNecessary(currentScope);
+		manageSyntheticWriteAccessIfNecessary(currentScope, flowInfo);
 
 		// check if assigning a final field 
 		if (binding.isFinal()) {
@@ -81,7 +82,7 @@
 						binding,
 						this);
 				} else {
-					flowContext.recordSettingFinal(binding, this);
+					flowContext.recordSettingFinal(binding, this, flowInfo);
 				}
 				flowInfo.markAsDefinitelyAssigned(binding);
 			} else {
@@ -108,7 +109,7 @@
 
 		receiver.analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic());
 		if (valueRequired) {
-			manageSyntheticReadAccessIfNecessary(currentScope);
+			manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
 		}
 		return flowInfo;
 	}
@@ -360,8 +361,9 @@
 	/*
 	 * No need to emulate access to protected fields since not implicitly accessed
 	 */
-	public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope) {
+	public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
+		if (!flowInfo.isReachable()) return;
 		if (binding.isPrivate()) {
 			if ((currentScope.enclosingSourceType() != binding.declaringClass)
 				&& (binding.constant == NotAConstant)) {
@@ -403,7 +405,7 @@
 			&& !this.receiverType.isArrayType()
 			&& binding.declaringClass != null // array.length
 			&& binding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
+			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
 				&& binding.declaringClass.id != T_Object)
 			//no change for Object fields (in case there was)
 				|| !binding.declaringClass.canBeSeenBy(currentScope))) {
@@ -417,8 +419,9 @@
 	/*
 	 * No need to emulate access to protected fields since not implicitly accessed
 	 */
-	public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope) {
+	public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
+		if (!flowInfo.isReachable()) return;
 		if (binding.isPrivate()) {
 			if (currentScope.enclosingSourceType() != binding.declaringClass) {
 				syntheticWriteAccessor =
@@ -460,7 +463,7 @@
 			&& !this.receiverType.isArrayType()
 			&& binding.declaringClass != null // array.length
 			&& binding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
+			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
 				&& binding.declaringClass.id != T_Object)
 			//no change for Object fields (in case there was)
 				|| !binding.declaringClass.canBeSeenBy(currentScope))) {
@@ -471,30 +474,45 @@
 		}
 	}
 
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		return receiver.printExpression(0, output).append('.').append(token);
+	}
+	
 	public TypeBinding resolveType(BlockScope scope) {
 
 		// Answer the signature type of the field.
 		// constants are propaged when the field is final
 		// and initialized with a (compile time) constant 
 
-		// regular receiver reference 
+		//always ignore receiver cast, since may affect constant pool reference
+		boolean receiverCast = false;
+		if (this.receiver instanceof CastExpression) {
+			this.receiver.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+			receiverCast = true;
+		}
 		this.receiverType = receiver.resolveType(scope);
 		if (this.receiverType == null) {
 			constant = NotAConstant;
 			return null;
 		}
+		if (receiverCast) {
+			 // due to change of declaring class with receiver type, only identity cast should be notified
+			if (((CastExpression)this.receiver).expression.resolvedType == this.receiverType) { 
+						scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);		
+			}
+		}		
 		// the case receiverType.isArrayType and token = 'length' is handled by the scope API
-		this.codegenBinding =
-			this.binding = scope.getField(this.receiverType, token, this);
+		this.codegenBinding = this.binding = scope.getField(this.receiverType, token, this);
 		if (!binding.isValidBinding()) {
 			constant = NotAConstant;
 			scope.problemReporter().invalidField(this, this.receiverType);
 			return null;
 		}
 
-		if (isFieldUseDeprecated(binding, scope))
+		if (isFieldUseDeprecated(binding, scope, (this.bits & IsStrictlyAssignedMASK) !=0)) {
 			scope.problemReporter().deprecatedField(binding, this);
-
+		}
 		boolean isImplicitThisRcv = receiver.isImplicitThis();
 		constant = FieldReference.getConstantFor(binding, this, isImplicitThisRcv, scope);
 		if (!isImplicitThisRcv) {
@@ -506,7 +524,10 @@
 					|| receiver.isSuper()
 					|| (receiver instanceof NameReference 
 						&& (((NameReference) receiver).bits & BindingIds.TYPE) != 0))) {
-				scope.problemReporter().unnecessaryReceiverForStaticField(this, binding);
+				scope.problemReporter().nonStaticAccessToStaticField(this, binding);
+			}
+			if (!isImplicitThisRcv && binding.declaringClass != receiverType) {
+				scope.problemReporter().indirectAccessToStaticField(this, binding);
 			}
 		}
 		return this.resolvedType = binding.type;
@@ -528,13 +549,7 @@
 		// ignored
 	}
 
-	public String toStringExpression() {
-
-		return receiver.toString() + "." //$NON-NLS-1$
-		+ new String(token);
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
 			receiver.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java
index fcae6d1..e92f51d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -51,8 +51,6 @@
 					break label; //exposant are valid !....
 				default :
 					return; //error
-
-
 			}
 		}
 	}
@@ -77,7 +75,7 @@
 public TypeBinding literalType(BlockScope scope) {
 	return FloatBinding;
 }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+public void traverse(ASTVisitor visitor, BlockScope blockScope) {
 	visitor.visit(this, blockScope);
 	visitor.endVisit(this, blockScope);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
index 52f01fd..5551cdf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
@@ -10,10 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
@@ -51,6 +51,8 @@
 		this.condition = condition;
 		this.increments = increments;
 		this.action = action;
+		// remember useful empty statement
+		if (action instanceof EmptyStatement) action.bits |= IsUsefulEmptyStatementMASK;
 		this.neededScope = neededScope;
 	}
 
@@ -64,9 +66,8 @@
 
 		// process the initializations
 		if (initializations != null) {
-			int count = initializations.length, i = 0;
-			while (i < count) {
-				flowInfo = initializations[i++].analyseCode(scope, flowContext, flowInfo);
+			for (int i = 0, count = initializations.length; i < count; i++) {
+				flowInfo = initializations[i].analyseCode(scope, flowContext, flowInfo);
 			}
 		}
 		preCondInitStateIndex =
@@ -97,7 +98,7 @@
 		LoopingFlowContext loopingContext;
 		FlowInfo actionInfo;
 		if (action == null 
-			|| (action.isEmptyBlock() && currentScope.environment().options.complianceLevel <= CompilerOptions.JDK1_3)) {
+			|| (action.isEmptyBlock() && currentScope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3)) {
 			if (condLoopContext != null)
 				condLoopContext.complainOnFinalAssignmentsInLoop(scope, flowInfo);
 			if (isConditionTrue) {
@@ -125,7 +126,7 @@
 						actionInfo.setReachMode(FlowInfo.UNREACHABLE);
 					}
 				}
-			if (!actionInfo.complainIfUnreachable(action, scope, false)) {
+			if (!this.action.complainIfUnreachable(actionInfo, scope, false)) {
 				actionInfo = action.analyseCode(scope, loopingContext, actionInfo);
 			}
 
@@ -135,39 +136,28 @@
 			} else {
 				if (condLoopContext != null)
 					condLoopContext.complainOnFinalAssignmentsInLoop(scope, flowInfo);
+				actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
 				loopingContext.complainOnFinalAssignmentsInLoop(scope, actionInfo);
-				actionInfo =
-					actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
-				// for increments
 			}
 		}
+		// for increments
 		if ((continueLabel != null) && (increments != null)) {
 			LoopingFlowContext loopContext =
 				new LoopingFlowContext(flowContext, this, null, null, scope);
-			int i = 0, count = increments.length;
-			while (i < count)
-				actionInfo = increments[i++].analyseCode(scope, loopContext, actionInfo);
+			for (int i = 0, count = increments.length; i < count; i++) {
+				actionInfo = increments[i].analyseCode(scope, loopContext, actionInfo);
+			}
 			loopContext.complainOnFinalAssignmentsInLoop(scope, actionInfo);
 		}
 
-		// infinite loop
-		FlowInfo mergedInfo;
-		if (isConditionOptimizedTrue) {
-			mergedInitStateIndex =
-				currentScope.methodScope().recordInitializationStates(
-					mergedInfo = loopingContext.initsOnBreak);
-			return mergedInfo;
-		}
-
-		//end of loop: either condition false or break
-		mergedInfo =
-			flowInfo.initsWhenFalse().unconditionalInits().mergedWith(
-				loopingContext.initsOnBreak.unconditionalInits());
-		if (isConditionOptimizedTrue && continueLabel == null){
-			mergedInfo.setReachMode(FlowInfo.UNREACHABLE);
-		}
-		mergedInitStateIndex =
-			currentScope.methodScope().recordInitializationStates(mergedInfo);
+		//end of loop
+		FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
+				loopingContext.initsOnBreak, 
+				isConditionOptimizedTrue, 
+				flowInfo.initsWhenFalse(), 
+				isConditionOptimizedFalse, 
+				!isConditionTrue /*for(;;){}while(true); unreachable(); */);
+		mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
 		return mergedInfo;
 	}
 
@@ -259,6 +249,39 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+
+		printIndent(tab, output).append("for ("); //$NON-NLS-1$
+		//inits
+		if (initializations != null) {
+			for (int i = 0; i < initializations.length; i++) {
+				//nice only with expressions
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				initializations[i].print(0, output);
+			}
+		}
+		output.append("; "); //$NON-NLS-1$
+		//cond
+		if (condition != null) condition.printExpression(0, output);
+		output.append("; "); //$NON-NLS-1$
+		//updates
+		if (increments != null) {
+			for (int i = 0; i < increments.length; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				increments[i].print(0, output);
+			}
+		}
+		output.append(") "); //$NON-NLS-1$
+		//block
+		if (action == null)
+			output.append(';');
+		else {
+			output.append('\n');
+			action.printStatement(tab + 1, output); //$NON-NLS-1$
+		}
+		return output.append(';');
+	}
+
 	public void resetStateForCodeGeneration() {
 		if (this.breakLabel != null) {
 			this.breakLabel.resetStateForCodeGeneration();
@@ -285,46 +308,9 @@
 		if (action != null)
 			action.resolve(scope);
 	}
-
-	public String toString(int tab) {
-
-		String s = tabString(tab) + "for ("; //$NON-NLS-1$
-		if (!neededScope)
-			s = s + " //--NO upperscope scope needed\n" + tabString(tab) + "     ";	//$NON-NLS-2$ //$NON-NLS-1$
-		//inits
-		if (initializations != null) {
-			for (int i = 0; i < initializations.length; i++) {
-				//nice only with expressions
-				s = s + initializations[i].toString(0);
-				if (i != (initializations.length - 1))
-					s = s + " , "; //$NON-NLS-1$
-			}
-		}; 
-		s = s + "; "; //$NON-NLS-1$
-		//cond
-		if (condition != null)
-			s = s + condition.toStringExpression();
-		s = s + "; "; //$NON-NLS-1$
-		//updates
-		if (increments != null) {
-			for (int i = 0; i < increments.length; i++) {
-				//nice only with expressions
-				s = s + increments[i].toString(0);
-				if (i != (increments.length - 1))
-					s = s + " , "; //$NON-NLS-1$
-			}
-		}; 
-		s = s + ") "; //$NON-NLS-1$
-		//block
-		if (action == null)
-			s = s + "{}"; //$NON-NLS-1$
-		else
-			s = s + "\n" + action.toString(tab + 1); //$NON-NLS-1$
-		return s;
-	}
 	
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
index 859548e..09e6769 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -40,6 +40,8 @@
 
 		this.condition = condition;
 		this.thenStatement = thenStatement;
+		// remember useful empty statement
+		if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatementMASK;
 		sourceStart = s;
 		sourceEnd = e;
 	}
@@ -53,6 +55,8 @@
 
 		this.condition = condition;
 		this.thenStatement = thenStatement;
+		// remember useful empty statement
+		if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatementMASK;
 		this.elseStatement = elseStatement;
 		sourceEnd = e;
 		sourceStart = s;
@@ -79,13 +83,13 @@
 			// Save info for code gen
 			thenInitStateIndex =
 				currentScope.methodScope().recordInitializationStates(thenFlowInfo);
-			if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope, false)) {
+			if (!thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, false)) {
 				thenFlowInfo =
 					thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
 			}
-		};
-		// optimizing the jump around the ELSE part
-		this.thenExit = !thenFlowInfo.isReachable();
+		}
+		// code gen: optimizing the jump around the ELSE part
+		this.thenExit =  !thenFlowInfo.isReachable();
 
 		// process the ELSE part
 		FlowInfo elseFlowInfo = flowInfo.initsWhenFalse().copy();
@@ -96,53 +100,20 @@
 			// Save info for code gen
 			elseInitStateIndex =
 				currentScope.methodScope().recordInitializationStates(elseFlowInfo);
-			if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope, false)) {
+			if (!elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, false)) {
 				elseFlowInfo =
 					elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
 			}
 		}
 
-		boolean elseExit = !elseFlowInfo.isReachable();
-		
 		// merge THEN & ELSE initializations
-		FlowInfo mergedInfo;
-//		if (isConditionOptimizedTrue){
-//			if (!this.thenExit) {
-//				mergedInfo = thenFlowInfo;
-//			} else {
-//				mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
-//			}
-//
-//		} else if (isConditionOptimizedFalse) {
-//			if (!elseExit) {
-//				mergedInfo = elseFlowInfo;
-//			} else {
-//				mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
-//			}
-//
-//		} else {
-//			mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
-//		}
-		if (isConditionOptimizedTrue){
-			if (!this.thenExit) {
-				mergedInfo = thenFlowInfo.addPotentialInitializationsFrom(elseFlowInfo);
-			} else {
-				mergedInfo = elseFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
-			}
-
-		} else if (isConditionOptimizedFalse) {
-			if (!elseExit) {
-				mergedInfo = elseFlowInfo.addPotentialInitializationsFrom(thenFlowInfo);
-			} else {
-				mergedInfo = thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE);
-			}
-
-		} else {
-			mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
-		}
-
-		mergedInitStateIndex =
-			currentScope.methodScope().recordInitializationStates(mergedInfo);
+		FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
+				thenFlowInfo, 
+				isConditionOptimizedTrue, 
+				elseFlowInfo, 
+				isConditionOptimizedFalse,
+				true /*if(true){ return; }  fake-reachable(); */);
+		mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
 		return mergedInfo;
 	}
 
@@ -235,6 +206,20 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+
+		printIndent(indent, output).append("if ("); //$NON-NLS-1$
+		condition.printExpression(0, output).append(")\n");	//$NON-NLS-1$ 
+		thenStatement.printStatement(indent + 2, output);
+		if (elseStatement != null) {
+			output.append('\n');
+			printIndent(indent, output);
+			output.append("else\n"); //$NON-NLS-1$
+			elseStatement.printStatement(indent + 2, output);
+		}
+		return output;
+	}
+
 	public void resolve(BlockScope scope) {
 
 		TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
@@ -245,19 +230,8 @@
 			elseStatement.resolve(scope);
 	}
 
-	public String toString(int tab) {
-
-		String inFront, s = tabString(tab);
-		inFront = s;
-		s = s + "if (" + condition.toStringExpression() + ") \n";	//$NON-NLS-1$ //$NON-NLS-2$
-		s = s + thenStatement.toString(tab + 2) + ";"; //$NON-NLS-1$
-		if (elseStatement != null)
-			s = s + "\n" + inFront + "else\n" + elseStatement.toString(tab + 2) + ";"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
-		return s;
-	}
-
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java
index 47aa3e1..3e18e30 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ImportReference.java
@@ -10,52 +10,63 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
-public class ImportReference extends AstNode {
-	
+public class ImportReference extends ASTNode {
+
 	public char[][] tokens;
 	public long[] sourcePositions; //each entry is using the code : (start<<32) + end
 	public boolean onDemand = true; //most of the time
-	public int declarationEnd;// doesn't include an potential trailing comment
+	public int declarationEnd; // doesn't include an potential trailing comment
 	public int declarationSourceStart;
 	public int declarationSourceEnd;
 	public boolean used;
+	public int modifiers; // 1.5 addition for static imports
 
-public ImportReference(char[][] sources , long[] poss , boolean d) {
-	tokens = sources ;
-	sourcePositions = poss ;
-	onDemand = d;
-	sourceEnd = (int)(sourcePositions[sourcePositions.length-1] & 0x00000000FFFFFFFF);
-	sourceStart = (int)(sourcePositions[0]>>>32) ;
-}
-/**
- * @return char[][]
- */
-public char[][] getImportName() {
-	return tokens;
-}
-public String toString(int tab ){
+	public ImportReference(
+			char[][] tokens,
+			long[] sourcePositions,
+			boolean onDemand,
+			int modifiers) {
 
-	return toString(tab,true);
-}
-public String toString(int tab, boolean withOnDemand) {
-	/* when withOnDemand is false, only the name is printed */
-	StringBuffer buffer = new StringBuffer();
-	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		if (i < (tokens.length - 1)) {
-			buffer.append("."); //$NON-NLS-1$
+		this.tokens = tokens;
+		this.sourcePositions = sourcePositions;
+		this.onDemand = onDemand;
+		this.sourceEnd = (int) (sourcePositions[sourcePositions.length-1] & 0x00000000FFFFFFFF);
+		this.sourceStart = (int) (sourcePositions[0] >>> 32);
+		this.modifiers = modifiers;
+	}
+
+	/**
+	 * @return char[][]
+	 */
+	public char[][] getImportName() {
+
+		return tokens;
+	}
+
+	public StringBuffer print(int indent, StringBuffer output) {
+
+		return print(indent, output, true);
+	}
+
+	public StringBuffer print(int tab, StringBuffer output, boolean withOnDemand) {
+
+		/* when withOnDemand is false, only the name is printed */
+		for (int i = 0; i < tokens.length; i++) {
+			if (i > 0) output.append('.');
+			output.append(tokens[i]);
 		}
+		if (withOnDemand && onDemand) {
+			output.append(".*"); //$NON-NLS-1$
+		}
+		return output;
 	}
-	if (withOnDemand && onDemand) {
-		buffer.append(".*"); //$NON-NLS-1$
+
+	public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
 	}
-	return buffer.toString();
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, CompilationUnitScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java
index c196460..f7490ee 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -19,13 +19,17 @@
 public class Initializer extends FieldDeclaration {
 	
 	public Block block;
-	public int lastFieldID;
+	public int lastVisibleFieldID;
 	public int bodyStart;
+	public int bodyEnd;
+	
+	public boolean errorInSignature = false; 
+	
 	public Initializer(Block block, int modifiers) {
 		this.block = block;
 		this.modifiers = modifiers;
 
-		declarationSourceStart = sourceStart = bodyStart = block.sourceStart;
+		declarationSourceStart = sourceStart = block.sourceStart;
 	}
 
 	public FlowInfo analyseCode(
@@ -65,18 +69,33 @@
 
 	public void parseStatements(
 		Parser parser,
-		TypeDeclaration type,
+		TypeDeclaration typeDeclaration,
 		CompilationUnitDeclaration unit) {
 
 		//fill up the method body with statement
-		parser.parse(this, type, unit);
+		parser.parse(this, typeDeclaration, unit);
 	}
 
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+
+		if (modifiers != 0) {
+			printIndent(indent, output);
+			printModifiers(modifiers, output).append("{\n"); //$NON-NLS-1$
+			block.printBody(indent, output);
+			printIndent(indent, output).append('}'); 
+			return output;
+		} else {
+			return block.printStatement(indent, output);
+		}
+	}
+	
 	public void resolve(MethodScope scope) {
 
-		int previous = scope.fieldDeclarationIndex;
+	    FieldBinding previousField = scope.initializedField;
+		int previousFieldID = scope.lastVisibleFieldID;
 		try {
-			scope.fieldDeclarationIndex = lastFieldID;
+		    scope.initializedField = null;
+			scope.lastVisibleFieldID = lastVisibleFieldID;
 			if (isStatic()) {
 				ReferenceBinding declaringType = scope.enclosingSourceType();
 				if (declaringType.isNestedType() && !declaringType.isStatic())
@@ -86,27 +105,12 @@
 			}
 			block.resolve(scope);
 		} finally {
-			scope.fieldDeclarationIndex = previous;
+		    scope.initializedField = previousField;
+			scope.lastVisibleFieldID = previousFieldID;
 		}
 	}
 
-	public String toString(int tab) {
-
-		if (modifiers != 0) {
-			StringBuffer buffer = new StringBuffer();
-			buffer.append(tabString(tab));
-			buffer.append(modifiersString(modifiers));
-			buffer.append("{\n"); //$NON-NLS-1$
-			buffer.append(block.toStringStatements(tab));
-			buffer.append(tabString(tab));
-			buffer.append("}"); //$NON-NLS-1$
-			return buffer.toString();
-		} else {
-			return block.toString(tab);
-		}
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, MethodScope scope) {
+	public void traverse(ASTVisitor visitor, MethodScope scope) {
 
 		if (visitor.visit(this, scope)) {
 			block.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InnerTypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InnerTypeDeclaration.java
deleted file mode 100644
index 12e1543..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InnerTypeDeclaration.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.compiler.ast;
-
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-
-public class InnerTypeDeclaration extends TypeDeclaration {
-	
-	public InnerTypeDeclaration(CompilationResult compilationResult){
-		super(compilationResult);
-	}	
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index 3cdd78f..bfaf37b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -10,7 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -41,159 +42,134 @@
 			.analyseCode(currentScope, flowContext, flowInfo)
 			.unconditionalInits();
 	}
-
-	public final boolean areTypesCastCompatible(
+	/**
+	 * Returns false if the instanceof unnecessary
+	 */
+	public final boolean checkCastTypesCompatibility(
 		BlockScope scope,
 		TypeBinding castType,
 		TypeBinding expressionType) {
-
-		//	see specifications p.68
-		//A more cpmplete version of this method is provided on
+	
+		//A more complete version of this method is provided on
 		//CastExpression (it deals with constant and need runtime checkcast)
 
-		if (castType == expressionType) return true;
+		if (castType == expressionType) return false;
 		
-		//by grammatical construction, the first test is ALWAYS false
-		//if (castTb.isBaseType())
-		//{	if (expressionTb.isBaseType())
-		//	{	if (expression.isConstantValueOfTypeAssignableToType(expressionTb,castTb))
-		//		{	return true;}
-		//		else
-		//		{	if (expressionTb==castTb)
-		//			{	return true;}
-		//			else 
-		//			{	if (scope.areTypesCompatible(expressionTb,castTb))
-		//				{	return true; }
-		//				
-		//				if (BaseTypeBinding.isNarrowing(castTb.id,expressionTb.id))
-		//				{	return true;}
-		//				return false;}}}
-		//	else
-		//	{	return false; }}
-		//else
-		{ //-------------checkcast to something which is NOT a basetype----------------------------------	
+		//by grammatical construction, the base type check is not necessary
 
-			//null is compatible with every thing .... 
-			if (NullBinding == expressionType) {
-				return true;
-			}
-			if (expressionType.isArrayType()) {
-				if (castType.isArrayType()) {
-					//------- (castTb.isArray) expressionTb.isArray -----------
-					TypeBinding expressionEltTb = ((ArrayBinding) expressionType).elementsType(scope);
-					if (expressionEltTb.isBaseType())
-						// <---stop the recursion------- 
-						return ((ArrayBinding) castType).elementsType(scope) == expressionEltTb;
-					//recursivly on the elts...
-					return areTypesCastCompatible(
-						scope,
-						((ArrayBinding) castType).elementsType(scope),
-						expressionEltTb);
-				}
-				if (castType.isClass()) {
-					//------(castTb.isClass) expressionTb.isArray ---------------	
-					if (scope.isJavaLangObject(castType))
-						return true;
-					return false;
-				}
-				if (castType.isInterface()) {
-					//------- (castTb.isInterface) expressionTb.isArray -----------
-					if (scope.isJavaLangCloneable(castType) || scope.isJavaIoSerializable(castType)) {
-						return true;
-					}
-					return false;
-				}
-
-				return false;
-			}
-			if (expressionType.isBaseType()) {
-				return false;
-			}
-			if (expressionType.isClass()) {
-				if (castType.isArrayType()) {
-					// ---- (castTb.isArray) expressionTb.isClass -------
-					if (scope.isJavaLangObject(expressionType)) {
-						return true;
-					} else {
-						return false;
-					}
-				}
-				if (castType.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------ 
-					if (expressionType.isCompatibleWith(castType))
-						return true;
-					else {
-						if (castType.isCompatibleWith(expressionType)) {
-							return true;
-						}
-						return false;
-					}
-				}
-				if (castType.isInterface()) {
-					// ----- (castTb.isInterface) expressionTb.isClass -------  
-					if (((ReferenceBinding) expressionType).isFinal()) {
-						//no subclass for expressionTb, thus compile-time check is valid
-						if (expressionType.isCompatibleWith(castType))
-							return true;
-						return false;
-					} else {
-						return true;
-					}
-				}
-
-				return false;
-			}
-			if (expressionType.isInterface()) {
-				if (castType.isArrayType()) {
-					// ----- (castTb.isArray) expressionTb.isInterface ------
-					if (scope.isJavaLangCloneable(expressionType)
-						|| scope.isJavaIoSerializable(expressionType))
-						//potential runtime error
-						{
-						return true;
-					}
-					return false;
-				}
-				if (castType.isClass()) {
-					// ----- (castTb.isClass) expressionTb.isInterface --------
-					if (scope.isJavaLangObject(castType))
-						return true;
-					if (((ReferenceBinding) castType).isFinal()) {
-						//no subclass for castTb, thus compile-time check is valid
-						if (castType.isCompatibleWith(expressionType)) {
-							return true;
-						}
-						return false;
-					}
-					return true;
-				}
-				if (castType.isInterface()) {
-					// ----- (castTb.isInterface) expressionTb.isInterface -------
-					if ((Scope.compareTypes(castType, expressionType) == NotRelated)) {
-						MethodBinding[] castTbMethods = ((ReferenceBinding) castType).methods();
-						int castTbMethodsLength = castTbMethods.length;
-						MethodBinding[] expressionTbMethods =
-							((ReferenceBinding) expressionType).methods();
-						int expressionTbMethodsLength = expressionTbMethods.length;
-						for (int i = 0; i < castTbMethodsLength; i++) {
-							for (int j = 0; j < expressionTbMethodsLength; j++) {
-								if (castTbMethods[i].selector == expressionTbMethods[j].selector) {
-									if (castTbMethods[i].returnType != expressionTbMethods[j].returnType) {
-										if (castTbMethods[i].areParametersEqual(expressionTbMethods[j])) {
-											return false;
-										}
-									}
-								}
-							}
-						}
-					}
-					return true;
-				}
-
-				return false;
-			} 
-
-			return false;
+		if (castType == null || expressionType == null) return true;
+	
+		//-----------cast to something which is NOT a base type--------------------------	
+		if (expressionType == NullBinding) {
+			//	if (castType.isArrayType()){ // 26903 - need checkcast when casting null to array type
+			//		needRuntimeCheckcast = true;
+			//	}
+			return false; //null is compatible with every thing
 		}
+		if (expressionType.isBaseType()) {
+			scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
+			return true;
+		}
+	
+		if (expressionType.isArrayType()) {
+			if (castType == expressionType) return false; // identity conversion
+	
+			if (castType.isArrayType()) {
+				//------- (castType.isArray) expressionType.isArray -----------
+				TypeBinding exprElementType = ((ArrayBinding) expressionType).elementsType(scope);
+				if (exprElementType.isBaseType()) {
+					// <---stop the recursion------- 
+					if (((ArrayBinding) castType).elementsType(scope) != exprElementType)
+						scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
+					return true;
+				}
+				// recursively on the elements...
+				return checkCastTypesCompatibility(
+					scope,
+					((ArrayBinding) castType).elementsType(scope),
+					exprElementType);
+			} else if (
+				castType.isClass()) {
+				//------(castType.isClass) expressionType.isArray ---------------	
+				if (scope.isJavaLangObject(castType)) {
+					return false;
+				}
+			} else { //------- (castType.isInterface) expressionType.isArray -----------
+				if (scope.isJavaLangCloneable(castType) || scope.isJavaIoSerializable(castType)) {
+					return true;
+				}
+			}
+			scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
+			return true;
+		}
+	
+		if (expressionType.isClass()) {
+			if (castType.isArrayType()) {
+				// ---- (castType.isArray) expressionType.isClass -------
+				if (scope.isJavaLangObject(expressionType)) { // potential runtime error
+					return true;
+				}
+			} else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isClass ------
+				if (expressionType.isCompatibleWith(castType)){ // no runtime error
+					return false;
+				}
+				if (castType.isCompatibleWith(expressionType)) {
+					// potential runtime  error
+					return true;
+				}
+			} else { // ----- (castType.isInterface) expressionType.isClass -------  
+				if (((ReferenceBinding) expressionType).isFinal()) {
+					// no subclass for expressionType, thus compile-time check is valid
+					if (expressionType.isCompatibleWith(castType)) 
+						return false;
+				} else { // a subclass may implement the interface ==> no check at compile time
+					return true;
+				}
+			}
+			scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
+			return true;
+		}
+	
+		//	if (expressionType.isInterface()) { cannot be anything else
+		if (castType.isArrayType()) {
+			// ----- (castType.isArray) expressionType.isInterface ------
+			if (!(scope.isJavaLangCloneable(expressionType)
+					|| scope.isJavaIoSerializable(expressionType))) {// potential runtime error
+				scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
+			}
+			return true;
+		} else if (castType.isClass()) { // ----- (castType.isClass) expressionType.isInterface --------
+			if (scope.isJavaLangObject(castType)) { // no runtime error
+				return false;
+			}
+			if (((ReferenceBinding) castType).isFinal()) {
+				// no subclass for castType, thus compile-time check is valid
+				if (!castType.isCompatibleWith(expressionType)) {
+					// potential runtime error
+					scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
+					return true;
+				}
+			}
+		} else { // ----- (castType.isInterface) expressionType.isInterface -------
+			if (castType == expressionType) { 
+				return false; // identity conversion
+			}
+			if (Scope.compareTypes(castType, expressionType) == NotRelated) {
+				MethodBinding[] castTypeMethods = ((ReferenceBinding) castType).methods();
+				MethodBinding[] expressionTypeMethods =
+					((ReferenceBinding) expressionType).methods();
+				int exprMethodsLength = expressionTypeMethods.length;
+				for (int i = 0, castMethodsLength = castTypeMethods.length; i < castMethodsLength; i++)
+					for (int j = 0; j < exprMethodsLength; j++) {
+						if ((castTypeMethods[i].returnType != expressionTypeMethods[j].returnType)
+								&& CharOperation.equals(castTypeMethods[i].selector, expressionTypeMethods[j].selector)
+								&& castTypeMethods[i].areParametersEqual(expressionTypeMethods[j])) {
+							scope.problemReporter().notCompatibleTypesError(this, expressionType, castType);
+						}
+					}
+			}
+		}
+		return true;
 	}
 	/**
 	 * Code generation for instanceOfExpression
@@ -215,6 +191,12 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
+	public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+
+		expression.printExpression(indent, output).append(" instanceof "); //$NON-NLS-1$
+		return type.print(0, output);
+	}
+	
 	public TypeBinding resolveType(BlockScope scope) {
 
 		constant = NotAConstant;
@@ -223,21 +205,14 @@
 		if (expressionType == null || checkType == null)
 			return null;
 
-		if (!areTypesCastCompatible(scope, checkType, expressionType)) {
-			scope.problemReporter().notCompatibleTypesError(this, expressionType, checkType);
-			return null;
+		boolean necessary = checkCastTypesCompatibility(scope, checkType, expressionType);
+		if (!necessary) {
+			scope.problemReporter().unnecessaryInstanceof(this, checkType);
 		}
-		this.resolvedType = BooleanBinding;
-		return BooleanBinding;
+		return this.resolvedType = BooleanBinding;
 	}
 
-	public String toStringExpressionNoParenthesis() {
-
-		return expression.toStringExpression() + " instanceof " + //$NON-NLS-1$
-		type.toString(0);
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
 			expression.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
index 035d067..3d4277b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -63,7 +63,7 @@
 		while (source[j]=='0') 
 		{	j++; //jump over redondant zero
 			if (j == length)
-			{	//watch for 000000000000000000 	:-(
+			{	//watch for 000000000000000000
 				constant = Constant.fromValue(value = (int)computedValue);
 				return ;}}
 		
@@ -134,14 +134,16 @@
 	}
 	return tb;
 }
-public String toStringExpression(){
+public StringBuffer printExpression(int indent, StringBuffer output){
 
-	if (source == null)
+	if (source == null) {
 	/* special optimized IntLiteral that are created by the compiler */
-		return String.valueOf(value);
-		
-	return super.toStringExpression();}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+		return output.append(String.valueOf(value));
+	}
+	return super.printExpression(indent, output);
+}
+	
+public void traverse(ASTVisitor visitor, BlockScope scope) {
 	visitor.visit(this, scope);
 	visitor.endVisit(this, scope);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IteratorForStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IteratorForStatement.java
new file mode 100644
index 0000000..81db8b8
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IteratorForStatement.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+
+public class IteratorForStatement extends Statement {
+
+	public Expression collection;
+	public LocalDeclaration localDeclaration;
+
+	public Statement action;
+
+	// we always need a new scope.
+	public BlockScope scope;
+
+	public IteratorForStatement(
+		LocalDeclaration localDeclaration,
+		Expression collection,
+		Statement action,
+		int start,
+		int end) {
+
+		this.localDeclaration = localDeclaration;
+		this.collection = collection;
+		this.sourceStart = start;
+		this.sourceEnd = end;
+		this.action = action;
+		// remember useful empty statement
+		if (action instanceof EmptyStatement) action.bits |= IsUsefulEmptyStatementMASK;
+	}
+
+	public FlowInfo analyseCode(
+		BlockScope currentScope,
+		FlowContext flowContext,
+		FlowInfo flowInfo) {
+		// TODO to be completed
+		return flowInfo;
+	}
+
+	/**
+	 * For statement code generation
+	 *
+	 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+	 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+	 */
+	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+		// TODO to be completed
+	}
+
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+
+		printIndent(tab, output).append("for ("); //$NON-NLS-1$
+		this.localDeclaration.print(0, output); 
+		output.append(" : ");//$NON-NLS-1$
+		this.collection.print(0, output).append(") "); //$NON-NLS-1$
+		//block
+		if (action == null)
+			output.append(';');
+		else {
+			output.append('\n');
+			action.printStatement(tab + 1, output); //$NON-NLS-1$
+		}
+		return output;
+	}
+
+	public void resetStateForCodeGeneration() {
+		// TODO to be completed
+	}
+
+	public void resolve(BlockScope upperScope) {
+		// TODO to be completed
+	}
+	
+	public void traverse(
+		ASTVisitor visitor,
+		BlockScope blockScope) {
+
+		if (visitor.visit(this, blockScope)) {
+			this.localDeclaration.traverse(visitor, scope);
+			this.collection.traverse(visitor, scope);
+			if (action != null) {
+				action.traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, blockScope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
new file mode 100644
index 0000000..2857936
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
@@ -0,0 +1,356 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * Node representing a structured Javadoc comment
+ */
+public class Javadoc extends ASTNode {
+
+	public JavadocSingleNameReference[] parameters; // @param
+	public TypeReference[] thrownExceptions; // @throws, @exception
+	public JavadocReturnStatement returnStatement; // @return
+	public Expression[] references; // @see
+
+	public Javadoc(int sourceStart, int sourceEnd) {
+		this.sourceStart = sourceStart;
+		this.sourceEnd = sourceEnd;
+	}
+	
+	/*
+	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#print(int, java.lang.StringBuffer)
+	 */
+	public StringBuffer print(int indent, StringBuffer output) {
+		printIndent(indent, output).append("/**\n"); //$NON-NLS-1$
+		if (this.parameters != null) {
+			for (int i = 0, length = this.parameters.length; i < length; i++) {
+				printIndent(indent + 1, output).append(" * @param "); //$NON-NLS-1$		
+				this.parameters[i].print(indent, output).append('\n');
+			}
+		}
+		if (this.returnStatement != null) {
+			printIndent(indent + 1, output).append(" * @return\n"); //$NON-NLS-1$		
+		}
+		if (this.thrownExceptions != null) {
+			for (int i = 0, length = this.thrownExceptions.length; i < length; i++) {
+				printIndent(indent + 1, output).append(" * @throws "); //$NON-NLS-1$		
+				this.thrownExceptions[i].print(indent, output).append('\n');
+			}
+		}
+		if (this.references != null) {
+			for (int i = 0, length = this.references.length; i < length; i++) {
+				printIndent(indent + 1, output).append(" * @see"); //$NON-NLS-1$		
+				this.references[i].print(indent, output).append('\n');
+			}
+		}
+		printIndent(indent, output).append(" */\n"); //$NON-NLS-1$
+		return output;
+	}
+
+	/*
+	 * Resolve type javadoc while a class scope
+	 */
+	public void resolve(ClassScope classScope) {
+		
+
+		// @param tags
+		int paramTagsSize = this.parameters == null ? 0 : this.parameters.length;
+		for (int i = 0; i < paramTagsSize; i++) {
+			JavadocSingleNameReference param = this.parameters[i];
+			classScope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
+		}
+
+		// @return tags
+		if (this.returnStatement != null) {
+			classScope.problemReporter().javadocUnexpectedTag(this.returnStatement.sourceStart, this.returnStatement.sourceEnd);
+		}
+
+		// @throws/@exception tags
+		int throwsTagsNbre = this.thrownExceptions == null ? 0 : this.thrownExceptions.length;
+		for (int i = 0; i < throwsTagsNbre; i++) {
+			TypeReference typeRef = this.thrownExceptions[i];
+			int start, end;
+			if (typeRef instanceof JavadocSingleTypeReference) {
+				JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef;
+				start = singleRef.tagSourceStart;
+				end = singleRef.tagSourceEnd;
+			} else if (typeRef instanceof JavadocQualifiedTypeReference) {
+				JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) typeRef;
+				start = qualifiedRef.tagSourceStart;
+				end = qualifiedRef.tagSourceEnd;
+			} else {
+				start = typeRef.sourceStart;
+				end = typeRef.sourceEnd;
+			}
+			classScope.problemReporter().javadocUnexpectedTag(start, end);
+		}
+
+		// @see tags
+		int seeTagsNbre = this.references == null ? 0 : this.references.length;
+		for (int i = 0; i < seeTagsNbre; i++) {
+			this.references[i].resolveType(classScope);
+		}
+	}
+	
+	/*
+	 * Resolve method javadoc while a method scope
+	 */
+	public void resolve(MethodScope methScope) {
+		
+		// get method declaration
+		AbstractMethodDeclaration methDecl = methScope.referenceMethod();
+		boolean overriding = methDecl == null ? false : (methDecl.binding.modifiers & (AccImplementing+AccOverriding)) != 0;
+
+		// @see tags
+		int seeTagsNbre = this.references == null ? 0 : this.references.length;
+		boolean superRef = false;
+		for (int i = 0; i < seeTagsNbre; i++) {
+			this.references[i].resolveType(methScope);
+			try {
+				// see whether we can have a super reference
+				if ((methDecl.isConstructor() || overriding) && !superRef) {
+					if (this.references[i] instanceof JavadocMessageSend) {
+						JavadocMessageSend messageSend = (JavadocMessageSend) this.references[i];
+						// if binding is valid then look if we have a reference to an overriden method/constructor
+						if (messageSend.binding != null && messageSend.binding.isValidBinding()) {
+							if (methDecl.binding.declaringClass.isCompatibleWith(messageSend.receiverType) &&
+								CharOperation.equals(messageSend.selector, methDecl.selector) &&
+								(messageSend.binding.returnType == methDecl.binding.returnType)) {
+								if (messageSend.arguments == null && methDecl.arguments == null) {
+									superRef = true;
+								}
+								else if (messageSend.arguments != null && methDecl.arguments != null) {
+									superRef = methDecl.binding.areParametersEqual(messageSend.binding);
+								}
+							}
+						}
+					}
+					else if (this.references[i] instanceof JavadocAllocationExpression) {
+						JavadocAllocationExpression allocationExpr = (JavadocAllocationExpression) this.references[i];
+						// if binding is valid then look if we have a reference to an overriden method/constructor
+						if (allocationExpr.binding != null && allocationExpr.binding.isValidBinding()) {
+							if (methDecl.binding.declaringClass.isCompatibleWith(allocationExpr.resolvedType)) {
+								if (allocationExpr.arguments == null && methDecl.arguments == null) {
+									superRef = true;
+								}
+								else if (allocationExpr.arguments != null && methDecl.arguments != null) {
+									superRef = methDecl.binding.areParametersEqual(allocationExpr.binding);
+								}
+							}
+						}
+					}
+				}
+			}
+			catch (Exception e) {
+				// Something wrong happen, forgot super ref...
+			}
+		}
+		
+		// Store if a reference exists to an overriden method/constructor or the method is in a local type,
+		boolean reportMissing = methDecl == null || !(superRef || (methDecl.binding.declaringClass != null && methDecl.binding.declaringClass.isLocalType()));
+
+		// @param tags
+		resolveParamTags(methScope, reportMissing);
+
+		// @return tags
+		if (this.returnStatement == null) {
+			if (reportMissing && methDecl != null) {
+				if (!methDecl.isConstructor() && !methDecl.isClinit()) {
+					MethodDeclaration meth = (MethodDeclaration) methDecl;
+					if (meth.binding.returnType != VoidBinding) {
+						// method with return should have @return tag
+						methScope.problemReporter().javadocMissingReturnTag(meth.returnType.sourceStart, meth.returnType.sourceEnd, methDecl.binding.modifiers);
+					}
+				}
+			}
+		} else {
+			this.returnStatement.resolve(methScope);
+		}
+
+		// @throws/@exception tags
+		resolveThrowsTags(methScope, reportMissing);
+	}
+	
+	/*
+	 * Resolve @param tags while method scope
+	 */
+	private void resolveParamTags(MethodScope methScope, boolean reportMissing) {
+		AbstractMethodDeclaration md = methScope.referenceMethod();
+		int paramTagsSize = this.parameters == null ? 0 : this.parameters.length;
+
+		// If no referenced method (field initializer for example) then report a problem for each param tag
+		if (md == null) {
+			for (int i = 0; i < paramTagsSize; i++) {
+				JavadocSingleNameReference param = this.parameters[i];
+				methScope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
+			}
+			return;
+		}
+		
+		// If no param tags then report a problem for each method argument
+		int argumentsSize = md.arguments == null ? 0 : md.arguments.length;
+		if (paramTagsSize == 0) {
+			if (reportMissing) {
+				for (int i = 0; i < argumentsSize; i++) {
+					Argument arg = md.arguments[i];
+					methScope.problemReporter().javadocMissingParamTag(arg, md.binding.modifiers);
+				}
+			}
+		} else {
+			LocalVariableBinding[] bindings = new LocalVariableBinding[paramTagsSize];
+			int maxBindings = 0;
+
+			// Scan all @param tags
+			for (int i = 0; i < paramTagsSize; i++) {
+				JavadocSingleNameReference param = this.parameters[i];
+				param.resolve(methScope);
+				if (param.binding != null && param.binding.isValidBinding()) {
+					// Verify duplicated tags
+					boolean found = false;
+					for (int j = 0; j < maxBindings && !found; j++) {
+						if (bindings[j] == param.binding) {
+							methScope.problemReporter().javadocDuplicatedParamTag(param, md.binding.modifiers);
+							found = true;
+						}
+					}
+					if (!found) {
+						bindings[maxBindings++] = (LocalVariableBinding) param.binding;
+					}
+				}
+			}
+
+			// Look for undocumented arguments
+			if (reportMissing) {
+				for (int i = 0; i < argumentsSize; i++) {
+					Argument arg = md.arguments[i];
+					boolean found = false;
+					for (int j = 0; j < maxBindings && !found; j++) {
+						LocalVariableBinding binding = bindings[j];
+						if (arg.binding == binding) {
+							found = true;
+						}
+					}
+					if (!found) {
+						methScope.problemReporter().javadocMissingParamTag(arg, md.binding.modifiers);
+					}
+				}
+			}
+		}
+	}
+
+	/*
+	 * Resolve @throws/@exception tags while method scope
+	 */
+	private void resolveThrowsTags(MethodScope methScope, boolean reportMissing) {
+		AbstractMethodDeclaration md = methScope.referenceMethod();
+		int throwsTagsNbre = this.thrownExceptions == null ? 0 : this.thrownExceptions.length;
+
+		// If no referenced method (field initializer for example) then report a problem for each throws tag
+		if (md == null) {
+			for (int i = 0; i < throwsTagsNbre; i++) {
+				TypeReference typeRef = this.thrownExceptions[i];
+				int start = typeRef.sourceStart;
+				int end = typeRef.sourceEnd;
+				if (typeRef instanceof JavadocQualifiedTypeReference) {
+					start = ((JavadocQualifiedTypeReference) typeRef).tagSourceStart;
+					end = ((JavadocQualifiedTypeReference) typeRef).tagSourceEnd;
+				} else if (typeRef instanceof JavadocSingleTypeReference) {
+					start = ((JavadocSingleTypeReference) typeRef).tagSourceStart;
+					end = ((JavadocSingleTypeReference) typeRef).tagSourceEnd;
+				}
+				methScope.problemReporter().javadocUnexpectedTag(start, end);
+			}
+			return;
+		}
+
+		// If no throws tags then report a problem for each method thrown exception
+		int thrownExceptionSize = md.thrownExceptions == null ? 0 : md.thrownExceptions.length;
+		if (throwsTagsNbre == 0) {
+			if (reportMissing) {
+				for (int i = 0; i < thrownExceptionSize; i++) {
+					TypeReference typeRef = md.thrownExceptions[i];
+					if (typeRef.resolvedType != null && typeRef.resolvedType.isValidBinding()) { // flag only valid class name
+						methScope.problemReporter().javadocMissingThrowsTag(typeRef, md.binding.modifiers);
+					}
+				}
+			}
+		} else {
+			int maxRef = 0;
+			TypeReference[] typeReferences = new TypeReference[throwsTagsNbre];
+
+			// Scan all @throws tags
+			for (int i = 0; i < throwsTagsNbre; i++) {
+				TypeReference typeRef = this.thrownExceptions[i];
+				typeRef.resolve(methScope);
+				TypeBinding typeBinding = typeRef.resolvedType;
+
+				if (typeBinding != null && typeBinding.isValidBinding() && typeBinding.isClass()) {
+					// Verify duplicated tags
+					boolean found = false;
+					for (int j = 0; j < maxRef && !found; j++) {
+						if (typeReferences[j].resolvedType == typeBinding) {
+							methScope.problemReporter().javadocDuplicatedThrowsClassName(typeRef, md.binding.modifiers);
+							found = true;
+						}
+					}
+					if (!found) {
+						typeReferences[maxRef++] = typeRef;
+					}
+				}
+			}
+
+			// Look for undocumented thrown exception
+			for (int i = 0; i < thrownExceptionSize; i++) {
+				TypeReference exception = md.thrownExceptions[i];
+				boolean found = false;
+				for (int j = 0; j < maxRef && !found; j++) {
+					if (typeReferences[j] != null) {
+						TypeBinding typeBinding = typeReferences[j].resolvedType;
+						if (exception.resolvedType == typeBinding) {
+							found = true;
+							typeReferences[j] = null;
+						}
+					}
+				}
+				if (!found && reportMissing) {
+					if (exception.resolvedType != null && exception.resolvedType.isValidBinding()) { // flag only valid class name
+						methScope.problemReporter().javadocMissingThrowsTag(exception, md.binding.modifiers);
+					}
+				}
+			}
+
+			// Verify additional @throws tags
+			for (int i = 0; i < maxRef; i++) {
+				TypeReference typeRef = typeReferences[i];
+				if (typeRef != null) {
+					boolean compatible = false;
+					// thrown exceptions subclasses are accepted
+					for (int j = 0; j<thrownExceptionSize && !compatible; j++) {
+						TypeBinding exceptionBinding = md.thrownExceptions[j].resolvedType;
+						if (exceptionBinding != null) {
+							compatible = typeRef.resolvedType.isCompatibleWith(exceptionBinding);
+						}
+					}
+			
+					//  If not compatible only complain on unchecked exception
+					if (!compatible &&
+						 !typeRef.resolvedType.isCompatibleWith(methScope.getJavaLangRuntimeException()) &&
+						 !typeRef.resolvedType.isCompatibleWith(methScope.getJavaLangError())) {
+						methScope.problemReporter().javadocInvalidThrowsClassName(typeRef, md.binding.modifiers);
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
new file mode 100644
index 0000000..3ec02e0
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class JavadocAllocationExpression extends AllocationExpression {
+
+	public int tagSourceStart, tagSourceEnd;
+	public boolean superAccess = false;
+	
+	public JavadocAllocationExpression(long pos) {
+		this.sourceStart = (int) (pos >>> 32);
+		this.sourceEnd = (int) pos;
+		this.bits |= InsideJavadoc;
+	}
+
+	/*
+	 * Resolves type on a Block or Class scope.
+	 */
+	private TypeBinding internalResolveType(Scope scope) {
+
+		// Propagate the type checking to the arguments, and check if the constructor is defined.
+		this.constant = NotAConstant;
+		if (scope.kind == Scope.CLASS_SCOPE) {
+			this.resolvedType = this.type.resolveType((ClassScope)scope);
+		} else {
+			this.resolvedType = this.type.resolveType((BlockScope)scope);
+		}
+
+		// buffering the arguments' types
+		TypeBinding[] argumentTypes = NoParameters;
+		if (this.arguments != null) {
+			boolean argHasError = false;
+			int length = this.arguments.length;
+			argumentTypes = new TypeBinding[length];
+			for (int i = 0; i < length; i++) {
+				Expression argument = this.arguments[i];
+				if (scope.kind == Scope.CLASS_SCOPE) {
+					argumentTypes[i] = argument.resolveType((ClassScope)scope);
+				} else {
+					argumentTypes[i] = argument.resolveType((BlockScope)scope);
+				}
+				if (argumentTypes[i] == null) {
+					argHasError = true;
+				}
+			}
+			if (argHasError) {
+				return null;
+			}
+		}
+
+		// check resolved type
+		if (this.resolvedType == null) {
+			return null;
+		}
+		this.superAccess = scope.enclosingSourceType().isCompatibleWith(this.resolvedType);
+
+		ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType;
+		this.binding = scope.getConstructor(allocationType, argumentTypes, this);
+		if (!this.binding.isValidBinding()) {
+			MethodBinding methodBinding = scope.getMethod(this.resolvedType, this.resolvedType.sourceName(), argumentTypes, this);
+			if (methodBinding.isValidBinding()) {
+				this.binding = methodBinding;
+			} else {
+				if (this.binding.declaringClass == null) {
+					this.binding.declaringClass = allocationType;
+				}
+				scope.problemReporter().javadocInvalidConstructor(this, this.binding, scope.getDeclarationModifiers());
+			}
+			return this.resolvedType;
+		}
+		if (isMethodUseDeprecated(this.binding, scope)) {
+			scope.problemReporter().javadocDeprecatedMethod(this.binding, this, scope.getDeclarationModifiers());
+		}
+
+		return allocationType;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
+	 */
+	public boolean isSuperAccess() {
+		return this.superAccess;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public TypeBinding resolveType(BlockScope scope) {
+		return internalResolveType(scope);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public TypeBinding resolveType(ClassScope scope) {
+		return internalResolveType(scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java
new file mode 100644
index 0000000..eb690e0
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+
+public class JavadocArgumentExpression extends Expression {
+	public char[] token;
+	public Argument argument;
+
+	public JavadocArgumentExpression(char[] name, int startPos, int endPos, TypeReference typeRef) {
+		this.token = name;
+		this.sourceStart = startPos;
+		this.sourceEnd = endPos;
+		long pos = (((long) startPos) << 32) + endPos;
+		this.argument = new Argument(name, pos, typeRef, IConstants.AccDefault);
+		this.bits |= InsideJavadoc;
+	}
+
+	/*
+	 * Resolves type on a Block or Class scope.
+	 */
+	private TypeBinding internalResolveType(Scope scope) {
+		this.constant = NotAConstant;
+		if (this.resolvedType != null) { // is a shared type reference which was already resolved
+			if (!this.resolvedType.isValidBinding()) {
+				return null; // already reported error
+			}
+		}
+		else {
+			if (this.argument != null) {
+				TypeReference typeRef = this.argument.type;
+				if (typeRef != null) {
+					this.resolvedType = typeRef.getTypeBinding(scope);
+					if (!this.resolvedType.isValidBinding()) {
+						scope.problemReporter().javadocInvalidType(typeRef, this.resolvedType, scope.getDeclarationModifiers());
+						return null;
+					}
+					if (isTypeUseDeprecated(this.resolvedType, scope)) {
+						scope.problemReporter().javadocDeprecatedType(this.resolvedType, typeRef, scope.getDeclarationModifiers());
+						return null;
+					}
+					return this.resolvedType;
+				}
+			}
+		}
+		return null;
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		if (this.argument == null) {
+			if (this.token != null) {
+				output.append(this.token);
+			}
+		}
+		else {
+			this.argument.print(indent, output);
+		}
+		return output;
+	}
+
+	public void resolve(BlockScope scope) {
+		if (this.argument != null) {
+			this.argument.resolve(scope);
+		}
+	}
+
+	public TypeBinding resolveType(BlockScope scope) {
+		return internalResolveType(scope);
+	}
+
+	public TypeBinding resolveType(ClassScope scope) {
+		return internalResolveType(scope);
+	}
+	
+	/* (non-Javadoc)
+	 * Redefine to capture javadoc specific signatures
+	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+		if (visitor.visit(this, blockScope)) {
+			if (this.argument != null) {
+				this.argument.traverse(visitor, blockScope);
+			}
+		}
+		visitor.endVisit(this, blockScope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.java
new file mode 100644
index 0000000..7b787d6
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+
+
+
+public class JavadocArrayQualifiedTypeReference extends ArrayQualifiedTypeReference {
+
+	public int tagSourceStart, tagSourceEnd;
+
+	public JavadocArrayQualifiedTypeReference(JavadocQualifiedTypeReference typeRef, int dim) {
+		super(typeRef.tokens, dim, typeRef.sourcePositions);
+	}
+
+	protected void reportInvalidType(Scope scope) {
+		scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers());
+	}
+	protected void reportDeprecatedType(Scope scope) {
+		scope.problemReporter().javadocDeprecatedType(this.resolvedType, this, scope.getDeclarationModifiers());
+	}
+
+	/* (non-Javadoc)
+	 * Redefine to capture javadoc specific signatures
+	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.java
new file mode 100644
index 0000000..3fa7e41
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+
+
+public class JavadocArraySingleTypeReference extends ArrayTypeReference {
+
+	public JavadocArraySingleTypeReference(char[] name, int dim, long pos) {
+		super(name, dim, pos);
+		this.bits |= InsideJavadoc;
+	}
+
+	protected void reportInvalidType(Scope scope) {
+		scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers());
+	}
+	protected void reportDeprecatedType(Scope scope) {
+		scope.problemReporter().javadocDeprecatedType(this.resolvedType, this, scope.getDeclarationModifiers());
+	}
+
+	/* (non-Javadoc)
+	 * Redefine to capture javadoc specific signatures
+	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java
new file mode 100644
index 0000000..f9d8563
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class JavadocFieldReference extends FieldReference {
+
+	public int tagSourceStart, tagSourceEnd;
+
+	public JavadocFieldReference(char[] source, long pos) {
+		super(source, pos);
+		this.bits |= InsideJavadoc;
+	}
+
+	/*
+	 * Resolves type on a Block or Class scope.
+	 */
+	private TypeBinding internalResolveType(Scope scope) {
+
+		this.constant = NotAConstant;
+		if (scope.kind == Scope.CLASS_SCOPE) {
+			this.receiverType = this.receiver.resolveType((ClassScope) scope);
+		} else {
+			this.receiverType = this.receiver.resolveType((BlockScope)scope);
+		}
+		if (this.receiverType == null) {
+			return null;
+		}
+
+		this.binding = scope.getField(this.receiverType, this.token, this);
+		if (!this.binding.isValidBinding()) {
+			scope.problemReporter().javadocInvalidField(this, this.receiverType, scope.getDeclarationModifiers());
+			return null;
+		}
+
+		if (isFieldUseDeprecated(this.binding, scope, (this.bits & IsStrictlyAssignedMASK) != 0)) {
+			scope.problemReporter().javadocDeprecatedField(this.binding, this, scope.getDeclarationModifiers());
+		}
+		return this.resolvedType = this.binding.type;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
+	 */
+	public boolean isSuperAccess() {
+		return false;
+	}
+
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		if (this.receiver != null) {
+			this.receiver.printExpression(0, output);
+		}
+		output.append('#').append(this.token);
+		return output;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public TypeBinding resolveType(BlockScope scope) {
+		return internalResolveType(scope);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public TypeBinding resolveType(ClassScope scope) {
+		return internalResolveType(scope);
+	}
+
+	/* (non-Javadoc)
+	 * Redefine to capture javadoc specific signatures
+	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+		if (visitor.visit(this, scope)) {
+			if (this.receiver != null) {
+				this.receiver.traverse(visitor, scope);
+			}
+		}
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
new file mode 100644
index 0000000..6ef86e4
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+
+public class JavadocMessageSend extends MessageSend {
+
+	public int tagSourceStart, tagSourceEnd;
+	public boolean superAccess = false;
+
+	public JavadocMessageSend(char[] name, long pos) {
+		this.selector = name;
+		this.nameSourcePosition = pos;
+		this.sourceStart = (int) (this.nameSourcePosition >>> 32);
+		this.sourceEnd = (int) this.nameSourcePosition;
+		this.bits |= InsideJavadoc;
+	}
+	public JavadocMessageSend(char[] name, long pos, JavadocArgumentExpression[] arguments) {
+		this(name, pos);
+		this.arguments = arguments;
+	}
+
+	/*
+	 * Resolves type on a Block or Class scope.
+	 */
+	private TypeBinding internalResolveType(Scope scope) {
+		// Answer the signature return type
+		// Base type promotion
+		this.constant = NotAConstant;
+		if (scope.kind == Scope.CLASS_SCOPE) {
+			this.receiverType = this.receiver.resolveType((ClassScope) scope);
+		} else {
+			this.receiverType = this.receiver.resolveType((BlockScope) scope);
+		}
+
+		// will check for null after args are resolved
+		TypeBinding[] argumentTypes = NoParameters;
+		if (this.arguments != null) {
+			boolean argHasError = false; // typeChecks all arguments 
+			int length = this.arguments.length;
+			argumentTypes = new TypeBinding[length];
+			for (int i = 0; i < length; i++){
+				Expression argument = this.arguments[i];
+				if (scope.kind == Scope.CLASS_SCOPE) {
+					argumentTypes[i] = argument.resolveType((ClassScope)scope);
+				} else {
+					argumentTypes[i] = argument.resolveType((BlockScope)scope);
+				}
+				if (argumentTypes[i] == null) {
+					argHasError = true;
+				}
+			}
+			if (argHasError) {
+				return null;
+			}
+		}
+
+		// check receiver type
+		if (this.receiverType == null) {
+			return null;
+		}
+		this.qualifyingType = this.receiverType;
+		this.superAccess = scope.enclosingSourceType().isCompatibleWith(this.receiverType);
+
+		// base type cannot receive any message
+		if (this.receiverType.isBaseType()) {
+			scope.problemReporter().javadocErrorNoMethodFor(this, this.receiverType, argumentTypes, scope.getDeclarationModifiers());
+			return null;
+		}
+		this.codegenBinding = this.binding = scope.getMethod(this.receiverType, this.selector, argumentTypes, this); 
+		if (!this.binding.isValidBinding()) {
+			if (this.binding.declaringClass == null) {
+				if (this.receiverType instanceof ReferenceBinding) {
+					this.binding.declaringClass = (ReferenceBinding) this.receiverType;
+				} else { 
+					scope.problemReporter().javadocErrorNoMethodFor(this, this.receiverType, argumentTypes, scope.getDeclarationModifiers());
+					return null;
+				}
+			}
+			scope.problemReporter().javadocInvalidMethod(this, this.binding, scope.getDeclarationModifiers());
+			// record the closest match, for clients who may still need hint about possible method match
+			if (this.binding instanceof ProblemMethodBinding){
+				MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
+				if (closestMatch != null) this.codegenBinding = this.binding = closestMatch;
+			}
+			return this.resolvedType = this.binding == null ? null : this.binding.returnType;
+		}
+		if (isMethodUseDeprecated(this.binding, scope)) {
+			scope.problemReporter().javadocDeprecatedMethod(this.binding, this, scope.getDeclarationModifiers());
+		}
+
+		return this.resolvedType = this.binding.returnType;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
+	 */
+	public boolean isSuperAccess() {
+		return this.superAccess;
+	}
+
+	public StringBuffer printExpression(int indent, StringBuffer output){
+	
+		if (this.receiver != null) {
+			this.receiver.printExpression(0, output);
+		}
+		output.append('#').append(this.selector).append('(');
+		if (this.arguments != null) {
+			for (int i = 0; i < this.arguments.length ; i ++) {	
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				this.arguments[i].printExpression(0, output);
+			}
+		}
+		return output.append(')');
+	}
+
+	public TypeBinding resolveType(BlockScope scope) {
+		return internalResolveType(scope);
+	}
+
+	public TypeBinding resolveType(ClassScope scope) {
+		return internalResolveType(scope);
+	}
+
+	/* (non-Javadoc)
+	 * Redefine to capture javadoc specific signatures
+	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+		if (visitor.visit(this, blockScope)) {
+			if (this.receiver != null) {
+				this.receiver.traverse(visitor, blockScope);
+			}
+			if (this.arguments != null) {
+				int argumentsLength = this.arguments.length;
+				for (int i = 0; i < argumentsLength; i++)
+					this.arguments[i].traverse(visitor, blockScope);
+			}
+		}
+		visitor.endVisit(this, blockScope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
new file mode 100644
index 0000000..445884f
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+
+
+
+public class JavadocQualifiedTypeReference extends QualifiedTypeReference {
+
+	public int tagSourceStart, tagSourceEnd;
+
+	public JavadocQualifiedTypeReference(char[][] sources, long[] pos, int tagStart, int tagEnd) {
+		super(sources, pos);
+		this.tagSourceStart = tagStart;
+		this.tagSourceEnd = tagEnd;
+		this.bits |= InsideJavadoc;
+	}
+
+	protected void reportInvalidType(Scope scope) {
+		scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers());
+	}
+	protected void reportDeprecatedType(Scope scope) {
+		scope.problemReporter().javadocDeprecatedType(this.resolvedType, this, scope.getDeclarationModifiers());
+	}
+
+	/* (non-Javadoc)
+	 * Redefine to capture javadoc specific signatures
+	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+	
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java
new file mode 100644
index 0000000..a10c7a2
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+
+public class JavadocReturnStatement extends ReturnStatement {
+	public char[] description;
+
+	public JavadocReturnStatement(int s, int e, char[] descr) {
+		super(null, s, e);
+		this.description = descr;
+		this.bits |= InsideJavadoc;
+	}
+
+	public void resolve(BlockScope scope) {
+		MethodScope methodScope = scope.methodScope();
+		MethodBinding methodBinding;
+		TypeBinding methodType =
+			(methodScope.referenceContext instanceof AbstractMethodDeclaration)
+				? ((methodBinding = ((AbstractMethodDeclaration) methodScope.referenceContext).binding) == null 
+					? null 
+					: methodBinding.returnType)
+				: VoidBinding;
+		if (methodType == null || methodType == VoidBinding) {
+			scope.problemReporter().javadocUnexpectedTag(this.sourceStart, this.sourceEnd);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * Redefine to capture javadoc specific signatures
+	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java
new file mode 100644
index 0000000..56566aa
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class JavadocSingleNameReference extends SingleNameReference {
+
+	public int tagSourceStart, tagSourceEnd;
+
+	public JavadocSingleNameReference(char[] name, int startPosition, int endPosition) {
+		super(name, (((long) startPosition) << 32) + endPosition);
+		this.bits |= InsideJavadoc;
+	}
+
+	public void resolve(BlockScope scope) {
+		
+		LocalVariableBinding variableBinding = scope.findVariable(this.token);
+		if (variableBinding != null && variableBinding.isValidBinding() && variableBinding.isArgument) {
+			this.binding = variableBinding;
+			return;
+		}
+		try {
+			MethodScope methScope = (MethodScope) scope;
+			scope.problemReporter().javadocInvalidParamName(this, methScope.referenceMethod().modifiers);
+		}
+		catch (Exception e) {
+			scope.problemReporter().javadocInvalidParamName(this, -1);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * Redefine to capture javadoc specific signatures
+	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
new file mode 100644
index 0000000..70358d0
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+
+
+public class JavadocSingleTypeReference extends SingleTypeReference {
+	
+	public int tagSourceStart, tagSourceEnd;
+
+	public JavadocSingleTypeReference(char[] source, long pos, int tagStart, int tagEnd) {
+		super(source, pos);
+		this.tagSourceStart = tagStart;
+		this.tagSourceEnd = tagEnd;
+		this.bits |= InsideJavadoc;
+	}
+
+	protected void reportInvalidType(Scope scope) {
+		scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers());
+	}
+	protected void reportDeprecatedType(Scope scope) {
+		scope.problemReporter().javadocDeprecatedType(this.resolvedType, this, scope.getDeclarationModifiers());
+	}
+
+	/* (non-Javadoc)
+	 * Redefine to capture javadoc specific signatures
+	 * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java
index f0ce979..0638b12 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -27,12 +27,14 @@
 	/**
 	 * LabeledStatement constructor comment.
 	 */
-	public LabeledStatement(char[] l, Statement st, int s, int e) {
+	public LabeledStatement(char[] label, Statement statement, int sourceStart, int sourceEnd) {
 		
-		this.statement = st;
-		this.label = l;
-		this.sourceStart = s;
-		this.sourceEnd = e;
+		this.statement = statement;
+		// remember useful empty statement
+		if (statement instanceof EmptyStatement) statement.bits |= IsUsefulEmptyStatementMASK;
+		this.label = label;
+		this.sourceStart = sourceStart;
+		this.sourceEnd = sourceEnd;
 	}
 	
 	public FlowInfo analyseCode(
@@ -65,7 +67,7 @@
 		}
 	}
 	
-	public AstNode concreteStatement() {
+	public ASTNode concreteStatement() {
 		
 		// return statement.concreteStatement(); // for supporting nested labels:   a:b:c: someStatement (see 21912)
 		return statement;
@@ -98,24 +100,30 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 	
-	public void resolve(BlockScope scope) {
-		
-		statement.resolve(scope);
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+
+		printIndent(tab, output).append(label).append(": "); //$NON-NLS-1$
+		if (this.statement == null) 
+			output.append(';');
+		else 
+			this.statement.printStatement(0, output); 
+		return output;
 	}
 	
-	public String toString(int tab) {
-
-		String s = tabString(tab);
-		s += new String(label) + ": " + statement.toString(0); //$NON-NLS-1$
-		return s;
+	public void resolve(BlockScope scope) {
+		
+		if (this.statement != null) {
+			this.statement.resolve(scope);
+		}
 	}
 
+
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
-			statement.traverse(visitor, blockScope);
+			if (this.statement != null) this.statement.traverse(visitor, blockScope);
 		}
 		visitor.endVisit(this, blockScope);
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Literal.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Literal.java
index 404b52b..696e61d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Literal.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Literal.java
@@ -16,30 +16,42 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public abstract class Literal extends Expression {
-	
-public Literal(int s,int e) {
-	sourceStart = s ;
-	sourceEnd= e;
-}
 
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-	return flowInfo;
-}
+	public Literal(int s, int e) {
 
-public abstract void computeConstant() ;
-	//ON ERROR constant STAYS NULL
-public abstract TypeBinding literalType(BlockScope scope);
-public TypeBinding resolveType(BlockScope scope) {
-	// compute the real value, which must range its type's range
-
-	computeConstant();
-	if (constant == null) {
-		scope.problemReporter().constantOutOfRange(this);
-		constant = Constant.NotAConstant;
-		return null;
+		sourceStart = s;
+		sourceEnd = e;
 	}
-	this.resolvedType = literalType(scope);
-	return this.resolvedType;
-}
-public abstract char[] source() ;
+
+	public FlowInfo analyseCode(
+		BlockScope currentScope,
+		FlowContext flowContext,
+		FlowInfo flowInfo) {
+			
+		return flowInfo;
+	}
+
+	public abstract void computeConstant();
+
+	public abstract TypeBinding literalType(BlockScope scope);
+
+	public StringBuffer printExpression(int indent, StringBuffer output){
+	
+		return output.append(source());
+	 }
+	 
+	public TypeBinding resolveType(BlockScope scope) {
+		// compute the real value, which must range its type's range
+		this.resolvedType = literalType(scope);
+
+		// in case of error, constant did remain null
+		computeConstant();
+		if (constant == null) {
+			scope.problemReporter().constantOutOfRange(this, this.resolvedType);
+			constant = Constant.NotAConstant;
+		}
+		return this.resolvedType;
+	}
+
+	public abstract char[] source();
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
index f739565..ccf71cf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -19,23 +19,16 @@
 public class LocalDeclaration extends AbstractVariableDeclaration {
 
 	public LocalVariableBinding binding;
-
+	
 	public LocalDeclaration(
-		Expression expr,
 		char[] name,
 		int sourceStart,
 		int sourceEnd) {
 
-		initialization = expr;
 		this.name = name;
 		this.sourceStart = sourceStart;
 		this.sourceEnd = sourceEnd;
-		if (initialization != null) {
-			this.declarationSourceEnd = initialization.sourceEnd;
-			this.declarationEnd = initialization.sourceEnd;
-		} else {
-			this.declarationEnd = sourceEnd;
-		}
+		this.declarationEnd = sourceEnd;
 	}
 
 	public FlowInfo analyseCode(
@@ -78,7 +71,7 @@
 
 	/**
 	 * Code generation for a local declaration:
-	 *	  normal assignment to a local variable + unused variable handling 
+	 *	i.e.&nbsp;normal assignment to a local variable + unused variable handling 
 	 */
 	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
 
@@ -138,45 +131,47 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
-	public String name() {
-
-		return String.valueOf(name);
-	}
-
 	public void resolve(BlockScope scope) {
 
 		// create a binding and add it to the scope
-		TypeBinding tb = type.resolveType(scope);
+		TypeBinding typeBinding = type.resolveType(scope);
 
 		checkModifiers();
 
-		if (tb != null) {
-			if (tb == VoidBinding) {
+		if (typeBinding != null) {
+			if (typeBinding == VoidBinding) {
 				scope.problemReporter().variableTypeCannotBeVoid(this);
 				return;
 			}
-			if (tb.isArrayType() && ((ArrayBinding) tb).leafComponentType == VoidBinding) {
+			if (typeBinding.isArrayType() && ((ArrayBinding) typeBinding).leafComponentType == VoidBinding) {
 				scope.problemReporter().variableTypeCannotBeVoidArray(this);
 				return;
 			}
 		}
-
-		// duplicate checks
-		if ((binding = scope.duplicateName(name)) != null) {
-			// the name already exists... may carry on with the first binding...
-			scope.problemReporter().redefineLocal(this);
-		} else {
+		
+		Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+		boolean shouldInsertInScope = true;
+		if (existingVariable != null && existingVariable.isValidBinding()){
+			if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
+				shouldInsertInScope = false;
+				scope.problemReporter().redefineLocal(this);
+			} else {
+				scope.problemReporter().localVariableHiding(this, existingVariable, false);
+			}
+		}
+				
+		if (shouldInsertInScope) {
 			if ((modifiers & AccFinal)!= 0 && this.initialization == null) {
 				modifiers |= AccBlankFinal;
 			}
-			binding = new LocalVariableBinding(this, tb, modifiers, false);
+			binding = new LocalVariableBinding(this, typeBinding, modifiers, false);
 			scope.addLocalVariable(binding);
 			binding.constant = NotAConstant;
 			// allow to recursivelly target the binding....
 			// the correct constant is harmed if correctly computed at the end of this method
 		}
 
-		if (tb == null) {
+		if (typeBinding == null) {
 			if (initialization != null)
 				initialization.resolveType(scope); // want to report all possible errors
 			return;
@@ -185,34 +180,36 @@
 		// store the constant for final locals 	
 		if (initialization != null) {
 			if (initialization instanceof ArrayInitializer) {
-				TypeBinding initTb = initialization.resolveTypeExpecting(scope, tb);
-				if (initTb != null) {
-					((ArrayInitializer) initialization).binding = (ArrayBinding) initTb;
-					initialization.implicitWidening(tb, initTb);
+				TypeBinding initializationType = initialization.resolveTypeExpecting(scope, typeBinding);
+				if (initializationType != null) {
+					((ArrayInitializer) initialization).binding = (ArrayBinding) initializationType;
+					initialization.implicitWidening(typeBinding, initializationType);
 				}
 			} else {
-				TypeBinding initTb = initialization.resolveType(scope);
-				if (initTb != null) {
-					if (initialization.isConstantValueOfTypeAssignableToType(initTb, tb)
-						|| (tb.isBaseType() && BaseTypeBinding.isWidening(tb.id, initTb.id))
-						|| initTb.isCompatibleWith(tb))
-						initialization.implicitWidening(tb, initTb);
+				TypeBinding initializationType = initialization.resolveType(scope);
+				if (initializationType != null) {
+					if (initialization.isConstantValueOfTypeAssignableToType(initializationType, typeBinding)
+						|| (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationType.id))
+						|| initializationType.isCompatibleWith(typeBinding))
+						initialization.implicitWidening(typeBinding, initializationType);
 					else
-						scope.problemReporter().typeMismatchError(initTb, tb, this);
+						scope.problemReporter().typeMismatchError(initializationType, typeBinding, this);
 				}
 			}
 
 			// change the constant in the binding when it is final
 			// (the optimization of the constant propagation will be done later on)
 			// cast from constant actual type to variable type
-			binding.constant =
-				binding.isFinal()
-					? initialization.constant.castTo((tb.id << 4) + initialization.constant.typeID())
-					: NotAConstant;
+			if (binding != null) {
+				binding.constant =
+					binding.isFinal()
+						? initialization.constant.castTo((typeBinding.id << 4) + initialization.constant.typeID())
+						: NotAConstant;
+			}
 		}
 	}
 
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
 			type.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalTypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalTypeDeclaration.java
deleted file mode 100644
index 7f10c6b..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalTypeDeclaration.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.compiler.ast;
-
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.*;
-
-public class LocalTypeDeclaration extends InnerTypeDeclaration {
-	public AbstractMethodDeclaration enclosingMethod;
-
-public LocalTypeDeclaration(CompilationResult compilationResult){
-	super(compilationResult);
-}	
-
-/**
- *	Iteration for a local innertype
- *
- */
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
-	if (ignoreFurtherInvestigation)
-		return;
-	try {
-		if (visitor.visit(this, blockScope)) {
-			if (superclass != null)
-				superclass.traverse(visitor, scope);
-			if (superInterfaces != null) {
-				int superInterfaceLength = superInterfaces.length;
-				for (int i = 0; i < superInterfaceLength; i++)
-					superInterfaces[i].traverse(visitor, scope);
-			}
-			if (memberTypes != null) {
-				int memberTypesLength = memberTypes.length;
-				for (int i = 0; i < memberTypesLength; i++)
-					memberTypes[i].traverse(visitor, scope);
-			}
-			if (fields != null) {
-				int fieldsLength = fields.length;
-				for (int i = 0; i < fieldsLength; i++) {
-					FieldDeclaration field;
-					if ((field = fields[i]).isStatic()) {
-						// local type cannot have static fields
-					} else {
-						field.traverse(visitor, initializerScope);
-					}
-				}
-			}
-			if (methods != null) {
-				int methodsLength = methods.length;
-				for (int i = 0; i < methodsLength; i++)
-					methods[i].traverse(visitor, scope);
-			}
-		}
-		visitor.endVisit(this, blockScope);
-	} catch (AbortType e) {
-	}
-}
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
index 7a06225..cea0574 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -134,7 +134,7 @@
 	}
 	return tb;
 }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+public void traverse(ASTVisitor visitor, BlockScope scope) {
 	visitor.visit(this, scope);
 	visitor.endVisit(this, scope);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MagicLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MagicLiteral.java
index fb75e63..9dd32fe 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MagicLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MagicLiteral.java
@@ -11,21 +11,19 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 public abstract class  MagicLiteral extends Literal {
-public MagicLiteral(int s , int e) {
-	super(s,e);
-}
-public boolean isValidJavaStatement(){
-	//should never be reach, but with a bug in the ast tree....
-	//see comment on the Statement class
 	
-	return false ;}
-/**
- * source method comment.
- */
-public char[] source() {
-	return null;
-}
-public String toStringExpression(){
-
-	return  new String(source()) ; }
+	public MagicLiteral(int start , int end) {
+		
+		super(start,end);
+	}
+	
+	public boolean isValidJavaStatement(){
+		
+		return false ;
+	}
+	
+	public char[] source() {
+	
+		return null;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberTypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberTypeDeclaration.java
deleted file mode 100644
index 2c87c26..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberTypeDeclaration.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.compiler.ast;
-
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.eclipse.jdt.internal.compiler.problem.AbortType;
-
-public class MemberTypeDeclaration extends InnerTypeDeclaration {
-	public TypeDeclaration enclosingType;
-	
-public MemberTypeDeclaration(CompilationResult compilationResult){
-	super(compilationResult);
-}		
-/**
- *	Iteration for a member innertype
- *
- */
-public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope classScope) {
-	if (ignoreFurtherInvestigation)
-		return;
-	try {
-		if (visitor.visit(this, classScope)) {
-			if (superclass != null)
-				superclass.traverse(visitor, scope);
-			if (superInterfaces != null) {
-				int superInterfaceLength = superInterfaces.length;
-				for (int i = 0; i < superInterfaceLength; i++)
-					superInterfaces[i].traverse(visitor, scope);
-			}
-			if (memberTypes != null) {
-				int memberTypesLength = memberTypes.length;
-				for (int i = 0; i < memberTypesLength; i++)
-					memberTypes[i].traverse(visitor, scope);
-			}
-			if (fields != null) {
-				int fieldsLength = fields.length;
-				for (int i = 0; i < fieldsLength; i++) {
-					FieldDeclaration field;
-					if ((field = fields[i]).isStatic()) {
-						field.traverse(visitor, staticInitializerScope);
-					} else {
-						field.traverse(visitor, initializerScope);
-					}
-				}
-			}
-			if (methods != null) {
-				int methodsLength = methods.length;
-				for (int i = 0; i < methodsLength; i++)
-					methods[i].traverse(visitor, scope);
-			}
-		}
-		visitor.endVisit(this, classScope);
-	} catch (AbortType e) {
-	}
-}
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index 6c388b5..f0272ee 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -7,12 +7,13 @@
  * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752)
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
-import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
@@ -28,9 +29,6 @@
 
 	public TypeBinding receiverType, qualifyingType;
 	
-public MessageSend() {
-	
-}
 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
 
 	flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic()).unconditionalInits();
@@ -45,9 +43,10 @@
 		// must verify that exceptions potentially thrown by this expression are caught in the method
 		flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo, currentScope);
 	}
-	manageSyntheticAccessIfNecessary(currentScope);	
+	manageSyntheticAccessIfNecessary(currentScope, flowInfo);	
 	return flowInfo;
 }
+
 /**
  * MessageSend code generation
  *
@@ -119,8 +118,9 @@
 public boolean isTypeAccess() {	
 	return receiver != null && receiver.isTypeReference();
 }
-public void manageSyntheticAccessIfNecessary(BlockScope currentScope){
+public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){
 
+	if (!flowInfo.isReachable()) return;
 	if (binding.isPrivate()){
 
 		// depth is set for both implicit and explicit access (see MethodBinding#canBeSeenBy)		
@@ -158,22 +158,48 @@
 	// and not from Object or implicit static method call.	
 	if (binding.declaringClass != this.qualifyingType
 		&& !this.qualifyingType.isArrayType()
-		&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
+		&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
 				&& (!receiver.isImplicitThis() || !binding.isStatic())
 				&& binding.declaringClass.id != T_Object) // no change for Object methods
 			|| !binding.declaringClass.canBeSeenBy(currentScope))) {
 
 		this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(binding, (ReferenceBinding) this.qualifyingType);
+
+		// Post 1.4.0 target, array clone() invocations are qualified with array type 
+		// This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding)
 	}
 }
 
+public StringBuffer printExpression(int indent, StringBuffer output){
+	
+	if (!receiver.isImplicitThis()) receiver.printExpression(0, output).append('.');
+	output.append(selector).append('(') ; //$NON-NLS-1$
+	if (arguments != null) {
+		for (int i = 0; i < arguments.length ; i ++) {	
+			if (i > 0) output.append(", "); //$NON-NLS-1$
+			arguments[i].printExpression(0, output);
+		}
+	}
+	return output.append(')');
+}
+
 public TypeBinding resolveType(BlockScope scope) {
 	// Answer the signature return type
 	// Base type promotion
 
 	constant = NotAConstant;
+	boolean receiverCast = false, argumentsCast = false; 
+	if (this.receiver instanceof CastExpression) {
+		this.receiver.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+		receiverCast = true;
+	}
 	this.qualifyingType = this.receiverType = receiver.resolveType(scope); 
-	
+	if (receiverCast && this.receiverType != null) {
+		 // due to change of declaring class with receiver type, only identity cast should be notified
+		if (((CastExpression)this.receiver).expression.resolvedType == this.receiverType) { 
+					scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);		
+		}
+	}
 	// will check for null after args are resolved
 	TypeBinding[] argumentTypes = NoParameters;
 	if (arguments != null) {
@@ -181,11 +207,16 @@
 		int length = arguments.length;
 		argumentTypes = new TypeBinding[length];
 		for (int i = 0; i < length; i++){
-			if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null){
+			Expression argument = arguments[i];
+			if (argument instanceof CastExpression) {
+				argument.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+				argumentsCast = true;
+			}
+			if ((argumentTypes[i] = argument.resolveType(scope)) == null){
 				argHasError = true;
 			}
 		}
-		if (argHasError){
+		if (argHasError) {
 			if(receiverType instanceof ReferenceBinding) {
 				// record any selector match, for clients who may still need hint about possible method match
 				this.codegenBinding = this.binding = scope.findMethod((ReferenceBinding)receiverType, selector, new TypeBinding[]{}, this);
@@ -201,7 +232,6 @@
 		scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
 		return null;
 	}
-
 	this.codegenBinding = this.binding = 
 		receiver.isImplicitThis()
 			? scope.getImplicitMethod(selector, argumentTypes, this)
@@ -221,7 +251,7 @@
 			MethodBinding closestMatch = ((ProblemMethodBinding)binding).closestMatch;
 			if (closestMatch != null) this.codegenBinding = this.binding = closestMatch;
 		}
-		return binding == null ? null : binding.returnType;
+		return this.resolvedType = binding == null ? null : binding.returnType;
 	}
 	if (!binding.isStatic()) {
 		// the "receiver" must not be a type, in other words, a NameReference that the TC has bound to a Type
@@ -235,13 +265,20 @@
 				|| receiver.isSuper()
 				|| (receiver instanceof NameReference 
 					&& (((NameReference) receiver).bits & BindingIds.TYPE) != 0))) {
-			scope.problemReporter().unnecessaryReceiverForStaticMethod(this, binding);
+			scope.problemReporter().nonStaticAccessToStaticMethod(this, binding);
+		}
+		if (!receiver.isImplicitThis() && binding.declaringClass != receiverType) {
+			scope.problemReporter().indirectAccessToStaticMethod(this, binding);
+		}		
+	}
+	if (arguments != null) {
+		for (int i = 0; i < arguments.length; i++) {
+			arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
+		}
+		if (argumentsCast) {
+			CastExpression.checkNeedForArgumentCasts(scope, this.receiver, receiverType, binding, this.arguments, argumentTypes, this);
 		}
 	}
-	if (arguments != null)
-		for (int i = 0; i < arguments.length; i++)
-			arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
-
 	//-------message send that are known to fail at compile time-----------
 	if (binding.isAbstract()) {
 		if (receiver.isSuper()) {
@@ -267,21 +304,7 @@
 	// ignore for here
 }
 
-public String toStringExpression(){
-	
-	String s = ""; //$NON-NLS-1$
-	if (!receiver.isImplicitThis())
-		s = s + receiver.toStringExpression()+"."; //$NON-NLS-1$
-	s = s + new String(selector) + "(" ; //$NON-NLS-1$
-	if (arguments != null)
-		for (int i = 0; i < arguments.length ; i ++)
-		{	s = s + arguments[i].toStringExpression();
-			if ( i != arguments.length -1 ) s = s + " , " ;};; //$NON-NLS-1$
-	s =s + ")" ; //$NON-NLS-1$
-	return s;
-}
-
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+public void traverse(ASTVisitor visitor, BlockScope blockScope) {
 	if (visitor.visit(this, blockScope)) {
 		receiver.traverse(visitor, blockScope);
 		if (arguments != null) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
index d63da92..a09eaf8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
@@ -12,7 +12,7 @@
 
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
@@ -65,8 +65,8 @@
 			if (statements != null) {
 				boolean didAlreadyComplain = false;
 				for (int i = 0, count = statements.length; i < count; i++) {
-					Statement stat;
-					if (!flowInfo.complainIfUnreachable((stat = statements[i]), scope, didAlreadyComplain)) {
+					Statement stat = statements[i];
+					if (!stat.complainIfUnreachable(flowInfo, scope, didAlreadyComplain)) {
 						flowInfo = stat.analyseCode(scope, methodContext, flowInfo);
 					} else {
 						didAlreadyComplain = true;
@@ -74,14 +74,16 @@
 				}
 			}
 			// check for missing returning path
-			TypeBinding returnType = binding.returnType;
-			if ((returnType == VoidBinding) || isAbstract()) {
+			TypeBinding returnTypeBinding = binding.returnType;
+			if ((returnTypeBinding == VoidBinding) || isAbstract()) {
 				this.needFreeReturn = flowInfo.isReachable();
 			} else {
 				if (flowInfo != FlowInfo.DEAD_END) { 
-					scope.problemReporter().shouldReturn(returnType, this);
+					scope.problemReporter().shouldReturn(returnTypeBinding, this);
 				}
 			}
+			// check unreachable catch blocks
+			methodContext.complainIfUnusedExceptionHandlers(this);
 		} catch (AbortMethod e) {
 			this.ignoreFurtherInvestigation = true;
 		}
@@ -95,6 +97,12 @@
 		parser.parse(this, unit);
 	}
 
+	public StringBuffer printReturnType(int indent, StringBuffer output) {
+
+		if (returnType == null) return output;
+		return returnType.printExpression(0, output).append(' ');
+	}
+
 	public void resolveStatements() {
 
 		// ========= abort on fatal error =============
@@ -106,9 +114,11 @@
 		if (binding != null && isTypeUseDeprecated(binding.returnType, scope))
 			scope.problemReporter().deprecatedType(binding.returnType, returnType);
 
-		if (CharOperation.equals(scope.enclosingSourceType().sourceName, selector))
+		// check if method with constructor name
+		if (CharOperation.equals(scope.enclosingSourceType().sourceName, selector)) {
 			scope.problemReporter().methodWithConstructorName(this);
-
+		}
+		
 		// by grammatical construction, interface methods are always abstract
 		if (!scope.enclosingSourceType().isInterface()){
 
@@ -127,15 +137,8 @@
 		super.resolveStatements(); 
 	}
 
-	public String returnTypeToString(int tab) {
-
-		if (returnType == null)
-			return ""; //$NON-NLS-1$
-		return returnType.toString(tab) + " "; //$NON-NLS-1$
-	}
-
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		ClassScope classScope) {
 
 		if (visitor.visit(this, classScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
index 027e12a..3edf351 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
@@ -52,7 +52,7 @@
 		return source;
 	}
 
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		visitor.visit(this, scope);
 		visitor.endVisit(this, scope);
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NumberLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NumberLiteral.java
index ed2d4bf..c9d36c2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NumberLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NumberLiteral.java
@@ -11,22 +11,26 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 public abstract class NumberLiteral extends Literal {
-	char[] source;
-public NumberLiteral(char[] token, int s, int e) {
-	this(s,e) ;
-	source = token ;
-}
-public NumberLiteral(int s, int e) {
-	super (s,e) ;
-}
-public boolean isValidJavaStatement(){
-	//should never be reach, but with a bug in the ast tree....
-	//see comment on the Statement class
-	
-	return false ;}
-public char[] source(){
-	return source;}
-public String toStringExpression(){
 
-	return new String(source);}
+	char[] source;
+	
+	public NumberLiteral(char[] token, int s, int e) {
+		
+		this(s,e) ;
+		source = token ;
+	}
+	
+	public NumberLiteral(int s, int e) {
+		super (s,e) ;
+	}
+	
+	public boolean isValidJavaStatement(){
+
+		return false ;
+	}
+	
+	public char[] source(){
+
+		return source;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
index 9c0f771..31159d3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -74,228 +74,195 @@
 
 	/**
 	 * Code generation for a binary operation
-	 *
-	 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
-	 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
-	 * @param valueRequired boolean
 	 */
-	public void generateCode(
-		BlockScope currentScope,
-		CodeStream codeStream,
-		boolean valueRequired) {
+	public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
 		int pc = codeStream.position;
-		Label falseLabel, endLabel;
 		if (constant != Constant.NotAConstant) {
+			// inlined value
 			if (valueRequired)
 				codeStream.generateConstant(constant, implicitConversion);
 			codeStream.recordPositionsFrom(pc, this.sourceStart);
 			return;
 		}
-		bits |= OnlyValueRequiredMASK;
-		generateOptimizedBoolean(
-			currentScope,
-			codeStream,
-			null,
-			(falseLabel = new Label(codeStream)),
-			valueRequired);
-		/*  improving code gen for such a case:		boolean b = i < 0 || true; 
-		 * since the label has never been used, we have the inlined value on the stack. */
-		if (falseLabel.hasForwardReferences()) {
-			if (valueRequired) {
-				codeStream.iconst_1();
-				if ((bits & ValueForReturnMASK) != 0) {
-					codeStream.ireturn();
-					falseLabel.place();
-					codeStream.iconst_0();
-				} else {
-					codeStream.goto_(endLabel = new Label(codeStream));
-					codeStream.decrStackSize(1);
-					falseLabel.place();
-					codeStream.iconst_0();
-					endLabel.place();
+		Constant cst = right.constant;
+		if (cst != NotAConstant) {
+			// <expr> || true --> true
+			if (cst.booleanValue() == true) {
+				this.left.generateCode(currentScope, codeStream, false);
+				if (valueRequired) codeStream.iconst_1();
+			} else {
+				// <expr>|| false --> <expr>
+				this.left.generateCode(currentScope, codeStream, valueRequired);
+			}
+			if (mergedInitStateIndex != -1) {
+				codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+			}			
+			codeStream.generateImplicitConversion(implicitConversion);
+			codeStream.updateLastRecordedEndPC(codeStream.position);
+			codeStream.recordPositionsFrom(pc, this.sourceStart);
+			return;
+		}
+		
+		Label trueLabel = new Label(codeStream), endLabel;
+		cst = left.optimizedBooleanConstant();
+		boolean leftIsConst = cst != NotAConstant;
+		boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
+
+		cst = right.optimizedBooleanConstant();
+		boolean rightIsConst = cst != NotAConstant;
+		boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
+
+		generateOperands : {
+			if (leftIsConst) {
+				left.generateCode(currentScope, codeStream, false);
+				if (leftIsTrue) {
+					break generateOperands; // no need to generate right operand
 				}
 			} else {
-				falseLabel.place();
+				left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, true); 
+				// need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1 
+			}
+			if (rightInitStateIndex != -1) {
+				codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+			}
+			if (rightIsConst) {
+				right.generateCode(currentScope, codeStream, false);
+			} else {
+				right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, valueRequired);
 			}
 		}
-		if (valueRequired) {
-			codeStream.generateImplicitConversion(implicitConversion);
+		if (mergedInitStateIndex != -1) {
+			codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
 		}
-		codeStream.recordPositionsFrom(pc, this.sourceStart);
+		/*
+		 * improving code gen for such a case: boolean b = i < 0 || true since
+		 * the label has never been used, we have the inlined value on the
+		 * stack.
+		 */
+		if (valueRequired) {
+			if (leftIsConst && leftIsTrue) {
+				codeStream.iconst_1();
+				codeStream.updateLastRecordedEndPC(codeStream.position);
+			} else {
+				if (rightIsConst && rightIsTrue) {
+					codeStream.iconst_1();
+					codeStream.updateLastRecordedEndPC(codeStream.position);
+				} else {
+					codeStream.iconst_0();
+				}
+				if (trueLabel.hasForwardReferences()) {
+					if ((bits & ValueForReturnMASK) != 0) {
+						codeStream.ireturn();
+						trueLabel.place();
+						codeStream.iconst_1();
+					} else {
+						codeStream.goto_(endLabel = new Label(codeStream));
+						codeStream.decrStackSize(1);
+						trueLabel.place();
+						codeStream.iconst_1();
+						endLabel.place();
+					}
+				} else {
+					trueLabel.place();
+				}
+			}
+			codeStream.generateImplicitConversion(implicitConversion);
+			codeStream.updateLastRecordedEndPC(codeStream.position);
+		} else {
+			trueLabel.place();
+		}
 	}
 
 	/**
-	 * Boolean operator code generation
-	 *	Optimized operations are: ||
+	 * Boolean operator code generation Optimized operations are: ||
 	 */
-	public void generateOptimizedBoolean(
-		BlockScope currentScope,
-		CodeStream codeStream,
-		Label trueLabel,
-		Label falseLabel,
-		boolean valueRequired) {
+	public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+
 		if (constant != Constant.NotAConstant) {
 			super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
 			return;
 		}
-		Constant condConst;
-		if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
-			if (condConst.booleanValue() == true) {
-				// <something equivalent to true> || x
-				left.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					trueLabel,
-					falseLabel,
-					false);
-				if (valueRequired) {
-					if ((bits & OnlyValueRequiredMASK) != 0) {
-						codeStream.iconst_1();
-					} else {
-						if (trueLabel != null) {
-							codeStream.goto_(trueLabel);
-						}
-					}
-				}
-				// reposition the endPC
-				codeStream.updateLastRecordedEndPC(codeStream.position);					
-			} else {
-				// <something equivalent to false> || x
-				left.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					trueLabel,
-					falseLabel,
-					false);
-				if (rightInitStateIndex != -1) {
-					codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
-				}
-				if ((bits & OnlyValueRequiredMASK) != 0) {
-					right.generateCode(currentScope, codeStream, valueRequired);
-				} else {
-					right.generateOptimizedBoolean(
-						currentScope,
-						codeStream,
-						trueLabel,
-						falseLabel,
-						valueRequired);
-				}
-			}
+
+		// <expr> || false --> <expr>
+		Constant cst = right.constant;
+		if (cst != NotAConstant && cst.booleanValue() == false) {
+			int pc = codeStream.position;
+			this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
 			if (mergedInitStateIndex != -1) {
-				codeStream.removeNotDefinitelyAssignedVariables(
-					currentScope,
-					mergedInitStateIndex);
-			}
+				codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+			}			
+			codeStream.recordPositionsFrom(pc, this.sourceStart);
 			return;
 		}
-		if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
-			if (condConst.booleanValue() == true) {
-				// x || <something equivalent to true>
-				Label internalFalseLabel = new Label(codeStream);
-				left.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					null,
-					internalFalseLabel, // will be true in the end
-					false);
-				if (rightInitStateIndex != -1) {
-					codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
-				}
-				internalFalseLabel.place();
-				right.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					trueLabel,
-					falseLabel,
-					false);
-				if (valueRequired) {
-					if ((bits & OnlyValueRequiredMASK) != 0) {
-						codeStream.iconst_1();
-					} else {
-						if (trueLabel != null) {
-							codeStream.goto_(trueLabel);
-						}
-					}
-				}
-				// reposition the endPC
-				codeStream.updateLastRecordedEndPC(codeStream.position);					
-			} else {
-				// x || <something equivalent to false>
-				if ((bits & OnlyValueRequiredMASK) != 0) {
-					left.generateCode(currentScope, codeStream, valueRequired);
-				} else {
-					left.generateOptimizedBoolean(
-						currentScope,
-						codeStream,
-						trueLabel,
-						falseLabel,
-						valueRequired);
-				}
-				if (rightInitStateIndex != -1) {
-					codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
-				}
-				right.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					trueLabel,
-					falseLabel,
-					false);
-			}
-			if (mergedInitStateIndex != -1) {
-				codeStream.removeNotDefinitelyAssignedVariables(
-					currentScope,
-					mergedInitStateIndex);
-			}
-			return;
-		}
+	
+		cst = left.optimizedBooleanConstant();
+		boolean leftIsConst = cst != NotAConstant;
+		boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
+
+		cst = right.optimizedBooleanConstant();
+		boolean rightIsConst = cst != NotAConstant;
+		boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
+
 		// default case
-		if (falseLabel == null) {
-			if (trueLabel != null) {
-				// implicit falling through the FALSE case
-				left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, true);
-				right.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					trueLabel,
-					null,
-					valueRequired);
-			}
-		} else {
-			// implicit falling through the TRUE case
-			if (trueLabel == null) {
-				Label internalTrueLabel = new Label(codeStream);
-				left.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					internalTrueLabel,
-					null,
-					true);
-				if (rightInitStateIndex != -1) {
-					codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+		generateOperands : {
+			if (falseLabel == null) {
+				if (trueLabel != null) {
+					// implicit falling through the FALSE case
+					left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, !leftIsConst); 
+					// need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1
+					if (leftIsConst && leftIsTrue) {
+						codeStream.goto_(trueLabel);
+						codeStream.updateLastRecordedEndPC(codeStream.position);
+						break generateOperands; // no need to generate right operand
+					}
+					if (rightInitStateIndex != -1) {
+						codeStream
+								.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+					}
+					right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, valueRequired && !rightIsConst);
+					if (valueRequired && rightIsConst && rightIsTrue) {
+						codeStream.goto_(trueLabel);
+						codeStream.updateLastRecordedEndPC(codeStream.position);
+					}
 				}
-				right.generateOptimizedBoolean(
-					currentScope,
-					codeStream,
-					null,
-					falseLabel,
-					valueRequired);
-				internalTrueLabel.place();
 			} else {
-				// no implicit fall through TRUE/FALSE --> should never occur
+				// implicit falling through the TRUE case
+				if (trueLabel == null) {
+					Label internalTrueLabel = new Label(codeStream);
+					left.generateOptimizedBoolean(currentScope, codeStream, internalTrueLabel, null, !leftIsConst); 
+					// need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1
+					if (leftIsConst && leftIsTrue) {
+						internalTrueLabel.place();
+						break generateOperands; // no need to generate right operand
+					}
+					if (rightInitStateIndex != -1) {
+						codeStream
+								.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+					}
+					right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired && !rightIsConst);
+					if (valueRequired && rightIsConst) {
+						if (!rightIsTrue) {
+							codeStream.goto_(falseLabel);
+							codeStream.updateLastRecordedEndPC(codeStream.position);
+						}
+					}
+					internalTrueLabel.place();
+				} else {
+					// no implicit fall through TRUE/FALSE --> should never occur
+				}
 			}
 		}
 		if (mergedInitStateIndex != -1) {
-			codeStream.removeNotDefinitelyAssignedVariables(
-				currentScope,
-				mergedInitStateIndex);
+			codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
 		}
 	}
-
+	
 	public boolean isCompactableOperation() {
 		return false;
 	}
 
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		if (visitor.visit(this, scope)) {
 			left.traverse(visitor, scope);
 			right.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
index c98285a..90d1572 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
@@ -12,7 +12,7 @@
 
 public abstract class OperatorExpression extends Expression implements OperatorIds {
 
-	public static int[][] ResolveTypeTables = new int[NumberOfTables][];
+	public static int[][] OperatorSignatures = new int[NumberOfTables][];
 
 	static {classInitialize();}
 
@@ -23,24 +23,24 @@
 		super();
 	}
 	public static final void classInitialize() {
-		ResolveTypeTables[AND] = get_AND();
-		ResolveTypeTables[AND_AND] = get_AND_AND();
-		ResolveTypeTables[DIVIDE] = get_DIVIDE();
-		ResolveTypeTables[EQUAL_EQUAL] = get_EQUAL_EQUAL();
-		ResolveTypeTables[GREATER] = get_GREATER();
-		ResolveTypeTables[GREATER_EQUAL] = get_GREATER_EQUAL();
-		ResolveTypeTables[LEFT_SHIFT] = get_LEFT_SHIFT();
-		ResolveTypeTables[LESS] = get_LESS();
-		ResolveTypeTables[LESS_EQUAL] = get_LESS_EQUAL();
-		ResolveTypeTables[MINUS] = get_MINUS();
-		ResolveTypeTables[MULTIPLY] = get_MULTIPLY();
-		ResolveTypeTables[OR] = get_OR();
-		ResolveTypeTables[OR_OR] = get_OR_OR();
-		ResolveTypeTables[PLUS] = get_PLUS();
-		ResolveTypeTables[REMAINDER] = get_REMAINDER();
-		ResolveTypeTables[RIGHT_SHIFT] = get_RIGHT_SHIFT();
-		ResolveTypeTables[UNSIGNED_RIGHT_SHIFT] = get_UNSIGNED_RIGHT_SHIFT();
-		ResolveTypeTables[XOR] = get_XOR();
+		OperatorSignatures[AND] = get_AND();
+		OperatorSignatures[AND_AND] = get_AND_AND();
+		OperatorSignatures[DIVIDE] = get_DIVIDE();
+		OperatorSignatures[EQUAL_EQUAL] = get_EQUAL_EQUAL();
+		OperatorSignatures[GREATER] = get_GREATER();
+		OperatorSignatures[GREATER_EQUAL] = get_GREATER_EQUAL();
+		OperatorSignatures[LEFT_SHIFT] = get_LEFT_SHIFT();
+		OperatorSignatures[LESS] = get_LESS();
+		OperatorSignatures[LESS_EQUAL] = get_LESS_EQUAL();
+		OperatorSignatures[MINUS] = get_MINUS();
+		OperatorSignatures[MULTIPLY] = get_MULTIPLY();
+		OperatorSignatures[OR] = get_OR();
+		OperatorSignatures[OR_OR] = get_OR_OR();
+		OperatorSignatures[PLUS] = get_PLUS();
+		OperatorSignatures[REMAINDER] = get_REMAINDER();
+		OperatorSignatures[RIGHT_SHIFT] = get_RIGHT_SHIFT();
+		OperatorSignatures[UNSIGNED_RIGHT_SHIFT] = get_UNSIGNED_RIGHT_SHIFT();
+		OperatorSignatures[XOR] = get_XOR();
 	}
 
 	public static final String generateTableTestCase(){
@@ -59,14 +59,14 @@
 		class Decode {
 			public  final String constant(int code){
 				switch(code){ 
-					case T_boolean 	: return "true" ; //$NON-NLS-1$
-					case T_byte		: return "((byte) 3)" ; //$NON-NLS-1$
-					case T_char		: return "'A'" ; //$NON-NLS-1$
-					case T_double	: return "300.0d" ; //$NON-NLS-1$
-					case T_float	: return "100.0f" ; //$NON-NLS-1$
-					case T_int		: return "1" ; //$NON-NLS-1$
-					case T_long		: return "7L" ; //$NON-NLS-1$
-					case T_String	: return "\"hello-world\"" ; //$NON-NLS-1$
+					case T_boolean 	: return "true"; //$NON-NLS-1$
+					case T_byte		: return "((byte) 3)"; //$NON-NLS-1$
+					case T_char		: return "'A'"; //$NON-NLS-1$
+					case T_double	: return "300.0d"; //$NON-NLS-1$
+					case T_float	: return "100.0f"; //$NON-NLS-1$
+					case T_int		: return "1"; //$NON-NLS-1$
+					case T_long		: return "7L"; //$NON-NLS-1$
+					case T_String	: return "\"hello-world\""; //$NON-NLS-1$
 					case T_null		: return "null"; //$NON-NLS-1$
 					case T_short	: return "((short) 5)"; //$NON-NLS-1$
 					case T_Object	: return "null";} //$NON-NLS-1$
@@ -74,14 +74,14 @@
 	
 			public  final String type(int code){
 				switch(code){ 
-					case T_boolean 	: return "z" ; //$NON-NLS-1$
-					case T_byte		: return "b" ; //$NON-NLS-1$
-					case T_char		: return "c" ; //$NON-NLS-1$
-					case T_double	: return "d" ; //$NON-NLS-1$
-					case T_float	: return "f" ; //$NON-NLS-1$
-					case T_int		: return "i" ; //$NON-NLS-1$
-					case T_long		: return "l" ; //$NON-NLS-1$
-					case T_String	: return "str" ; //$NON-NLS-1$
+					case T_boolean 	: return "z"; //$NON-NLS-1$
+					case T_byte		: return "b"; //$NON-NLS-1$
+					case T_char		: return "c"; //$NON-NLS-1$
+					case T_double	: return "d"; //$NON-NLS-1$
+					case T_float	: return "f"; //$NON-NLS-1$
+					case T_int		: return "i"; //$NON-NLS-1$
+					case T_long		: return "l"; //$NON-NLS-1$
+					case T_String	: return "str"; //$NON-NLS-1$
 					case T_null		: return "null"; //$NON-NLS-1$
 					case T_short	: return "s"; //$NON-NLS-1$
 					case T_Object	: return "obj";} //$NON-NLS-1$
@@ -108,13 +108,13 @@
 					case TWIDDLE :		return "~"; //$NON-NLS-1$
 					case DIVIDE :		return "/"; //$NON-NLS-1$
 					case GREATER :		return ">"; //$NON-NLS-1$
-					case LESS :			return "<";	}; //$NON-NLS-1$
+					case LESS :			return "<";	} //$NON-NLS-1$
 				return "????";} //$NON-NLS-1$
 		}
 	
 			
 		Decode decode = new Decode();
-		String s ;
+		String s;
 	
 		s = "\tpublic static void binaryOperationTablesTestCase(){\n" + //$NON-NLS-1$
 	
@@ -122,24 +122,24 @@
 			"\t\t//method automatically generated by\n"+ //$NON-NLS-1$
 			"\t\t//org.eclipse.jdt.internal.compiler.ast.OperatorExpression.generateTableTestCase();\n"+ //$NON-NLS-1$
 		
-			"\t\tString str0 ;\t String str\t= "+decode.constant(T_String)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
-			"\t\tint i0 ;\t int i\t= "+decode.constant(T_int)+" ;\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+			"\t\tString str0;\t String str\t= "+decode.constant(T_String)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+			"\t\tint i0;\t int i\t= "+decode.constant(T_int)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
 			"\t\tboolean z0;\t boolean z\t= "+decode.constant(T_boolean)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
-			"\t\tchar c0; \t char  c\t= "+decode.constant(T_char)+" ;\n"+ //$NON-NLS-1$ //$NON-NLS-2$
-			"\t\tfloat f0; \t float f\t= "+decode.constant(T_float)+" ;\n"+ //$NON-NLS-1$ //$NON-NLS-2$
-			"\t\tdouble d0;\t double d\t= "+decode.constant(T_double)+" ;\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+			"\t\tchar c0; \t char  c\t= "+decode.constant(T_char)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+			"\t\tfloat f0; \t float f\t= "+decode.constant(T_float)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+			"\t\tdouble d0;\t double d\t= "+decode.constant(T_double)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
 			"\t\tbyte b0; \t byte b\t= "+decode.constant(T_byte)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
 			"\t\tshort s0; \t short s\t= "+decode.constant(T_short)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
-			"\t\tlong l0; \t long l\t= "+decode.constant(T_long)+" ;\n"+ //$NON-NLS-1$ //$NON-NLS-2$
-			"\t\tObject obj0; \t Object obj\t= "+decode.constant(T_Object)+" ;\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+			"\t\tlong l0; \t long l\t= "+decode.constant(T_long)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+			"\t\tObject obj0; \t Object obj\t= "+decode.constant(T_Object)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
 			"\n"; //$NON-NLS-1$
 	
 		int error = 0;		
-		for (int i=0; i < operators.length ; i++)
+		for (int i=0; i < operators.length; i++)
 		{	int operator = operators[i];
 			for (int left=0; left<16;left++)
 			for (int right=0; right<16;right++)
-			{	int result = (ResolveTypeTables[operator][(left<<4)+right]) & 0x0000F;
+			{	int result = (OperatorSignatures[operator][(left<<4)+right]) & 0x0000F;
 				if (result != T_undefined)
 	
 					//1/ First regular computation then 2/ comparaison
@@ -151,7 +151,7 @@
 				{	s += "\t\t"+decode.type(result)+"0"+" = "+decode.type(left); //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$
 					s += " "+decode.operator(operator)+" "+decode.type(right)+";\n"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
 					String begin = result == T_String ? "\t\tif (! " : "\t\tif ( "; //$NON-NLS-2$ //$NON-NLS-1$
-					String test = result == T_String ? ".equals(" : " != (" ; //$NON-NLS-2$ //$NON-NLS-1$
+					String test = result == T_String ? ".equals(" : " != ("; //$NON-NLS-2$ //$NON-NLS-1$
 					s += begin	+decode.type(result)+"0"+test //$NON-NLS-1$
 								+decode.constant(left)+" " //$NON-NLS-1$
 								+decode.operator(operator)+" " //$NON-NLS-1$
@@ -162,7 +162,7 @@
 				}
 			}
 			
-		return s += "\n\t\tSystem.out.println(\"binary tables test : done\");}" ; //$NON-NLS-1$
+		return s += "\n\t\tSystem.out.println(\"binary tables test : done\");}"; //$NON-NLS-1$
 	}
 
 	public static final int[] get_AND(){
@@ -172,191 +172,191 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		int[] table  = new int[16*16] ;
+		int[] table  = new int[16*16];
 		
-		//	table[(T_undefined<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_undefined<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_long] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_short] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_void] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_String] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_double] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_float] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_char] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_int] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_null] 			= T_undefined ;
+		//	table[(T_undefined<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_undefined<<4)+T_byte] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_long] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_short] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_void] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_String] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_Object] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_double] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_float] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_char] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_int] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_byte<<4)+T_undefined] 	= T_undefined ;
-		table[(T_byte<<4)+T_byte] 		= (Byte2Int<<12) +(Byte2Int<<4) +T_int ;
-		table[(T_byte<<4)+T_long]		= (Byte2Long<<12)+(Long2Long<<4)+T_long ;
+		//	table[(T_byte<<4)+T_undefined] 	= T_undefined;
+		table[(T_byte<<4)+T_byte] 		= (Byte2Int<<12) +(Byte2Int<<4) +T_int;
+		table[(T_byte<<4)+T_long]		= (Byte2Long<<12)+(Long2Long<<4)+T_long;
 		table[(T_byte<<4)+T_short] 		= (Byte2Int<<12) +(Short2Int<<4)+T_int;
-		//	table[(T_byte<<4)+T_void] 		= T_undefined ;
-		//	table[(T_byte<<4)+T_String] 	= T_undefined ;
-		//	table[(T_byte<<4)+T_Object] 	= T_undefined ;
-		//	table[(T_byte<<4)+T_double] 	= T_undefined ;
-		//	table[(T_byte<<4)+T_float] 		= T_undefined ;
-		//	table[(T_byte<<4)+T_boolean] 	= T_undefined ;
-		table[(T_byte<<4)+T_char] 		= (Byte2Int<<12) +(Char2Int<<4) +T_int ;
-		table[(T_byte<<4)+T_int] 		= (Byte2Int<<12) +(Int2Int<<4)  +T_int ;
-		//	table[(T_byte<<4)+T_null] 		= T_undefined ;
+		//	table[(T_byte<<4)+T_void] 		= T_undefined;
+		//	table[(T_byte<<4)+T_String] 	= T_undefined;
+		//	table[(T_byte<<4)+T_Object] 	= T_undefined;
+		//	table[(T_byte<<4)+T_double] 	= T_undefined;
+		//	table[(T_byte<<4)+T_float] 		= T_undefined;
+		//	table[(T_byte<<4)+T_boolean] 	= T_undefined;
+		table[(T_byte<<4)+T_char] 		= (Byte2Int<<12) +(Char2Int<<4) +T_int;
+		table[(T_byte<<4)+T_int] 		= (Byte2Int<<12) +(Int2Int<<4)  +T_int;
+		//	table[(T_byte<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_long<<4)+T_undefined] 	= T_undefined ;
+		//	table[(T_long<<4)+T_undefined] 	= T_undefined;
 		table[(T_long<<4)+T_byte] 		= (Long2Long<<12)+(Byte2Long<<4)+T_long;
-		table[(T_long<<4)+T_long] 		= (Long2Long<<12)+(Long2Long<<4)+T_long ;
-		table[(T_long<<4)+T_short] 		= (Long2Long<<12)+(Short2Long<<4)+T_long; ;
-		//	table[(T_long<<4)+T_void] 		= T_undefined ;
-		//	table[(T_long<<4)+T_String] 	= T_undefined ;
-		//	table[(T_long<<4)+T_Object] 	= T_undefined ;
-		//	table[(T_long<<4)+T_double] 	= T_undefined ;
-		//	table[(T_long<<4)+T_float] 		= T_undefined ;
-		//	table[(T_long<<4)+T_boolean] 	= T_undefined ;
-		table[(T_long<<4)+T_char] 		= (Long2Long<<12)+(Char2Long<<4)+T_long ;
-		table[(T_long<<4)+T_int] 		= (Long2Long<<12)+(Int2Long<<4)+T_long ;
-		//	table[(T_long<<4)+T_null] 		= T_undefined ;
+		table[(T_long<<4)+T_long] 		= (Long2Long<<12)+(Long2Long<<4)+T_long;
+		table[(T_long<<4)+T_short] 		= (Long2Long<<12)+(Short2Long<<4)+T_long;
+		//	table[(T_long<<4)+T_void] 		= T_undefined;
+		//	table[(T_long<<4)+T_String] 	= T_undefined;
+		//	table[(T_long<<4)+T_Object] 	= T_undefined;
+		//	table[(T_long<<4)+T_double] 	= T_undefined;
+		//	table[(T_long<<4)+T_float] 		= T_undefined;
+		//	table[(T_long<<4)+T_boolean] 	= T_undefined;
+		table[(T_long<<4)+T_char] 		= (Long2Long<<12)+(Char2Long<<4)+T_long;
+		table[(T_long<<4)+T_int] 		= (Long2Long<<12)+(Int2Long<<4)+T_long;
+		//	table[(T_long<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_short<<4)+T_undefined] 	= T_undefined ;
-		table[(T_short<<4)+T_byte] 			= (Short2Int<<12)+(Byte2Int<<4)+T_int ;
-		table[(T_short<<4)+T_long] 			= (Short2Long<<12)+(Long2Long<<4)+T_long ;
-		table[(T_short<<4)+T_short] 		= (Short2Int<<12)+(Short2Int<<4)+T_int ;
-		//	table[(T_short<<4)+T_void] 			= T_undefined ;
-		//	table[(T_short<<4)+T_String] 		= T_undefined ;
-		//	table[(T_short<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_short<<4)+T_double] 		= T_undefined ;
-		//	table[(T_short<<4)+T_float] 		= T_undefined ;
-		//	table[(T_short<<4)+T_boolean] 		= T_undefined ;
-		table[(T_short<<4)+T_char] 			= (Short2Int<<12)+(Char2Int<<4)+T_int ;
-		table[(T_short<<4)+T_int] 			= (Short2Int<<12)+(Int2Int<<4)+T_int ;
-		//	table[(T_short<<4)+T_null] 			= T_undefined ;
+		//	table[(T_short<<4)+T_undefined] 	= T_undefined;
+		table[(T_short<<4)+T_byte] 			= (Short2Int<<12)+(Byte2Int<<4)+T_int;
+		table[(T_short<<4)+T_long] 			= (Short2Long<<12)+(Long2Long<<4)+T_long;
+		table[(T_short<<4)+T_short] 		= (Short2Int<<12)+(Short2Int<<4)+T_int;
+		//	table[(T_short<<4)+T_void] 			= T_undefined;
+		//	table[(T_short<<4)+T_String] 		= T_undefined;
+		//	table[(T_short<<4)+T_Object] 		= T_undefined;
+		//	table[(T_short<<4)+T_double] 		= T_undefined;
+		//	table[(T_short<<4)+T_float] 		= T_undefined;
+		//	table[(T_short<<4)+T_boolean] 		= T_undefined;
+		table[(T_short<<4)+T_char] 			= (Short2Int<<12)+(Char2Int<<4)+T_int;
+		table[(T_short<<4)+T_int] 			= (Short2Int<<12)+(Int2Int<<4)+T_int;
+		//	table[(T_short<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_void<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_void<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_void<<4)+T_long] 		= T_undefined ;
-		//	table[(T_void<<4)+T_short] 		= T_undefined ;
-		//	table[(T_void<<4)+T_void] 		= T_undefined ;
-		//	table[(T_void<<4)+T_String] 	= T_undefined ;
-		//	table[(T_void<<4)+T_Object] 	= T_undefined ;
-		//	table[(T_void<<4)+T_double] 	= T_undefined ;
-		//	table[(T_void<<4)+T_float] 		= T_undefined ;
-		//	table[(T_void<<4)+T_boolean] 	= T_undefined ;
-		//	table[(T_void<<4)+T_char] 		= T_undefined ;
-		//	table[(T_void<<4)+T_int] 		= T_undefined ;
-		//	table[(T_void<<4)+T_null] 		= T_undefined ;
+		//	table[(T_void<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_void<<4)+T_byte] 		= T_undefined;
+		//	table[(T_void<<4)+T_long] 		= T_undefined;
+		//	table[(T_void<<4)+T_short] 		= T_undefined;
+		//	table[(T_void<<4)+T_void] 		= T_undefined;
+		//	table[(T_void<<4)+T_String] 	= T_undefined;
+		//	table[(T_void<<4)+T_Object] 	= T_undefined;
+		//	table[(T_void<<4)+T_double] 	= T_undefined;
+		//	table[(T_void<<4)+T_float] 		= T_undefined;
+		//	table[(T_void<<4)+T_boolean] 	= T_undefined;
+		//	table[(T_void<<4)+T_char] 		= T_undefined;
+		//	table[(T_void<<4)+T_int] 		= T_undefined;
+		//	table[(T_void<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_String<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_String<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_String<<4)+T_long] 		= T_undefined ;
-		//	table[(T_String<<4)+T_short] 		= T_undefined ;
-		//	table[(T_String<<4)+T_void] 		= T_undefined ;
-		//	table[(T_String<<4)+T_String] 		= T_undefined ;
-		//	table[(T_String<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_String<<4)+T_double] 		= T_undefined ;
-		//	table[(T_String<<4)+T_float] 		= T_undefined ;
-		//	table[(T_String<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_String<<4)+T_char] 		= T_undefined ;
-		//	table[(T_String<<4)+T_int] 			= T_undefined ;
-		//	table[(T_String<<4)+T_null] 		= T_undefined ;
+		//	table[(T_String<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_String<<4)+T_byte] 		= T_undefined;
+		//	table[(T_String<<4)+T_long] 		= T_undefined;
+		//	table[(T_String<<4)+T_short] 		= T_undefined;
+		//	table[(T_String<<4)+T_void] 		= T_undefined;
+		//	table[(T_String<<4)+T_String] 		= T_undefined;
+		//	table[(T_String<<4)+T_Object] 		= T_undefined;
+		//	table[(T_String<<4)+T_double] 		= T_undefined;
+		//	table[(T_String<<4)+T_float] 		= T_undefined;
+		//	table[(T_String<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_String<<4)+T_char] 		= T_undefined;
+		//	table[(T_String<<4)+T_int] 			= T_undefined;
+		//	table[(T_String<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_Object<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_Object<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_long] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_short]		= T_undefined ;
-		//	table[(T_Object<<4)+T_void] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_String] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_double] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_float] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_boolean]		= T_undefined ;
-		//	table[(T_Object<<4)+T_char] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_int] 			= T_undefined ;
-		//	table[(T_Object<<4)+T_null] 		= T_undefined ;
+		//	table[(T_Object<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_Object<<4)+T_byte] 		= T_undefined;
+		//	table[(T_Object<<4)+T_long] 		= T_undefined;
+		//	table[(T_Object<<4)+T_short]		= T_undefined;
+		//	table[(T_Object<<4)+T_void] 		= T_undefined;
+		//	table[(T_Object<<4)+T_String] 		= T_undefined;
+		//	table[(T_Object<<4)+T_Object] 		= T_undefined;
+		//	table[(T_Object<<4)+T_double] 		= T_undefined;
+		//	table[(T_Object<<4)+T_float] 		= T_undefined;
+		//	table[(T_Object<<4)+T_boolean]		= T_undefined;
+		//	table[(T_Object<<4)+T_char] 		= T_undefined;
+		//	table[(T_Object<<4)+T_int] 			= T_undefined;
+		//	table[(T_Object<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_double<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_double<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_double<<4)+T_long] 		= T_undefined ;
-		//	table[(T_double<<4)+T_short] 		= T_undefined ;
-		//	table[(T_double<<4)+T_void] 		= T_undefined ;
-		//	table[(T_double<<4)+T_String] 		= T_undefined ;
-		//	table[(T_double<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_double<<4)+T_double] 		= T_undefined ;
-		//	table[(T_double<<4)+T_float] 		= T_undefined ;
-		//	table[(T_double<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_double<<4)+T_char] 		= T_undefined ;
+		//	table[(T_double<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_double<<4)+T_byte] 		= T_undefined;
+		//	table[(T_double<<4)+T_long] 		= T_undefined;
+		//	table[(T_double<<4)+T_short] 		= T_undefined;
+		//	table[(T_double<<4)+T_void] 		= T_undefined;
+		//	table[(T_double<<4)+T_String] 		= T_undefined;
+		//	table[(T_double<<4)+T_Object] 		= T_undefined;
+		//	table[(T_double<<4)+T_double] 		= T_undefined;
+		//	table[(T_double<<4)+T_float] 		= T_undefined;
+		//	table[(T_double<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_double<<4)+T_char] 		= T_undefined;
 		//	table[(T_double<<4)+T_int] 			= T_undefined;
-		//	table[(T_double<<4)+T_null] 		= T_undefined ;
+		//	table[(T_double<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_float<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_float<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_float<<4)+T_long] 			= T_undefined ;
-		//	table[(T_float<<4)+T_short] 		= T_undefined ;
-		//	table[(T_float<<4)+T_void] 			= T_undefined ;
-		//	table[(T_float<<4)+T_String] 		= T_undefined ;
-		//	table[(T_float<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_float<<4)+T_double] 		= T_undefined ;
-		//	table[(T_float<<4)+T_float] 		= T_undefined ;
-		//	table[(T_float<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_float<<4)+T_char] 			= T_undefined ;
-		//	table[(T_float<<4)+T_int] 			= T_undefined ;
-		//	table[(T_float<<4)+T_null] 			= T_undefined ;
+		//	table[(T_float<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_float<<4)+T_byte] 			= T_undefined;
+		//	table[(T_float<<4)+T_long] 			= T_undefined;
+		//	table[(T_float<<4)+T_short] 		= T_undefined;
+		//	table[(T_float<<4)+T_void] 			= T_undefined;
+		//	table[(T_float<<4)+T_String] 		= T_undefined;
+		//	table[(T_float<<4)+T_Object] 		= T_undefined;
+		//	table[(T_float<<4)+T_double] 		= T_undefined;
+		//	table[(T_float<<4)+T_float] 		= T_undefined;
+		//	table[(T_float<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_float<<4)+T_char] 			= T_undefined;
+		//	table[(T_float<<4)+T_int] 			= T_undefined;
+		//	table[(T_float<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_boolean<<4)+T_undefined] 		= T_undefined ;
-		//	table[(T_boolean<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_long] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_short] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_void] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_String] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_Object] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_double] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_float] 			= T_undefined ;
-		table[(T_boolean<<4)+T_boolean] 		= (Boolean2Boolean << 12)+(Boolean2Boolean << 4)+T_boolean ;
-		//	table[(T_boolean<<4)+T_char] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_int] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_null] 			= T_undefined ;
+		//	table[(T_boolean<<4)+T_undefined] 		= T_undefined;
+		//	table[(T_boolean<<4)+T_byte] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_long] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_short] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_void] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_String] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_Object] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_double] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_float] 			= T_undefined;
+		table[(T_boolean<<4)+T_boolean] 		= (Boolean2Boolean << 12)+(Boolean2Boolean << 4)+T_boolean;
+		//	table[(T_boolean<<4)+T_char] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_int] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_null] 			= T_undefined;
 			
-		//	table[(T_char<<4)+T_undefined] 		= T_undefined ;
-		table[(T_char<<4)+T_byte] 			= (Char2Int<<12)+(Byte2Int<<4)+T_int ;
+		//	table[(T_char<<4)+T_undefined] 		= T_undefined;
+		table[(T_char<<4)+T_byte] 			= (Char2Int<<12)+(Byte2Int<<4)+T_int;
 		table[(T_char<<4)+T_long] 			= (Char2Long<<12)+(Long2Long<<4)+T_long;
-		table[(T_char<<4)+T_short] 			= (Char2Int<<12)+(Short2Int<<4)+T_int ;
-		//	table[(T_char<<4)+T_void] 			= T_undefined ;
-		//	table[(T_char<<4)+T_String] 		= T_undefined ;
-		//	table[(T_char<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_char<<4)+T_double] 		= T_undefined ;
-		//	table[(T_char<<4)+T_float] 			= T_undefined ;
-		//	table[(T_char<<4)+T_boolean] 		= T_undefined ;
-		table[(T_char<<4)+T_char] 			= (Char2Int<<12)+(Char2Int<<4)+T_int ;
-		table[(T_char<<4)+T_int] 			= (Char2Int<<12)+(Int2Int<<4)+T_int ;
-		//	table[(T_char<<4)+T_null] 			= T_undefined ;
+		table[(T_char<<4)+T_short] 			= (Char2Int<<12)+(Short2Int<<4)+T_int;
+		//	table[(T_char<<4)+T_void] 			= T_undefined;
+		//	table[(T_char<<4)+T_String] 		= T_undefined;
+		//	table[(T_char<<4)+T_Object] 		= T_undefined;
+		//	table[(T_char<<4)+T_double] 		= T_undefined;
+		//	table[(T_char<<4)+T_float] 			= T_undefined;
+		//	table[(T_char<<4)+T_boolean] 		= T_undefined;
+		table[(T_char<<4)+T_char] 			= (Char2Int<<12)+(Char2Int<<4)+T_int;
+		table[(T_char<<4)+T_int] 			= (Char2Int<<12)+(Int2Int<<4)+T_int;
+		//	table[(T_char<<4)+T_null] 			= T_undefined;
 			
-		//	table[(T_int<<4)+T_undefined] 	= T_undefined ;
-		table[(T_int<<4)+T_byte] 		= (Int2Int<<12)+(Byte2Int<<4)+T_int ;
-		table[(T_int<<4)+T_long] 		= (Int2Long<<12)+(Long2Long<<4)+T_long ;
-		table[(T_int<<4)+T_short] 		= (Int2Int<<12)+(Short2Int<<4)+T_int ;
-		//	table[(T_int<<4)+T_void] 		= T_undefined ;
-		//	table[(T_int<<4)+T_String] 		= T_undefined ;
-		//	table[(T_int<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_int<<4)+T_double] 		= T_undefined ;
-		//	table[(T_int<<4)+T_float] 		= T_undefined ;
-		//	table[(T_int<<4)+T_boolean] 	= T_undefined ;
-		table[(T_int<<4)+T_char] 		= (Int2Int<<12)+(Char2Int<<4)+T_int ;
-		table[(T_int<<4)+T_int] 		= (Int2Int<<12)+(Int2Int<<4)+T_int ;
-		//	table[(T_int<<4)+T_null] 		= T_undefined ;
+		//	table[(T_int<<4)+T_undefined] 	= T_undefined;
+		table[(T_int<<4)+T_byte] 		= (Int2Int<<12)+(Byte2Int<<4)+T_int;
+		table[(T_int<<4)+T_long] 		= (Int2Long<<12)+(Long2Long<<4)+T_long;
+		table[(T_int<<4)+T_short] 		= (Int2Int<<12)+(Short2Int<<4)+T_int;
+		//	table[(T_int<<4)+T_void] 		= T_undefined;
+		//	table[(T_int<<4)+T_String] 		= T_undefined;
+		//	table[(T_int<<4)+T_Object] 		= T_undefined;
+		//	table[(T_int<<4)+T_double] 		= T_undefined;
+		//	table[(T_int<<4)+T_float] 		= T_undefined;
+		//	table[(T_int<<4)+T_boolean] 	= T_undefined;
+		table[(T_int<<4)+T_char] 		= (Int2Int<<12)+(Char2Int<<4)+T_int;
+		table[(T_int<<4)+T_int] 		= (Int2Int<<12)+(Int2Int<<4)+T_int;
+		//	table[(T_int<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_null<<4)+T_undefined] 		= T_undefined ;
-		//	table[(T_null<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_null<<4)+T_long] 			= T_undefined ;
-		//	table[(T_null<<4)+T_short] 			= T_undefined ;
-		//	table[(T_null<<4)+T_void] 			= T_undefined ;
-		//	table[(T_null<<4)+T_String] 		= T_undefined ;
-		//	table[(T_null<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_null<<4)+T_double] 		= T_undefined ;
-		//	table[(T_null<<4)+T_float] 			= T_undefined ;
-		//	table[(T_null<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_null<<4)+T_char] 			= T_undefined ;
-		//	table[(T_null<<4)+T_int] 			= T_undefined ;
-		//	table[(T_null<<4)+T_null] 			= T_undefined ;
+		//	table[(T_null<<4)+T_undefined] 		= T_undefined;
+		//	table[(T_null<<4)+T_byte] 			= T_undefined;
+		//	table[(T_null<<4)+T_long] 			= T_undefined;
+		//	table[(T_null<<4)+T_short] 			= T_undefined;
+		//	table[(T_null<<4)+T_void] 			= T_undefined;
+		//	table[(T_null<<4)+T_String] 		= T_undefined;
+		//	table[(T_null<<4)+T_Object] 		= T_undefined;
+		//	table[(T_null<<4)+T_double] 		= T_undefined;
+		//	table[(T_null<<4)+T_float] 			= T_undefined;
+		//	table[(T_null<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_null<<4)+T_char] 			= T_undefined;
+		//	table[(T_null<<4)+T_int] 			= T_undefined;
+		//	table[(T_null<<4)+T_null] 			= T_undefined;
 	
-		return table ;
+		return table;
 	}
 
 	public static final int[] get_AND_AND(){
@@ -366,190 +366,190 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		int[] table  = new int[16*16] ;
+		int[] table  = new int[16*16];
 		
-		//     table[(T_undefined<<4)+T_undefined] 		= T_undefined ;
-		//     table[(T_undefined<<4)+T_byte] 			= T_undefined ;
-		//     table[(T_undefined<<4)+T_long] 			= T_undefined ;
-		//     table[(T_undefined<<4)+T_short] 			= T_undefined ;
-		//     table[(T_undefined<<4)+T_void] 			= T_undefined ;
-		//     table[(T_undefined<<4)+T_String] 		= T_undefined ;
-		//     table[(T_undefined<<4)+T_Object] 		= T_undefined ;
-		//     table[(T_undefined<<4)+T_double] 		= T_undefined ;
-		//     table[(T_undefined<<4)+T_float] 			= T_undefined ;
-		//     table[(T_undefined<<4)+T_boolean] 		= T_undefined ;
-		//     table[(T_undefined<<4)+T_char] 			= T_undefined ;
-		//     table[(T_undefined<<4)+T_int] 			= T_undefined ;
-		//     table[(T_undefined<<4)+T_null] 			= T_undefined ;
+		//     table[(T_undefined<<4)+T_undefined] 		= T_undefined;
+		//     table[(T_undefined<<4)+T_byte] 			= T_undefined;
+		//     table[(T_undefined<<4)+T_long] 			= T_undefined;
+		//     table[(T_undefined<<4)+T_short] 			= T_undefined;
+		//     table[(T_undefined<<4)+T_void] 			= T_undefined;
+		//     table[(T_undefined<<4)+T_String] 		= T_undefined;
+		//     table[(T_undefined<<4)+T_Object] 		= T_undefined;
+		//     table[(T_undefined<<4)+T_double] 		= T_undefined;
+		//     table[(T_undefined<<4)+T_float] 			= T_undefined;
+		//     table[(T_undefined<<4)+T_boolean] 		= T_undefined;
+		//     table[(T_undefined<<4)+T_char] 			= T_undefined;
+		//     table[(T_undefined<<4)+T_int] 			= T_undefined;
+		//     table[(T_undefined<<4)+T_null] 			= T_undefined;
 			
-		//     table[(T_byte<<4)+T_undefined] 	= T_undefined ;
-		//     table[(T_byte<<4)+T_byte] 		= T_undefined ;
-		//     table[(T_byte<<4)+T_long] 		= T_undefined ;
-		//     table[(T_byte<<4)+T_short] 		= T_undefined ;
-		//     table[(T_byte<<4)+T_void] 		= T_undefined ;
-		//     table[(T_byte<<4)+T_String] 		= T_undefined ;
-		//     table[(T_byte<<4)+T_Object] 		= T_undefined ;
-		//     table[(T_byte<<4)+T_double] 		= T_undefined ;
-		//     table[(T_byte<<4)+T_float] 		= T_undefined ;
-		//     table[(T_byte<<4)+T_boolean] 	= T_undefined ;
-		//     table[(T_byte<<4)+T_char] 		= T_undefined ;
-		//     table[(T_byte<<4)+T_int] 		= T_undefined ;
-		//     table[(T_byte<<4)+T_null] 		= T_undefined ;
+		//     table[(T_byte<<4)+T_undefined] 	= T_undefined;
+		//     table[(T_byte<<4)+T_byte] 		= T_undefined;
+		//     table[(T_byte<<4)+T_long] 		= T_undefined;
+		//     table[(T_byte<<4)+T_short] 		= T_undefined;
+		//     table[(T_byte<<4)+T_void] 		= T_undefined;
+		//     table[(T_byte<<4)+T_String] 		= T_undefined;
+		//     table[(T_byte<<4)+T_Object] 		= T_undefined;
+		//     table[(T_byte<<4)+T_double] 		= T_undefined;
+		//     table[(T_byte<<4)+T_float] 		= T_undefined;
+		//     table[(T_byte<<4)+T_boolean] 	= T_undefined;
+		//     table[(T_byte<<4)+T_char] 		= T_undefined;
+		//     table[(T_byte<<4)+T_int] 		= T_undefined;
+		//     table[(T_byte<<4)+T_null] 		= T_undefined;
 		
-		//     table[(T_long<<4)+T_undefined] 	= T_undefined ;
+		//     table[(T_long<<4)+T_undefined] 	= T_undefined;
 		//     table[(T_long<<4)+T_byte] 		= T_undefined;
-		//     table[(T_long<<4)+T_long] 		= T_undefined ;
-		//     table[(T_long<<4)+T_short] 		= T_undefined ;
-		//     table[(T_long<<4)+T_void] 		= T_undefined ;
-		//     table[(T_long<<4)+T_String] 		= T_undefined ;
-		//     table[(T_long<<4)+T_Object] 		= T_undefined ;
-		//     table[(T_long<<4)+T_double] 		= T_undefined ;
-		//     table[(T_long<<4)+T_float] 		= T_undefined ;
-		//     table[(T_long<<4)+T_boolean] 	= T_undefined ;
-		//     table[(T_long<<4)+T_char] 		= T_undefined ;
-		//     table[(T_long<<4)+T_int] 		= T_undefined ;
-		//     table[(T_long<<4)+T_null] 		= T_undefined ;
+		//     table[(T_long<<4)+T_long] 		= T_undefined;
+		//     table[(T_long<<4)+T_short] 		= T_undefined;
+		//     table[(T_long<<4)+T_void] 		= T_undefined;
+		//     table[(T_long<<4)+T_String] 		= T_undefined;
+		//     table[(T_long<<4)+T_Object] 		= T_undefined;
+		//     table[(T_long<<4)+T_double] 		= T_undefined;
+		//     table[(T_long<<4)+T_float] 		= T_undefined;
+		//     table[(T_long<<4)+T_boolean] 	= T_undefined;
+		//     table[(T_long<<4)+T_char] 		= T_undefined;
+		//     table[(T_long<<4)+T_int] 		= T_undefined;
+		//     table[(T_long<<4)+T_null] 		= T_undefined;
 		
-		//     table[(T_short<<4)+T_undefined] 	= T_undefined ;
-		//     table[(T_short<<4)+T_byte] 		= T_undefined ;
-		//     table[(T_short<<4)+T_long] 		= T_undefined ;
-		//     table[(T_short<<4)+T_short] 		= T_undefined ;
-		//     table[(T_short<<4)+T_void] 		= T_undefined ;
-		//     table[(T_short<<4)+T_String] 	= T_undefined ;
-		//     table[(T_short<<4)+T_Object] 	= T_undefined ;
-		//     table[(T_short<<4)+T_double] 	= T_undefined ;
-		//     table[(T_short<<4)+T_float] 		= T_undefined ;
-		//     table[(T_short<<4)+T_boolean]	= T_undefined ;
-		//     table[(T_short<<4)+T_char] 		= T_undefined ;
-		//     table[(T_short<<4)+T_int] 		= T_undefined ;
-		//     table[(T_short<<4)+T_null] 		= T_undefined ;
+		//     table[(T_short<<4)+T_undefined] 	= T_undefined;
+		//     table[(T_short<<4)+T_byte] 		= T_undefined;
+		//     table[(T_short<<4)+T_long] 		= T_undefined;
+		//     table[(T_short<<4)+T_short] 		= T_undefined;
+		//     table[(T_short<<4)+T_void] 		= T_undefined;
+		//     table[(T_short<<4)+T_String] 	= T_undefined;
+		//     table[(T_short<<4)+T_Object] 	= T_undefined;
+		//     table[(T_short<<4)+T_double] 	= T_undefined;
+		//     table[(T_short<<4)+T_float] 		= T_undefined;
+		//     table[(T_short<<4)+T_boolean]	= T_undefined;
+		//     table[(T_short<<4)+T_char] 		= T_undefined;
+		//     table[(T_short<<4)+T_int] 		= T_undefined;
+		//     table[(T_short<<4)+T_null] 		= T_undefined;
 		
-		//     table[(T_void<<4)+T_undefined] 	= T_undefined ;
-		//     table[(T_void<<4)+T_byte] 		= T_undefined ;
-		//     table[(T_void<<4)+T_long] 		= T_undefined ;
-		//     table[(T_void<<4)+T_short] 		= T_undefined ;
-		//     table[(T_void<<4)+T_void] 		= T_undefined ;
-		//     table[(T_void<<4)+T_String] 	= T_undefined ;
-		//     table[(T_void<<4)+T_Object] 	= T_undefined ;
-		//     table[(T_void<<4)+T_double] 	= T_undefined ;
-		//     table[(T_void<<4)+T_float] 		= T_undefined ;
-		//     table[(T_void<<4)+T_boolean] 	= T_undefined ;
-		//     table[(T_void<<4)+T_char] 		= T_undefined ;
-		//     table[(T_void<<4)+T_int] 		= T_undefined ;
-		//     table[(T_void<<4)+T_null] 		= T_undefined ;
+		//     table[(T_void<<4)+T_undefined] 	= T_undefined;
+		//     table[(T_void<<4)+T_byte] 		= T_undefined;
+		//     table[(T_void<<4)+T_long] 		= T_undefined;
+		//     table[(T_void<<4)+T_short] 		= T_undefined;
+		//     table[(T_void<<4)+T_void] 		= T_undefined;
+		//     table[(T_void<<4)+T_String] 	= T_undefined;
+		//     table[(T_void<<4)+T_Object] 	= T_undefined;
+		//     table[(T_void<<4)+T_double] 	= T_undefined;
+		//     table[(T_void<<4)+T_float] 		= T_undefined;
+		//     table[(T_void<<4)+T_boolean] 	= T_undefined;
+		//     table[(T_void<<4)+T_char] 		= T_undefined;
+		//     table[(T_void<<4)+T_int] 		= T_undefined;
+		//     table[(T_void<<4)+T_null] 		= T_undefined;
 		
-		//     table[(T_String<<4)+T_undefined] 	= T_undefined ;
-		//     table[(T_String<<4)+T_byte] 		= T_undefined ;
-		//     table[(T_String<<4)+T_long] 		= T_undefined ;
-		//     table[(T_String<<4)+T_short] 		= T_undefined ;
-		//     table[(T_String<<4)+T_void] 		= T_undefined ;
-		//     table[(T_String<<4)+T_String] 		= T_undefined ;
-		//     table[(T_String<<4)+T_Object] 		= T_undefined ;
-		//     table[(T_String<<4)+T_double] 		= T_undefined ;
-		//     table[(T_String<<4)+T_float] 		= T_undefined ;
-		//     table[(T_String<<4)+T_boolean] 		= T_undefined ;
-		//     table[(T_String<<4)+T_char] 		= T_undefined ;
-		//     table[(T_String<<4)+T_int] 			= T_undefined ;
-		//     table[(T_String<<4)+T_null] 		= T_undefined ;
+		//     table[(T_String<<4)+T_undefined] 	= T_undefined;
+		//     table[(T_String<<4)+T_byte] 		= T_undefined;
+		//     table[(T_String<<4)+T_long] 		= T_undefined;
+		//     table[(T_String<<4)+T_short] 		= T_undefined;
+		//     table[(T_String<<4)+T_void] 		= T_undefined;
+		//     table[(T_String<<4)+T_String] 		= T_undefined;
+		//     table[(T_String<<4)+T_Object] 		= T_undefined;
+		//     table[(T_String<<4)+T_double] 		= T_undefined;
+		//     table[(T_String<<4)+T_float] 		= T_undefined;
+		//     table[(T_String<<4)+T_boolean] 		= T_undefined;
+		//     table[(T_String<<4)+T_char] 		= T_undefined;
+		//     table[(T_String<<4)+T_int] 			= T_undefined;
+		//     table[(T_String<<4)+T_null] 		= T_undefined;
 		
-		//     table[(T_Object<<4)+T_undefined] 	= T_undefined ;
-		//     table[(T_Object<<4)+T_byte] 		= T_undefined ;
-		//     table[(T_Object<<4)+T_long] 		= T_undefined ;
-		//     table[(T_Object<<4)+T_short]		= T_undefined ;
-		//     table[(T_Object<<4)+T_void] 		= T_undefined ;
-		//     table[(T_Object<<4)+T_String] 		= T_undefined ;
-		//     table[(T_Object<<4)+T_Object] 		= T_undefined ;
-		//     table[(T_Object<<4)+T_double] 		= T_undefined ;
-		//     table[(T_Object<<4)+T_float] 		= T_undefined ;
-		//     table[(T_Object<<4)+T_boolean]		= T_undefined ;
-		//     table[(T_Object<<4)+T_char] 		= T_undefined ;
-		//     table[(T_Object<<4)+T_int] 			= T_undefined ;
-		//     table[(T_Object<<4)+T_null] 		= T_undefined ;
+		//     table[(T_Object<<4)+T_undefined] 	= T_undefined;
+		//     table[(T_Object<<4)+T_byte] 		= T_undefined;
+		//     table[(T_Object<<4)+T_long] 		= T_undefined;
+		//     table[(T_Object<<4)+T_short]		= T_undefined;
+		//     table[(T_Object<<4)+T_void] 		= T_undefined;
+		//     table[(T_Object<<4)+T_String] 		= T_undefined;
+		//     table[(T_Object<<4)+T_Object] 		= T_undefined;
+		//     table[(T_Object<<4)+T_double] 		= T_undefined;
+		//     table[(T_Object<<4)+T_float] 		= T_undefined;
+		//     table[(T_Object<<4)+T_boolean]		= T_undefined;
+		//     table[(T_Object<<4)+T_char] 		= T_undefined;
+		//     table[(T_Object<<4)+T_int] 			= T_undefined;
+		//     table[(T_Object<<4)+T_null] 		= T_undefined;
 		
-		//     table[(T_double<<4)+T_undefined] 	= T_undefined ;
-		//     table[(T_double<<4)+T_byte] 		= T_undefined ;
-		//     table[(T_double<<4)+T_long] 		= T_undefined ;
-		//     table[(T_double<<4)+T_short] 		= T_undefined ;
-		//     table[(T_double<<4)+T_void] 		= T_undefined ;
-		//     table[(T_double<<4)+T_String] 		= T_undefined ;
-		//     table[(T_double<<4)+T_Object] 		= T_undefined ;
-		//     table[(T_double<<4)+T_double] 		= T_undefined ;
-		//     table[(T_double<<4)+T_float] 		= T_undefined ;
-		//     table[(T_double<<4)+T_boolean] 		= T_undefined ;
-		//     table[(T_double<<4)+T_char] 		= T_undefined ;
+		//     table[(T_double<<4)+T_undefined] 	= T_undefined;
+		//     table[(T_double<<4)+T_byte] 		= T_undefined;
+		//     table[(T_double<<4)+T_long] 		= T_undefined;
+		//     table[(T_double<<4)+T_short] 		= T_undefined;
+		//     table[(T_double<<4)+T_void] 		= T_undefined;
+		//     table[(T_double<<4)+T_String] 		= T_undefined;
+		//     table[(T_double<<4)+T_Object] 		= T_undefined;
+		//     table[(T_double<<4)+T_double] 		= T_undefined;
+		//     table[(T_double<<4)+T_float] 		= T_undefined;
+		//     table[(T_double<<4)+T_boolean] 		= T_undefined;
+		//     table[(T_double<<4)+T_char] 		= T_undefined;
 		//     table[(T_double<<4)+T_int] 			= T_undefined;
-		//     table[(T_double<<4)+T_null] 		= T_undefined ;
+		//     table[(T_double<<4)+T_null] 		= T_undefined;
 		
-		//     table[(T_float<<4)+T_undefined] 	= T_undefined ;
-		//     table[(T_float<<4)+T_byte] 			= T_undefined ;
-		//     table[(T_float<<4)+T_long] 			= T_undefined ;
-		//     table[(T_float<<4)+T_short] 		= T_undefined ;
-		//     table[(T_float<<4)+T_void] 			= T_undefined ;
-		//     table[(T_float<<4)+T_String] 		= T_undefined ;
-		//     table[(T_float<<4)+T_Object] 		= T_undefined ;
-		//     table[(T_float<<4)+T_double] 		= T_undefined ;
-		//     table[(T_float<<4)+T_float] 		= T_undefined ;
-		//     table[(T_float<<4)+T_boolean] 		= T_undefined ;
-		//     table[(T_float<<4)+T_char] 			= T_undefined ;
-		//     table[(T_float<<4)+T_int] 			= T_undefined ;
-		//     table[(T_float<<4)+T_null] 			= T_undefined ;
+		//     table[(T_float<<4)+T_undefined] 	= T_undefined;
+		//     table[(T_float<<4)+T_byte] 			= T_undefined;
+		//     table[(T_float<<4)+T_long] 			= T_undefined;
+		//     table[(T_float<<4)+T_short] 		= T_undefined;
+		//     table[(T_float<<4)+T_void] 			= T_undefined;
+		//     table[(T_float<<4)+T_String] 		= T_undefined;
+		//     table[(T_float<<4)+T_Object] 		= T_undefined;
+		//     table[(T_float<<4)+T_double] 		= T_undefined;
+		//     table[(T_float<<4)+T_float] 		= T_undefined;
+		//     table[(T_float<<4)+T_boolean] 		= T_undefined;
+		//     table[(T_float<<4)+T_char] 			= T_undefined;
+		//     table[(T_float<<4)+T_int] 			= T_undefined;
+		//     table[(T_float<<4)+T_null] 			= T_undefined;
 		
-		//     table[(T_boolean<<4)+T_undefined] 		= T_undefined ;
-		//     table[(T_boolean<<4)+T_byte] 			= T_undefined ;
-		//     table[(T_boolean<<4)+T_long] 			= T_undefined ;
-		//     table[(T_boolean<<4)+T_short] 			= T_undefined ;
-		//     table[(T_boolean<<4)+T_void] 			= T_undefined ;
-		//     table[(T_boolean<<4)+T_String] 			= T_undefined ;
-		//     table[(T_boolean<<4)+T_Object] 			= T_undefined ;
-		//     table[(T_boolean<<4)+T_double] 			= T_undefined ;
-		//     table[(T_boolean<<4)+T_float] 			= T_undefined ;
-	   table[(T_boolean<<4)+T_boolean] 		= (Boolean2Boolean<<12)+(Boolean2Boolean<<4)+T_boolean ;
-		//     table[(T_boolean<<4)+T_char] 			= T_undefined ;
-		//     table[(T_boolean<<4)+T_int] 			= T_undefined ;
-		//     table[(T_boolean<<4)+T_null] 			= T_undefined ;
+		//     table[(T_boolean<<4)+T_undefined] 		= T_undefined;
+		//     table[(T_boolean<<4)+T_byte] 			= T_undefined;
+		//     table[(T_boolean<<4)+T_long] 			= T_undefined;
+		//     table[(T_boolean<<4)+T_short] 			= T_undefined;
+		//     table[(T_boolean<<4)+T_void] 			= T_undefined;
+		//     table[(T_boolean<<4)+T_String] 			= T_undefined;
+		//     table[(T_boolean<<4)+T_Object] 			= T_undefined;
+		//     table[(T_boolean<<4)+T_double] 			= T_undefined;
+		//     table[(T_boolean<<4)+T_float] 			= T_undefined;
+	   table[(T_boolean<<4)+T_boolean] 		= (Boolean2Boolean<<12)+(Boolean2Boolean<<4)+T_boolean;
+		//     table[(T_boolean<<4)+T_char] 			= T_undefined;
+		//     table[(T_boolean<<4)+T_int] 			= T_undefined;
+		//     table[(T_boolean<<4)+T_null] 			= T_undefined;
 			
-		//     table[(T_char<<4)+T_undefined] 		= T_undefined ;
-		//     table[(T_char<<4)+T_byte] 			= T_undefined ;
+		//     table[(T_char<<4)+T_undefined] 		= T_undefined;
+		//     table[(T_char<<4)+T_byte] 			= T_undefined;
 		//     table[(T_char<<4)+T_long] 			= T_undefined;
-		//     table[(T_char<<4)+T_short] 			= T_undefined ;
-		//     table[(T_char<<4)+T_void] 			= T_undefined ;
-		//     table[(T_char<<4)+T_String] 		= T_undefined ;
-		//     table[(T_char<<4)+T_Object] 		= T_undefined ;
-		//     table[(T_char<<4)+T_double] 		= T_undefined ;
-		//     table[(T_char<<4)+T_float] 			= T_undefined ;
-		//     table[(T_char<<4)+T_boolean] 		= T_undefined ;
-		//     table[(T_char<<4)+T_char] 			= T_undefined ;
-		//     table[(T_char<<4)+T_int] 			= T_undefined ;
-		//     table[(T_char<<4)+T_null] 			= T_undefined ;
+		//     table[(T_char<<4)+T_short] 			= T_undefined;
+		//     table[(T_char<<4)+T_void] 			= T_undefined;
+		//     table[(T_char<<4)+T_String] 		= T_undefined;
+		//     table[(T_char<<4)+T_Object] 		= T_undefined;
+		//     table[(T_char<<4)+T_double] 		= T_undefined;
+		//     table[(T_char<<4)+T_float] 			= T_undefined;
+		//     table[(T_char<<4)+T_boolean] 		= T_undefined;
+		//     table[(T_char<<4)+T_char] 			= T_undefined;
+		//     table[(T_char<<4)+T_int] 			= T_undefined;
+		//     table[(T_char<<4)+T_null] 			= T_undefined;
 			
-		//     table[(T_int<<4)+T_undefined] 	= T_undefined ;
-		//     table[(T_int<<4)+T_byte] 		= T_undefined ;
-		//     table[(T_int<<4)+T_long] 		= T_undefined ;
-		//     table[(T_int<<4)+T_short] 		= T_undefined ;
-		//     table[(T_int<<4)+T_void] 		= T_undefined ;
-		//     table[(T_int<<4)+T_String] 		= T_undefined ;
-		//     table[(T_int<<4)+T_Object] 		= T_undefined ;
-		//     table[(T_int<<4)+T_double] 		= T_undefined ;
-		//     table[(T_int<<4)+T_float] 		= T_undefined ;
-		//     table[(T_int<<4)+T_boolean] 	= T_undefined ;
-		//     table[(T_int<<4)+T_char] 		= T_undefined ;
-		//     table[(T_int<<4)+T_int] 		= T_undefined ;
-		//     table[(T_int<<4)+T_null] 		= T_undefined ;
+		//     table[(T_int<<4)+T_undefined] 	= T_undefined;
+		//     table[(T_int<<4)+T_byte] 		= T_undefined;
+		//     table[(T_int<<4)+T_long] 		= T_undefined;
+		//     table[(T_int<<4)+T_short] 		= T_undefined;
+		//     table[(T_int<<4)+T_void] 		= T_undefined;
+		//     table[(T_int<<4)+T_String] 		= T_undefined;
+		//     table[(T_int<<4)+T_Object] 		= T_undefined;
+		//     table[(T_int<<4)+T_double] 		= T_undefined;
+		//     table[(T_int<<4)+T_float] 		= T_undefined;
+		//     table[(T_int<<4)+T_boolean] 	= T_undefined;
+		//     table[(T_int<<4)+T_char] 		= T_undefined;
+		//     table[(T_int<<4)+T_int] 		= T_undefined;
+		//     table[(T_int<<4)+T_null] 		= T_undefined;
 		
-		//     table[(T_null<<4)+T_undefined] 		= T_undefined ;
-		//     table[(T_null<<4)+T_byte] 			= T_undefined ;
-		//     table[(T_null<<4)+T_long] 			= T_undefined ;
-		//     table[(T_null<<4)+T_short] 			= T_undefined ;
-		//     table[(T_null<<4)+T_void] 			= T_undefined ;
-		//     table[(T_null<<4)+T_String] 		= T_undefined ;
-		//     table[(T_null<<4)+T_Object] 		= T_undefined ;
-		//     table[(T_null<<4)+T_double] 		= T_undefined ;
-		//     table[(T_null<<4)+T_float] 			= T_undefined ;
-		//     table[(T_null<<4)+T_boolean] 		= T_undefined ;
-		//     table[(T_null<<4)+T_char] 			= T_undefined ;
-		//     table[(T_null<<4)+T_int] 			= T_undefined ;
-		//     table[(T_null<<4)+T_null] 			= T_undefined ;
-		return table ;
+		//     table[(T_null<<4)+T_undefined] 		= T_undefined;
+		//     table[(T_null<<4)+T_byte] 			= T_undefined;
+		//     table[(T_null<<4)+T_long] 			= T_undefined;
+		//     table[(T_null<<4)+T_short] 			= T_undefined;
+		//     table[(T_null<<4)+T_void] 			= T_undefined;
+		//     table[(T_null<<4)+T_String] 		= T_undefined;
+		//     table[(T_null<<4)+T_Object] 		= T_undefined;
+		//     table[(T_null<<4)+T_double] 		= T_undefined;
+		//     table[(T_null<<4)+T_float] 			= T_undefined;
+		//     table[(T_null<<4)+T_boolean] 		= T_undefined;
+		//     table[(T_null<<4)+T_char] 			= T_undefined;
+		//     table[(T_null<<4)+T_int] 			= T_undefined;
+		//     table[(T_null<<4)+T_null] 			= T_undefined;
+		return table;
 	}
 
 	public static final int[] get_DIVIDE(){
@@ -560,7 +560,7 @@
 		//  <<16   <<12       <<8    <<4       
 		
 		
-	//	int[] table  = new int[16*16] ;
+	//	int[] table  = new int[16*16];
 		
 		return get_MINUS();
 	}
@@ -572,199 +572,199 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		int[] table  = new int[16*16] ;
+		int[] table  = new int[16*16];
 		
-		//	table[(T_undefined<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_undefined<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_long] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_short] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_void] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_String] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_double] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_float] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_char] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_int] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_null] 			= T_undefined ;
+		//	table[(T_undefined<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_undefined<<4)+T_byte] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_long] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_short] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_void] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_String] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_Object] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_double] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_float] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_char] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_int] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_byte<<4)+T_undefined] 	= T_undefined ;
-		table[(T_byte<<4)+T_byte] 		= (Byte2Int<<12)+(Byte2Int<<4)+T_boolean ;
-		table[(T_byte<<4)+T_long] 		= (Byte2Long<<12)+(Long2Long<<4)+T_boolean ;
-		table[(T_byte<<4)+T_short] 		= (Byte2Int<<12)+(Short2Int<<4)+T_boolean ;
-		//	table[(T_byte<<4)+T_void] 		= T_undefined ;
-		//	table[(T_byte<<4)+T_String] 	= T_undefined ;
-		//	table[(T_byte<<4)+T_Object] 	= T_undefined ;
-		table[(T_byte<<4)+T_double] 	= (Byte2Double<<12)+(Double2Double<<4)+T_boolean ;
+		//	table[(T_byte<<4)+T_undefined] 	= T_undefined;
+		table[(T_byte<<4)+T_byte] 		= (Byte2Int<<12)+(Byte2Int<<4)+T_boolean;
+		table[(T_byte<<4)+T_long] 		= (Byte2Long<<12)+(Long2Long<<4)+T_boolean;
+		table[(T_byte<<4)+T_short] 		= (Byte2Int<<12)+(Short2Int<<4)+T_boolean;
+		//	table[(T_byte<<4)+T_void] 		= T_undefined;
+		//	table[(T_byte<<4)+T_String] 	= T_undefined;
+		//	table[(T_byte<<4)+T_Object] 	= T_undefined;
+		table[(T_byte<<4)+T_double] 	= (Byte2Double<<12)+(Double2Double<<4)+T_boolean;
 		table[(T_byte<<4)+T_float] 		= (Byte2Float<<12)+(Float2Float<<4)+T_boolean;
-		//	table[(T_byte<<4)+T_boolean] 	= T_undefined ;
-		table[(T_byte<<4)+T_char] 		= (Byte2Int<<12)+(Char2Int<<4)+T_boolean ;
+		//	table[(T_byte<<4)+T_boolean] 	= T_undefined;
+		table[(T_byte<<4)+T_char] 		= (Byte2Int<<12)+(Char2Int<<4)+T_boolean;
 		table[(T_byte<<4)+T_int] 		= (Byte2Int<<12)+(Int2Int<<4)+T_boolean;
-		//	table[(T_byte<<4)+T_null] 		= T_undefined ;
+		//	table[(T_byte<<4)+T_null] 		= T_undefined;
 	
-		//	table[(T_long<<4)+T_undefined] 	= T_undefined ;
+		//	table[(T_long<<4)+T_undefined] 	= T_undefined;
 		table[(T_long<<4)+T_byte] 		= (Long2Long<<12)+(Byte2Long<<4)+T_boolean;
-		table[(T_long<<4)+T_long] 		= (Long2Long<<12)+(Long2Long<<4)+T_boolean ;
-		table[(T_long<<4)+T_short] 		= (Long2Long<<12)+(Short2Long<<4)+T_boolean ;
-		//	table[(T_long<<4)+T_void] 		= T_undefined ;
-		//	table[(T_long<<4)+T_String] 	= T_undefined ;
-		//	table[(T_long<<4)+T_Object] 	= T_undefined ;
-		table[(T_long<<4)+T_double] 	= (Long2Double<<12)+(Double2Double<<4)+T_boolean ;
-		table[(T_long<<4)+T_float] 		= (Long2Float<<12)+(Float2Float<<4)+T_boolean ;
-		//	table[(T_long<<4)+T_boolean] 	= T_undefined ;
-		table[(T_long<<4)+T_char] 		= (Long2Long<<12)+(Char2Long<<4)+T_boolean ;
-		table[(T_long<<4)+T_int] 		= (Long2Long<<12)+(Int2Long<<4)+T_boolean ;
-		//	table[(T_long<<4)+T_null] 		= T_undefined ;
+		table[(T_long<<4)+T_long] 		= (Long2Long<<12)+(Long2Long<<4)+T_boolean;
+		table[(T_long<<4)+T_short] 		= (Long2Long<<12)+(Short2Long<<4)+T_boolean;
+		//	table[(T_long<<4)+T_void] 		= T_undefined;
+		//	table[(T_long<<4)+T_String] 	= T_undefined;
+		//	table[(T_long<<4)+T_Object] 	= T_undefined;
+		table[(T_long<<4)+T_double] 	= (Long2Double<<12)+(Double2Double<<4)+T_boolean;
+		table[(T_long<<4)+T_float] 		= (Long2Float<<12)+(Float2Float<<4)+T_boolean;
+		//	table[(T_long<<4)+T_boolean] 	= T_undefined;
+		table[(T_long<<4)+T_char] 		= (Long2Long<<12)+(Char2Long<<4)+T_boolean;
+		table[(T_long<<4)+T_int] 		= (Long2Long<<12)+(Int2Long<<4)+T_boolean;
+		//	table[(T_long<<4)+T_null] 		= T_undefined;
 	
-		//	table[(T_short<<4)+T_undefined] 	= T_undefined ;
-		table[(T_short<<4)+T_byte] 			= (Short2Int<<12)+(Byte2Int<<4)+T_boolean ;
-		table[(T_short<<4)+T_long] 			= (Short2Long<<12)+(Long2Long<<4)+T_boolean ;
-		table[(T_short<<4)+T_short] 		= (Short2Int<<12)+(Short2Int<<4)+T_boolean ;
-		//	table[(T_short<<4)+T_void] 			= T_undefined ;
-		//	table[(T_short<<4)+T_String] 		= T_undefined ;
-		//	table[(T_short<<4)+T_Object] 		= T_undefined ;
-		table[(T_short<<4)+T_double] 		= (Short2Double<<12)+(Double2Double<<4)+T_boolean ;
-		table[(T_short<<4)+T_float] 		= (Short2Float<<12)+(Float2Float<<4)+T_boolean ;
-		//	table[(T_short<<4)+T_boolean] 		= T_undefined ;
-		table[(T_short<<4)+T_char] 			= (Short2Int<<12)+(Char2Int<<4)+T_boolean ;
-		table[(T_short<<4)+T_int] 			= (Short2Int<<12)+(Int2Int<<4)+T_boolean ;
-		//	table[(T_short<<4)+T_null] 			= T_undefined ;
+		//	table[(T_short<<4)+T_undefined] 	= T_undefined;
+		table[(T_short<<4)+T_byte] 			= (Short2Int<<12)+(Byte2Int<<4)+T_boolean;
+		table[(T_short<<4)+T_long] 			= (Short2Long<<12)+(Long2Long<<4)+T_boolean;
+		table[(T_short<<4)+T_short] 		= (Short2Int<<12)+(Short2Int<<4)+T_boolean;
+		//	table[(T_short<<4)+T_void] 			= T_undefined;
+		//	table[(T_short<<4)+T_String] 		= T_undefined;
+		//	table[(T_short<<4)+T_Object] 		= T_undefined;
+		table[(T_short<<4)+T_double] 		= (Short2Double<<12)+(Double2Double<<4)+T_boolean;
+		table[(T_short<<4)+T_float] 		= (Short2Float<<12)+(Float2Float<<4)+T_boolean;
+		//	table[(T_short<<4)+T_boolean] 		= T_undefined;
+		table[(T_short<<4)+T_char] 			= (Short2Int<<12)+(Char2Int<<4)+T_boolean;
+		table[(T_short<<4)+T_int] 			= (Short2Int<<12)+(Int2Int<<4)+T_boolean;
+		//	table[(T_short<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_void<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_void<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_void<<4)+T_long] 		= T_undefined ;
-		//	table[(T_void<<4)+T_short] 		= T_undefined ;
-		//	table[(T_void<<4)+T_void] 		= T_undefined ;
-		//	table[(T_void<<4)+T_String] 	= T_undefined ;
-		//	table[(T_void<<4)+T_Object] 	= T_undefined ;
-		//	table[(T_void<<4)+T_double] 	= T_undefined ;
-		//	table[(T_void<<4)+T_float] 		= T_undefined ;
-		//	table[(T_void<<4)+T_boolean] 	= T_undefined ;
-		//	table[(T_void<<4)+T_char] 		= T_undefined ;
-		//	table[(T_void<<4)+T_int] 		= T_undefined ;
-		//	table[(T_void<<4)+T_null] 		= T_undefined ;
+		//	table[(T_void<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_void<<4)+T_byte] 		= T_undefined;
+		//	table[(T_void<<4)+T_long] 		= T_undefined;
+		//	table[(T_void<<4)+T_short] 		= T_undefined;
+		//	table[(T_void<<4)+T_void] 		= T_undefined;
+		//	table[(T_void<<4)+T_String] 	= T_undefined;
+		//	table[(T_void<<4)+T_Object] 	= T_undefined;
+		//	table[(T_void<<4)+T_double] 	= T_undefined;
+		//	table[(T_void<<4)+T_float] 		= T_undefined;
+		//	table[(T_void<<4)+T_boolean] 	= T_undefined;
+		//	table[(T_void<<4)+T_char] 		= T_undefined;
+		//	table[(T_void<<4)+T_int] 		= T_undefined;
+		//	table[(T_void<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_String<<4)+T_undefined] 	= T_undefined ; 
-		//	table[(T_String<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_String<<4)+T_long] 		= T_undefined ; 
-		//	table[(T_String<<4)+T_short] 		= T_undefined ;
-		//	table[(T_String<<4)+T_void] 		= T_undefined ;
+		//	table[(T_String<<4)+T_undefined] 	= T_undefined; 
+		//	table[(T_String<<4)+T_byte] 		= T_undefined;
+		//	table[(T_String<<4)+T_long] 		= T_undefined; 
+		//	table[(T_String<<4)+T_short] 		= T_undefined;
+		//	table[(T_String<<4)+T_void] 		= T_undefined;
 		table[(T_String<<4)+T_String] 		= /*String2Object                 String2Object*/
-											  (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_String<<4)+T_boolean ;
+											  (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_String<<4)+T_boolean;
 		table[(T_String<<4)+T_Object] 		= /*String2Object                 Object2Object*/
-											  (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean ;
-		//	table[(T_String<<4)+T_double] 		= T_undefined ;
-		//	table[(T_String<<4)+T_float] 		= T_undefined ; 
-		//	table[(T_String<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_String<<4)+T_char] 		= T_undefined ;
-		//	table[(T_String<<4)+T_int] 			= T_undefined ;
+											  (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean;
+		//	table[(T_String<<4)+T_double] 		= T_undefined;
+		//	table[(T_String<<4)+T_float] 		= T_undefined; 
+		//	table[(T_String<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_String<<4)+T_char] 		= T_undefined;
+		//	table[(T_String<<4)+T_int] 			= T_undefined;
 		table[(T_String<<4)+T_null] 		= /*Object2String                null2Object */
-											  (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_null<<4)+T_boolean ;
+											  (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_null<<4)+T_boolean;
 	
-		//	table[(T_Object<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_Object<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_long] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_short]		= T_undefined ;
-		//	table[(T_Object<<4)+T_void] 		= T_undefined ;
+		//	table[(T_Object<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_Object<<4)+T_byte] 		= T_undefined;
+		//	table[(T_Object<<4)+T_long] 		= T_undefined;
+		//	table[(T_Object<<4)+T_short]		= T_undefined;
+		//	table[(T_Object<<4)+T_void] 		= T_undefined;
 		table[(T_Object<<4)+T_String] 		= /*Object2Object                 String2Object*/
-											  (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_String<<4)+T_boolean ;
+											  (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_String<<4)+T_boolean;
 		table[(T_Object<<4)+T_Object] 		= /*Object2Object                 Object2Object*/
-											  (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean ;
-		//	table[(T_Object<<4)+T_double] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_float] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_boolean]		= T_undefined ;
-		//	table[(T_Object<<4)+T_char] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_int] 			= T_undefined ;
+											  (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean;
+		//	table[(T_Object<<4)+T_double] 		= T_undefined;
+		//	table[(T_Object<<4)+T_float] 		= T_undefined;
+		//	table[(T_Object<<4)+T_boolean]		= T_undefined;
+		//	table[(T_Object<<4)+T_char] 		= T_undefined;
+		//	table[(T_Object<<4)+T_int] 			= T_undefined;
 		table[(T_Object<<4)+T_null] 		= /*Object2Object                 null2Object*/
-											  (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_null<<4)+T_boolean ;
+											  (T_Object<<16)+(T_Object<<12)+(T_Object<<8)+(T_null<<4)+T_boolean;
 	
-		//	table[(T_double<<4)+T_undefined] 	= T_undefined ;
-		table[(T_double<<4)+T_byte] 		= (Double2Double<<12)+(Byte2Double<<4)+T_boolean ;
-		table[(T_double<<4)+T_long] 		= (Double2Double<<12)+(Long2Double<<4)+T_boolean ;
-		table[(T_double<<4)+T_short] 		= (Double2Double<<12)+(Short2Double<<4)+T_boolean ;
-		//	table[(T_double<<4)+T_void] 		= T_undefined ;
-		//	table[(T_double<<4)+T_String] 		= T_undefined ;
-		//	table[(T_double<<4)+T_Object] 		= T_undefined ;
-		table[(T_double<<4)+T_double] 		= (Double2Double<<12)+(Double2Double<<4)+T_boolean ;
+		//	table[(T_double<<4)+T_undefined] 	= T_undefined;
+		table[(T_double<<4)+T_byte] 		= (Double2Double<<12)+(Byte2Double<<4)+T_boolean;
+		table[(T_double<<4)+T_long] 		= (Double2Double<<12)+(Long2Double<<4)+T_boolean;
+		table[(T_double<<4)+T_short] 		= (Double2Double<<12)+(Short2Double<<4)+T_boolean;
+		//	table[(T_double<<4)+T_void] 		= T_undefined;
+		//	table[(T_double<<4)+T_String] 		= T_undefined;
+		//	table[(T_double<<4)+T_Object] 		= T_undefined;
+		table[(T_double<<4)+T_double] 		= (Double2Double<<12)+(Double2Double<<4)+T_boolean;
 		table[(T_double<<4)+T_float] 		= (Double2Double<<12)+(Float2Double<<4)+T_boolean;
-		//	table[(T_double<<4)+T_boolean] 		= T_undefined ;
-		table[(T_double<<4)+T_char] 		= (Double2Double<<12)+(Char2Double<<4)+T_boolean ;
-		table[(T_double<<4)+T_int] 			= (Double2Double<<12)+(Int2Double<<4)+T_boolean ;
-		//	table[(T_double<<4)+T_null] 		= T_undefined ;
+		//	table[(T_double<<4)+T_boolean] 		= T_undefined;
+		table[(T_double<<4)+T_char] 		= (Double2Double<<12)+(Char2Double<<4)+T_boolean;
+		table[(T_double<<4)+T_int] 			= (Double2Double<<12)+(Int2Double<<4)+T_boolean;
+		//	table[(T_double<<4)+T_null] 		= T_undefined;
 	
-		//	table[(T_float<<4)+T_undefined] 	= T_undefined ;
-		table[(T_float<<4)+T_byte] 			= (Float2Float<<12)+(Byte2Float<<4)+T_boolean ;
-		table[(T_float<<4)+T_long] 			= (Float2Float<<12)+(Long2Float<<4)+T_boolean ;
-		table[(T_float<<4)+T_short] 		= (Float2Float<<12)+(Short2Float<<4)+T_boolean ;
-		//	table[(T_float<<4)+T_void] 			= T_undefined ;
-		//	table[(T_float<<4)+T_String] 		= T_undefined ;
-		//	table[(T_float<<4)+T_Object] 		= T_undefined ;
-		table[(T_float<<4)+T_double] 		= (Float2Double<<12)+(Double2Double<<4)+T_boolean ;
-		table[(T_float<<4)+T_float] 		= (Float2Float<<12)+(Float2Float<<4)+T_boolean ;
-		//	table[(T_float<<4)+T_boolean] 		= T_undefined ;
-		table[(T_float<<4)+T_char] 			= (Float2Float<<12)+(Char2Float<<4)+T_boolean ;
-		table[(T_float<<4)+T_int] 			= (Float2Float<<12)+(Int2Float<<4)+T_boolean ;
-		//	table[(T_float<<4)+T_null] 			= T_undefined ;
+		//	table[(T_float<<4)+T_undefined] 	= T_undefined;
+		table[(T_float<<4)+T_byte] 			= (Float2Float<<12)+(Byte2Float<<4)+T_boolean;
+		table[(T_float<<4)+T_long] 			= (Float2Float<<12)+(Long2Float<<4)+T_boolean;
+		table[(T_float<<4)+T_short] 		= (Float2Float<<12)+(Short2Float<<4)+T_boolean;
+		//	table[(T_float<<4)+T_void] 			= T_undefined;
+		//	table[(T_float<<4)+T_String] 		= T_undefined;
+		//	table[(T_float<<4)+T_Object] 		= T_undefined;
+		table[(T_float<<4)+T_double] 		= (Float2Double<<12)+(Double2Double<<4)+T_boolean;
+		table[(T_float<<4)+T_float] 		= (Float2Float<<12)+(Float2Float<<4)+T_boolean;
+		//	table[(T_float<<4)+T_boolean] 		= T_undefined;
+		table[(T_float<<4)+T_char] 			= (Float2Float<<12)+(Char2Float<<4)+T_boolean;
+		table[(T_float<<4)+T_int] 			= (Float2Float<<12)+(Int2Float<<4)+T_boolean;
+		//	table[(T_float<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_boolean<<4)+T_undefined] 		= T_undefined ;
-		//	table[(T_boolean<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_long] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_short] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_void] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_String] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_Object] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_double] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_float] 			= T_undefined ;
-		table[(T_boolean<<4)+T_boolean] 		= (Boolean2Boolean<<12)+(Boolean2Boolean<<4)+T_boolean ;
-		//	table[(T_boolean<<4)+T_char] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_int] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_null] 			= T_undefined ;
+		//	table[(T_boolean<<4)+T_undefined] 		= T_undefined;
+		//	table[(T_boolean<<4)+T_byte] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_long] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_short] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_void] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_String] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_Object] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_double] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_float] 			= T_undefined;
+		table[(T_boolean<<4)+T_boolean] 		= (Boolean2Boolean<<12)+(Boolean2Boolean<<4)+T_boolean;
+		//	table[(T_boolean<<4)+T_char] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_int] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_null] 			= T_undefined;
 			
-		//	table[(T_char<<4)+T_undefined] 		= T_undefined ;
-		table[(T_char<<4)+T_byte] 			= (Char2Int<<12)+(Byte2Int<<4)+T_boolean ;
-		table[(T_char<<4)+T_long] 			= (Char2Long<<12)+(Long2Long<<4)+T_boolean ;
-		table[(T_char<<4)+T_short] 			= (Char2Int<<12)+(Short2Int<<4)+T_boolean ;
-		//	table[(T_char<<4)+T_void] 			= T_undefined ;
-		//	table[(T_char<<4)+T_String] 		= T_undefined ;
-		//	table[(T_char<<4)+T_Object] 		= T_undefined ;
-		table[(T_char<<4)+T_double] 		= (Char2Double<<12)+(Double2Double<<4)+T_boolean ;
-		table[(T_char<<4)+T_float] 			= (Char2Float<<12)+(Float2Float<<4)+T_boolean ;
-		//	table[(T_char<<4)+T_boolean] 		= T_undefined ;
-		table[(T_char<<4)+T_char] 			= (Char2Int<<12)+(Char2Int<<4)+T_boolean ;
-		table[(T_char<<4)+T_int] 			= (Char2Int<<12)+(Int2Int<<4)+T_boolean ;
-		//	table[(T_char<<4)+T_null] 			= T_undefined ;
+		//	table[(T_char<<4)+T_undefined] 		= T_undefined;
+		table[(T_char<<4)+T_byte] 			= (Char2Int<<12)+(Byte2Int<<4)+T_boolean;
+		table[(T_char<<4)+T_long] 			= (Char2Long<<12)+(Long2Long<<4)+T_boolean;
+		table[(T_char<<4)+T_short] 			= (Char2Int<<12)+(Short2Int<<4)+T_boolean;
+		//	table[(T_char<<4)+T_void] 			= T_undefined;
+		//	table[(T_char<<4)+T_String] 		= T_undefined;
+		//	table[(T_char<<4)+T_Object] 		= T_undefined;
+		table[(T_char<<4)+T_double] 		= (Char2Double<<12)+(Double2Double<<4)+T_boolean;
+		table[(T_char<<4)+T_float] 			= (Char2Float<<12)+(Float2Float<<4)+T_boolean;
+		//	table[(T_char<<4)+T_boolean] 		= T_undefined;
+		table[(T_char<<4)+T_char] 			= (Char2Int<<12)+(Char2Int<<4)+T_boolean;
+		table[(T_char<<4)+T_int] 			= (Char2Int<<12)+(Int2Int<<4)+T_boolean;
+		//	table[(T_char<<4)+T_null] 			= T_undefined;
 			
-		//	table[(T_int<<4)+T_undefined] 	= T_undefined ;
-		table[(T_int<<4)+T_byte] 		= (Int2Int<<12)+(Byte2Int<<4)+T_boolean ;
-		table[(T_int<<4)+T_long] 		= (Int2Long<<12)+(Long2Long<<4)+T_boolean ;
-		table[(T_int<<4)+T_short] 		= (Int2Int<<12)+(Short2Int<<4)+T_boolean ;
-		//	table[(T_int<<4)+T_void] 		= T_undefined ;
-		//	table[(T_int<<4)+T_String] 		= T_undefined ;
-		//	table[(T_int<<4)+T_Object] 		= T_undefined ;
-		table[(T_int<<4)+T_double] 		= (Int2Double<<12)+(Double2Double<<4)+T_boolean ;
+		//	table[(T_int<<4)+T_undefined] 	= T_undefined;
+		table[(T_int<<4)+T_byte] 		= (Int2Int<<12)+(Byte2Int<<4)+T_boolean;
+		table[(T_int<<4)+T_long] 		= (Int2Long<<12)+(Long2Long<<4)+T_boolean;
+		table[(T_int<<4)+T_short] 		= (Int2Int<<12)+(Short2Int<<4)+T_boolean;
+		//	table[(T_int<<4)+T_void] 		= T_undefined;
+		//	table[(T_int<<4)+T_String] 		= T_undefined;
+		//	table[(T_int<<4)+T_Object] 		= T_undefined;
+		table[(T_int<<4)+T_double] 		= (Int2Double<<12)+(Double2Double<<4)+T_boolean;
 		table[(T_int<<4)+T_float] 		= (Int2Float<<12)+(Float2Float<<4)+T_boolean;
-		//	table[(T_int<<4)+T_boolean] 	= T_undefined ;
-		table[(T_int<<4)+T_char] 		= (Int2Int<<12)+(Char2Int<<4)+T_boolean ;
-		table[(T_int<<4)+T_int] 		= (Int2Int<<12)+(Int2Int<<4)+T_boolean ;
-		//	table[(T_int<<4)+T_null] 		= T_undefined ;
+		//	table[(T_int<<4)+T_boolean] 	= T_undefined;
+		table[(T_int<<4)+T_char] 		= (Int2Int<<12)+(Char2Int<<4)+T_boolean;
+		table[(T_int<<4)+T_int] 		= (Int2Int<<12)+(Int2Int<<4)+T_boolean;
+		//	table[(T_int<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_null<<4)+T_undefined] 		= T_undefined ;
-		//	table[(T_null<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_null<<4)+T_long] 			= T_undefined ;
-		//	table[(T_null<<4)+T_short] 			= T_undefined ;
-		//	table[(T_null<<4)+T_void] 			= T_undefined ;
+		//	table[(T_null<<4)+T_undefined] 		= T_undefined;
+		//	table[(T_null<<4)+T_byte] 			= T_undefined;
+		//	table[(T_null<<4)+T_long] 			= T_undefined;
+		//	table[(T_null<<4)+T_short] 			= T_undefined;
+		//	table[(T_null<<4)+T_void] 			= T_undefined;
 		table[(T_null<<4)+T_String] 		= /*null2Object                 String2Object*/
-											  (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_String<<4)+T_boolean ;
+											  (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_String<<4)+T_boolean;
 		table[(T_null<<4)+T_Object] 		= /*null2Object                 Object2Object*/
-											  (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean ; ;
-		//	table[(T_null<<4)+T_double] 		= T_undefined ;
-		//	table[(T_null<<4)+T_float] 			= T_undefined ;
-		//	table[(T_null<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_null<<4)+T_char] 			= T_undefined ;
-		//	table[(T_null<<4)+T_int] 			= T_undefined ;
+											  (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean; 
+		//	table[(T_null<<4)+T_double] 		= T_undefined;
+		//	table[(T_null<<4)+T_float] 			= T_undefined;
+		//	table[(T_null<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_null<<4)+T_char] 			= T_undefined;
+		//	table[(T_null<<4)+T_int] 			= T_undefined;
 		table[(T_null<<4)+T_null] 			= /*null2Object                 null2Object*/
-											  (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_null<<4)+T_boolean ;
-		return table ;
+											  (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_null<<4)+T_boolean;
+		return table;
 	}
 
 	public static final int[] get_GREATER(){
@@ -774,7 +774,7 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		//	int[] table  = new int[16*16] ;
+		//	int[] table  = new int[16*16];
 		return get_LESS();
 	}
 
@@ -785,7 +785,7 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		//	int[] table  = new int[16*16] ;
+		//	int[] table  = new int[16*16];
 		return get_LESS();
 	}
 
@@ -796,191 +796,191 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		int[] table  = new int[16*16] ;
+		int[] table  = new int[16*16];
 		
-		//	table[(T_undefined<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_undefined<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_long] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_short] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_void] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_String] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_double] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_float] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_char] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_int] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_null] 			= T_undefined ;
+		//	table[(T_undefined<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_undefined<<4)+T_byte] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_long] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_short] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_void] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_String] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_Object] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_double] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_float] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_char] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_int] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_null] 			= T_undefined;
 			
-		//	table[(T_byte<<4)+T_undefined] 	= T_undefined ;
-		table[(T_byte<<4)+T_byte] 		= (Byte2Int<<12)+(Byte2Int<<4)+T_int ;
-		table[(T_byte<<4)+T_long] 		= (Byte2Int<<12)+(Long2Int<<4)+T_int ;
-		table[(T_byte<<4)+T_short] 		= (Byte2Int<<12)+(Short2Int<<4)+T_int ;
-		//	table[(T_byte<<4)+T_void] 		= T_undefined ;
-		//	table[(T_byte<<4)+T_String] 	= T_undefined ;
-		//	table[(T_byte<<4)+T_Object] 	= T_undefined ;
-		//	table[(T_byte<<4)+T_double] 	= T_undefined ;
-		//	table[(T_byte<<4)+T_float] 		= T_undefined ;
-		//	table[(T_byte<<4)+T_boolean] 	= T_undefined ;
-		table[(T_byte<<4)+T_char] 		= (Byte2Int<<12)+(Char2Int<<4)+T_int ;
-		table[(T_byte<<4)+T_int] 		= (Byte2Int<<12)+(Int2Int<<4)+T_int ;
-		//	table[(T_byte<<4)+T_null] 		= T_undefined ;
+		//	table[(T_byte<<4)+T_undefined] 	= T_undefined;
+		table[(T_byte<<4)+T_byte] 		= (Byte2Int<<12)+(Byte2Int<<4)+T_int;
+		table[(T_byte<<4)+T_long] 		= (Byte2Int<<12)+(Long2Int<<4)+T_int;
+		table[(T_byte<<4)+T_short] 		= (Byte2Int<<12)+(Short2Int<<4)+T_int;
+		//	table[(T_byte<<4)+T_void] 		= T_undefined;
+		//	table[(T_byte<<4)+T_String] 	= T_undefined;
+		//	table[(T_byte<<4)+T_Object] 	= T_undefined;
+		//	table[(T_byte<<4)+T_double] 	= T_undefined;
+		//	table[(T_byte<<4)+T_float] 		= T_undefined;
+		//	table[(T_byte<<4)+T_boolean] 	= T_undefined;
+		table[(T_byte<<4)+T_char] 		= (Byte2Int<<12)+(Char2Int<<4)+T_int;
+		table[(T_byte<<4)+T_int] 		= (Byte2Int<<12)+(Int2Int<<4)+T_int;
+		//	table[(T_byte<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_long<<4)+T_undefined] 	= T_undefined ;
+		//	table[(T_long<<4)+T_undefined] 	= T_undefined;
 		table[(T_long<<4)+T_byte] 		= (Long2Long<<12)+(Byte2Int<<4)+T_long;
-		table[(T_long<<4)+T_long] 		= (Long2Long<<12)+(Long2Int<<4)+T_long ;
-		table[(T_long<<4)+T_short] 		= (Long2Long<<12)+(Short2Int<<4)+T_long ;
-		//	table[(T_long<<4)+T_void] 		= T_undefined ;
-		//	table[(T_long<<4)+T_String] 	= T_undefined ;
-		//	table[(T_long<<4)+T_Object] 	= T_undefined ;
-		//	table[(T_long<<4)+T_double] 	= T_undefined ;
-		//	table[(T_long<<4)+T_float] 		= T_undefined ;
-		//	table[(T_long<<4)+T_boolean] 	= T_undefined ;
-		table[(T_long<<4)+T_char] 		= (Long2Long<<12)+(Char2Int<<4)+T_long ;
-		table[(T_long<<4)+T_int] 		= (Long2Long<<12)+(Int2Int<<4)+T_long ;
-		//	table[(T_long<<4)+T_null] 		= T_undefined ;
+		table[(T_long<<4)+T_long] 		= (Long2Long<<12)+(Long2Int<<4)+T_long;
+		table[(T_long<<4)+T_short] 		= (Long2Long<<12)+(Short2Int<<4)+T_long;
+		//	table[(T_long<<4)+T_void] 		= T_undefined;
+		//	table[(T_long<<4)+T_String] 	= T_undefined;
+		//	table[(T_long<<4)+T_Object] 	= T_undefined;
+		//	table[(T_long<<4)+T_double] 	= T_undefined;
+		//	table[(T_long<<4)+T_float] 		= T_undefined;
+		//	table[(T_long<<4)+T_boolean] 	= T_undefined;
+		table[(T_long<<4)+T_char] 		= (Long2Long<<12)+(Char2Int<<4)+T_long;
+		table[(T_long<<4)+T_int] 		= (Long2Long<<12)+(Int2Int<<4)+T_long;
+		//	table[(T_long<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_short<<4)+T_undefined] 	= T_undefined ;
-		table[(T_short<<4)+T_byte] 			= (Short2Int<<12)+(Byte2Int<<4)+T_int ;
-		table[(T_short<<4)+T_long] 			= (Short2Int<<12)+(Long2Int<<4)+T_int ;
-		table[(T_short<<4)+T_short] 		= (Short2Int<<12)+(Short2Int<<4)+T_int ;
-		//	table[(T_short<<4)+T_void] 			= T_undefined ;
-		//	table[(T_short<<4)+T_String] 		= T_undefined ;
-		//	table[(T_short<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_short<<4)+T_double] 		= T_undefined ;
-		//	table[(T_short<<4)+T_float] 		= T_undefined ;
-		//	table[(T_short<<4)+T_boolean] 		= T_undefined ;
-		table[(T_short<<4)+T_char] 			= (Short2Int<<12)+(Char2Int<<4)+T_int ;
-		table[(T_short<<4)+T_int] 			= (Short2Int<<12)+(Int2Int<<4)+T_int ;
-		//	table[(T_short<<4)+T_null] 			= T_undefined ;
+		//	table[(T_short<<4)+T_undefined] 	= T_undefined;
+		table[(T_short<<4)+T_byte] 			= (Short2Int<<12)+(Byte2Int<<4)+T_int;
+		table[(T_short<<4)+T_long] 			= (Short2Int<<12)+(Long2Int<<4)+T_int;
+		table[(T_short<<4)+T_short] 		= (Short2Int<<12)+(Short2Int<<4)+T_int;
+		//	table[(T_short<<4)+T_void] 			= T_undefined;
+		//	table[(T_short<<4)+T_String] 		= T_undefined;
+		//	table[(T_short<<4)+T_Object] 		= T_undefined;
+		//	table[(T_short<<4)+T_double] 		= T_undefined;
+		//	table[(T_short<<4)+T_float] 		= T_undefined;
+		//	table[(T_short<<4)+T_boolean] 		= T_undefined;
+		table[(T_short<<4)+T_char] 			= (Short2Int<<12)+(Char2Int<<4)+T_int;
+		table[(T_short<<4)+T_int] 			= (Short2Int<<12)+(Int2Int<<4)+T_int;
+		//	table[(T_short<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_void<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_void<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_void<<4)+T_long] 		= T_undefined ;
-		//	table[(T_void<<4)+T_short] 		= T_undefined ;
-		//	table[(T_void<<4)+T_void] 		= T_undefined ;
-		//	table[(T_void<<4)+T_String] 	= T_undefined ;
-		//	table[(T_void<<4)+T_Object] 	= T_undefined ;
-		//	table[(T_void<<4)+T_double] 	= T_undefined ;
-		//	table[(T_void<<4)+T_float] 		= T_undefined ;
-		//	table[(T_void<<4)+T_boolean] 	= T_undefined ;
-		//	table[(T_void<<4)+T_char] 		= T_undefined ;
-		//	table[(T_void<<4)+T_int] 		= T_undefined ;
-		//	table[(T_void<<4)+T_null] 		= T_undefined ;
+		//	table[(T_void<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_void<<4)+T_byte] 		= T_undefined;
+		//	table[(T_void<<4)+T_long] 		= T_undefined;
+		//	table[(T_void<<4)+T_short] 		= T_undefined;
+		//	table[(T_void<<4)+T_void] 		= T_undefined;
+		//	table[(T_void<<4)+T_String] 	= T_undefined;
+		//	table[(T_void<<4)+T_Object] 	= T_undefined;
+		//	table[(T_void<<4)+T_double] 	= T_undefined;
+		//	table[(T_void<<4)+T_float] 		= T_undefined;
+		//	table[(T_void<<4)+T_boolean] 	= T_undefined;
+		//	table[(T_void<<4)+T_char] 		= T_undefined;
+		//	table[(T_void<<4)+T_int] 		= T_undefined;
+		//	table[(T_void<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_String<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_String<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_String<<4)+T_long] 		= T_undefined ;
-		//	table[(T_String<<4)+T_short] 		= T_undefined ;
-		//	table[(T_String<<4)+T_void] 		= T_undefined ;
-		//	table[(T_String<<4)+T_String] 		= T_undefined ;
-		//	table[(T_String<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_String<<4)+T_double] 		= T_undefined ;
-		//	table[(T_String<<4)+T_float] 		= T_undefined ;
-		//	table[(T_String<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_String<<4)+T_char] 		= T_undefined ;
-		//	table[(T_String<<4)+T_int] 			= T_undefined ;
-		//	table[(T_String<<4)+T_null] 		= T_undefined ;
+		//	table[(T_String<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_String<<4)+T_byte] 		= T_undefined;
+		//	table[(T_String<<4)+T_long] 		= T_undefined;
+		//	table[(T_String<<4)+T_short] 		= T_undefined;
+		//	table[(T_String<<4)+T_void] 		= T_undefined;
+		//	table[(T_String<<4)+T_String] 		= T_undefined;
+		//	table[(T_String<<4)+T_Object] 		= T_undefined;
+		//	table[(T_String<<4)+T_double] 		= T_undefined;
+		//	table[(T_String<<4)+T_float] 		= T_undefined;
+		//	table[(T_String<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_String<<4)+T_char] 		= T_undefined;
+		//	table[(T_String<<4)+T_int] 			= T_undefined;
+		//	table[(T_String<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_Object<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_Object<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_long] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_short]		= T_undefined ;
-		//	table[(T_Object<<4)+T_void] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_String] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_double] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_float] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_boolean]		= T_undefined ;
-		//	table[(T_Object<<4)+T_char] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_int] 			= T_undefined ;
-		//	table[(T_Object<<4)+T_null] 		= T_undefined ;
+		//	table[(T_Object<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_Object<<4)+T_byte] 		= T_undefined;
+		//	table[(T_Object<<4)+T_long] 		= T_undefined;
+		//	table[(T_Object<<4)+T_short]		= T_undefined;
+		//	table[(T_Object<<4)+T_void] 		= T_undefined;
+		//	table[(T_Object<<4)+T_String] 		= T_undefined;
+		//	table[(T_Object<<4)+T_Object] 		= T_undefined;
+		//	table[(T_Object<<4)+T_double] 		= T_undefined;
+		//	table[(T_Object<<4)+T_float] 		= T_undefined;
+		//	table[(T_Object<<4)+T_boolean]		= T_undefined;
+		//	table[(T_Object<<4)+T_char] 		= T_undefined;
+		//	table[(T_Object<<4)+T_int] 			= T_undefined;
+		//	table[(T_Object<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_double<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_double<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_double<<4)+T_long] 		= T_undefined ;
-		//	table[(T_double<<4)+T_short] 		= T_undefined ;
-		//	table[(T_double<<4)+T_void] 		= T_undefined ;
-		//	table[(T_double<<4)+T_String] 		= T_undefined ;
-		//	table[(T_double<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_double<<4)+T_double] 		= T_undefined ;
-		//	table[(T_double<<4)+T_float] 		= T_undefined ;
-		//	table[(T_double<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_double<<4)+T_char] 		= T_undefined ;
+		//	table[(T_double<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_double<<4)+T_byte] 		= T_undefined;
+		//	table[(T_double<<4)+T_long] 		= T_undefined;
+		//	table[(T_double<<4)+T_short] 		= T_undefined;
+		//	table[(T_double<<4)+T_void] 		= T_undefined;
+		//	table[(T_double<<4)+T_String] 		= T_undefined;
+		//	table[(T_double<<4)+T_Object] 		= T_undefined;
+		//	table[(T_double<<4)+T_double] 		= T_undefined;
+		//	table[(T_double<<4)+T_float] 		= T_undefined;
+		//	table[(T_double<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_double<<4)+T_char] 		= T_undefined;
 		//	table[(T_double<<4)+T_int] 			= T_undefined;
-		//	table[(T_double<<4)+T_null] 		= T_undefined ;
+		//	table[(T_double<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_float<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_float<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_float<<4)+T_long] 			= T_undefined ;
-		//	table[(T_float<<4)+T_short] 		= T_undefined ;
-		//	table[(T_float<<4)+T_void] 			= T_undefined ;
-		//	table[(T_float<<4)+T_String] 		= T_undefined ;
-		//	table[(T_float<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_float<<4)+T_double] 		= T_undefined ;
-		//	table[(T_float<<4)+T_float] 		= T_undefined ;
-		//	table[(T_float<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_float<<4)+T_char] 			= T_undefined ;
-		//	table[(T_float<<4)+T_int] 			= T_undefined ;
-		//	table[(T_float<<4)+T_null] 			= T_undefined ;
+		//	table[(T_float<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_float<<4)+T_byte] 			= T_undefined;
+		//	table[(T_float<<4)+T_long] 			= T_undefined;
+		//	table[(T_float<<4)+T_short] 		= T_undefined;
+		//	table[(T_float<<4)+T_void] 			= T_undefined;
+		//	table[(T_float<<4)+T_String] 		= T_undefined;
+		//	table[(T_float<<4)+T_Object] 		= T_undefined;
+		//	table[(T_float<<4)+T_double] 		= T_undefined;
+		//	table[(T_float<<4)+T_float] 		= T_undefined;
+		//	table[(T_float<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_float<<4)+T_char] 			= T_undefined;
+		//	table[(T_float<<4)+T_int] 			= T_undefined;
+		//	table[(T_float<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_boolean<<4)+T_undefined] 		= T_undefined ;
-		//	table[(T_boolean<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_long] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_short] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_void] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_String] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_Object] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_double] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_float] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_boolean<<4)+T_char] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_int] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_null] 			= T_undefined ;
+		//	table[(T_boolean<<4)+T_undefined] 		= T_undefined;
+		//	table[(T_boolean<<4)+T_byte] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_long] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_short] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_void] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_String] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_Object] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_double] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_float] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_boolean<<4)+T_char] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_int] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_null] 			= T_undefined;
 			
-		//	table[(T_char<<4)+T_undefined] 		= T_undefined ;
-		table[(T_char<<4)+T_byte] 			= (Char2Int<<12)+(Byte2Int<<4)+T_int ;
-		table[(T_char<<4)+T_long] 			= (Char2Int<<12)+(Long2Int<<4)+T_int ;
-		table[(T_char<<4)+T_short] 			= (Char2Int<<12)+(Short2Int<<4)+T_int ;
-		//	table[(T_char<<4)+T_void] 			= T_undefined ;
-		//	table[(T_char<<4)+T_String] 		= T_undefined ;
-		//	table[(T_char<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_char<<4)+T_double] 		= T_undefined ;
-		//	table[(T_char<<4)+T_float] 			= T_undefined ;
-		//	table[(T_char<<4)+T_boolean] 		= T_undefined ;
-		table[(T_char<<4)+T_char] 			= (Char2Int<<12)+(Char2Int<<4)+T_int ;
-		table[(T_char<<4)+T_int] 			= (Char2Int<<12)+(Int2Int<<4)+T_int ;
-		//	table[(T_char<<4)+T_null] 			= T_undefined ;
+		//	table[(T_char<<4)+T_undefined] 		= T_undefined;
+		table[(T_char<<4)+T_byte] 			= (Char2Int<<12)+(Byte2Int<<4)+T_int;
+		table[(T_char<<4)+T_long] 			= (Char2Int<<12)+(Long2Int<<4)+T_int;
+		table[(T_char<<4)+T_short] 			= (Char2Int<<12)+(Short2Int<<4)+T_int;
+		//	table[(T_char<<4)+T_void] 			= T_undefined;
+		//	table[(T_char<<4)+T_String] 		= T_undefined;
+		//	table[(T_char<<4)+T_Object] 		= T_undefined;
+		//	table[(T_char<<4)+T_double] 		= T_undefined;
+		//	table[(T_char<<4)+T_float] 			= T_undefined;
+		//	table[(T_char<<4)+T_boolean] 		= T_undefined;
+		table[(T_char<<4)+T_char] 			= (Char2Int<<12)+(Char2Int<<4)+T_int;
+		table[(T_char<<4)+T_int] 			= (Char2Int<<12)+(Int2Int<<4)+T_int;
+		//	table[(T_char<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_int<<4)+T_undefined] 	= T_undefined ;
-		table[(T_int<<4)+T_byte] 		= (Int2Int<<12)+(Byte2Int<<4)+T_int ;
-		table[(T_int<<4)+T_long] 		= (Int2Int<<12)+(Long2Int<<4)+T_int ;
-		table[(T_int<<4)+T_short] 		= (Int2Int<<12)+(Short2Int<<4)+T_int ;
-		//	table[(T_int<<4)+T_void] 		= T_undefined ;
-		//	table[(T_int<<4)+T_String] 		= T_undefined ;
-		//	table[(T_int<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_int<<4)+T_double] 		= T_undefined ;
-		//	table[(T_int<<4)+T_float] 		= T_undefined ;
-		//	table[(T_int<<4)+T_boolean] 	= T_undefined ;
-		table[(T_int<<4)+T_char] 		= (Int2Int<<12)+(Char2Int<<4)+T_int ;
-		table[(T_int<<4)+T_int] 		= (Int2Int<<12)+(Int2Int<<4)+T_int ;
-		//	table[(T_int<<4)+T_null] 		= T_undefined ;
+		//	table[(T_int<<4)+T_undefined] 	= T_undefined;
+		table[(T_int<<4)+T_byte] 		= (Int2Int<<12)+(Byte2Int<<4)+T_int;
+		table[(T_int<<4)+T_long] 		= (Int2Int<<12)+(Long2Int<<4)+T_int;
+		table[(T_int<<4)+T_short] 		= (Int2Int<<12)+(Short2Int<<4)+T_int;
+		//	table[(T_int<<4)+T_void] 		= T_undefined;
+		//	table[(T_int<<4)+T_String] 		= T_undefined;
+		//	table[(T_int<<4)+T_Object] 		= T_undefined;
+		//	table[(T_int<<4)+T_double] 		= T_undefined;
+		//	table[(T_int<<4)+T_float] 		= T_undefined;
+		//	table[(T_int<<4)+T_boolean] 	= T_undefined;
+		table[(T_int<<4)+T_char] 		= (Int2Int<<12)+(Char2Int<<4)+T_int;
+		table[(T_int<<4)+T_int] 		= (Int2Int<<12)+(Int2Int<<4)+T_int;
+		//	table[(T_int<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_null<<4)+T_undefined] 		= T_undefined ;
-		//	table[(T_null<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_null<<4)+T_long] 			= T_undefined ;
-		//	table[(T_null<<4)+T_short] 			= T_undefined ;
-		//	table[(T_null<<4)+T_void] 			= T_undefined ;
-		//	table[(T_null<<4)+T_String] 		= T_undefined ;
-		//	table[(T_null<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_null<<4)+T_double] 		= T_undefined ;
-		//	table[(T_null<<4)+T_float] 			= T_undefined ;
-		//	table[(T_null<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_null<<4)+T_char] 			= T_undefined ;
-		//	table[(T_null<<4)+T_int] 			= T_undefined ;
-		//	table[(T_null<<4)+T_null] 			= T_undefined ;
+		//	table[(T_null<<4)+T_undefined] 		= T_undefined;
+		//	table[(T_null<<4)+T_byte] 			= T_undefined;
+		//	table[(T_null<<4)+T_long] 			= T_undefined;
+		//	table[(T_null<<4)+T_short] 			= T_undefined;
+		//	table[(T_null<<4)+T_void] 			= T_undefined;
+		//	table[(T_null<<4)+T_String] 		= T_undefined;
+		//	table[(T_null<<4)+T_Object] 		= T_undefined;
+		//	table[(T_null<<4)+T_double] 		= T_undefined;
+		//	table[(T_null<<4)+T_float] 			= T_undefined;
+		//	table[(T_null<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_null<<4)+T_char] 			= T_undefined;
+		//	table[(T_null<<4)+T_int] 			= T_undefined;
+		//	table[(T_null<<4)+T_null] 			= T_undefined;
 	
-		return table ;
+		return table;
 	}
 
 	public static final int[] get_LESS(){
@@ -990,191 +990,191 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		int[] table  = new int[16*16] ;
+		int[] table  = new int[16*16];
 		
-		//	table[(T_undefined<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_undefined<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_long] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_short] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_void] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_String] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_double] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_float] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_char] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_int] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_null] 			= T_undefined ;
+		//	table[(T_undefined<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_undefined<<4)+T_byte] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_long] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_short] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_void] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_String] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_Object] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_double] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_float] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_char] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_int] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_byte<<4)+T_undefined] 	= T_undefined ;
-		table[(T_byte<<4)+T_byte] 		= (Byte2Int<<12)+(Byte2Int<<4)+T_boolean ;
-		table[(T_byte<<4)+T_long] 		= (Byte2Long<<12)+(Long2Long<<4)+T_boolean ;
-		table[(T_byte<<4)+T_short] 		= (Byte2Int<<12)+(Short2Int<<4)+T_boolean ;
-		//	table[(T_byte<<4)+T_void] 		= T_undefined ;
-		//	table[(T_byte<<4)+T_String] 	= T_undefined ;
-		//	table[(T_byte<<4)+T_Object] 	= T_undefined ;
-		table[(T_byte<<4)+T_double] 	= (Byte2Double<<12)+(Double2Double<<4)+T_boolean ;
+		//	table[(T_byte<<4)+T_undefined] 	= T_undefined;
+		table[(T_byte<<4)+T_byte] 		= (Byte2Int<<12)+(Byte2Int<<4)+T_boolean;
+		table[(T_byte<<4)+T_long] 		= (Byte2Long<<12)+(Long2Long<<4)+T_boolean;
+		table[(T_byte<<4)+T_short] 		= (Byte2Int<<12)+(Short2Int<<4)+T_boolean;
+		//	table[(T_byte<<4)+T_void] 		= T_undefined;
+		//	table[(T_byte<<4)+T_String] 	= T_undefined;
+		//	table[(T_byte<<4)+T_Object] 	= T_undefined;
+		table[(T_byte<<4)+T_double] 	= (Byte2Double<<12)+(Double2Double<<4)+T_boolean;
 		table[(T_byte<<4)+T_float] 		= (Byte2Float<<12)+(Float2Float<<4)+T_boolean;
-		//	table[(T_byte<<4)+T_boolean] 	= T_undefined ;
-		table[(T_byte<<4)+T_char] 		= (Byte2Int<<12)+(Char2Int<<4)+T_boolean ;
-		table[(T_byte<<4)+T_int] 		= (Byte2Int<<12)+(Int2Int<<4)+T_boolean ;
-		//	table[(T_byte<<4)+T_null] 		= T_undefined ;
+		//	table[(T_byte<<4)+T_boolean] 	= T_undefined;
+		table[(T_byte<<4)+T_char] 		= (Byte2Int<<12)+(Char2Int<<4)+T_boolean;
+		table[(T_byte<<4)+T_int] 		= (Byte2Int<<12)+(Int2Int<<4)+T_boolean;
+		//	table[(T_byte<<4)+T_null] 		= T_undefined;
 	
-		//	table[(T_long<<4)+T_undefined] 	= T_undefined ;
+		//	table[(T_long<<4)+T_undefined] 	= T_undefined;
 		table[(T_long<<4)+T_byte] 		= (Long2Long<<12)+(Byte2Long<<4)+T_boolean;
-		table[(T_long<<4)+T_long] 		= (Long2Long<<12)+(Long2Long<<4)+T_boolean ;
-		table[(T_long<<4)+T_short] 		= (Long2Long<<12)+(Short2Long<<4)+T_boolean ;
-		//	table[(T_long<<4)+T_void] 		= T_undefined ;
-		//	table[(T_long<<4)+T_String] 	= T_undefined ;
-		//	table[(T_long<<4)+T_Object] 	= T_undefined ;
-		table[(T_long<<4)+T_double] 	= (Long2Double<<12)+(Double2Double<<4)+T_boolean ;
-		table[(T_long<<4)+T_float] 		= (Long2Float<<12)+(Float2Float<<4)+T_boolean ;
-		//	table[(T_long<<4)+T_boolean] 	= T_undefined ;
-		table[(T_long<<4)+T_char] 		= (Long2Long<<12)+(Char2Long<<4)+T_boolean ;
-		table[(T_long<<4)+T_int] 		= (Long2Long<<12)+(Int2Long<<4)+T_boolean ;
-		//	table[(T_long<<4)+T_null] 		= T_undefined ;
+		table[(T_long<<4)+T_long] 		= (Long2Long<<12)+(Long2Long<<4)+T_boolean;
+		table[(T_long<<4)+T_short] 		= (Long2Long<<12)+(Short2Long<<4)+T_boolean;
+		//	table[(T_long<<4)+T_void] 		= T_undefined;
+		//	table[(T_long<<4)+T_String] 	= T_undefined;
+		//	table[(T_long<<4)+T_Object] 	= T_undefined;
+		table[(T_long<<4)+T_double] 	= (Long2Double<<12)+(Double2Double<<4)+T_boolean;
+		table[(T_long<<4)+T_float] 		= (Long2Float<<12)+(Float2Float<<4)+T_boolean;
+		//	table[(T_long<<4)+T_boolean] 	= T_undefined;
+		table[(T_long<<4)+T_char] 		= (Long2Long<<12)+(Char2Long<<4)+T_boolean;
+		table[(T_long<<4)+T_int] 		= (Long2Long<<12)+(Int2Long<<4)+T_boolean;
+		//	table[(T_long<<4)+T_null] 		= T_undefined;
 	
-		//	table[(T_short<<4)+T_undefined] 	= T_undefined ;
-		table[(T_short<<4)+T_byte] 			= (Short2Int<<12)+(Byte2Int<<4)+T_boolean ;
-		table[(T_short<<4)+T_long] 			= (Short2Long<<12)+(Long2Long<<4)+T_boolean ;
-		table[(T_short<<4)+T_short] 		= (Short2Int<<12)+(Short2Int<<4)+T_boolean ;
-		//	table[(T_short<<4)+T_void] 			= T_undefined ;
-		//	table[(T_short<<4)+T_String] 		= T_undefined ;
-		//	table[(T_short<<4)+T_Object] 		= T_undefined ;
-		table[(T_short<<4)+T_double] 		= (Short2Double<<12)+(Double2Double<<4)+T_boolean ;
-		table[(T_short<<4)+T_float] 		= (Short2Float<<12)+(Float2Float<<4)+T_boolean ;
-		//	table[(T_short<<4)+T_boolean] 		= T_undefined ;
-		table[(T_short<<4)+T_char] 			= (Short2Int<<12)+(Char2Int<<4)+T_boolean ;
-		table[(T_short<<4)+T_int] 			= (Short2Int<<12)+(Int2Int<<4)+T_boolean ;
-		//	table[(T_short<<4)+T_null] 			= T_undefined ;
+		//	table[(T_short<<4)+T_undefined] 	= T_undefined;
+		table[(T_short<<4)+T_byte] 			= (Short2Int<<12)+(Byte2Int<<4)+T_boolean;
+		table[(T_short<<4)+T_long] 			= (Short2Long<<12)+(Long2Long<<4)+T_boolean;
+		table[(T_short<<4)+T_short] 		= (Short2Int<<12)+(Short2Int<<4)+T_boolean;
+		//	table[(T_short<<4)+T_void] 			= T_undefined;
+		//	table[(T_short<<4)+T_String] 		= T_undefined;
+		//	table[(T_short<<4)+T_Object] 		= T_undefined;
+		table[(T_short<<4)+T_double] 		= (Short2Double<<12)+(Double2Double<<4)+T_boolean;
+		table[(T_short<<4)+T_float] 		= (Short2Float<<12)+(Float2Float<<4)+T_boolean;
+		//	table[(T_short<<4)+T_boolean] 		= T_undefined;
+		table[(T_short<<4)+T_char] 			= (Short2Int<<12)+(Char2Int<<4)+T_boolean;
+		table[(T_short<<4)+T_int] 			= (Short2Int<<12)+(Int2Int<<4)+T_boolean;
+		//	table[(T_short<<4)+T_null] 			= T_undefined;
 	
-		//	table[(T_void<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_void<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_void<<4)+T_long] 		= T_undefined ;
-		//	table[(T_void<<4)+T_short] 		= T_undefined ;
-		//	table[(T_void<<4)+T_void] 		= T_undefined ;
-		//	table[(T_void<<4)+T_String] 	= T_undefined ;
-		//	table[(T_void<<4)+T_Object] 	= T_undefined ;
-		//	table[(T_void<<4)+T_double] 	= T_undefined ;
-		//	table[(T_void<<4)+T_float] 		= T_undefined ;
-		//	table[(T_void<<4)+T_boolean] 	= T_undefined ;
-		//	table[(T_void<<4)+T_char] 		= T_undefined ;
-		//	table[(T_void<<4)+T_int] 		= T_undefined ;
-		//	table[(T_void<<4)+T_null] 		= T_undefined ;
+		//	table[(T_void<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_void<<4)+T_byte] 		= T_undefined;
+		//	table[(T_void<<4)+T_long] 		= T_undefined;
+		//	table[(T_void<<4)+T_short] 		= T_undefined;
+		//	table[(T_void<<4)+T_void] 		= T_undefined;
+		//	table[(T_void<<4)+T_String] 	= T_undefined;
+		//	table[(T_void<<4)+T_Object] 	= T_undefined;
+		//	table[(T_void<<4)+T_double] 	= T_undefined;
+		//	table[(T_void<<4)+T_float] 		= T_undefined;
+		//	table[(T_void<<4)+T_boolean] 	= T_undefined;
+		//	table[(T_void<<4)+T_char] 		= T_undefined;
+		//	table[(T_void<<4)+T_int] 		= T_undefined;
+		//	table[(T_void<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_String<<4)+T_undefined] 	= T_undefined ; 
-		//	table[(T_String<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_String<<4)+T_long] 		= T_undefined ; 
-		//	table[(T_String<<4)+T_short] 		= T_undefined ;
-		//	table[(T_String<<4)+T_void] 		= T_undefined ;
-		//	table[(T_String<<4)+T_String] 		= T_undefined ;
-		//	table[(T_String<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_String<<4)+T_double] 		= T_undefined ;
-		//	table[(T_String<<4)+T_float] 		= T_undefined ; 
-		//	table[(T_String<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_String<<4)+T_char] 		= T_undefined ;
-		//	table[(T_String<<4)+T_int] 			= T_undefined ;
-		//	table[(T_String<<4)+T_null] 		= T_undefined ;
+		//	table[(T_String<<4)+T_undefined] 	= T_undefined; 
+		//	table[(T_String<<4)+T_byte] 		= T_undefined;
+		//	table[(T_String<<4)+T_long] 		= T_undefined; 
+		//	table[(T_String<<4)+T_short] 		= T_undefined;
+		//	table[(T_String<<4)+T_void] 		= T_undefined;
+		//	table[(T_String<<4)+T_String] 		= T_undefined;
+		//	table[(T_String<<4)+T_Object] 		= T_undefined;
+		//	table[(T_String<<4)+T_double] 		= T_undefined;
+		//	table[(T_String<<4)+T_float] 		= T_undefined; 
+		//	table[(T_String<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_String<<4)+T_char] 		= T_undefined;
+		//	table[(T_String<<4)+T_int] 			= T_undefined;
+		//	table[(T_String<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_Object<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_Object<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_long] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_short]		= T_undefined ;
-		//	table[(T_Object<<4)+T_void] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_String] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_double] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_float] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_boolean]		= T_undefined ;
-		//	table[(T_Object<<4)+T_char] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_int] 			= T_undefined ;
-		//	table[(T_Object<<4)+T_null] 		= T_undefined ;
+		//	table[(T_Object<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_Object<<4)+T_byte] 		= T_undefined;
+		//	table[(T_Object<<4)+T_long] 		= T_undefined;
+		//	table[(T_Object<<4)+T_short]		= T_undefined;
+		//	table[(T_Object<<4)+T_void] 		= T_undefined;
+		//	table[(T_Object<<4)+T_String] 		= T_undefined;
+		//	table[(T_Object<<4)+T_Object] 		= T_undefined;
+		//	table[(T_Object<<4)+T_double] 		= T_undefined;
+		//	table[(T_Object<<4)+T_float] 		= T_undefined;
+		//	table[(T_Object<<4)+T_boolean]		= T_undefined;
+		//	table[(T_Object<<4)+T_char] 		= T_undefined;
+		//	table[(T_Object<<4)+T_int] 			= T_undefined;
+		//	table[(T_Object<<4)+T_null] 		= T_undefined;
 	
-		//	table[(T_double<<4)+T_undefined] 	= T_undefined ;
-		table[(T_double<<4)+T_byte] 		= (Double2Double<<12)+(Byte2Double<<4)+T_boolean ;
+		//	table[(T_double<<4)+T_undefined] 	= T_undefined;
+		table[(T_double<<4)+T_byte] 		= (Double2Double<<12)+(Byte2Double<<4)+T_boolean;
 		table[(T_double<<4)+T_long] 		= (Double2Double<<12)+(Long2Double<<4)+T_boolean;
-		table[(T_double<<4)+T_short] 		= (Double2Double<<12)+(Short2Double<<4)+T_boolean ;
-		//	table[(T_double<<4)+T_void] 		= T_undefined ;
-		//	table[(T_double<<4)+T_String] 		= T_undefined ;
-		//	table[(T_double<<4)+T_Object] 		= T_undefined ;
-		table[(T_double<<4)+T_double] 		= (Double2Double<<12)+(Double2Double<<4)+T_boolean ;
-		table[(T_double<<4)+T_float] 		= (Double2Double<<12)+(Float2Double<<4)+T_boolean ;
-		//	table[(T_double<<4)+T_boolean] 		= T_undefined ;
-		table[(T_double<<4)+T_char] 		= (Double2Double<<12)+(Char2Double<<4)+T_boolean ;
+		table[(T_double<<4)+T_short] 		= (Double2Double<<12)+(Short2Double<<4)+T_boolean;
+		//	table[(T_double<<4)+T_void] 		= T_undefined;
+		//	table[(T_double<<4)+T_String] 		= T_undefined;
+		//	table[(T_double<<4)+T_Object] 		= T_undefined;
+		table[(T_double<<4)+T_double] 		= (Double2Double<<12)+(Double2Double<<4)+T_boolean;
+		table[(T_double<<4)+T_float] 		= (Double2Double<<12)+(Float2Double<<4)+T_boolean;
+		//	table[(T_double<<4)+T_boolean] 		= T_undefined;
+		table[(T_double<<4)+T_char] 		= (Double2Double<<12)+(Char2Double<<4)+T_boolean;
 		table[(T_double<<4)+T_int] 			= (Double2Double<<12)+(Int2Double<<4)+T_boolean;
-		//	table[(T_double<<4)+T_null] 		= T_undefined ;
+		//	table[(T_double<<4)+T_null] 		= T_undefined;
 	
-		//	table[(T_float<<4)+T_undefined] 	= T_undefined ;
-		table[(T_float<<4)+T_byte] 			= (Float2Float<<12)+(Byte2Float<<4)+T_boolean ;
-		table[(T_float<<4)+T_long] 			= (Float2Float<<12)+(Long2Float<<4)+T_boolean ;
-		table[(T_float<<4)+T_short] 		= (Float2Float<<12)+(Short2Float<<4)+T_boolean ;
-		//	table[(T_float<<4)+T_void] 			= T_undefined ;
-		//	table[(T_float<<4)+T_String] 		= T_undefined ;
-		//	table[(T_float<<4)+T_Object] 		= T_undefined ;
-		table[(T_float<<4)+T_double] 		= (Float2Double<<12)+(Double2Double<<4)+T_boolean ;
-		table[(T_float<<4)+T_float] 		= (Float2Float<<12)+(Float2Float<<4)+T_boolean ;
-		//	table[(T_float<<4)+T_boolean] 		= T_undefined ;
-		table[(T_float<<4)+T_char] 			= (Float2Float<<12)+(Char2Float<<4)+T_boolean ;
-		table[(T_float<<4)+T_int] 			= (Float2Float<<12)+(Int2Float<<4)+T_boolean ;
-		//	table[(T_float<<4)+T_null] 			= T_undefined ;
+		//	table[(T_float<<4)+T_undefined] 	= T_undefined;
+		table[(T_float<<4)+T_byte] 			= (Float2Float<<12)+(Byte2Float<<4)+T_boolean;
+		table[(T_float<<4)+T_long] 			= (Float2Float<<12)+(Long2Float<<4)+T_boolean;
+		table[(T_float<<4)+T_short] 		= (Float2Float<<12)+(Short2Float<<4)+T_boolean;
+		//	table[(T_float<<4)+T_void] 			= T_undefined;
+		//	table[(T_float<<4)+T_String] 		= T_undefined;
+		//	table[(T_float<<4)+T_Object] 		= T_undefined;
+		table[(T_float<<4)+T_double] 		= (Float2Double<<12)+(Double2Double<<4)+T_boolean;
+		table[(T_float<<4)+T_float] 		= (Float2Float<<12)+(Float2Float<<4)+T_boolean;
+		//	table[(T_float<<4)+T_boolean] 		= T_undefined;
+		table[(T_float<<4)+T_char] 			= (Float2Float<<12)+(Char2Float<<4)+T_boolean;
+		table[(T_float<<4)+T_int] 			= (Float2Float<<12)+(Int2Float<<4)+T_boolean;
+		//	table[(T_float<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_boolean<<4)+T_undefined] 		= T_undefined ;
-		//	table[(T_boolean<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_long] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_short] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_void] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_String] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_Object] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_double] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_float] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_boolean<<4)+T_char] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_int] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_null] 			= T_undefined ;
+		//	table[(T_boolean<<4)+T_undefined] 		= T_undefined;
+		//	table[(T_boolean<<4)+T_byte] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_long] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_short] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_void] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_String] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_Object] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_double] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_float] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_boolean<<4)+T_char] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_int] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_null] 			= T_undefined;
 			
-		//	table[(T_char<<4)+T_undefined] 		= T_undefined ;
-		table[(T_char<<4)+T_byte] 			= (Char2Int<<12)+(Byte2Int<<4)+T_boolean ;
-		table[(T_char<<4)+T_long] 			= (Char2Long<<12)+(Long2Long<<4)+T_boolean ;
-		table[(T_char<<4)+T_short] 			= (Char2Int<<12)+(Short2Int<<4)+T_boolean ;
-		//	table[(T_char<<4)+T_void] 			= T_undefined ;
-		//	table[(T_char<<4)+T_String] 		= T_undefined ;
-		//	table[(T_char<<4)+T_Object] 		= T_undefined ;
-		table[(T_char<<4)+T_double] 		= (Char2Double<<12)+(Double2Double<<4)+T_boolean ;
-		table[(T_char<<4)+T_float] 			= (Char2Float<<12)+(Float2Float<<4)+T_boolean ;
-		//	table[(T_char<<4)+T_boolean] 		= T_undefined ;
-		table[(T_char<<4)+T_char] 			= (Char2Int<<12)+(Char2Int<<4)+T_boolean ;
-		table[(T_char<<4)+T_int] 			= (Char2Int<<12)+(Int2Int<<4)+T_boolean ;
-		//	table[(T_char<<4)+T_null] 			= T_undefined ;
+		//	table[(T_char<<4)+T_undefined] 		= T_undefined;
+		table[(T_char<<4)+T_byte] 			= (Char2Int<<12)+(Byte2Int<<4)+T_boolean;
+		table[(T_char<<4)+T_long] 			= (Char2Long<<12)+(Long2Long<<4)+T_boolean;
+		table[(T_char<<4)+T_short] 			= (Char2Int<<12)+(Short2Int<<4)+T_boolean;
+		//	table[(T_char<<4)+T_void] 			= T_undefined;
+		//	table[(T_char<<4)+T_String] 		= T_undefined;
+		//	table[(T_char<<4)+T_Object] 		= T_undefined;
+		table[(T_char<<4)+T_double] 		= (Char2Double<<12)+(Double2Double<<4)+T_boolean;
+		table[(T_char<<4)+T_float] 			= (Char2Float<<12)+(Float2Float<<4)+T_boolean;
+		//	table[(T_char<<4)+T_boolean] 		= T_undefined;
+		table[(T_char<<4)+T_char] 			= (Char2Int<<12)+(Char2Int<<4)+T_boolean;
+		table[(T_char<<4)+T_int] 			= (Char2Int<<12)+(Int2Int<<4)+T_boolean;
+		//	table[(T_char<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_int<<4)+T_undefined] 	= T_undefined ;
-		table[(T_int<<4)+T_byte] 		= (Int2Int<<12)+(Byte2Int<<4)+T_boolean ;
+		//	table[(T_int<<4)+T_undefined] 	= T_undefined;
+		table[(T_int<<4)+T_byte] 		= (Int2Int<<12)+(Byte2Int<<4)+T_boolean;
 		table[(T_int<<4)+T_long] 		= (Int2Long<<12)+(Long2Long<<4)+T_boolean;
-		table[(T_int<<4)+T_short] 		= (Int2Int<<12)+(Short2Int<<4)+T_boolean ;
-		//	table[(T_int<<4)+T_void] 		= T_undefined ;
-		//	table[(T_int<<4)+T_String] 		= T_undefined ;
-		//	table[(T_int<<4)+T_Object] 		= T_undefined ;
-		table[(T_int<<4)+T_double] 		= (Int2Double<<12)+(Double2Double<<4)+T_boolean ;
-		table[(T_int<<4)+T_float] 		= (Int2Float<<12)+(Float2Float<<4)+T_boolean ;
-		//	table[(T_int<<4)+T_boolean] 	= T_undefined ;
-		table[(T_int<<4)+T_char] 		= (Int2Int<<12)+(Char2Int<<4)+T_boolean ;
+		table[(T_int<<4)+T_short] 		= (Int2Int<<12)+(Short2Int<<4)+T_boolean;
+		//	table[(T_int<<4)+T_void] 		= T_undefined;
+		//	table[(T_int<<4)+T_String] 		= T_undefined;
+		//	table[(T_int<<4)+T_Object] 		= T_undefined;
+		table[(T_int<<4)+T_double] 		= (Int2Double<<12)+(Double2Double<<4)+T_boolean;
+		table[(T_int<<4)+T_float] 		= (Int2Float<<12)+(Float2Float<<4)+T_boolean;
+		//	table[(T_int<<4)+T_boolean] 	= T_undefined;
+		table[(T_int<<4)+T_char] 		= (Int2Int<<12)+(Char2Int<<4)+T_boolean;
 		table[(T_int<<4)+T_int] 		= (Int2Int<<12)+(Int2Int<<4)+T_boolean;
-		//	table[(T_int<<4)+T_null] 		= T_undefined ;
+		//	table[(T_int<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_null<<4)+T_undefined] 		= T_undefined ;
-		//	table[(T_null<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_null<<4)+T_long] 			= T_undefined ;
-		//	table[(T_null<<4)+T_short] 			= T_undefined ;
-		//	table[(T_null<<4)+T_void] 			= T_undefined ;
-		//	table[(T_null<<4)+T_String] 		= T_undefined ;
-		//	table[(T_null<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_null<<4)+T_double] 		= T_undefined ;
-		//	table[(T_null<<4)+T_float] 			= T_undefined ;
-		//	table[(T_null<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_null<<4)+T_char] 			= T_undefined ;
-		//	table[(T_null<<4)+T_int] 			= T_undefined ;
-		//	table[(T_null<<4)+T_null] 			= T_undefined ;
+		//	table[(T_null<<4)+T_undefined] 		= T_undefined;
+		//	table[(T_null<<4)+T_byte] 			= T_undefined;
+		//	table[(T_null<<4)+T_long] 			= T_undefined;
+		//	table[(T_null<<4)+T_short] 			= T_undefined;
+		//	table[(T_null<<4)+T_void] 			= T_undefined;
+		//	table[(T_null<<4)+T_String] 		= T_undefined;
+		//	table[(T_null<<4)+T_Object] 		= T_undefined;
+		//	table[(T_null<<4)+T_double] 		= T_undefined;
+		//	table[(T_null<<4)+T_float] 			= T_undefined;
+		//	table[(T_null<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_null<<4)+T_char] 			= T_undefined;
+		//	table[(T_null<<4)+T_int] 			= T_undefined;
+		//	table[(T_null<<4)+T_null] 			= T_undefined;
 	
-		return table ;
+		return table;
 	}
 
 	public static final int[] get_LESS_EQUAL(){
@@ -1184,7 +1184,7 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		//	int[] table  = new int[16*16] ;
+		//	int[] table  = new int[16*16];
 		return get_LESS();
 	}
 
@@ -1195,39 +1195,39 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		int[] table  = new int[16*16] ;
+		int[] table  = new int[16*16];
 	
 		table = (int[]) get_PLUS().clone();
 
 		// customization	
-		table[(T_String<<4)+T_byte] 		= T_undefined ;
-		table[(T_String<<4)+T_long] 		= T_undefined ;
-		table[(T_String<<4)+T_short] 		= T_undefined ;
-		table[(T_String<<4)+T_void] 		= T_undefined ;
-		table[(T_String<<4)+T_String] 		= T_undefined ;
-		table[(T_String<<4)+T_Object] 		= T_undefined ;
-		table[(T_String<<4)+T_double] 		= T_undefined ;
-		table[(T_String<<4)+T_float] 		= T_undefined ;
-		table[(T_String<<4)+T_boolean] 		= T_undefined ;
-		table[(T_String<<4)+T_char] 		= T_undefined ;
-		table[(T_String<<4)+T_int] 			= T_undefined ;
-		table[(T_String<<4)+T_null] 		= T_undefined ;
+		table[(T_String<<4)+T_byte] 		= T_undefined;
+		table[(T_String<<4)+T_long] 		= T_undefined;
+		table[(T_String<<4)+T_short] 		= T_undefined;
+		table[(T_String<<4)+T_void] 		= T_undefined;
+		table[(T_String<<4)+T_String] 		= T_undefined;
+		table[(T_String<<4)+T_Object] 		= T_undefined;
+		table[(T_String<<4)+T_double] 		= T_undefined;
+		table[(T_String<<4)+T_float] 		= T_undefined;
+		table[(T_String<<4)+T_boolean] 		= T_undefined;
+		table[(T_String<<4)+T_char] 		= T_undefined;
+		table[(T_String<<4)+T_int] 			= T_undefined;
+		table[(T_String<<4)+T_null] 		= T_undefined;
 		
-		table[(T_byte<<4)	+T_String] 		= T_undefined ;
-		table[(T_long<<4)	+T_String] 		= T_undefined ;
-		table[(T_short<<4)	+T_String] 		= T_undefined ;
-		table[(T_void<<4)	+T_String] 		= T_undefined ;
-		table[(T_Object<<4)	+T_String] 		= T_undefined ;
-		table[(T_double<<4)	+T_String] 		= T_undefined ;
-		table[(T_float<<4)	+T_String] 		= T_undefined ;
-		table[(T_boolean<<4)+T_String] 		= T_undefined ;
-		table[(T_char<<4)	+T_String] 		= T_undefined ;
-		table[(T_int<<4)	+T_String] 		= T_undefined ;
-		table[(T_null<<4)	+T_String] 		= T_undefined ;
+		table[(T_byte<<4)	+T_String] 		= T_undefined;
+		table[(T_long<<4)	+T_String] 		= T_undefined;
+		table[(T_short<<4)	+T_String] 		= T_undefined;
+		table[(T_void<<4)	+T_String] 		= T_undefined;
+		table[(T_Object<<4)	+T_String] 		= T_undefined;
+		table[(T_double<<4)	+T_String] 		= T_undefined;
+		table[(T_float<<4)	+T_String] 		= T_undefined;
+		table[(T_boolean<<4)+T_String] 		= T_undefined;
+		table[(T_char<<4)	+T_String] 		= T_undefined;
+		table[(T_int<<4)	+T_String] 		= T_undefined;
+		table[(T_null<<4)	+T_String] 		= T_undefined;
 		
-		table[(T_null<<4)	+T_null] 		= T_undefined ;
+		table[(T_null<<4)	+T_null] 		= T_undefined;
 	
-		return table ;
+		return table;
 	}
 
 	public static final int[] get_MULTIPLY(){
@@ -1237,7 +1237,7 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		//	int[] table  = new int[16*16] ;
+		//	int[] table  = new int[16*16];
 		return get_MINUS();
 	}
 
@@ -1249,8 +1249,8 @@
 		//  <<16   <<12       <<8    <<4       
 		
 		
-		//	int[] table  = new int[16*16] ;
-		return get_AND() ;
+		//	int[] table  = new int[16*16];
+		return get_AND();
 	}
 
 	public static final int[] get_OR_OR(){
@@ -1260,8 +1260,8 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		//	int[] table  = new int[16*16] ;
-		return get_AND_AND() ;
+		//	int[] table  = new int[16*16];
+		return get_AND_AND();
 	}
 
 	public static final int[] get_PLUS(){
@@ -1271,191 +1271,191 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		int[] table  = new int[16*16] ;
+		int[] table  = new int[16*16];
 		
-		//	table[(T_undefined<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_undefined<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_long] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_short] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_void] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_String] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_double] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_float] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_undefined<<4)+T_char] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_int] 			= T_undefined ;
-		//	table[(T_undefined<<4)+T_null] 			= T_undefined ;
+		//	table[(T_undefined<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_undefined<<4)+T_byte] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_long] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_short] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_void] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_String] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_Object] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_double] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_float] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_undefined<<4)+T_char] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_int] 			= T_undefined;
+		//	table[(T_undefined<<4)+T_null] 			= T_undefined;
 			
-		//	table[(T_byte<<4)+T_undefined] 	= T_undefined ;
-		table[(T_byte<<4)+T_byte] 		= (Byte2Int<<12)+(Byte2Int<<4)+T_int ;
-		table[(T_byte<<4)+T_long] 		= (Byte2Long<<12)+(Long2Long<<4)+T_long ;
-		table[(T_byte<<4)+T_short] 		= (Byte2Int<<12)+(Short2Int<<4)+T_int ;
-		//	table[(T_byte<<4)+T_void] 		= T_undefined ;
-		table[(T_byte<<4)+T_String] 	= (Byte2Byte<<12)+(String2String<<4)+T_String ;
-		//	table[(T_byte<<4)+T_Object] 	= T_undefined ;
-		table[(T_byte<<4)+T_double] 	= (Byte2Double<<12)+(Double2Double<<4)+T_double ;
+		//	table[(T_byte<<4)+T_undefined] 	= T_undefined;
+		table[(T_byte<<4)+T_byte] 		= (Byte2Int<<12)+(Byte2Int<<4)+T_int;
+		table[(T_byte<<4)+T_long] 		= (Byte2Long<<12)+(Long2Long<<4)+T_long;
+		table[(T_byte<<4)+T_short] 		= (Byte2Int<<12)+(Short2Int<<4)+T_int;
+		//	table[(T_byte<<4)+T_void] 		= T_undefined;
+		table[(T_byte<<4)+T_String] 	= (Byte2Byte<<12)+(String2String<<4)+T_String;
+		//	table[(T_byte<<4)+T_Object] 	= T_undefined;
+		table[(T_byte<<4)+T_double] 	= (Byte2Double<<12)+(Double2Double<<4)+T_double;
 		table[(T_byte<<4)+T_float] 		= (Byte2Float<<12)+(Float2Float<<4)+T_float;
-		//	table[(T_byte<<4)+T_boolean] 	= T_undefined ;
-		table[(T_byte<<4)+T_char] 		= (Byte2Int<<12)+(Char2Int<<4)+T_int ;
-		table[(T_byte<<4)+T_int] 		= (Byte2Int<<12)+(Int2Int<<4)+T_int ;
-		//	table[(T_byte<<4)+T_null] 		= T_undefined ;
+		//	table[(T_byte<<4)+T_boolean] 	= T_undefined;
+		table[(T_byte<<4)+T_char] 		= (Byte2Int<<12)+(Char2Int<<4)+T_int;
+		table[(T_byte<<4)+T_int] 		= (Byte2Int<<12)+(Int2Int<<4)+T_int;
+		//	table[(T_byte<<4)+T_null] 		= T_undefined;
 	
-		//	table[(T_long<<4)+T_undefined] 	= T_undefined ;
+		//	table[(T_long<<4)+T_undefined] 	= T_undefined;
 		table[(T_long<<4)+T_byte] 		= (Long2Long<<12)+(Byte2Long<<4)+T_long;
-		table[(T_long<<4)+T_long] 		= (Long2Long<<12)+(Long2Long<<4)+T_long ;
-		table[(T_long<<4)+T_short] 		= (Long2Long<<12)+(Short2Long<<4)+T_long ;
-		//	table[(T_long<<4)+T_void] 		= T_undefined ;
-		table[(T_long<<4)+T_String] 	= (Long2Long<<12)+(String2String<<4)+T_String ;
-		//	table[(T_long<<4)+T_Object] 	= T_undefined ;
-		table[(T_long<<4)+T_double] 	= (Long2Double<<12)+(Double2Double<<4)+T_double ;
-		table[(T_long<<4)+T_float] 		= (Long2Float<<12)+(Float2Float<<4)+T_float ;
-		//	table[(T_long<<4)+T_boolean] 	= T_undefined ;
-		table[(T_long<<4)+T_char] 		= (Long2Long<<12)+(Char2Long<<4)+T_long ;
-		table[(T_long<<4)+T_int] 		= (Long2Long<<12)+(Int2Long<<4)+T_long ; ;
-		//	table[(T_long<<4)+T_null] 		= T_undefined ;
+		table[(T_long<<4)+T_long] 		= (Long2Long<<12)+(Long2Long<<4)+T_long;
+		table[(T_long<<4)+T_short] 		= (Long2Long<<12)+(Short2Long<<4)+T_long;
+		//	table[(T_long<<4)+T_void] 		= T_undefined;
+		table[(T_long<<4)+T_String] 	= (Long2Long<<12)+(String2String<<4)+T_String;
+		//	table[(T_long<<4)+T_Object] 	= T_undefined;
+		table[(T_long<<4)+T_double] 	= (Long2Double<<12)+(Double2Double<<4)+T_double;
+		table[(T_long<<4)+T_float] 		= (Long2Float<<12)+(Float2Float<<4)+T_float;
+		//	table[(T_long<<4)+T_boolean] 	= T_undefined;
+		table[(T_long<<4)+T_char] 		= (Long2Long<<12)+(Char2Long<<4)+T_long;
+		table[(T_long<<4)+T_int] 		= (Long2Long<<12)+(Int2Long<<4)+T_long; 
+		//	table[(T_long<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_short<<4)+T_undefined] 	= T_undefined ;
-		table[(T_short<<4)+T_byte] 			= (Short2Int<<12)+(Byte2Int<<4)+T_int ;
-		table[(T_short<<4)+T_long] 			= (Short2Long<<12)+(Long2Long<<4)+T_long ;
-		table[(T_short<<4)+T_short] 		= (Short2Int<<12)+(Short2Int<<4)+T_int ;
-		//	table[(T_short<<4)+T_void] 			= T_undefined ;
-		table[(T_short<<4)+T_String] 		= (Short2Short<<12)+(String2String<<4)+T_String ;
-		//	table[(T_short<<4)+T_Object] 		= T_undefined ;
-		table[(T_short<<4)+T_double] 		= (Short2Double<<12)+(Double2Double<<4)+T_double ;
-		table[(T_short<<4)+T_float] 		= (Short2Float<<12)+(Float2Float<<4)+T_float ;
-		//	table[(T_short<<4)+T_boolean] 		= T_undefined ;
-		table[(T_short<<4)+T_char] 			= (Short2Int<<12)+(Char2Int<<4)+T_int ;
-		table[(T_short<<4)+T_int] 			= (Short2Int<<12)+(Int2Int<<4)+T_int ;
-		//	table[(T_short<<4)+T_null] 			= T_undefined ;
+		//	table[(T_short<<4)+T_undefined] 	= T_undefined;
+		table[(T_short<<4)+T_byte] 			= (Short2Int<<12)+(Byte2Int<<4)+T_int;
+		table[(T_short<<4)+T_long] 			= (Short2Long<<12)+(Long2Long<<4)+T_long;
+		table[(T_short<<4)+T_short] 		= (Short2Int<<12)+(Short2Int<<4)+T_int;
+		//	table[(T_short<<4)+T_void] 			= T_undefined;
+		table[(T_short<<4)+T_String] 		= (Short2Short<<12)+(String2String<<4)+T_String;
+		//	table[(T_short<<4)+T_Object] 		= T_undefined;
+		table[(T_short<<4)+T_double] 		= (Short2Double<<12)+(Double2Double<<4)+T_double;
+		table[(T_short<<4)+T_float] 		= (Short2Float<<12)+(Float2Float<<4)+T_float;
+		//	table[(T_short<<4)+T_boolean] 		= T_undefined;
+		table[(T_short<<4)+T_char] 			= (Short2Int<<12)+(Char2Int<<4)+T_int;
+		table[(T_short<<4)+T_int] 			= (Short2Int<<12)+(Int2Int<<4)+T_int;
+		//	table[(T_short<<4)+T_null] 			= T_undefined;
 	
-		//	table[(T_void<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_void<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_void<<4)+T_long] 		= T_undefined ;
-		//	table[(T_void<<4)+T_short] 		= T_undefined ;
-		//	table[(T_void<<4)+T_void] 		= T_undefined ;
-		//	table[(T_void<<4)+T_String] 	= T_undefined ;
-		//	table[(T_void<<4)+T_Object] 	= T_undefined ;
-		//	table[(T_void<<4)+T_double] 	= T_undefined ;
-		//	table[(T_void<<4)+T_float] 		= T_undefined ;
-		//	table[(T_void<<4)+T_boolean] 	= T_undefined ;
-		//	table[(T_void<<4)+T_char] 		= T_undefined ;
-		//	table[(T_void<<4)+T_int] 		= T_undefined ;
-		//	table[(T_void<<4)+T_null] 		= T_undefined ;
+		//	table[(T_void<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_void<<4)+T_byte] 		= T_undefined;
+		//	table[(T_void<<4)+T_long] 		= T_undefined;
+		//	table[(T_void<<4)+T_short] 		= T_undefined;
+		//	table[(T_void<<4)+T_void] 		= T_undefined;
+		//	table[(T_void<<4)+T_String] 	= T_undefined;
+		//	table[(T_void<<4)+T_Object] 	= T_undefined;
+		//	table[(T_void<<4)+T_double] 	= T_undefined;
+		//	table[(T_void<<4)+T_float] 		= T_undefined;
+		//	table[(T_void<<4)+T_boolean] 	= T_undefined;
+		//	table[(T_void<<4)+T_char] 		= T_undefined;
+		//	table[(T_void<<4)+T_int] 		= T_undefined;
+		//	table[(T_void<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_String<<4)+T_undefined] 	= T_undefined ; 
-		table[(T_String<<4)+T_byte] 		= (String2String<<12)+(Byte2Byte<<4)+T_String ;
-		table[(T_String<<4)+T_long] 		= (String2String<<12)+(Long2Long<<4)+T_String ; 
-		table[(T_String<<4)+T_short] 		= (String2String<<12)+(Short2Short<<4)+T_String ;
-		//	table[(T_String<<4)+T_void] 		= T_undefined ;
-		table[(T_String<<4)+T_String] 		= (String2String<<12)+(String2String<<4)+T_String ;
-		table[(T_String<<4)+T_Object] 		= (String2String<<12)+(Object2Object<<4)+T_String ;
-		table[(T_String<<4)+T_double] 		= (String2String<<12)+(Double2Double<<4)+T_String ;
-		table[(T_String<<4)+T_float] 		= (String2String<<12)+(Float2Float<<4)+T_String ; 
-		table[(T_String<<4)+T_boolean] 		= (String2String<<12)+(Boolean2Boolean<<4)+T_String ;
-		table[(T_String<<4)+T_char] 		= (String2String<<12)+(Char2Char<<4)+T_String ;
-		table[(T_String<<4)+T_int] 			= (String2String<<12)+(Int2Int<<4)+T_String ;
-		table[(T_String<<4)+T_null] 		= (String2String<<12)+(T_null<<8)+(T_null<<4)+T_String ;
+		//	table[(T_String<<4)+T_undefined] 	= T_undefined; 
+		table[(T_String<<4)+T_byte] 		= (String2String<<12)+(Byte2Byte<<4)+T_String;
+		table[(T_String<<4)+T_long] 		= (String2String<<12)+(Long2Long<<4)+T_String; 
+		table[(T_String<<4)+T_short] 		= (String2String<<12)+(Short2Short<<4)+T_String;
+		//	table[(T_String<<4)+T_void] 		= T_undefined;
+		table[(T_String<<4)+T_String] 		= (String2String<<12)+(String2String<<4)+T_String;
+		table[(T_String<<4)+T_Object] 		= (String2String<<12)+(Object2Object<<4)+T_String;
+		table[(T_String<<4)+T_double] 		= (String2String<<12)+(Double2Double<<4)+T_String;
+		table[(T_String<<4)+T_float] 		= (String2String<<12)+(Float2Float<<4)+T_String; 
+		table[(T_String<<4)+T_boolean] 		= (String2String<<12)+(Boolean2Boolean<<4)+T_String;
+		table[(T_String<<4)+T_char] 		= (String2String<<12)+(Char2Char<<4)+T_String;
+		table[(T_String<<4)+T_int] 			= (String2String<<12)+(Int2Int<<4)+T_String;
+		table[(T_String<<4)+T_null] 		= (String2String<<12)+(T_null<<8)+(T_null<<4)+T_String;
 	
-		//	table[(T_Object<<4)+T_undefined] 	= T_undefined ;
-		//	table[(T_Object<<4)+T_byte] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_long] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_short]		= T_undefined ;
-		//	table[(T_Object<<4)+T_void] 		= T_undefined ;
-		table[(T_Object<<4)+T_String] 		= (Object2Object<<12)+(String2String<<4)+T_String ;
-		//	table[(T_Object<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_double] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_float] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_boolean]		= T_undefined ;
-		//	table[(T_Object<<4)+T_char] 		= T_undefined ;
-		//	table[(T_Object<<4)+T_int] 			= T_undefined ;
-		//	table[(T_Object<<4)+T_null] 		= T_undefined ;
+		//	table[(T_Object<<4)+T_undefined] 	= T_undefined;
+		//	table[(T_Object<<4)+T_byte] 		= T_undefined;
+		//	table[(T_Object<<4)+T_long] 		= T_undefined;
+		//	table[(T_Object<<4)+T_short]		= T_undefined;
+		//	table[(T_Object<<4)+T_void] 		= T_undefined;
+		table[(T_Object<<4)+T_String] 		= (Object2Object<<12)+(String2String<<4)+T_String;
+		//	table[(T_Object<<4)+T_Object] 		= T_undefined;
+		//	table[(T_Object<<4)+T_double] 		= T_undefined;
+		//	table[(T_Object<<4)+T_float] 		= T_undefined;
+		//	table[(T_Object<<4)+T_boolean]		= T_undefined;
+		//	table[(T_Object<<4)+T_char] 		= T_undefined;
+		//	table[(T_Object<<4)+T_int] 			= T_undefined;
+		//	table[(T_Object<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_double<<4)+T_undefined] 	= T_undefined ;
-		table[(T_double<<4)+T_byte] 		= (Double2Double<<12)+(Byte2Double<<4)+T_double ;
-		table[(T_double<<4)+T_long] 		= (Double2Double<<12)+(Long2Double<<4)+T_double ;
-		table[(T_double<<4)+T_short] 		= (Double2Double<<12)+(Short2Double<<4)+T_double ; ;
-		//	table[(T_double<<4)+T_void] 		= T_undefined ;
-		table[(T_double<<4)+T_String] 		= (Double2Double<<12)+(String2String<<4)+T_String ;
-		//	table[(T_double<<4)+T_Object] 		= T_undefined ;
-		table[(T_double<<4)+T_double] 		= (Double2Double<<12)+(Double2Double<<4)+T_double ;
-		table[(T_double<<4)+T_float] 		= (Double2Double<<12)+(Float2Double<<4)+T_double ; ;
-		//	table[(T_double<<4)+T_boolean] 		= T_undefined ;
-		table[(T_double<<4)+T_char] 		= (Double2Double<<12)+(Char2Double<<4)+T_double ; ;
-		table[(T_double<<4)+T_int] 			= (Double2Double<<12)+(Int2Double<<4)+T_double ; ;
-		//	table[(T_double<<4)+T_null] 		= T_undefined ;
+		//	table[(T_double<<4)+T_undefined] 	= T_undefined;
+		table[(T_double<<4)+T_byte] 		= (Double2Double<<12)+(Byte2Double<<4)+T_double;
+		table[(T_double<<4)+T_long] 		= (Double2Double<<12)+(Long2Double<<4)+T_double;
+		table[(T_double<<4)+T_short] 		= (Double2Double<<12)+(Short2Double<<4)+T_double; 
+		//	table[(T_double<<4)+T_void] 		= T_undefined;
+		table[(T_double<<4)+T_String] 		= (Double2Double<<12)+(String2String<<4)+T_String;
+		//	table[(T_double<<4)+T_Object] 		= T_undefined;
+		table[(T_double<<4)+T_double] 		= (Double2Double<<12)+(Double2Double<<4)+T_double;
+		table[(T_double<<4)+T_float] 		= (Double2Double<<12)+(Float2Double<<4)+T_double; 
+		//	table[(T_double<<4)+T_boolean] 		= T_undefined;
+		table[(T_double<<4)+T_char] 		= (Double2Double<<12)+(Char2Double<<4)+T_double; 
+		table[(T_double<<4)+T_int] 			= (Double2Double<<12)+(Int2Double<<4)+T_double; 
+		//	table[(T_double<<4)+T_null] 		= T_undefined;
 		
-		//	table[(T_float<<4)+T_undefined] 	= T_undefined ;
-		table[(T_float<<4)+T_byte] 			= (Float2Float<<12)+(Byte2Float<<4)+T_float ;
-		table[(T_float<<4)+T_long] 			= (Float2Float<<12)+(Long2Float<<4)+T_float ;
-		table[(T_float<<4)+T_short] 		= (Float2Float<<12)+(Short2Float<<4)+T_float ;
-		//	table[(T_float<<4)+T_void] 			= T_undefined ;
-		table[(T_float<<4)+T_String] 		= (Float2Float<<12)+(String2String<<4)+T_String ;
-		//	table[(T_float<<4)+T_Object] 		= T_undefined ;
-		table[(T_float<<4)+T_double] 		= (Float2Double<<12)+(Double2Double<<4)+T_double ;
-		table[(T_float<<4)+T_float] 		= (Float2Float<<12)+(Float2Float<<4)+T_float ;
-		//	table[(T_float<<4)+T_boolean] 		= T_undefined ;
-		table[(T_float<<4)+T_char] 			= (Float2Float<<12)+(Char2Float<<4)+T_float ;
-		table[(T_float<<4)+T_int] 			= (Float2Float<<12)+(Int2Float<<4)+T_float ;
-		//	table[(T_float<<4)+T_null] 			= T_undefined ;
+		//	table[(T_float<<4)+T_undefined] 	= T_undefined;
+		table[(T_float<<4)+T_byte] 			= (Float2Float<<12)+(Byte2Float<<4)+T_float;
+		table[(T_float<<4)+T_long] 			= (Float2Float<<12)+(Long2Float<<4)+T_float;
+		table[(T_float<<4)+T_short] 		= (Float2Float<<12)+(Short2Float<<4)+T_float;
+		//	table[(T_float<<4)+T_void] 			= T_undefined;
+		table[(T_float<<4)+T_String] 		= (Float2Float<<12)+(String2String<<4)+T_String;
+		//	table[(T_float<<4)+T_Object] 		= T_undefined;
+		table[(T_float<<4)+T_double] 		= (Float2Double<<12)+(Double2Double<<4)+T_double;
+		table[(T_float<<4)+T_float] 		= (Float2Float<<12)+(Float2Float<<4)+T_float;
+		//	table[(T_float<<4)+T_boolean] 		= T_undefined;
+		table[(T_float<<4)+T_char] 			= (Float2Float<<12)+(Char2Float<<4)+T_float;
+		table[(T_float<<4)+T_int] 			= (Float2Float<<12)+(Int2Float<<4)+T_float;
+		//	table[(T_float<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_boolean<<4)+T_undefined] 		= T_undefined ;
-		//	table[(T_boolean<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_long] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_short] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_void] 			= T_undefined ;
-		table[(T_boolean<<4)+T_String] 			= (Boolean2Boolean<<12)+(String2String<<4)+T_String ;
-		//	table[(T_boolean<<4)+T_Object] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_double] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_float] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_boolean<<4)+T_char] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_int] 			= T_undefined ;
-		//	table[(T_boolean<<4)+T_null] 			= T_undefined ;
+		//	table[(T_boolean<<4)+T_undefined] 		= T_undefined;
+		//	table[(T_boolean<<4)+T_byte] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_long] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_short] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_void] 			= T_undefined;
+		table[(T_boolean<<4)+T_String] 			= (Boolean2Boolean<<12)+(String2String<<4)+T_String;
+		//	table[(T_boolean<<4)+T_Object] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_double] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_float] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_boolean<<4)+T_char] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_int] 			= T_undefined;
+		//	table[(T_boolean<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_char<<4)+T_undefined] 		= T_undefined ;
-		table[(T_char<<4)+T_byte] 			= (Char2Int<<12)+(Byte2Int<<4)+T_int ;
-		table[(T_char<<4)+T_long] 			= (Char2Long<<12)+(Long2Long<<4)+T_long ;
-		table[(T_char<<4)+T_short] 			= (Char2Int<<12)+(Short2Int<<4)+T_int ;
-		//	table[(T_char<<4)+T_void] 			= T_undefined ;
-		table[(T_char<<4)+T_String] 		= (Char2Char<<12)+(String2String<<4)+T_String ;
-		//	table[(T_char<<4)+T_Object] 		= T_undefined ;
-		table[(T_char<<4)+T_double] 		= (Char2Double<<12)+(Double2Double<<4)+T_double ;
-		table[(T_char<<4)+T_float] 			= (Char2Float<<12)+(Float2Float<<4)+T_float ;
-		//	table[(T_char<<4)+T_boolean] 		= T_undefined ;
-		table[(T_char<<4)+T_char] 			= (Char2Int<<12)+(Char2Int<<4)+T_int ; ;
-		table[(T_char<<4)+T_int] 			= (Char2Int<<12)+(Int2Int<<4)+T_int ;
-		//	table[(T_char<<4)+T_null] 			= T_undefined ;
+		//	table[(T_char<<4)+T_undefined] 		= T_undefined;
+		table[(T_char<<4)+T_byte] 			= (Char2Int<<12)+(Byte2Int<<4)+T_int;
+		table[(T_char<<4)+T_long] 			= (Char2Long<<12)+(Long2Long<<4)+T_long;
+		table[(T_char<<4)+T_short] 			= (Char2Int<<12)+(Short2Int<<4)+T_int;
+		//	table[(T_char<<4)+T_void] 			= T_undefined;
+		table[(T_char<<4)+T_String] 		= (Char2Char<<12)+(String2String<<4)+T_String;
+		//	table[(T_char<<4)+T_Object] 		= T_undefined;
+		table[(T_char<<4)+T_double] 		= (Char2Double<<12)+(Double2Double<<4)+T_double;
+		table[(T_char<<4)+T_float] 			= (Char2Float<<12)+(Float2Float<<4)+T_float;
+		//	table[(T_char<<4)+T_boolean] 		= T_undefined;
+		table[(T_char<<4)+T_char] 			= (Char2Int<<12)+(Char2Int<<4)+T_int;
+		table[(T_char<<4)+T_int] 			= (Char2Int<<12)+(Int2Int<<4)+T_int;
+		//	table[(T_char<<4)+T_null] 			= T_undefined;
 		
-		//	table[(T_int<<4)+T_undefined] 	= T_undefined ;
-		table[(T_int<<4)+T_byte] 		= (Int2Int<<12)+(Byte2Int<<4)+T_int ;
-		table[(T_int<<4)+T_long] 		= (Int2Long<<12)+(Long2Long<<4)+T_long ;
-		table[(T_int<<4)+T_short] 		= (Int2Int<<12)+(Short2Int<<4)+T_int ;
-		//	table[(T_int<<4)+T_void] 		= T_undefined ;
-		table[(T_int<<4)+T_String] 		= (Int2Int<<12)+(String2String<<4)+T_String ;
-		//	table[(T_int<<4)+T_Object] 		= T_undefined ;
-		table[(T_int<<4)+T_double] 		= (Int2Double<<12)+(Double2Double<<4)+T_double ;
-		table[(T_int<<4)+T_float] 		= (Int2Float<<12)+(Float2Float<<4)+T_float ;
-		//	table[(T_int<<4)+T_boolean] 	= T_undefined ;
-		table[(T_int<<4)+T_char] 		= (Int2Int<<12)+(Char2Int<<4)+T_int ;
-		table[(T_int<<4)+T_int] 		= (Int2Int<<12)+(Int2Int<<4)+T_int ;
-		//	table[(T_int<<4)+T_null] 		= T_undefined ;
+		//	table[(T_int<<4)+T_undefined] 	= T_undefined;
+		table[(T_int<<4)+T_byte] 		= (Int2Int<<12)+(Byte2Int<<4)+T_int;
+		table[(T_int<<4)+T_long] 		= (Int2Long<<12)+(Long2Long<<4)+T_long;
+		table[(T_int<<4)+T_short] 		= (Int2Int<<12)+(Short2Int<<4)+T_int;
+		//	table[(T_int<<4)+T_void] 		= T_undefined;
+		table[(T_int<<4)+T_String] 		= (Int2Int<<12)+(String2String<<4)+T_String;
+		//	table[(T_int<<4)+T_Object] 		= T_undefined;
+		table[(T_int<<4)+T_double] 		= (Int2Double<<12)+(Double2Double<<4)+T_double;
+		table[(T_int<<4)+T_float] 		= (Int2Float<<12)+(Float2Float<<4)+T_float;
+		//	table[(T_int<<4)+T_boolean] 	= T_undefined;
+		table[(T_int<<4)+T_char] 		= (Int2Int<<12)+(Char2Int<<4)+T_int;
+		table[(T_int<<4)+T_int] 		= (Int2Int<<12)+(Int2Int<<4)+T_int;
+		//	table[(T_int<<4)+T_null] 		= T_undefined;
 	
-		//	table[(T_null<<4)+T_undefined] 		= T_undefined ;
-		//	table[(T_null<<4)+T_byte] 			= T_undefined ;
-		//	table[(T_null<<4)+T_long] 			= T_undefined ;
-		//	table[(T_null<<4)+T_short] 			= T_undefined ;
-		//	table[(T_null<<4)+T_void] 			= T_undefined ;
-		table[(T_null<<4)+T_String] 		= (T_null<<16)+(T_null<<12)+(String2String<<4)+T_String ;
-		//	table[(T_null<<4)+T_Object] 		= T_undefined ;
-		//	table[(T_null<<4)+T_double] 		= T_undefined ;
-		//	table[(T_null<<4)+T_float] 			= T_undefined ;
-		//	table[(T_null<<4)+T_boolean] 		= T_undefined ;
-		//	table[(T_null<<4)+T_char] 			= T_undefined ;
-		//	table[(T_null<<4)+T_int] 			= T_undefined ;
-		//	table[(T_null<<4)+T_null] 			= (Null2String<<12)+(Null2String<<4)+T_String ;;
+		//	table[(T_null<<4)+T_undefined] 		= T_undefined;
+		//	table[(T_null<<4)+T_byte] 			= T_undefined;
+		//	table[(T_null<<4)+T_long] 			= T_undefined;
+		//	table[(T_null<<4)+T_short] 			= T_undefined;
+		//	table[(T_null<<4)+T_void] 			= T_undefined;
+		table[(T_null<<4)+T_String] 		= (T_null<<16)+(T_null<<12)+(String2String<<4)+T_String;
+		//	table[(T_null<<4)+T_Object] 		= T_undefined;
+		//	table[(T_null<<4)+T_double] 		= T_undefined;
+		//	table[(T_null<<4)+T_float] 			= T_undefined;
+		//	table[(T_null<<4)+T_boolean] 		= T_undefined;
+		//	table[(T_null<<4)+T_char] 			= T_undefined;
+		//	table[(T_null<<4)+T_int] 			= T_undefined;
+		//	table[(T_null<<4)+T_null] 			= (Null2String<<12)+(Null2String<<4)+T_String;;
 	
-		return table ;
+		return table;
 	}
 
 	public static final int[] get_REMAINDER(){
@@ -1465,7 +1465,7 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		//	int[] table  = new int[16*16] ;
+		//	int[] table  = new int[16*16];
 		return get_MINUS();
 	}
 
@@ -1476,7 +1476,7 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		//	int[] table  = new int[16*16] ;
+		//	int[] table  = new int[16*16];
 		return get_LEFT_SHIFT();
 	}
 
@@ -1487,7 +1487,7 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 		
-		//	int[] table  = new int[16*16] ;
+		//	int[] table  = new int[16*16];
 		return get_LEFT_SHIFT();
 	}
 
@@ -1498,8 +1498,8 @@
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       
 
-		//	int[] table  = new int[16*16] ;
-		return get_AND() ;
+		//	int[] table  = new int[16*16];
+		return get_AND();
 	}
 	
 	public String operatorToString() {
@@ -1550,15 +1550,15 @@
 				return "?:"; //$NON-NLS-1$
 			case EQUAL :
 				return "="; //$NON-NLS-1$
-		};
+		}
 		return "unknown operator"; //$NON-NLS-1$
 	}
 
-	public String toStringExpression(){
+	public StringBuffer printExpression(int indent, StringBuffer output){
 
-		//subclass redefine toStringExpressionNoParenthesis()
-		return	"(" + toStringExpressionNoParenthesis() + ")";  //$NON-NLS-2$ //$NON-NLS-1$
+		output.append('(');
+		return printExpressionNoParenthesis(0, output).append(')');
 	}
 	
-	public abstract String toStringExpressionNoParenthesis();
+	public abstract StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PostfixExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PostfixExpression.java
index 99fbeb8..5c85e72 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PostfixExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PostfixExpression.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
@@ -57,17 +57,17 @@
 		return "unknown operator"; //$NON-NLS-1$
 	}
 	
+	public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+
+		return lhs.printExpression(indent, output).append(' ').append(operatorToString()); 
+	} 
+
 	public boolean restrainUsageToNumericTypes() {
 
 		return true;
 	}
 	
-	public String toStringExpressionNoParenthesis() {
-
-		return lhs.toStringExpression() + " " + operatorToString(); //$NON-NLS-1$
-	} 
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
 			lhs.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PrefixExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PrefixExpression.java
index e94e9ac..84bffa6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PrefixExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/PrefixExpression.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class PrefixExpression extends CompoundAssignment {
@@ -39,18 +39,18 @@
 		return "unknown operator"; //$NON-NLS-1$
 	}
 
+	public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+
+		output.append(operatorToString()).append(' ');
+		return lhs.printExpression(0, output); 
+	} 
+	
 	public boolean restrainUsageToNumericTypes() {
 
 		return true;
 	}
 
-	public String toStringExpressionNoParenthesis() {
-
-		return operatorToString() + " " + lhs.toStringExpression(); //$NON-NLS-1$
-
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
 			lhs.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index c641a0c..8a16b9d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -22,13 +22,14 @@
 	
 	//qualification may be on both side
 	public Expression enclosingInstance;
-	public AnonymousLocalTypeDeclaration anonymousType;
+	public TypeDeclaration anonymousType;
 	public ReferenceBinding superTypeBinding;
 	
 	public QualifiedAllocationExpression() {
+		// for subtypes
 	}
 
-	public QualifiedAllocationExpression(AnonymousLocalTypeDeclaration anonymousType) {
+	public QualifiedAllocationExpression(TypeDeclaration anonymousType) {
 		this.anonymousType = anonymousType;
 	}
 
@@ -70,8 +71,8 @@
 				flowInfo,
 				currentScope);
 		}
-		manageEnclosingInstanceAccessIfNecessary(currentScope);
-		manageSyntheticAccessIfNecessary(currentScope);
+		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+		manageSyntheticAccessIfNecessary(currentScope, flowInfo);
 		return flowInfo;
 	}
 
@@ -149,8 +150,9 @@
 	 * types, since by the time we reach them, we might not yet know their
 	 * exact need.
 	 */
-	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
+	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
+		if (!flowInfo.isReachable()) return;
 		ReferenceBinding allocatedType;
 
 		// perform some emulation work in case there is some and we are inside a local type only
@@ -166,6 +168,17 @@
 		}
 	}
 
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		if (enclosingInstance != null)
+			enclosingInstance.printExpression(0, output).append('.'); 
+		super.printExpression(0, output);
+		if (anonymousType != null) {
+			anonymousType.print(indent, output);
+		}
+		return output;
+	}
+	
 	public TypeBinding resolveType(BlockScope scope) {
 
 		// added for code assist...cannot occur with 'normal' code
@@ -184,7 +197,14 @@
 		TypeBinding enclosingInstanceType = null;
 		TypeBinding receiverType = null;
 		boolean hasError = false;
-		if (anonymousType == null) { //----------------no anonymous class------------------------	
+		boolean enclosingInstanceContainsCast = false;
+		boolean argsContainCast = false;
+		
+		if (enclosingInstance != null) {
+			if (enclosingInstance instanceof CastExpression) {
+				enclosingInstance.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+				enclosingInstanceContainsCast = true;
+			}
 			if ((enclosingInstanceType = enclosingInstance.resolveType(scope)) == null){
 				hasError = true;
 			} else if (enclosingInstanceType.isBaseType() || enclosingInstanceType.isArrayType()) {
@@ -192,101 +212,95 @@
 					enclosingInstanceType,
 					enclosingInstance);
 				hasError = true;
-			} else if ((this.resolvedType = receiverType = ((SingleTypeReference) type).resolveTypeEnclosing(
-							scope,
-							(ReferenceBinding) enclosingInstanceType)) == null) {
-				hasError = true;
-			}
-			// will check for null after args are resolved
-			TypeBinding[] argumentTypes = NoParameters;
-			if (arguments != null) {
-				int length = arguments.length;
-				argumentTypes = new TypeBinding[length];
-				for (int i = 0; i < length; i++)
-					if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null){
-						hasError = true;
-					}
-			}
-			// limit of fault-tolerance
-			if (hasError) return receiverType;
-
-			if (!receiverType.canBeInstantiated()) {
-				scope.problemReporter().cannotInstantiate(type, receiverType);
-				return receiverType;
-			}
-			if ((this.binding = scope.getConstructor((ReferenceBinding) receiverType, argumentTypes, this))
-					.isValidBinding()) {
-				if (isMethodUseDeprecated(binding, scope))
-					scope.problemReporter().deprecatedMethod(this.binding, this);
-
-				if (arguments != null)
-					for (int i = 0; i < arguments.length; i++)
-						arguments[i].implicitWidening(this.binding.parameters[i], argumentTypes[i]);
 			} else {
-				if (this.binding.declaringClass == null)
-					this.binding.declaringClass = (ReferenceBinding) receiverType;
-				scope.problemReporter().invalidConstructor(this, this.binding);
-				return receiverType;
-			}
-
-			// The enclosing instance must be compatible with the innermost enclosing type
-			ReferenceBinding expectedType = this.binding.declaringClass.enclosingType();
-			if (enclosingInstanceType.isCompatibleWith(expectedType))
-				return receiverType;
-			scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
-				this.enclosingInstance,
-				enclosingInstanceType,
-				expectedType);
-			return receiverType;
-		}
-
-		//--------------there is an anonymous type declaration-----------------
-		if (this.enclosingInstance != null) {
-			if ((enclosingInstanceType = this.enclosingInstance.resolveType(scope)) == null) {
-				hasError = true;
-			} else if (enclosingInstanceType.isBaseType() || enclosingInstanceType.isArrayType()) {
-				scope.problemReporter().illegalPrimitiveOrArrayTypeForEnclosingInstance(
-					enclosingInstanceType,
-					this.enclosingInstance);
-				hasError = true;
-			} else {
-				receiverType = ((SingleTypeReference) type).resolveTypeEnclosing(
-										scope,
-										(ReferenceBinding) enclosingInstanceType);				
+				receiverType = ((SingleTypeReference) type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstanceType);
+				if (receiverType != null && enclosingInstanceContainsCast) {
+						CastExpression.checkNeedForEnclosingInstanceCast(scope, enclosingInstance, enclosingInstanceType, receiverType);
+				}
 			}
 		} else {
 			receiverType = type.resolveType(scope);
 		}
 		if (receiverType == null) {
 			hasError = true;
-		} else if (((ReferenceBinding) receiverType).isFinal()) {
+		} else if (((ReferenceBinding) receiverType).isFinal() && this.anonymousType != null) {
 			scope.problemReporter().anonymousClassCannotExtendFinalClass(type, receiverType);
 			hasError = true;
 		}
+
+		// will check for null after args are resolved
 		TypeBinding[] argumentTypes = NoParameters;
 		if (arguments != null) {
 			int length = arguments.length;
 			argumentTypes = new TypeBinding[length];
-			for (int i = 0; i < length; i++)
-				if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null) {
+			for (int i = 0; i < length; i++) {
+				Expression argument = this.arguments[i];
+				if (argument instanceof CastExpression) {
+					argument.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+					argsContainCast = true;
+				}
+				if ((argumentTypes[i] = argument.resolveType(scope)) == null){
 					hasError = true;
 				}
+			}
 		}
 		// limit of fault-tolerance
-		if (hasError) {
+		if (hasError) return this.resolvedType = receiverType;
+		
+		if (this.anonymousType == null) {
+			// qualified allocation with no anonymous type
+			ReferenceBinding allocationType = (ReferenceBinding) receiverType;
+			if (!receiverType.canBeInstantiated()) {
+				scope.problemReporter().cannotInstantiate(type, receiverType);
+				return this.resolvedType = receiverType;
+			}
+			if ((this.binding = scope.getConstructor(allocationType, argumentTypes, this)).isValidBinding()) {
+				if (isMethodUseDeprecated(binding, scope)) {
+					scope.problemReporter().deprecatedMethod(this.binding, this);
+				}
+				if (arguments != null) {
+					for (int i = 0; i < arguments.length; i++) {
+						arguments[i].implicitWidening(this.binding.parameters[i], argumentTypes[i]);
+					}
+					if (argsContainCast) {
+						CastExpression.checkNeedForArgumentCasts(scope, null, allocationType, binding, this.arguments, argumentTypes, this);
+					}
+				}
+			} else {
+				if (this.binding.declaringClass == null) {
+					this.binding.declaringClass = allocationType;
+				}
+				scope.problemReporter().invalidConstructor(this, this.binding);
+				return this.resolvedType = receiverType;
+			}
+
+			// The enclosing instance must be compatible with the innermost enclosing type
+			ReferenceBinding expectedType = this.binding.declaringClass.enclosingType();
+			if (enclosingInstanceType.isCompatibleWith(expectedType)) {
 				return receiverType;
+			}
+			scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
+				this.enclosingInstance,
+				enclosingInstanceType,
+				expectedType);
+			return this.resolvedType = receiverType;
 		}
 
+		// anonymous type scenario
 		// an anonymous class inherits from java.lang.Object when declared "after" an interface
-		this.superTypeBinding =
-			receiverType.isInterface() ? scope.getJavaLangObject() : (ReferenceBinding) receiverType;
-		MethodBinding inheritedBinding =
-			scope.getConstructor(this.superTypeBinding, argumentTypes, this);
+		this.superTypeBinding = receiverType.isInterface() ? scope.getJavaLangObject() : (ReferenceBinding) receiverType;
+		// insert anonymous type in scope
+		scope.addAnonymousType(this.anonymousType, (ReferenceBinding) receiverType);
+		this.anonymousType.resolve(scope);		
+		
+		// find anonymous super constructor
+		MethodBinding inheritedBinding = scope.getConstructor(this.superTypeBinding, argumentTypes, this);
 		if (!inheritedBinding.isValidBinding()) {
-			if (inheritedBinding.declaringClass == null)
+			if (inheritedBinding.declaringClass == null) {
 				inheritedBinding.declaringClass = this.superTypeBinding;
+			}
 			scope.problemReporter().invalidConstructor(this, inheritedBinding);
-			return null;
+			return this.resolvedType = anonymousType.binding;
 		}
 		if (enclosingInstance != null) {
 			if (!enclosingInstanceType.isCompatibleWith(inheritedBinding.declaringClass.enclosingType())) {
@@ -294,40 +308,26 @@
 					enclosingInstance,
 					enclosingInstanceType,
 					inheritedBinding.declaringClass.enclosingType());
-				return null;
+				return this.resolvedType = anonymousType.binding;
 			}
 		}
 
 		// this promotion has to be done somewhere: here or inside the constructor of the
 		// anonymous class. We do it here while the constructor of the inner is then easier.
-		if (arguments != null)
-			for (int i = 0; i < arguments.length; i++)
+		if (arguments != null) {
+			for (int i = 0; i < arguments.length; i++) {
 				arguments[i].implicitWidening(inheritedBinding.parameters[i], argumentTypes[i]);
-
+			}
+			if (argsContainCast) {
+				CastExpression.checkNeedForArgumentCasts(scope, null, this.superTypeBinding, inheritedBinding, this.arguments, argumentTypes, this);
+			}
+		}
 		// Update the anonymous inner class : superclass, interface  
-		scope.addAnonymousType(anonymousType, (ReferenceBinding) receiverType);
-		anonymousType.resolve(scope);
 		binding = anonymousType.createsInternalConstructorWithBinding(inheritedBinding);
-		return anonymousType.binding; // 1.2 change
+		return this.resolvedType = anonymousType.binding; // 1.2 change
 	}
 	
-	public String toStringExpression() {
-		return this.toStringExpression(0);
-	}
-
-	public String toStringExpression(int tab) {
-
-		String s = ""; //$NON-NLS-1$
-		if (enclosingInstance != null)
-			s += enclosingInstance.toString() + "."; //$NON-NLS-1$
-		s += super.toStringExpression();
-		if (anonymousType != null) {
-			s += anonymousType.toString(tab);
-		} //allows to restart just after the } one line under ....
-		return s;
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 
 		if (visitor.visit(this, scope)) {
 			if (enclosingInstance != null)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
index d5e4271..5226313 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
@@ -10,15 +10,18 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 
 public class QualifiedNameReference extends NameReference {
 	
 	public char[][] tokens;
+	public long[] sourcePositions;	
 	public FieldBinding[] otherBindings, otherCodegenBindings;
 	int[] otherDepths;
 	public int indexOfFirstFieldBinding;//points (into tokens) for the first token that corresponds to first FieldBinding
@@ -27,10 +30,12 @@
 	protected FieldBinding lastFieldBinding;
 	public QualifiedNameReference(
 		char[][] sources,
+		long[] positions,
 		int sourceStart,
 		int sourceEnd) {
 		super();
-		tokens = sources;
+		this.tokens = sources;
+		this.sourcePositions = positions;
 		this.sourceStart = sourceStart;
 		this.sourceEnd = sourceEnd;
 	}
@@ -48,7 +53,7 @@
 			case FIELD : // reading a field
 				lastFieldBinding = (FieldBinding) binding;
 				if (needValue) {
-					manageSyntheticReadAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0);
+					manageSyntheticReadAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0, flowInfo);
 				}				// check if final blank field
 				if (lastFieldBinding.isBlankFinal()
 				    && this.otherBindings != null // the last field binding is only assigned
@@ -75,7 +80,7 @@
 		}
 		
 		if (needValue) {
-			manageEnclosingInstanceAccessIfNecessary(currentScope);
+			manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
 			// only for first binding
 		}
 		// all intermediate field accesses are read accesses
@@ -90,7 +95,8 @@
 						i == 0 
 							? ((VariableBinding)binding).type
 							: otherBindings[i-1].type,
-						i + 1);
+						i + 1, 
+						flowInfo);
 				}
 			}
 			lastFieldBinding = otherBindings[otherBindingsCount-1];
@@ -119,7 +125,8 @@
 				lastReceiverType,
 				lastFieldBinding == binding
 					? 0 
-					: otherBindingsCount);
+					: otherBindingsCount, 
+				flowInfo);
 		}
 		
 		if (assignment.expression != null) {
@@ -140,7 +147,7 @@
 				if (flowInfo.isPotentiallyAssigned(lastFieldBinding)) {
 					currentScope.problemReporter().duplicateInitializationOfBlankFinalField(lastFieldBinding, this);
 				} else {
-					flowContext.recordSettingFinal(lastFieldBinding, this);
+					flowContext.recordSettingFinal(lastFieldBinding, this, flowInfo);
 				}
 				flowInfo.markAsDefinitelyAssigned(lastFieldBinding);
 			} else {
@@ -159,7 +166,7 @@
 		} else {
 			lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
 		}
-		manageSyntheticWriteAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType);
+		manageSyntheticWriteAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, flowInfo);
 
 		return flowInfo;
 	}
@@ -185,7 +192,7 @@
 		switch (bits & RestrictiveFlagMASK) {
 			case FIELD : // reading a field
 				if (needValue) {
-					manageSyntheticReadAccessIfNecessary(currentScope, (FieldBinding) binding, this.actualReceiverType, 0);
+					manageSyntheticReadAccessIfNecessary(currentScope, (FieldBinding) binding, this.actualReceiverType, 0, flowInfo);
 				}
 				// check if reading a final blank field
 				FieldBinding fieldBinding;
@@ -210,7 +217,7 @@
 				}
 		}
 		if (needValue) {
-			manageEnclosingInstanceAccessIfNecessary(currentScope);
+			manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
 			// only for first binding
 		}
 		if (otherBindings != null) {
@@ -223,7 +230,8 @@
 						i == 0 
 							? ((VariableBinding)binding).type
 							: otherBindings[i-1].type,
-						i + 1);
+						i + 1,
+						flowInfo);
 				}
 			}
 		}
@@ -237,8 +245,8 @@
 		FieldBinding fieldBinding = (FieldBinding) binding;
 		MethodScope methodScope = scope.methodScope();
 		if (methodScope.enclosingSourceType() == fieldBinding.declaringClass
-			&& methodScope.fieldDeclarationIndex != MethodScope.NotInFieldDecl
-			&& fieldBinding.id >= methodScope.fieldDeclarationIndex) {
+			&& methodScope.lastVisibleFieldID >= 0
+			&& fieldBinding.id >= methodScope.lastVisibleFieldID) {
 			if ((!fieldBinding.isStatic() || methodScope.isStatic)
 				&& this.indexOfFirstFieldBinding == 1)
 				scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
@@ -442,8 +450,8 @@
 				}
 				break;
 			case LOCAL : // reading the first local variable
-				if (!needValue) break; // no value needed
 				lastFieldBinding = null;
+				if (!needValue) break; // no value needed
 				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 				// regular local variable read
 				if (localBinding.constant != NotAConstant) {
@@ -502,30 +510,29 @@
 	}
 	public TypeBinding getOtherFieldBindings(BlockScope scope) {
 		// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
+		int length = tokens.length;
 		if ((bits & FIELD) != 0) {
-			if (!((FieldBinding) binding).isStatic()) {
+			FieldBinding fieldBinding = (FieldBinding) binding;
+			if (!fieldBinding.isStatic()) {
 				//must check for the static status....
-				if (indexOfFirstFieldBinding == 1) {
-					//the field is the first token of the qualified reference....
-					if (scope.methodScope().isStatic) {
-						scope.problemReporter().staticFieldAccessToNonStaticVariable(
-							this,
-							(FieldBinding) binding);
-						return null;
-					}
-				} else { //accessing to a field using a type as "receiver" is allowed only with static field	
-					scope.problemReporter().staticFieldAccessToNonStaticVariable(
-						this,
-						(FieldBinding) binding);
+				if (indexOfFirstFieldBinding > 1  //accessing to a field using a type as "receiver" is allowed only with static field
+						 || scope.methodScope().isStatic) { 	// the field is the first token of the qualified reference....
+					scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding);
 					return null;
+				 }
+			} else {
+				// indirect static reference ?
+				if (indexOfFirstFieldBinding > 1 
+						&& fieldBinding.declaringClass != actualReceiverType) {
+					scope.problemReporter().indirectAccessToStaticField(this, fieldBinding);
 				}
 			}
-			if (isFieldUseDeprecated((FieldBinding) binding, scope))
-				scope.problemReporter().deprecatedField((FieldBinding) binding, this);
+			// only last field is actually a write access if any
+			if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssignedMASK) !=0 && indexOfFirstFieldBinding == length))
+				scope.problemReporter().deprecatedField(fieldBinding, this);
 		}
 		TypeBinding type = ((VariableBinding) binding).type;
 		int index = indexOfFirstFieldBinding;
-		int length = tokens.length;
 		if (index == length) { //	restrictiveFlag == FIELD
 			this.constant = FieldReference.getConstantFor((FieldBinding) binding, this, false, scope);
 			return type;
@@ -554,22 +561,26 @@
 			otherBindings[place] = field;
 			otherDepths[place] = (bits & DepthMASK) >> DepthSHIFT;
 			if (field.isValidBinding()) {
-				if (isFieldUseDeprecated(field, scope))
+				// only last field is actually a write access if any
+				if (isFieldUseDeprecated(field, scope, (this.bits & IsStrictlyAssignedMASK) !=0 && index+1 == length)) {
 					scope.problemReporter().deprecatedField(field, this);
+				}
 				Constant someConstant = FieldReference.getConstantFor(field, this, false, scope);
 				// constant propagation can only be performed as long as the previous one is a constant too.
 				if (this.constant != NotAConstant) {
 					this.constant = someConstant;					
 				}
 
-				type = field.type;
-				index++;
-				
 				if (field.isStatic()) {
 					// static field accessed through receiver? legal but unoptimal (optional warning)
-					scope.problemReporter().unnecessaryReceiverForStaticField(this, field);
+					scope.problemReporter().nonStaticAccessToStaticField(this, field);
+					// indirect static reference ?
+					if (field.declaringClass != type) {
+						scope.problemReporter().indirectAccessToStaticField(this, field);
+					}
 				}
-				
+				type = field.type;
+				index++;
 			} else {
 				constant = NotAConstant; //don't fill other constants slots...
 				scope.problemReporter().invalidField(this, field, index, type);
@@ -580,7 +591,8 @@
 		setDepth(firstDepth);
 		return (otherBindings[otherBindingsLength - 1]).type;
 	}
-	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
+	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+		if (!flowInfo.isReachable()) return;
 		//If inlinable field, forget the access emulation, the code gen will directly target it
 		if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) {
 			return;
@@ -590,10 +602,12 @@
 		}
 	}
 	public void manageSyntheticReadAccessIfNecessary(
-		BlockScope currentScope,
-		FieldBinding fieldBinding,
-		TypeBinding lastReceiverType,
-		int index) {
+			BlockScope currentScope,
+			FieldBinding fieldBinding,
+			TypeBinding lastReceiverType,
+			int index,
+			FlowInfo flowInfo) {
+		if (!flowInfo.isReachable()) return;
 		// index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings'
 		if (fieldBinding.constant != NotAConstant)
 			return;
@@ -636,7 +650,7 @@
 			&& !lastReceiverType.isArrayType()			
 			&& fieldBinding.declaringClass != null
 			&& fieldBinding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
+			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
 					&& (index > 0 || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
 					&& fieldBinding.declaringClass.id != T_Object)
 				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
@@ -655,9 +669,11 @@
 	 * No need to emulate access to protected fields since not implicitly accessed
 	 */
 	public void manageSyntheticWriteAccessIfNecessary(
-		BlockScope currentScope,
-		FieldBinding fieldBinding,
-		TypeBinding lastReceiverType) {
+			BlockScope currentScope,
+			FieldBinding fieldBinding,
+			TypeBinding lastReceiverType,
+			FlowInfo flowInfo) {
+		if (!flowInfo.isReachable()) return;
 		if (fieldBinding.isPrivate()) {
 			if (fieldBinding.declaringClass != currentScope.enclosingSourceType()) {
 				syntheticWriteAccessor = ((SourceTypeBinding) fieldBinding.declaringClass)
@@ -682,7 +698,7 @@
 			&& !lastReceiverType.isArrayType()			
 			&& fieldBinding.declaringClass != null
 			&& fieldBinding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
+			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
 					&& (fieldBinding != binding || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
 					&& fieldBinding.declaringClass.id != T_Object)
 				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
@@ -698,6 +714,16 @@
 		}
 		
 	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		
+		for (int i = 0; i < tokens.length; i++) {
+			if (i > 0) output.append('.');
+			output.append(tokens[i]);
+		}
+		return output;
+	}
+		
 	/**
 	 * Normal field binding did not work, try to bind to a field of the delegate receiver.
 	 */
@@ -717,8 +743,7 @@
 		// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField 
 		this.actualReceiverType = this.receiverType = scope.enclosingSourceType();
 		constant = Constant.NotAConstant;
-		if ((this.codegenBinding = this.binding = scope.getBinding(tokens, bits & RestrictiveFlagMASK, this))
-			.isValidBinding()) {
+		if ((this.codegenBinding = this.binding = scope.getBinding(tokens, bits & RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
 			switch (bits & RestrictiveFlagMASK) {
 				case VARIABLE : //============only variable===========
 				case TYPE | VARIABLE :
@@ -736,11 +761,17 @@
 						FieldBinding fieldBinding = (FieldBinding) binding;
 						MethodScope methodScope = scope.methodScope();
 						if (methodScope.enclosingSourceType() == fieldBinding.declaringClass
-							&& methodScope.fieldDeclarationIndex != MethodScope.NotInFieldDecl
-							&& fieldBinding.id >= methodScope.fieldDeclarationIndex) {
+								&& methodScope.lastVisibleFieldID >= 0
+								&& fieldBinding.id >= methodScope.lastVisibleFieldID) {
 							if ((!fieldBinding.isStatic() || methodScope.isStatic)
-								&& this.indexOfFirstFieldBinding == 1)
+								&& this.indexOfFirstFieldBinding == 1) {
 								scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
+								}
+						}
+						if (!fieldBinding.isStatic() 
+								&& this.indexOfFirstFieldBinding == 1
+								&& scope.environment().options.getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) {
+							scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding);
 						}
 						bits &= ~RestrictiveFlagMASK; // clear bits
 						bits |= FIELD;
@@ -766,20 +797,12 @@
 		//========error cases===============
 		return this.resolvedType = this.reportError(scope);
 	}
+	
 	public void setFieldIndex(int index) {
 		this.indexOfFirstFieldBinding = index;
 	}
-	public String toStringExpression() {
-		StringBuffer buffer = new StringBuffer();
-		for (int i = 0; i < tokens.length; i++) {
-			buffer.append(tokens[i]);
-			if (i < (tokens.length - 1)) {
-				buffer.append("."); //$NON-NLS-1$
-			}
-		}
-		return buffer.toString();
-	}
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		visitor.visit(this, scope);
 		visitor.endVisit(this, scope);
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
index d35b82d..e84d71d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class QualifiedSuperReference extends QualifiedThisReference {
@@ -29,6 +29,11 @@
 		return false;
 	}
 
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+
+		return qualification.print(0, output).append(".super"); //$NON-NLS-1$
+	}
+	
 	public TypeBinding resolveType(BlockScope scope) {
 
 		if ((this.bits & ParenthesizedMASK) != 0) {
@@ -46,13 +51,8 @@
 		return this.resolvedType = currentCompatibleType.superclass();
 	}
 
-	public String toStringExpression() {
-
-		return qualification.toString(0) + ".super"; //$NON-NLS-1$
-	}
-
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
index 86d38dd..70f268b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -72,7 +72,7 @@
 	public TypeBinding resolveType(BlockScope scope) {
 
 		constant = NotAConstant;
-		this.resolvedType = qualification.resolveType(scope);
+		this.resolvedType = this.qualification.resolveType(scope);
 		if (this.resolvedType == null) return null;
 
 		// the qualification MUST exactly match some enclosing type name
@@ -99,13 +99,13 @@
 		return this.resolvedType;
 	}
 
-	public String toStringExpression() {
+	public StringBuffer printExpression(int indent, StringBuffer output) {
 
-		return qualification.toString(0) + ".this"; //$NON-NLS-1$
+		return qualification.print(0, output).append(".this"); //$NON-NLS-1$
 	}
 
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
index 3244db7..462f7da 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
@@ -10,53 +10,64 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class QualifiedTypeReference extends TypeReference {
+
 	public char[][] tokens;
 	public long[] sourcePositions;
-public QualifiedTypeReference(char[][] sources , long[] poss) {
-	tokens = sources ;
-	sourcePositions = poss ;
-	sourceStart = (int) (sourcePositions[0]>>>32) ;
-	sourceEnd = (int)(sourcePositions[sourcePositions.length-1] & 0x00000000FFFFFFFFL ) ;
-}
-public QualifiedTypeReference(char[][] sources , TypeBinding type , long[] poss) {
-	this(sources,poss);
-	this.resolvedType = type;
-}
-public TypeReference copyDims(int dim){
-	//return a type reference copy of me with some dimensions
-	//warning : the new type ref has a null binding
-	
-	return new ArrayQualifiedTypeReference(tokens,null,dim,sourcePositions) ;
-}
-public TypeBinding getTypeBinding(Scope scope) {
-	if (this.resolvedType != null)
-		return this.resolvedType;
-	return scope.getType(tokens);
-}
-public char[][] getTypeName(){
 
-	return tokens;
-}
-public String toStringExpression(int tab) {
-	StringBuffer buffer = new StringBuffer();
-	for (int i = 0; i < tokens.length; i++) {
-		buffer.append(tokens[i]);
-		if (i < (tokens.length - 1)) {
-			buffer.append("."); //$NON-NLS-1$
-		}
+	public QualifiedTypeReference(char[][] sources , long[] poss) {
+		
+		tokens = sources ;
+		sourcePositions = poss ;
+		sourceStart = (int) (sourcePositions[0]>>>32) ;
+		sourceEnd = (int)(sourcePositions[sourcePositions.length-1] & 0x00000000FFFFFFFFL ) ;
 	}
-	return buffer.toString();
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
+	
+	public QualifiedTypeReference(char[][] sources , TypeBinding type , long[] poss) {
+		
+		this(sources,poss);
+		this.resolvedType = type;
+	}
+	
+	public TypeReference copyDims(int dim){
+		//return a type reference copy of me with some dimensions
+		//warning : the new type ref has a null binding
+		return new ArrayQualifiedTypeReference(tokens,null,dim,sourcePositions) ;
+	}
+	
+	public TypeBinding getTypeBinding(Scope scope) {
+		
+		if (this.resolvedType != null)
+			return this.resolvedType;
+		return scope.getType(tokens);
+	}
+	
+	public char[][] getTypeName(){
+	
+		return tokens;
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		
+		for (int i = 0; i < tokens.length; i++) {
+			if (i > 0) output.append('.');
+			output.append(tokens[i]);
+		}
+		return output;
+	}
+	
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+	
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
index cb47c2c..d45b40c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
@@ -10,234 +10,229 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class ReturnStatement extends Statement {
+		
 	public Expression expression;
-
 	public TypeBinding expressionType;
 	public boolean isSynchronized;
-	public AstNode[] subroutines;
+	public SubRoutineStatement[] subroutines;
+	public boolean isAnySubRoutineEscaping = false;
 	public LocalVariableBinding saveValueVariable;
-
-public ReturnStatement(Expression expr, int s, int e ) {
-	sourceStart = s;
-	sourceEnd = e;
-	expression = expr ;
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {	// here requires to generate a sequence of finally blocks invocations depending corresponding
-	// to each of the traversed try statements, so that execution will terminate properly.
-
-	// lookup the label, this should answer the returnContext
-
-	if (expression != null) {
-		flowInfo = expression.analyseCode(currentScope, flowContext, flowInfo);
+	
+	public ReturnStatement(Expression expr, int s, int e ) {
+		sourceStart = s;
+		sourceEnd = e;
+		expression = expr ;
 	}
-	// compute the return sequence (running the finally blocks)
-	FlowContext traversedContext = flowContext;
-	int subIndex = 0, maxSub = 5;
-	boolean saveValueNeeded = false;
-	boolean hasValueToSave = expression != null && expression.constant == NotAConstant;
-	do {
-		AstNode sub;
-		if ((sub = traversedContext.subRoutine()) != null) {
-			if (this.subroutines == null){
-				this.subroutines = new AstNode[maxSub];
-			}
-			if (subIndex == maxSub) {
-				System.arraycopy(this.subroutines, 0, (this.subroutines = new AstNode[maxSub *= 2]), 0, subIndex); // grow
-			}
-			this.subroutines[subIndex++] = sub;
-			if (sub.cannotReturn()) {
-				saveValueNeeded = false;
-				break;
-			}
+	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {	// here requires to generate a sequence of finally blocks invocations depending corresponding
+		// to each of the traversed try statements, so that execution will terminate properly.
+	
+		// lookup the label, this should answer the returnContext
+	
+		if (expression != null) {
+			flowInfo = expression.analyseCode(currentScope, flowContext, flowInfo);
 		}
-		traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
-
-		AstNode node;
-		if ((node = traversedContext.associatedNode) instanceof SynchronizedStatement) {
-			isSynchronized = true;
-
-		} else if (node instanceof TryStatement) {
-			TryStatement tryStatement = (TryStatement) node;
-			flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
-			if (hasValueToSave) {
-				if (this.saveValueVariable == null){ // closest subroutine secret variable is used
-					prepareSaveValueLocation(tryStatement);
+		// compute the return sequence (running the finally blocks)
+		FlowContext traversedContext = flowContext;
+		int subIndex = 0, maxSub = 5;
+		boolean saveValueNeeded = false;
+		boolean hasValueToSave = expression != null && expression.constant == NotAConstant;
+		do {
+			SubRoutineStatement sub;
+			if ((sub = traversedContext.subRoutine()) != null) {
+				if (this.subroutines == null){
+					this.subroutines = new SubRoutineStatement[maxSub];
 				}
-				saveValueNeeded = true;
-			}
-
-		} else if (traversedContext instanceof InitializationFlowContext) {
-				currentScope.problemReporter().cannotReturnInInitializer(this);
-				return FlowInfo.DEAD_END;
-		}
-	} while ((traversedContext = traversedContext.parent) != null);
-	
-	// resize subroutines
-	if ((subroutines != null) && (subIndex != maxSub)) {
-		System.arraycopy(subroutines, 0, (subroutines = new AstNode[subIndex]), 0, subIndex);
-	}
-
-	// secret local variable for return value (note that this can only occur in a real method)
-	if (saveValueNeeded) {
-		if (this.saveValueVariable != null) {
-			this.saveValueVariable.useFlag = LocalVariableBinding.USED;
-		}
-	} else {
-		this.saveValueVariable = null;
-		if ((!isSynchronized) && (expressionType == BooleanBinding)) {
-			this.expression.bits |= ValueForReturnMASK;
-		}
-	}
-	return FlowInfo.DEAD_END;
-}
- 
-/**
- * Retrun statement code generation
- *
- *   generate the finallyInvocationSequence.
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream) {
-	if ((bits & IsReachableMASK) == 0) {
-		return;
-	}
-	int pc = codeStream.position;
-	// generate the expression
-	if ((expression != null) && (expression.constant == NotAConstant)) {
-		expression.generateCode(currentScope, codeStream, needValue()); // no value needed if non-returning subroutine
-		generateStoreSaveValueIfNecessary(codeStream);
-	}
-	
-	// generation of code responsible for invoking the finally blocks in sequence
-	if (subroutines != null) {
-		for (int i = 0, max = subroutines.length; i < max; i++) {
-			AstNode sub;
-			if ((sub = subroutines[i]) instanceof SynchronizedStatement) {
-				codeStream.load(((SynchronizedStatement) sub).synchroVariable);
-				codeStream.monitorexit();
-			} else {
-				TryStatement trySub = (TryStatement) sub;
-				if (trySub.subRoutineCannotReturn) {
-					codeStream.goto_(trySub.subRoutineStartLabel);
-					codeStream.recordPositionsFrom(pc, this.sourceStart);
-					return;
-				} else {
-					codeStream.jsr(trySub.subRoutineStartLabel);
+				if (subIndex == maxSub) {
+					System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[maxSub *= 2]), 0, subIndex); // grow
+				}
+				this.subroutines[subIndex++] = sub;
+				if (sub.isSubRoutineEscaping()) {
+					saveValueNeeded = false;
+					isAnySubRoutineEscaping = true;
+					break;
 				}
 			}
-		}
-	}
-	if (saveValueVariable != null) codeStream.load(saveValueVariable);
+			traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
 	
-	if ((expression != null) && (expression.constant != NotAConstant)) {
-		codeStream.generateConstant(expression.constant, expression.implicitConversion);
-		generateStoreSaveValueIfNecessary(codeStream);		
-	}
-	// output the suitable return bytecode or wrap the value inside a descriptor for doits
-	this.generateReturnBytecode(codeStream);
+			ASTNode node;
+			if ((node = traversedContext.associatedNode) instanceof SynchronizedStatement) {
+				isSynchronized = true;
 	
-	codeStream.recordPositionsFrom(pc, this.sourceStart);
-}
-/**
- * Dump the suitable return bytecode for a return statement
- *
- */
-public void generateReturnBytecode(CodeStream codeStream) {
-
-	if (expression == null) {
-		codeStream.return_();
-	} else {
-		switch (expression.implicitConversion >> 4) {
-			case T_boolean :
-			case T_int :
-				codeStream.ireturn();
-				break;
-			case T_float :
-				codeStream.freturn();
-				break;
-			case T_long :
-				codeStream.lreturn();
-				break;
-			case T_double :
-				codeStream.dreturn();
-				break;
-			default :
-				codeStream.areturn();
-		}
-	}
-}
-public void generateStoreSaveValueIfNecessary(CodeStream codeStream){
-	if (saveValueVariable != null) codeStream.store(saveValueVariable, false);
-}
-public boolean needValue(){
-	return (subroutines == null) || (saveValueVariable != null) || isSynchronized;
-}
-public void prepareSaveValueLocation(TryStatement targetTryStatement){
+			} else if (node instanceof TryStatement) {
+				TryStatement tryStatement = (TryStatement) node;
+				flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
+				if (hasValueToSave) {
+					if (this.saveValueVariable == null){ // closest subroutine secret variable is used
+						prepareSaveValueLocation(tryStatement);
+					}
+					saveValueNeeded = true;
+				}
+	
+			} else if (traversedContext instanceof InitializationFlowContext) {
+					currentScope.problemReporter().cannotReturnInInitializer(this);
+					return FlowInfo.DEAD_END;
+			}
+		} while ((traversedContext = traversedContext.parent) != null);
 		
-	this.saveValueVariable = targetTryStatement.secretReturnValue;
-}
-public void resolve(BlockScope scope) {
-	MethodScope methodScope = scope.methodScope();
-	MethodBinding methodBinding;
-	TypeBinding methodType =
-		(methodScope.referenceContext instanceof AbstractMethodDeclaration)
-			? ((methodBinding = ((AbstractMethodDeclaration) methodScope.referenceContext).binding) == null 
-				? null 
-				: methodBinding.returnType)
-			: VoidBinding;
-	if (methodType == VoidBinding) {
-		// the expression should be null
-		if (expression == null)
+		// resize subroutines
+		if ((subroutines != null) && (subIndex != maxSub)) {
+			System.arraycopy(subroutines, 0, (subroutines = new SubRoutineStatement[subIndex]), 0, subIndex);
+		}
+	
+		// secret local variable for return value (note that this can only occur in a real method)
+		if (saveValueNeeded) {
+			if (this.saveValueVariable != null) {
+				this.saveValueVariable.useFlag = LocalVariableBinding.USED;
+			}
+		} else {
+			this.saveValueVariable = null;
+			if ((!isSynchronized) && (expressionType == BooleanBinding)) {
+				this.expression.bits |= ValueForReturnMASK;
+			}
+		}
+		return FlowInfo.DEAD_END;
+	}
+	 
+	/**
+	 * Retrun statement code generation
+	 *
+	 *   generate the finallyInvocationSequence.
+	 *
+	 * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+	 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+	 */
+	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+		if ((bits & IsReachableMASK) == 0) {
 			return;
-		if ((expressionType = expression.resolveType(scope)) != null)
-			scope.problemReporter().attemptToReturnNonVoidExpression(this, expressionType);
-		return;
+		}
+		int pc = codeStream.position;
+		// generate the expression
+		if ((expression != null) && (expression.constant == NotAConstant)) {
+			expression.generateCode(currentScope, codeStream, needValue()); // no value needed if non-returning subroutine
+			generateStoreSaveValueIfNecessary(codeStream);
+		}
+		
+		// generation of code responsible for invoking the finally blocks in sequence
+		if (subroutines != null) {
+			for (int i = 0, max = subroutines.length; i < max; i++) {
+				SubRoutineStatement sub = subroutines[i];
+				sub.generateSubRoutineInvocation(currentScope, codeStream);
+				if (sub.isSubRoutineEscaping()) {
+						codeStream.recordPositionsFrom(pc, this.sourceStart);
+						SubRoutineStatement.reenterExceptionHandlers(subroutines, i, codeStream);
+						return;
+				}
+				sub.exitAnyExceptionHandler();
+			}
+		}
+		if (saveValueVariable != null) codeStream.load(saveValueVariable);
+		
+		if ((expression != null) && (expression.constant != NotAConstant)) {
+			codeStream.generateConstant(expression.constant, expression.implicitConversion);
+			generateStoreSaveValueIfNecessary(codeStream);		
+		}
+		// output the suitable return bytecode or wrap the value inside a descriptor for doits
+		this.generateReturnBytecode(codeStream);
+		codeStream.recordPositionsFrom(pc, this.sourceStart);
+		SubRoutineStatement.reenterExceptionHandlers(subroutines, -1, codeStream);
 	}
-	if (expression == null) {
-		if (methodType != null) scope.problemReporter().shouldReturn(methodType, this);
-		return;
+	/**
+	 * Dump the suitable return bytecode for a return statement
+	 *
+	 */
+	public void generateReturnBytecode(CodeStream codeStream) {
+	
+		if (expression == null) {
+			codeStream.return_();
+		} else {
+			switch (expression.implicitConversion >> 4) {
+				case T_boolean :
+				case T_int :
+					codeStream.ireturn();
+					break;
+				case T_float :
+					codeStream.freturn();
+					break;
+				case T_long :
+					codeStream.lreturn();
+					break;
+				case T_double :
+					codeStream.dreturn();
+					break;
+				default :
+					codeStream.areturn();
+			}
+		}
 	}
-	if ((expressionType = expression.resolveType(scope)) == null)
-		return;
-
-	if (methodType != null && expression.isConstantValueOfTypeAssignableToType(expressionType, methodType)) {
-		// dealing with constant
-		expression.implicitWidening(methodType, expressionType);
-		return;
+	public void generateStoreSaveValueIfNecessary(CodeStream codeStream){
+		if (saveValueVariable != null) codeStream.store(saveValueVariable, false);
 	}
-	if (expressionType == VoidBinding) {
-		scope.problemReporter().attemptToReturnVoidValue(this);
-		return;
+	public boolean needValue(){
+		return (subroutines == null) || (saveValueVariable != null) || isSynchronized;
 	}
-	if (methodType != null && expressionType.isCompatibleWith(methodType)) {
-		expression.implicitWidening(methodType, expressionType);
-		return;
+	public void prepareSaveValueLocation(TryStatement targetTryStatement){
+			
+		this.saveValueVariable = targetTryStatement.secretReturnValue;
 	}
-	if (methodType != null){
-		scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionType, methodType);
+	public StringBuffer printStatement(int tab, StringBuffer output){
+	
+		printIndent(tab, output).append("return "); //$NON-NLS-1$
+		if (expression != null )
+			expression.printExpression(0, output) ;
+		return output.append(';');
 	}
-}
-public String toString(int tab){
-
-	String s = tabString(tab) ;
-	s = s + "return "; //$NON-NLS-1$
-	if (expression != null )
-		s = s + expression.toStringExpression() ;
-	return s;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	if (visitor.visit(this, scope)) {
-		if (expression != null)
-			expression.traverse(visitor, scope);
+	public void resolve(BlockScope scope) {
+		MethodScope methodScope = scope.methodScope();
+		MethodBinding methodBinding;
+		TypeBinding methodType =
+			(methodScope.referenceContext instanceof AbstractMethodDeclaration)
+				? ((methodBinding = ((AbstractMethodDeclaration) methodScope.referenceContext).binding) == null 
+					? null 
+					: methodBinding.returnType)
+				: VoidBinding;
+		if (methodType == VoidBinding) {
+			// the expression should be null
+			if (expression == null)
+				return;
+			if ((expressionType = expression.resolveType(scope)) != null)
+				scope.problemReporter().attemptToReturnNonVoidExpression(this, expressionType);
+			return;
+		}
+		if (expression == null) {
+			if (methodType != null) scope.problemReporter().shouldReturn(methodType, this);
+			return;
+		}
+		if ((expressionType = expression.resolveType(scope)) == null)
+			return;
+	
+		if (methodType != null && expression.isConstantValueOfTypeAssignableToType(expressionType, methodType)) {
+			// dealing with constant
+			expression.implicitWidening(methodType, expressionType);
+			return;
+		}
+		if (expressionType == VoidBinding) {
+			scope.problemReporter().attemptToReturnVoidValue(this);
+			return;
+		}
+		if (methodType != null && expressionType.isCompatibleWith(methodType)) {
+			expression.implicitWidening(methodType, expressionType);
+			return;
+		}
+		if (methodType != null){
+			scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionType, methodType);
+		}
 	}
-	visitor.endVisit(this, scope);
-}
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		if (visitor.visit(this, scope)) {
+			if (expression != null)
+				expression.traverse(visitor, scope);
+		}
+		visitor.endVisit(this, scope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
index d3f56db..82aeb39 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
@@ -10,11 +10,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 
 public class SingleNameReference extends NameReference implements OperatorIds {
 	public char[] token;
@@ -23,18 +25,102 @@
 	public static final int READ = 0;
 	public static final int WRITE = 1;
 	
-public SingleNameReference(char[] source, long pos) {
-	super();
-	token = source;
-	sourceStart = (int) (pos >>> 32);
-	sourceEnd = (int) pos;
-}
-public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
-
-	// compound assignment extra work
-	if (isCompound) { // check the variable part is initialized if blank final
+	public SingleNameReference(char[] source, long pos) {
+		super();
+		token = source;
+		sourceStart = (int) (pos >>> 32);
+		sourceEnd = (int) pos;
+	}
+	public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
+	
+		boolean isReachable = flowInfo.isReachable();
+		// compound assignment extra work
+		if (isCompound) { // check the variable part is initialized if blank final
+			switch (bits & RestrictiveFlagMASK) {
+				case FIELD : // reading a field
+					FieldBinding fieldBinding;
+					if ((fieldBinding = (FieldBinding) binding).isBlankFinal() 
+							&& currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
+						if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
+							currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
+						}
+					}
+					manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+					break;
+				case LOCAL : // reading a local variable
+					// check if assigning a final blank field
+					LocalVariableBinding localBinding;
+					if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
+						currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
+						// we could improve error msg here telling "cannot use compound assignment on final local variable"
+					}
+					if (isReachable) {
+						localBinding.useFlag = LocalVariableBinding.USED;
+					} else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
+						localBinding.useFlag = LocalVariableBinding.FAKE_USED;
+					}
+			}
+		}
+		if (assignment.expression != null) {
+			flowInfo = assignment.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+		}
+		switch (bits & RestrictiveFlagMASK) {
+			case FIELD : // assigning to a field
+				manageSyntheticWriteAccessIfNecessary(currentScope, flowInfo);
+	
+				// check if assigning a final field
+				FieldBinding fieldBinding;
+				if ((fieldBinding = (FieldBinding) binding).isFinal()) {
+					// inside a context where allowed
+					if (!isCompound && fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
+						if (flowInfo.isPotentiallyAssigned(fieldBinding)) {
+							currentScope.problemReporter().duplicateInitializationOfBlankFinalField(fieldBinding, this);
+						} else {
+							flowContext.recordSettingFinal(fieldBinding, this, flowInfo);						
+						}
+						flowInfo.markAsDefinitelyAssigned(fieldBinding);
+					} else {
+						currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this);
+					}
+				}
+				break;
+			case LOCAL : // assigning to a local variable 
+				LocalVariableBinding localBinding = (LocalVariableBinding) binding;
+				if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes
+					bits |= FirstAssignmentToLocalMASK;
+				} else {
+					bits &= ~FirstAssignmentToLocalMASK;
+				}
+				if (localBinding.isFinal()) {
+					if ((bits & DepthMASK) == 0) {
+						// tolerate assignment to final local in unreachable code (45674)
+						if ((isReachable && isCompound) || !localBinding.isBlankFinal()){
+							currentScope.problemReporter().cannotAssignToFinalLocal(localBinding, this);
+						} else if (flowInfo.isPotentiallyAssigned(localBinding)) {
+							currentScope.problemReporter().duplicateInitializationOfFinalLocal(localBinding, this);
+						} else {
+							flowContext.recordSettingFinal(localBinding, this, flowInfo);								
+						}
+					} else {
+						currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this);
+					}
+				}
+				flowInfo.markAsDefinitelyAssigned(localBinding);
+		}
+		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+		return flowInfo;
+	}
+	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+		return analyseCode(currentScope, flowContext, flowInfo, true);
+	}
+	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
+	
 		switch (bits & RestrictiveFlagMASK) {
 			case FIELD : // reading a field
+				if (valueRequired) {
+					manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+				}
+				// check if reading a final blank field
 				FieldBinding fieldBinding;
 				if ((fieldBinding = (FieldBinding) binding).isBlankFinal() 
 						&& currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
@@ -42,14 +128,11 @@
 						currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
 					}
 				}
-				manageSyntheticReadAccessIfNecessary(currentScope);
 				break;
 			case LOCAL : // reading a local variable
-				// check if assigning a final blank field
 				LocalVariableBinding localBinding;
 				if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
 					currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
-					// we could improve error msg here telling "cannot use compound assignment on final local variable"
 				}
 				if (flowInfo.isReachable()) {
 					localBinding.useFlag = LocalVariableBinding.USED;
@@ -57,608 +140,548 @@
 					localBinding.useFlag = LocalVariableBinding.FAKE_USED;
 				}
 		}
+		if (valueRequired) {
+			manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+		}
+		return flowInfo;
 	}
-	if (assignment.expression != null) {
-		flowInfo = assignment.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
-	}
-	switch (bits & RestrictiveFlagMASK) {
-		case FIELD : // assigning to a field
-			manageSyntheticWriteAccessIfNecessary(currentScope);
-
-			// check if assigning a final field
-			FieldBinding fieldBinding;
-			if ((fieldBinding = (FieldBinding) binding).isFinal()) {
-				// inside a context where allowed
-				if (!isCompound && fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
-					if (flowInfo.isPotentiallyAssigned(fieldBinding)) {
-						currentScope.problemReporter().duplicateInitializationOfBlankFinalField(fieldBinding, this);
-					} else {
-						flowContext.recordSettingFinal(fieldBinding, this);						
-					}
-					flowInfo.markAsDefinitelyAssigned(fieldBinding);
-				} else {
-					currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this);
-				}
-			}
-			break;
-		case LOCAL : // assigning to a local variable 
-			LocalVariableBinding localBinding = (LocalVariableBinding) binding;
-			if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes
-				bits |= FirstAssignmentToLocalMASK;
-			} else {
-				bits &= ~FirstAssignmentToLocalMASK;
-			}
-			if (localBinding.isFinal()) {
-				if ((bits & DepthMASK) == 0) {
-					if (isCompound || !localBinding.isBlankFinal()){
-						currentScope.problemReporter().cannotAssignToFinalLocal(localBinding, this);
-					} else if (flowInfo.isPotentiallyAssigned(localBinding)) {
-						currentScope.problemReporter().duplicateInitializationOfFinalLocal(localBinding, this);
-					} else {
-						flowContext.recordSettingFinal(localBinding, this);								
-					}
-				} else {
-					currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this);
-				}
-			}
-			flowInfo.markAsDefinitelyAssigned(localBinding);
-	}
-	manageEnclosingInstanceAccessIfNecessary(currentScope);
-	return flowInfo;
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
-	return analyseCode(currentScope, flowContext, flowInfo, true);
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
-
-	switch (bits & RestrictiveFlagMASK) {
-		case FIELD : // reading a field
-			if (valueRequired) {
-				manageSyntheticReadAccessIfNecessary(currentScope);
-			}
-			// check if reading a final blank field
-			FieldBinding fieldBinding;
-			if ((fieldBinding = (FieldBinding) binding).isBlankFinal() 
-					&& currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
-				if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
-					currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
-				}
-			}
-			break;
-		case LOCAL : // reading a local variable
-			LocalVariableBinding localBinding;
-			if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
-				currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
-			}
-			if (flowInfo.isReachable()) {
-				localBinding.useFlag = LocalVariableBinding.USED;
-			} else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
-				localBinding.useFlag = LocalVariableBinding.FAKE_USED;
-			}
-	}
-	if (valueRequired) {
-		manageEnclosingInstanceAccessIfNecessary(currentScope);
-	}
-	return flowInfo;
-}
-public TypeBinding checkFieldAccess(BlockScope scope) {
-
-	FieldBinding fieldBinding = (FieldBinding) binding;
+	public TypeBinding checkFieldAccess(BlockScope scope) {
 	
-	bits &= ~RestrictiveFlagMASK; // clear bits
-	bits |= FIELD;
-	if (!((FieldBinding) binding).isStatic()) {
-		// must check for the static status....
-		if (scope.methodScope().isStatic) {
-			scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding);
-			constant = NotAConstant;
-			return fieldBinding.type;
-		}
-	}
-	constant = FieldReference.getConstantFor(fieldBinding, this, true, scope);
-
-	if (isFieldUseDeprecated(fieldBinding, scope))
-		scope.problemReporter().deprecatedField(fieldBinding, this);
-
-	MethodScope ms = scope.methodScope();
-	if ((this.bits & IsStrictlyAssignedMASK) == 0
-		&& ms.enclosingSourceType() == fieldBinding.declaringClass
-		&& ms.fieldDeclarationIndex != MethodScope.NotInFieldDecl
-		&& fieldBinding.id >= ms.fieldDeclarationIndex) {
-		//if the field is static and ms is not .... then it is valid
-		if (!fieldBinding.isStatic() || ms.isStatic)
-			scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
-	}
-	//====================================================
-
-	return fieldBinding.type;
-
-}
-public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
-
-	// optimizing assignment like: i = i + 1 or i = 1 + i
-	if (assignment.expression.isCompactableOperation()) {
-		BinaryExpression operation = (BinaryExpression) assignment.expression;
-		SingleNameReference variableReference;
-		if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == binding)) {
-			// i = i + value, then use the variable on the right hand side, since it has the correct implicit conversion
-			variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.right, (operation.bits & OperatorMASK) >> OperatorSHIFT, operation.left.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
-			return;
-		}
-		int operator = (operation.bits & OperatorMASK) >> OperatorSHIFT;
-		if ((operation.right instanceof SingleNameReference)
-			&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
-			&& ((variableReference = (SingleNameReference) operation.right).binding == binding)
-			&& (operation.left.constant != NotAConstant) // exclude non constant expressions, since could have side-effect
-			&& ((operation.left.implicitConversion >> 4) != T_String) // exclude string concatenation which would occur backwards
-			&& ((operation.right.implicitConversion >> 4) != T_String)) { // exclude string concatenation which would occur backwards
-			// i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
-			variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.left, operator, operation.right.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
-			return;
-		}
-	}
-	switch (bits & RestrictiveFlagMASK) {
-		case FIELD : // assigning to a field
-			FieldBinding fieldBinding;
-			if (!(fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { // need a receiver?
-				if ((bits & DepthMASK) != 0) {
-					ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
-					Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
-					codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
-				} else {
-					this.generateReceiver(codeStream);
-				}
+		FieldBinding fieldBinding = (FieldBinding) binding;
+		
+		bits &= ~RestrictiveFlagMASK; // clear bits
+		bits |= FIELD;
+		if (!((FieldBinding) binding).isStatic()) {
+			// must check for the static status....
+			if (scope.methodScope().isStatic) {
+				scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding);
+				constant = NotAConstant;
+				return fieldBinding.type;
 			}
-			assignment.expression.generateCode(currentScope, codeStream, true);
-			fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], valueRequired);
-			if (valueRequired) {
-				codeStream.generateImplicitConversion(assignment.implicitConversion);
-			}
-			return;
-		case LOCAL : // assigning to a local variable
-			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
-			if (localBinding.resolvedPosition != -1) {
-				assignment.expression.generateCode(currentScope, codeStream, true);
-			} else {
-				if (assignment.expression.constant != NotAConstant) {
-					// assigning an unused local to a constant value = no actual assignment is necessary
-					if (valueRequired) {
-						codeStream.generateConstant(assignment.expression.constant, assignment.implicitConversion);
-					}
-				} else {
-					assignment.expression.generateCode(currentScope, codeStream, true);
-					/* Even though the value may not be required, we force it to be produced, and discard it later
-					on if it was actually not necessary, so as to provide the same behavior as JDK1.2beta3.	*/
-					if (valueRequired) {
-						codeStream.generateImplicitConversion(assignment.implicitConversion); // implicit conversion
-					} else {
-						if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
-							codeStream.pop2();
-						} else {
-							codeStream.pop();
-						}
-					}
-				}
+		}
+		constant = FieldReference.getConstantFor(fieldBinding, this, true, scope);
+	
+		if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssignedMASK) !=0))
+			scope.problemReporter().deprecatedField(fieldBinding, this);
+	
+		MethodScope ms = scope.methodScope();
+		if ((this.bits & IsStrictlyAssignedMASK) == 0
+			&& ms.enclosingSourceType() == fieldBinding.declaringClass
+			&& ms.lastVisibleFieldID >= 0
+			&& fieldBinding.id >= ms.lastVisibleFieldID) {
+			//if the field is static and ms is not .... then it is valid
+			if (!fieldBinding.isStatic() || ms.isStatic)
+				scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
+		}
+		//====================================================
+	
+		return fieldBinding.type;
+	
+	}
+	public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
+	
+		// optimizing assignment like: i = i + 1 or i = 1 + i
+		if (assignment.expression.isCompactableOperation()) {
+			BinaryExpression operation = (BinaryExpression) assignment.expression;
+			SingleNameReference variableReference;
+			if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == binding)) {
+				// i = i + value, then use the variable on the right hand side, since it has the correct implicit conversion
+				variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.right, (operation.bits & OperatorMASK) >> OperatorSHIFT, operation.left.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
 				return;
 			}
-			// 26903, need extra cast to store null in array local var	
-			if (localBinding.type.isArrayType() 
-				&& (assignment.expression.resolvedType == NullBinding	// arrayLoc = null
-					|| ((assignment.expression instanceof CastExpression)	// arrayLoc = (type[])null
-						&& (((CastExpression)assignment.expression).innermostCastedExpression().resolvedType == NullBinding)))){
-				codeStream.checkcast(localBinding.type); 
+			int operator = (operation.bits & OperatorMASK) >> OperatorSHIFT;
+			if ((operation.right instanceof SingleNameReference)
+				&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
+				&& ((variableReference = (SingleNameReference) operation.right).binding == binding)
+				&& (operation.left.constant != NotAConstant) // exclude non constant expressions, since could have side-effect
+				&& ((operation.left.implicitConversion >> 4) != T_String) // exclude string concatenation which would occur backwards
+				&& ((operation.right.implicitConversion >> 4) != T_String)) { // exclude string concatenation which would occur backwards
+				// i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
+				variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.left, operator, operation.right.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
+				return;
 			}
-			
-			// normal local assignment (since cannot store in outer local which are final locations)
-			codeStream.store(localBinding, valueRequired);
-			if ((bits & FirstAssignmentToLocalMASK) != 0) { // for local variable debug attributes
-				localBinding.recordInitializationStartPC(codeStream.position);
-			}
-			// implicit conversion
-			if (valueRequired) {
-				codeStream.generateImplicitConversion(assignment.implicitConversion);
-			}
-	}
-}
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
-	int pc = codeStream.position;
-	if (constant != NotAConstant) {
-		if (valueRequired) {
-			codeStream.generateConstant(constant, implicitConversion);
 		}
-	} else {
 		switch (bits & RestrictiveFlagMASK) {
-			case FIELD : // reading a field
+			case FIELD : // assigning to a field
 				FieldBinding fieldBinding;
+				if (!(fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { // need a receiver?
+					if ((bits & DepthMASK) != 0) {
+						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
+						codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
+					} else {
+						this.generateReceiver(codeStream);
+					}
+				}
+				assignment.expression.generateCode(currentScope, codeStream, true);
+				fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], valueRequired);
 				if (valueRequired) {
-					if ((fieldBinding = (FieldBinding) this.codegenBinding).constant == NotAConstant) { // directly use inlined value for constant fields
-						boolean isStatic;
-						if (!(isStatic = fieldBinding.isStatic())) {
-							if ((bits & DepthMASK) != 0) {
-								ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
-								Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
-								codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
+					codeStream.generateImplicitConversion(assignment.implicitConversion);
+				}
+				return;
+			case LOCAL : // assigning to a local variable
+				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
+				if (localBinding.resolvedPosition != -1) {
+					assignment.expression.generateCode(currentScope, codeStream, true);
+				} else {
+					if (assignment.expression.constant != NotAConstant) {
+						// assigning an unused local to a constant value = no actual assignment is necessary
+						if (valueRequired) {
+							codeStream.generateConstant(assignment.expression.constant, assignment.implicitConversion);
+						}
+					} else {
+						assignment.expression.generateCode(currentScope, codeStream, true);
+						/* Even though the value may not be required, we force it to be produced, and discard it later
+						on if it was actually not necessary, so as to provide the same behavior as JDK1.2beta3.	*/
+						if (valueRequired) {
+							codeStream.generateImplicitConversion(assignment.implicitConversion); // implicit conversion
+						} else {
+							if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
+								codeStream.pop2();
 							} else {
-								generateReceiver(codeStream);
+								codeStream.pop();
 							}
 						}
-						// managing private access							
-						if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
-							if (isStatic) {
-								codeStream.getstatic(fieldBinding);
-							} else {
-								codeStream.getfield(fieldBinding);
+					}
+					return;
+				}
+				// 26903, need extra cast to store null in array local var	
+				if (localBinding.type.isArrayType() 
+					&& (assignment.expression.resolvedType == NullBinding	// arrayLoc = null
+						|| ((assignment.expression instanceof CastExpression)	// arrayLoc = (type[])null
+							&& (((CastExpression)assignment.expression).innermostCastedExpression().resolvedType == NullBinding)))){
+					codeStream.checkcast(localBinding.type); 
+				}
+				
+				// normal local assignment (since cannot store in outer local which are final locations)
+				codeStream.store(localBinding, valueRequired);
+				if ((bits & FirstAssignmentToLocalMASK) != 0) { // for local variable debug attributes
+					localBinding.recordInitializationStartPC(codeStream.position);
+				}
+				// implicit conversion
+				if (valueRequired) {
+					codeStream.generateImplicitConversion(assignment.implicitConversion);
+				}
+		}
+	}
+	public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+		int pc = codeStream.position;
+		if (constant != NotAConstant) {
+			if (valueRequired) {
+				codeStream.generateConstant(constant, implicitConversion);
+			}
+		} else {
+			switch (bits & RestrictiveFlagMASK) {
+				case FIELD : // reading a field
+					FieldBinding fieldBinding;
+					if (valueRequired) {
+						if ((fieldBinding = (FieldBinding) this.codegenBinding).constant == NotAConstant) { // directly use inlined value for constant fields
+							boolean isStatic;
+							if (!(isStatic = fieldBinding.isStatic())) {
+								if ((bits & DepthMASK) != 0) {
+									ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+									Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
+									codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
+								} else {
+									generateReceiver(codeStream);
+								}
 							}
+							// managing private access							
+							if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
+								if (isStatic) {
+									codeStream.getstatic(fieldBinding);
+								} else {
+									codeStream.getfield(fieldBinding);
+								}
+							} else {
+								codeStream.invokestatic(syntheticAccessors[READ]);
+							}
+							codeStream.generateImplicitConversion(implicitConversion);
+						} else { // directly use the inlined value
+							codeStream.generateConstant(fieldBinding.constant, implicitConversion);
+						}
+					}
+					break;
+				case LOCAL : // reading a local
+					LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
+					if (valueRequired) {
+						// outer local?
+						if ((bits & DepthMASK) != 0) {
+							// outer local can be reached either through a synthetic arg or a synthetic field
+							VariableBinding[] path = currentScope.getEmulationPath(localBinding);
+							codeStream.generateOuterAccess(path, this, localBinding, currentScope);
 						} else {
-							codeStream.invokestatic(syntheticAccessors[READ]);
+							// regular local variable read
+							codeStream.load(localBinding);
 						}
 						codeStream.generateImplicitConversion(implicitConversion);
-					} else { // directly use the inlined value
-						codeStream.generateConstant(fieldBinding.constant, implicitConversion);
+					}
+			}
+		}
+		codeStream.recordPositionsFrom(pc, this.sourceStart);
+	}
+	/*
+	 * Regular API for compound assignment, relies on the fact that there is only one reference to the
+	 * variable, which carries both synthetic read/write accessors.
+	 * The APIs with an extra argument is used whenever there are two references to the same variable which
+	 * are optimized in one access: e.g "a = a + 1" optimized into "a++".
+	 */
+	public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
+	
+		this.generateCompoundAssignment(
+			currentScope, 
+			codeStream, 
+			syntheticAccessors == null ? null : syntheticAccessors[WRITE],
+			expression,
+			operator, 
+			assignmentImplicitConversion, 
+			valueRequired);
+	}
+	/*
+	 * The APIs with an extra argument is used whenever there are two references to the same variable which
+	 * are optimized in one access: e.g "a = a + 1" optimized into "a++".
+	 */
+	public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
+		switch (bits & RestrictiveFlagMASK) {
+			case FIELD : // assigning to a field
+				FieldBinding fieldBinding;
+				if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
+					if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
+						codeStream.getstatic(fieldBinding);
+					} else {
+						codeStream.invokestatic(syntheticAccessors[READ]);
+					}
+				} else {
+					if ((bits & DepthMASK) != 0) {
+						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
+						codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
+					} else {
+						codeStream.aload_0();
+					}
+					codeStream.dup();
+					if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
+						codeStream.getfield(fieldBinding);
+					} else {
+						codeStream.invokestatic(syntheticAccessors[READ]);
 					}
 				}
 				break;
-			case LOCAL : // reading a local
+			case LOCAL : // assigning to a local variable (cannot assign to outer local)
 				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
-				if (valueRequired) {
-					// outer local?
-					if ((bits & DepthMASK) != 0) {
-						// outer local can be reached either through a synthetic arg or a synthetic field
-						VariableBinding[] path = currentScope.getEmulationPath(localBinding);
-						codeStream.generateOuterAccess(path, this, localBinding, currentScope);
-					} else {
-						// regular local variable read
+				Constant assignConstant;
+				int increment;
+				// using incr bytecode if possible
+				switch (localBinding.type.id) {
+					case T_String :
+						codeStream.generateStringAppend(currentScope, this, expression);
+						if (valueRequired) {
+							codeStream.dup();
+						}
+						codeStream.store(localBinding, false);
+						return;
+					case T_int :
+						if (((assignConstant = expression.constant) != NotAConstant) 
+							&& (assignConstant.typeID() != T_float) // only for integral types
+							&& (assignConstant.typeID() != T_double)
+							&& ((increment = assignConstant.intValue()) == (short) increment)) { // 16 bits value
+							switch (operator) {
+								case PLUS :
+									codeStream.iinc(localBinding.resolvedPosition, increment);
+									if (valueRequired) {
+										codeStream.load(localBinding);
+									}
+									return;
+								case MINUS :
+									codeStream.iinc(localBinding.resolvedPosition, -increment);
+									if (valueRequired) {
+										codeStream.load(localBinding);
+									}
+									return;
+							}
+						}
+					default :
 						codeStream.load(localBinding);
-					}
-					codeStream.generateImplicitConversion(implicitConversion);
 				}
 		}
-	}
-	codeStream.recordPositionsFrom(pc, this.sourceStart);
-}
-/*
- * Regular API for compound assignment, relies on the fact that there is only one reference to the
- * variable, which carries both synthetic read/write accessors.
- * The APIs with an extra argument is used whenever there are two references to the same variable which
- * are optimized in one access: e.g "a = a + 1" optimized into "a++".
- */
-public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
-
-	this.generateCompoundAssignment(
-		currentScope, 
-		codeStream, 
-		syntheticAccessors == null ? null : syntheticAccessors[WRITE],
-		expression,
-		operator, 
-		assignmentImplicitConversion, 
-		valueRequired);
-}
-/*
- * The APIs with an extra argument is used whenever there are two references to the same variable which
- * are optimized in one access: e.g "a = a + 1" optimized into "a++".
- */
-public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
-	switch (bits & RestrictiveFlagMASK) {
-		case FIELD : // assigning to a field
-			FieldBinding fieldBinding;
-			if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
-				if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
-					codeStream.getstatic(fieldBinding);
-				} else {
-					codeStream.invokestatic(syntheticAccessors[READ]);
-				}
-			} else {
-				if ((bits & DepthMASK) != 0) {
-					ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
-					Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
-					codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
-				} else {
-					codeStream.aload_0();
-				}
-				codeStream.dup();
-				if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
-					codeStream.getfield(fieldBinding);
-				} else {
-					codeStream.invokestatic(syntheticAccessors[READ]);
-				}
-			}
-			break;
-		case LOCAL : // assigning to a local variable (cannot assign to outer local)
-			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
-			Constant assignConstant;
-			int increment;
-			// using incr bytecode if possible
-			switch (localBinding.type.id) {
-				case T_String :
-					codeStream.generateStringAppend(currentScope, this, expression);
-					if (valueRequired) {
-						codeStream.dup();
-					}
-					codeStream.store(localBinding, false);
-					return;
-				case T_int :
-					if (((assignConstant = expression.constant) != NotAConstant) 
-						&& (assignConstant.typeID() != T_float) // only for integral types
-						&& (assignConstant.typeID() != T_double)
-						&& ((increment = assignConstant.intValue()) == (short) increment)) { // 16 bits value
-						switch (operator) {
-							case PLUS :
-								codeStream.iinc(localBinding.resolvedPosition, increment);
-								if (valueRequired) {
-									codeStream.load(localBinding);
-								}
-								return;
-							case MINUS :
-								codeStream.iinc(localBinding.resolvedPosition, -increment);
-								if (valueRequired) {
-									codeStream.load(localBinding);
-								}
-								return;
-						}
-					}
-				default :
-					codeStream.load(localBinding);
-			}
-	}
-	// perform the actual compound operation
-	int operationTypeID;
-	if ((operationTypeID = implicitConversion >> 4) == T_String || operationTypeID == T_Object) {
-		// we enter here if the single name reference is a field of type java.lang.String or if the type of the 
-		// operation is java.lang.Object
-		// For example: o = o + ""; // where the compiled type of o is java.lang.Object.
-		codeStream.generateStringAppend(currentScope, null, expression);
-	} else {
-		// promote the array reference to the suitable operation type
-		codeStream.generateImplicitConversion(implicitConversion);
-		// generate the increment value (will by itself  be promoted to the operation value)
-		if (expression == IntLiteral.One){ // prefix operation
-			codeStream.generateConstant(expression.constant, implicitConversion);			
+		// perform the actual compound operation
+		int operationTypeID;
+		if ((operationTypeID = implicitConversion >> 4) == T_String || operationTypeID == T_Object) {
+			// we enter here if the single name reference is a field of type java.lang.String or if the type of the 
+			// operation is java.lang.Object
+			// For example: o = o + ""; // where the compiled type of o is java.lang.Object.
+			codeStream.generateStringAppend(currentScope, null, expression);
 		} else {
-			expression.generateCode(currentScope, codeStream, true);
-		}		
-		// perform the operation
-		codeStream.sendOperator(operator, operationTypeID);
-		// cast the value back to the array reference type
-		codeStream.generateImplicitConversion(assignmentImplicitConversion);
-	}
-	// store the result back into the variable
-	switch (bits & RestrictiveFlagMASK) {
-		case FIELD : // assigning to a field
-			fieldStore(codeStream, (FieldBinding) this.codegenBinding, writeAccessor, valueRequired);
-			return;
-		case LOCAL : // assigning to a local variable
-			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
-			if (valueRequired) {
-				if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
-					codeStream.dup2();
-				} else {
-					codeStream.dup();
-				}
-			}
-			codeStream.store(localBinding, false);
-	}
-}
-public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
-	switch (bits & RestrictiveFlagMASK) {
-		case FIELD : // assigning to a field
-			FieldBinding fieldBinding;
-			if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
-				if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
-					codeStream.getstatic(fieldBinding);
-				} else {
-					codeStream.invokestatic(syntheticAccessors[READ]);
-				}
+			// promote the array reference to the suitable operation type
+			codeStream.generateImplicitConversion(implicitConversion);
+			// generate the increment value (will by itself  be promoted to the operation value)
+			if (expression == IntLiteral.One){ // prefix operation
+				codeStream.generateConstant(expression.constant, implicitConversion);			
 			} else {
-				if ((bits & DepthMASK) != 0) {
-					ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
-					Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
-					codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
-				} else {
-					codeStream.aload_0();
-				}
-				codeStream.dup();
-				if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
-					codeStream.getfield(fieldBinding);
-				} else {
-					codeStream.invokestatic(syntheticAccessors[READ]);
-				}
-			}
-			if (valueRequired) {
-				if (fieldBinding.isStatic()) {
-					if ((fieldBinding.type == LongBinding) || (fieldBinding.type == DoubleBinding)) {
-						codeStream.dup2();
-					} else {
-						codeStream.dup();
-					}
-				} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
-					if ((fieldBinding.type == LongBinding) || (fieldBinding.type == DoubleBinding)) {
-						codeStream.dup2_x1();
-					} else {
-						codeStream.dup_x1();
-					}
-				}
-			}
-			codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
-			codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
-			codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
-			fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], false);
-			return;
-		case LOCAL : // assigning to a local variable
-			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
-			// using incr bytecode if possible
-			if (localBinding.type == IntBinding) {
+				expression.generateCode(currentScope, codeStream, true);
+			}		
+			// perform the operation
+			codeStream.sendOperator(operator, operationTypeID);
+			// cast the value back to the array reference type
+			codeStream.generateImplicitConversion(assignmentImplicitConversion);
+		}
+		// store the result back into the variable
+		switch (bits & RestrictiveFlagMASK) {
+			case FIELD : // assigning to a field
+				fieldStore(codeStream, (FieldBinding) this.codegenBinding, writeAccessor, valueRequired);
+				return;
+			case LOCAL : // assigning to a local variable
+				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 				if (valueRequired) {
-					codeStream.load(localBinding);
-				}
-				if (postIncrement.operator == PLUS) {
-					codeStream.iinc(localBinding.resolvedPosition, 1);
-				} else {
-					codeStream.iinc(localBinding.resolvedPosition, -1);
-				}
-			} else {
-				codeStream.load(localBinding);
-				if (valueRequired){
 					if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
 						codeStream.dup2();
 					} else {
 						codeStream.dup();
 					}
 				}
-				codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
-				codeStream.sendOperator(postIncrement.operator, localBinding.type.id);
-				codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
-
 				codeStream.store(localBinding, false);
-			}
-	}
-}
-public void generateReceiver(CodeStream codeStream) {
-	codeStream.aload_0();
-}
-public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
-
-	//If inlinable field, forget the access emulation, the code gen will directly target it
-	if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) return;
-
-	if ((bits & RestrictiveFlagMASK) == LOCAL) {
-		currentScope.emulateOuterAccess((LocalVariableBinding) binding);
-	}
-}
-public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope) {
-
-	//If inlinable field, forget the access emulation, the code gen will directly target it
-	if (constant != NotAConstant)
-		return;
-
-	if ((bits & FIELD) != 0) {
-		FieldBinding fieldBinding = (FieldBinding) binding;
-		if (((bits & DepthMASK) != 0)
-			&& (fieldBinding.isPrivate() // private access
-				|| (fieldBinding.isProtected() // implicit protected access
-						&& fieldBinding.declaringClass.getPackage() 
-							!= currentScope.enclosingSourceType().getPackage()))) {
-			if (syntheticAccessors == null)
-				syntheticAccessors = new MethodBinding[2];
-			syntheticAccessors[READ] = 
-				((SourceTypeBinding)currentScope.enclosingSourceType().
-					enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
-						addSyntheticMethod(fieldBinding, true);
-			currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
-			return;
-		}
-		// if the binding declaring class is not visible, need special action
-		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
-		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-		// and not from Object or implicit static field access.	
-		if (fieldBinding.declaringClass != this.actualReceiverType
-			&& !this.actualReceiverType.isArrayType()	
-			&& fieldBinding.declaringClass != null
-			&& fieldBinding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2 
-					&& !fieldBinding.isStatic()
-					&& fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
-				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
-			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
 		}
 	}
-}
-public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope) {
-
-	if ((bits & FIELD) != 0) {
-		FieldBinding fieldBinding = (FieldBinding) binding;
-		if (((bits & DepthMASK) != 0) 
-			&& (fieldBinding.isPrivate() // private access
-				|| (fieldBinding.isProtected() // implicit protected access
-						&& fieldBinding.declaringClass.getPackage() 
-							!= currentScope.enclosingSourceType().getPackage()))) {
-			if (syntheticAccessors == null)
-				syntheticAccessors = new MethodBinding[2];
-			syntheticAccessors[WRITE] = 
-				((SourceTypeBinding)currentScope.enclosingSourceType().
-					enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
-						addSyntheticMethod(fieldBinding, false);
-			currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
-			return;
-		}
-		// if the binding declaring class is not visible, need special action
-		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
-		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-		// and not from Object or implicit static field access.	
-		if (fieldBinding.declaringClass != this.actualReceiverType
-			&& !this.actualReceiverType.isArrayType()	
-			&& fieldBinding.declaringClass != null
-			&& fieldBinding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2 
-					&& !fieldBinding.isStatic()
-					&& fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
-				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
-			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
-		}
-	}
-}
-public TypeBinding reportError(BlockScope scope) {
-	//=====error cases=======
-	constant = Constant.NotAConstant;
-	if (binding instanceof ProblemFieldBinding) {
-		scope.problemReporter().invalidField(this, (FieldBinding) binding);
-	} else if (binding instanceof ProblemReferenceBinding) {
-		scope.problemReporter().invalidType(this, (TypeBinding) binding);
-	} else {
-		scope.problemReporter().unresolvableReference(this, binding);
-	}
-	return null;
-}
-public TypeBinding resolveType(BlockScope scope) {
-	// for code gen, harm the restrictiveFlag 	
-
-	this.actualReceiverType = this.receiverType = scope.enclosingSourceType();
 	
-	if ((this.codegenBinding = this.binding = scope.getBinding(token, bits & RestrictiveFlagMASK, this)).isValidBinding()) {
+	public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
 		switch (bits & RestrictiveFlagMASK) {
-			case VARIABLE : // =========only variable============
-			case VARIABLE | TYPE : //====both variable and type============
-				if (binding instanceof VariableBinding) {
-					VariableBinding variable = (VariableBinding) binding;
-					if (binding instanceof LocalVariableBinding) {
-						bits &= ~RestrictiveFlagMASK;  // clear bits
-						bits |= LOCAL;
-						if ((this.bits & IsStrictlyAssignedMASK) == 0) {
-							constant = variable.constant;
-						} else {
-							constant = NotAConstant;
-						}
-						if ((!variable.isFinal()) && ((bits & DepthMASK) != 0)) {
-							scope.problemReporter().cannotReferToNonFinalOuterLocal((LocalVariableBinding)variable, this);
-						}
-						return this.resolvedType = variable.type;
+			case FIELD : // assigning to a field
+				FieldBinding fieldBinding;
+				if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
+					if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
+						codeStream.getstatic(fieldBinding);
+					} else {
+						codeStream.invokestatic(syntheticAccessors[READ]);
 					}
-					// a field
-					return this.resolvedType = checkFieldAccess(scope);
+				} else {
+					if ((bits & DepthMASK) != 0) {
+						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
+						codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
+					} else {
+						codeStream.aload_0();
+					}
+					codeStream.dup();
+					if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
+						codeStream.getfield(fieldBinding);
+					} else {
+						codeStream.invokestatic(syntheticAccessors[READ]);
+					}
 				}
-
-				// thus it was a type
-				bits &= ~RestrictiveFlagMASK;  // clear bits
-				bits |= TYPE;
-			case TYPE : //========only type==============
-				constant = Constant.NotAConstant;
-				//deprecated test
-				if (isTypeUseDeprecated((TypeBinding) binding, scope))
-					scope.problemReporter().deprecatedType((TypeBinding) binding, this);
-				return this.resolvedType = (TypeBinding) binding;
+				if (valueRequired) {
+					if (fieldBinding.isStatic()) {
+						if ((fieldBinding.type == LongBinding) || (fieldBinding.type == DoubleBinding)) {
+							codeStream.dup2();
+						} else {
+							codeStream.dup();
+						}
+					} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
+						if ((fieldBinding.type == LongBinding) || (fieldBinding.type == DoubleBinding)) {
+							codeStream.dup2_x1();
+						} else {
+							codeStream.dup_x1();
+						}
+					}
+				}
+				codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
+				codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
+				codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
+				fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], false);
+				return;
+			case LOCAL : // assigning to a local variable
+				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
+				// using incr bytecode if possible
+				if (localBinding.type == IntBinding) {
+					if (valueRequired) {
+						codeStream.load(localBinding);
+					}
+					if (postIncrement.operator == PLUS) {
+						codeStream.iinc(localBinding.resolvedPosition, 1);
+					} else {
+						codeStream.iinc(localBinding.resolvedPosition, -1);
+					}
+				} else {
+					codeStream.load(localBinding);
+					if (valueRequired){
+						if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
+							codeStream.dup2();
+						} else {
+							codeStream.dup();
+						}
+					}
+					codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
+					codeStream.sendOperator(postIncrement.operator, localBinding.type.id);
+					codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
+	
+					codeStream.store(localBinding, false);
+				}
 		}
 	}
-
-	// error scenarii
-	return this.resolvedType = this.reportError(scope);
-}
-public String toStringExpression(){
-
-	return new String(token);}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
-public String unboundReferenceErrorName(){
-
-	return new String(token);}
+	
+	public void generateReceiver(CodeStream codeStream) {
+		
+		codeStream.aload_0();
+	}
+	
+	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+	
+		if (!flowInfo.isReachable()) return;
+		//If inlinable field, forget the access emulation, the code gen will directly target it
+		if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) return;
+	
+		if ((bits & RestrictiveFlagMASK) == LOCAL) {
+			currentScope.emulateOuterAccess((LocalVariableBinding) binding);
+		}
+	}
+	public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+	
+		if (!flowInfo.isReachable()) return;
+	
+		//If inlinable field, forget the access emulation, the code gen will directly target it
+		if (constant != NotAConstant)
+			return;
+	
+		if ((bits & FIELD) != 0) {
+			FieldBinding fieldBinding = (FieldBinding) binding;
+			if (((bits & DepthMASK) != 0)
+				&& (fieldBinding.isPrivate() // private access
+					|| (fieldBinding.isProtected() // implicit protected access
+							&& fieldBinding.declaringClass.getPackage() 
+								!= currentScope.enclosingSourceType().getPackage()))) {
+				if (syntheticAccessors == null)
+					syntheticAccessors = new MethodBinding[2];
+				syntheticAccessors[READ] = 
+					((SourceTypeBinding)currentScope.enclosingSourceType().
+						enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
+							addSyntheticMethod(fieldBinding, true);
+				currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
+				return;
+			}
+			// if the binding declaring class is not visible, need special action
+			// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
+			// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
+			// and not from Object or implicit static field access.	
+			if (fieldBinding.declaringClass != this.actualReceiverType
+				&& !this.actualReceiverType.isArrayType()	
+				&& fieldBinding.declaringClass != null
+				&& fieldBinding.constant == NotAConstant
+				&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
+						&& !fieldBinding.isStatic()
+						&& fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
+					|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
+				this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
+			}
+		}
+	}
+	public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+	
+		if (!flowInfo.isReachable()) return;
+		if ((bits & FIELD) != 0) {
+			FieldBinding fieldBinding = (FieldBinding) binding;
+			if (((bits & DepthMASK) != 0) 
+				&& (fieldBinding.isPrivate() // private access
+					|| (fieldBinding.isProtected() // implicit protected access
+							&& fieldBinding.declaringClass.getPackage() 
+								!= currentScope.enclosingSourceType().getPackage()))) {
+				if (syntheticAccessors == null)
+					syntheticAccessors = new MethodBinding[2];
+				syntheticAccessors[WRITE] = 
+					((SourceTypeBinding)currentScope.enclosingSourceType().
+						enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
+							addSyntheticMethod(fieldBinding, false);
+				currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
+				return;
+			}
+			// if the binding declaring class is not visible, need special action
+			// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
+			// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
+			// and not from Object or implicit static field access.	
+			if (fieldBinding.declaringClass != this.actualReceiverType
+				&& !this.actualReceiverType.isArrayType()	
+				&& fieldBinding.declaringClass != null
+				&& fieldBinding.constant == NotAConstant
+				&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
+						&& !fieldBinding.isStatic()
+						&& fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
+					|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
+				this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
+			}
+		}
+	}
+	public StringBuffer printExpression(int indent, StringBuffer output){
+	
+		return output.append(token);
+	}
+	
+	public TypeBinding reportError(BlockScope scope) {
+		
+		//=====error cases=======
+		constant = Constant.NotAConstant;
+		if (binding instanceof ProblemFieldBinding) {
+			scope.problemReporter().invalidField(this, (FieldBinding) binding);
+		} else if (binding instanceof ProblemReferenceBinding) {
+			scope.problemReporter().invalidType(this, (TypeBinding) binding);
+		} else {
+			scope.problemReporter().unresolvableReference(this, binding);
+		}
+		return null;
+	}
+	public TypeBinding resolveType(BlockScope scope) {
+		// for code gen, harm the restrictiveFlag 	
+	
+		this.actualReceiverType = this.receiverType = scope.enclosingSourceType();
+		
+		if ((this.codegenBinding = this.binding = scope.getBinding(token, bits & RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
+			switch (bits & RestrictiveFlagMASK) {
+				case VARIABLE : // =========only variable============
+				case VARIABLE | TYPE : //====both variable and type============
+					if (binding instanceof VariableBinding) {
+						VariableBinding variable = (VariableBinding) binding;
+						if (binding instanceof LocalVariableBinding) {
+							bits &= ~RestrictiveFlagMASK;  // clear bits
+							bits |= LOCAL;
+							if ((this.bits & IsStrictlyAssignedMASK) == 0) {
+								constant = variable.constant;
+							} else {
+								constant = NotAConstant;
+							}
+							if (!variable.isFinal() && (bits & DepthMASK) != 0) {
+								scope.problemReporter().cannotReferToNonFinalOuterLocal((LocalVariableBinding)variable, this);
+							}
+							return this.resolvedType = variable.type;
+						}
+						// a field
+						FieldBinding field = (FieldBinding) this.binding;
+						if (!field.isStatic() && scope.environment().options.getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) {
+							scope.problemReporter().unqualifiedFieldAccess(this, field);
+						}
+						return this.resolvedType = checkFieldAccess(scope);
+					}
+	
+					// thus it was a type
+					bits &= ~RestrictiveFlagMASK;  // clear bits
+					bits |= TYPE;
+				case TYPE : //========only type==============
+					constant = Constant.NotAConstant;
+					//deprecated test
+					if (isTypeUseDeprecated((TypeBinding) binding, scope))
+						scope.problemReporter().deprecatedType((TypeBinding) binding, this);
+					return this.resolvedType = (TypeBinding) binding;
+			}
+		}
+	
+		// error scenarii
+		return this.resolvedType = this.reportError(scope);
+	}
+		
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+	
+	public String unboundReferenceErrorName(){
+	
+		return new String(token);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
index e907566..9838d04 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
@@ -10,56 +10,67 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class SingleTypeReference extends TypeReference {
-	public char[] token;
-	
 
-public SingleTypeReference(char[] source, long pos) {
-		token = source;
-		sourceStart = (int) (pos>>>32)  ;
-		sourceEnd = (int) (pos & 0x00000000FFFFFFFFL) ;
-	
-}
-public SingleTypeReference(char[] source ,TypeBinding type, long pos) {
-	this(source, pos) ;
-	this.resolvedType = type ;
-}
-public TypeReference copyDims(int dim){
-	//return a type reference copy of me with some dimensions
-	//warning : the new type ref has a null binding
-	
-	return new ArrayTypeReference(token,null,dim,(((long)sourceStart)<<32)+sourceEnd) ;
-}
-public TypeBinding getTypeBinding(Scope scope) {
-	if (this.resolvedType != null)
-		return this.resolvedType;
-	return scope.getType(token);
-}
-public char [][] getTypeName() {
-	return new char[][] { token };
-}
-public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
-	ReferenceBinding memberTb = scope.getMemberType(token, enclosingType);
-	if (!memberTb.isValidBinding()) {
-		scope.problemReporter().invalidEnclosingType(this, memberTb, enclosingType);
-		return null;
+	public char[] token;
+
+	public SingleTypeReference(char[] source, long pos) {
+
+			token = source;
+			sourceStart = (int) (pos>>>32)  ;
+			sourceEnd = (int) (pos & 0x00000000FFFFFFFFL) ;
+		
 	}
-	if (isTypeUseDeprecated(memberTb, scope))
-		scope.problemReporter().deprecatedType(memberTb, this);
-	return this.resolvedType = memberTb;
-}
-public String toStringExpression(int tab){
-	return new String(token) ;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope scope) {
-	visitor.visit(this, scope);
-	visitor.endVisit(this, scope);
-}
+
+	public SingleTypeReference(char[] source ,TypeBinding type, long pos) {
+		this(source, pos) ;
+		this.resolvedType = type ;
+	}
+
+	public TypeReference copyDims(int dim){
+		//return a type reference copy of me with some dimensions
+		//warning : the new type ref has a null binding
+		
+		return new ArrayTypeReference(token,null,dim,(((long)sourceStart)<<32)+sourceEnd) ;
+	}
+
+	public TypeBinding getTypeBinding(Scope scope) {
+		if (this.resolvedType != null)
+			return this.resolvedType;
+		return scope.getType(token);
+	}
+
+	public char [][] getTypeName() {
+		return new char[][] { token };
+	}
+
+	public StringBuffer printExpression(int indent, StringBuffer output){
+		
+		return output.append(token);
+	}
+
+	public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
+
+		ReferenceBinding memberTb = scope.getMemberType(token, enclosingType);
+		if (!memberTb.isValidBinding()) {
+			scope.problemReporter().invalidEnclosingType(this, memberTb, enclosingType);
+			return null;
+		}
+		if (isTypeUseDeprecated(memberTb, scope))
+			scope.problemReporter().deprecatedType(memberTb, this);
+		return this.resolvedType = memberTb;
+	}
+
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
+
+	public void traverse(ASTVisitor visitor, ClassScope scope) {
+		visitor.visit(this, scope);
+		visitor.endVisit(this, scope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
index bdacc05..9bbb636 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -15,17 +15,32 @@
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
-public abstract class Statement extends AstNode {
-	
-	/**
-	 * Statement constructor comment.
-	 */
-	public Statement() {
-		super();
-	}
+public abstract class Statement extends ASTNode {
 	
 	public abstract FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo);
 	
+	/**
+	 * INTERNAL USE ONLY.
+	 * This is used to redirect inter-statements jumps.
+	 */
+	public void branchChainTo(Label label) {
+		// do nothing by default
+	}
+	
+	// Report an error if necessary
+	public boolean complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, boolean didAlreadyComplain) {
+	
+		if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0) {
+			this.bits &= ~ASTNode.IsReachableMASK;
+			boolean reported = flowInfo == FlowInfo.DEAD_END;
+			if (!didAlreadyComplain && reported) {
+				scope.problemReporter().unreachableCode(this);
+			}
+			return reported; // keep going for fake reachable
+		}
+		return false;
+	}
+	
 	public abstract void generateCode(BlockScope currentScope, CodeStream codeStream);
 	
 	public boolean isEmptyBlock() {
@@ -47,6 +62,15 @@
 		return true;
 	}
 	
+	public StringBuffer print(int indent, StringBuffer output) {
+		return printStatement(indent, output);
+	}
+	public abstract StringBuffer printStatement(int indent, StringBuffer output);
+
+	public void resetStateForCodeGeneration() {
+		// do nothing by default
+	}
+	
 	public abstract void resolve(BlockScope scope);
 	
 	public Constant resolveCase(BlockScope scope, TypeBinding testType, SwitchStatement switchStatement) {
@@ -55,14 +79,5 @@
 		resolve(scope);
 		return null;
 	}
-	
-	public void resetStateForCodeGeneration() {
-	}
-	
-	/**
-	 * INTERNAL USE ONLY.
-	 * Do nothing by default. This is used to redirect inter-statements jumps.
-	 */
-	public void branchChainTo(Label label) {
-	}
+
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/StringLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/StringLiteral.java
index 656c7f4..b4c5ec7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/StringLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/StringLiteral.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -64,50 +64,50 @@
 		return scope.getJavaLangString();
 	}
 
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+	
+		// handle some special char.....
+		output.append('\"');
+		for (int i = 0; i < source.length; i++) {
+			switch (source[i]) {
+				case '\b' :
+					output.append("\\b"); //$NON-NLS-1$
+					break;
+				case '\t' :
+					output.append("\\t"); //$NON-NLS-1$
+					break;
+				case '\n' :
+					output.append("\\n"); //$NON-NLS-1$
+					break;
+				case '\f' :
+					output.append("\\f"); //$NON-NLS-1$
+					break;
+				case '\r' :
+					output.append("\\r"); //$NON-NLS-1$
+					break;
+				case '\"' :
+					output.append("\\\""); //$NON-NLS-1$
+					break;
+				case '\'' :
+					output.append("\\'"); //$NON-NLS-1$
+					break;
+				case '\\' : //take care not to display the escape as a potential real char
+					output.append("\\\\"); //$NON-NLS-1$
+					break;
+				default :
+					output.append(source[i]);
+			}
+		}
+		output.append('\"'); 
+		return output;
+	}
+
 	public char[] source() {
 
 		return source;
 	}
 
-	public String toStringExpression() {
-	
-		// handle some special char.....
-		StringBuffer result = new StringBuffer("\""); //$NON-NLS-1$
-		for (int i = 0; i < source.length; i++) {
-			switch (source[i]) {
-				case '\b' :
-					result.append("\\b"); //$NON-NLS-1$
-					break;
-				case '\t' :
-					result.append("\\t"); //$NON-NLS-1$
-					break;
-				case '\n' :
-					result.append("\\n"); //$NON-NLS-1$
-					break;
-				case '\f' :
-					result.append("\\f"); //$NON-NLS-1$
-					break;
-				case '\r' :
-					result.append("\\r"); //$NON-NLS-1$
-					break;
-				case '\"' :
-					result.append("\\\""); //$NON-NLS-1$
-					break;
-				case '\'' :
-					result.append("\\'"); //$NON-NLS-1$
-					break;
-				case '\\' : //take care not to display the escape as a potential real char
-					result.append("\\\\"); //$NON-NLS-1$
-					break;
-				default :
-					result.append(source[i]);
-			}
-		}
-		result.append("\""); //$NON-NLS-1$
-		return result.toString();
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+	public void traverse(ASTVisitor visitor, BlockScope scope) {
 		visitor.visit(this, scope);
 		visitor.endVisit(this, scope);
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java
new file mode 100644
index 0000000..51e37ac
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+
+/**
+ * Extra behavior for statements which are generating subroutines
+ */
+public abstract class SubRoutineStatement extends Statement {
+	
+	public static final ExceptionLabel[] NO_EXCEPTION_HANDLER = new ExceptionLabel[0];
+	ExceptionLabel[] anyExceptionLabels = NO_EXCEPTION_HANDLER;
+	int anyExceptionLabelsCount = 0;
+	
+	public abstract boolean isSubRoutineEscaping();
+
+	public abstract void generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream);
+	
+	public ExceptionLabel enterAnyExceptionHandler(CodeStream codeStream) {
+		
+		int length;
+		if ((length = this.anyExceptionLabelsCount) == this.anyExceptionLabels.length) {
+			System.arraycopy(this.anyExceptionLabels, 0 , this.anyExceptionLabels=new ExceptionLabel[length*2 + 1], 0, length);
+		}
+		ExceptionLabel exceptionLabel = new ExceptionLabel(codeStream, null);
+		this.anyExceptionLabels[this.anyExceptionLabelsCount++] = exceptionLabel;
+		return exceptionLabel;
+	}
+
+	public void exitAnyExceptionHandler() {
+		if (this.anyExceptionLabelsCount == 0) return;
+		ExceptionLabel currentLabel = this.anyExceptionLabels[this.anyExceptionLabelsCount-1];
+		if (currentLabel.start == currentLabel.codeStream.position) {
+			// discard empty exception handler
+			this.anyExceptionLabels[--this.anyExceptionLabelsCount] = null;
+		}
+		currentLabel.placeEnd();
+	}
+	
+	public void placeAllAnyExceptionHandlers() {
+		
+		for (int i = 0; i < this.anyExceptionLabelsCount; i++) {
+			this.anyExceptionLabels[i].place();
+		}
+	}
+	
+	public static void reenterExceptionHandlers(SubRoutineStatement[] subroutines, int max, CodeStream codeStream) {
+		if (subroutines == null) return;
+		if (max < 0) max = subroutines.length;
+		for (int i = 0; i < max; i++) {
+			subroutines[i].enterAnyExceptionHandler(codeStream); 
+		}	
+	}
+
+	public void resetStateForCodeGeneration() {
+		if (this.anyExceptionLabelsCount > 0) {
+			this.anyExceptionLabels = NO_EXCEPTION_HANDLER;
+			this.anyExceptionLabelsCount = 0;
+		}
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
index 2111e62..feb3718 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
@@ -10,49 +10,59 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 
 public class SuperReference extends ThisReference {
 	
-public SuperReference(int sourceStart, int sourceEnd) {
-	super(sourceStart, sourceEnd);
-}
-public static ExplicitConstructorCall implicitSuperConstructorCall() {
-	return new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
-}
-public boolean isImplicitThis() {
-	
-	return false;
-}
-public boolean isSuper() {
-	
-	return true;
-}
-public boolean isThis() {
-	
-	return false ;
-}
-public TypeBinding resolveType(BlockScope scope) {
-	constant = NotAConstant;
-	if (!checkAccess(scope.methodScope()))
-		return null;
-	SourceTypeBinding enclosingTb = scope.enclosingSourceType();
-	if (scope.isJavaLangObject(enclosingTb)) {
-		scope.problemReporter().cannotUseSuperInJavaLangObject(this);
-		return null;
-	}
-	return this.resolvedType = enclosingTb.superclass;
-}
-public String toStringExpression(){
+	public SuperReference(int sourceStart, int sourceEnd) {
 
-	return "super"; //$NON-NLS-1$
+		super(sourceStart, sourceEnd);
+	}
+
+	public static ExplicitConstructorCall implicitSuperConstructorCall() {
+
+		return new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
+	}
+
+	public boolean isImplicitThis() {
+		
+		return false;
+	}
+
+	public boolean isSuper() {
+		
+		return true;
+	}
+
+	public boolean isThis() {
+		
+		return false ;
+	}
+
+	public StringBuffer printExpression(int indent, StringBuffer output){
 	
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
-	visitor.visit(this, blockScope);
-	visitor.endVisit(this, blockScope);
-}
+		return output.append("super"); //$NON-NLS-1$
+		
+	}
+
+	public TypeBinding resolveType(BlockScope scope) {
+
+		constant = NotAConstant;
+		if (!checkAccess(scope.methodScope()))
+			return null;
+		SourceTypeBinding enclosingTb = scope.enclosingSourceType();
+		if (scope.isJavaLangObject(enclosingTb)) {
+			scope.problemReporter().cannotUseSuperInJavaLangObject(this);
+			return null;
+		}
+		return this.resolvedType = enclosingTb.superclass;
+	}
+
+	public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+		visitor.visit(this, blockScope);
+		visitor.endVisit(this, blockScope);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
index a8fa167..4302a0c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
@@ -10,36 +10,43 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class SwitchStatement extends Statement {
-	public Expression testExpression;
+
+	public Expression expression;
 	public Statement[] statements;
 	public BlockScope scope;
 	public int explicitDeclarations;
 	public Label breakLabel;
-	public Case[] cases;
-	public DefaultCase defaultCase;
+	public CaseStatement[] cases;
+	public CaseStatement defaultCase;
 	public int caseCount = 0;
-
+	public int blockStart;
+	
 	// for local variables table attributes
 	int preSwitchInitStateIndex = -1;
 	int mergedInitStateIndex = -1;
+
 	/**
 	 * SwitchStatement constructor comment.
 	 */
 	public SwitchStatement() {
+
 		super();
 	}
+
 	public FlowInfo analyseCode(
-		BlockScope currentScope,
-		FlowContext flowContext,
-		FlowInfo flowInfo) {
-		flowInfo = testExpression.analyseCode(currentScope, flowContext, flowInfo);
+			BlockScope currentScope,
+			FlowContext flowContext,
+			FlowInfo flowInfo) {
+			
+		flowInfo = expression.analyseCode(currentScope, flowContext, flowInfo);
 		SwitchFlowContext switchContext =
 			new SwitchFlowContext(flowContext, this, (breakLabel = new Label()));
 
@@ -62,7 +69,7 @@
 					caseInits = caseInits.mergedWith(flowInfo.copy().unconditionalInits());
 					didAlreadyComplain = false; // reset complaint
 				}
-				if (!caseInits.complainIfUnreachable(statement, scope, didAlreadyComplain)) {
+				if (!statement.complainIfUnreachable(caseInits, scope, didAlreadyComplain)) {
 					caseInits = statement.analyseCode(scope, switchContext, caseInits);
 				} else {
 					didAlreadyComplain = true;
@@ -86,6 +93,7 @@
 			currentScope.methodScope().recordInitializationStates(mergedInfo);
 		return mergedInfo;
 	}
+
 	/**
 	 * Switch code generation
 	 *
@@ -93,6 +101,7 @@
 	 * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
 	 */
 	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
 		int[] sortedIndexes = new int[caseCount];
 		int[] localKeysCopy;
 		if ((bits & IsReachableMASK) == 0) {
@@ -126,7 +135,7 @@
 			defaultCase.targetLabel = defaultLabel;
 		}
 		// generate expression testes
-		testExpression.generateCode(currentScope, codeStream, needSwitch);
+		expression.generateCode(currentScope, codeStream, needSwitch);
 
 		// generate the appropriate switch table/lookup bytecode
 		if (needSwitch) {
@@ -136,7 +145,7 @@
 				
 				// work-around 1.3 VM bug, if max>0x7FFF0000, must use lookup bytecode
 				// see http://dev.eclipse.org/bugs/show_bug.cgi?id=21557
-				if (max > 0x7FFF0000 && currentScope.environment().options.complianceLevel < CompilerOptions.JDK1_4) {
+				if (max > 0x7FFF0000 && currentScope.environment().options.complianceLevel < ClassFileConstants.JDK1_4) {
 					codeStream.lookupswitch(defaultLabel, constants, sortedIndexes, caseLabels);
 
 				} else {
@@ -197,22 +206,40 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+
+		printIndent(indent, output).append("switch ("); //$NON-NLS-1$
+		expression.printExpression(0, output).append(") {"); //$NON-NLS-1$
+		if (statements != null) {
+			for (int i = 0; i < statements.length; i++) {
+				output.append('\n');
+				if (statements[i] instanceof CaseStatement) {
+					statements[i].printStatement(indent, output);
+				} else {
+					statements[i].printStatement(indent+2, output);
+				}
+			}
+		}
+		output.append("\n"); //$NON-NLS-1$
+		return printIndent(indent, output).append('}');
+	}
 
 	public void resetStateForCodeGeneration() {
+
 		if (this.breakLabel != null) {
 			this.breakLabel.resetStateForCodeGeneration();
 		}
 	}
 
 	public void resolve(BlockScope upperScope) {
-
-		TypeBinding testType = testExpression.resolveType(upperScope);
+	
+		TypeBinding testType = expression.resolveType(upperScope);
 		if (testType == null)
 			return;
-		testExpression.implicitWidening(testType, testType);
-		if (!(testExpression.isConstantValueOfTypeAssignableToType(testType, IntBinding))) {
+		expression.implicitWidening(testType, testType);
+		if (!(expression.isConstantValueOfTypeAssignableToType(testType, IntBinding))) {
 			if (!testType.isCompatibleWith(IntBinding)) {
-				upperScope.problemReporter().incorrectSwitchType(testExpression, testType);
+				upperScope.problemReporter().incorrectSwitchType(expression, testType);
 				return;
 			}
 		}
@@ -220,83 +247,59 @@
 			scope = explicitDeclarations == 0 ? upperScope : new BlockScope(upperScope);
 			int length;
 			// collection of cases is too big but we will only iterate until caseCount
-			cases = new Case[length = statements.length];
+			cases = new CaseStatement[length = statements.length];
 			int[] casesValues = new int[length];
+			CaseStatement[] duplicateCaseStatements = null;
+			int duplicateCaseStatementsCounter = 0;
 			int counter = 0;
 			for (int i = 0; i < length; i++) {
-				Constant cst;
-				if ((cst = statements[i].resolveCase(scope, testType, this)) != null) {
+				Constant constant;
+				final Statement statement = statements[i];
+				if ((constant = statement.resolveCase(scope, testType, this)) != null) {
 					//----check for duplicate case statement------------
-					if (cst != NotAConstant) {
-						int key = cst.intValue();
+					if (constant != NotAConstant) {
+						int key = constant.intValue();
 						for (int j = 0; j < counter; j++) {
 							if (casesValues[j] == key) {
-								scope.problemReporter().duplicateCase((Case) statements[i], cst); //TODO: (philippe) could improve diagnosis to indicate colliding case
+								final CaseStatement currentCaseStatement = (CaseStatement) statement;
+								if (duplicateCaseStatements == null) {
+									scope.problemReporter().duplicateCase(cases[j]);
+									scope.problemReporter().duplicateCase(currentCaseStatement);
+									duplicateCaseStatements = new CaseStatement[length];
+									duplicateCaseStatements[duplicateCaseStatementsCounter++] = cases[j];
+									duplicateCaseStatements[duplicateCaseStatementsCounter++] = currentCaseStatement;
+								} else {
+									boolean found = false;
+									searchReportedDuplicate: for (int k = 2; k < duplicateCaseStatementsCounter; k++) {
+										if (duplicateCaseStatements[k] == statement) {
+											found = true;
+											break searchReportedDuplicate;
+										}
+									}
+									if (!found) {
+										scope.problemReporter().duplicateCase(currentCaseStatement);
+										duplicateCaseStatements[duplicateCaseStatementsCounter++] = currentCaseStatement;
+									}
+								}
 							}
 						}
 						casesValues[counter++] = key;
 					}
 				}
 			}
-		}
-	}
-	public String toString(int tab) {
-
-		String inFront, s = tabString(tab);
-		inFront = s;
-		s = s + "switch (" + testExpression.toStringExpression() + ") "; //$NON-NLS-1$ //$NON-NLS-2$
-		if (statements == null) {
-			s = s + "{}"; //$NON-NLS-1$
-			return s;
-		} else
-			s = s + "{"; //$NON-NLS-1$
-			s = s
-					+ (explicitDeclarations != 0
-						? "// ---scope needed for " //$NON-NLS-1$
-							+ String.valueOf(explicitDeclarations)
-							+ " locals------------ \n"//$NON-NLS-1$
-						: "// ---NO scope needed------ \n"); //$NON-NLS-1$
-
-		int i = 0;
-		String tabulation = "  "; //$NON-NLS-1$
-		try {
-			while (true) {
-				//use instanceof in order not to polluate classes with behavior only needed for printing purpose.
-				if (statements[i] instanceof Expression)
-					s = s + "\n" + inFront + tabulation; //$NON-NLS-1$
-				if (statements[i] instanceof Break)
-					s = s + statements[i].toString(0);
-				else
-					s = s + "\n" + statements[i].toString(tab + 2); //$NON-NLS-1$
-				//=============	
-				if ((statements[i] instanceof Case)
-					|| (statements[i] instanceof DefaultCase)) {
-					i++;
-					while (!((statements[i] instanceof Case)
-						|| (statements[i] instanceof DefaultCase))) {
-						if ((statements[i] instanceof Expression) || (statements[i] instanceof Break))
-							s = s + statements[i].toString(0) + " ; "; //$NON-NLS-1$
-						else
-							s = s + "\n" + statements[i].toString(tab + 6) + " ; "; //$NON-NLS-1$ //$NON-NLS-2$
-						i++;
-					}
-				} else {
-					s = s + " ;"; //$NON-NLS-1$
-					i++;
-				}
+		} else {
+			if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
+				upperScope.problemReporter().undocumentedEmptyBlock(this.blockStart, this.sourceEnd);
 			}
-		} catch (IndexOutOfBoundsException e) {
-		};
-		s = s + "}"; //$NON-NLS-1$
-		return s;
+		}
 	}
 
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
-		BlockScope blockScope) {
+			ASTVisitor visitor,
+			BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
-			testExpression.traverse(visitor, scope);
+			expression.traverse(visitor, scope);
 			if (statements != null) {
 				int statementsLength = statements.length;
 				for (int i = 0; i < statementsLength; i++)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
index ac2f5a3..e92358a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
@@ -10,17 +10,16 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
-public class SynchronizedStatement extends Statement {
+public class SynchronizedStatement extends SubRoutineStatement {
 
 	public Expression expression;
 	public Block block;
 	public BlockScope scope;
-
 	boolean blockExit;
 	public LocalVariableBinding synchroVariable;
 	static final char[] SecretLocalDeclarationName = " syncValue".toCharArray(); //$NON-NLS-1$
@@ -58,6 +57,11 @@
 		return flowInfo;
 	}
 
+	public boolean isSubRoutineEscaping() {
+
+		return false;
+	}
+	
 	/**
 	 * Synchronized statement code generation
 	 *
@@ -89,8 +93,7 @@
 			codeStream.monitorenter();
 
 			// generate  the body of the synchronized block
-			ExceptionLabel anyExceptionHandler = new ExceptionLabel(codeStream, null);
-			//'null' denotes any kind of exception
+			this.enterAnyExceptionHandler(codeStream);
 			block.generateCode(scope, codeStream);
 			Label endLabel = new Label(codeStream);
 			if (!blockExit) {
@@ -99,8 +102,8 @@
 				codeStream.goto_(endLabel);
 			}
 			// generate the body of the exception handler
-			anyExceptionHandler.placeEnd();
-			anyExceptionHandler.place();
+			this.exitAnyExceptionHandler();
+			this.placeAllAnyExceptionHandlers();
 			codeStream.incrStackSize(1);
 			codeStream.load(synchroVariable);
 			codeStream.monitorexit();
@@ -115,6 +118,17 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement#generateSubRoutineInvocation(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.codegen.CodeStream)
+	 */
+	public void generateSubRoutineInvocation(
+			BlockScope currentScope,
+			CodeStream codeStream) {
+
+		codeStream.load(this.synchroVariable);
+		codeStream.monitorexit();
+	}
+
 	public void resolve(BlockScope upperScope) {
 
 		// special scope for secret locals optimization.
@@ -148,16 +162,17 @@
 		block.resolveUsing(scope);
 	}
 
-	public String toString(int tab) {
+	public StringBuffer printStatement(int indent, StringBuffer output) {
 
-		String s = tabString(tab);
-		s = s + "synchronized (" + expression.toStringExpression() + ")";  //$NON-NLS-1$ //$NON-NLS-2$
-		s = s + "\n" + block.toString(tab + 1); //$NON-NLS-1$
-		return s;
+		printIndent(indent, output);
+		output.append("synchronized ("); //$NON-NLS-1$
+		expression.printExpression(0, output).append(')');
+		output.append('\n');
+		return block.printStatement(indent + 1, output); 
 	}
 
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
index ea71f99..b01ff1d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
@@ -97,21 +97,22 @@
 		return true ;
 	}
 
+	public StringBuffer printExpression(int indent, StringBuffer output){
+	
+		if (this.isImplicitThis()) return output;
+		return output.append("this"); //$NON-NLS-1$
+	}
+
 	public TypeBinding resolveType(BlockScope scope) {
 	
 		constant = NotAConstant;
-		if (!this.isImplicitThis() && !checkAccess(scope.methodScope()))
+		if (!this.isImplicitThis() &&!checkAccess(scope.methodScope())) {
 			return null;
+		}
 		return this.resolvedType = scope.enclosingSourceType();
 	}
 
-	public String toStringExpression(){
-	
-		if (this.isImplicitThis()) return "" ; //$NON-NLS-1$
-		return "this"; //$NON-NLS-1$
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+	public void traverse(ASTVisitor visitor, BlockScope blockScope) {
 
 		visitor.visit(this, blockScope);
 		visitor.endVisit(this, blockScope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
index d938232..c530c6c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
@@ -10,11 +10,11 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 
@@ -52,26 +52,26 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+
+		printIndent(indent, output).append("throw "); //$NON-NLS-1$
+		exception.printExpression(0, output);
+		return output.append(';');
+	}
+
 	public void resolve(BlockScope scope) {
 		
 		exceptionType = exception.resolveTypeExpecting(scope, scope.getJavaLangThrowable());
 		
 		if (exceptionType == NullBinding
-				&& scope.environment().options.complianceLevel <= CompilerOptions.JDK1_3){
+				&& scope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3){
 			// if compliant with 1.4, this problem will not be reported
 			scope.problemReporter().cannotThrowNull(this);
 	 	}
 		exception.implicitWidening(exceptionType, exceptionType);
 	}
 
-	public String toString(int tab) {
-		String s = tabString(tab);
-		s = s + "throw "; //$NON-NLS-1$
-		s = s + exception.toStringExpression();
-		return s;
-	}
-
-	public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+	public void traverse(ASTVisitor visitor, BlockScope blockScope) {
 		if (visitor.visit(this, blockScope))
 			exception.traverse(visitor, blockScope);
 		visitor.endVisit(this, blockScope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java
index 9960bac..ff09188 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 import org.eclipse.jdt.internal.compiler.codegen.Label;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
@@ -63,7 +63,7 @@
 public char[] source() {
 	return source;
 }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+public void traverse(ASTVisitor visitor, BlockScope scope) {
 	visitor.visit(this, scope);
 	visitor.endVisit(this, scope);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
index ed49960..e77a969 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
@@ -10,12 +10,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
-public class TryStatement extends Statement {
+public class TryStatement extends SubRoutineStatement {
 	
 	public Block tryBlock;
 	public Block[] catchBlocks;
@@ -23,7 +24,7 @@
 	public Block finallyBlock;
 	BlockScope scope;
 
-	public boolean subRoutineCannotReturn = true;
+	private boolean isSubRoutineEscaping = false;
 	public UnconditionalFlowInfo subRoutineInits;
 	
 	// should rename into subRoutineComplete to be set to false by default
@@ -64,7 +65,7 @@
 		if (anyExceptionVariable != null) {
 			anyExceptionVariable.useFlag = LocalVariableBinding.USED;
 		}
-		if (returnAddressVariable != null) {
+		if (returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused
 			returnAddressVariable.useFlag = LocalVariableBinding.USED;
 		}
 		InsideSubRoutineFlowContext insideSubContext;
@@ -85,8 +86,9 @@
 						finallyContext = new FinallyFlowContext(flowContext, finallyBlock),
 						flowInfo.copy())
 					.unconditionalInits();
-			if (subInfo.isReachable()) {
-				subRoutineCannotReturn = false;
+			if (subInfo == FlowInfo.DEAD_END) {
+				isSubRoutineEscaping = true;
+				scope.problemReporter().finallyMustCompleteNormally(finallyBlock);
 			}
 			this.subRoutineInits = subInfo;
 		}
@@ -100,7 +102,7 @@
 				flowInfo.unconditionalInits());
 
 		FlowInfo tryInfo;
-		if (tryBlock.statements == null) {
+		if (tryBlock.isEmptyBlock()) {
 			tryInfo = flowInfo;
 			tryBlockExit = false;
 		} else {
@@ -109,7 +111,7 @@
 		}
 
 		// check unreachable catch blocks
-		handlingContext.complainIfUnusedExceptionHandlers(catchBlocks, scope, this);
+		handlingContext.complainIfUnusedExceptionHandlers(scope, this);
 
 		// process the catch blocks - computing the minimal exit depth amongst try/catch
 		if (catchArguments != null) {
@@ -135,7 +137,7 @@
 				"(uncheckedExceptionTypes notNil and: [uncheckedExceptionTypes at: index])
 				ifTrue: [catchInits addPotentialInitializationsFrom: tryInits]."
 				*/
-				// TODO: should only tag as unreachable if the catchblock cannot be reached
+				// TODO (philippe) should only tag as unreachable if the catchblock cannot be reached?
 				//??? if (!handlingContext.initsOnException(caughtExceptionTypes[i]).isReachable()){
 				if (tryBlock.statements == null) {
 					catchInfo.setReachMode(FlowInfo.UNREACHABLE);
@@ -175,157 +177,140 @@
 		}
 	}
 
-	public boolean cannotReturn() {
+	public boolean isSubRoutineEscaping() {
 
-		return subRoutineCannotReturn;
+		return isSubRoutineEscaping;
 	}
 
 	/**
-	 * Try statement code generation
-	 *
+	 * Try statement code generation with or without jsr bytecode use
+	 *	post 1.5 target level, cannot use jsr bytecode, must instead inline finally block
+	 * returnAddress is only allocated if jsr is allowed
 	 */
 	public void generateCode(BlockScope currentScope, CodeStream codeStream) {
 
 		if ((bits & IsReachableMASK) == 0) {
 			return;
 		}
-		if (tryBlock.isEmptyBlock()) {
-			if (subRoutineStartLabel != null) {
-				// since not passing the finallyScope, the block generation will exitUserScope(finallyScope)
-				finallyBlock.generateCode(scope, codeStream);
-			}
-			// May loose some local variable initializations : affecting the local variable attributes
-			if (mergedInitStateIndex != -1) {
-				codeStream.removeNotDefinitelyAssignedVariables(
-					currentScope,
-					mergedInitStateIndex);
-			}
-			// no local bytecode produced so no need for position remembering
-			return;
-		}
 		int pc = codeStream.position;
-		Label endLabel = new Label(codeStream);
-		boolean requiresNaturalJsr = false;
-
+		final int NO_FINALLY = 0;									// no finally block
+		final int FINALLY_SUBROUTINE = 1; 					// finally is generated as a subroutine (using jsr/ret bytecodes)
+		final int FINALLY_DOES_NOT_COMPLETE = 2;	// non returning finally is optimized with only one instance of finally block
+		final int FINALLY_MUST_BE_INLINED = 3;			// finally block must be inlined since cannot use jsr/ret bytecodes >1.5
+		int finallyMode;
+		if (subRoutineStartLabel == null) { 
+			finallyMode = NO_FINALLY;
+		} else {
+			if (this.isSubRoutineEscaping) {
+				finallyMode = FINALLY_DOES_NOT_COMPLETE;
+			} else if (scope.environment().options.targetJDK < ClassFileConstants.JDK1_5) {
+				finallyMode = FINALLY_SUBROUTINE;
+			} else {
+				finallyMode = FINALLY_MUST_BE_INLINED;
+			}
+		}
+		boolean requiresNaturalExit = false;
 		// preparing exception labels
 		int maxCatches;
 		ExceptionLabel[] exceptionLabels =
 			new ExceptionLabel[maxCatches =
 				catchArguments == null ? 0 : catchArguments.length];
 		for (int i = 0; i < maxCatches; i++) {
-			boolean preserveCurrentHandler =
-				(preserveExceptionHandler[i
-					/ ExceptionHandlingFlowContext.BitCacheSize]
-						& (1 << (i % ExceptionHandlingFlowContext.BitCacheSize)))
-					!= 0;
-			if (preserveCurrentHandler) {
-				exceptionLabels[i] =
-					new ExceptionLabel(
-						codeStream,
-						(ReferenceBinding) catchArguments[i].binding.type);
-			}
+			exceptionLabels[i] = new ExceptionLabel(codeStream, catchArguments[i].binding.type);
 		}
-		ExceptionLabel anyExceptionLabel = null;
 		if (subRoutineStartLabel != null) {
 			subRoutineStartLabel.codeStream = codeStream;
-			anyExceptionLabel = new ExceptionLabel(codeStream, null);
+			this.enterAnyExceptionHandler(codeStream);
 		}
 		// generate the try block
 		tryBlock.generateCode(scope, codeStream);
 		boolean tryBlockHasSomeCode = codeStream.position != pc;
 		// flag telling if some bytecodes were issued inside the try block
 
-		// natural exit: only if necessary
-		boolean nonReturningSubRoutine =
-			(subRoutineStartLabel != null) && subRoutineCannotReturn;
-		if ((!tryBlockExit) && tryBlockHasSomeCode) {
-			int position = codeStream.position;
-			if (nonReturningSubRoutine) {
-				codeStream.goto_(subRoutineStartLabel);
-			} else {
-				requiresNaturalJsr = true;
-				codeStream.goto_(endLabel);
-			}
-			codeStream.updateLastRecordedEndPC(position);
-			//goto is tagged as part of the try block
-		}
 		// place end positions of user-defined exception labels
 		if (tryBlockHasSomeCode) {
-			for (int i = 0; i < maxCatches; i++) {
-				boolean preserveCurrentHandler =
-					(preserveExceptionHandler[i	/ ExceptionHandlingFlowContext.BitCacheSize]
-							& (1 << (i % ExceptionHandlingFlowContext.BitCacheSize)))
-						!= 0;
-				if (preserveCurrentHandler) {
-					exceptionLabels[i].placeEnd();
+			// natural exit may require subroutine invocation (if finally != null)
+			Label naturalExitLabel = new Label(codeStream);
+			if (!tryBlockExit) {
+				int position = codeStream.position;
+				switch(finallyMode) {
+					case FINALLY_SUBROUTINE :
+					case FINALLY_MUST_BE_INLINED :
+						requiresNaturalExit = true;
+						// fall through
+					case NO_FINALLY :
+						codeStream.goto_(naturalExitLabel);
+						break;
+					case FINALLY_DOES_NOT_COMPLETE :
+						codeStream.goto_(subRoutineStartLabel);
+						break;
 				}
+				codeStream.updateLastRecordedEndPC(position);
+				//goto is tagged as part of the try block
+			}
+			for (int i = 0; i < maxCatches; i++) {
+				exceptionLabels[i].placeEnd();
 			}
 			/* generate sequence of handler, all starting by storing the TOS (exception
 			thrown) into their own catch variables, the one specified in the source
 			that must denote the handled exception.
 			*/
 			if (catchArguments == null) {
-				if (anyExceptionLabel != null) {
-					anyExceptionLabel.placeEnd();
-				}
+				this.exitAnyExceptionHandler();
 			} else {
 				for (int i = 0; i < maxCatches; i++) {
-					boolean preserveCurrentHandler =
-						(preserveExceptionHandler[i / ExceptionHandlingFlowContext.BitCacheSize]
-								& (1 << (i % ExceptionHandlingFlowContext.BitCacheSize)))
-							!= 0;
-					if (preserveCurrentHandler) {
-						// May loose some local variable initializations : affecting the local variable attributes
-						if (preTryInitStateIndex != -1) {
-							codeStream.removeNotDefinitelyAssignedVariables(
-								currentScope,
-								preTryInitStateIndex);
-						}
-						exceptionLabels[i].place();
-						codeStream.incrStackSize(1);
-						// optimizing the case where the exception variable is not actually used
-						LocalVariableBinding catchVar;
-						int varPC = codeStream.position;
-						if ((catchVar = catchArguments[i].binding).resolvedPosition != -1) {
-							codeStream.store(catchVar, false);
-							catchVar.recordInitializationStartPC(codeStream.position);
-							codeStream.addVisibleLocalVariable(catchVar);
-						} else {
-							codeStream.pop();
-						}
-						codeStream.recordPositionsFrom(varPC, catchArguments[i].sourceStart);
-						// Keep track of the pcs at diverging point for computing the local attribute
-						// since not passing the catchScope, the block generation will exitUserScope(catchScope)
-						catchBlocks[i].generateCode(scope, codeStream);
+					// May loose some local variable initializations : affecting the local variable attributes
+					if (preTryInitStateIndex != -1) {
+						codeStream.removeNotDefinitelyAssignedVariables(
+							currentScope,
+							preTryInitStateIndex);
 					}
-					if (i == maxCatches - 1) {
-						if (anyExceptionLabel != null) {
-							anyExceptionLabel.placeEnd();
-						}
-						if (subRoutineStartLabel != null) {
-							if (!catchExits[i] && preserveCurrentHandler) {
-								requiresNaturalJsr = true;
-								codeStream.goto_(endLabel);
-							}
-						}
+					exceptionLabels[i].place();
+					codeStream.incrStackSize(1);
+					// optimizing the case where the exception variable is not actually used
+					LocalVariableBinding catchVar;
+					int varPC = codeStream.position;
+					if ((catchVar = catchArguments[i].binding).resolvedPosition != -1) {
+						codeStream.store(catchVar, false);
+						catchVar.recordInitializationStartPC(codeStream.position);
+						codeStream.addVisibleLocalVariable(catchVar);
 					} else {
-						if (!catchExits[i] && preserveCurrentHandler) {
-							if (nonReturningSubRoutine) {
+						codeStream.pop();
+					}
+					codeStream.recordPositionsFrom(varPC, catchArguments[i].sourceStart);
+					// Keep track of the pcs at diverging point for computing the local attribute
+					// since not passing the catchScope, the block generation will exitUserScope(catchScope)
+					catchBlocks[i].generateCode(scope, codeStream);
+
+					if (i == maxCatches - 1) {
+						this.exitAnyExceptionHandler();
+					}
+					if (!catchExits[i]) {
+						switch(finallyMode) {
+							case FINALLY_SUBROUTINE :
+							case FINALLY_MUST_BE_INLINED :
+								requiresNaturalExit = true;
+								// fall through
+							case NO_FINALLY :
+								codeStream.goto_(naturalExitLabel);
+								break;
+							case FINALLY_DOES_NOT_COMPLETE :
 								codeStream.goto_(subRoutineStartLabel);
-							} else {
-								requiresNaturalJsr = true;
-								codeStream.goto_(endLabel);
-							}
+								break;
 						}
 					}
 				}
 			}
+			// extra handler for trailing natural exit (will be fixed up later on when natural exit is generated below)
+			ExceptionLabel naturalExitExceptionHandler = 
+				finallyMode == FINALLY_SUBROUTINE && requiresNaturalExit ? this.enterAnyExceptionHandler(codeStream) : null;
+						
 			// addition of a special handler so as to ensure that any uncaught exception (or exception thrown
 			// inside catch blocks) will run the finally block
 			int finallySequenceStartPC = codeStream.position;
 			if (subRoutineStartLabel != null) {
 				// the additional handler is doing: jsr finallyBlock and rethrow TOS-exception
-				anyExceptionLabel.place();
+				this.placeAllAnyExceptionHandlers();
 
 				if (preTryInitStateIndex != -1) {
 					// reset initialization state, as for a normal catch block
@@ -335,46 +320,78 @@
 				}
 
 				codeStream.incrStackSize(1);
-				if (nonReturningSubRoutine) {
-					codeStream.pop();
-					// "if subroutine cannot return, no need to jsr/jump to subroutine since it will be entered in sequence
-				} else {
-					codeStream.store(anyExceptionVariable, false);
-					codeStream.jsr(subRoutineStartLabel);
-					codeStream.load(anyExceptionVariable);
-					codeStream.athrow();
+				switch(finallyMode) {
+					
+					case FINALLY_SUBROUTINE :
+						codeStream.store(anyExceptionVariable, false);
+						codeStream.jsr(subRoutineStartLabel);
+						codeStream.load(anyExceptionVariable);
+						codeStream.athrow();
+						subRoutineStartLabel.place();
+						codeStream.incrStackSize(1);
+						codeStream.store(returnAddressVariable, false);
+						codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+						finallyBlock.generateCode(scope, codeStream);
+						int position = codeStream.position;
+						codeStream.ret(returnAddressVariable.resolvedPosition);
+						codeStream.updateLastRecordedEndPC(position);
+						codeStream.recordPositionsFrom(
+							position,
+							finallyBlock.sourceEnd);
+						// the ret bytecode is part of the subroutine
+						break;
+						
+					case FINALLY_MUST_BE_INLINED :
+						codeStream.store(anyExceptionVariable, false);
+						this.finallyBlock.generateCode(currentScope, codeStream);
+						codeStream.load(anyExceptionVariable);
+						codeStream.athrow();
+						subRoutineStartLabel.place();
+						codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+						break;
+						
+					case FINALLY_DOES_NOT_COMPLETE :
+						codeStream.pop();
+						subRoutineStartLabel.place();
+						codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+						finallyBlock.generateCode(scope, codeStream);
+						break;
 				}
-			}
-			// end of catch sequence, place label that will correspond to the finally block beginning, or end of statement
-			endLabel.place();
-			if (subRoutineStartLabel != null) {
-				if (nonReturningSubRoutine) {
-					requiresNaturalJsr = false;
+				// will naturally fall into subsequent code after subroutine invocation
+				naturalExitLabel.place();
+				if (requiresNaturalExit) {
+					switch(finallyMode) {
+
+						case FINALLY_SUBROUTINE :
+							int position = codeStream.position;					
+							// fix up natural exit handler
+							naturalExitExceptionHandler.placeStart();
+							codeStream.jsr(subRoutineStartLabel);
+							naturalExitExceptionHandler.placeEnd();
+							codeStream.recordPositionsFrom(
+								position,
+								finallyBlock.sourceStart);					
+							break;
+						
+						case FINALLY_MUST_BE_INLINED :
+							// May loose some local variable initializations : affecting the local variable attributes
+							// needed since any exception handler got inlined subroutine
+							if (preTryInitStateIndex != -1) {
+								codeStream.removeNotDefinitelyAssignedVariables(
+									currentScope,
+									preTryInitStateIndex);
+							}
+							// entire sequence for finally is associated to finally block
+							finallyBlock.generateCode(scope, codeStream);
+							break;
+						
+						case FINALLY_DOES_NOT_COMPLETE :
+							break;
+					}
 				}
-				Label veryEndLabel = new Label(codeStream);
-				if (requiresNaturalJsr) {
-					codeStream.jsr(subRoutineStartLabel);
-					codeStream.goto_(veryEndLabel);
-				}
-				subRoutineStartLabel.place();
-				if (!nonReturningSubRoutine) {
-					codeStream.incrStackSize(1);
-					codeStream.store(returnAddressVariable, false);
-				}
-				codeStream.recordPositionsFrom(
-					finallySequenceStartPC,
-					finallyBlock.sourceStart);
-				// entire sequence for finally is associated to finally block
-				finallyBlock.generateCode(scope, codeStream);
-				if (!nonReturningSubRoutine) {
-					int position = codeStream.position;
-					codeStream.ret(returnAddressVariable.resolvedPosition);
-					codeStream.updateLastRecordedEndPC(position);
-					// the ret bytecode is part of the subroutine
-				}
-				if (requiresNaturalJsr) {
-					veryEndLabel.place();
-				}
+			} else {
+				// no subroutine, simply position end label (natural exit == end)
+				naturalExitLabel.place();
 			}
 		} else {
 			// try block had no effect, only generate the body of the finally block if any
@@ -392,7 +409,50 @@
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement#generateSubRoutineInvocation(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.codegen.CodeStream)
+	 */
+	public void generateSubRoutineInvocation(
+			BlockScope currentScope,
+			CodeStream codeStream) {
+	
+		if (this.isSubRoutineEscaping) {
+				codeStream.goto_(this.subRoutineStartLabel);
+		} else {
+			if (currentScope.environment().options.targetJDK < ClassFileConstants.JDK1_5) {
+				// classic subroutine invocation, distinguish case of non-returning subroutine
+				codeStream.jsr(this.subRoutineStartLabel);
+			} else {
+				// cannot use jsr bytecode, then simply inline the subroutine
+				this.finallyBlock.generateCode(currentScope, codeStream);
+			}
+		}
+	}
+
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+		printIndent(indent, output).append("try \n"); //$NON-NLS-1$
+		tryBlock.printStatement(indent + 1, output); //$NON-NLS-1$
+
+		//catches
+		if (catchBlocks != null)
+			for (int i = 0; i < catchBlocks.length; i++) {
+					output.append('\n');
+					printIndent(indent, output).append("catch ("); //$NON-NLS-1$
+					catchArguments[i].print(0, output).append(") "); //$NON-NLS-1$
+					catchBlocks[i].printStatement(indent + 1, output);
+			}
+		//finally
+		if (finallyBlock != null) {
+			output.append('\n');
+			printIndent(indent, output).append("finally\n"); //$NON-NLS-1$
+			finallyBlock.printStatement(indent + 1, output);
+		}
+
+		return output;
+	}
+	
 	public void resetStateForCodeGeneration() {
+		super.resetStateForCodeGeneration();
 		if (this.subRoutineStartLabel != null) {
 			this.subRoutineStartLabel.resetStateForCodeGeneration();
 		}
@@ -406,47 +466,53 @@
 		BlockScope tryScope = new BlockScope(scope);
 		BlockScope finallyScope = null;
 		
-		if (finallyBlock != null
-			&& finallyBlock.statements != null) {
-
-			finallyScope = new BlockScope(scope, false); // don't add it yet to parent scope
-
-			// provision for returning and forcing the finally block to run
-			MethodScope methodScope = scope.methodScope();
-
-			// the type does not matter as long as it is not a base type
-			this.returnAddressVariable =
-				new LocalVariableBinding(SecretReturnName, upperScope.getJavaLangObject(), AccDefault, false);
-			finallyScope.addLocalVariable(returnAddressVariable);
-			this.returnAddressVariable.constant = NotAConstant; // not inlinable
-			this.subRoutineStartLabel = new Label();
-
-			this.anyExceptionVariable =
-				new LocalVariableBinding(SecretAnyHandlerName, scope.getJavaLangThrowable(), AccDefault, false);
-			finallyScope.addLocalVariable(this.anyExceptionVariable);
-			this.anyExceptionVariable.constant = NotAConstant; // not inlinable
-
-			if (!methodScope.isInsideInitializer()) {
-				MethodBinding methodBinding =
-					((AbstractMethodDeclaration) methodScope.referenceContext).binding;
-				if (methodBinding != null) {
-					TypeBinding methodReturnType = methodBinding.returnType;
-					if (methodReturnType.id != T_void) {
-						this.secretReturnValue =
-							new LocalVariableBinding(
-								SecretLocalDeclarationName,
-								methodReturnType,
-								AccDefault,
-								false);
-						finallyScope.addLocalVariable(this.secretReturnValue);
-						this.secretReturnValue.constant = NotAConstant; // not inlinable
+		if (finallyBlock != null) {
+			if (finallyBlock.isEmptyBlock()) {
+				if ((finallyBlock.bits & UndocumentedEmptyBlockMASK) != 0) {
+					scope.problemReporter().undocumentedEmptyBlock(finallyBlock.sourceStart, finallyBlock.sourceEnd);
+				}
+			} else {
+				finallyScope = new BlockScope(scope, false); // don't add it yet to parent scope
+	
+				// provision for returning and forcing the finally block to run
+				MethodScope methodScope = scope.methodScope();
+	
+				// the type does not matter as long as it is not a base type
+				if (upperScope.environment().options.targetJDK < ClassFileConstants.JDK1_5) {
+					this.returnAddressVariable =
+						new LocalVariableBinding(SecretReturnName, upperScope.getJavaLangObject(), AccDefault, false);
+					finallyScope.addLocalVariable(returnAddressVariable);
+					this.returnAddressVariable.constant = NotAConstant; // not inlinable
+				}
+				this.subRoutineStartLabel = new Label();
+	
+				this.anyExceptionVariable =
+					new LocalVariableBinding(SecretAnyHandlerName, scope.getJavaLangThrowable(), AccDefault, false);
+				finallyScope.addLocalVariable(this.anyExceptionVariable);
+				this.anyExceptionVariable.constant = NotAConstant; // not inlinable
+	
+				if (!methodScope.isInsideInitializer()) {
+					MethodBinding methodBinding =
+						((AbstractMethodDeclaration) methodScope.referenceContext).binding;
+					if (methodBinding != null) {
+						TypeBinding methodReturnType = methodBinding.returnType;
+						if (methodReturnType.id != T_void) {
+							this.secretReturnValue =
+								new LocalVariableBinding(
+									SecretLocalDeclarationName,
+									methodReturnType,
+									AccDefault,
+									false);
+							finallyScope.addLocalVariable(this.secretReturnValue);
+							this.secretReturnValue.constant = NotAConstant; // not inlinable
+						}
 					}
 				}
+				finallyBlock.resolveUsing(finallyScope);
+				// force the finally scope to have variable positions shifted after its try scope and catch ones
+				finallyScope.shiftScopes = new BlockScope[catchArguments == null ? 1 : catchArguments.length+1];
+				finallyScope.shiftScopes[0] = tryScope;
 			}
-			finallyBlock.resolveUsing(finallyScope);
-			// force the finally scope to have variable positions shifted after its try scope and catch ones
-			finallyScope.shiftScopes = new BlockScope[catchArguments == null ? 1 : catchArguments.length+1];
-			finallyScope.shiftScopes[0] = tryScope;
 		}
 		this.tryBlock.resolveUsing(tryScope);
 
@@ -472,8 +538,7 @@
 				caughtExceptionTypes[i] = (ReferenceBinding) argumentTypes[i];
 				for (int j = 0; j < i; j++) {
 					if (caughtExceptionTypes[i].isCompatibleWith(argumentTypes[j])) {
-						scope.problemReporter().wrongSequenceOfExceptionTypesError(this, i, j);
-						// cannot return - since may still proceed if unreachable code is ignored (21203)
+						scope.problemReporter().wrongSequenceOfExceptionTypesError(this, caughtExceptionTypes[i], i, argumentTypes[j]);
 					}
 				}
 			}
@@ -489,35 +554,8 @@
 		}
 	}
 
-	public String toString(int tab) {
-		String s = tabString(tab);
-		//try
-		s = s + "try "; //$NON-NLS-1$
-		if (tryBlock == Block.None)
-			s = s + "{}"; //$NON-NLS-1$
-		else
-			s = s + "\n" + tryBlock.toString(tab + 1); //$NON-NLS-1$
-
-		//catches
-		if (catchBlocks != null)
-			for (int i = 0; i < catchBlocks.length; i++)
-					s = s + "\n" + tabString(tab) + "catch (" //$NON-NLS-2$ //$NON-NLS-1$
-						+catchArguments[i].toString(0) + ") " //$NON-NLS-1$
-						+catchBlocks[i].toString(tab + 1);
-		//finally
-		if (finallyBlock != null) {
-			if (finallyBlock == Block.None)
-				s = s + "\n" + tabString(tab) + "finally {}"; //$NON-NLS-2$ //$NON-NLS-1$
-			else
-					s = s + "\n" + tabString(tab) + "finally\n" + //$NON-NLS-2$ //$NON-NLS-1$
-			finallyBlock.toString(tab + 1);
-		}
-
-		return s;
-	}
-
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index 198a8c5..9f639ab 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -11,7 +11,7 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
@@ -24,14 +24,16 @@
 	extends Statement
 	implements ProblemSeverities, ReferenceContext {
 
-	public int modifiers;
+	public static final char[] ANONYMOUS_EMPTY_NAME = new char[] {};
+
+	public int modifiers = AccDefault;
 	public int modifiersSourceStart;
 	public char[] name;
 	public TypeReference superclass;
 	public TypeReference[] superInterfaces;
 	public FieldDeclaration[] fields;
 	public AbstractMethodDeclaration[] methods;
-	public MemberTypeDeclaration[] memberTypes;
+	public TypeDeclaration[] memberTypes;
 	public SourceTypeBinding binding;
 	public ClassScope scope;
 	public MethodScope initializerScope;
@@ -45,7 +47,11 @@
 	protected boolean hasBeenGenerated = false;
 	public CompilationResult compilationResult;
 	private MethodDeclaration[] missingAbstractMethods;
+	public Javadoc javadoc;	
 
+	public QualifiedAllocationExpression allocation; // for anonymous only
+	public TypeDeclaration enclosingType; // for member types only
+	
 	public TypeDeclaration(CompilationResult compilationResult){
 		this.compilationResult = compilationResult;
 	}
@@ -55,22 +61,15 @@
 	 */
 	public void abort(int abortLevel) {
 
-		if (scope == null) {
-			throw new AbortCompilation(); // cannot do better
-		}
-
-		CompilationResult compilationResult =
-			scope.referenceCompilationUnit().compilationResult;
-
 		switch (abortLevel) {
 			case AbortCompilation :
-				throw new AbortCompilation(compilationResult);
+				throw new AbortCompilation(this.compilationResult);
 			case AbortCompilationUnit :
-				throw new AbortCompilationUnit(compilationResult);
+				throw new AbortCompilationUnit(this.compilationResult);
 			case AbortMethod :
-				throw new AbortMethod(compilationResult);
+				throw new AbortMethod(this.compilationResult);
 			default :
-				throw new AbortType(compilationResult);
+				throw new AbortType(this.compilationResult);
 		}
 	}
 	/**
@@ -88,219 +87,30 @@
 		//see comment on needClassInitMethod
 		if (needClassInitMethod()) {
 			int length;
-			AbstractMethodDeclaration[] methods;
-			if ((methods = this.methods) == null) {
+			AbstractMethodDeclaration[] methodDeclarations;
+			if ((methodDeclarations = this.methods) == null) {
 				length = 0;
-				methods = new AbstractMethodDeclaration[1];
+				methodDeclarations = new AbstractMethodDeclaration[1];
 			} else {
-				length = methods.length;
+				length = methodDeclarations.length;
 				System.arraycopy(
-					methods,
+					methodDeclarations,
 					0,
-					(methods = new AbstractMethodDeclaration[length + 1]),
+					(methodDeclarations = new AbstractMethodDeclaration[length + 1]),
 					1,
 					length);
 			}
 			Clinit clinit = new Clinit(this.compilationResult);
-			methods[0] = clinit;
+			methodDeclarations[0] = clinit;
 			// clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
 			clinit.declarationSourceStart = clinit.sourceStart = sourceStart;
 			clinit.declarationSourceEnd = clinit.sourceEnd = sourceEnd;
 			clinit.bodyEnd = sourceEnd;
-			this.methods = methods;
-		}
-	}
-
-	/**
-	 *	Flow analysis for a local innertype
-	 *
-	 */
-	public FlowInfo analyseCode(
-		BlockScope currentScope,
-		FlowContext flowContext,
-		FlowInfo flowInfo) {
-
-		if (ignoreFurtherInvestigation)
-			return flowInfo;
-		try {
-			bits |= IsReachableMASK;
-			LocalTypeBinding localType = (LocalTypeBinding) binding;
-			
-			localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
-			manageEnclosingInstanceAccessIfNecessary(currentScope);
-			
-			updateMaxFieldCount(); // propagate down the max field count
-			internalAnalyseCode(flowContext, flowInfo); 
-		} catch (AbortType e) {
-			this.ignoreFurtherInvestigation = true;
-		}
-		return flowInfo;
-	}
-
-	/**
-	 *	Flow analysis for a member innertype
-	 *
-	 */
-	public void analyseCode(ClassScope enclosingClassScope) {
-
-		if (ignoreFurtherInvestigation)
-			return;
-		try {
-			// propagate down the max field count
-			updateMaxFieldCount();
-			internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
-		} catch (AbortType e) {
-			this.ignoreFurtherInvestigation = true;
-		}
-	}
-
-	/**
-	 *	Flow analysis for a local member innertype
-	 *
-	 */
-	public void analyseCode(
-		ClassScope currentScope,
-		FlowContext flowContext,
-		FlowInfo flowInfo) {
-
-		if (ignoreFurtherInvestigation)
-			return;
-		try {
-			bits |= IsReachableMASK;
-			LocalTypeBinding localType = (LocalTypeBinding) binding;
-
-			localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
-			manageEnclosingInstanceAccessIfNecessary(currentScope);
-			
-			updateMaxFieldCount(); // propagate down the max field count
-			internalAnalyseCode(flowContext, flowInfo);
-		} catch (AbortType e) {
-			this.ignoreFurtherInvestigation = true;
-		}
-	}
-
-	/**
-	 *	Flow analysis for a package member type
-	 *
-	 */
-	public void analyseCode(CompilationUnitScope unitScope) {
-
-		if (ignoreFurtherInvestigation)
-			return;
-		try {
-			internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
-		} catch (AbortType e) {
-			this.ignoreFurtherInvestigation = true;
+			this.methods = methodDeclarations;
 		}
 	}
 
 	/*
-	 * Check for constructor vs. method with no return type.
-	 * Answers true if at least one constructor is defined
-	 */
-	public boolean checkConstructors(Parser parser) {
-
-		//if a constructor has not the name of the type,
-		//convert it into a method with 'null' as its return type
-		boolean hasConstructor = false;
-		if (methods != null) {
-			for (int i = methods.length; --i >= 0;) {
-				AbstractMethodDeclaration am;
-				if ((am = methods[i]).isConstructor()) {
-					if (!CharOperation.equals(am.selector, name)) {
-						// the constructor was in fact a method with no return type
-						// unless an explicit constructor call was supplied
-						ConstructorDeclaration c = (ConstructorDeclaration) am;
-						if ((c.constructorCall == null)
-							|| (c.constructorCall.isImplicitSuper())) { //changed to a method
-							MethodDeclaration m = new MethodDeclaration(this.compilationResult);
-							m.sourceStart = c.sourceStart;
-							m.sourceEnd = c.sourceEnd;
-							m.bodyStart = c.bodyStart;
-							m.bodyEnd = c.bodyEnd;
-							m.declarationSourceEnd = c.declarationSourceEnd;
-							m.declarationSourceStart = c.declarationSourceStart;
-							m.selector = c.selector;
-							m.statements = c.statements;
-							m.modifiers = c.modifiers;
-							m.arguments = c.arguments;
-							m.thrownExceptions = c.thrownExceptions;
-							m.explicitDeclarations = c.explicitDeclarations;
-							m.returnType = null;
-							methods[i] = m;
-						}
-					} else {
-						if (this.isInterface()) {
-							// report the problem and continue the parsing
-							parser.problemReporter().interfaceCannotHaveConstructors(
-								(ConstructorDeclaration) am);
-						}
-						hasConstructor = true;
-					}
-				}
-			}
-		}
-		return hasConstructor;
-	}
-
-	public CompilationResult compilationResult() {
-
-		return this.compilationResult;
-	}
-
-	public ConstructorDeclaration createsInternalConstructor(
-		boolean needExplicitConstructorCall,
-		boolean needToInsert) {
-
-		//Add to method'set, the default constuctor that just recall the
-		//super constructor with no arguments
-		//The arguments' type will be positionned by the TC so just use
-		//the default int instead of just null (consistency purpose)
-
-		//the constructor
-		ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
-		constructor.isDefaultConstructor = true;
-		constructor.selector = name;
-		if (modifiers != AccDefault) {
-			constructor.modifiers =
-				((this instanceof MemberTypeDeclaration) && (modifiers & AccPrivate) != 0)
-					? AccDefault
-					: modifiers & AccVisibilityMASK;
-		}
-
-		//if you change this setting, please update the 
-		//SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
-		constructor.declarationSourceStart = constructor.sourceStart = sourceStart;
-		constructor.declarationSourceEnd =
-			constructor.sourceEnd = constructor.bodyEnd = sourceEnd;
-
-		//the super call inside the constructor
-		if (needExplicitConstructorCall) {
-			constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
-			constructor.constructorCall.sourceStart = sourceStart;
-			constructor.constructorCall.sourceEnd = sourceEnd;
-		}
-
-		//adding the constructor in the methods list
-		if (needToInsert) {
-			if (methods == null) {
-				methods = new AbstractMethodDeclaration[] { constructor };
-			} else {
-				AbstractMethodDeclaration[] newMethods;
-				System.arraycopy(
-					methods,
-					0,
-					newMethods = new AbstractMethodDeclaration[methods.length + 1],
-					1,
-					methods.length);
-				newMethods[0] = constructor;
-				methods = newMethods;
-			}
-		}
-		return constructor;
-	}
-
-	/**
 	 * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding.
 	 * It is used to report errors for missing abstract methods.
 	 */
@@ -366,7 +176,262 @@
 
 		return methodDeclaration;
 	}
+
+	/**
+	 *	Flow analysis for a local innertype
+	 *
+	 */
+	public FlowInfo analyseCode(
+		BlockScope currentScope,
+		FlowContext flowContext,
+		FlowInfo flowInfo) {
+
+		if (ignoreFurtherInvestigation)
+			return flowInfo;
+		try {
+			if (flowInfo.isReachable()) {
+				bits |= IsReachableMASK;
+				LocalTypeBinding localType = (LocalTypeBinding) binding;
+				localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
+			}
+			manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+			updateMaxFieldCount(); // propagate down the max field count
+			internalAnalyseCode(flowContext, flowInfo); 
+		} catch (AbortType e) {
+			this.ignoreFurtherInvestigation = true;
+		}
+		return flowInfo;
+	}
+
+	/**
+	 *	Flow analysis for a member innertype
+	 *
+	 */
+	public void analyseCode(ClassScope enclosingClassScope) {
+
+		if (ignoreFurtherInvestigation)
+			return;
+		try {
+			// propagate down the max field count
+			updateMaxFieldCount();
+			internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
+		} catch (AbortType e) {
+			this.ignoreFurtherInvestigation = true;
+		}
+	}
+
+	/**
+	 *	Flow analysis for a local member innertype
+	 *
+	 */
+	public void analyseCode(
+		ClassScope currentScope,
+		FlowContext flowContext,
+		FlowInfo flowInfo) {
+
+		if (ignoreFurtherInvestigation)
+			return;
+		try {
+			if (flowInfo.isReachable()) {
+				bits |= IsReachableMASK;
+				LocalTypeBinding localType = (LocalTypeBinding) binding;
+				localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
+			}
+			manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+			updateMaxFieldCount(); // propagate down the max field count
+			internalAnalyseCode(flowContext, flowInfo);
+		} catch (AbortType e) {
+			this.ignoreFurtherInvestigation = true;
+		}
+	}
+
+	/**
+	 *	Flow analysis for a package member type
+	 *
+	 */
+	public void analyseCode(CompilationUnitScope unitScope) {
+
+		if (ignoreFurtherInvestigation)
+			return;
+		try {
+			internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
+		} catch (AbortType e) {
+			this.ignoreFurtherInvestigation = true;
+		}
+	}
+
+	/*
+	 * Check for constructor vs. method with no return type.
+	 * Answers true if at least one constructor is defined
+	 */
+	public boolean checkConstructors(Parser parser) {
+
+		//if a constructor has not the name of the type,
+		//convert it into a method with 'null' as its return type
+		boolean hasConstructor = false;
+		if (methods != null) {
+			for (int i = methods.length; --i >= 0;) {
+				AbstractMethodDeclaration am;
+				if ((am = methods[i]).isConstructor()) {
+					if (!CharOperation.equals(am.selector, name)) {
+						// the constructor was in fact a method with no return type
+						// unless an explicit constructor call was supplied
+						ConstructorDeclaration c = (ConstructorDeclaration) am;
+						if (c.constructorCall == null || c.constructorCall.isImplicitSuper()) { //changed to a method
+							MethodDeclaration m = parser.convertToMethodDeclaration(c, this.compilationResult);
+							methods[i] = m;
+						}
+					} else {
+						if (this.isInterface()) {
+							// report the problem and continue the parsing
+							parser.problemReporter().interfaceCannotHaveConstructors(
+								(ConstructorDeclaration) am);
+						}
+						hasConstructor = true;
+					}
+				}
+			}
+		}
+		return hasConstructor;
+	}
+
+	public CompilationResult compilationResult() {
+
+		return this.compilationResult;
+	}
+
+	public ConstructorDeclaration createsInternalConstructor(
+		boolean needExplicitConstructorCall,
+		boolean needToInsert) {
+
+		//Add to method'set, the default constuctor that just recall the
+		//super constructor with no arguments
+		//The arguments' type will be positionned by the TC so just use
+		//the default int instead of just null (consistency purpose)
+
+		//the constructor
+		ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
+		constructor.isDefaultConstructor = true;
+		constructor.selector = name;
+		if (modifiers != AccDefault) {
+			constructor.modifiers =
+				(((this.bits & ASTNode.IsMemberTypeMASK) != 0) && (modifiers & AccPrivate) != 0)
+					? AccDefault
+					: modifiers & AccVisibilityMASK;
+		}
+
+		//if you change this setting, please update the 
+		//SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
+		constructor.declarationSourceStart = constructor.sourceStart = sourceStart;
+		constructor.declarationSourceEnd =
+			constructor.sourceEnd = constructor.bodyEnd = sourceEnd;
+
+		//the super call inside the constructor
+		if (needExplicitConstructorCall) {
+			constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
+			constructor.constructorCall.sourceStart = sourceStart;
+			constructor.constructorCall.sourceEnd = sourceEnd;
+		}
+
+		//adding the constructor in the methods list
+		if (needToInsert) {
+			if (methods == null) {
+				methods = new AbstractMethodDeclaration[] { constructor };
+			} else {
+				AbstractMethodDeclaration[] newMethods;
+				System.arraycopy(
+					methods,
+					0,
+					newMethods = new AbstractMethodDeclaration[methods.length + 1],
+					1,
+					methods.length);
+				newMethods[0] = constructor;
+				methods = newMethods;
+			}
+		}
+		return constructor;
+	}
 	
+	// anonymous type constructor creation
+	public MethodBinding createsInternalConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
+
+		//Add to method'set, the default constuctor that just recall the
+		//super constructor with the same arguments
+		String baseName = "$anonymous"; //$NON-NLS-1$
+		TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
+		int argumentsLength = argumentTypes.length;
+		//the constructor
+		ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationResult);
+		cd.selector = new char[] { 'x' }; //no maining
+		cd.sourceStart = sourceStart;
+		cd.sourceEnd = sourceEnd;
+		cd.modifiers = modifiers & AccVisibilityMASK;
+		cd.isDefaultConstructor = true;
+
+		if (argumentsLength > 0) {
+			Argument[] arguments = (cd.arguments = new Argument[argumentsLength]);
+			for (int i = argumentsLength; --i >= 0;) {
+				arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, AccDefault);
+			}
+		}
+
+		//the super call inside the constructor
+		cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+		cd.constructorCall.sourceStart = sourceStart;
+		cd.constructorCall.sourceEnd = sourceEnd;
+
+		if (argumentsLength > 0) {
+			Expression[] args;
+			args = cd.constructorCall.arguments = new Expression[argumentsLength];
+			for (int i = argumentsLength; --i >= 0;) {
+				args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
+			}
+		}
+
+		//adding the constructor in the methods list
+		if (methods == null) {
+			methods = new AbstractMethodDeclaration[] { cd };
+		} else {
+			AbstractMethodDeclaration[] newMethods;
+			System.arraycopy(
+				methods,
+				0,
+				newMethods = new AbstractMethodDeclaration[methods.length + 1],
+				1,
+				methods.length);
+			newMethods[0] = cd;
+			methods = newMethods;
+		}
+
+		//============BINDING UPDATE==========================
+		cd.binding = new MethodBinding(
+				cd.modifiers, //methodDeclaration
+				argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
+				inheritedConstructorBinding.thrownExceptions, //exceptions
+				binding); //declaringClass
+				
+		cd.scope = new MethodScope(scope, cd, true);
+		cd.bindArguments();
+		cd.constructorCall.resolve(cd.scope);
+
+		if (binding.methods == null) {
+			binding.methods = new MethodBinding[] { cd.binding };
+		} else {
+			MethodBinding[] newMethods;
+			System.arraycopy(
+				binding.methods,
+				0,
+				newMethods = new MethodBinding[binding.methods.length + 1],
+				1,
+				binding.methods.length);
+			newMethods[0] = cd.binding;
+			binding.methods = newMethods;
+		}
+		//===================================================
+
+		return cd.binding;
+	}
+
 	/*
 	 * Find the matching parse node, answers null if nothing found
 	 */
@@ -514,6 +579,9 @@
 	 */
 	public void generateCode(BlockScope blockScope, CodeStream codeStream) {
 
+		if ((this.bits & IsReachableMASK) == 0) {
+			return;
+		}		
 		if (hasBeenGenerated) return;
 		int pc = codeStream.position;
 		if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
@@ -642,8 +710,9 @@
 	 * with an enclosing instance.
 	 * 15.9.2
 	 */
-	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
+	public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
+		if (!flowInfo.isReachable()) return;
 		NestedTypeBinding nestedType = (NestedTypeBinding) binding;
 		
 		MethodScope methodScope = currentScope.methodScope();
@@ -653,12 +722,12 @@
 		}
 		// add superclass enclosing instance arg for anonymous types (if necessary)
 		if (binding.isAnonymousType()) { 
-			ReferenceBinding superclass = binding.superclass;
-			if (superclass.enclosingType() != null && !superclass.isStatic()) {
-				if (!binding.superclass.isLocalType()
-						|| ((NestedTypeBinding)binding.superclass).getSyntheticField(superclass.enclosingType(), true) != null){
+			ReferenceBinding superclassBinding = binding.superclass;
+			if (superclassBinding.enclosingType() != null && !superclassBinding.isStatic()) {
+				if (!superclassBinding.isLocalType()
+						|| ((NestedTypeBinding)superclassBinding).getSyntheticField(superclassBinding.enclosingType(), true) != null){
 
-					nestedType.addSyntheticArgument(superclass.enclosingType());	
+					nestedType.addSyntheticArgument(superclassBinding.enclosingType());	
 				}
 			}
 		}
@@ -673,8 +742,9 @@
 	 * 
 	 * Local member cannot be static.
 	 */
-	public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope) {
+	public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope, FlowInfo flowInfo) {
 
+		if (!flowInfo.isReachable()) return;
 		NestedTypeBinding nestedType = (NestedTypeBinding) binding;
 		nestedType.addSyntheticArgumentAndField(binding.enclosingType());
 	}	
@@ -736,74 +806,147 @@
 		}
 	}
 
+	public StringBuffer print(int indent, StringBuffer output) {
+
+		if ((this.bits & IsAnonymousTypeMASK) == 0) {
+			printIndent(indent, output);
+			printHeader(0, output);
+		}
+		return printBody(indent, output);
+	}
+
+	public StringBuffer printBody(int indent, StringBuffer output) {
+
+		output.append(" {"); //$NON-NLS-1$
+		if (memberTypes != null) {
+			for (int i = 0; i < memberTypes.length; i++) {
+				if (memberTypes[i] != null) {
+					output.append('\n');
+					memberTypes[i].print(indent + 1, output);
+				}
+			}
+		}
+		if (fields != null) {
+			for (int fieldI = 0; fieldI < fields.length; fieldI++) {
+				if (fields[fieldI] != null) {
+					output.append('\n');
+					fields[fieldI].print(indent + 1, output);
+				}
+			}
+		}
+		if (methods != null) {
+			for (int i = 0; i < methods.length; i++) {
+				if (methods[i] != null) {
+					output.append('\n');
+					methods[i].print(indent + 1, output); 
+				}
+			}
+		}
+		output.append('\n');
+		return printIndent(indent, output).append('}');
+	}
+
+	public StringBuffer printHeader(int indent, StringBuffer output) {
+
+		printModifiers(this.modifiers, output);
+		output.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
+		output.append(name);
+		if (superclass != null) {
+			output.append(" extends ");  //$NON-NLS-1$
+			superclass.print(0, output);
+		}
+		if (superInterfaces != null && superInterfaces.length > 0) {
+			output.append(isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
+			for (int i = 0; i < superInterfaces.length; i++) {
+				if (i > 0) output.append( ", "); //$NON-NLS-1$
+				superInterfaces[i].print(0, output);
+			}
+		}
+		return output;
+	}
+
+	public StringBuffer printStatement(int tab, StringBuffer output) {
+		return print(tab, output);
+	}
+
 	public void resolve() {
 
-		if (binding == null) {
-			ignoreFurtherInvestigation = true;
+		if (this.binding == null) {
+			this.ignoreFurtherInvestigation = true;
 			return;
 		}
-
 		try {
+			if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
+				this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd+1);
+			}
 			// check superclass & interfaces
-			if (binding.superclass != null) // watch out for Object ! (and other roots)	
-				if (isTypeUseDeprecated(binding.superclass, scope))
-					scope.problemReporter().deprecatedType(binding.superclass, superclass);
-			if (superInterfaces != null)
-				for (int i = superInterfaces.length; --i >= 0;)
-					if (superInterfaces[i].resolvedType != null)
-						if (isTypeUseDeprecated(superInterfaces[i].resolvedType, scope))
-							scope.problemReporter().deprecatedType(
-								superInterfaces[i].resolvedType,
-								superInterfaces[i]);
-			maxFieldCount = 0;
-			int lastFieldID = -1;
-			if (fields != null) {
-				for (int i = 0, count = fields.length; i < count; i++) {
-					FieldDeclaration field = fields[i];
+			if (this.binding.superclass != null) // watch out for Object ! (and other roots)	
+				if (isTypeUseDeprecated(this.binding.superclass, this.scope))
+					this.scope.problemReporter().deprecatedType(this.binding.superclass, this.superclass);
+			if (this.superInterfaces != null)
+				for (int i = this.superInterfaces.length; --i >= 0;)
+					if (this.superInterfaces[i].resolvedType != null)
+						if (isTypeUseDeprecated(this.superInterfaces[i].resolvedType, this.scope))
+							this.scope.problemReporter().deprecatedType(
+								this.superInterfaces[i].resolvedType,
+								this.superInterfaces[i]);
+			this.maxFieldCount = 0;
+			int lastVisibleFieldID = -1;
+			if (this.fields != null) {
+				for (int i = 0, count = this.fields.length; i < count; i++) {
+					FieldDeclaration field = this.fields[i];
 					if (field.isField()) {
 						if (field.binding == null) {
 							// still discover secondary errors
-							if (field.initialization != null) field.initialization.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
-							ignoreFurtherInvestigation = true;
+							if (field.initialization != null) field.initialization.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
+							this.ignoreFurtherInvestigation = true;
 							continue;
 						}
-						maxFieldCount++;
-						lastFieldID = field.binding.id;
+						this.maxFieldCount++;
+						lastVisibleFieldID = field.binding.id;
 					} else { // initializer
-						 ((Initializer) field).lastFieldID = lastFieldID + 1;
+						 ((Initializer) field).lastVisibleFieldID = lastVisibleFieldID + 1;
 					}
-					field.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
+					field.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
 				}
 			}
-			if (memberTypes != null) {
-				for (int i = 0, count = memberTypes.length; i < count; i++) {
-					memberTypes[i].resolve(scope);
+			if (this.memberTypes != null) {
+				for (int i = 0, count = this.memberTypes.length; i < count; i++) {
+					this.memberTypes[i].resolve(this.scope);
 				}
 			}
 			int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
-			int methodsLength = this.methods == null ? 0 : methods.length;
+			int methodsLength = this.methods == null ? 0 : this.methods.length;
 			if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) {
-				scope.problemReporter().tooManyMethods(this);
+				this.scope.problemReporter().tooManyMethods(this);
 			}
 			
-			if (methods != null) {
-				for (int i = 0, count = methods.length; i < count; i++) {
-					methods[i].resolve(scope);
+			if (this.methods != null) {
+				for (int i = 0, count = this.methods.length; i < count; i++) {
+					this.methods[i].resolve(this.scope);
 				}
 			}
+			// Resolve javadoc
+			if (this.javadoc != null) {
+				if (this.scope != null) {
+					this.javadoc.resolve(this.scope);
+				}
+			} else if (this.binding != null && !this.binding.isLocalType()) {
+				this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
+			}
+			
 		} catch (AbortType e) {
 			this.ignoreFurtherInvestigation = true;
 			return;
-		};
+		}
 	}
 
 	public void resolve(BlockScope blockScope) {
 		// local type declaration
 
 		// need to build its scope first and proceed with binding's creation
-		blockScope.addLocalType(this);
+		if ((this.bits & IsAnonymousTypeMASK) == 0) blockScope.addLocalType(this);
 
-		// and TC....
 		if (binding != null) {
 			// remember local types binding for innerclass emulation propagation
 			blockScope.referenceCompilationUnit().record((LocalTypeBinding)binding);
@@ -813,7 +956,7 @@
 			updateMaxFieldCount();
 		}
 	}
-
+	
 	public void resolve(ClassScope upperScope) {
 		// member scopes are already created
 		// request the construction of a binding if local member type
@@ -837,67 +980,13 @@
 		ignoreFurtherInvestigation = true;
 	}
 
-	public String toString(int tab) {
-
-		return tabString(tab) + toStringHeader() + toStringBody(tab);
-	}
-
-	public String toStringBody(int tab) {
-
-		String s = " {"; //$NON-NLS-1$
-		if (memberTypes != null) {
-			for (int i = 0; i < memberTypes.length; i++) {
-				if (memberTypes[i] != null) {
-					s += "\n" + memberTypes[i].toString(tab + 1); //$NON-NLS-1$
-				}
-			}
-		}
-		if (fields != null) {
-			for (int fieldI = 0; fieldI < fields.length; fieldI++) {
-				if (fields[fieldI] != null) {
-					s += "\n" + fields[fieldI].toString(tab + 1); //$NON-NLS-1$
-					if (fields[fieldI].isField())
-						s += ";"; //$NON-NLS-1$
-				}
-			}
-		}
-		if (methods != null) {
-			for (int i = 0; i < methods.length; i++) {
-				if (methods[i] != null) {
-					s += "\n" + methods[i].toString(tab + 1); //$NON-NLS-1$
-				}
-			}
-		}
-		s += "\n" + tabString(tab) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
-		return s;
-	}
-
-	public String toStringHeader() {
-
-		String s = ""; //$NON-NLS-1$
-		if (modifiers != AccDefault) {
-			s += modifiersString(modifiers);
-		}
-		s += (isInterface() ? "interface " : "class ") + new String(name);//$NON-NLS-1$ //$NON-NLS-2$
-		if (superclass != null)
-			s += " extends " + superclass.toString(0); //$NON-NLS-1$
-		if (superInterfaces != null && superInterfaces.length > 0) {
-			s += (isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
-			for (int i = 0; i < superInterfaces.length; i++) {
-				s += superInterfaces[i].toString(0);
-				if (i != superInterfaces.length - 1)
-					s += ", "; //$NON-NLS-1$
-			};
-		};
-		return s;
-	}
 
 	/**
 	 *	Iteration for a package member type
 	 *
 	 */
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		CompilationUnitScope unitScope) {
 
 		if (ignoreFurtherInvestigation)
@@ -935,10 +1024,99 @@
 			}
 			visitor.endVisit(this, unitScope);
 		} catch (AbortType e) {
+			// silent abort
 		}
 	}
 
 	/**
+	 *	Iteration for a local innertype
+	 *
+	 */
+	public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+		if (ignoreFurtherInvestigation)
+			return;
+		try {
+			if (visitor.visit(this, blockScope)) {
+				if (superclass != null)
+					superclass.traverse(visitor, scope);
+				if (superInterfaces != null) {
+					int superInterfaceLength = superInterfaces.length;
+					for (int i = 0; i < superInterfaceLength; i++)
+						superInterfaces[i].traverse(visitor, scope);
+				}
+				if (memberTypes != null) {
+					int memberTypesLength = memberTypes.length;
+					for (int i = 0; i < memberTypesLength; i++)
+						memberTypes[i].traverse(visitor, scope);
+				}
+				if (fields != null) {
+					int fieldsLength = fields.length;
+					for (int i = 0; i < fieldsLength; i++) {
+						FieldDeclaration field;
+						if ((field = fields[i]).isStatic()) {
+							// local type cannot have static fields
+						} else {
+							field.traverse(visitor, initializerScope);
+						}
+					}
+				}
+				if (methods != null) {
+					int methodsLength = methods.length;
+					for (int i = 0; i < methodsLength; i++)
+						methods[i].traverse(visitor, scope);
+				}
+			}
+			visitor.endVisit(this, blockScope);
+		} catch (AbortType e) {
+			// silent abort
+		}
+	}
+
+	/**
+	 *	Iteration for a member innertype
+	 *
+	 */
+	public void traverse(ASTVisitor visitor, ClassScope classScope) {
+		if (ignoreFurtherInvestigation)
+			return;
+		try {
+			if (visitor.visit(this, classScope)) {
+				if (superclass != null)
+					superclass.traverse(visitor, scope);
+				if (superInterfaces != null) {
+					int superInterfaceLength = superInterfaces.length;
+					for (int i = 0; i < superInterfaceLength; i++)
+						superInterfaces[i].traverse(visitor, scope);
+				}
+				if (memberTypes != null) {
+					int memberTypesLength = memberTypes.length;
+					for (int i = 0; i < memberTypesLength; i++)
+						memberTypes[i].traverse(visitor, scope);
+				}
+				if (fields != null) {
+					int fieldsLength = fields.length;
+					for (int i = 0; i < fieldsLength; i++) {
+						FieldDeclaration field;
+						if ((field = fields[i]).isStatic()) {
+							field.traverse(visitor, staticInitializerScope);
+						} else {
+							field.traverse(visitor, initializerScope);
+						}
+					}
+				}
+				if (methods != null) {
+					int methodsLength = methods.length;
+					for (int i = 0; i < methodsLength; i++)
+						methods[i].traverse(visitor, scope);
+				}
+			}
+			visitor.endVisit(this, classScope);
+		} catch (AbortType e) {
+			// silent abort
+		}
+	}	
+
+	/**
 	 * MaxFieldCount's computation is necessary so as to reserve space for
 	 * the flow info field portions. It corresponds to the maximum amount of
 	 * fields this class or one of its innertypes have.
@@ -958,5 +1136,5 @@
 		} else {
 			maxFieldCount = outerMostType.maxFieldCount; // down
 		}
-	}
+	}	
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
index 8916982..3e27b18 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -26,7 +26,9 @@
 }
 
 // allows us to trap completion & selection nodes
-public void aboutToResolve(Scope scope) {}
+public void aboutToResolve(Scope scope) {
+	// default implementation: do nothing
+}
 /*
  * Answer a base type reference (can be an array of base type).
  */
@@ -87,22 +89,48 @@
 public boolean isTypeReference() {
 	return true;
 }
-public TypeBinding resolveType(BlockScope scope) {
+public TypeBinding resolveType(BlockScope blockScope) {
 	// handle the error here
-	constant = NotAConstant;
+	this.constant = NotAConstant;
 	if (this.resolvedType != null) { // is a shared type reference which was already resolved
 		if (!this.resolvedType.isValidBinding())
 			return null; // already reported error
 	} else {
-		this.resolvedType = getTypeBinding(scope);
+		this.resolvedType = getTypeBinding(blockScope);
 		if (!this.resolvedType.isValidBinding()) {
-			scope.problemReporter().invalidType(this, this.resolvedType);
+			reportInvalidType(blockScope);
 			return null;
 		}
-		if (isTypeUseDeprecated(this.resolvedType, scope))
-			scope.problemReporter().deprecatedType(this.resolvedType, this);
+		if (isTypeUseDeprecated(this.resolvedType, blockScope)) {
+			reportDeprecatedType(blockScope);
+		}
 	}
 	return this.resolvedType;
 }
-public abstract void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope classScope);
+
+public TypeBinding resolveType(ClassScope classScope) {
+	// handle the error here
+	this.constant = NotAConstant;
+	if (this.resolvedType != null) { // is a shared type reference which was already resolved
+		if (!this.resolvedType.isValidBinding())
+			return null; // already reported error
+	} else {
+		this.resolvedType = getTypeBinding(classScope);
+		if (!this.resolvedType.isValidBinding()) {
+			reportInvalidType(classScope);
+			return null;
+		}
+		if (isTypeUseDeprecated(this.resolvedType, classScope)) {
+			reportDeprecatedType(classScope);
+		}
+	}
+	return this.resolvedType;
+}
+protected void reportInvalidType(Scope scope) {
+	scope.problemReporter().invalidType(this, this.resolvedType);
+}
+protected void reportDeprecatedType(Scope scope) {
+	scope.problemReporter().deprecatedType(this.resolvedType, this);
+}
+public abstract void traverse(ASTVisitor visitor, ClassScope classScope);
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
index ade8fd3..1dbd8f7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
@@ -198,20 +198,28 @@
 		}
 	}
 
+	public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+		
+		output.append(operatorToString()).append(' ');
+		return this.expression.printExpression(0, output);
+	} 
+	
 	public TypeBinding resolveType(BlockScope scope) {
 		
+		boolean expressionIsCast;
+		if ((expressionIsCast = this.expression instanceof CastExpression) == true) this.expression.bits |= IgnoreNeedForCastCheckMASK; // will check later on
 		TypeBinding expressionType = this.expression.resolveType(scope);
 		if (expressionType == null) {
 			this.constant = NotAConstant;
 			return null;
 		}
-		int expressionId = expressionType.id;
-		if (expressionId > 15) {
+		int expressionTypeId = expressionType.id;
+		if (expressionTypeId > 15) {
 			this.constant = NotAConstant;
 			scope.problemReporter().invalidOperator(this, expressionType);
 			return null;
 		}
-
+	
 		int tableId;
 		switch ((bits & OperatorMASK) >> OperatorSHIFT) {
 			case NOT :
@@ -223,15 +231,15 @@
 			default :
 				tableId = MINUS;
 		} //+ and - cases
-
+	
 		// the code is an int
 		// (cast)  left   Op (cast)  rigth --> result
 		//  0000   0000       0000   0000      0000
 		//  <<16   <<12       <<8    <<4       <<0
-		int result = ResolveTypeTables[tableId][(expressionId << 4) + expressionId];
-		this.expression.implicitConversion = result >>> 12;
-		this.bits |= result & 0xF;
-		switch (result & 0xF) { // only switch on possible result type.....
+		int operatorSignature = OperatorSignatures[tableId][(expressionTypeId << 4) + expressionTypeId];
+		this.expression.implicitConversion = operatorSignature >>> 12;
+		this.bits |= operatorSignature & 0xF;
+		switch (operatorSignature & 0xF) { // only switch on possible result type.....
 			case T_boolean :
 				this.resolvedType = BooleanBinding;
 				break;
@@ -255,7 +263,7 @@
 				break;
 			default : //error........
 				this.constant = Constant.NotAConstant;
-				if (expressionId != T_undefined)
+				if (expressionTypeId != T_undefined)
 					scope.problemReporter().invalidOperator(this, expressionType);
 				return null;
 		}
@@ -264,7 +272,7 @@
 			this.constant =
 				Constant.computeConstantOperation(
 					this.expression.constant,
-					expressionId,
+					expressionTypeId,
 					(bits & OperatorMASK) >> OperatorSHIFT);
 		} else {
 			this.constant = Constant.NotAConstant;
@@ -274,16 +282,15 @@
 					this.optimizedBooleanConstant = Constant.fromValue(!cst.booleanValue());
 			}
 		}
+		if (expressionIsCast) {
+		// check need for operand cast
+			CastExpression.checkNeedForArgumentCast(scope, tableId, operatorSignature, this.expression, expressionTypeId);
+		}
 		return this.resolvedType;
 	}
 
-	public String toStringExpressionNoParenthesis() {
-		
-		return operatorToString() + " " + this.expression.toStringExpression(); //$NON-NLS-1$
-	} 
-	
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 			
 		if (visitor.visit(this, blockScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
index 4ab98e7..9e35784 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
@@ -10,8 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -29,6 +30,8 @@
 
 		this.condition = condition;
 		this.action = action;
+		// remember useful empty statement
+		if (action instanceof EmptyStatement) action.bits |= IsUsefulEmptyStatementMASK;
 		sourceStart = s;
 		sourceEnd = e;
 	}
@@ -62,7 +65,7 @@
 		LoopingFlowContext loopingContext;
 		FlowInfo actionInfo;
 		if (action == null 
-			|| (action.isEmptyBlock() && currentScope.environment().options.complianceLevel <= CompilerOptions.JDK1_3)) {
+			|| (action.isEmptyBlock() && currentScope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3)) {
 			condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
 			if (isConditionTrue) {
 				return FlowInfo.DEAD_END;
@@ -99,38 +102,29 @@
 				currentScope.methodScope().recordInitializationStates(
 					postCondInfo.initsWhenTrue());
 
-			if (!actionInfo.complainIfUnreachable(action, currentScope, false)) {
-				actionInfo = action.analyseCode(currentScope, loopingContext, actionInfo);
+			if (!this.action.complainIfUnreachable(actionInfo, currentScope, false)) {
+				actionInfo = this.action.analyseCode(currentScope, loopingContext, actionInfo);
 			}
 
 			// code generation can be optimized when no need to continue in the loop
 			if (!actionInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
 				continueLabel = null;
 			} else {
-				// TODO: (philippe) should simplify in one Loop context
+				// TODO (philippe) should simplify in one Loop context
 				condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
+				actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
 				loopingContext.complainOnFinalAssignmentsInLoop(currentScope, actionInfo);
 			}
 		}
 
-		// infinite loop
-		FlowInfo mergedInfo;
-		if (isConditionOptimizedTrue) {
-			mergedInitStateIndex =
-				currentScope.methodScope().recordInitializationStates(
-					mergedInfo = loopingContext.initsOnBreak);
-			return mergedInfo;
-		}
-
-		// end of loop: either condition false or break
-		mergedInfo =
-			postCondInfo.initsWhenFalse().unconditionalInits().mergedWith(
-				loopingContext.initsOnBreak);
-		if (isConditionOptimizedTrue && continueLabel == null){
-			mergedInfo.setReachMode(FlowInfo.UNREACHABLE);
-		}
-		mergedInitStateIndex =
-			currentScope.methodScope().recordInitializationStates(mergedInfo);
+		// end of loop
+		FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
+				loopingContext.initsOnBreak, 
+				isConditionOptimizedTrue, 
+				postCondInfo.initsWhenFalse(), 
+				isConditionOptimizedFalse,
+				!isConditionTrue /*while(true); unreachable(); */);
+		mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
 		return mergedInfo;
 	}
 
@@ -228,21 +222,19 @@
 			action.resolve(scope);
 	}
 
-	public String toString(int tab) {
+	public StringBuffer printStatement(int tab, StringBuffer output) {
 
-		String s = tabString(tab);
-		s = s + "while (" + condition.toStringExpression() + ")"; 	//$NON-NLS-1$ //$NON-NLS-2$
+		printIndent(tab, output).append("while ("); //$NON-NLS-1$
+		condition.printExpression(0, output).append(')');
 		if (action == null)
-			s = s + " {} ;"; //$NON-NLS-1$ 
-		else if (action instanceof Block)
-			s = s + "\n" + action.toString(tab + 1); //$NON-NLS-1$
+			output.append(';');
 		else
-			s = s + " {\n" + action.toString(tab + 1) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
-		return s;
+			action.printStatement(tab + 1, output); 
+		return output;
 	}
 
 	public void traverse(
-		IAbstractSyntaxTreeVisitor visitor,
+		ASTVisitor visitor,
 		BlockScope blockScope) {
 
 		if (visitor.visit(this, blockScope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
index 0052909..ed943cc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
@@ -37,4 +37,23 @@
 	int ConstantStringFixedSize = 3;
 	int ConstantUtf8FixedSize = 3;
 	int ConstantNameAndTypeFixedSize = 5;
+	
+	int MAJOR_VERSION_1_1 = 45;
+	int MAJOR_VERSION_1_2 = 46;
+	int MAJOR_VERSION_1_3 = 47;
+	int MAJOR_VERSION_1_4 = 48;
+	int MAJOR_VERSION_1_5 = 49; 
+	
+	int MINOR_VERSION_0 = 0;
+	int MINOR_VERSION_1 = 1;
+	int MINOR_VERSION_2 = 2;	
+	int MINOR_VERSION_3 = 3;	
+	
+	// JDK 1.1 -> 1.5, comparable value allowing to check both major/minor version at once 1.4.1 > 1.4.0
+	// 16 unsigned bits for major, then 16 bits for minor
+	long JDK1_1 = ((long)ClassFileConstants.MAJOR_VERSION_1_1 << 16) + ClassFileConstants.MINOR_VERSION_3; // 1.1. is 45.3
+	long JDK1_2 =  ((long)ClassFileConstants.MAJOR_VERSION_1_2 << 16) + ClassFileConstants.MINOR_VERSION_0;
+	long JDK1_3 =  ((long)ClassFileConstants.MAJOR_VERSION_1_3 << 16) + ClassFileConstants.MINOR_VERSION_0;
+	long JDK1_4 = ((long)ClassFileConstants.MAJOR_VERSION_1_4 << 16) + ClassFileConstants.MINOR_VERSION_0;
+	long JDK1_5 = ((long)ClassFileConstants.MAJOR_VERSION_1_5 << 16) + ClassFileConstants.MINOR_VERSION_0;	
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
index aae0a8f..6ea27d4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
@@ -24,6 +24,7 @@
 public class ClassFileReader extends ClassFileStruct implements AttributeNamesConstants, IBinaryType {
 	private int constantPoolCount;
 	private int[] constantPoolOffsets;
+	private long version;
 	private int accessFlags;
 	private char[] className;
 	private char[] superclassName;
@@ -60,6 +61,7 @@
 	this.classFileName = fileName;
 	int readOffset = 10;
 	try {
+		this.version = ((long)this.u2At(6) << 16) + this.u2At(4); // major<<16 + minor
 		constantPoolCount = this.u2At(8);
 		// Pass #1 - Fill in all primitive constants
 		this.constantPoolOffsets = new int[constantPoolCount];
@@ -404,6 +406,14 @@
 	return this.superclassName;
 }
 /**
+ * Answer the major/minor version defined in this class file according to the VM spec.
+ * as a long: (major<<16)+minor
+ * @return the major/minor version found
+ */
+public long getVersion() {
+	return this.version;
+}
+/**
  * Answer true if the receiver is an anonymous type, false otherwise
  *
  * @return <CODE>boolean</CODE>
@@ -578,8 +588,8 @@
 		}
 
 		// member types
-		IBinaryNestedType[] currentMemberTypes = (IBinaryNestedType[]) this.getMemberTypes();
-		IBinaryNestedType[] otherMemberTypes = (IBinaryNestedType[]) newClassFile.getMemberTypes();
+		IBinaryNestedType[] currentMemberTypes = this.getMemberTypes();
+		IBinaryNestedType[] otherMemberTypes = newClassFile.getMemberTypes();
 		if (currentMemberTypes != otherMemberTypes) { // TypeConstants.NoMemberTypes
 			int currentMemberTypeLength = currentMemberTypes == null ? 0 : currentMemberTypes.length;
 			int otherMemberTypeLength = otherMemberTypes == null ? 0 : otherMemberTypes.length;
@@ -706,10 +716,10 @@
 				return currentConstant.shortValue() != otherConstant.shortValue();
 			case TypeIds.T_char :
 				return currentConstant.charValue() != otherConstant.charValue();
-			case TypeIds.T_float :
-				return currentConstant.floatValue() != otherConstant.floatValue();
 			case TypeIds.T_long :
 				return currentConstant.longValue() != otherConstant.longValue();
+			case TypeIds.T_float :
+				return currentConstant.floatValue() != otherConstant.floatValue();
 			case TypeIds.T_double :
 				return currentConstant.doubleValue() != otherConstant.doubleValue();
 			case TypeIds.T_boolean :
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java
index 329e6ff..e4f5593 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java
@@ -40,7 +40,14 @@
 }
 public long i8At(int relativeOffset) {
 	int position = relativeOffset + structOffset;
-	return (((long) (reference[position++] & 0xFF)) << 56) + (((long) (reference[position++] & 0xFF)) << 48) + (((long) (reference[position++] & 0xFF)) << 40) + (((long) (reference[position++] & 0xFF)) << 32) + (((long) (reference[position++] & 0xFF)) << 24) + (((long) (reference[position++] & 0xFF)) << 16) + (((long) (reference[position++] & 0xFF)) << 8) + ((long) (reference[position++] & 0xFF));
+	return (((long) (reference[position++] & 0xFF)) << 56) 
+					+ (((long) (reference[position++] & 0xFF)) << 48) 
+					+ (((long) (reference[position++] & 0xFF)) << 40) 
+					+ (((long) (reference[position++] & 0xFF)) << 32) 
+					+ (((long) (reference[position++] & 0xFF)) << 24) 
+					+ (((long) (reference[position++] & 0xFF)) << 16) 
+					+ (((long) (reference[position++] & 0xFF)) << 8) 
+					+ (reference[position++] & 0xFF);
 }
 public static String printTypeModifiers(int modifiers) {
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java
index ad63ee5..49f2e94 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java
@@ -59,4 +59,10 @@
 public int getErrorCode() {
 	return errorCode;
 }
+/**
+ * @return int
+ */
+public int getBufferPosition() {
+	return bufferPosition;
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
index af19cbd..bebe256 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
@@ -24,6 +24,7 @@
 import org.eclipse.jdt.internal.compiler.impl.ShortConstant;
 import org.eclipse.jdt.internal.compiler.impl.StringConstant;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class FieldInfo extends ClassFileStruct implements AttributeNamesConstants, IBinaryField, Comparable, TypeIds {
 	private Constant constant;
@@ -40,7 +41,7 @@
  * @param offsets int[]
  * @param offset int
  */
-public FieldInfo (byte classFileBytes[], int offsets[], int offset) throws ClassFormatException {
+public FieldInfo (byte classFileBytes[], int offsets[], int offset) {
 	super(classFileBytes, offset);
 	constantPoolOffsets = offsets;
 	accessFlags = -1;
@@ -116,44 +117,40 @@
 }
 /**
  * Return a wrapper that contains the constant of the field.
- * Throws a java.ibm.compiler.java.classfmt.ClassFormatException in case the signature is 
- * incompatible with the constant tag.
- * 
- * @exception java.ibm.compiler.java.classfmt.ClassFormatException
  * @return java.lang.Object
  */
-public Object getWrappedConstantValue() throws ClassFormatException {
+public Object getWrappedConstantValue() {
 
 	if (this.wrappedConstantValue == null) {
 		if (hasConstant()) {
-			Constant constant = getConstant();
-			switch (constant.typeID()) {
+			Constant fieldConstant = getConstant();
+			switch (fieldConstant.typeID()) {
 				case T_int :
-					this.wrappedConstantValue = new Integer(constant.intValue());
+					this.wrappedConstantValue = new Integer(fieldConstant.intValue());
 					break;
 				case T_byte :
-					this.wrappedConstantValue = new Byte(constant.byteValue());
+					this.wrappedConstantValue = new Byte(fieldConstant.byteValue());
 					break;
 				case T_short :
-					this.wrappedConstantValue = new Short(constant.shortValue());
+					this.wrappedConstantValue = new Short(fieldConstant.shortValue());
 					break;
 				case T_char :
-					this.wrappedConstantValue = new Character(constant.charValue());
+					this.wrappedConstantValue = new Character(fieldConstant.charValue());
 					break;
 				case T_float :
-					this.wrappedConstantValue = new Float(constant.floatValue());
+					this.wrappedConstantValue = new Float(fieldConstant.floatValue());
 					break;
 				case T_double :
-					this.wrappedConstantValue = new Double(constant.doubleValue());
+					this.wrappedConstantValue = new Double(fieldConstant.doubleValue());
 					break;
 				case T_boolean :
-					this.wrappedConstantValue = new Boolean(constant.booleanValue());
+					this.wrappedConstantValue = Util.toBoolean(fieldConstant.booleanValue());
 					break;
 				case T_long :
-					this.wrappedConstantValue = new Long(constant.longValue());
+					this.wrappedConstantValue = new Long(fieldConstant.longValue());
 					break;
 				case T_String :
-					this.wrappedConstantValue = constant.stringValue();
+					this.wrappedConstantValue = fieldConstant.stringValue();
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java
index d1245c9..233834f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java
@@ -29,8 +29,7 @@
 	private boolean readInnerClassName = false;
 	private boolean readOuterClassName = false;
 	private boolean readInnerName = false;
-public InnerClassInfo(byte classFileBytes[], int offsets[], int offset)
-	throws ClassFormatException {
+public InnerClassInfo(byte classFileBytes[], int offsets[], int offset) {
 	super(classFileBytes, offset);
 	constantPoolOffsets = offsets;
 	innerClassNameIndex = u2At(0);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
index f04bc9f..c512041 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
@@ -29,7 +29,7 @@
  * @param offsets int[]
  * @param offset int
  */
-public MethodInfo (byte classFileBytes[], int offsets[], int offset) throws ClassFormatException {
+public MethodInfo (byte classFileBytes[], int offsets[], int offset) {
 	super(classFileBytes, offset);
 	constantPoolOffsets = offsets;
 	accessFlags = -1;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
index fda994a..d686c23 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
@@ -19,14 +19,16 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class CodeStream implements OperatorIds, ClassFileConstants, Opcodes, BaseTypes, TypeConstants, TypeIds {
-	// It will be responsible for the following items.
 
+	public static final boolean DEBUG = false;
+	
+	// It will be responsible for the following items.
 	// -> Tracking Max Stack.
 
 	public int stackMax; // Use Ints to keep from using extra bc when adding
 	public int stackDepth; // Use Ints to keep from using extra bc when adding
 	public int maxLocals;
-	public static final int max = 100; // Maximum size of the code array
+	public static final int MAXCODE = 100; // Maximum size of the code array
 	public static final int growFactor = 400;
 	public static final int LABELS_INCREMENT = 5;
 	public byte[] bCodeStream;
@@ -73,6 +75,7 @@
 	}
 }
 final public void aaload() {
+	if (DEBUG) System.out.println(position + "\t\taaload"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -83,6 +86,7 @@
 	}
 }
 final public void aastore() {
+	if (DEBUG) System.out.println(position + "\t\taastore"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 3;
 	try {
@@ -93,6 +97,7 @@
 	}
 }
 final public void aconst_null() {
+	if (DEBUG) System.out.println(position + "\t\taconst_null"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -153,6 +158,7 @@
 	visibleLocals[visibleLocalsCount++] = localBinding;
 }
 final public void aload(int iArg) {
+	if (DEBUG) System.out.println(position + "\t\taload:"+iArg); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -191,6 +197,7 @@
 	}
 }
 final public void aload_0() {
+	if (DEBUG) System.out.println(position + "\t\taload_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -206,6 +213,7 @@
 	}
 }
 final public void aload_1() {
+	if (DEBUG) System.out.println(position + "\t\taload_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -221,6 +229,7 @@
 	}
 }
 final public void aload_2() {
+	if (DEBUG) System.out.println(position + "\t\taload_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -236,6 +245,7 @@
 	}
 }
 final public void aload_3() {
+	if (DEBUG) System.out.println(position + "\t\taload_3"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -251,6 +261,7 @@
 	}
 }
 public final void anewarray(TypeBinding typeBinding) {
+	if (DEBUG) System.out.println(position + "\t\tanewarray: " + typeBinding); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -261,6 +272,7 @@
 	writeUnsignedShort(constantPool.literalIndex(typeBinding));
 }
 final public void areturn() {
+	if (DEBUG) System.out.println(position + "\t\tareturn"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	// the stackDepth should be equal to 0 
@@ -344,6 +356,7 @@
 	}
 }
 final public void arraylength() {
+	if (DEBUG) System.out.println(position + "\t\tarraylength"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -353,6 +366,7 @@
 	}
 }
 final public void astore(int iArg) {
+	if (DEBUG) System.out.println(position + "\t\tastore:"+iArg); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= iArg) {
@@ -388,6 +402,7 @@
 	}
 }
 final public void astore_0() {
+	if (DEBUG) System.out.println(position + "\t\tastore_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals == 0) {
@@ -401,6 +416,7 @@
 	}
 }
 final public void astore_1() {
+	if (DEBUG) System.out.println(position + "\t\tastore_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= 1) {
@@ -414,6 +430,7 @@
 	}
 }
 final public void astore_2() {
+	if (DEBUG) System.out.println(position + "\t\tastore_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= 2) {
@@ -427,6 +444,7 @@
 	}
 }
 final public void astore_3() {
+	if (DEBUG) System.out.println(position + "\t\tastore_3"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= 3) {
@@ -440,6 +458,7 @@
 	}
 }
 final public void athrow() {
+	if (DEBUG) System.out.println(position + "\t\tathrow"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -450,6 +469,7 @@
 	}
 }
 final public void baload() {
+	if (DEBUG) System.out.println(position + "\t\tbaload"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -460,6 +480,7 @@
 	}
 }
 final public void bastore() {
+	if (DEBUG) System.out.println(position + "\t\tbastore"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 3;
 	try {
@@ -470,6 +491,7 @@
 	}
 }
 final public void bipush(byte b) {
+	if (DEBUG) System.out.println(position + "\t\tbipush "+b); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -483,6 +505,7 @@
 	writeSignedByte(b);
 }
 final public void caload() {
+	if (DEBUG) System.out.println(position + "\t\tcaload"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -493,6 +516,7 @@
 	}
 }
 final public void castore() {
+	if (DEBUG) System.out.println(position + "\t\tcastore"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 3;
 	try {
@@ -503,6 +527,7 @@
 	}
 }
 public final void checkcast(TypeBinding typeBinding) {
+	if (DEBUG) System.out.println(position + "\t\tcheckcast:"+typeBinding); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -513,6 +538,7 @@
 	writeUnsignedShort(constantPool.literalIndex(typeBinding));
 }
 final public void d2f() {
+	if (DEBUG) System.out.println(position + "\t\td2f"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -523,6 +549,7 @@
 	}
 }
 final public void d2i() {
+	if (DEBUG) System.out.println(position + "\t\td2i"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -533,6 +560,7 @@
 	}
 }
 final public void d2l() {
+	if (DEBUG) System.out.println(position + "\t\td2l"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -542,6 +570,7 @@
 	}
 }
 final public void dadd() {
+	if (DEBUG) System.out.println(position + "\t\tdadd"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -552,6 +581,7 @@
 	}
 }
 final public void daload() {
+	if (DEBUG) System.out.println(position + "\t\tdaload"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -561,6 +591,7 @@
 	}
 }
 final public void dastore() {
+	if (DEBUG) System.out.println(position + "\t\tdastore"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 4;
 	try {
@@ -571,6 +602,7 @@
 	}
 }
 final public void dcmpg() {
+	if (DEBUG) System.out.println(position + "\t\tdcmpg"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 3;
 	try {
@@ -581,6 +613,7 @@
 	}
 }
 final public void dcmpl() {
+	if (DEBUG) System.out.println(position + "\t\tdcmpl"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 3;
 	try {
@@ -591,6 +624,7 @@
 	}
 }
 final public void dconst_0() {
+	if (DEBUG) System.out.println(position + "\t\tdconst_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -603,6 +637,7 @@
 	}
 }
 final public void dconst_1() {
+	if (DEBUG) System.out.println(position + "\t\tdconst_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -615,6 +650,7 @@
 	}
 }
 final public void ddiv() {
+	if (DEBUG) System.out.println(position + "\t\tddiv"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -628,6 +664,7 @@
 	stackDepth -= offset;
 }
 final public void dload(int iArg) {
+	if (DEBUG) System.out.println(position + "\t\tdload:"+iArg); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -666,6 +703,7 @@
 	}
 }
 final public void dload_0() {
+	if (DEBUG) System.out.println(position + "\t\tdload_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -681,6 +719,7 @@
 	}
 }
 final public void dload_1() {
+	if (DEBUG) System.out.println(position + "\t\tdload_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -696,6 +735,7 @@
 	}
 }
 final public void dload_2() {
+	if (DEBUG) System.out.println(position + "\t\tdload_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -711,6 +751,7 @@
 	}
 }
 final public void dload_3() {
+	if (DEBUG) System.out.println(position + "\t\tdload_3"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -726,6 +767,7 @@
 	}
 }
 final public void dmul() {
+	if (DEBUG) System.out.println(position + "\t\tdmul"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -736,6 +778,7 @@
 	}
 }
 final public void dneg() {
+	if (DEBUG) System.out.println(position + "\t\tdneg"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -745,6 +788,7 @@
 	}
 }
 final public void drem() {
+	if (DEBUG) System.out.println(position + "\t\tdrem"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -755,6 +799,7 @@
 	}
 }
 final public void dreturn() {
+	if (DEBUG) System.out.println(position + "\t\tdreturn"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	// the stackDepth should be equal to 0 
@@ -766,6 +811,7 @@
 	}
 }
 final public void dstore(int iArg) {
+	if (DEBUG) System.out.println(position + "\t\tdstore:"+iArg); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (maxLocals <= iArg + 1) {
@@ -801,6 +847,7 @@
 	}
 }
 final public void dstore_0() {
+	if (DEBUG) System.out.println(position + "\t\tdstore_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (maxLocals < 2) {
@@ -814,6 +861,7 @@
 	}
 }
 final public void dstore_1() {
+	if (DEBUG) System.out.println(position + "\t\tdstore_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (maxLocals < 3) {
@@ -827,6 +875,7 @@
 	}
 }
 final public void dstore_2() {
+	if (DEBUG) System.out.println(position + "\t\tdstore_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (maxLocals < 4) {
@@ -840,6 +889,7 @@
 	}
 }
 final public void dstore_3() {
+	if (DEBUG) System.out.println(position + "\t\tdstore_3"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (maxLocals < 5) {
@@ -853,6 +903,7 @@
 	}
 }
 final public void dsub() {
+	if (DEBUG) System.out.println(position + "\t\tdsub"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -863,6 +914,7 @@
 	}
 }
 final public void dup() {
+	if (DEBUG) System.out.println(position + "\t\tdup"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -875,6 +927,7 @@
 	}
 }
 final public void dup_x1() {
+	if (DEBUG) System.out.println(position + "\t\tdup_x1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -887,6 +940,7 @@
 	}
 }
 final public void dup_x2() {
+	if (DEBUG) System.out.println(position + "\t\tdup_x2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -899,6 +953,7 @@
 	}
 }
 final public void dup2() {
+	if (DEBUG) System.out.println(position + "\t\tdup2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -911,6 +966,7 @@
 	}
 }
 final public void dup2_x1() {
+	if (DEBUG) System.out.println(position + "\t\tdup2_x1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -923,6 +979,7 @@
 	}
 }
 final public void dup2_x2() {
+	if (DEBUG) System.out.println(position + "\t\tdup2_x2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -951,6 +1008,7 @@
 	}
 }
 final public void f2d() {
+	if (DEBUG) System.out.println(position + "\t\tf2d"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -963,6 +1021,7 @@
 	}
 }
 final public void f2i() {
+	if (DEBUG) System.out.println(position + "\t\tf2i"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -972,6 +1031,7 @@
 	}
 }
 final public void f2l() {
+	if (DEBUG) System.out.println(position + "\t\tf2l"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -984,6 +1044,7 @@
 	}
 }
 final public void fadd() {
+	if (DEBUG) System.out.println(position + "\t\tfadd"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -994,6 +1055,7 @@
 	}
 }
 final public void faload() {
+	if (DEBUG) System.out.println(position + "\t\tfaload"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -1004,6 +1066,7 @@
 	}
 }
 final public void fastore() {
+	if (DEBUG) System.out.println(position + "\t\tfaload"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 3;
 	try {
@@ -1014,6 +1077,7 @@
 	}
 }
 final public void fcmpg() {
+	if (DEBUG) System.out.println(position + "\t\tfcmpg"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -1024,6 +1088,7 @@
 	}
 }
 final public void fcmpl() {
+	if (DEBUG) System.out.println(position + "\t\tfcmpl"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -1034,6 +1099,7 @@
 	}
 }
 final public void fconst_0() {
+	if (DEBUG) System.out.println(position + "\t\tfconst_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -1046,6 +1112,7 @@
 	}
 }
 final public void fconst_1() {
+	if (DEBUG) System.out.println(position + "\t\tfconst_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -1058,6 +1125,7 @@
 	}
 }
 final public void fconst_2() {
+	if (DEBUG) System.out.println(position + "\t\tfconst_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -1070,6 +1138,7 @@
 	}
 }
 final public void fdiv() {
+	if (DEBUG) System.out.println(position + "\t\tfdiv"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -1080,6 +1149,7 @@
 	}
 }
 final public void fload(int iArg) {
+	if (DEBUG) System.out.println(position + "\t\tfload:"+iArg); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (maxLocals <= iArg) {
@@ -1117,6 +1187,7 @@
 	}
 }
 final public void fload_0() {
+	if (DEBUG) System.out.println(position + "\t\tfload_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (maxLocals == 0) {
@@ -1132,6 +1203,7 @@
 	}
 }
 final public void fload_1() {
+	if (DEBUG) System.out.println(position + "\t\tfload_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (maxLocals <= 1) {
@@ -1147,6 +1219,7 @@
 	}
 }
 final public void fload_2() {
+	if (DEBUG) System.out.println(position + "\t\tfload_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (maxLocals <= 2) {
@@ -1162,6 +1235,7 @@
 	}
 }
 final public void fload_3() {
+	if (DEBUG) System.out.println(position + "\t\tfload_3"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (maxLocals <= 3) {
@@ -1177,6 +1251,7 @@
 	}
 }
 final public void fmul() {
+	if (DEBUG) System.out.println(position + "\t\tfmul"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -1187,6 +1262,7 @@
 	}
 }
 final public void fneg() {
+	if (DEBUG) System.out.println(position + "\t\tfneg"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -1196,6 +1272,7 @@
 	}
 }
 final public void frem() {
+	if (DEBUG) System.out.println(position + "\t\tfrem"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -1206,6 +1283,7 @@
 	}
 }
 final public void freturn() {
+	if (DEBUG) System.out.println(position + "\t\tfreturn"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	// the stackDepth should be equal to 0 
@@ -1217,6 +1295,7 @@
 	}
 }
 final public void fstore(int iArg) {
+	if (DEBUG) System.out.println(position + "\t\tfstore:"+iArg); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= iArg) {
@@ -1252,6 +1331,7 @@
 	}
 }
 final public void fstore_0() {
+	if (DEBUG) System.out.println(position + "\t\tfstore_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals == 0) {
@@ -1265,6 +1345,7 @@
 	}
 }
 final public void fstore_1() {
+	if (DEBUG) System.out.println(position + "\t\tfstore_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= 1) {
@@ -1278,6 +1359,7 @@
 	}
 }
 final public void fstore_2() {
+	if (DEBUG) System.out.println(position + "\t\tfstore_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= 2) {
@@ -1291,6 +1373,7 @@
 	}
 }
 final public void fstore_3() {
+	if (DEBUG) System.out.println(position + "\t\tfstore_3"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= 3) {
@@ -1304,6 +1387,7 @@
 	}
 }
 final public void fsub() {
+	if (DEBUG) System.out.println(position + "\t\tfsub"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -1344,10 +1428,24 @@
 
 	// Wrap the code in an exception handler to convert a ClassNotFoundException into a NoClassDefError
 
-	anyExceptionHandler = new ExceptionLabel(this, TypeBinding.NullBinding /* represents ClassNotFoundException*/);
-	this.ldc(accessedType == TypeBinding.NullBinding ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$
+	anyExceptionHandler = new ExceptionLabel(this, BaseTypes.NullBinding /* represents ClassNotFoundException*/);
+	this.ldc(accessedType == BaseTypes.NullBinding ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$
 	this.invokeClassForName();
 
+	/* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=37565
+	if (accessedType == BaseTypes.NullBinding) {
+		this.ldc("java.lang.Object"); //$NON-NLS-1$
+	} else if (accessedType.isArrayType()) {
+		this.ldc(String.valueOf(accessedType.constantPoolName()).replace('/', '.'));
+	} else {
+		// we make it an array type (to avoid class initialization)
+		this.ldc("[L" + String.valueOf(accessedType.constantPoolName()).replace('/', '.') + ";"); //$NON-NLS-1$//$NON-NLS-2$
+	}
+	this.invokeClassForName();
+	if (!accessedType.isArrayType()) { // extract the component type, which doesn't initialize the class
+		this.invokeJavaLangClassGetComponentType();
+	}	
+	*/
 	/* We need to protect the runtime code from binary inconsistencies
 	in case the accessedType is missing, the ClassNotFoundException has to be converted
 	into a NoClassDefError(old ex message), we thus need to build an exception handler for this one. */
@@ -1553,7 +1651,7 @@
 			break;
 		default :
 			if ((-128 <= inlinedValue) && (inlinedValue <= 127)) {
-				this.bipush((byte) inlinedValue);
+				this.bipush(inlinedValue);
 				return;
 			}
 	}
@@ -1705,10 +1803,10 @@
 	else
 		this.iconst_0();
 }
-public void generateOuterAccess(Object[] mappingSequence, AstNode invocationSite, Binding target, Scope scope) {
+public void generateOuterAccess(Object[] mappingSequence, ASTNode invocationSite, Binding target, Scope scope) {
 	if (mappingSequence == null) {
 		if (target instanceof LocalVariableBinding) {
-			scope.problemReporter().needImplementation(); //TODO: (philippe) should improve local emulation failure reporting
+			scope.problemReporter().needImplementation(); //TODO (philippe) should improve local emulation failure reporting
 		} else {
 			scope.problemReporter().noSuchEnclosingInstance((ReferenceBinding)target, invocationSite, false);
 		}
@@ -1775,7 +1873,11 @@
  * Code responsible to generate the suitable code to supply values for the synthetic enclosing
  * instance arguments of a constructor invocation of a nested type.
  */
-public void generateSyntheticEnclosingInstanceValues(BlockScope currentScope, ReferenceBinding targetType, Expression enclosingInstance, AstNode invocationSite) {
+public void generateSyntheticEnclosingInstanceValues(
+		BlockScope currentScope, 
+		ReferenceBinding targetType, 
+		Expression enclosingInstance, 
+		ASTNode invocationSite) {
 
 	// supplying enclosing instance for the anonymous type's superclass
 	ReferenceBinding checkedTargetType = targetType.isAnonymousType() ? targetType.superclass() : targetType;
@@ -1791,24 +1893,26 @@
 	if ((syntheticArgumentTypes = targetType.syntheticEnclosingInstanceTypes()) != null) {
 
 		ReferenceBinding targetEnclosingType = checkedTargetType.enclosingType();
-		boolean needEnclosingInstanceNullCheck = currentScope.environment().options.complianceLevel >= CompilerOptions.JDK1_4;
+		boolean complyTo14 = currentScope.environment().options.complianceLevel >= ClassFileConstants.JDK1_4;
+		// deny access to enclosing instance argument for allocation and super constructor call (if 1.4)
+		boolean ignoreEnclosingArgInConstructorCall = invocationSite instanceof AllocationExpression
+					|| (complyTo14 && ((invocationSite instanceof ExplicitConstructorCall && ((ExplicitConstructorCall)invocationSite).isSuperAccess())));
 						
 		for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) {
 			ReferenceBinding syntheticArgType = syntheticArgumentTypes[i];
 			if (hasExtraEnclosingInstance && syntheticArgType == targetEnclosingType) {
 				hasExtraEnclosingInstance = false;
 				enclosingInstance.generateCode(currentScope, this, true);
-				if (needEnclosingInstanceNullCheck){
+				if (complyTo14){
 					dup();
 					invokeObjectGetClass(); // will perform null check
 					pop();
 				}
-				
 			} else {
 				Object[] emulationPath = currentScope.getEmulationPath(
-					syntheticArgType, 
-					false /*not only exact match (that is, allow compatible)*/,
-					targetType.isAnonymousType());
+						syntheticArgType, 
+						false /*not only exact match (that is, allow compatible)*/,
+						ignoreEnclosingArgInConstructorCall);
 				this.generateOuterAccess(emulationPath, invocationSite, syntheticArgType, currentScope);
 			}
 		}
@@ -1823,7 +1927,7 @@
  * variable arguments of a constructor invocation of a nested type.
  * (bug 26122) - synthetic values for outer locals must be passed after user arguments, e.g. new X(i = 1){}
  */
-public void generateSyntheticOuterArgumentValues(BlockScope currentScope, ReferenceBinding targetType, AstNode invocationSite) {
+public void generateSyntheticOuterArgumentValues(BlockScope currentScope, ReferenceBinding targetType, ASTNode invocationSite) {
 
 	// generate the synthetic outer arguments then
 	SyntheticArgumentBinding syntheticArguments[];
@@ -1987,6 +2091,7 @@
 	return contents;
 }
 final public void getfield(FieldBinding fieldBinding) {
+	if (DEBUG) System.out.println(position + "\t\tgetfield:"+fieldBinding); //$NON-NLS-1$
 	countLabels = 0;
 	if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
 		if (++stackDepth > stackMax)
@@ -2001,6 +2106,7 @@
 	writeUnsignedShort(constantPool.literalIndex(fieldBinding));
 }
 final public void getstatic(FieldBinding fieldBinding) {
+	if (DEBUG) System.out.println(position + "\t\tgetstatic:"+fieldBinding); //$NON-NLS-1$
 	countLabels = 0;
 	if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long))
 		stackDepth += 2;
@@ -2016,18 +2122,6 @@
 	}
 	writeUnsignedShort(constantPool.literalIndex(fieldBinding));
 }
-public void getSystemOut() {
-	countLabels = 0;
-	if (++stackDepth > stackMax)
-		stackMax = stackDepth;
-	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_getstatic;
-	} catch (IndexOutOfBoundsException e) {
-		resizeByteArray(OPC_getstatic);
-	}
-	writeUnsignedShort(constantPool.literalIndexForJavaLangSystemOut());
-}
 public void getTYPE(int baseTypeID) {
 	countLabels = 0;
 	if (++stackDepth > stackMax)
@@ -2039,40 +2133,49 @@
 		resizeByteArray(OPC_getstatic);
 	}
 	switch (baseTypeID) {
-		// getstatic: java.lang.Byte.TYPE			
 		case T_byte :
+			// getstatic: java.lang.Byte.TYPE			
+			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Byte.TYPE"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangByteTYPE());
 			break;
-			// getstatic: java.lang.Short.TYPE			
 		case T_short :
+			// getstatic: java.lang.Short.TYPE			
+			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Short.TYPE"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangShortTYPE());
 			break;
-			// getstatic: java.lang.Character.TYPE			
 		case T_char :
+			// getstatic: java.lang.Character.TYPE			
+			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Character.TYPE"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangCharacterTYPE());
 			break;
-			// getstatic: java.lang.Integer.TYPE			
 		case T_int :
+			// getstatic: java.lang.Integer.TYPE			
+			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Integer.TYPE"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangIntegerTYPE());
 			break;
-			// getstatic: java.lang.Long.TYPE			
 		case T_long :
+			// getstatic: java.lang.Long.TYPE			
+			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Long.TYPE"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangLongTYPE());
 			break;
-			// getstatic: java.lang.Float.TYPE			
 		case T_float :
+			// getstatic: java.lang.Float.TYPE			
+			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Float.TYPE"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangFloatTYPE());
 			break;
-			// getstatic: java.lang.Double.TYPE			
 		case T_double :
+			// getstatic: java.lang.Double.TYPE			
+			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Double.TYPE"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangDoubleTYPE());
 			break;
-			// getstatic: java.lang.Boolean.TYPE			
 		case T_boolean :
+			// getstatic: java.lang.Boolean.TYPE			
+			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Boolean.TYPE"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangBooleanTYPE());
 			break;
-			// getstatic: java.lang.Void.TYPE
 		case T_void :
+			// getstatic: java.lang.Void.TYPE
+			if (DEBUG) System.out.println(position + "\t\tgetstatic: java.lang.Void.TYPE"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangVoidTYPE());
 			break;
 	}
@@ -2080,13 +2183,14 @@
 /**
  * We didn't call it goto, because there is a conflit with the goto keyword
  */
-final public void goto_(Label lbl) {
+final public void goto_(Label label) {
 	if (this.wideMode) {
-		this.goto_w(lbl);
+		this.goto_w(label);
 		return;
 	}
+	if (DEBUG) System.out.println(position + "\t\tgoto:"+label); //$NON-NLS-1$
 	try {
-		lbl.inlineForwardReferencesFromLabelsTargeting(position);
+		label.inlineForwardReferencesFromLabelsTargeting(position);
 		/*
 		 Possible optimization for code such as:
 		 public Object foo() {
@@ -2119,50 +2223,11 @@
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_goto);
 	}
-	lbl.branch();
+	label.branch();
 }
 
-/**
- * We didn't call it goto, because there is a conflit with the goto keyword
- */
-final public void internal_goto_(Label lbl) {
-	try {
-		lbl.inlineForwardReferencesFromLabelsTargeting(position);
-		/*
-		 Possible optimization for code such as:
-		 public Object foo() {
-			boolean b = true;
-			if (b) {
-				if (b)
-					return null;
-			} else {
-				if (b) {
-					return null;
-				}
-			}
-			return null;
-		}
-		The goto around the else block for the first if will
-		be unreachable, because the thenClause of the second if
-		returns.
-		See inlineForwardReferencesFromLabelsTargeting defined
-		on the Label class for the remaining part of this
-		optimization.
-		 if (!lbl.isBranchTarget(position)) {
-			switch(bCodeStream[classFileOffset-1]) {
-				case OPC_return :
-				case OPC_areturn:
-					return;
-			}
-		}*/
-		position++;
-		bCodeStream[classFileOffset++] = OPC_goto;
-	} catch (IndexOutOfBoundsException e) {
-		resizeByteArray(OPC_goto);
-	}
-	lbl.branch();
-}
 final public void goto_w(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tgotow:"+lbl); //$NON-NLS-1$
 	try {
 		position++;
 		bCodeStream[classFileOffset++] = OPC_goto_w;
@@ -2172,6 +2237,7 @@
 	lbl.branchWide();
 }
 final public void i2b() {
+	if (DEBUG) System.out.println(position + "\t\ti2b"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -2181,6 +2247,7 @@
 	}
 }
 final public void i2c() {
+	if (DEBUG) System.out.println(position + "\t\ti2c"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -2190,6 +2257,7 @@
 	}
 }
 final public void i2d() {
+	if (DEBUG) System.out.println(position + "\t\ti2d"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -2202,6 +2270,7 @@
 	}
 }
 final public void i2f() {
+	if (DEBUG) System.out.println(position + "\t\ti2f"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -2211,6 +2280,7 @@
 	}
 }
 final public void i2l() {
+	if (DEBUG) System.out.println(position + "\t\ti2l"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -2223,6 +2293,7 @@
 	}
 }
 final public void i2s() {
+	if (DEBUG) System.out.println(position + "\t\ti2s"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -2232,6 +2303,7 @@
 	}
 }
 final public void iadd() {
+	if (DEBUG) System.out.println(position + "\t\tiadd"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -2242,6 +2314,7 @@
 	}
 }
 final public void iaload() {
+	if (DEBUG) System.out.println(position + "\t\tiaload"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -2252,6 +2325,7 @@
 	}
 }
 final public void iand() {
+	if (DEBUG) System.out.println(position + "\t\tiand"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -2262,6 +2336,7 @@
 	}
 }
 final public void iastore() {
+	if (DEBUG) System.out.println(position + "\t\tiastore"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 3;
 	try {
@@ -2272,6 +2347,7 @@
 	}
 }
 final public void iconst_0() {
+	if (DEBUG) System.out.println(position + "\t\ticonst_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -2284,6 +2360,7 @@
 	}
 }
 final public void iconst_1() {
+	if (DEBUG) System.out.println(position + "\t\ticonst_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -2296,6 +2373,7 @@
 	}
 }
 final public void iconst_2() {
+	if (DEBUG) System.out.println(position + "\t\ticonst_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -2308,6 +2386,7 @@
 	}
 }
 final public void iconst_3() {
+	if (DEBUG) System.out.println(position + "\t\ticonst_3"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -2320,6 +2399,7 @@
 	}
 }
 final public void iconst_4() {
+	if (DEBUG) System.out.println(position + "\t\ticonst_4"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -2332,6 +2412,7 @@
 	}
 }
 final public void iconst_5() {
+	if (DEBUG) System.out.println(position + "\t\ticonst_5"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -2344,6 +2425,7 @@
 	}
 }
 final public void iconst_m1() {
+	if (DEBUG) System.out.println(position + "\t\ticonst_m1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -2356,6 +2438,7 @@
 	}
 }
 final public void idiv() {
+	if (DEBUG) System.out.println(position + "\t\tidiv"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -2366,10 +2449,11 @@
 	}
 }
 final public void if_acmpeq(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tif_acmpeq:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth-=2;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_if_acmpeq, lbl);
+		generateWideRevertedConditionalBranch(OPC_if_acmpne, lbl);
 	} else {	
 		try {
 			position++;
@@ -2381,10 +2465,11 @@
 	}
 }
 final public void if_acmpne(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tif_acmpne:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth-=2;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_if_acmpne, lbl);
+		generateWideRevertedConditionalBranch(OPC_if_acmpeq, lbl);
 	} else {	
 		try {
 			position++;
@@ -2396,10 +2481,11 @@
 	}
 }
 final public void if_icmpeq(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tif_cmpeq:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_if_icmpeq, lbl);
+		generateWideRevertedConditionalBranch(OPC_if_icmpne, lbl);
 	} else {	
 		try {
 			position++;
@@ -2411,10 +2497,11 @@
 	}
 }
 final public void if_icmpge(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tif_iacmpge:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_if_icmpge, lbl);
+		generateWideRevertedConditionalBranch(OPC_if_icmplt, lbl);
 	} else {	
 		try {
 			position++;
@@ -2426,10 +2513,11 @@
 	}
 }
 final public void if_icmpgt(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tif_iacmpgt:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_if_icmpgt, lbl);
+		generateWideRevertedConditionalBranch(OPC_if_icmple, lbl);
 	} else {	
 		try {
 			position++;
@@ -2441,10 +2529,11 @@
 	}
 }
 final public void if_icmple(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tif_iacmple:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_if_icmple, lbl);
+		generateWideRevertedConditionalBranch(OPC_if_icmpgt, lbl);
 	} else {	
 		try {
 			position++;
@@ -2456,10 +2545,11 @@
 	}
 }
 final public void if_icmplt(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tif_iacmplt:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_if_icmplt, lbl);
+		generateWideRevertedConditionalBranch(OPC_if_icmpge, lbl);
 	} else {
 		try {
 			position++;
@@ -2471,10 +2561,11 @@
 	}
 }
 final public void if_icmpne(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tif_iacmpne:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_if_icmpne, lbl);
+		generateWideRevertedConditionalBranch(OPC_if_icmpeq, lbl);
 	} else {
 		try {
 			position++;
@@ -2486,10 +2577,11 @@
 	}
 }
 final public void ifeq(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tifeq:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_ifeq, lbl);
+		generateWideRevertedConditionalBranch(OPC_ifne, lbl);
 	} else {
 		try {
 			position++;
@@ -2501,10 +2593,11 @@
 	}
 }
 final public void ifge(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tifge:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_ifge, lbl);
+		generateWideRevertedConditionalBranch(OPC_iflt, lbl);
 	} else {
 		try {
 			position++;
@@ -2516,10 +2609,11 @@
 	}
 }
 final public void ifgt(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tifgt:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_ifgt, lbl);
+		generateWideRevertedConditionalBranch(OPC_ifle, lbl);
 	} else {
 		try {
 			position++;
@@ -2531,10 +2625,11 @@
 	}
 }
 final public void ifle(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tifle:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_ifle, lbl);
+		generateWideRevertedConditionalBranch(OPC_ifgt, lbl);
 	} else {
 		try {
 			position++;
@@ -2546,10 +2641,11 @@
 	}
 }
 final public void iflt(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tiflt:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_iflt, lbl);
+		generateWideRevertedConditionalBranch(OPC_ifge, lbl);
 	} else {
 		try {
 			position++;
@@ -2561,10 +2657,11 @@
 	}
 }
 final public void ifne(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tifne:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_ifne, lbl);
+		generateWideRevertedConditionalBranch(OPC_ifeq, lbl);
 	} else {
 		try {
 			position++;
@@ -2576,10 +2673,11 @@
 	}
 }
 final public void ifnonnull(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tifnonnull:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_ifnonnull, lbl);
+		generateWideRevertedConditionalBranch(OPC_ifnull, lbl);
 	} else {
 		try {
 			position++;
@@ -2591,10 +2689,11 @@
 	}
 }
 final public void ifnull(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tifnull:"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (this.wideMode) {
-		generateWideConditionalBranch(OPC_ifnull, lbl);
+		generateWideRevertedConditionalBranch(OPC_ifnonnull, lbl);
 	} else {
 		try {
 			position++;
@@ -2606,6 +2705,7 @@
 	}
 }
 final public void iinc(int index, int value) {
+	if (DEBUG) System.out.println(position + "\t\tiinc:"+index+","+value); //$NON-NLS-1$ //$NON-NLS-2$
 	countLabels = 0;
 	if ((index > 255) || (value < -128 || value > 127)) { // have to widen
 		try {
@@ -2634,6 +2734,7 @@
 	}
 }
 final public void iload(int iArg) {
+	if (DEBUG) System.out.println(position + "\t\tiload:"+iArg); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (maxLocals <= iArg) {
@@ -2671,6 +2772,7 @@
 	}
 }
 final public void iload_0() {
+	if (DEBUG) System.out.println(position + "\t\tiload_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (maxLocals <= 0) {
@@ -2686,6 +2788,7 @@
 	}
 }
 final public void iload_1() {
+	if (DEBUG) System.out.println(position + "\t\tiload_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (maxLocals <= 1) {
@@ -2701,6 +2804,7 @@
 	}
 }
 final public void iload_2() {
+	if (DEBUG) System.out.println(position + "\t\tiload_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (maxLocals <= 2) {
@@ -2716,6 +2820,7 @@
 	}
 }
 final public void iload_3() {
+	if (DEBUG) System.out.println(position + "\t\tiload_3"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (maxLocals <= 3) {
@@ -2731,6 +2836,7 @@
 	}
 }
 final public void imul() {
+	if (DEBUG) System.out.println(position + "\t\timul"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -2762,6 +2868,7 @@
 	return -1;
 }
 final public void ineg() {
+	if (DEBUG) System.out.println(position + "\t\tineg"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -2770,11 +2877,11 @@
 		resizeByteArray(OPC_ineg);
 	}
 }
-public void init(ClassFile classFile) {
-	this.classFile = classFile;
-	this.constantPool = classFile.constantPool;
-	this.bCodeStream = classFile.contents;
-	this.classFileOffset = classFile.contentsOffset;
+public void init(ClassFile targetClassFile) {
+	this.classFile = targetClassFile;
+	this.constantPool = targetClassFile.constantPool;
+	this.bCodeStream = targetClassFile.contents;
+	this.classFileOffset = targetClassFile.contentsOffset;
 	this.startingClassFileOffset = this.classFileOffset;
 	pcToSourceMapSize = 0;
 	lastEntryPC = 0;
@@ -2890,6 +2997,7 @@
  * instanceof keyword
  */
 final public void instance_of(TypeBinding typeBinding) {
+	if (DEBUG) System.out.println(position + "\t\tinstance_of:"+typeBinding); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -2901,6 +3009,7 @@
 }
 public void invokeClassForName() {
 	// invokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class;
+	if (DEBUG) System.out.println(position + "\t\tinvokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class;"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -2913,6 +3022,7 @@
 
 public void invokeJavaLangClassDesiredAssertionStatus() {
 	// invokevirtual: java.lang.Class.desiredAssertionStatus()Z;
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Class.desiredAssertionStatus()Z;"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -2923,8 +3033,23 @@
 	}
 	writeUnsignedShort(constantPool.literalIndexForJavaLangClassDesiredAssertionStatus());
 }
+
+public void invokeJavaLangClassGetComponentType() {
+	// invokevirtual: java.lang.Class.getComponentType()java.lang.Class;
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Class.getComponentType()java.lang.Class;"); //$NON-NLS-1$
+	countLabels = 0;
+	try {
+		position++;
+		bCodeStream[classFileOffset++] = OPC_invokevirtual;
+	} catch (IndexOutOfBoundsException e) {
+		resizeByteArray(OPC_invokevirtual);
+	}
+	writeUnsignedShort(constantPool.literalIndexForJavaLangClassGetComponentType());
+}
+
 final public void invokeinterface(MethodBinding methodBinding) {
 	// initialized to 1 to take into account this  immediately
+	if (DEBUG) System.out.println(position + "\t\tinvokeinterface: " + methodBinding); //$NON-NLS-1$
 	countLabels = 0;
 	int argCount = 1;
 	int id;
@@ -2961,6 +3086,7 @@
 }
 public void invokeJavaLangErrorConstructor() {
 	// invokespecial: java.lang.Error<init>(Ljava.lang.String;)V
+	if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.Error<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -2973,6 +3099,7 @@
 }
 public void invokeNoClassDefFoundErrorStringConstructor() {
 	// invokespecial: java.lang.NoClassDefFoundError.<init>(Ljava.lang.String;)V
+	if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.NoClassDefFoundError.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -2985,6 +3112,7 @@
 }
 public void invokeObjectGetClass() {
 	// invokevirtual: java.lang.Object.getClass()Ljava.lang.Class;
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Object.getClass()Ljava.lang.Class;"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -2996,6 +3124,7 @@
 }
 
 final public void invokespecial(MethodBinding methodBinding) {
+	if (DEBUG) System.out.println(position + "\t\tinvokespecial:"+methodBinding); //$NON-NLS-1$
 	// initialized to 1 to take into account this  immediately
 	countLabels = 0;
 	int argCount = 1;
@@ -3047,6 +3176,7 @@
 		stackMax = stackDepth;
 }
 final public void invokestatic(MethodBinding methodBinding) {
+	if (DEBUG) System.out.println(position + "\t\tinvokestatic:"+methodBinding); //$NON-NLS-1$
 	// initialized to 0 to take into account that there is no this for
 	// a static method
 	countLabels = 0;
@@ -3079,6 +3209,7 @@
  * @param typeID <CODE>int</CODE>
  */
 public void invokeStringBufferAppendForType(int typeID) {
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.StringBuffer.append(...)"); //$NON-NLS-1$
 	countLabels = 0;
 	int usedTypeID;
 	if (typeID == T_null)
@@ -3101,6 +3232,7 @@
 
 public void invokeJavaLangAssertionErrorConstructor(int typeBindingID) {
 	// invokespecial: java.lang.AssertionError.<init>(typeBindingID)V
+	if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.AssertionError.<init>(typeBindingID)V"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3114,6 +3246,7 @@
 
 public void invokeJavaLangAssertionErrorDefaultConstructor() {
 	// invokespecial: java.lang.AssertionError.<init>()V
+	if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.AssertionError.<init>()V"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3127,6 +3260,7 @@
 
 public void invokeStringBufferDefaultConstructor() {
 	// invokespecial: java.lang.StringBuffer.<init>()V
+	if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.StringBuffer.<init>()V"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3139,6 +3273,7 @@
 }
 public void invokeStringBufferStringConstructor() {
 	// invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
+	if (DEBUG) System.out.println(position + "\t\tjava.lang.StringBuffer.<init>(Ljava.lang.String;)V"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3152,6 +3287,7 @@
 
 public void invokeStringBufferToString() {
 	// invokevirtual: StringBuffer.toString()Ljava.lang.String;
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: StringBuffer.toString()Ljava.lang.String;"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3163,6 +3299,7 @@
 }
 public void invokeStringIntern() {
 	// invokevirtual: java.lang.String.intern()
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.String.intern()"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3174,6 +3311,7 @@
 }
 public void invokeStringValueOf(int typeID) {
 	// invokestatic: java.lang.String.valueOf(argumentType)
+	if (DEBUG) System.out.println(position + "\t\tinvokestatic: java.lang.String.valueOf(...)"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3183,20 +3321,9 @@
 	}
 	writeUnsignedShort(constantPool.literalIndexForJavaLangStringValueOf(typeID));
 }
-public void invokeSystemExit() {
-	// invokestatic: java.lang.System.exit(I)
-	countLabels = 0;
-	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_invokestatic;
-	} catch (IndexOutOfBoundsException e) {
-		resizeByteArray(OPC_invokestatic);
-	}
-	writeUnsignedShort(constantPool.literalIndexForJavaLangSystemExitInt());
-	stackDepth--; // int argument
-}
 public void invokeThrowableGetMessage() {
 	// invokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String;
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String;"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3207,6 +3334,7 @@
 	writeUnsignedShort(constantPool.literalIndexForJavaLangThrowableGetMessage());
 }
 final public void invokevirtual(MethodBinding methodBinding) {
+	if (DEBUG) System.out.println(position + "\t\tinvokevirtual:"+methodBinding); //$NON-NLS-1$
 	// initialized to 1 to take into account this  immediately
 	countLabels = 0;
 	int argCount = 1;
@@ -3234,6 +3362,7 @@
 		stackMax = stackDepth;
 }
 final public void ior() {
+	if (DEBUG) System.out.println(position + "\t\tior"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -3244,6 +3373,7 @@
 	}
 }
 final public void irem() {
+	if (DEBUG) System.out.println(position + "\t\tirem"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -3254,6 +3384,7 @@
 	}
 }
 final public void ireturn() {
+	if (DEBUG) System.out.println(position + "\t\tireturn"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	// the stackDepth should be equal to 0 
@@ -3271,22 +3402,23 @@
 	if (local.isArgument) {
 		return true;
 	}
-	int position = local.id + maxFieldCount;
+	int localPosition = local.id + maxFieldCount;
 	MethodScope methodScope = scope.methodScope();
 	// id is zero-based
-	if (position < UnconditionalFlowInfo.BitCacheSize) {
-		return (methodScope.definiteInits[initStateIndex] & (1L << position)) != 0; // use bits
+	if (localPosition < UnconditionalFlowInfo.BitCacheSize) {
+		return (methodScope.definiteInits[initStateIndex] & (1L << localPosition)) != 0; // use bits
 	}
 	// use extra vector
 	long[] extraInits = methodScope.extraDefiniteInits[initStateIndex];
 	if (extraInits == null)
 		return false; // if vector not yet allocated, then not initialized
 	int vectorIndex;
-	if ((vectorIndex = (position / UnconditionalFlowInfo.BitCacheSize) - 1) >= extraInits.length)
+	if ((vectorIndex = (localPosition / UnconditionalFlowInfo.BitCacheSize) - 1) >= extraInits.length)
 		return false; // if not enough room in vector, then not initialized 
-	return ((extraInits[vectorIndex]) & (1L << (position % UnconditionalFlowInfo.BitCacheSize))) != 0;
+	return ((extraInits[vectorIndex]) & (1L << (localPosition % UnconditionalFlowInfo.BitCacheSize))) != 0;
 }
 final public void ishl() {
+	if (DEBUG) System.out.println(position + "\t\tishl"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -3297,6 +3429,7 @@
 	}
 }
 final public void ishr() {
+	if (DEBUG) System.out.println(position + "\t\tishr"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -3307,6 +3440,7 @@
 	}
 }
 final public void istore(int iArg) {
+	if (DEBUG) System.out.println(position + "\t\tistore:"+iArg); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= iArg) {
@@ -3342,6 +3476,7 @@
 	}
 }
 final public void istore_0() {
+	if (DEBUG) System.out.println(position + "\t\tistore_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals == 0) {
@@ -3355,6 +3490,7 @@
 	}
 }
 final public void istore_1() {
+	if (DEBUG) System.out.println(position + "\t\tistore_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= 1) {
@@ -3368,6 +3504,7 @@
 	}
 }
 final public void istore_2() {
+	if (DEBUG) System.out.println(position + "\t\tistore_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= 2) {
@@ -3381,6 +3518,7 @@
 	}
 }
 final public void istore_3() {
+	if (DEBUG) System.out.println(position + "\t\tistore_3"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	if (maxLocals <= 3) {
@@ -3394,6 +3532,7 @@
 	}
 }
 final public void isub() {
+	if (DEBUG) System.out.println(position + "\t\tisub"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -3404,6 +3543,7 @@
 	}
 }
 final public void iushr() {
+	if (DEBUG) System.out.println(position + "\t\tiushr"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -3414,6 +3554,7 @@
 	}
 }
 final public void ixor() {
+	if (DEBUG) System.out.println(position + "\t\tixor"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -3428,6 +3569,7 @@
 		this.jsr_w(lbl);
 		return;
 	}
+	if (DEBUG) System.out.println(position + "\t\tjsr"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3438,6 +3580,7 @@
 	lbl.branch();
 }
 final public void jsr_w(Label lbl) {
+	if (DEBUG) System.out.println(position + "\t\tjsr_w"+lbl); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3448,6 +3591,7 @@
 	lbl.branchWide();
 }
 final public void l2d() {
+	if (DEBUG) System.out.println(position + "\t\tl2d"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3457,6 +3601,7 @@
 	}
 }
 final public void l2f() {
+	if (DEBUG) System.out.println(position + "\t\tl2f"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -3467,6 +3612,7 @@
 	}
 }
 final public void l2i() {
+	if (DEBUG) System.out.println(position + "\t\tl2i"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -3477,6 +3623,7 @@
 	}
 }
 final public void ladd() {
+	if (DEBUG) System.out.println(position + "\t\tladd"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -3487,6 +3634,7 @@
 	}
 }
 final public void laload() {
+	if (DEBUG) System.out.println(position + "\t\tlaload"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -3496,6 +3644,7 @@
 	}
 }
 final public void land() {
+	if (DEBUG) System.out.println(position + "\t\tland"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -3506,6 +3655,7 @@
 	}
 }
 final public void lastore() {
+	if (DEBUG) System.out.println(position + "\t\tlastore"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 4;
 	try {
@@ -3516,6 +3666,7 @@
 	}
 }
 final public void lcmp() {
+	if (DEBUG) System.out.println(position + "\t\tlcmp"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 3;
 	try {
@@ -3526,6 +3677,7 @@
 	}
 }
 final public void lconst_0() {
+	if (DEBUG) System.out.println(position + "\t\tlconst_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -3538,6 +3690,7 @@
 	}
 }
 final public void lconst_1() {
+	if (DEBUG) System.out.println(position + "\t\tlconst_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (stackDepth > stackMax)
@@ -3550,6 +3703,7 @@
 	}
 }
 final public void ldc(float constant) {
+	if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
 	countLabels = 0;
 	int index = constantPool.literalIndex(constant);
 	stackDepth++;
@@ -3576,6 +3730,7 @@
 	}
 }
 final public void ldc(int constant) {
+	if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
 	countLabels = 0;
 	int index = constantPool.literalIndex(constant);
 	stackDepth++;
@@ -3602,6 +3757,7 @@
 	}
 }
 final public void ldc(String constant) {
+	if (DEBUG) System.out.println(position + "\t\tldc:"+constant); //$NON-NLS-1$
 	countLabels = 0;
 	int currentConstantPoolIndex = constantPool.currentIndex;
 	int currentConstantPoolOffset = constantPool.currentOffset;
@@ -3768,6 +3924,7 @@
 	}
 }
 final public void ldc2_w(double constant) {
+	if (DEBUG) System.out.println(position + "\t\tldc2_w:"+constant); //$NON-NLS-1$
 	countLabels = 0;
 	int index = constantPool.literalIndex(constant);
 	stackDepth += 2;
@@ -3783,6 +3940,7 @@
 	writeUnsignedShort(index);
 }
 final public void ldc2_w(long constant) {
+	if (DEBUG) System.out.println(position + "\t\tldc2_w:"+constant); //$NON-NLS-1$
 	countLabels = 0;
 	int index = constantPool.literalIndex(constant);
 	stackDepth += 2;
@@ -3798,6 +3956,7 @@
 	writeUnsignedShort(index);
 }
 final public void ldiv() {
+	if (DEBUG) System.out.println(position + "\t\tldiv"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -3808,6 +3967,7 @@
 	}
 }
 final public void lload(int iArg) {
+	if (DEBUG) System.out.println(position + "\t\tlload:"+iArg); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (maxLocals <= iArg + 1) {
@@ -3845,6 +4005,7 @@
 	}
 }
 final public void lload_0() {
+	if (DEBUG) System.out.println(position + "\t\tlload_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (maxLocals < 2) {
@@ -3860,6 +4021,7 @@
 	}
 }
 final public void lload_1() {
+	if (DEBUG) System.out.println(position + "\t\tlload_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (maxLocals < 3) {
@@ -3875,6 +4037,7 @@
 	}
 }
 final public void lload_2() {
+	if (DEBUG) System.out.println(position + "\t\tlload_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (maxLocals < 4) {
@@ -3890,6 +4053,7 @@
 	}
 }
 final public void lload_3() {
+	if (DEBUG) System.out.println(position + "\t\tlload_3"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth += 2;
 	if (maxLocals < 5) {
@@ -3905,6 +4069,7 @@
 	}
 }
 final public void lmul() {
+	if (DEBUG) System.out.println(position + "\t\tlmul"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -3915,6 +4080,7 @@
 	}
 }
 final public void lneg() {
+	if (DEBUG) System.out.println(position + "\t\tlneg"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -4208,6 +4374,7 @@
 	}
 }
 final public void lookupswitch(CaseLabel defaultLabel, int[] keys, int[] sortedIndexes, CaseLabel[] casesLabel) {
+	if (DEBUG) System.out.println(position + "\t\tlookupswitch"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	int length = keys.length;
@@ -4238,6 +4405,7 @@
 	}
 }
 final public void lor() {
+	if (DEBUG) System.out.println(position + "\t\tlor"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -4248,6 +4416,7 @@
 	}
 }
 final public void lrem() {
+	if (DEBUG) System.out.println(position + "\t\tlrem"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -4258,6 +4427,7 @@
 	}
 }
 final public void lreturn() {
+	if (DEBUG) System.out.println(position + "\t\tlreturn"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	// the stackDepth should be equal to 0 
@@ -4269,6 +4439,7 @@
 	}
 }
 final public void lshl() {
+	if (DEBUG) System.out.println(position + "\t\tlshl"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -4279,6 +4450,7 @@
 	}
 }
 final public void lshr() {
+	if (DEBUG) System.out.println(position + "\t\tlshr"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -4289,6 +4461,7 @@
 	}
 }
 final public void lstore(int iArg) {
+	if (DEBUG) System.out.println(position + "\t\tlstore:"+iArg); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (maxLocals <= iArg + 1) {
@@ -4324,6 +4497,7 @@
 	}
 }
 final public void lstore_0() {
+	if (DEBUG) System.out.println(position + "\t\tlstore_0"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (maxLocals < 2) {
@@ -4337,6 +4511,7 @@
 	}
 }
 final public void lstore_1() {
+	if (DEBUG) System.out.println(position + "\t\tlstore_1"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (maxLocals < 3) {
@@ -4350,6 +4525,7 @@
 	}
 }
 final public void lstore_2() {
+	if (DEBUG) System.out.println(position + "\t\tlstore_2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (maxLocals < 4) {
@@ -4363,6 +4539,7 @@
 	}
 }
 final public void lstore_3() {
+	if (DEBUG) System.out.println(position + "\t\tlstore_3"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	if (maxLocals < 5) {
@@ -4376,6 +4553,7 @@
 	}
 }
 final public void lsub() {
+	if (DEBUG) System.out.println(position + "\t\tlsub"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -4386,6 +4564,7 @@
 	}
 }
 final public void lushr() {
+	if (DEBUG) System.out.println(position + "\t\tlushr"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -4396,6 +4575,7 @@
 	}
 }
 final public void lxor() {
+	if (DEBUG) System.out.println(position + "\t\tlxor"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -4406,6 +4586,7 @@
 	}
 }
 final public void monitorenter() {
+	if (DEBUG) System.out.println(position + "\t\tmonitorenter"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -4416,6 +4597,7 @@
 	}
 }
 final public void monitorexit() {
+	if (DEBUG) System.out.println(position + "\t\tmonitorexit"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -4426,6 +4608,7 @@
 	}
 }
 final public void multianewarray(TypeBinding typeBinding, int dimensions) {
+	if (DEBUG) System.out.println(position + "\t\tmultinewarray:"+typeBinding+","+dimensions); //$NON-NLS-1$ //$NON-NLS-2$
 	countLabels = 0;
 	stackDepth += (1 - dimensions);
 	try {
@@ -4437,12 +4620,11 @@
 	writeUnsignedShort(constantPool.literalIndex(typeBinding));
 	writeUnsignedByte(dimensions);
 }
-public static void needImplementation() {
-}
 /**
  * We didn't call it new, because there is a conflit with the new keyword
  */
 final public void new_(TypeBinding typeBinding) {
+	if (DEBUG) System.out.println(position + "\t\tnew:"+typeBinding); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -4456,6 +4638,7 @@
 	writeUnsignedShort(constantPool.literalIndex(typeBinding));
 }
 final public void newarray(int array_Type) {
+	if (DEBUG) System.out.println(position + "\t\tnewarray:"+array_Type); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -4498,6 +4681,7 @@
 }
 public void newJavaLangError() {
 	// new: java.lang.Error
+	if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Error"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -4513,6 +4697,7 @@
 
 public void newJavaLangAssertionError() {
 	// new: java.lang.AssertionError
+	if (DEBUG) System.out.println(position + "\t\tnew: java.lang.AssertionError"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -4526,7 +4711,9 @@
 	writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionError());
 }
 
-public void newNoClassDefFoundError() { // new: java.lang.NoClassDefFoundError
+public void newNoClassDefFoundError() {
+	// new: java.lang.NoClassDefFoundError
+	if (DEBUG) System.out.println(position + "\t\tnew: java.lang.NoClassDefFoundError"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -4539,7 +4726,9 @@
 	}
 	writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundError());
 }
-public void newStringBuffer() { // new: java.lang.StringBuffer
+public void newStringBuffer() {
+	// new: java.lang.StringBuffer
+	if (DEBUG) System.out.println(position + "\t\tnew: java.lang.StringBuffer"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -4565,34 +4754,44 @@
 	}
 	switch (typeID) {
 		case T_int : // new: java.lang.Integer
+			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Integer"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangInteger());
 			break;
 		case T_boolean : // new: java.lang.Boolean
+			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Boolean"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangBoolean());
 			break;
 		case T_byte : // new: java.lang.Byte
+			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Byte"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangByte());
 			break;
 		case T_char : // new: java.lang.Character
+			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Character"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangCharacter());
 			break;
 		case T_float : // new: java.lang.Float
+			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Float"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangFloat());
 			break;
 		case T_double : // new: java.lang.Double
+			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Double"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangDouble());
 			break;
 		case T_short : // new: java.lang.Short
+			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Short"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangShort());
 			break;
 		case T_long : // new: java.lang.Long
+			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Long"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangLong());
 			break;
 		case T_void : // new: java.lang.Void
+			if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Void"); //$NON-NLS-1$
 			writeUnsignedShort(constantPool.literalIndexForJavaLangVoid());
 	}
 }
 final public void nop() {
+	if (DEBUG) System.out.println(position + "\t\tnop"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -4602,6 +4801,7 @@
 	}
 }
 final public void pop() {
+	if (DEBUG) System.out.println(position + "\t\tpop"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -4612,6 +4812,7 @@
 	}
 }
 final public void pop2() {
+	if (DEBUG) System.out.println(position + "\t\tpop2"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 2;
 	try {
@@ -4622,6 +4823,7 @@
 	}
 }
 final public void putfield(FieldBinding fieldBinding) {
+	if (DEBUG) System.out.println(position + "\t\tputfield:"+fieldBinding); //$NON-NLS-1$
 	countLabels = 0;
 	int id;
 	if (((id = fieldBinding.type.id) == T_double) || (id == T_long))
@@ -4639,6 +4841,7 @@
 	writeUnsignedShort(constantPool.literalIndex(fieldBinding));
 }
 final public void putstatic(FieldBinding fieldBinding) {
+	if (DEBUG) System.out.println(position + "\t\tputstatic:"+fieldBinding); //$NON-NLS-1$
 	countLabels = 0;
 	int id;
 	if (((id = fieldBinding.type.id) == T_double) || (id == T_long))
@@ -4805,18 +5008,18 @@
  * @param methodDeclaration org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
  * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
  */
-public void reset(AbstractMethodDeclaration methodDeclaration, ClassFile classFile) {
-	init(classFile);
-	this.methodDeclaration = methodDeclaration;
-	preserveUnusedLocals = methodDeclaration.scope.problemReporter().options.preserveAllLocalVariables;
-	initializeMaxLocals(methodDeclaration.binding);
+public void reset(AbstractMethodDeclaration referenceMethod, ClassFile targetClassFile) {
+	init(targetClassFile);
+	this.methodDeclaration = referenceMethod;
+	preserveUnusedLocals = referenceMethod.scope.problemReporter().options.preserveAllLocalVariables;
+	initializeMaxLocals(referenceMethod.binding);
 }
 /**
  * @param methodDeclaration org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
  * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
  */
-public void resetForProblemClinit(ClassFile classFile) {
-	init(classFile);
+public void resetForProblemClinit(ClassFile targetClassFile) {
+	init(targetClassFile);
 	maxLocals = 0;
 }
 protected final void resizeByteArray() {
@@ -4838,6 +5041,7 @@
 	bCodeStream[classFileOffset - 1] = b;
 }
 final public void ret(int index) {
+	if (DEBUG) System.out.println(position + "\t\tret:"+index); //$NON-NLS-1$
 	countLabels = 0;
 	if (index > 255) { // Widen
 		try {
@@ -4869,6 +5073,7 @@
 	}
 }
 final public void return_() {
+	if (DEBUG) System.out.println(position + "\t\treturn"); //$NON-NLS-1$
 	countLabels = 0;
 	// the stackDepth should be equal to 0 
 	try {
@@ -4879,6 +5084,7 @@
 	}
 }
 final public void saload() {
+	if (DEBUG) System.out.println(position + "\t\tsaload"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	try {
@@ -4889,6 +5095,7 @@
 	}
 }
 final public void sastore() {
+	if (DEBUG) System.out.println(position + "\t\tsastore"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth -= 3;
 	try {
@@ -5020,6 +5227,7 @@
 	}
 }
 final public void sipush(int s) {
+	if (DEBUG) System.out.println(position + "\t\tsipush:"+s); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth++;
 	if (stackDepth > stackMax)
@@ -5074,7 +5282,7 @@
 }
 
 public final void store(LocalVariableBinding localBinding, boolean valueRequired) {
-	int position = localBinding.resolvedPosition;
+	int localPosition = localBinding.resolvedPosition;
 	// Using dedicated int bytecode
 	switch(localBinding.type.id) {
 		case TypeIds.T_int :
@@ -5084,7 +5292,7 @@
 		case TypeIds.T_boolean :
 			if (valueRequired)
 				this.dup();
-			switch (position) {
+			switch (localPosition) {
 				case 0 :
 					this.istore_0();
 					break;
@@ -5101,13 +5309,13 @@
 				// internal failure: trying to store into variable not supposed to be generated
 				//	break;
 				default :
-					this.istore(position);
+					this.istore(localPosition);
 			}
 			break;
 		case TypeIds.T_float :
 			if (valueRequired)
 				this.dup();
-			switch (position) {
+			switch (localPosition) {
 				case 0 :
 					this.fstore_0();
 					break;
@@ -5121,13 +5329,13 @@
 					this.fstore_3();
 					break;
 				default :
-					this.fstore(position);
+					this.fstore(localPosition);
 			}
 			break;
 		case TypeIds.T_double :
 			if (valueRequired)
 				this.dup2();
-			switch (position) {
+			switch (localPosition) {
 				case 0 :
 					this.dstore_0();
 					break;
@@ -5141,13 +5349,13 @@
 					this.dstore_3();
 					break;
 				default :
-					this.dstore(position);
+					this.dstore(localPosition);
 			}
 			break;
 		case TypeIds.T_long :
 			if (valueRequired)
 				this.dup2();
-			switch (position) {
+			switch (localPosition) {
 				case 0 :
 					this.lstore_0();
 					break;
@@ -5161,14 +5369,14 @@
 					this.lstore_3();
 					break;
 				default :
-					this.lstore(position);
+					this.lstore(localPosition);
 			}
 			break;
 		default:
 			// Reference object
 			if (valueRequired)
 				this.dup();
-			switch (position) {
+			switch (localPosition) {
 				case 0 :
 					this.astore_0();
 					break;
@@ -5182,14 +5390,14 @@
 					this.astore_3();
 					break;
 				default :
-					this.astore(position);
+					this.astore(localPosition);
 			}
 	}
 }
-public final void store(TypeBinding type, int position) {
+public final void store(TypeBinding type, int localPosition) {
 	// Using dedicated int bytecode
 	if ((type == IntBinding) || (type == CharBinding) || (type == ByteBinding) || (type == ShortBinding) || (type == BooleanBinding)) {
-		switch (position) {
+		switch (localPosition) {
 			case 0 :
 				this.istore_0();
 				break;
@@ -5203,13 +5411,13 @@
 				this.istore_3();
 				break;
 			default :
-				this.istore(position);
+				this.istore(localPosition);
 		}
 		return;
 	}
 	// Using dedicated float bytecode
 	if (type == FloatBinding) {
-		switch (position) {
+		switch (localPosition) {
 			case 0 :
 				this.fstore_0();
 				break;
@@ -5223,13 +5431,13 @@
 				this.fstore_3();
 				break;
 			default :
-				this.fstore(position);
+				this.fstore(localPosition);
 		}
 		return;
 	}
 	// Using dedicated long bytecode
 	if (type == LongBinding) {
-		switch (position) {
+		switch (localPosition) {
 			case 0 :
 				this.lstore_0();
 				break;
@@ -5243,13 +5451,13 @@
 				this.lstore_3();
 				break;
 			default :
-				this.lstore(position);
+				this.lstore(localPosition);
 		}
 		return;
 	}
 	// Using dedicated double bytecode
 	if (type == DoubleBinding) {
-		switch (position) {
+		switch (localPosition) {
 			case 0 :
 				this.dstore_0();
 				break;
@@ -5263,12 +5471,12 @@
 				this.dstore_3();
 				break;
 			default :
-				this.dstore(position);
+				this.dstore(localPosition);
 		}
 		return;
 	}
 	// Reference object
-	switch (position) {
+	switch (localPosition) {
 		case 0 :
 			this.astore_0();
 			break;
@@ -5282,11 +5490,11 @@
 			this.astore_3();
 			break;
 		default :
-			this.astore(position);
+			this.astore(localPosition);
 	}
 }
-public final void storeInt(int position) {
-	switch (position) {
+public final void storeInt(int localPosition) {
+	switch (localPosition) {
 		case 0 :
 			this.istore_0();
 			break;
@@ -5300,11 +5508,11 @@
 			this.istore_3();
 			break;
 		default :
-			this.istore(position);
+			this.istore(localPosition);
 	}
 }
-public final void storeObject(int position) {
-	switch (position) {
+public final void storeObject(int localPosition) {
+	switch (localPosition) {
 		case 0 :
 			this.astore_0();
 			break;
@@ -5318,10 +5526,11 @@
 			this.astore_3();
 			break;
 		default :
-			this.astore(position);
+			this.astore(localPosition);
 	}
 }
 final public void swap() {
+	if (DEBUG) System.out.println(position + "\t\tswap"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -5340,6 +5549,7 @@
 	result[i] = T;
 }
 final public void tableswitch(CaseLabel defaultLabel, int low, int high, int[] keys, int[] sortedIndexes, CaseLabel[] casesLabel) {
+	if (DEBUG) System.out.println(position + "\t\ttableswitch"); //$NON-NLS-1$
 	countLabels = 0;
 	stackDepth--;
 	int length = casesLabel.length;
@@ -5407,6 +5617,7 @@
 
 	if (!generateLineNumberAttributes)
 		return;
+	this.lastEntryPC = pos;
 	// need to update the initialization endPC in case of generation of local variable attributes.
 	updateLocalVariablesAttribute(pos);
 }
@@ -5424,6 +5635,7 @@
 	}
 }
 final public void wide() {
+	if (DEBUG) System.out.println(position + "\t\twide"); //$NON-NLS-1$
 	countLabels = 0;
 	try {
 		position++;
@@ -5432,65 +5644,65 @@
 		resizeByteArray(OPC_wide);
 	}
 }
-public final void writeByte(byte b) {
+public final void writeByte(byte value) {
 	try {
 		position++;
-		bCodeStream[classFileOffset++] = b;
+		bCodeStream[classFileOffset++] = value;
 	} catch (IndexOutOfBoundsException e) {
-		resizeByteArray(b);
+		resizeByteArray(value);
 	}
 }
-public final void writeByteAtPos(int pos, byte b) {
+public final void writeByteAtPos(int pos, byte value) {
 	try {
-		bCodeStream[pos] = b;
+		bCodeStream[pos] = value;
 	} catch (IndexOutOfBoundsException ex) {
 		resizeByteArray();
-		bCodeStream[pos] = b;
+		bCodeStream[pos] = value;
 	}
 }
 /**
  * Write a unsigned 8 bits value into the byte array
  * @param b the signed byte
  */
-public final void writeSignedByte(int b) {
+public final void writeSignedByte(int value) {
 	try {
 		position++;
-		bCodeStream[classFileOffset++] = (byte) b;
+		bCodeStream[classFileOffset++] = (byte) value;
 	} catch (IndexOutOfBoundsException e) {
-		resizeByteArray((byte) b);
+		resizeByteArray((byte) value);
 	}
 }
 /**
  * Write a signed 16 bits value into the byte array
- * @param b the signed short
+ * @param value the signed short
  */
-public final void writeSignedShort(int b) {
+public final void writeSignedShort(int value) {
 	try {
 		position++;
-		bCodeStream[classFileOffset++] = (byte) (b >> 8);
+		bCodeStream[classFileOffset++] = (byte) (value >> 8);
 	} catch (IndexOutOfBoundsException e) {
-		resizeByteArray((byte) (b >> 8));
+		resizeByteArray((byte) (value >> 8));
 	}
 	try {
 		position++;
-		bCodeStream[classFileOffset++] = (byte) b;
+		bCodeStream[classFileOffset++] = (byte) value;
 	} catch (IndexOutOfBoundsException e) {
-		resizeByteArray((byte) b);
+		resizeByteArray((byte) value);
 	}
 }
-public final void writeSignedShort(int pos, int b) {
+public final void writeSignedShort(int pos, int value) {
 	int currentOffset = startingClassFileOffset + pos;
 	try {
-		bCodeStream[currentOffset] = (byte) (b >> 8);
+		bCodeStream[currentOffset] = (byte) (value >> 8);
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray();
-		bCodeStream[currentOffset] = (byte) (b >> 8);
+		bCodeStream[currentOffset] = (byte) (value >> 8);
 	}
 	try {
-		bCodeStream[currentOffset + 1] = (byte) b;
+		bCodeStream[currentOffset + 1] = (byte) value;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray();
-		bCodeStream[currentOffset + 1] = (byte) b;
+		bCodeStream[currentOffset + 1] = (byte) value;
 	}
 }
 public final void writeSignedWord(int value) {
@@ -5550,30 +5762,30 @@
  * Write a unsigned 8 bits value into the byte array
  * @param b the unsigned byte
  */
-public final void writeUnsignedByte(int b) {
+public final void writeUnsignedByte(int value) {
 	try {
 		position++;
-		bCodeStream[classFileOffset++] = (byte) b;
+		bCodeStream[classFileOffset++] = (byte) value;
 	} catch (IndexOutOfBoundsException e) {
-		resizeByteArray((byte) b);
+		resizeByteArray((byte) value);
 	}
 }
 /**
  * Write a unsigned 16 bits value into the byte array
  * @param b the unsigned short
  */
-public final void writeUnsignedShort(int b) {
+public final void writeUnsignedShort(int value) {
 	try {
 		position++;
-		bCodeStream[classFileOffset++] = (byte) (b >>> 8);
+		bCodeStream[classFileOffset++] = (byte) (value >>> 8);
 	} catch (IndexOutOfBoundsException e) {
-		resizeByteArray((byte) (b >>> 8));
+		resizeByteArray((byte) (value >>> 8));
 	}
 	try {
 		position++;
-		bCodeStream[classFileOffset++] = (byte) b;
+		bCodeStream[classFileOffset++] = (byte) value;
 	} catch (IndexOutOfBoundsException e) {
-		resizeByteArray((byte) b);
+		resizeByteArray((byte) value);
 	}
 }
 /**
@@ -5607,29 +5819,25 @@
 	}
 }
 
-public void generateWideConditionalBranch(byte opcode, Label lbl) {
-		/* we handle the goto_w problem inside an if.... with some macro expansion
-		 * at the bytecode level
-		 * instead of:
-		 * if_...... lbl
-		 * we have:
-		 *    ifne <l1>
-		 *    goto <l2>
-		 * l1 gotow <l3> // l3 is a wide target
-		 * l2 ....
-		 */
-		Label l1 = new Label(this);
+
+/*
+ * Wide conditional branch compare, improved by swapping comparison opcode
+ *   ifeq WideTarget
+ * becomes
+ *    ifne Intermediate
+ *    gotow WideTarget
+ *    Intermediate:
+ */
+public void generateWideRevertedConditionalBranch(byte revertedOpcode, Label wideTarget) {
+		Label intermediate = new Label(this);
 		try {
 			position++;
-			bCodeStream[classFileOffset++] = opcode;
+			bCodeStream[classFileOffset++] = revertedOpcode;
 		} catch (IndexOutOfBoundsException e) {
-			resizeByteArray(opcode);
+			resizeByteArray(revertedOpcode);
 		}
-		l1.branch();
-		Label l2 = new Label(this);
-		this.internal_goto_(l2);
-		l1.place();
-		this.goto_w(lbl);
-		l2.place();
+		intermediate.branch();
+		this.goto_w(wideTarget);
+		intermediate.place();
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
index ad3803e..d5a27a8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
@@ -46,10 +46,10 @@
 	protected FieldNameAndTypeCache nameAndTypeCacheForFields;
 	protected MethodNameAndTypeCache nameAndTypeCacheForMethods;
 	int[] wellKnownTypes = new int[21];
-	int[] wellKnownMethods = new int[35];
+	int[] wellKnownMethods = new int[36];
 	int[] wellKnownFields = new int[10];
 	int[] wellKnownFieldNameAndTypes = new int[2];
-	int[] wellKnownMethodNameAndTypes = new int[32];
+	int[] wellKnownMethodNameAndTypes = new int[33];
 	public byte[] poolContent;
 	public int currentIndex = 1;
 	public int currentOffset;
@@ -123,6 +123,8 @@
 	final static int ASSERTIONERROR_DEFAULT_CONSTR_METHOD = 32;
 	final static int DESIREDASSERTIONSTATUS_CLASS_METHOD = 33;
 	final static int GETCLASS_OBJECT_METHOD = 34;
+	final static int GETCOMPONENTTYPE_CLASS_METHOD = 35;
+	
 	// predefined constant index for well known name and type for fields
 	final static int TYPE_JAVALANGCLASS_NAME_AND_TYPE = 0;
 	final static int OUT_SYSTEM_NAME_AND_TYPE = 1;
@@ -159,7 +161,7 @@
 	final static int CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE = 29;
 	final static int DESIREDASSERTIONSTATUS_METHOD_NAME_AND_TYPE = 30;
 	final static int GETCLASS_OBJECT_METHOD_NAME_AND_TYPE = 31;
-
+	final static int GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE = 32;
 	
 	public ClassFile classFile;
 
@@ -414,7 +416,12 @@
 				&& methodBinding.returnType.id == T_JavaLangClass
 				&& CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetClass)) {
 					return GETCLASS_OBJECT_METHOD_NAME_AND_TYPE;
-			}				
+			}
+			if (methodBinding.parameters.length == 0
+				&& methodBinding.returnType.id == T_JavaLangClass
+				&& CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetComponentType)) {
+					return GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE;
+			}
 			break;
 		case 'i' :
 			if ((methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangString) && (CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.Intern))) {
@@ -442,6 +449,8 @@
 				return FORNAME_CLASS_METHOD;
 			} else if ((firstChar == 'd') && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_boolean) && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.DesiredAssertionStatus)) {
 					return DESIREDASSERTIONSTATUS_CLASS_METHOD;
+			} else if ((firstChar == 'g') && (methodBinding.parameters.length == 0) && (methodBinding.returnType.id == T_JavaLangClass) && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetComponentType)) {
+				return GETCOMPONENTTYPE_CLASS_METHOD;
 			}
 			break;
 		case T_JavaLangNoClassDefError :
@@ -766,7 +775,7 @@
 				poolContent[currentOffset - 1] = (byte) (temp >>> (56 - (i << 3)));
 			}
 		}
-	};
+	}
 	return index;
 }
 /**
@@ -804,7 +813,7 @@
 				poolContent[currentOffset - 1] = (byte) (temp >>> (24 - i * 8));
 			}
 		}
-	};
+	}
 	return index;
 }
 /**
@@ -841,7 +850,7 @@
 				poolContent[currentOffset - 1] = (byte) (key >>> (24 - i * 8));
 			}
 		}
-	};
+	}
 	return index;
 }
 /**
@@ -952,7 +961,8 @@
  * This method returns the index into the constantPool corresponding to the 
  * method descriptor. It can be either an interface method reference constant
  * or a method reference constant.
- *
+ * Note: uses the method binding #constantPoolDeclaringClass which could be an array type
+ * for the array clone method (see UpdatedMethodDeclaration).
  * @param MethodBinding aMethodBinding
  * @return <CODE>int</CODE>
  */
@@ -962,10 +972,10 @@
 	int classIndex;
 	int indexWellKnownMethod;
 	if ((indexWellKnownMethod = indexOfWellKnownMethods(aMethodBinding)) == -1) {
-		if (aMethodBinding.declaringClass.isInterface()) {
+		if (aMethodBinding.constantPoolDeclaringClass().isInterface()) {
 			// Lookinf into the interface method ref table
 			if ((index = interfaceMethodCache.get(aMethodBinding)) < 0) {
-				classIndex = literalIndex(aMethodBinding.declaringClass);
+				classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
 				nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
 				index = interfaceMethodCache.put(aMethodBinding, currentIndex++);
 				if (index > 0xFFFF){
@@ -982,7 +992,7 @@
 		} else {
 			// Lookinf into the method ref table
 			if ((index = methodCache.get(aMethodBinding)) < 0) {
-				classIndex = literalIndex(aMethodBinding.declaringClass);
+				classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
 				nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
 				index = methodCache.put(aMethodBinding, currentIndex++);
 				if (index > 0xFFFF){
@@ -1001,9 +1011,9 @@
 		// This is a well known method
 		if ((index = wellKnownMethods[indexWellKnownMethod]) == 0) {
 			// this methods was not inserted yet
-			if (aMethodBinding.declaringClass.isInterface()) {
+			if (aMethodBinding.constantPoolDeclaringClass().isInterface()) {
 				// Lookinf into the interface method ref table
-				classIndex = literalIndex(aMethodBinding.declaringClass);
+				classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
 				nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
 				index = wellKnownMethods[indexWellKnownMethod] = currentIndex++;
 				if (index > 0xFFFF){
@@ -1018,7 +1028,7 @@
 				writeU2(nameAndTypeIndex);
 			} else {
 				// Lookinf into the method ref table
-				classIndex = literalIndex(aMethodBinding.declaringClass);
+				classIndex = literalIndex(aMethodBinding.constantPoolDeclaringClass());
 				nameAndTypeIndex = literalIndexForMethods(literalIndex(aMethodBinding.constantPoolName()), literalIndex(aMethodBinding.signature()), aMethodBinding);
 				index = wellKnownMethods[indexWellKnownMethod] = currentIndex++;
 				if (index > 0xFFFF){
@@ -1364,6 +1374,42 @@
 	return index;
 }
 /**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangClassGetComponentType() {
+	int index;
+	int nameAndTypeIndex;
+	int classIndex;
+	// Looking into the method ref table
+	if ((index = wellKnownMethods[GETCOMPONENTTYPE_CLASS_METHOD]) == 0) {
+		classIndex = literalIndexForJavaLangClass();
+		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
+			int nameIndex = literalIndex(QualifiedNamesConstants.GetComponentType);
+			int typeIndex = literalIndex(QualifiedNamesConstants.GetComponentTypeSignature);
+			nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE] = currentIndex++;
+			writeU1(NameAndTypeTag);
+			writeU2(nameIndex);
+			writeU2(typeIndex);
+		}
+		index = wellKnownMethods[GETCOMPONENTTYPE_CLASS_METHOD] = currentIndex++;
+		if (index > 0xFFFF){
+			this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+		}
+		// Write the method ref constant into the constant pool
+		// First add the tag
+		writeU1(MethodRefTag);
+		// Then write the class index
+		writeU2(classIndex);
+		// The write the nameAndType index
+		writeU2(nameAndTypeIndex);
+	}
+	return index;
+}
+/**
  * This method returns the index into the constantPool corresponding to the type descriptor.
  *
  * @param TypeBinding aTypeBinding
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java
index b120831..e0c354b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java
@@ -13,24 +13,37 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 
 public class ExceptionLabel extends Label {
+	
 	public int start = POS_NOT_SET;
 	public int end = POS_NOT_SET;
 	public TypeBinding exceptionType;
-public ExceptionLabel(CodeStream codeStream, TypeBinding exceptionType) {
-	super(codeStream);
-	this.exceptionType = exceptionType;
-	this.start = codeStream.position;	
-}
-public boolean isStandardLabel(){
-	return false;
-}
-public void place() {
-	// register the handler inside the codeStream then normal place
-	codeStream.registerExceptionHandler(this);
-	super.place();
+	
+	public ExceptionLabel(CodeStream codeStream, TypeBinding exceptionType) {
 
-}
-public void placeEnd() {
-	end = codeStream.position;
-}
+		super(codeStream);
+		this.exceptionType = exceptionType;
+		this.placeStart();	
+	}
+
+	public boolean isStandardLabel(){
+
+		return false;
+	}
+
+	public void place() {
+
+		// register the handler inside the codeStream then normal place
+		codeStream.registerExceptionHandler(this);
+		super.place();
+	}
+
+	public void placeEnd() {
+
+		this.end = codeStream.position;
+	}
+	
+	public void placeStart() {
+
+		this.start = codeStream.position;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/Label.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/Label.java
index dff500a..8868d61 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/Label.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/Label.java
@@ -24,6 +24,7 @@
 	public int forwardReferenceCount = 0;
 	private boolean isWide = false;
 public Label() {
+	// for creating labels ahead of code generation
 }
 /**
  * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
@@ -56,7 +57,7 @@
 	forwardReferenceCount = neededSpace;
 }
 /*
-* Put down  a refernece to the array at the location in the codestream.
+* Put down  a reference to the array at the location in the codestream.
 */
 void branch() {
 	if (position == POS_NOT_SET) {
@@ -72,7 +73,7 @@
 		if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
 			throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
 		}
-		codeStream.writeSignedShort((short) offset);
+		codeStream.writeSignedShort(offset);
 	}
 }
 /*
@@ -99,6 +100,7 @@
  * Some placed labels might be branching to a goto bytecode which we can optimize better.
  */
 public void inlineForwardReferencesFromLabelsTargeting(int gotoLocation) {
+	
 /*
  Code required to optimized unreachable gotos.
 	public boolean isBranchTarget(int location) {
@@ -134,14 +136,17 @@
 * Place the label. If we have forward references resolve them.
 */
 public void place() { // Currently lacking wide support.
+	if (CodeStream.DEBUG) System.out.println("\t\t\t\t<place at: "+codeStream.position+" - "+ this); //$NON-NLS-1$ //$NON-NLS-2$
+
 	if (position == POS_NOT_SET) {
 		position = codeStream.position;
 		codeStream.addLabel(this);
 		int oldPosition = position;
-		boolean optimizedBranch = false;
+		boolean isOptimizedBranch = false;
 		// TURNED OFF since fail on 1F4IRD9
 		if (forwardReferenceCount != 0) {
-			if (optimizedBranch = (forwardReferences[forwardReferenceCount - 1] + 2 == position) && (codeStream.bCodeStream[codeStream.classFileOffset - 3] == CodeStream.OPC_goto)) {
+			isOptimizedBranch = (forwardReferences[forwardReferenceCount - 1] + 2 == position) && (codeStream.bCodeStream[codeStream.classFileOffset - 3] == Opcodes.OPC_goto);
+			if (isOptimizedBranch) {
 				codeStream.position = (position -= 3);
 				codeStream.classFileOffset -= 3;
 				forwardReferenceCount--;
@@ -188,16 +193,16 @@
 				if (this.isWide) {
 					codeStream.writeSignedWord(forwardReferences[i], offset);
 				} else {
-					codeStream.writeSignedShort(forwardReferences[i], (short) offset);
+					codeStream.writeSignedShort(forwardReferences[i], offset);
 				}
 			} else {
-				codeStream.writeSignedShort(forwardReferences[i], (short) offset);
+				codeStream.writeSignedShort(forwardReferences[i], offset);
 			}
 		}
 		// For all labels placed at that position we check if we need to rewrite the jump
 		// offset. It is the case each time a label had a forward reference to the current position.
 		// Like we change the current position, we have to change the jump offset. See 1F4IRD9 for more details.
-		if (optimizedBranch) {
+		if (isOptimizedBranch) {
 			for (int i = 0; i < codeStream.countLabels; i++) {
 				Label label = codeStream.labels[i];
 				if (oldPosition == label.position) {
@@ -219,10 +224,10 @@
 								if (this.isWide) {
 									codeStream.writeSignedWord(forwardPosition, offset);
 								} else {
-									codeStream.writeSignedShort(forwardPosition, (short) offset);
+									codeStream.writeSignedShort(forwardPosition, offset);
 								}
 							} else {
-								codeStream.writeSignedShort(forwardPosition, (short) offset);
+								codeStream.writeSignedShort(forwardPosition, offset);
 							}
 						}
 					}
@@ -235,8 +240,11 @@
  * Print out the receiver
  */
 public String toString() {
-	StringBuffer buffer = new StringBuffer("(position="); //$NON-NLS-1$
-	buffer.append(position);
+	String basic = getClass().getName();
+	basic = basic.substring(basic.lastIndexOf('.')+1);
+	StringBuffer buffer = new StringBuffer(basic); 
+	buffer.append('@').append(Integer.toHexString(hashCode()));
+	buffer.append("(position=").append(position); //$NON-NLS-1$
 	buffer.append(", forwards = ["); //$NON-NLS-1$
 	for (int i = 0; i < forwardReferenceCount - 1; i++)
 		buffer.append(forwardReferences[i] + ", "); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java
index 304ebda..4d5e158 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java
@@ -88,5 +88,6 @@
 	char[] ByteConstrSignature = "(B)V".toCharArray(); //$NON-NLS-1$
 	char[] GetClass = "getClass".toCharArray(); //$NON-NLS-1$
 	char[] GetClassSignature = "()Ljava/lang/Class;".toCharArray(); //$NON-NLS-1$
-	
+	char[] GetComponentType = "getComponentType".toCharArray(); //$NON-NLS-1$
+	char[] GetComponentTypeSignature = GetClassSignature;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ResetStateForCodeGenerationVisitor.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ResetStateForCodeGenerationVisitor.java
index 66c0de4..1c3fb44 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ResetStateForCodeGenerationVisitor.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ResetStateForCodeGenerationVisitor.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.codegen;
 
-import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.ast.BranchStatement;
 import org.eclipse.jdt.internal.compiler.ast.DoStatement;
@@ -21,7 +21,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 
 public class ResetStateForCodeGenerationVisitor
-	extends AbstractSyntaxTreeVisitorAdapter {
+	extends ASTVisitor {
 
 	public boolean visit(SwitchStatement statement, BlockScope scope) {
 		statement.resetStateForCodeGeneration();
@@ -56,6 +56,11 @@
 	public boolean visit(TryStatement tryStatement, BlockScope scope) {
 		tryStatement.resetStateForCodeGeneration();
 		return true;
+	}
+
+	public boolean visit(SynchronizedStatement synchronizedStatement, BlockScope scope) {
+		synchronizedStatement.resetStateForCodeGeneration();
+		return true;
 	}	
 }
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IConstants.java
index 7eb36a4..ebc44df 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/IConstants.java
@@ -15,6 +15,8 @@
  */
 public interface IConstants {
 
+	int AccDefault = 0;
+
 	/*
 	 * Modifiers
 	 */
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceImport.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceImport.java
new file mode 100644
index 0000000..d76f523
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceImport.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.env;
+
+public interface ISourceImport {
+
+/**
+ * Answer the source end position of the import declaration.
+ */
+
+int getDeclarationSourceEnd();
+/**
+ * Answer the source start position of the import declaration.
+ */
+
+int getDeclarationSourceStart();
+
+/**
+ * Answer an int whose bits are set according the access constants
+ * defined by the VM spec.
+ */ // TODO 1.5 feature, may need to be removed if static imports are not to be supported
+int getModifiers();
+
+/**
+ * Answer the name of the import.
+ * A name is a simple name or a qualified, dot separated name.
+ * For example, Hashtable or java.util.Hashtable.
+ */
+char[] getName();	
+
+/**
+ * Answer whether the import is on demand or not
+ * On demand import names have no trailing star
+ */
+boolean onDemand();
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
index 95c2e14..02525e9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
@@ -11,38 +11,40 @@
 package org.eclipse.jdt.internal.compiler.env;
 
 public interface ISourceType extends IGenericType {
+
 /**
  * Answer the source end position of the type's declaration.
  */
-
 int getDeclarationSourceEnd();
+
 /**
  * Answer the source start position of the type's declaration.
  */
-
 int getDeclarationSourceStart();
+
 /**
  * Answer the enclosing type
  * or null if the receiver is a top level type.
  */
-
 ISourceType getEnclosingType();
+
 /**
  * Answer the receiver's fields or null if the array is empty.
  *
  * NOTE: Multiple fields with the same name can exist in the result.
  */
-
 ISourceField[] getFields();
+
 /**
- * Answer the unresolved names of the receiver's imports
- * or null if the array is empty.
+ * Answer the receiver's imports or null if the array is empty.
  *
  * An import is a qualified, dot separated name.
  * For example, java.util.Hashtable or java.lang.*.
+ * A static import used 'static.' as its first fragment, for
+ * example: static.java.util.Hashtable.*
  */
+ISourceImport[] getImports();
 
-char[][] getImports();
 /**
  * Answer the unresolved names of the receiver's interfaces
  * or null if the array is empty.
@@ -50,52 +52,44 @@
  * A name is a simple name or a qualified, dot separated name.
  * For example, Hashtable or java.util.Hashtable.
  */
-
 char[][] getInterfaceNames();
+
 /**
  * Answer the receiver's member types
  * or null if the array is empty.
  */
-
 ISourceType[] getMemberTypes();
+
 /**
  * Answer the receiver's methods or null if the array is empty.
  *
  * NOTE: Multiple methods with the same name & parameter types can exist in the result.
  */
-
 ISourceMethod[] getMethods();
+
 /**
  * Answer the simple source name of the receiver.
  */
-
 char[] getName();
+
 /**
  * Answer the source end position of the type's name.
  */
-
 int getNameSourceEnd();
+
 /**
  * Answer the source start position of the type's name.
  */
-
 int getNameSourceStart();
+
 /**
  * Answer the qualified name of the receiver's package separated by periods
  * or null if its the default package.
  *
  * For example, {java.util.Hashtable}.
  */
-
 char[] getPackageName();
-/**
- * Answer the qualified name of the receiver.
- *
- * The name is a qualified, dot separated name.
- * For example, java.util.Hashtable.
- */
 
-char[] getQualifiedName();
 /**
  * Answer the unresolved name of the receiver's superclass
  * or null if it does not have one.
@@ -103,6 +97,5 @@
  * The name is a simple name or a qualified, dot separated name.
  * For example, Hashtable or java.util.Hashtable.
  */
-
 char[] getSuperclassName();
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java
index 588f3e4..7c747da 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java
@@ -12,10 +12,12 @@
 
 import java.util.ArrayList;
 
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.TryStatement;
 import org.eclipse.jdt.internal.compiler.codegen.ObjectCache;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -42,7 +44,7 @@
 	
 	public ExceptionHandlingFlowContext(
 		FlowContext parent,
-		AstNode associatedNode,
+		ASTNode associatedNode,
 		ReferenceBinding[] handledExceptions,
 		BlockScope scope,
 		UnconditionalFlowInfo flowInfo) {
@@ -70,8 +72,23 @@
 		this.initsOnReturn = FlowInfo.DEAD_END;	
 	}
 
+	public void complainIfUnusedExceptionHandlers(AbstractMethodDeclaration method) {
+		MethodScope scope = method.scope;
+		// report errors for unreachable exception handlers
+		for (int i = 0, count = handledExceptions.length; i < count; i++) {
+			int index = indexes.get(handledExceptions[i]);
+			int cacheIndex = index / BitCacheSize;
+			int bitMask = 1 << (index % BitCacheSize);
+			if ((isReached[cacheIndex] & bitMask) == 0) {
+				scope.problemReporter().unusedDeclaredThrownException(
+					handledExceptions[index],
+					method,
+					method.thrownExceptions[index]);
+			}
+		}
+	}
+	
 	public void complainIfUnusedExceptionHandlers(
-		AstNode[] exceptionHandlers,
 		BlockScope scope,
 		TryStatement tryStatement) {
 		// report errors for unreachable exception handlers
@@ -80,19 +97,17 @@
 			int cacheIndex = index / BitCacheSize;
 			int bitMask = 1 << (index % BitCacheSize);
 			if ((isReached[cacheIndex] & bitMask) == 0) {
-				scope.problemReporter().unreachableExceptionHandler(
+				scope.problemReporter().unreachableCatchBlock(
 					handledExceptions[index],
-					exceptionHandlers[index]);
+					tryStatement.catchArguments[index].type);
 			} else {
 				if ((isNeeded[cacheIndex] & bitMask) == 0) {
-					scope.problemReporter().maskedExceptionHandler(
+					scope.problemReporter().hiddenCatchBlock(
 						handledExceptions[index],
-						exceptionHandlers[index]);
+						tryStatement.catchArguments[index].type);
 				}
 			}
 		}
-		// will optimized out unnecessary catch block during code gen
-		tryStatement.preserveExceptionHandler = isNeeded;
 	}
 
 	public String individualToString() {
@@ -135,7 +150,7 @@
 		ReferenceBinding exceptionType,
 		UnconditionalFlowInfo flowInfo,
 		TypeBinding raisedException,
-		AstNode invocationSite,
+		ASTNode invocationSite,
 		boolean wasAlreadyDefinitelyCaught) {
 			
 		int index = indexes.get(exceptionType);
@@ -150,7 +165,7 @@
 		initsOnExceptions[index] =
 			initsOnExceptions[index] == FlowInfo.DEAD_END
 				? flowInfo.copy().unconditionalInits()
-				: initsOnExceptions[index].mergedWith(flowInfo);
+				: initsOnExceptions[index].mergedWith(flowInfo.copy().unconditionalInits());
 	}
 	
 	public void recordReturnFrom(FlowInfo flowInfo) {
@@ -159,7 +174,7 @@
 		if (initsOnReturn == FlowInfo.DEAD_END) {
 			initsOnReturn = flowInfo.copy().unconditionalInits();
 		} else {
-			initsOnReturn = initsOnReturn.mergedWith(flowInfo.unconditionalInits());
+			initsOnReturn = initsOnReturn.mergedWith(flowInfo.copy().unconditionalInits());
 		}
 	}
 	
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
index a09fa55..6bd9350 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.flow;
 
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Reference;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
@@ -27,7 +27,7 @@
 	VariableBinding finalVariables[];
 	int assignCount;
 	
-	public FinallyFlowContext(FlowContext parent, AstNode associatedNode) {
+	public FinallyFlowContext(FlowContext parent, ASTNode associatedNode) {
 		super(parent, associatedNode);
 	}
 
@@ -104,7 +104,7 @@
 				(finalVariables = new VariableBinding[assignCount * 2]),
 				0,
 				assignCount);
-		};
+		}
 		finalAssignments[assignCount] = finalAssignment;
 		finalVariables[assignCount++] = binding;
 		return true;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
index bea317f..35acba3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
@@ -12,8 +12,9 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Reference;
+import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement;
 import org.eclipse.jdt.internal.compiler.ast.TryStatement;
 import org.eclipse.jdt.internal.compiler.codegen.Label;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -29,12 +30,12 @@
  */
 public class FlowContext implements TypeConstants {
 	
-	public AstNode associatedNode;
+	public ASTNode associatedNode;
 	public FlowContext parent;
 
 	public final static FlowContext NotContinuableContext = new FlowContext(null, null);
 		
-	public FlowContext(FlowContext parent, AstNode associatedNode) {
+	public FlowContext(FlowContext parent, ASTNode associatedNode) {
 
 		this.parent = parent;
 		this.associatedNode = associatedNode;
@@ -47,7 +48,7 @@
 	
 	public void checkExceptionHandlers(
 		TypeBinding[] raisedExceptions,
-		AstNode location,
+		ASTNode location,
 		FlowInfo flowInfo,
 		BlockScope scope) {
 
@@ -73,8 +74,8 @@
 		FlowContext traversedContext = this;
 
 		while (traversedContext != null) {
-			AstNode sub;
-			if (((sub = traversedContext.subRoutine()) != null) && sub.cannotReturn()) {
+			SubRoutineStatement sub;
+			if (((sub = traversedContext.subRoutine()) != null) && sub.isSubRoutineEscaping()) {
 				// traversing a non-returning subroutine means that all unhandled 
 				// exceptions will actually never get sent...
 				return;
@@ -182,7 +183,7 @@
 
 	public void checkExceptionHandlers(
 		TypeBinding raisedException,
-		AstNode location,
+		ASTNode location,
 		FlowInfo flowInfo,
 		BlockScope scope) {
 
@@ -193,8 +194,8 @@
 		// until the point where it is safely handled (Smarter - see comment at the end)
 		FlowContext traversedContext = this;
 		while (traversedContext != null) {
-			AstNode sub;
-			if (((sub = traversedContext.subRoutine()) != null) && sub.cannotReturn()) {
+			SubRoutineStatement sub;
+			if (((sub = traversedContext.subRoutine()) != null) && sub.isSubRoutineEscaping()) {
 				// traversing a non-returning subroutine means that all unhandled 
 				// exceptions will actually never get sent...
 				return;
@@ -424,9 +425,11 @@
 	}
 
 	public void recordBreakFrom(FlowInfo flowInfo) {
+		// default implementation: do nothing
 	}
 
 	public void recordContinueFrom(FlowInfo flowInfo) {
+		// default implementation: do nothing
 	}
 
 	boolean recordFinalAssignment(
@@ -437,11 +440,15 @@
 	}
 
 	public void recordReturnFrom(FlowInfo flowInfo) {
+		// default implementation: do nothing
 	}
 
 	public void recordSettingFinal(
 		VariableBinding variable,
-		Reference finalReference) {
+		Reference finalReference,
+		FlowInfo flowInfo) {
+
+		if (!flowInfo.isReachable()) return;
 
 		// for initialization inside looping statement that effectively loops
 		FlowContext context = this;
@@ -454,9 +461,10 @@
 	}
 
 	void removeFinalAssignmentIfAny(Reference reference) {
+		// default implementation: do nothing
 	}
 
-	public AstNode subRoutine() {
+	public SubRoutineStatement subRoutine() {
 
 		return null;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
index 231b8c8..4eb03d9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
@@ -10,8 +10,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.flow;
 
-import org.eclipse.jdt.internal.compiler.ast.Statement;
-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
 
@@ -34,12 +32,6 @@
 		return this;
 	}
 
-	public boolean complainIfUnreachable(Statement statement, BlockScope scope, boolean didAlreadyComplain) {
-
-		// Report an error if necessary
-		return false;
-	}
-
 	public static FlowInfo conditional(FlowInfo initsWhenTrue, FlowInfo initsWhenFalse){
 
 		// if (initsWhenTrue.equals(initsWhenFalse)) return initsWhenTrue; -- could optimize if #equals is defined
@@ -103,6 +95,31 @@
 	 */
 	abstract public void markAsDefinitelyNotAssigned(LocalVariableBinding local);
 
+	/**
+	 * Merge branches using optimized boolean conditions
+	 */
+	public static FlowInfo mergedOptimizedBranches(FlowInfo initsWhenTrue, boolean isOptimizedTrue, FlowInfo initsWhenFalse, boolean isOptimizedFalse, boolean allowFakeDeadBranch) {
+		FlowInfo mergedInfo;
+		if (isOptimizedTrue){
+			if (initsWhenTrue == FlowInfo.DEAD_END && allowFakeDeadBranch) {
+				mergedInfo = initsWhenFalse.setReachMode(FlowInfo.UNREACHABLE);
+			} else {
+				mergedInfo = initsWhenTrue.addPotentialInitializationsFrom(initsWhenFalse);
+			}
+
+		} else if (isOptimizedFalse) {
+			if (initsWhenFalse == FlowInfo.DEAD_END && allowFakeDeadBranch) {
+				mergedInfo = initsWhenTrue.setReachMode(FlowInfo.UNREACHABLE);
+			} else {
+				mergedInfo = initsWhenFalse.addPotentialInitializationsFrom(initsWhenTrue);
+			}
+
+		} else {
+			mergedInfo = initsWhenTrue.unconditionalInits().mergedWith(initsWhenFalse.unconditionalInits());
+		}
+		return mergedInfo;
+	}
+	
 	abstract public int reachMode();
 
 	abstract public FlowInfo setReachMode(int reachMode);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.java
index 6de6a69..649bab6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.flow;
 
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -23,12 +23,12 @@
 
 	public int exceptionCount;
 	public TypeBinding[] thrownExceptions = new TypeBinding[5];
-	public AstNode[] exceptionThrowers = new AstNode[5];
+	public ASTNode[] exceptionThrowers = new ASTNode[5];
 	public FlowInfo[] exceptionThrowerFlowInfos = new FlowInfo[5];
 	
 	public InitializationFlowContext(
 		FlowContext parent,
-		AstNode associatedNode,
+		ASTNode associatedNode,
 		BlockScope scope) {
 		super(
 			parent,
@@ -65,7 +65,7 @@
 		ReferenceBinding exceptionType,
 		UnconditionalFlowInfo flowInfo,
 		TypeBinding raisedException,
-		AstNode invocationSite,
+		ASTNode invocationSite,
 		boolean wasMasked) {
 			
 		// even if unreachable code, need to perform unhandled exception diagnosis
@@ -80,7 +80,7 @@
 			System.arraycopy(
 				exceptionThrowers,
 				0,
-				(exceptionThrowers = new AstNode[size * 2]),
+				(exceptionThrowers = new ASTNode[size * 2]),
 				0,
 				size);
 			System.arraycopy(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/InsideSubRoutineFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/InsideSubRoutineFlowContext.java
index 966adab..8d5ca9c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/InsideSubRoutineFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/InsideSubRoutineFlowContext.java
@@ -10,7 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.flow;
 
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement;
 
 /**
  * Reflects the context of code analysis, keeping track of enclosing
@@ -22,7 +23,7 @@
 	
 	public InsideSubRoutineFlowContext(
 		FlowContext parent,
-		AstNode associatedNode) {
+		ASTNode associatedNode) {
 		super(parent, associatedNode);
 		this.initsOnReturn = FlowInfo.DEAD_END;				
 	}
@@ -39,11 +40,11 @@
 	}
 		
 	public boolean isNonReturningContext() {
-		return associatedNode.cannotReturn();
+		return subRoutine().isSubRoutineEscaping();
 	}
 	
-	public AstNode subRoutine() {
-		return associatedNode;
+	public SubRoutineStatement subRoutine() {
+		return (SubRoutineStatement)associatedNode;
 	}
 	
 	public void recordReturnFrom(FlowInfo flowInfo) {
@@ -52,7 +53,7 @@
 		if (initsOnReturn == FlowInfo.DEAD_END) {
 			initsOnReturn = flowInfo.copy().unconditionalInits();
 		} else {
-			initsOnReturn = initsOnReturn.mergedWith(flowInfo.unconditionalInits());
+			initsOnReturn = initsOnReturn.mergedWith(flowInfo.copy().unconditionalInits());
 		}
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java
index 9f5c81c..4d24a2c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java
@@ -11,7 +11,7 @@
 package org.eclipse.jdt.internal.compiler.flow;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.codegen.Label;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 
@@ -25,7 +25,7 @@
 	
 	public LabelFlowContext(
 		FlowContext parent,
-		AstNode associatedNode,
+		ASTNode associatedNode,
 		char[] labelName,
 		Label breakLabel,
 		BlockScope scope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
index f25fb2a..1b7f475 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.flow;
 
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Reference;
 import org.eclipse.jdt.internal.compiler.codegen.Label;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -34,7 +34,7 @@
 	
 	public LoopingFlowContext(
 		FlowContext parent,
-		AstNode associatedNode,
+		ASTNode associatedNode,
 		Label breakLabel,
 		Label continueLabel,
 		Scope associatedScope) {
@@ -102,13 +102,14 @@
 		if (initsOnContinue == FlowInfo.DEAD_END) {
 			initsOnContinue = flowInfo.copy().unconditionalInits();
 		} else {
-			initsOnContinue = initsOnContinue.mergedWith(flowInfo.unconditionalInits());
-		};
+			initsOnContinue = initsOnContinue.mergedWith(flowInfo.copy().unconditionalInits());
+		}
 	}
 
 	boolean recordFinalAssignment(
 		VariableBinding binding,
 		Reference finalAssignment) {
+
 		// do not consider variables which are defined inside this loop
 		if (binding instanceof LocalVariableBinding) {
 			Scope scope = ((LocalVariableBinding) binding).declaringScope;
@@ -134,7 +135,7 @@
 				(finalVariables = new VariableBinding[assignCount * 2]),
 				0,
 				assignCount);
-		};
+		}
 		finalAssignments[assignCount] = finalAssignment;
 		finalVariables[assignCount++] = binding;
 		return true;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java
index 85f350f..ce17744 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.flow;
 
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.codegen.Label;
 
 /**
@@ -23,7 +23,7 @@
 	
 	public SwitchFlowContext(
 		FlowContext parent,
-		AstNode associatedNode,
+		ASTNode associatedNode,
 		Label breakLabel) {
 		super(parent, associatedNode);
 		this.breakLabel = breakLabel;
@@ -48,7 +48,7 @@
 		if (initsOnBreak == FlowInfo.DEAD_END) {
 			initsOnBreak = flowInfo.copy().unconditionalInits();
 		} else {
-			initsOnBreak = initsOnBreak.mergedWith(flowInfo.unconditionalInits());
-		};
+			initsOnBreak = initsOnBreak.mergedWith(flowInfo.copy().unconditionalInits());
+		}
 	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
index 6784d35..7333b72 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
@@ -10,10 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.flow;
 
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.Statement;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -31,7 +28,7 @@
 	public long extraDefiniteInits[];
 	public long extraPotentialInits[];
 	
-	public int reachMode = REACHABLE; // by default
+	public int reachMode; // by default
 
 	public int maxFieldCount;
 	
@@ -39,6 +36,7 @@
 	public static final int BitCacheSize = 64; // 64 bits in a long.
 
 	UnconditionalFlowInfo() {
+		this.reachMode = REACHABLE;
 	}
 
 	// unions of both sets of initialization - used for try/finally
@@ -140,20 +138,6 @@
 		return this;
 	}
 
-	// Report an error if necessary
-	public boolean complainIfUnreachable(Statement statement, BlockScope scope, boolean didAlreadyComplain) {
-	
-		if ((this.reachMode & UNREACHABLE) != 0) {
-			statement.bits &= ~AstNode.IsReachableMASK;
-			boolean reported = this == DEAD_END;
-			if (!didAlreadyComplain && reported) {
-				scope.problemReporter().unreachableCode(statement);
-			}
-			return reported; // keep going for fake reachable
-		}
-		return false;
-	}
-	
 	/**
 	 * Answers a copy of the current instance
 	 */
@@ -176,7 +160,7 @@
 			int length;
 			System.arraycopy(this.extraDefiniteInits, 0, (copy.extraDefiniteInits = new long[ (length = extraDefiniteInits.length)]), 0, length);
 			System.arraycopy(this.extraPotentialInits, 0, (copy.extraPotentialInits = new long[length]), 0, length);
-		};
+		}
 		return copy;
 	}
 	
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java
index 6412e0a..3f6f83c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java
@@ -10,29 +10,34 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.impl;
 
+import org.eclipse.jdt.internal.compiler.util.Util;
+
 public class BooleanConstant extends Constant {
+
 	boolean value;
-
 	
-public BooleanConstant(boolean value) {
-	this.value = value;
-}
-public boolean booleanValue() {
-	return (boolean) value;
-}
-public String stringValue() {
-	//spec 15.17.11
-	
-	String s = new Boolean(value).toString() ;
-	if (s == null)
-		return "null"; //$NON-NLS-1$
-	else
-		return s;
-}
-public String toString(){
+	public BooleanConstant(boolean value) {
+		this.value = value;
+	}
 
-	return "(boolean)" + value ; } //$NON-NLS-1$
-public int typeID() {
-	return T_boolean;
-}
+	public boolean booleanValue() {
+		return value;
+	}
+
+	public String stringValue() {
+		//spec 15.17.11
+		String s = Util.toBoolean(value).toString();
+		if (s == null)
+			return "null"; //$NON-NLS-1$
+		else
+			return s;
+	}
+
+	public String toString(){
+		return "(boolean)" + value ;  //$NON-NLS-1$
+	}
+
+	public int typeID() {
+		return T_boolean;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java
index 223f6ad..f20b55b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java
@@ -16,25 +16,25 @@
 	this.value = value;
 }
 public byte byteValue() {
-	return (byte) value;
+	return this.value;
 }
 public char charValue() {
 	return (char) value;
 }
 public double doubleValue() {
-	return (double) value;
+	return value; // implicit cast to return type
 }
 public float floatValue() {
-	return (float) value;
+	return value; // implicit cast to return type
 }
 public int intValue() {
-	return (int) value;
+	return value; // implicit cast to return type
 }
 public long longValue() {
-	return (long) value;
+	return value; // implicit cast to return type
 }
 public short shortValue() {
-	return (short) value;
+	return value; // implicit cast to return type
 }
 public String stringValue() {
 	//spec 15.17.11
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CharConstant.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CharConstant.java
index fdbdb93..7218dd8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CharConstant.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CharConstant.java
@@ -11,44 +11,47 @@
 package org.eclipse.jdt.internal.compiler.impl;
 
 public class CharConstant extends Constant {
-	char value;
-public CharConstant(char value) {
-	this.value = value;
-}
-public byte byteValue() {
-	return (byte) value;
-}
-public char charValue() {
-	return (char) value;
-}
-public double doubleValue() {
-	return (double) value;
-}
-public float floatValue() {
-	return (float) value;
-}
-public int intValue() {
-	return (int) value;
-}
-public long longValue() {
-	return (long) value;
-}
-public short shortValue() {
-	return (short) value;
-}
-public String stringValue() {
-	//spec 15.17.11
-	
-	String s = new Character(value).toString() ;
-	if (s == null)
-		return "null"; //$NON-NLS-1$
-	else
-		return s;
-}
-public String toString(){
 
-	return "(char)" + value ; } //$NON-NLS-1$
-public int typeID() {
-	return T_char;
-}
+	char value;
+
+	public CharConstant(char value) {
+		this.value = value;
+	}
+	public byte byteValue() {
+		return (byte) value;
+	}
+	public char charValue() {
+		return this.value;
+	}
+	public double doubleValue() {
+		return value; // implicit cast to return type
+	}
+	public float floatValue() {
+		return value; // implicit cast to return type
+	}
+	public int intValue() {
+		return value; // implicit cast to return type
+	}
+	public long longValue() {
+		return value; // implicit cast to return type
+	}
+	public short shortValue() {
+		return (short) value;
+	}
+	public String stringValue() {
+		//spec 15.17.11
+		
+		String s = new Character(value).toString() ;
+		if (s == null)
+			return "null"; //$NON-NLS-1$
+		else
+			return s;
+	}
+	public String toString(){
+	
+		return "(char)" + value; //$NON-NLS-1$
+	}
+	public int typeID() {
+		return T_char;
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 4e3089d..453d234 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -13,16 +13,16 @@
 import java.io.ByteArrayInputStream;
 import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
-import java.util.Iterator;
+import java.util.HashMap;
 import java.util.Map;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 
-
-public class CompilerOptions implements ProblemReasons, ProblemSeverities {
+public class CompilerOptions implements ProblemReasons, ProblemSeverities, ClassFileConstants {
 	
 	/**
 	 * Option IDs
@@ -31,12 +31,11 @@
 	public static final String OPTION_LineNumberAttribute = "org.eclipse.jdt.core.compiler.debug.lineNumber"; //$NON-NLS-1$
 	public static final String OPTION_SourceFileAttribute = "org.eclipse.jdt.core.compiler.debug.sourceFile"; //$NON-NLS-1$
 	public static final String OPTION_PreserveUnusedLocal = "org.eclipse.jdt.core.compiler.codegen.unusedLocal"; //$NON-NLS-1$
-	public static final String OPTION_ReportUnreachableCode = "org.eclipse.jdt.core.compiler.problem.unreachableCode"; //$NON-NLS-1$
-	public static final String OPTION_ReportInvalidImport = "org.eclipse.jdt.core.compiler.problem.invalidImport"; //$NON-NLS-1$
 	public static final String OPTION_ReportMethodWithConstructorName = "org.eclipse.jdt.core.compiler.problem.methodWithConstructorName"; //$NON-NLS-1$
 	public static final String OPTION_ReportOverridingPackageDefaultMethod = "org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod"; //$NON-NLS-1$
 	public static final String OPTION_ReportDeprecation = "org.eclipse.jdt.core.compiler.problem.deprecation"; //$NON-NLS-1$
 	public static final String OPTION_ReportDeprecationInDeprecatedCode = "org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode"; //$NON-NLS-1$
+	public static final String OPTION_ReportDeprecationWhenOverridingDeprecatedMethod = "org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"; //$NON-NLS-1$
 	public static final String OPTION_ReportHiddenCatchBlock = "org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock"; //$NON-NLS-1$
 	public static final String OPTION_ReportUnusedLocal = "org.eclipse.jdt.core.compiler.problem.unusedLocal"; //$NON-NLS-1$
 	public static final String OPTION_ReportUnusedParameter = "org.eclipse.jdt.core.compiler.problem.unusedParameter"; //$NON-NLS-1$
@@ -45,20 +44,44 @@
 	public static final String OPTION_ReportUnusedImport = "org.eclipse.jdt.core.compiler.problem.unusedImport"; //$NON-NLS-1$
 	public static final String OPTION_ReportSyntheticAccessEmulation = "org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation"; //$NON-NLS-1$
 	public static final String OPTION_ReportNoEffectAssignment = "org.eclipse.jdt.core.compiler.problem.noEffectAssignment"; //$NON-NLS-1$
+	public static final String OPTION_ReportLocalVariableHiding = "org.eclipse.jdt.core.compiler.problem.localVariableHiding"; //$NON-NLS-1$
+	public static final String OPTION_ReportSpecialParameterHidingField = "org.eclipse.jdt.core.compiler.problem.specialParameterHidingField"; //$NON-NLS-1$
+	public static final String OPTION_ReportFieldHiding = "org.eclipse.jdt.core.compiler.problem.fieldHiding"; //$NON-NLS-1$
+	public static final String OPTION_ReportPossibleAccidentalBooleanAssignment = "org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment"; //$NON-NLS-1$
 	public static final String OPTION_ReportNonExternalizedStringLiteral = "org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral"; //$NON-NLS-1$
 	public static final String OPTION_ReportIncompatibleNonInheritedInterfaceMethod = "org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod"; //$NON-NLS-1$
 	public static final String OPTION_ReportUnusedPrivateMember = "org.eclipse.jdt.core.compiler.problem.unusedPrivateMember"; //$NON-NLS-1$
 	public static final String OPTION_ReportNoImplicitStringConversion = "org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion"; //$NON-NLS-1$
+	public static final String OPTION_ReportAssertIdentifier = "org.eclipse.jdt.core.compiler.problem.assertIdentifier"; //$NON-NLS-1$
+	public static final String OPTION_ReportNonStaticAccessToStatic = "org.eclipse.jdt.core.compiler.problem.staticAccessReceiver"; //$NON-NLS-1$
+	public static final String OPTION_ReportIndirectStaticAccess = "org.eclipse.jdt.core.compiler.problem.indirectStaticAccess"; //$NON-NLS-1$
+	public static final String OPTION_ReportSuperfluousSemicolon = "org.eclipse.jdt.core.compiler.problem.superfluousSemicolon"; //$NON-NLS-1$
+	public static final String OPTION_ReportUnnecessaryTypeCheck = "org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck"; //$NON-NLS-1$
+	public static final String OPTION_ReportUndocumentedEmptyBlock = "org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock"; //$NON-NLS-1$
+	public static final String OPTION_ReportInvalidJavadoc = "org.eclipse.jdt.core.compiler.problem.invalidJavadoc"; //$NON-NLS-1$
+	public static final String OPTION_ReportInvalidJavadocTags = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTags"; //$NON-NLS-1$
+	public static final String OPTION_ReportInvalidJavadocTagsVisibility = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility"; //$NON-NLS-1$
+	public static final String OPTION_ReportMissingJavadocTags = "org.eclipse.jdt.core.compiler.problem.missingJavadocTags"; //$NON-NLS-1$
+	public static final String OPTION_ReportMissingJavadocTagsVisibility = "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility"; //$NON-NLS-1$
+	public static final String OPTION_ReportMissingJavadocTagsOverriding = "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding"; //$NON-NLS-1$
+	public static final String OPTION_ReportMissingJavadocComments = "org.eclipse.jdt.core.compiler.problem.missingJavadocComments"; //$NON-NLS-1$
+	public static final String OPTION_ReportMissingJavadocCommentsVisibility = "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility"; //$NON-NLS-1$
+	public static final String OPTION_ReportMissingJavadocCommentsOverriding = "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding"; //$NON-NLS-1$
+	public static final String OPTION_ReportFinallyBlockNotCompletingNormally = "org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally"; //$NON-NLS-1$
+	public static final String OPTION_ReportUnusedDeclaredThrownException = "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException"; //$NON-NLS-1$
+	public static final String OPTION_ReportUnqualifiedFieldAccess = "org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess"; //$NON-NLS-1$
 	public static final String OPTION_Source = "org.eclipse.jdt.core.compiler.source"; //$NON-NLS-1$
 	public static final String OPTION_TargetPlatform = "org.eclipse.jdt.core.compiler.codegen.targetPlatform"; //$NON-NLS-1$
-	public static final String OPTION_ReportAssertIdentifier = "org.eclipse.jdt.core.compiler.problem.assertIdentifier"; //$NON-NLS-1$
 	public static final String OPTION_Compliance = "org.eclipse.jdt.core.compiler.compliance"; //$NON-NLS-1$
 	public static final String OPTION_Encoding = "org.eclipse.jdt.core.encoding"; //$NON-NLS-1$
 	public static final String OPTION_MaxProblemPerUnit = "org.eclipse.jdt.core.compiler.maxProblemPerUnit"; //$NON-NLS-1$
-	public static final String OPTION_ReportStaticAccessReceiver = "org.eclipse.jdt.core.compiler.problem.staticAccessReceiver"; //$NON-NLS-1$
 	public static final String OPTION_TaskTags = "org.eclipse.jdt.core.compiler.taskTags"; //$NON-NLS-1$
 	public static final String OPTION_TaskPriorities = "org.eclipse.jdt.core.compiler.taskPriorities"; //$NON-NLS-1$
-
+	
+	// Backward compatibility
+	public static final String OPTION_ReportInvalidAnnotation = "org.eclipse.jdt.core.compiler.problem.invalidAnnotation"; //$NON-NLS-1$
+	public static final String OPTION_ReportMissingAnnotation = "org.eclipse.jdt.core.compiler.problem.missingAnnotation"; //$NON-NLS-1$
+	public static final String OPTION_ReportMissingJavadoc = "org.eclipse.jdt.core.compiler.problem.missingJavadoc"; //$NON-NLS-1$
 
 	/* should surface ??? */
 	public static final String OPTION_PrivateConstructorAccess = "org.eclipse.jdt.core.compiler.codegen.constructorAccessEmulation"; //$NON-NLS-1$
@@ -74,47 +97,69 @@
 	public static final String VERSION_1_2 = "1.2"; //$NON-NLS-1$
 	public static final String VERSION_1_3 = "1.3"; //$NON-NLS-1$
 	public static final String VERSION_1_4 = "1.4"; //$NON-NLS-1$
+	public static final String VERSION_1_5 = "1.5"; //$NON-NLS-1$
 	public static final String ERROR = "error"; //$NON-NLS-1$
 	public static final String WARNING = "warning"; //$NON-NLS-1$
 	public static final String IGNORE = "ignore"; //$NON-NLS-1$
 	public static final String ENABLED = "enabled"; //$NON-NLS-1$
 	public static final String DISABLED = "disabled"; //$NON-NLS-1$
+	public static final String PUBLIC = "public";	//$NON-NLS-1$
+	public static final String PROTECTED = "protected";	//$NON-NLS-1$
+	public static final String DEFAULT = "default";	//$NON-NLS-1$
+	public static final String PRIVATE = "private";	//$NON-NLS-1$
 	
 	/**
 	 * Bit mask for configurable problems (error/warning threshold)
 	 */
-	public static final int UnreachableCode = 0x100;
-	public static final int ImportProblem = 0x400;
-	public static final int MethodWithConstructorName = 0x1000;
-	public static final int OverriddenPackageDefaultMethod = 0x2000;
-	public static final int UsingDeprecatedAPI = 0x4000;
-	public static final int MaskedCatchBlock = 0x8000;
-	public static final int UnusedLocalVariable = 0x10000;
-	public static final int UnusedArgument = 0x20000;
-	public static final int NoImplicitStringConversion = 0x40000;
-	public static final int AccessEmulation = 0x80000;
-	public static final int NonExternalizedString = 0x100000;
-	public static final int AssertUsedAsAnIdentifier = 0x200000;
-	public static final int UnusedImport = 0x400000;
-	public static final int StaticAccessReceiver = 0x800000;
-	public static final int Task = 0x1000000;
-	public static final int NoEffectAssignment = 0x2000000;
-	public static final int IncompatibleNonInheritedInterfaceMethod = 0x4000000;
-	public static final int UnusedPrivateMember = 0x8000000;
-	
+	// 0x100L unused
+	// 0x200L unused
+	// 0x400L unused
+	// 0x800L unused
+	public static final long MethodWithConstructorName = 0x1000L;
+	public static final long OverriddenPackageDefaultMethod = 0x2000L;
+	public static final long UsingDeprecatedAPI = 0x4000L;
+	public static final long MaskedCatchBlock = 0x8000L;
+	public static final long UnusedLocalVariable = 0x10000L;
+	public static final long UnusedArgument = 0x20000L;
+	public static final long NoImplicitStringConversion = 0x40000L;
+	public static final long AccessEmulation = 0x80000L;
+	public static final long NonExternalizedString = 0x100000L;
+	public static final long AssertUsedAsAnIdentifier = 0x200000L;
+	public static final long UnusedImport = 0x400000L;
+	public static final long NonStaticAccessToStatic = 0x800000L;
+	public static final long Task = 0x1000000L;
+	public static final long NoEffectAssignment = 0x2000000L;
+	public static final long IncompatibleNonInheritedInterfaceMethod = 0x4000000L;
+	public static final long UnusedPrivateMember = 0x8000000L;
+	public static final long LocalVariableHiding = 0x10000000L;
+	public static final long FieldHiding = 0x20000000L;
+	public static final long AccidentalBooleanAssign = 0x40000000L;
+	public static final long SuperfluousSemicolon = 0x80000000L;
+	public static final long IndirectStaticAccess = 0x100000000L;
+	public static final long UndocumentedEmptyBlock = 0x200000000L;
+	public static final long UnnecessaryTypeCheck = 0x400000000L;
+	public static final long InvalidJavadoc = 0x800000000L;
+	public static final long FinallyBlockNotCompleting = 0x1000000000L;
+	public static final long UnusedDeclaredThrownException = 0x2000000000L;
+	public static final long UnqualifiedFieldAccess = 0x4000000000L;
+	public static final long MissingJavadocTags = 0x8000000000L;
+	public static final long MissingJavadocComments  = 0x10000000000L;
+
 	// Default severity level for handlers
-	public int errorThreshold = 
-		UnreachableCode 
-		| ImportProblem;
+	public long errorThreshold = 0;
 		
-	public int warningThreshold = 
+	public long warningThreshold = 
 		MethodWithConstructorName 
-		| OverriddenPackageDefaultMethod
 		| UsingDeprecatedAPI 
 		| MaskedCatchBlock 
-		| AssertUsedAsAnIdentifier 
+		| OverriddenPackageDefaultMethod
+		| UnusedImport
+		| NonStaticAccessToStatic
+		| NoEffectAssignment
+		| IncompatibleNonInheritedInterfaceMethod
 		| NoImplicitStringConversion
-		| IncompatibleNonInheritedInterfaceMethod;
+		| FinallyBlockNotCompleting
+		| AssertUsedAsAnIdentifier;
 
 	// Debug attributes
 	public static final int Source = 1; // SourceFileAttribute
@@ -124,20 +169,12 @@
 	// By default only lines and source attributes are generated.
 	public int produceDebugAttributes = Lines | Source;
 
-	// JDK 1.1, 1.2, 1.3 or 1.4
-	public static final int JDK1_1 = 0;
-	public static final int JDK1_2 = 1;
-	public static final int JDK1_3 = 2;
-	public static final int JDK1_4 = 3;
-	
-	public int targetJDK = JDK1_1; // default generates for JVM1.1
-	public int complianceLevel = JDK1_3; // by default be compliant with 1.3
+	public long complianceLevel = JDK1_4; // by default be compliant with 1.4
+	public long sourceLevel = JDK1_3; //1.3 source behavior by default
+	public long targetJDK = JDK1_2; // default generates for JVM1.2
 
 	// toggle private access emulation for 1.2 (constr. accessor has extra arg on constructor) or 1.3 (make private constructor default access when access needed)
 	public boolean isPrivateConstructorAccessChangingVisibility = false; // by default, follows 1.2
-
-	// 1.4 feature (assertions are available in source 1.4 mode only)
-	public int sourceLevel = JDK1_3; //1.3 behavior by default
 	
 	// source encoding format
 	public String defaultEncoding = null; // will use the platform default encoding
@@ -154,9 +191,6 @@
 	// indicates whether literal expressions are inlined at parse-time or not
 	public boolean parseLiteralExpressionsAsConstants = true;
 
-	// exception raised for unresolved compile errors
-	public String runtimeExceptionNameForCompileError = "java.lang.Error"; //$NON-NLS-1$
-
 	// max problems per compilation unit
 	public int maxProblemsPerUnit = 100; // no more than 100 problems per default
 	
@@ -168,641 +202,453 @@
 
 	// deprecation report
 	public boolean reportDeprecationInsideDeprecatedCode = false;
+	public boolean reportDeprecationWhenOverridingDeprecatedMethod = false;
 	
 	// unused parameters report
 	public boolean reportUnusedParameterWhenImplementingAbstract = false;
 	public boolean reportUnusedParameterWhenOverridingConcrete = false;
+
+	// constructor/setter parameter hiding
+	public boolean reportSpecialParameterHidingField = false;
+
+	// check javadoc comments
+	public int reportInvalidJavadocTagsVisibility = AccPrivate; 
+	public boolean reportInvalidJavadocTags = true; 
+
+	// check missing javadoc tags
+	public int reportMissingJavadocTagsVisibility = AccPrivate; 
+	public boolean reportMissingJavadocTagsOverriding = true;
+
+	// check missing javadoc comments
+	public int reportMissingJavadocCommentsVisibility = AccPublic; 
+	public boolean reportMissingJavadocCommentsOverriding = true; 
 	
 	/** 
 	 * Initializing the compiler options with defaults
 	 */
 	public CompilerOptions(){
+		// use default options
 	}
 
 	/** 
 	 * Initializing the compiler options with external settings
+	 * @param settings
 	 */
 	public CompilerOptions(Map settings){
 
 		if (settings == null) return;
-		
-		// filter options which are related to the compiler component
-		Iterator entries = settings.entrySet().iterator();
-		while (entries.hasNext()) {
-			Map.Entry entry = (Map.Entry)entries.next();
-			if (!(entry.getKey() instanceof String)) continue;
-			if (!(entry.getValue() instanceof String)) continue;
-			String optionID = (String) entry.getKey();
-			String optionValue = (String) entry.getValue();
-			
-			// Local variable attribute
-			if(optionID.equals(OPTION_LocalVariableAttribute)){
-				if (optionValue.equals(GENERATE)) {
-					this.produceDebugAttributes |= Vars;
-				} else if (optionValue.equals(DO_NOT_GENERATE)){
-					this.produceDebugAttributes &= ~Vars;
-				}
-				continue;
-			}  
-			// Line number attribute	
-			if(optionID.equals(OPTION_LineNumberAttribute)) {
-				if (optionValue.equals(GENERATE)) {
-					this.produceDebugAttributes |= Lines;
-				} else if (optionValue.equals(DO_NOT_GENERATE)) {
-					this.produceDebugAttributes &= ~Lines;
-				}
-				continue;
-			} 
-			// Source file attribute	
-			if(optionID.equals(OPTION_SourceFileAttribute)) {
-				if (optionValue.equals(GENERATE)) {
-					this.produceDebugAttributes |= Source;
-				} else if (optionValue.equals(DO_NOT_GENERATE)) {
-					this.produceDebugAttributes &= ~Source;
-				}
-				continue;
-			} 
-			// Preserve unused local	
-			if(optionID.equals(OPTION_PreserveUnusedLocal)){
-				if (optionValue.equals(PRESERVE)) {
-					this.preserveAllLocalVariables = true;
-				} else if (optionValue.equals(OPTIMIZE_OUT)) {
-					this.preserveAllLocalVariables = false;
-				}
-				continue;
-			} 
-			// Report unreachable code				
-			if(optionID.equals(OPTION_ReportUnreachableCode)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= UnreachableCode;
-					this.warningThreshold &= ~UnreachableCode;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~UnreachableCode;
-					this.warningThreshold |= UnreachableCode;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~UnreachableCode;
-					this.warningThreshold &= ~UnreachableCode;
-				}
-				continue;
-			} 
-			// Report invalid import	
-			if(optionID.equals(OPTION_ReportInvalidImport)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= ImportProblem;
-					this.warningThreshold &= ~ImportProblem;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~ImportProblem;
-					this.warningThreshold |= ImportProblem;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~ImportProblem;
-					this.warningThreshold &= ~ImportProblem;
-				}
-				continue;
-			} 
-			// Define the target JDK tag for .classfiles
-			if(optionID.equals(OPTION_TargetPlatform)){
-				if (optionValue.equals(VERSION_1_1)) {
-					this.targetJDK = JDK1_1;
-				} else if (optionValue.equals(VERSION_1_2)) {
-					this.targetJDK = JDK1_2;
-				} else if (optionValue.equals(VERSION_1_3)) {
-					this.targetJDK = JDK1_3;
-				} else if (optionValue.equals(VERSION_1_4)) {
-					this.targetJDK = JDK1_4;
-				}
-				continue;
-			} 
-			// Define the JDK compliance level
-			if(optionID.equals(OPTION_Compliance)){
-				if (optionValue.equals(VERSION_1_1)) {
-					this.complianceLevel = JDK1_1;
-				} else if (optionValue.equals(VERSION_1_2)) {
-					this.complianceLevel = JDK1_2;
-				} else if (optionValue.equals(VERSION_1_3)) {
-					this.complianceLevel = JDK1_3;
-				} else if (optionValue.equals(VERSION_1_4)) {
-					this.complianceLevel = JDK1_4;
-				}
-				continue;
-			} 
-			// Private constructor access emulation (extra arg vs. visibility change)
-			if(optionID.equals(OPTION_PrivateConstructorAccess)){
-				if (optionValue.equals(VERSION_1_1)) {
-					this.isPrivateConstructorAccessChangingVisibility = false;
-				} else if (optionValue.equals(VERSION_1_2)) {
-					this.isPrivateConstructorAccessChangingVisibility = false;
-				} else if (optionValue.equals(VERSION_1_3)) {
-					this.isPrivateConstructorAccessChangingVisibility = true;
-				} else if (optionValue.equals(VERSION_1_4)) {
-					this.isPrivateConstructorAccessChangingVisibility = true;
-				}
-				continue;
-			} 
-			// Report method with constructor name
-			if(optionID.equals(OPTION_ReportMethodWithConstructorName)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= MethodWithConstructorName;
-					this.warningThreshold &= ~MethodWithConstructorName;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~MethodWithConstructorName;
-					this.warningThreshold |= MethodWithConstructorName;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~MethodWithConstructorName;
-					this.warningThreshold &= ~MethodWithConstructorName;
-				}
-				continue;
-			} 
-			// Report overriding package default method
-			if(optionID.equals(OPTION_ReportOverridingPackageDefaultMethod)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= OverriddenPackageDefaultMethod;
-					this.warningThreshold &= ~OverriddenPackageDefaultMethod;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~OverriddenPackageDefaultMethod;
-					this.warningThreshold |= OverriddenPackageDefaultMethod;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~OverriddenPackageDefaultMethod;
-					this.warningThreshold &= ~OverriddenPackageDefaultMethod;
-				}
-				continue;
-			} 
-			// Report deprecation
-			if(optionID.equals(OPTION_ReportDeprecation)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= UsingDeprecatedAPI;
-					this.warningThreshold &= ~UsingDeprecatedAPI;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~UsingDeprecatedAPI;
-					this.warningThreshold |= UsingDeprecatedAPI;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~UsingDeprecatedAPI;
-					this.warningThreshold &= ~UsingDeprecatedAPI;
-				}
-				continue;
-			} 
-			// Report deprecation inside deprecated code 
-			if(optionID.equals(OPTION_ReportDeprecationInDeprecatedCode)){
-				if (optionValue.equals(ENABLED)) {
-					this.reportDeprecationInsideDeprecatedCode = true;
-				} else if (optionValue.equals(DISABLED)) {
-					this.reportDeprecationInsideDeprecatedCode = false;
-				}
-				continue;
-			} 
-			// Report hidden catch block
-			if(optionID.equals(OPTION_ReportHiddenCatchBlock)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= MaskedCatchBlock;
-					this.warningThreshold &= ~MaskedCatchBlock;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~MaskedCatchBlock;
-					this.warningThreshold |= MaskedCatchBlock;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~MaskedCatchBlock;
-					this.warningThreshold &= ~MaskedCatchBlock;
-				}
-				continue;
-			} 
-			// Report unused local variable
-			if(optionID.equals(OPTION_ReportUnusedLocal)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= UnusedLocalVariable;
-					this.warningThreshold &= ~UnusedLocalVariable;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~UnusedLocalVariable;
-					this.warningThreshold |= UnusedLocalVariable;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~UnusedLocalVariable;
-					this.warningThreshold &= ~UnusedLocalVariable;
-				}
-				continue;
-			}
-			// Report no implicit String conversion
-			if (optionID.equals(OPTION_ReportNoImplicitStringConversion)) {
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= NoImplicitStringConversion;
-					this.warningThreshold &= ~NoImplicitStringConversion;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~NoImplicitStringConversion;
-					this.warningThreshold |= NoImplicitStringConversion;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~NoImplicitStringConversion;
-					this.warningThreshold &= ~NoImplicitStringConversion;
-				}
-				continue;
-			}
-			// Report unused parameter
-			if(optionID.equals(OPTION_ReportUnusedParameter)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= UnusedArgument;
-					this.warningThreshold &= ~UnusedArgument;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~UnusedArgument;
-					this.warningThreshold |= UnusedArgument;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~UnusedArgument;
-					this.warningThreshold &= ~UnusedArgument;
-				}
-				continue;
-			} 
-			// Report unused parameter when implementing abstract method 
-			if(optionID.equals(OPTION_ReportUnusedParameterWhenImplementingAbstract)){
-				if (optionValue.equals(ENABLED)) {
-					this.reportUnusedParameterWhenImplementingAbstract = true;
-				} else if (optionValue.equals(DISABLED)) {
-					this.reportUnusedParameterWhenImplementingAbstract = false;
-				}
-				continue;
-			} 
-			// Report unused parameter when implementing abstract method 
-			if(optionID.equals(OPTION_ReportUnusedParameterWhenOverridingConcrete)){
-				if (optionValue.equals(ENABLED)) {
-					this.reportUnusedParameterWhenOverridingConcrete = true;
-				} else if (optionValue.equals(DISABLED)) {
-					this.reportUnusedParameterWhenOverridingConcrete = false;
-				}
-				continue;
-			} 
-			// Report unused import
-			if(optionID.equals(OPTION_ReportUnusedImport)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= UnusedImport;
-					this.warningThreshold &= ~UnusedImport;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~UnusedImport;
-					this.warningThreshold |= UnusedImport;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~UnusedImport;
-					this.warningThreshold &= ~UnusedImport;
-				}
-				continue;
-			} 
-			// Report synthetic access emulation
-			if(optionID.equals(OPTION_ReportSyntheticAccessEmulation)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= AccessEmulation;
-					this.warningThreshold &= ~AccessEmulation;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~AccessEmulation;
-					this.warningThreshold |= AccessEmulation;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~AccessEmulation;
-					this.warningThreshold &= ~AccessEmulation;
-				}
-				continue;
-			}
-			// Report non-externalized string literals
-			if(optionID.equals(OPTION_ReportNonExternalizedStringLiteral)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= NonExternalizedString;
-					this.warningThreshold &= ~NonExternalizedString;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~NonExternalizedString;
-					this.warningThreshold |= NonExternalizedString;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~NonExternalizedString;
-					this.warningThreshold &= ~NonExternalizedString;
-				}
-				continue;
-			}
-			// Report usage of 'assert' as an identifier
-			if(optionID.equals(OPTION_ReportAssertIdentifier)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= AssertUsedAsAnIdentifier;
-					this.warningThreshold &= ~AssertUsedAsAnIdentifier;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~AssertUsedAsAnIdentifier;
-					this.warningThreshold |= AssertUsedAsAnIdentifier;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~AssertUsedAsAnIdentifier;
-					this.warningThreshold &= ~AssertUsedAsAnIdentifier;
-				}
-				continue;
-			}
-			// Set the source compatibility mode (assertions)
-			if(optionID.equals(OPTION_Source)){
-				if (optionValue.equals(VERSION_1_3)) {
-					this.sourceLevel = JDK1_3;
-				} else if (optionValue.equals(VERSION_1_4)) {
-					this.sourceLevel = JDK1_4;
-				}
-				continue;
-			}
-			// Set the default encoding format
-			if(optionID.equals(OPTION_Encoding)){
-				if (optionValue.length() == 0){
-					this.defaultEncoding = null;
-				} else {
-					try { // ignore unsupported encoding
-						new InputStreamReader(new ByteArrayInputStream(new byte[0]), optionValue);
-						this.defaultEncoding = optionValue;
-					} catch(UnsupportedEncodingException e){
-					}
-				}
-				continue;
-			}
-			// Set the threshold for problems per unit
-			if(optionID.equals(OPTION_MaxProblemPerUnit)){
-				try {
-					int val = Integer.parseInt(optionValue);
-					if (val >= 0) this.maxProblemsPerUnit = val;
-				} catch(NumberFormatException e){
-				}				
-				continue;
-			}
-			// Report unnecessary receiver for static access
-			if(optionID.equals(OPTION_ReportStaticAccessReceiver)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= StaticAccessReceiver;
-					this.warningThreshold &= ~StaticAccessReceiver;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~StaticAccessReceiver;
-					this.warningThreshold |= StaticAccessReceiver;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~StaticAccessReceiver;
-					this.warningThreshold &= ~StaticAccessReceiver;
-				}
-				continue;
-			} 
-			// Report interface method incompatible with non-inherited Object method
-			if(optionID.equals(OPTION_ReportIncompatibleNonInheritedInterfaceMethod)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= IncompatibleNonInheritedInterfaceMethod;
-					this.warningThreshold &= ~IncompatibleNonInheritedInterfaceMethod;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~IncompatibleNonInheritedInterfaceMethod;
-					this.warningThreshold |= IncompatibleNonInheritedInterfaceMethod;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~IncompatibleNonInheritedInterfaceMethod;
-					this.warningThreshold &= ~IncompatibleNonInheritedInterfaceMethod;
-				}
-				continue;
-			} 
-			// Report unused private members
-			if(optionID.equals(OPTION_ReportUnusedPrivateMember)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= UnusedPrivateMember;
-					this.warningThreshold &= ~UnusedPrivateMember;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~UnusedPrivateMember;
-					this.warningThreshold |= UnusedPrivateMember;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~UnusedPrivateMember;
-					this.warningThreshold &= ~UnusedPrivateMember;
-				}
-				continue;
-			} 
-			// Report task
-			if(optionID.equals(OPTION_TaskTags)){
-				if (optionValue.length() == 0) {
-					this.taskTags = null;
-				} else {
-					this.taskTags = CharOperation.splitAndTrimOn(',', optionValue.toCharArray());
-				}
-				continue;
-			} 
-			// Report no-op assignments
-			if(optionID.equals(OPTION_ReportNoEffectAssignment)){
-				if (optionValue.equals(ERROR)) {
-					this.errorThreshold |= NoEffectAssignment;
-					this.warningThreshold &= ~NoEffectAssignment;
-				} else if (optionValue.equals(WARNING)) {
-					this.errorThreshold &= ~NoEffectAssignment;
-					this.warningThreshold |= NoEffectAssignment;
-				} else if (optionValue.equals(IGNORE)) {
-					this.errorThreshold &= ~NoEffectAssignment;
-					this.warningThreshold &= ~NoEffectAssignment;
-				}
-				continue;
-			}
-			if(optionID.equals(OPTION_TaskPriorities)){
-				if (optionValue.length() == 0) {
-					this.taskPriorites = null;
-				} else {
-					this.taskPriorites = CharOperation.splitAndTrimOn(',', optionValue.toCharArray());
-				}
-				continue;
-			} 
+		set(settings);		
+	}
+
+	public Map getMap() {
+		Map optionsMap = new HashMap(30);
+		optionsMap.put(OPTION_LocalVariableAttribute, (this.produceDebugAttributes & Vars) != 0 ? GENERATE : DO_NOT_GENERATE); 
+		optionsMap.put(OPTION_LineNumberAttribute, (this.produceDebugAttributes & Lines) != 0 ? GENERATE : DO_NOT_GENERATE);
+		optionsMap.put(OPTION_SourceFileAttribute, (this.produceDebugAttributes & Source) != 0 ? GENERATE : DO_NOT_GENERATE);
+		optionsMap.put(OPTION_PreserveUnusedLocal, this.preserveAllLocalVariables ? PRESERVE : OPTIMIZE_OUT);
+		optionsMap.put(OPTION_ReportMethodWithConstructorName, getSeverityString(MethodWithConstructorName)); 
+		optionsMap.put(OPTION_ReportOverridingPackageDefaultMethod, getSeverityString(OverriddenPackageDefaultMethod)); 
+		optionsMap.put(OPTION_ReportDeprecation, getSeverityString(UsingDeprecatedAPI)); 
+		optionsMap.put(OPTION_ReportDeprecationInDeprecatedCode, this.reportDeprecationInsideDeprecatedCode ? ENABLED : DISABLED); 
+		optionsMap.put(OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, this.reportDeprecationWhenOverridingDeprecatedMethod ? ENABLED : DISABLED); 
+		optionsMap.put(OPTION_ReportHiddenCatchBlock, getSeverityString(MaskedCatchBlock)); 
+		optionsMap.put(OPTION_ReportUnusedLocal, getSeverityString(UnusedLocalVariable)); 
+		optionsMap.put(OPTION_ReportUnusedParameter, getSeverityString(UnusedArgument)); 
+		optionsMap.put(OPTION_ReportUnusedImport, getSeverityString(UnusedImport)); 
+		optionsMap.put(OPTION_ReportSyntheticAccessEmulation, getSeverityString(AccessEmulation)); 
+		optionsMap.put(OPTION_ReportNoEffectAssignment, getSeverityString(NoEffectAssignment)); 
+		optionsMap.put(OPTION_ReportNonExternalizedStringLiteral, getSeverityString(NonExternalizedString)); 
+		optionsMap.put(OPTION_ReportNoImplicitStringConversion, getSeverityString(NoImplicitStringConversion)); 
+		optionsMap.put(OPTION_ReportNonStaticAccessToStatic, getSeverityString(NonStaticAccessToStatic)); 
+		optionsMap.put(OPTION_ReportIndirectStaticAccess, getSeverityString(IndirectStaticAccess)); 
+		optionsMap.put(OPTION_ReportIncompatibleNonInheritedInterfaceMethod, getSeverityString(IncompatibleNonInheritedInterfaceMethod)); 
+		optionsMap.put(OPTION_ReportUnusedPrivateMember, getSeverityString(UnusedPrivateMember)); 
+		optionsMap.put(OPTION_ReportLocalVariableHiding, getSeverityString(LocalVariableHiding)); 
+		optionsMap.put(OPTION_ReportFieldHiding, getSeverityString(FieldHiding)); 
+		optionsMap.put(OPTION_ReportPossibleAccidentalBooleanAssignment, getSeverityString(AccidentalBooleanAssign)); 
+		optionsMap.put(OPTION_ReportSuperfluousSemicolon, getSeverityString(SuperfluousSemicolon)); 
+		optionsMap.put(OPTION_ReportAssertIdentifier, getSeverityString(AssertUsedAsAnIdentifier)); 
+		optionsMap.put(OPTION_ReportUndocumentedEmptyBlock, getSeverityString(UndocumentedEmptyBlock)); 
+		optionsMap.put(OPTION_ReportUnnecessaryTypeCheck, getSeverityString(UnnecessaryTypeCheck)); 
+		optionsMap.put(OPTION_ReportInvalidJavadoc, getSeverityString(InvalidJavadoc));
+		optionsMap.put(OPTION_ReportInvalidJavadocTagsVisibility, getVisibilityString(this.reportInvalidJavadocTagsVisibility));
+		optionsMap.put(OPTION_ReportInvalidJavadocTags, this.reportInvalidJavadocTags? ENABLED : DISABLED);
+		optionsMap.put(OPTION_ReportMissingJavadocTags, getSeverityString(MissingJavadocTags));
+		optionsMap.put(OPTION_ReportMissingJavadocTagsVisibility, getVisibilityString(this.reportMissingJavadocTagsVisibility));
+		optionsMap.put(OPTION_ReportMissingJavadocTagsOverriding, this.reportMissingJavadocTagsOverriding ? ENABLED : DISABLED);
+		optionsMap.put(OPTION_ReportMissingJavadocComments, getSeverityString(MissingJavadocComments));
+		optionsMap.put(OPTION_ReportMissingJavadocCommentsVisibility, getVisibilityString(this.reportMissingJavadocCommentsVisibility));
+		optionsMap.put(OPTION_ReportMissingJavadocCommentsOverriding, this.reportMissingJavadocCommentsOverriding ? ENABLED : DISABLED);
+		optionsMap.put(OPTION_ReportFinallyBlockNotCompletingNormally, getSeverityString(FinallyBlockNotCompleting));
+		optionsMap.put(OPTION_ReportUnusedDeclaredThrownException, getSeverityString(UnusedDeclaredThrownException));
+		optionsMap.put(OPTION_ReportUnqualifiedFieldAccess, getSeverityString(UnqualifiedFieldAccess));
+		optionsMap.put(OPTION_Compliance, versionFromJdkLevel(this.complianceLevel)); 
+		optionsMap.put(OPTION_Source, versionFromJdkLevel(this.sourceLevel)); 
+		optionsMap.put(OPTION_TargetPlatform, versionFromJdkLevel(this.targetJDK)); 
+		if (this.defaultEncoding != null) {
+			optionsMap.put(OPTION_Encoding, this.defaultEncoding); 
 		}
+		optionsMap.put(OPTION_TaskTags, this.taskTags == null ? "" : new String(CharOperation.concatWith(this.taskTags,','))); //$NON-NLS-1$
+		optionsMap.put(OPTION_TaskPriorities, this.taskPriorites == null ? "" : new String(CharOperation.concatWith(this.taskPriorites,','))); //$NON-NLS-1$
+		optionsMap.put(OPTION_ReportUnusedParameterWhenImplementingAbstract, this.reportUnusedParameterWhenImplementingAbstract ? ENABLED : DISABLED); 
+		optionsMap.put(OPTION_ReportUnusedParameterWhenOverridingConcrete, this.reportUnusedParameterWhenOverridingConcrete ? ENABLED : DISABLED); 
+		optionsMap.put(OPTION_ReportSpecialParameterHidingField, this.reportSpecialParameterHidingField ? ENABLED : DISABLED); 
+		optionsMap.put(OPTION_MaxProblemPerUnit, String.valueOf(this.maxProblemsPerUnit));
+
+		return optionsMap;		
 	}
 	
-	public int getSeverity(int irritant) {
-		if((warningThreshold & irritant) != 0)
+	public int getSeverity(long irritant) {
+		if((this.warningThreshold & irritant) != 0)
 			return Warning;
-		if((errorThreshold & irritant) != 0)
+		if((this.errorThreshold & irritant) != 0)
 			return Error;
 		return Ignore;
 	}
 
+	public String getSeverityString(long irritant) {
+		if((this.warningThreshold & irritant) != 0)
+			return WARNING;
+		if((this.errorThreshold & irritant) != 0)
+			return ERROR;
+		return IGNORE;
+	}
+	
+	public String getVisibilityString(int level) {
+		switch (level) {
+			case AccPublic:
+				return PUBLIC;
+			case AccProtected:
+				return PROTECTED;
+			case AccPrivate:
+				return PRIVATE;
+			default:
+				return DEFAULT;
+		}
+	}
+	
 	public void produceReferenceInfo(boolean flag) {
 		this.produceReferenceInfo = flag;
 	}
 
+	public void set(Map optionsMap) {
+
+		Object optionValue;
+		if ((optionValue = optionsMap.get(OPTION_LocalVariableAttribute)) != null) {
+			if (GENERATE.equals(optionValue)) {
+				this.produceDebugAttributes |= Vars;
+			} else if (DO_NOT_GENERATE.equals(optionValue)) {
+				this.produceDebugAttributes &= ~Vars;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_LineNumberAttribute)) != null) {
+			if (GENERATE.equals(optionValue)) {
+				this.produceDebugAttributes |= Lines;
+			} else if (DO_NOT_GENERATE.equals(optionValue)) {
+				this.produceDebugAttributes &= ~Lines;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_SourceFileAttribute)) != null) {
+			if (GENERATE.equals(optionValue)) {
+				this.produceDebugAttributes |= Source;
+			} else if (DO_NOT_GENERATE.equals(optionValue)) {
+				this.produceDebugAttributes &= ~Source;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_PreserveUnusedLocal)) != null) {
+			if (PRESERVE.equals(optionValue)) {
+				this.preserveAllLocalVariables = true;
+			} else if (OPTIMIZE_OUT.equals(optionValue)) {
+				this.preserveAllLocalVariables = false;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportDeprecationInDeprecatedCode)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.reportDeprecationInsideDeprecatedCode = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.reportDeprecationInsideDeprecatedCode = false;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportDeprecationWhenOverridingDeprecatedMethod)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.reportDeprecationWhenOverridingDeprecatedMethod = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.reportDeprecationWhenOverridingDeprecatedMethod = false;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_Compliance)) != null) {
+			long level = versionToJdkLevel(optionValue);
+			if (level != 0) this.complianceLevel = level;
+		}
+		if ((optionValue = optionsMap.get(OPTION_Source)) != null) {
+			long level = versionToJdkLevel(optionValue);
+			if (level != 0) this.sourceLevel = level;
+		}
+		if ((optionValue = optionsMap.get(OPTION_TargetPlatform)) != null) {
+			long level = versionToJdkLevel(optionValue);
+			if (level != 0) this.targetJDK = level;
+		}
+		if ((optionValue = optionsMap.get(OPTION_Encoding)) != null) {
+			if (optionValue instanceof String) {
+				this.defaultEncoding = null;
+				String stringValue = (String) optionValue;
+				if (stringValue.length() > 0){
+					try { 
+						new InputStreamReader(new ByteArrayInputStream(new byte[0]), stringValue);
+						this.defaultEncoding = stringValue;
+					} catch(UnsupportedEncodingException e){
+						// ignore unsupported encoding
+					}
+				}
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_PrivateConstructorAccess)) != null) {
+			long level = versionToJdkLevel(optionValue);
+			if (level >= JDK1_3) this.isPrivateConstructorAccessChangingVisibility = true;
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameterWhenImplementingAbstract)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.reportUnusedParameterWhenImplementingAbstract = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.reportUnusedParameterWhenImplementingAbstract = false;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameterWhenOverridingConcrete)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.reportUnusedParameterWhenOverridingConcrete = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.reportUnusedParameterWhenOverridingConcrete = false;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportSpecialParameterHidingField)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.reportSpecialParameterHidingField = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.reportSpecialParameterHidingField = false;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_MaxProblemPerUnit)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				try {
+					int val = Integer.parseInt(stringValue);
+					if (val >= 0) this.maxProblemsPerUnit = val;
+				} catch(NumberFormatException e){
+					// ignore ill-formatted limit
+				}				
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_TaskTags)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() == 0) {
+					this.taskTags = null;
+				} else {
+					this.taskTags = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				}
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_TaskPriorities)) != null) {
+			if (optionValue instanceof String) {
+				String stringValue = (String) optionValue;
+				if (stringValue.length() == 0) {
+					this.taskPriorites = null;
+				} else {
+					this.taskPriorites = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+				}
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportMethodWithConstructorName)) != null) updateSeverity(MethodWithConstructorName, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportOverridingPackageDefaultMethod)) != null) updateSeverity(OverriddenPackageDefaultMethod, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportDeprecation)) != null) updateSeverity(UsingDeprecatedAPI, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportHiddenCatchBlock)) != null) updateSeverity(MaskedCatchBlock, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportUnusedLocal)) != null) updateSeverity(UnusedLocalVariable, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameter)) != null) updateSeverity(UnusedArgument, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportUnusedImport)) != null) updateSeverity(UnusedImport, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportUnusedPrivateMember)) != null) updateSeverity(UnusedPrivateMember, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportUnusedDeclaredThrownException)) != null) updateSeverity(UnusedDeclaredThrownException, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportNoImplicitStringConversion)) != null) updateSeverity(NoImplicitStringConversion, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportSyntheticAccessEmulation)) != null) updateSeverity(AccessEmulation, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportLocalVariableHiding)) != null) updateSeverity(LocalVariableHiding, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportFieldHiding)) != null) updateSeverity(FieldHiding, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportPossibleAccidentalBooleanAssignment)) != null) updateSeverity(AccidentalBooleanAssign, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportSuperfluousSemicolon)) != null) updateSeverity(SuperfluousSemicolon, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportNonExternalizedStringLiteral)) != null) updateSeverity(NonExternalizedString, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportAssertIdentifier)) != null) updateSeverity(AssertUsedAsAnIdentifier, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportNonStaticAccessToStatic)) != null) updateSeverity(NonStaticAccessToStatic, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportIndirectStaticAccess)) != null) updateSeverity(IndirectStaticAccess, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportIncompatibleNonInheritedInterfaceMethod)) != null) updateSeverity(IncompatibleNonInheritedInterfaceMethod, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportUndocumentedEmptyBlock)) != null) updateSeverity(UndocumentedEmptyBlock, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportUnnecessaryTypeCheck)) != null) updateSeverity(UnnecessaryTypeCheck, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportFinallyBlockNotCompletingNormally)) != null) updateSeverity(FinallyBlockNotCompleting, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportUnqualifiedFieldAccess)) != null) updateSeverity(UnqualifiedFieldAccess, optionValue);
+		if ((optionValue = optionsMap.get(OPTION_ReportNoEffectAssignment)) != null) updateSeverity(NoEffectAssignment, optionValue);
+
+		// Javadoc options
+		if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadoc)) != null) {
+			updateSeverity(InvalidJavadoc, optionValue);
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTagsVisibility)) != null) {
+			if (PUBLIC.equals(optionValue)) {
+				this.reportInvalidJavadocTagsVisibility = AccPublic;
+			} else if (PROTECTED.equals(optionValue)) {
+				this.reportInvalidJavadocTagsVisibility = AccProtected;
+			} else if (DEFAULT.equals(optionValue)) {
+				this.reportInvalidJavadocTagsVisibility = AccDefault;
+			} else if (PRIVATE.equals(optionValue)) {
+				this.reportInvalidJavadocTagsVisibility = AccPrivate;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTags)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.reportInvalidJavadocTags= true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.reportInvalidJavadocTags = false;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTags)) != null) {
+			updateSeverity(MissingJavadocTags, optionValue);
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTagsVisibility)) != null) {
+			if (PUBLIC.equals(optionValue)) {
+				this.reportMissingJavadocTagsVisibility = AccPublic;
+			} else if (PROTECTED.equals(optionValue)) {
+				this.reportMissingJavadocTagsVisibility = AccProtected;
+			} else if (DEFAULT.equals(optionValue)) {
+				this.reportMissingJavadocTagsVisibility = AccDefault;
+			} else if (PRIVATE.equals(optionValue)) {
+				this.reportMissingJavadocTagsVisibility = AccPrivate;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTagsOverriding)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.reportMissingJavadocTagsOverriding = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.reportMissingJavadocTagsOverriding = false;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocComments)) != null) {
+			updateSeverity(MissingJavadocComments, optionValue);
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocCommentsVisibility)) != null) {
+			if (PUBLIC.equals(optionValue)) {
+				this.reportMissingJavadocCommentsVisibility = AccPublic;
+			} else if (PROTECTED.equals(optionValue)) {
+				this.reportMissingJavadocCommentsVisibility = AccProtected;
+			} else if (DEFAULT.equals(optionValue)) {
+				this.reportMissingJavadocCommentsVisibility = AccDefault;
+			} else if (PRIVATE.equals(optionValue)) {
+				this.reportMissingJavadocCommentsVisibility = AccPrivate;
+			}
+		}
+		if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocCommentsOverriding)) != null) {
+			if (ENABLED.equals(optionValue)) {
+				this.reportMissingJavadocCommentsOverriding = true;
+			} else if (DISABLED.equals(optionValue)) {
+				this.reportMissingJavadocCommentsOverriding = false;
+			}
+		}
+	}
+
 	public void setVerboseMode(boolean flag) {
 		this.verbose = flag;
 	}
 
 	public String toString() {
 	
-
 		StringBuffer buf = new StringBuffer("CompilerOptions:"); //$NON-NLS-1$
-		if ((produceDebugAttributes & Vars) != 0){
-			buf.append("\n-local variables debug attributes: ON"); //$NON-NLS-1$
-		} else {
-			buf.append("\n-local variables debug attributes: OFF"); //$NON-NLS-1$
-		}
-		if ((produceDebugAttributes & Lines) != 0){
-			buf.append("\n-line number debug attributes: ON"); //$NON-NLS-1$
-		} else {
-			buf.append("\n-line number debug attributes: OFF"); //$NON-NLS-1$
-		}
-		if ((produceDebugAttributes & Source) != 0){
-			buf.append("\n-source debug attributes: ON"); //$NON-NLS-1$
-		} else {
-			buf.append("\n-source debug attributes: OFF"); //$NON-NLS-1$
-		}
-		if (preserveAllLocalVariables){
-			buf.append("\n-preserve all local variables: ON"); //$NON-NLS-1$
-		} else {
-			buf.append("\n-preserve all local variables: OFF"); //$NON-NLS-1$
-		}
-		if ((errorThreshold & UnreachableCode) != 0){
-			buf.append("\n-unreachable code: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & UnreachableCode) != 0){
-				buf.append("\n-unreachable code: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-unreachable code: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & ImportProblem) != 0){
-			buf.append("\n-import problem: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & ImportProblem) != 0){
-				buf.append("\n-import problem: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-import problem: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & MethodWithConstructorName) != 0){
-			buf.append("\n-method with constructor name: ERROR");		 //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & MethodWithConstructorName) != 0){
-				buf.append("\n-method with constructor name: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-method with constructor name: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & OverriddenPackageDefaultMethod) != 0){
-			buf.append("\n-overridden package default method: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & OverriddenPackageDefaultMethod) != 0){
-				buf.append("\n-overridden package default method: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-overridden package default method: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & UsingDeprecatedAPI) != 0){
-			buf.append("\n-deprecation: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & UsingDeprecatedAPI) != 0){
-				buf.append("\n-deprecation: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-deprecation: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & MaskedCatchBlock) != 0){
-			buf.append("\n-masked catch block: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & MaskedCatchBlock) != 0){
-				buf.append("\n-masked catch block: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-masked catch block: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & UnusedLocalVariable) != 0){
-			buf.append("\n-unused local variable: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & UnusedLocalVariable) != 0){
-				buf.append("\n-unused local variable: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-unused local variable: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & UnusedArgument) != 0){
-			buf.append("\n-unused parameter: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & UnusedArgument) != 0){
-				buf.append("\n-unused parameter: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-unused parameter: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & UnusedImport) != 0){
-			buf.append("\n-unused import: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & UnusedImport) != 0){
-				buf.append("\n-unused import: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-unused import: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & AccessEmulation) != 0){
-			buf.append("\n-synthetic access emulation: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & AccessEmulation) != 0){
-				buf.append("\n-synthetic access emulation: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-synthetic access emulation: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & NoEffectAssignment) != 0){
-			buf.append("\n-assignment with no effect: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & NoEffectAssignment) != 0){
-				buf.append("\n-assignment with no effect: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-assignment with no effect: IGNORE"); //$NON-NLS-1$
-			}
-		}		if ((errorThreshold & NonExternalizedString) != 0){
-			buf.append("\n-non externalized string: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & NonExternalizedString) != 0){
-				buf.append("\n-non externalized string: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-non externalized string: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & StaticAccessReceiver) != 0){
-			buf.append("\n-static access receiver: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & StaticAccessReceiver) != 0){
-				buf.append("\n-static access receiver: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-static access receiver: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & IncompatibleNonInheritedInterfaceMethod) != 0){
-			buf.append("\n-incompatible non inherited interface method: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & IncompatibleNonInheritedInterfaceMethod) != 0){
-				buf.append("\n-incompatible non inherited interface method: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-incompatible non inherited interface method: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		if ((errorThreshold & UnusedPrivateMember) != 0){
-			buf.append("\n-unused private member: ERROR"); //$NON-NLS-1$
-		} else {
-			if ((warningThreshold & UnusedPrivateMember) != 0){
-				buf.append("\n-unused private member: WARNING"); //$NON-NLS-1$
-			} else {
-				buf.append("\n-unused private member: IGNORE"); //$NON-NLS-1$
-			}
-		}
-		switch(targetJDK){
-			case JDK1_1 :
-				buf.append("\n-target JDK: 1.1"); //$NON-NLS-1$
-				break;
-			case JDK1_2 :
-				buf.append("\n-target JDK: 1.2"); //$NON-NLS-1$
-				break;
-			case JDK1_3 :
-				buf.append("\n-target JDK: 1.3"); //$NON-NLS-1$
-				break;
-			case JDK1_4 :
-				buf.append("\n-target JDK: 1.4"); //$NON-NLS-1$
-				break;
-		}
-		switch(complianceLevel){
-			case JDK1_1 :
-				buf.append("\n-compliance JDK: 1.1"); //$NON-NLS-1$
-				break;
-			case JDK1_2 :
-				buf.append("\n-compliance JDK: 1.2"); //$NON-NLS-1$
-				break;
-			case JDK1_3 :
-				buf.append("\n-compliance JDK: 1.3"); //$NON-NLS-1$
-				break;
-			case JDK1_4 :
-				buf.append("\n-compliance JDK: 1.4"); //$NON-NLS-1$
-				break;
-		}
-		if (isPrivateConstructorAccessChangingVisibility){
-			buf.append("\n-private constructor access emulation: extra argument"); //$NON-NLS-1$
-		} else {
-			buf.append("\n-private constructor access emulation: make default access"); //$NON-NLS-1$
-		}
-		buf.append("\n-verbose : " + (verbose ? "ON" : "OFF")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-		buf.append("\n-produce reference info : " + (produceReferenceInfo ? "ON" : "OFF")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-		buf.append("\n-parse literal expressions as constants : " + (parseLiteralExpressionsAsConstants ? "ON" : "OFF")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-		buf.append("\n-runtime exception name for compile error : " + runtimeExceptionNameForCompileError); //$NON-NLS-1$
-		buf.append("\n-encoding : " + (defaultEncoding == null ? "<default>" : defaultEncoding)); //$NON-NLS-1$ //$NON-NLS-2$
-		buf.append("\n-task tags: " + (this.taskTags == null ? "" : new String(CharOperation.concatWith(this.taskTags,','))));  //$NON-NLS-1$ //$NON-NLS-2$
-		buf.append("\n-task priorities : " + (this.taskPriorites == null ? "" : new String(CharOperation.concatWith(this.taskPriorites,',')))); //$NON-NLS-1$ //$NON-NLS-2$
-		buf.append("\n-report deprecation inside deprecated code : " + (reportDeprecationInsideDeprecatedCode ? "ENABLED" : "DISABLED")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-		buf.append("\n-report unused parameter when implementing abstract method : " + (reportUnusedParameterWhenImplementingAbstract ? "ENABLED" : "DISABLED")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-		buf.append("\n-report unused parameter when overriding concrete method : " + (reportUnusedParameterWhenOverridingConcrete ? "ENABLED" : "DISABLED")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- local variables debug attributes: ").append((this.produceDebugAttributes & Vars) != 0 ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- line number debug attributes: ").append((this.produceDebugAttributes & Lines) != 0 ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- source debug attributes: ").append((this.produceDebugAttributes & Source) != 0 ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- preserve all local variables: ").append(this.preserveAllLocalVariables ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- method with constructor name: ").append(getSeverityString(MethodWithConstructorName)); //$NON-NLS-1$
+		buf.append("\n\t- overridden package default method: ").append(getSeverityString(OverriddenPackageDefaultMethod)); //$NON-NLS-1$
+		buf.append("\n\t- deprecation: ").append(getSeverityString(UsingDeprecatedAPI)); //$NON-NLS-1$
+		buf.append("\n\t- masked catch block: ").append(getSeverityString(MaskedCatchBlock)); //$NON-NLS-1$
+		buf.append("\n\t- unused local variable: ").append(getSeverityString(UnusedLocalVariable)); //$NON-NLS-1$
+		buf.append("\n\t- unused parameter: ").append(getSeverityString(UnusedArgument)); //$NON-NLS-1$
+		buf.append("\n\t- unused import: ").append(getSeverityString(UnusedImport)); //$NON-NLS-1$
+		buf.append("\n\t- synthetic access emulation: ").append(getSeverityString(AccessEmulation)); //$NON-NLS-1$
+		buf.append("\n\t- assignment with no effect: ").append(getSeverityString(NoEffectAssignment)); //$NON-NLS-1$
+		buf.append("\n\t- non externalized string: ").append(getSeverityString(NonExternalizedString)); //$NON-NLS-1$
+		buf.append("\n\t- static access receiver: ").append(getSeverityString(NonStaticAccessToStatic)); //$NON-NLS-1$
+		buf.append("\n\t- indirect static access: ").append(getSeverityString(IndirectStaticAccess)); //$NON-NLS-1$
+		buf.append("\n\t- incompatible non inherited interface method: ").append(getSeverityString(IncompatibleNonInheritedInterfaceMethod)); //$NON-NLS-1$
+		buf.append("\n\t- unused private member: ").append(getSeverityString(UnusedPrivateMember)); //$NON-NLS-1$
+		buf.append("\n\t- local variable hiding another variable: ").append(getSeverityString(LocalVariableHiding)); //$NON-NLS-1$
+		buf.append("\n\t- field hiding another variable: ").append(getSeverityString(FieldHiding)); //$NON-NLS-1$
+		buf.append("\n\t- possible accidental boolean assignment: ").append(getSeverityString(AccidentalBooleanAssign)); //$NON-NLS-1$
+		buf.append("\n\t- superfluous semicolon: ").append(getSeverityString(SuperfluousSemicolon)); //$NON-NLS-1$
+		buf.append("\n\t- uncommented empty block: ").append(getSeverityString(UndocumentedEmptyBlock)); //$NON-NLS-1$
+		buf.append("\n\t- unnecessary type check: ").append(getSeverityString(UnnecessaryTypeCheck)); //$NON-NLS-1$
+		buf.append("\n\t- invalid javadoc: ").append(getSeverityString(InvalidJavadoc)); //$NON-NLS-1$
+		buf.append("\n\t- report invalid javadoc tags: ").append(this.reportInvalidJavadocTags ? ENABLED : DISABLED); //$NON-NLS-1$
+		buf.append("\n\t- visibility level to report invalid javadoc tags: ").append(getVisibilityString(this.reportInvalidJavadocTagsVisibility)); //$NON-NLS-1$
+		buf.append("\n\t- missing javadoc tags: ").append(getSeverityString(MissingJavadocTags)); //$NON-NLS-1$
+		buf.append("\n\t- visibility level to report missing javadoc tags: ").append(getVisibilityString(this.reportMissingJavadocTagsVisibility)); //$NON-NLS-1$
+		buf.append("\n\t- report missing javadoc tags in overriding methods: ").append(this.reportMissingJavadocTagsOverriding ? ENABLED : DISABLED); //$NON-NLS-1$
+		buf.append("\n\t- missing javadoc comments: ").append(getSeverityString(MissingJavadocComments)); //$NON-NLS-1$
+		buf.append("\n\t- visibility level to report missing javadoc comments: ").append(getVisibilityString(this.reportMissingJavadocCommentsVisibility)); //$NON-NLS-1$
+		buf.append("\n\t- report missing javadoc comments in overriding methods: ").append(this.reportMissingJavadocCommentsOverriding ? ENABLED : DISABLED); //$NON-NLS-1$
+		buf.append("\n\t- finally block not completing normally: ").append(getSeverityString(FinallyBlockNotCompleting)); //$NON-NLS-1$
+		buf.append("\n\t- unused declared thrown exception: ").append(getSeverityString(UnusedDeclaredThrownException)); //$NON-NLS-1$
+		buf.append("\n\t- JDK compliance level: "+ versionFromJdkLevel(this.complianceLevel)); //$NON-NLS-1$
+		buf.append("\n\t- JDK source level: "+ versionFromJdkLevel(this.sourceLevel)); //$NON-NLS-1$
+		buf.append("\n\t- JDK target level: "+ versionFromJdkLevel(this.targetJDK)); //$NON-NLS-1$
+		buf.append("\n\t- private constructor access: ").append(this.isPrivateConstructorAccessChangingVisibility ? "extra argument" : "make default access"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- verbose : ").append(this.verbose ? "ON" : "OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- produce reference info : ").append(this.produceReferenceInfo ? "ON" : "OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- parse literal expressions as constants : ").append(this.parseLiteralExpressionsAsConstants ? "ON" : "OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- encoding : ").append(this.defaultEncoding == null ? "<default>" : this.defaultEncoding); //$NON-NLS-1$ //$NON-NLS-2$
+		buf.append("\n\t- task tags: ").append(this.taskTags == null ? "" : new String(CharOperation.concatWith(this.taskTags,',')));  //$NON-NLS-1$ //$NON-NLS-2$
+		buf.append("\n\t- task priorities : ").append(this.taskPriorites == null ? "" : new String(CharOperation.concatWith(this.taskPriorites,','))); //$NON-NLS-1$ //$NON-NLS-2$
+		buf.append("\n\t- report deprecation inside deprecated code : ").append(this.reportDeprecationInsideDeprecatedCode ? "ENABLED" : "DISABLED"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- report deprecation when overriding deprecated method : ").append(this.reportDeprecationWhenOverridingDeprecatedMethod ? "ENABLED" : "DISABLED"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- report unused parameter when implementing abstract method : ").append(this.reportUnusedParameterWhenImplementingAbstract ? "ENABLED" : "DISABLED"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- report unused parameter when overriding concrete method : ").append(this.reportUnusedParameterWhenOverridingConcrete ? "ENABLED" : "DISABLED"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		buf.append("\n\t- report constructor/setter parameter hiding existing field : ").append(this.reportSpecialParameterHidingField ? "ENABLED" : "DISABLED"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 		return buf.toString();
 	}
+
+	void updateSeverity(long irritant, Object severityString) {
+		if (ERROR.equals(severityString)) {
+			this.errorThreshold |= irritant;
+			this.warningThreshold &= ~irritant;
+		} else if (WARNING.equals(severityString)) {
+			this.errorThreshold &= ~irritant;
+			this.warningThreshold |= irritant;
+		} else if (IGNORE.equals(severityString)) {
+			this.errorThreshold &= ~irritant;
+			this.warningThreshold &= ~irritant;
+		}
+	}				
+	public static long versionToJdkLevel(Object versionID) {
+		if (VERSION_1_1.equals(versionID)) {
+			return JDK1_1;
+		} else if (VERSION_1_2.equals(versionID)) {
+			return JDK1_2;
+		} else if (VERSION_1_3.equals(versionID)) {
+			return JDK1_3;
+		} else if (VERSION_1_4.equals(versionID)) {
+			return JDK1_4;
+		} else if (VERSION_1_5.equals(versionID)) {
+			return JDK1_5;
+		}
+		return 0; // unknown
+	}
+
+	public static String versionFromJdkLevel(long jdkLevel) {
+		if (jdkLevel == JDK1_1) {
+			return VERSION_1_1;
+		} else if (jdkLevel == JDK1_2) {
+			return VERSION_1_2;
+		} else if (jdkLevel == JDK1_3) {
+			return VERSION_1_3;
+		} else if (jdkLevel == JDK1_4) {
+			return VERSION_1_4;
+		} else if (jdkLevel == JDK1_5) {
+			return VERSION_1_5;
+		}
+		return ""; // unknown version //$NON-NLS-1$
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java
index d18ca7f..2a64edb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java
@@ -27,7 +27,7 @@
 	}
 	
 	public double doubleValue() {
-		return (double) value;
+		return this.value;
 	}
 	
 	public float floatValue() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java
index 013ae9d..8b17121 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java
@@ -27,11 +27,11 @@
 	}
 	
 	public double doubleValue() {
-		return (double) value;
+		return value; // implicit cast to return type
 	}
 	
 	public float floatValue() {
-		return (float) value;
+		return this.value;
 	}
 	
 	public int intValue() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IntConstant.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IntConstant.java
index 48ec7dd..8de4299 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IntConstant.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/IntConstant.java
@@ -27,19 +27,19 @@
 	}
 	
 	public double doubleValue() {
-		return (double) value;
+		return value; // implicit cast to return type
 	}
 	
 	public float floatValue() {
-		return (float) value;
+		return value; // implicit cast to return type
 	}
 	
 	public int intValue() {
-		return (int) value;
+		return value;
 	}
 	
 	public long longValue() {
-		return (long) value;
+		return value; // implicit cast to return type
 	}
 	
 	public short shortValue() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/LongConstant.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/LongConstant.java
index 4465487..57b2932 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/LongConstant.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/LongConstant.java
@@ -22,16 +22,16 @@
 	return (char) value;
 }
 public double doubleValue() {
-	return (double) value;
+	return value; // implicit cast to return type
 }
 public float floatValue() {
-	return (float) value;
+	return value; // implicit cast to return type
 }
 public int intValue() {
 	return (int) value;
 }
 public long longValue() {
-	return (long) value;
+	return value; 
 }
 public short shortValue() {
 	return (short) value;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java
index a2c5f83..c821c0d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java
@@ -22,19 +22,19 @@
 	return (char) value;
 }
 public double doubleValue() {
-	return (double) value;
+	return value; // implicit cast to return type
 }
 public float floatValue() {
-	return (float) value;
+	return value; // implicit cast to return type
 }
 public int intValue() {
-	return (int) value;
+	return value; // implicit cast to return type
 }
 public long longValue() {
-	return (long) value;
+	return value; // implicit cast to return type
 }
 public short shortValue() {
-	return (short) value;
+	return value;
 }
 public String stringValue() {
 	//spec 15.17.11
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
index 8e293ab..be0ec29 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
@@ -16,7 +16,7 @@
 public final class ArrayBinding extends TypeBinding {
 	// creation and initialization of the length field
 	// the declaringClass of this field is intentionally set to null so it can be distinguished.
-	public static final FieldBinding LengthField = new FieldBinding(LENGTH, IntBinding, AccPublic | AccFinal, null, Constant.NotAConstant);
+	public static final FieldBinding ArrayLength = new FieldBinding(LENGTH, IntBinding, AccPublic | AccFinal, null, Constant.NotAConstant);
 
 	public TypeBinding leafComponentType;
 	public int dimensions;
@@ -27,18 +27,18 @@
 	this.leafComponentType = type;
 	this.dimensions = dimensions;
 }
-/* Answer the receiver's constant pool name.
-*
-* NOTE: This method should only be used during/after code gen.
-*/
+/**
+ * Answer the receiver's constant pool name.
+ * NOTE: This method should only be used during/after code gen.
+ * e.g. '[Ljava/lang/Object;'
+ */
 
-public char[] constantPoolName() /*	[Ljava/lang/Object; */ {
+public char[] constantPoolName() {
 	if (constantPoolName != null)
 		return constantPoolName;
 
 	char[] brackets = new char[dimensions];
-	for (int i = dimensions - 1; i >= 0; i--)
-		brackets[i] = '[';
+	for (int i = dimensions - 1; i >= 0; i--) brackets[i] = '[';
 	return constantPoolName = CharOperation.concat(brackets, leafComponentType.signature());
 }
 String debugName() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java
index 1c2cd15..a6d9f11 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java
@@ -11,148 +11,176 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 public final class BaseTypeBinding extends TypeBinding {
+
 	public char[] simpleName;
-	private char [] constantPoolName;
-BaseTypeBinding(int id, char[] name, char[] constantPoolName) {
-	this.tagBits |= IsBaseType;
-	this.id = id;
-	this.simpleName = name;
-	this.constantPoolName = constantPoolName;
-}
-/* Answer the receiver's constant pool name.
-*/
+	private char[] constantPoolName;
 
-public char[] constantPoolName() {
-	return constantPoolName;
-}
-public PackageBinding getPackage() {
-	return null;
-}
-/* Answer true if the receiver type can be assigned to the argument type (right)
-*/
+	BaseTypeBinding(int id, char[] name, char[] constantPoolName) {
 
-public final boolean isCompatibleWith(TypeBinding right) {
-	if (this == right)
-		return true;
-	if (!right.isBaseType())
-		return this == NullBinding;
-
-	switch (right.id) {
-		case T_boolean :
-		case T_byte :
-		case T_char :
-			return false;
-		case T_double :
-			switch (id) {
-				case T_byte :
-				case T_char :
-				case T_short :
-				case T_int :
-				case T_long :
-				case T_float :
-					return true;
-				default :
-					return false;
-			}
-		case T_float :
-			switch (id) {
-				case T_byte :
-				case T_char :
-				case T_short :
-				case T_int :
-				case T_long :
-					return true;
-				default :
-					return false;
-			}
-		case T_long :
-			switch (id) {
-				case T_byte :
-				case T_char :
-				case T_short :
-				case T_int :
-					return true;
-				default :
-					return false;
-			}
-		case T_int :
-			switch (id) {
-				case T_byte :
-				case T_char :
-				case T_short :
-					return true;
-				default :
-					return false;
-			}
-		case T_short :
-			return (id == T_byte);
+		this.tagBits |= IsBaseType;
+		this.id = id;
+		this.simpleName = name;
+		this.constantPoolName = constantPoolName;
 	}
-	return false;
-}
-public static final boolean isNarrowing(int left, int right) {
-	//can "left" store a "right" using some narrowing conversion
-	//(is left smaller than right)
 
-	switch (left) {
-		case T_boolean :
-			return right == T_boolean;
-		case T_char :
-		case T_byte :
-			if (right == T_byte) return true;
-		case T_short :
-			if (right == T_short) return true;
-			if (right == T_char) return true;
-		case T_int :
-			if (right == T_int) return true;
-		case T_long :
-			if (right == T_long) return true;
-		case T_float :
-			if (right == T_float) return true;
-		case T_double :
-			if (right == T_double) return true;
-		default :
-			return false;
-	}
-}
-public static final boolean isWidening(int left, int right) {
-	//can "left" store a "right" using some widening conversion
-	//(is left "bigger" than right)
+	/* Answer the receiver's constant pool name.
+	*/
+	public char[] constantPoolName() {
 
-	switch (left) {
-		case T_boolean :
-			return right == T_boolean;
-		case T_char :
-			return right == T_char;
-		case T_double :
-			if (right == T_double) return true;
-		case T_float :
-			if (right == T_float) return true;
-		case T_long :
-			if (right == T_long) return true;
-		case T_int :
-			if (right == T_int) return true;
-			if (right == T_char) return true;
-		case T_short :
-			if (right == T_short) return true;
-		case T_byte :
-			if (right == T_byte) return true;
-		default :
-			return false;
+		return constantPoolName;
 	}
-}
-public char[] qualifiedSourceName() {
-	return simpleName;
-}
-public char[] readableName() {
-	return simpleName;
-}
-public char[] shortReadableName(){
-	return simpleName;
-}
-public char[] sourceName() {
-	return simpleName;
-}
-public String toString() {
-	return new String(constantPoolName) + " (id=" + id + ")"; //$NON-NLS-1$ //$NON-NLS-2$
-}
+
+	public PackageBinding getPackage() {
+
+		return null;
+	}
+
+	/* Answer true if the receiver type can be assigned to the argument type (right)
+	*/
+	public final boolean isCompatibleWith(TypeBinding right) {
+
+		if (this == right)
+			return true;
+		if (!right.isBaseType())
+			return this == NullBinding;
+
+		switch (right.id) {
+			case T_boolean :
+			case T_byte :
+			case T_char :
+				return false;
+			case T_double :
+				switch (id) {
+					case T_byte :
+					case T_char :
+					case T_short :
+					case T_int :
+					case T_long :
+					case T_float :
+						return true;
+					default :
+						return false;
+				}
+			case T_float :
+				switch (id) {
+					case T_byte :
+					case T_char :
+					case T_short :
+					case T_int :
+					case T_long :
+						return true;
+					default :
+						return false;
+				}
+			case T_long :
+				switch (id) {
+					case T_byte :
+					case T_char :
+					case T_short :
+					case T_int :
+						return true;
+					default :
+						return false;
+				}
+			case T_int :
+				switch (id) {
+					case T_byte :
+					case T_char :
+					case T_short :
+						return true;
+					default :
+						return false;
+				}
+			case T_short :
+				return (id == T_byte);
+		}
+		return false;
+	}
+
+	public static final boolean isNarrowing(int left, int right) {
+
+		//can "left" store a "right" using some narrowing conversion
+		//(is left smaller than right)
+		switch (left) {
+			case T_boolean :
+				return right == T_boolean;
+			case T_char :
+			case T_byte :
+				if (right == T_byte)
+					return true;
+			case T_short :
+				if (right == T_short)
+					return true;
+				if (right == T_char)
+					return true;
+			case T_int :
+				if (right == T_int)
+					return true;
+			case T_long :
+				if (right == T_long)
+					return true;
+			case T_float :
+				if (right == T_float)
+					return true;
+			case T_double :
+				if (right == T_double)
+					return true;
+			default :
+				return false;
+		}
+	}
+
+	public static final boolean isWidening(int left, int right) {
+
+		//can "left" store a "right" using some widening conversion
+		//(is left "bigger" than right)
+		switch (left) {
+			case T_boolean :
+				return right == T_boolean;
+			case T_char :
+				return right == T_char;
+			case T_double :
+				if (right == T_double)
+					return true;
+			case T_float :
+				if (right == T_float)
+					return true;
+			case T_long :
+				if (right == T_long)
+					return true;
+			case T_int :
+				if (right == T_int)
+					return true;
+				if (right == T_char)
+					return true;
+			case T_short :
+				if (right == T_short)
+					return true;
+			case T_byte :
+				if (right == T_byte)
+					return true;
+			default :
+				return false;
+		}
+	}
+
+	public char[] qualifiedSourceName() {
+		return simpleName;
+	}
+
+	public char[] readableName() {
+		return simpleName;
+	}
+
+	public char[] shortReadableName() {
+		return simpleName;
+	}
+
+	public char[] sourceName() {
+		return simpleName;
+	}
+
+	public String toString() {
+		return new String(constantPoolName) + " (id=" + id + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index 0395d61..be35746 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -47,7 +47,7 @@
 	this.tagBits |= IsBinaryBinding;
 	this.environment = environment;
 	this.fPackage = packageBinding;
-	this.	fileName = binaryType.getFileName();
+	this.fileName = binaryType.getFileName();
 
 	// source name must be one name without "$".
 	char[] possibleSourceName = this.compoundName[this.compoundName.length - 1];
@@ -62,6 +62,14 @@
 	this.modifiers = binaryType.getModifiers();
 	if (binaryType.isInterface())
 		this.modifiers |= AccInterface;
+		
+	if (binaryType.isAnonymous()) {
+		this.tagBits |= AnonymousTypeMask;
+	} else if (binaryType.isLocal()) {
+		this.tagBits |= LocalTypeMask;
+	} else if (binaryType.isMember()) {
+		this.tagBits |= MemberTypeMask;
+	}
 }
 
 public FieldBinding[] availableFields() {
@@ -73,6 +81,7 @@
 			availableFields[count] = resolveTypeFor(fields[i]);
 			count++;
 		} catch (AbortCompilation a){
+			// silent abort
 		}
 	}
 	
@@ -92,6 +101,7 @@
 			availableMethods[count] = resolveTypesFor(methods[i]);
 			count++;
 		} catch (AbortCompilation a){
+			// silent abort
 		}
 	}
 	System.arraycopy(availableMethods, 0, availableMethods = new MethodBinding[count], 0, count);
@@ -138,9 +148,12 @@
 				this.superInterfaces[i] = environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1);
 		}
 	}
-	if (needFieldsAndMethods){
+	if (needFieldsAndMethods) {
 		createFields(binaryType.getFields());
 		createMethods(binaryType.getMethods());
+	} else { // protect against incorrect use of the needFieldsAndMethods flag, see 48459
+		this.fields = NoFields;
+		this.methods = NoMethods;
 	}
 }
 private void createFields(IBinaryField[] iFields) {
@@ -155,7 +168,7 @@
 					new FieldBinding(
 						field.getName(),
 						environment.getTypeFromSignature(field.getTypeName(), 0, -1),
-						field.getModifiers(),
+						field.getModifiers() | AccUnresolved,
 						this,
 						field.getConstant());
 			}
@@ -163,7 +176,7 @@
 	}
 }
 private MethodBinding createMethod(IBinaryMethod method) {
-	int modifiers = method.getModifiers() | AccUnresolved;
+	int methodModifiers = method.getModifiers() | AccUnresolved;
 
 	ReferenceBinding[] exceptions = NoExceptions;
 	char[][] exceptionTypes = method.getExceptionTypeNames();
@@ -177,15 +190,15 @@
 	}
 
 	TypeBinding[] parameters = NoParameters;
-	char[] signature = method.getMethodDescriptor();   // of the form (I[Ljava/jang/String;)V
+	char[] methodSignature = method.getMethodDescriptor();   // of the form (I[Ljava/jang/String;)V
 	int numOfParams = 0;
 	char nextChar;
 	int index = 0;   // first character is always '(' so skip it
-	while ((nextChar = signature[++index]) != ')') {
+	while ((nextChar = methodSignature[++index]) != ')') {
 		if (nextChar != '[') {
 			numOfParams++;
 			if (nextChar == 'L')
-				while ((nextChar = signature[++index]) != ';');
+				while ((nextChar = methodSignature[++index]) != ';');
 		}
 	}
 
@@ -197,24 +210,24 @@
 		index = 1;
 		int end = 0;   // first character is always '(' so skip it
 		for (int i = 0; i < numOfParams; i++) {
-			while ((nextChar = signature[++end]) == '[');
+			while ((nextChar = methodSignature[++end]) == '[');
 			if (nextChar == 'L')
-				while ((nextChar = signature[++end]) != ';');
+				while ((nextChar = methodSignature[++end]) != ';');
 
 			if (i >= startIndex)   // skip the synthetic arg if necessary
-				parameters[i - startIndex] = environment.getTypeFromSignature(signature, index, end);
+				parameters[i - startIndex] = environment.getTypeFromSignature(methodSignature, index, end);
 			index = end + 1;
 		}
 	}
 
 	MethodBinding binding = null;
 	if (method.isConstructor())
-		binding = new MethodBinding(modifiers, parameters, exceptions, this);
+		binding = new MethodBinding(methodModifiers, parameters, exceptions, this);
 	else
 		binding = new MethodBinding(
-			modifiers,
+			methodModifiers,
 			method.getSelector(),
-			environment.getTypeFromSignature(signature, index + 1, -1),   // index is currently pointing at the ')'
+			environment.getTypeFromSignature(methodSignature, index + 1, -1),   // index is currently pointing at the ')'
 			parameters,
 			exceptions,
 			this);
@@ -331,12 +344,12 @@
 }
 // NOTE: the type of a field of a binary type is resolved when needed
 
-public FieldBinding getField(char[] fieldName) {
+public FieldBinding getField(char[] fieldName, boolean needResolve) {
 	int fieldLength = fieldName.length;
 	for (int f = fields.length; --f >= 0;) {
 		char[] name = fields[f].name;
 		if (name.length == fieldLength && CharOperation.prefixEquals(name, fieldName))
-			return resolveTypeFor(fields[f]);
+			return needResolve ? resolveTypeFor(fields[f]) : fields[f];
 	}
 	return null;
 }
@@ -387,7 +400,7 @@
 	modifiers ^= AccUnresolved;
 	return methods;
 }
-private TypeBinding resolveType(TypeBinding type) {
+TypeBinding resolveType(TypeBinding type) {
 	if (type instanceof UnresolvedReferenceBinding)
 		return ((UnresolvedReferenceBinding) type).resolve(environment);
 	if (type instanceof ArrayBinding) {
@@ -398,7 +411,10 @@
 	return type;
 }
 private FieldBinding resolveTypeFor(FieldBinding field) {
-	field.type = resolveType(field.type);
+	if ((field.modifiers & AccUnresolved) != 0) {
+		field.type = resolveType(field.type);
+		field.modifiers ^= AccUnresolved;
+	}
 	return field;
 }
 private MethodBinding resolveTypesFor(MethodBinding method) {
@@ -435,6 +451,9 @@
 			superInterfaces[i] = ((UnresolvedReferenceBinding) superInterfaces[i]).resolve(environment);
 	return superInterfaces;
 }
+MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
+	return methods;
+}
 public String toString() {
 	String s = ""; //$NON-NLS-1$
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index 3ddc416..ca14a99 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -11,13 +11,9 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Argument;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 
@@ -39,7 +35,7 @@
 	public final static VariableBinding[] NoEnclosingInstanceInStaticContext = {};
 
 	public Scope[] subscopes = new Scope[1]; // need access from code assist
-	public int scopeIndex = 0; // need access from code assist
+	public int subscopeCount = 0; // need access from code assist
 
 	protected BlockScope(int kind, Scope parent) {
 
@@ -131,14 +127,14 @@
 	}
 
 	public void addSubscope(Scope childScope) {
-		if (scopeIndex == subscopes.length)
+		if (subscopeCount == subscopes.length)
 			System.arraycopy(
 				subscopes,
 				0,
-				(subscopes = new Scope[scopeIndex * 2]),
+				(subscopes = new Scope[subscopeCount * 2]),
 				0,
-				scopeIndex);
-		subscopes[scopeIndex++] = childScope;
+				subscopeCount);
+		subscopes[subscopeCount++] = childScope;
 	}
 
 	/* Answer true if the receiver is suitable for assigning final blank fields.
@@ -202,7 +198,7 @@
 		boolean hasMoreVariables = ilocal < maxLocals;
 
 		// scope init
-		int iscope = 0, maxScopes = this.scopeIndex;
+		int iscope = 0, maxScopes = this.subscopeCount;
 		boolean hasMoreScopes = maxScopes > 0;
 
 		// iterate scopes and variables in parallel
@@ -229,7 +225,7 @@
 				// do not report fake used variable
 				if (local.useFlag == LocalVariableBinding.UNUSED
 					&& (local.declaration != null) // unused (and non secret) local
-					&& ((local.declaration.bits & AstNode.IsLocalDeclarationReachableMASK) != 0)) { // declaration is reachable
+					&& ((local.declaration.bits & ASTNode.IsLocalDeclarationReachableMASK) != 0)) { // declaration is reachable
 						
 					if (!(local.declaration instanceof Argument))  // do not report unused catch arguments
 						this.problemReporter().unusedLocalVariable(local.declaration);
@@ -260,7 +256,7 @@
 					if (this.offset > 0xFFFF) { // no more than 65535 words of locals
 						this.problemReporter().noMoreAvailableSpaceForLocal(
 							local, 
-							local.declaration == null ? (AstNode)this.methodScope().referenceContext : local.declaration);
+							local.declaration == null ? (ASTNode)this.methodScope().referenceContext : local.declaration);
 					}
 				} else {
 					local.resolvedPosition = -1; // not generated
@@ -272,19 +268,6 @@
 			this.maxOffset = this.offset;
 	}
 
-	/* Answer true if the variable name already exists within the receiver's scope.
-	 */
-	public final LocalVariableBinding duplicateName(char[] name) {
-		for (int i = 0; i < localIndex; i++)
-			if (CharOperation.equals(name, locals[i].name))
-				return locals[i];
-
-		if (this instanceof MethodScope)
-			return null;
-		else
-			return ((BlockScope) parent).duplicateName(name);
-	}
-
 	/*
 	 *	Record the suitable binding denoting a synthetic field or constructor argument,
 	 * mapping to the actual outer local variable in the scope context.
@@ -333,7 +316,7 @@
 	 */
 	public final ReferenceBinding findLocalType(char[] name) {
 
-		for (int i = 0, length = scopeIndex; i < length; i++) {
+		for (int i = 0, length = subscopeCount; i < length; i++) {
 			if (subscopes[i] instanceof ClassScope) {
 				SourceTypeBinding sourceType =
 					((ClassScope) subscopes[i]).referenceContext.binding;
@@ -388,9 +371,9 @@
 	 *
 	 *	IMPORTANT NOTE: This method is written under the assumption that compoundName is longer than length 1.
 	 */
-	public Binding getBinding(char[][] compoundName, int mask, InvocationSite invocationSite) {
+	public Binding getBinding(char[][] compoundName, int mask, InvocationSite invocationSite, boolean needResolve) {
 
-		Binding binding = getBinding(compoundName[0], mask | TYPE | PACKAGE, invocationSite);
+		Binding binding = getBinding(compoundName[0], mask | TYPE | PACKAGE, invocationSite, needResolve);
 		invocationSite.setFieldIndex(1);
 		if (binding instanceof VariableBinding) return binding;
 		compilationUnitScope().recordSimpleReference(compoundName[0]);
@@ -423,7 +406,7 @@
 					if (!((ReferenceBinding) binding).canBeSeenBy(this))
 						return new ProblemReferenceBinding(
 							CharOperation.subarray(compoundName, 0, currentIndex),
-							binding,
+							(ReferenceBinding) binding,
 							NotVisible);
 					break foundType;
 				}
@@ -442,7 +425,7 @@
 			char[] nextName = compoundName[currentIndex++];
 			invocationSite.setFieldIndex(currentIndex);
 			invocationSite.setActualReceiverType(typeBinding);
-			if ((mask & FIELD) != 0 && (binding = findField(typeBinding, nextName, invocationSite)) != null) {
+			if ((mask & FIELD) != 0 && (binding = findField(typeBinding, nextName, invocationSite, true /*resolve*/)) != null) {
 				if (!binding.isValidBinding())
 					return new ProblemFieldBinding(
 						((FieldBinding) binding).declaringClass,
@@ -500,7 +483,8 @@
 			getBinding(
 				compoundName[currentIndex++],
 				VARIABLE | TYPE | PACKAGE,
-				invocationSite);
+				invocationSite, 
+				true /*resolve*/);
 		if (!binding.isValidBinding())
 			return binding;
 
@@ -527,7 +511,7 @@
 					if (!((ReferenceBinding) binding).canBeSeenBy(this))
 						return new ProblemReferenceBinding(
 							CharOperation.subarray(compoundName, 0, currentIndex),
-							binding, 
+							(ReferenceBinding) binding, 
 							NotVisible);
 					break foundType;
 				}
@@ -539,7 +523,7 @@
 			while (currentIndex < length) {
 				ReferenceBinding typeBinding = (ReferenceBinding) binding;
 				char[] nextName = compoundName[currentIndex++];
-				if ((binding = findField(typeBinding, nextName, invocationSite)) != null) {
+				if ((binding = findField(typeBinding, nextName, invocationSite, true /*resolve*/)) != null) {
 					if (!binding.isValidBinding())
 						return new ProblemFieldBinding(
 							((FieldBinding) binding).declaringClass,
@@ -574,7 +558,7 @@
 					CharOperation.subarray(compoundName, 0, currentIndex + 1),
 					NotFound);
 			variableBinding =
-				findField(typeBinding, compoundName[currentIndex++], invocationSite);
+				findField(typeBinding, compoundName[currentIndex++], invocationSite, true /*resolve*/);
 			if (variableBinding == null)
 				return new ProblemFieldBinding(
 					null,
@@ -586,251 +570,6 @@
 		return variableBinding;
 	}
 
-	/* API
-     *	
-	 *	Answer the binding that corresponds to the argument name.
-	 *	flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE, PACKAGE.
-	 *	Only bindings corresponding to the mask can be answered.
-	 *
-	 *	For example, getBinding("foo", VARIABLE, site) will answer
-	 *	the binding for the field or local named "foo" (or an error binding if none exists).
-	 *	If a type named "foo" exists, it will not be detected (and an error binding will be answered)
-	 *
-	 *	The VARIABLE mask has precedence over the TYPE mask.
-	 *
-	 *	If the VARIABLE mask is not set, neither fields nor locals will be looked for.
-	 *
-	 *	InvocationSite implements:
-	 *		isSuperAccess(); this is used to determine if the discovered field is visible.
-	 *
-	 *	Limitations: cannot request FIELD independently of LOCAL, or vice versa
-	 */
-	public Binding getBinding(char[] name, int mask, InvocationSite invocationSite) {
-			
-		Binding binding = null;
-		FieldBinding problemField = null;
-		if ((mask & VARIABLE) != 0) {
-			if (this.kind == BLOCK_SCOPE || this.kind == METHOD_SCOPE) {
-				LocalVariableBinding variableBinding = findVariable(name);
-				// looks in this scope only
-				if (variableBinding != null) return variableBinding;
-			}
-
-			boolean insideStaticContext = false;
-			boolean insideConstructorCall = false;
-			if (this.kind == METHOD_SCOPE) {
-				MethodScope methodScope = (MethodScope) this;
-				insideStaticContext |= methodScope.isStatic;
-				insideConstructorCall |= methodScope.isConstructorCall;
-			}
-
-			FieldBinding foundField = null;
-			// can be a problem field which is answered if a valid field is not found
-			ProblemFieldBinding foundInsideProblem = null;
-			// inside Constructor call or inside static context
-			Scope scope = parent;
-			int depth = 0;
-			int foundDepth = 0;
-			ReferenceBinding foundActualReceiverType = null;
-			done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
-				switch (scope.kind) {
-					case METHOD_SCOPE :
-						MethodScope methodScope = (MethodScope) scope;
-						insideStaticContext |= methodScope.isStatic;
-						insideConstructorCall |= methodScope.isConstructorCall;
-						// Fall through... could duplicate the code below to save a cast - questionable optimization
-					case BLOCK_SCOPE :
-						LocalVariableBinding variableBinding = ((BlockScope) scope).findVariable(name);
-						// looks in this scope only
-						if (variableBinding != null) {
-							if (foundField != null && foundField.isValidBinding())
-								return new ProblemFieldBinding(
-									foundField.declaringClass,
-									name,
-									InheritedNameHidesEnclosingName);
-							if (depth > 0)
-								invocationSite.setDepth(depth);
-							return variableBinding;
-						}
-						break;
-					case CLASS_SCOPE :
-						ClassScope classScope = (ClassScope) scope;
-						SourceTypeBinding enclosingType = classScope.referenceContext.binding;
-						FieldBinding fieldBinding =
-							classScope.findField(enclosingType, name, invocationSite);
-						// Use next line instead if willing to enable protected access accross inner types
-						// FieldBinding fieldBinding = findField(enclosingType, name, invocationSite);
-						if (fieldBinding != null) { // skip it if we did not find anything
-							if (fieldBinding.problemId() == Ambiguous) {
-								if (foundField == null || foundField.problemId() == NotVisible)
-									// supercedes any potential InheritedNameHidesEnclosingName problem
-									return fieldBinding;
-								else
-									// make the user qualify the field, likely wants the first inherited field (javac generates an ambiguous error instead)
-									return new ProblemFieldBinding(
-										fieldBinding.declaringClass,
-										name,
-										InheritedNameHidesEnclosingName);
-							}
-
-							ProblemFieldBinding insideProblem = null;
-							if (fieldBinding.isValidBinding()) {
-								if (!fieldBinding.isStatic()) {
-									if (insideConstructorCall) {
-										insideProblem =
-											new ProblemFieldBinding(
-												fieldBinding.declaringClass,
-												name,
-												NonStaticReferenceInConstructorInvocation);
-									} else if (insideStaticContext) {
-										insideProblem =
-											new ProblemFieldBinding(
-												fieldBinding.declaringClass,
-												name,
-												NonStaticReferenceInStaticContext);
-									}
-								}
-								if (enclosingType == fieldBinding.declaringClass
-									|| environment().options.complianceLevel >= CompilerOptions.JDK1_4){
-									// found a valid field in the 'immediate' scope (ie. not inherited)
-									// OR in 1.4 mode (inherited shadows enclosing)
-									if (foundField == null) {
-										if (depth > 0){
-											invocationSite.setDepth(depth);
-											invocationSite.setActualReceiverType(enclosingType);
-										}
-										// return the fieldBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
-										return insideProblem == null ? fieldBinding : insideProblem;
-									}
-									if (foundField.isValidBinding())
-										// if a valid field was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
-										if (foundField.declaringClass != fieldBinding.declaringClass)
-											// ie. have we found the same field - do not trust field identity yet
-											return new ProblemFieldBinding(
-												fieldBinding.declaringClass,
-												name,
-												InheritedNameHidesEnclosingName);
-								}
-							}
-
-							if (foundField == null
-								|| (foundField.problemId() == NotVisible
-									&& fieldBinding.problemId() != NotVisible)) {
-								// only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is...
-								foundDepth = depth;
-								foundActualReceiverType = enclosingType;
-								foundInsideProblem = insideProblem;
-								foundField = fieldBinding;
-							}
-						}
-						depth++;
-						insideStaticContext |= enclosingType.isStatic();
-						// 1EX5I8Z - accessing outer fields within a constructor call is permitted
-						// in order to do so, we change the flag as we exit from the type, not the method
-						// itself, because the class scope is used to retrieve the fields.
-						MethodScope enclosingMethodScope = scope.methodScope();
-						insideConstructorCall =
-							enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
-						break;
-					case COMPILATION_UNIT_SCOPE :
-						break done;
-				}
-				scope = scope.parent;
-			}
-
-			if (foundInsideProblem != null){
-				return foundInsideProblem;
-			}
-			if (foundField != null) {
-				if (foundField.isValidBinding()){
-					if (foundDepth > 0){
-						invocationSite.setDepth(foundDepth);
-						invocationSite.setActualReceiverType(foundActualReceiverType);
-					}
-					return foundField;
-				}
-				problemField = foundField;
-			}
-		}
-
-		// We did not find a local or instance variable.
-		if ((mask & TYPE) != 0) {
-			if ((binding = getBaseType(name)) != null)
-				return binding;
-			binding = getTypeOrPackage(name, (mask & PACKAGE) == 0 ? TYPE : TYPE | PACKAGE);
-			if (binding.isValidBinding() || mask == TYPE)
-				return binding;
-			// answer the problem type binding if we are only looking for a type
-		} else if ((mask & PACKAGE) != 0) {
-			compilationUnitScope().recordSimpleReference(name);
-			if ((binding = environment().getTopLevelPackage(name)) != null)
-				return binding;
-		}
-		if (problemField != null)
-			return problemField;
-		else
-			return new ProblemBinding(name, enclosingSourceType(), NotFound);
-	}
-
-	/* API
-	 *
-	 *	Answer the constructor binding that corresponds to receiverType, argumentTypes.
-	 *
-	 *	InvocationSite implements 
-	 *		isSuperAccess(); this is used to determine if the discovered constructor is visible.
-	 *
-	 *	If no visible constructor is discovered, an error binding is answered.
-	 */
-	public MethodBinding getConstructor(
-		ReferenceBinding receiverType,
-		TypeBinding[] argumentTypes,
-		InvocationSite invocationSite) {
-
-		compilationUnitScope().recordTypeReference(receiverType);
-		compilationUnitScope().recordTypeReferences(argumentTypes);
-		MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
-		if (methodBinding != null) {
-			if (methodBinding.canBeSeenBy(invocationSite, this))
-				return methodBinding;
-		}
-		MethodBinding[] methods =
-			receiverType.getMethods(ConstructorDeclaration.ConstantPoolName);
-		if (methods == NoMethods) {
-			return new ProblemMethodBinding(
-				ConstructorDeclaration.ConstantPoolName,
-				argumentTypes,
-				NotFound);
-		}
-		MethodBinding[] compatible = new MethodBinding[methods.length];
-		int compatibleIndex = 0;
-		for (int i = 0, length = methods.length; i < length; i++)
-			if (areParametersAssignable(methods[i].parameters, argumentTypes))
-				compatible[compatibleIndex++] = methods[i];
-		if (compatibleIndex == 0)
-			return new ProblemMethodBinding(
-				ConstructorDeclaration.ConstantPoolName,
-				argumentTypes,
-				NotFound);
-		// need a more descriptive error... cannot convert from X to Y
-
-		MethodBinding[] visible = new MethodBinding[compatibleIndex];
-		int visibleIndex = 0;
-		for (int i = 0; i < compatibleIndex; i++) {
-			MethodBinding method = compatible[i];
-			if (method.canBeSeenBy(invocationSite, this))
-				visible[visibleIndex++] = method;
-		}
-		if (visibleIndex == 1)
-			return visible[0];
-		if (visibleIndex == 0)
-			return new ProblemMethodBinding(
-				compatible[0],
-				ConstructorDeclaration.ConstantPoolName,
-				compatible[0].parameters,
-				NotVisible);
-		return mostSpecificClassMethodBinding(visible, visibleIndex);
-	}
-
 	/*
 	 * This retrieves the argument that maps to an enclosing instance of the suitable type,
 	 * 	if not found then answers nil -- do not create one
@@ -880,41 +619,33 @@
 	 * This retrieves the argument that maps to an enclosing instance of the suitable type,
 	 * 	if not found then answers nil -- do not create one
 	 *
-	 *		#implicitThis		  	 					:  the implicit this will be ok
-	 *		#((arg) this$n)								: available as a constructor arg
-	 * 		#((arg) this$n access$m... access$p) 		: available as as a constructor arg + a sequence of synthetic accessors to synthetic fields
-	 * 		#((fieldDescr) this$n access#m... access$p)	: available as a first synthetic field + a sequence of synthetic accessors to synthetic fields
-	 * 		nil 		 														: not found
-	 *	jls 15.9.2
+	 *		#implicitThis		  	 											:  the implicit this will be ok
+	 *		#((arg) this$n)													: available as a constructor arg
+	 * 	#((arg) this$n access$m... access$p) 		: available as as a constructor arg + a sequence of synthetic accessors to synthetic fields
+	 * 	#((fieldDescr) this$n access#m... access$p)	: available as a first synthetic field + a sequence of synthetic accessors to synthetic fields
+	 * 	null 		 															: not found
+	 *	jls 15.9.2 + http://www.ergnosis.com/java-spec-report/java-language/jls-8.8.5.1-d.html
 	 */
 	public Object[] getEmulationPath(
 			ReferenceBinding targetEnclosingType, 
 			boolean onlyExactMatch,
 			boolean ignoreEnclosingArgInConstructorCall) {
-		//TODO: (philippe) investigate why exactly test76 fails if ignoreEnclosingArgInConstructorCall is always false
+				
 		MethodScope currentMethodScope = this.methodScope();
 		SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType();
 
-		// identity check
-		if (!currentMethodScope.isStatic 
-			&& (!currentMethodScope.isConstructorCall || ignoreEnclosingArgInConstructorCall)
-			&& (sourceType == targetEnclosingType
-				|| (!onlyExactMatch && targetEnclosingType.isSuperclassOf(sourceType)))) {
-			if (currentMethodScope.isConstructorCall) {
-				return NoEnclosingInstanceInConstructorCall;
+		// use 'this' if possible
+		if (!currentMethodScope.isConstructorCall && !currentMethodScope.isStatic) {
+			if (sourceType == targetEnclosingType || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(sourceType))) {
+				return EmulationPathToImplicitThis; // implicit this is good enough
 			}
-			if (currentMethodScope.isStatic){
-				return NoEnclosingInstanceInStaticContext;
-			}
-			return EmulationPathToImplicitThis; // implicit this is good enough
 		}
 		if (!sourceType.isNestedType() || sourceType.isStatic()) { // no emulation from within non-inner types
 			if (currentMethodScope.isConstructorCall) {
 				return NoEnclosingInstanceInConstructorCall;
+			} else if (currentMethodScope.isStatic){
+				return NoEnclosingInstanceInStaticContext;
 			}
-				if (currentMethodScope.isStatic){
-					return NoEnclosingInstanceInStaticContext;
-				}
 			return null;
 		}
 		boolean insideConstructor = currentMethodScope.isInsideInitializerOrConstructor();
@@ -922,6 +653,12 @@
 		if (insideConstructor) {
 			SyntheticArgumentBinding syntheticArg;
 			if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(targetEnclosingType, onlyExactMatch)) != null) {
+				// reject allocation and super constructor call
+				if (ignoreEnclosingArgInConstructorCall 
+						&& currentMethodScope.isConstructorCall 
+						&& (sourceType == targetEnclosingType || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(sourceType)))) {
+					return NoEnclosingInstanceInConstructorCall;
+				}
 				return new Object[] { syntheticArg };
 			}
 		}
@@ -941,12 +678,12 @@
 		Object[] path = new Object[2]; // probably at least 2 of them
 		ReferenceBinding currentType = sourceType.enclosingType();
 		if (insideConstructor) {
-			path[0] = ((NestedTypeBinding) sourceType).getSyntheticArgument((SourceTypeBinding) currentType, onlyExactMatch);
+			path[0] = ((NestedTypeBinding) sourceType).getSyntheticArgument(currentType, onlyExactMatch);
 		} else {
 			if (currentMethodScope.isConstructorCall){
 				return NoEnclosingInstanceInConstructorCall;
 			}
-			path[0] = sourceType.getSyntheticField((SourceTypeBinding) currentType, onlyExactMatch);
+			path[0] = sourceType.getSyntheticField(currentType, onlyExactMatch);
 		}
 		if (path[0] != null) { // keep accumulating
 			
@@ -968,7 +705,7 @@
 					}
 				}
 				
-				syntheticField = ((NestedTypeBinding) currentType).getSyntheticField((SourceTypeBinding) currentEnclosingType, onlyExactMatch);
+				syntheticField = ((NestedTypeBinding) currentType).getSyntheticField(currentEnclosingType, onlyExactMatch);
 				if (syntheticField == null) break;
 
 				// append inside the path
@@ -989,34 +726,6 @@
 
 	/* API
      *	
-	 *	Answer the field binding that corresponds to fieldName.
-	 *	Start the lookup at the receiverType.
-	 *	InvocationSite implements
-	 *		isSuperAccess(); this is used to determine if the discovered field is visible.
-	 *	Only fields defined by the receiverType or its supertypes are answered;
-	 *	a field of an enclosing type will not be found using this API.
-	 *
-	 *	If no visible field is discovered, an error binding is answered.
-	 */
-	public FieldBinding getField(
-		TypeBinding receiverType,
-		char[] fieldName,
-		InvocationSite invocationSite) {
-
-		FieldBinding field = findField(receiverType, fieldName, invocationSite);
-		if (field == null)
-			return new ProblemFieldBinding(
-				receiverType instanceof ReferenceBinding
-					? (ReferenceBinding) receiverType
-					: null,
-				fieldName,
-				NotFound);
-		else
-			return field;
-	}
-
-	/* API
-     *	
 	 *	Answer the method binding that corresponds to selector, argumentTypes.
 	 *	Start the lookup at the enclosing type of the receiver.
 	 *	InvocationSite implements 
@@ -1128,7 +837,7 @@
 							
 							if (receiverType == methodBinding.declaringClass
 								|| (receiverType.getMethods(selector)) != NoMethods
-								|| ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= CompilerOptions.JDK1_4)){
+								|| ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= ClassFileConstants.JDK1_4)){
 								// found a valid method in the 'immediate' scope (ie. not inherited)
 								// OR the receiverType implemented a method with the correct name
 								// OR in 1.4 mode (inherited visible shadows enclosing)
@@ -1193,64 +902,21 @@
 			return foundMethod;
 		return new ProblemMethodBinding(selector, argumentTypes, NotFound);
 	}
+	
 
-	/* API
-     *	
-	 *	Answer the method binding that corresponds to selector, argumentTypes.
-	 *	Start the lookup at the receiverType.
-	 *	InvocationSite implements 
-	 *		isSuperAccess(); this is used to determine if the discovered method is visible.
-	 *
-	 *	Only methods defined by the receiverType or its supertypes are answered;
-	 *	use getImplicitMethod() to discover methods of enclosing types.
-	 *
-	 *	If no visible method is discovered, an error binding is answered.
+	
+	/* Answer true if the variable name already exists within the receiver's scope.
 	 */
-	public MethodBinding getMethod(
-		TypeBinding receiverType,
-		char[] selector,
-		TypeBinding[] argumentTypes,
-		InvocationSite invocationSite) {
-
-		if (receiverType.isArrayType())
-			return findMethodForArray(
-				(ArrayBinding) receiverType,
-				selector,
-				argumentTypes,
-				invocationSite);
-		if (receiverType.isBaseType())
-			return new ProblemMethodBinding(selector, argumentTypes, NotFound);
-
-		ReferenceBinding currentType = (ReferenceBinding) receiverType;
-		if (!currentType.canBeSeenBy(this))
-			return new ProblemMethodBinding(selector, argumentTypes, ReceiverTypeNotVisible);
-
-		// retrieve an exact visible match (if possible)
-		MethodBinding methodBinding =
-			findExactMethod(currentType, selector, argumentTypes, invocationSite);
-		if (methodBinding != null)
-			return methodBinding;
-
-		// answers closest approximation, may not check argumentTypes or visibility
-		methodBinding =
-			findMethod(currentType, selector, argumentTypes, invocationSite);
-		if (methodBinding == null)
-			return new ProblemMethodBinding(selector, argumentTypes, NotFound);
-		if (methodBinding.isValidBinding()) {
-			if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
-				return new ProblemMethodBinding(
-					methodBinding,
-					selector,
-					argumentTypes,
-					NotFound);
-			if (!methodBinding.canBeSeenBy(currentType, invocationSite, this))
-				return new ProblemMethodBinding(
-					methodBinding,
-					selector,
-					methodBinding.parameters,
-					NotVisible);
+	public final boolean isDuplicateLocalVariable(char[] name) {
+		BlockScope current = this;
+		while (true) {
+			for (int i = 0; i < localIndex; i++) {
+				if (CharOperation.equals(name, current.locals[i].name))
+					return true;
+			}
+			if (current.kind != BLOCK_SCOPE) return false;
+			current = (BlockScope)current.parent;
 		}
-		return methodBinding;
 	}
 
 	public int maxShiftedOffset() {
@@ -1305,6 +971,20 @@
 		return methodScope().referenceType();
 	}
 
+	/*
+	 * Answer the index of this scope relatively to its parent.
+	 * For method scope, answers -1 (not a classScope relative position)
+	 */
+	public int scopeIndex() {
+		if (this instanceof MethodScope) return -1;
+		BlockScope parentScope = (BlockScope)parent;
+		Scope[] parentSubscopes = parentScope.subscopes;
+		for (int i = 0, max = parentScope.subscopeCount; i < max; i++) {
+			if (parentSubscopes[i] == this) return i;
+		}
+		return -1;
+	}
+	
 	// start position in this scope - for ordering scopes vs. variables
 	int startIndex() {
 		return startIndex;
@@ -1317,7 +997,7 @@
 	public String toString(int tab) {
 
 		String s = basicToString(tab);
-		for (int i = 0; i < scopeIndex; i++)
+		for (int i = 0; i < subscopeCount; i++)
 			if (subscopes[i] instanceof BlockScope)
 				s += ((BlockScope) subscopes[i]).toString(tab + 1) + "\n"; //$NON-NLS-1$
 		return s;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index 8108dc3..5374f72 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -38,7 +38,7 @@
 			sourceType.superInterfaces = new ReferenceBinding[] { supertype };
 		} else {
 			sourceType.superclass = supertype;
-			sourceType.superInterfaces = TypeBinding.NoSuperInterfaces;
+			sourceType.superInterfaces = TypeConstants.NoSuperInterfaces;
 		}
 		connectMemberTypes();
 		buildFieldsAndMethods();
@@ -70,7 +70,7 @@
 				if (referenceContext.binding.isInterface())
 					problemReporter().interfaceCannotHaveInitializers(referenceContext.binding, field);
 			} else {
-				FieldBinding fieldBinding = new FieldBinding(field, null, referenceContext.binding);
+				FieldBinding fieldBinding = new FieldBinding(field, null, field.modifiers | AccUnresolved, referenceContext.binding);
 				// field's type will be resolved when needed for top level types
 				checkAndSetModifiersForField(fieldBinding, field);
 
@@ -303,26 +303,37 @@
 			// checks for member types before local types to catch local members
 			if (enclosingType.isStrictfp())
 				modifiers |= AccStrictfp;
-			if (enclosingType.isDeprecated())
+			if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
 				modifiers |= AccDeprecatedImplicitly;
 			if (enclosingType.isInterface())
 				modifiers |= AccPublic;
 		} else if (sourceType.isLocalType()) {
-			if (sourceType.isAnonymousType())
-				modifiers |= AccFinal;
-			ReferenceContext refContext = methodScope().referenceContext;
+			if (sourceType.isAnonymousType()) 
+			    modifiers |= AccFinal;
+			MethodScope methodScope = methodScope();
+			ReferenceContext refContext = methodScope.referenceContext;
 			if (refContext instanceof TypeDeclaration) {
-				ReferenceBinding type = ((TypeDeclaration) refContext).binding;
-				if (type.isStrictfp())
-					modifiers |= AccStrictfp;
-				if (type.isDeprecated())
-					modifiers |= AccDeprecatedImplicitly;
+			    
+				SourceTypeBinding type = ((TypeDeclaration) refContext).binding;
+
+				// inside field declaration ? check field modifier to see if deprecated
+				if (methodScope.initializedField != null) {
+						// currently inside this field initialization
+					if (methodScope.initializedField.isViewedAsDeprecated() && !sourceType.isDeprecated()){
+						modifiers |= AccDeprecatedImplicitly;
+					}
+				} else {
+					if (type.isStrictfp())
+						modifiers |= AccStrictfp;
+					if (type.isViewedAsDeprecated() && !sourceType.isDeprecated()) 
+						modifiers |= AccDeprecatedImplicitly;
+				}					
 			} else {
 				MethodBinding method = ((AbstractMethodDeclaration) refContext).binding;
 				if (method != null){
 					if (method.isStrictfp())
 						modifiers |= AccStrictfp;
-					if (method.isDeprecated())
+					if (method.isViewedAsDeprecated() && !sourceType.isDeprecated())
 						modifiers |= AccDeprecatedImplicitly;
 				}
 			}
@@ -581,6 +592,7 @@
 		}
 		ReferenceBinding superclass = findSupertype(referenceContext.superclass);
 		if (superclass != null) { // is null if a cycle was detected cycle
+			referenceContext.superclass.resolvedType = superclass; // hold onto the problem type
 			if (!superclass.isValidBinding()) {
 				problemReporter().invalidSuperclass(sourceType, referenceContext.superclass, superclass);
 			} else if (superclass.isInterface()) {
@@ -589,7 +601,6 @@
 				problemReporter().classExtendFinalClass(sourceType, referenceContext.superclass, superclass);
 			} else {
 				// only want to reach here when no errors are reported
-				referenceContext.superclass.resolvedType = superclass;
 				sourceType.superclass = superclass;
 				return true;
 			}
@@ -629,6 +640,7 @@
 				noProblems = false;
 				continue nextInterface;
 			}
+			referenceContext.superInterfaces[i].resolvedType = superInterface; // hold onto the problem type
 			if (!superInterface.isValidBinding()) {
 				problemReporter().invalidSuperinterface(
 					sourceType,
@@ -653,7 +665,6 @@
 				continue nextInterface;
 			}
 
-			referenceContext.superInterfaces[i].resolvedType = superInterface;
 			// only want to reach here when no errors are reported
 			interfaceBindings[count++] = superInterface;
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
index 7b66433..27b412e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
@@ -14,9 +14,10 @@
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.jdt.internal.compiler.util.CompoundNameVector;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfType;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
 import org.eclipse.jdt.internal.compiler.util.SimpleNameVector;
@@ -28,6 +29,7 @@
 	public char[][] currentPackageName;
 	public PackageBinding fPackage;
 	public ImportBinding[] imports;
+	public HashtableOfObject resolvedSingeTypeImports;
 	
 	public SourceTypeBinding[] topLevelTypes;
 
@@ -129,20 +131,8 @@
 		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;
+		imports = getDefaultImports();
 		return;
 	}
 
@@ -157,7 +147,7 @@
 		}
 	}
 	ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
-	resolvedImports[0] = environment.defaultImports[0];
+	resolvedImports[0] = getDefaultImports()[0];
 	int index = 1;
 
 	nextImport : for (int i = 0; i < numberOfStatements; i++) {
@@ -277,7 +267,7 @@
 		}
 	}
 	ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
-	resolvedImports[0] = environment.defaultImports[0];
+	resolvedImports[0] = getDefaultImports()[0];
 	int index = 1;
 
 	nextImport : for (int i = 0; i < numberOfStatements; i++) {
@@ -344,6 +334,14 @@
 	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();
@@ -376,7 +374,7 @@
 	ReferenceBinding type;
 	if (binding == null) {
 		if (environment.defaultPackage == null
-				|| environment.options.complianceLevel >= CompilerOptions.JDK1_4){
+				|| environment.options.complianceLevel >= ClassFileConstants.JDK1_4){
 			return new ProblemReferenceBinding(
 				CharOperation.subarray(compoundName, 0, i),
 				NotFound);
@@ -411,7 +409,7 @@
 		// findType records the reference
 		// the name cannot be a package
 		if (environment.defaultPackage == null 
-			|| environment.options.complianceLevel >= CompilerOptions.JDK1_4)
+			|| environment.options.complianceLevel >= ClassFileConstants.JDK1_4)
 			return new ProblemReferenceBinding(compoundName, NotFound);
 		ReferenceBinding typeBinding = findType(compoundName[0], environment.defaultPackage, fPackage);
 		if (typeBinding == null)
@@ -421,6 +419,20 @@
 	}
 	return findOnDemandImport(compoundName);
 }
+ImportBinding[] getDefaultImports() {
+	// initialize the default imports if necessary... share the default java.lang.* import
+	if (environment.defaultImports != null) return environment.defaultImports;
+
+	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());
+
+	return environment.defaultImports = new ImportBinding[] {new ImportBinding(JAVA_LANG, true, importBinding, null)};
+}
 /* Answer the problem reporter to use for raising new problems.
 *
 * Note that as a side-effect, this updates the current reference context
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java
index d9d06aa..b99f214 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java
@@ -30,6 +30,7 @@
 	final int AccUnresolved = 0x2000000; // bit26
 	final int AccClearPrivateModifier = 0x4000000; // bit27 might be requested during private access emulation
 	final int AccBlankFinal = 0x4000000; // bit27 for blank final variables
+	final int AccIsDefaultConstructor = 0x4000000; // bit27 for default constructor
 	final int AccPrivateUsed = 0x8000000; // bit28 used to diagnose unused private members
 	final int AccVisibilityMASK = AccPublic | AccProtected | AccPrivate;
 	
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
index a2f5e06..454425f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
@@ -16,6 +16,7 @@
 public class FieldBinding extends VariableBinding {
 	public ReferenceBinding declaringClass;
 protected FieldBinding() {
+	// for creating problem field
 }
 public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant) {
 	this.modifiers = modifiers;
@@ -29,10 +30,9 @@
 		if (this.declaringClass.isViewedAsDeprecated() && !isDeprecated())
 			this.modifiers |= AccDeprecatedImplicitly;
 }
-public FieldBinding(FieldDeclaration field, TypeBinding type, ReferenceBinding declaringClass) {
-	this(field.name, type, field.modifiers, declaringClass, null);
-
-	field.binding = this;
+public FieldBinding(FieldDeclaration field, TypeBinding type, int modifiers, ReferenceBinding declaringClass) {
+	this(field.name, type, modifiers, declaringClass, null);
+	field.binding = this; // record binding in declaration
 }
 // special API used to change field declaring class for runtime visibility check
 public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaringClass) {
@@ -127,12 +127,12 @@
 	// receiverType can be an array binding in one case... see if you can change it
 	if (receiverType instanceof ArrayBinding)
 		return false;
-	ReferenceBinding type = (ReferenceBinding) receiverType;
+	ReferenceBinding currentType = (ReferenceBinding) receiverType;
 	PackageBinding declaringPackage = declaringClass.fPackage;
 	do {
-		if (declaringClass == type) return true;
-		if (declaringPackage != type.fPackage) return false;
-	} while ((type = type.superclass()) != null);
+		if (declaringClass == currentType) return true;
+		if (declaringPackage != currentType.fPackage) return false;
+	} while ((currentType = currentType.superclass()) != null);
 	return false;
 }
 public final int getAccessFlags() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
index be127bf..a5fcbf4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
@@ -11,7 +11,7 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 public final class LocalTypeBinding extends NestedTypeBinding {
@@ -26,7 +26,7 @@
 		scope,
 		enclosingType);
 
-	if (this.sourceName == AnonymousLocalTypeDeclaration.ANONYMOUS_EMPTY_NAME)
+	if (this.sourceName == TypeDeclaration.ANONYMOUS_EMPTY_NAME)
 		this.tagBits |= AnonymousTypeMask;
 	else
 		this.tagBits |= LocalTypeMask;
@@ -36,7 +36,7 @@
 * all its dependents so as to update them (see updateInnerEmulationDependents()).
 */
 
-public void addInnerEmulationDependent(BlockScope scope, boolean wasEnclosingInstanceSupplied) {
+public void addInnerEmulationDependent(BlockScope dependentScope, boolean wasEnclosingInstanceSupplied) {
 	int index;
 	if (dependents == null) {
 		index = 0;
@@ -44,11 +44,11 @@
 	} else {
 		index = dependents.length;
 		for (int i = 0; i < index; i++)
-			if (dependents[i].scope == scope)
+			if (dependents[i].scope == dependentScope)
 				return; // already stored
 		System.arraycopy(dependents, 0, (dependents = new InnerEmulationDependency[index + 1]), 0, index);
 	}
-	dependents[index] = new InnerEmulationDependency(scope, wasEnclosingInstanceSupplied);
+	dependents[index] = new InnerEmulationDependency(dependentScope, wasEnclosingInstanceSupplied);
 	//  System.out.println("Adding dependency: "+ new String(scope.enclosingType().readableName()) + " --> " + new String(this.readableName()));
 }
 /* Answer the receiver's constant pool name.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
index 65c2465..a4a0aae 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
@@ -35,7 +35,8 @@
 		this.name = name;
 		this.type = type;
 		this.modifiers = modifiers;
-		if (this.isArgument = isArgument)
+		this.isArgument = isArgument;
+		if (isArgument)
 			this.constant = Constant.NotAConstant;
 	}
 	
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index 160f686..8dbb054 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -25,6 +25,7 @@
 	char[] signature;
 
 protected MethodBinding() {
+	// for creating problem or synthetic method
 }
 public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
 	this.modifiers = modifiers;
@@ -206,7 +207,13 @@
 	} while ((type = type.superclass()) != null);
 	return false;
 }
-
+/* 
+ * Answer the declaring class to use in the constant pool
+ * may not be a reference binding (see subtypes)
+ */
+public TypeBinding constantPoolDeclaringClass() {
+	return this.declaringClass;
+}
 /* Answer the receiver's constant pool name.
 *
 * <init> for constructors
@@ -395,7 +402,7 @@
 	return buffer.toString().toCharArray();
 }
 
-protected final void selector(char[] selector) {
+protected final void setSelector(char[] selector) {
 	this.selector = selector;
 	this.signature = null;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
index 93def53..b620815 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
@@ -34,9 +34,10 @@
 	public boolean isStatic; // method modifier or initializer one
 
 	//fields used during name resolution
-	public static final int NotInFieldDecl = -1; //must be a negative value 
 	public boolean isConstructorCall = false; 
-	public int fieldDeclarationIndex = NotInFieldDecl; 
+	public FieldBinding initializedField; // the field being initialized
+	public int lastVisibleFieldID = -1; // the ID of the last field which got declared 
+	// note that #initializedField can be null AND lastVisibleFieldID >= 0, when processing instance field initializers.
 
 	// flow analysis
 	public int analysisIndex; // for setting flow-analysis id
@@ -246,7 +247,7 @@
 			// do not report fake used variable
 			if (isReportingUnusedArgument
 					&& local.useFlag == LocalVariableBinding.UNUSED
-					&& ((local.declaration.bits & AstNode.IsLocalDeclarationReachableMASK) != 0)) { // declaration is reachable
+					&& ((local.declaration.bits & ASTNode.IsLocalDeclarationReachableMASK) != 0)) { // declaration is reachable
 				this.problemReporter().unusedArgument(local.declaration);
 			}
 
@@ -279,7 +280,7 @@
 					this.offset++;
 				}
 				if (this.offset > 0xFF) { // no more than 255 words of arguments
-					this.problemReporter().noMoreAvailableSpaceForArgument(argument, (AstNode)this.referenceContext); 
+					this.problemReporter().noMoreAvailableSpaceForArgument(argument, (ASTNode)this.referenceContext); 
 				}
 			}
 		}
@@ -299,6 +300,9 @@
 		SourceTypeBinding declaringClass = referenceType().binding;
 		int modifiers = method.modifiers | AccUnresolved;
 		if (method.isConstructor()) {
+			if (method.isDefaultConstructor()) {
+				modifiers |= AccIsDefaultConstructor;
+			}
 			method.binding = new MethodBinding(modifiers, null, null, declaringClass);
 			checkAndSetModifiersForConstructor(method.binding);
 		} else {
@@ -308,7 +312,6 @@
 				new MethodBinding(modifiers, method.selector, null, null, null, declaringClass);
 			checkAndSetModifiersForMethod(method.binding);
 		}
-
 		this.isStatic = method.binding.isStatic();
 		return method.binding;
 	}
@@ -326,9 +329,10 @@
 	public FieldBinding findField(
 		TypeBinding receiverType,
 		char[] fieldName,
-		InvocationSite invocationSite) {
+		InvocationSite invocationSite,
+		boolean needResolve) {
 
-		FieldBinding field = super.findField(receiverType, fieldName, invocationSite);
+		FieldBinding field = super.findField(receiverType, fieldName, invocationSite, needResolve);
 		if (field == null)
 			return null;
 		if (!field.isValidBinding())
@@ -357,6 +361,11 @@
 		return field;
 	}
 
+	public boolean isInsideConstructor() {
+
+		return (referenceContext instanceof ConstructorDeclaration);
+	}
+	
 	public boolean isInsideInitializer() {
 
 		return (referenceContext instanceof TypeDeclaration);
@@ -443,13 +452,21 @@
 		return lastIndex++;
 	}
 
+	/* Answer the reference method of this scope, or null if initialization scoope.
+	*/
+	public AbstractMethodDeclaration referenceMethod() {
+
+		if (referenceContext instanceof AbstractMethodDeclaration) return (AbstractMethodDeclaration) referenceContext;
+		return null;
+	}
+
 	/* Answer the reference type of this scope.
 	*
 	* It is the nearest enclosing type of this scope.
 	*/
 	public TypeDeclaration referenceType() {
 
-		return (TypeDeclaration) ((ClassScope) parent).referenceContext;
+		return ((ClassScope) parent).referenceContext;
 	}
 
 	String basicToString(int tab) {
@@ -465,7 +482,8 @@
 			s += newLine + "\t" + locals[i].toString(); //$NON-NLS-1$
 		s += newLine + "startIndex = " + startIndex; //$NON-NLS-1$
 		s += newLine + "isConstructorCall = " + isConstructorCall; //$NON-NLS-1$
-		s += newLine + "fieldDeclarationIndex = " + fieldDeclarationIndex; //$NON-NLS-1$
+		s += newLine + "initializedField = " + initializedField; //$NON-NLS-1$
+		s += newLine + "lastVisibleFieldID = " + lastVisibleFieldID; //$NON-NLS-1$
 		s += newLine + "referenceContext = " + referenceContext; //$NON-NLS-1$
 		return s;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
index 9035629..1145f60 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
@@ -48,14 +48,44 @@
 	this.errorException = null;
 	this.environment = environment;
 }
+private boolean areParametersEqual(MethodBinding one, MethodBinding two) {
+	TypeBinding[] oneArgs = one.parameters;
+	TypeBinding[] twoArgs = two.parameters;
+	if (oneArgs == twoArgs) return true;
+
+	int length = oneArgs.length;
+	if (length != twoArgs.length) return false;
+
+	for (int i = 0; i < length; i++)
+		if (!areTypesEqual(oneArgs[i], twoArgs[i])) return false;
+	return true;
+}
+private boolean areTypesEqual(TypeBinding one, TypeBinding two) {
+	if (one == two) return true;
+	if (one instanceof ReferenceBinding && two instanceof ReferenceBinding)
+		// can compare unresolved to resolved reference bindings
+		return CharOperation.equals(((ReferenceBinding) one).compoundName, ((ReferenceBinding) two).compoundName);
+	return false; // all other type bindings are identical
+}
+private void checkAbstractMethod(MethodBinding abstractMethod) {
+	if (mustImplementAbstractMethod(abstractMethod)) {
+		TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
+		if (typeDeclaration != null) {
+			MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(abstractMethod);
+			missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod);
+		} else {
+			this.problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod);
+		}
+	}
+}
 private void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length) {
 	currentMethod.modifiers |= CompilerModifiers.AccOverriding;
-	for (int i = length; --i >= 0;) {
+	nextMethod : for (int i = length; --i >= 0;) {
 		MethodBinding inheritedMethod = methods[i];
 		if (!currentMethod.isAbstract() && inheritedMethod.isAbstract())
 			currentMethod.modifiers |= CompilerModifiers.AccImplementing;
 
-		if (currentMethod.returnType != inheritedMethod.returnType) {
+		if (!areTypesEqual(currentMethod.returnType, inheritedMethod.returnType)) {
 			this.problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod);
 		} else if (currentMethod.isStatic() != inheritedMethod.isStatic()) {  // Cannot override a static method or hide an instance method
 			this.problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
@@ -66,9 +96,18 @@
 				this.problemReporter(currentMethod).finalMethodCannotBeOverridden(currentMethod, inheritedMethod);
 			if (!this.isAsVisible(currentMethod, inheritedMethod))
 				this.problemReporter(currentMethod).visibilityConflict(currentMethod, inheritedMethod);
-			if (inheritedMethod.isViewedAsDeprecated())
-				if (!currentMethod.isViewedAsDeprecated() || environment.options.reportDeprecationInsideDeprecatedCode)
+			if (environment.options.reportDeprecationWhenOverridingDeprecatedMethod && inheritedMethod.isViewedAsDeprecated()) {
+				if (!currentMethod.isViewedAsDeprecated() || environment.options.reportDeprecationInsideDeprecatedCode) {
+					// check against the other inherited methods to see if they hide this inheritedMethod
+					ReferenceBinding declaringClass = inheritedMethod.declaringClass;
+					if (declaringClass.isInterface())
+						for (int j = length; --j >= 0;)
+							if (i != j && methods[j].declaringClass.implementsInterface(declaringClass, false))
+								continue nextMethod;
+
 					this.problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod);
+				}
+			}
 		}
 	}
 }
@@ -79,8 +118,8 @@
 Unchecked exceptions (compatible with runtime & error) are ignored (see the spec on pg. 203).
 */
 private void checkExceptions(MethodBinding newMethod, MethodBinding inheritedMethod) {
-	ReferenceBinding[] newExceptions = newMethod.thrownExceptions;
-	ReferenceBinding[] inheritedExceptions = inheritedMethod.thrownExceptions;
+	ReferenceBinding[] newExceptions = resolvedExceptionTypesFor(newMethod);
+	ReferenceBinding[] inheritedExceptions = resolvedExceptionTypesFor(inheritedMethod);
 	for (int i = newExceptions.length; --i >= 0;) {
 		ReferenceBinding newException = newExceptions[i];
 		int j = inheritedExceptions.length;
@@ -93,7 +132,7 @@
 private void checkInheritedMethods(MethodBinding[] methods, int length) {
 	TypeBinding returnType = methods[0].returnType;
 	int index = length;
-	while (--index > 0 && returnType == methods[index].returnType);
+	while (--index > 0 && areTypesEqual(returnType, methods[index].returnType));
 	if (index > 0) {  // All inherited methods do NOT have the same vmSignature
 		this.problemReporter().inheritedMethodsHaveIncompatibleReturnTypes(this.type, methods, length);
 		return;
@@ -110,15 +149,17 @@
 	}
 	if (concreteMethod == null) {
 		if (this.type.isClass() && !this.type.isAbstract()) {
-			for (int i = length; --i >= 0;)
-				if (!mustImplementAbstractMethod(methods[i])) return;  // have already reported problem against the concrete superclass
-
-			TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
-			if (typeDeclaration != null) {
-				MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(methods[0]);
-				missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
-			} else {
-				this.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
+			for (int i = length; --i >= 0;) {
+				if (mustImplementAbstractMethod(methods[i])) {
+					TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
+					if (typeDeclaration != null) {
+						MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(methods[0]);
+						missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
+					} else {
+						this.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
+					}
+					return;
+				}
 			}
 		}
 		return;
@@ -162,52 +203,49 @@
 private void checkMethods() { 
 	boolean mustImplementAbstractMethods = this.type.isClass() && !this.type.isAbstract();
 	char[][] methodSelectors = this.inheritedMethods.keyTable;
-	for (int s = methodSelectors.length; --s >= 0;) {
-		if (methodSelectors[s] != null) {
-			MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(methodSelectors[s]);
-			MethodBinding[] inherited = (MethodBinding[]) this.inheritedMethods.valueTable[s];
+	nextSelector : for (int s = methodSelectors.length; --s >= 0;) {
+		if (methodSelectors[s] == null) continue nextSelector;
 
-			int index = -1;
-			MethodBinding[] matchingInherited = new MethodBinding[inherited.length];
-			if (current != null) {
-				for (int i = 0, length1 = current.length; i < length1; i++) {
-					while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods
-					MethodBinding currentMethod = current[i];
-					for (int j = 0, length2 = inherited.length; j < length2; j++) {
-						if (inherited[j] != null && currentMethod.areParametersEqual(inherited[j])) {
-							matchingInherited[++index] = inherited[j];
-							inherited[j] = null; // do not want to find it again
-						}
-					}
-					if (index >= 0)
-						this.checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1); // pass in the length of matching
-				}
-			}
-			for (int i = 0, length = inherited.length; i < length; i++) {
+		MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(methodSelectors[s]);
+		MethodBinding[] inherited = (MethodBinding[]) this.inheritedMethods.valueTable[s];
+		if (inherited.length == 1 && current == null) { // handle the common case
+			if (mustImplementAbstractMethods && inherited[0].isAbstract())
+				checkAbstractMethod(inherited[0]);
+			continue nextSelector;
+		}
+
+		int index = -1;
+		MethodBinding[] matchingInherited = new MethodBinding[inherited.length];
+		if (current != null) {
+			for (int i = 0, length1 = current.length; i < length1; i++) {
 				while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods
-				if (inherited[i] != null) {
-					matchingInherited[++index] = inherited[i];
-					for (int j = i + 1; j < length; j++) {
-						if (inherited[j] != null && inherited[i].areParametersEqual(inherited[j])) {
-							matchingInherited[++index] = inherited[j];
-							inherited[j] = null; // do not want to find it again
-						}
+				MethodBinding currentMethod = current[i];
+				for (int j = 0, length2 = inherited.length; j < length2; j++) {
+					if (inherited[j] != null && areParametersEqual(currentMethod, inherited[j])) {
+						matchingInherited[++index] = inherited[j];
+						inherited[j] = null; // do not want to find it again
 					}
 				}
-				if (index > 0) {
-					this.checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching
-				} else if (mustImplementAbstractMethods && index == 0 && matchingInherited[0].isAbstract()) {
-					if (mustImplementAbstractMethod(matchingInherited[0])) {
-						TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
-						if (typeDeclaration != null) {
-							MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(matchingInherited[0]);
-							missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, matchingInherited[0]);
-						} else {
-							this.problemReporter().abstractMethodMustBeImplemented(this.type, matchingInherited[0]);
-						}
+				if (index >= 0)
+					this.checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1); // pass in the length of matching
+			}
+		}
+
+		for (int i = 0, length = inherited.length; i < length; i++) {
+			while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods
+			if (inherited[i] != null) {
+				matchingInherited[++index] = inherited[i];
+				for (int j = i + 1; j < length; j++) {
+					if (inherited[j] != null && areParametersEqual(inherited[i], inherited[j])) {
+						matchingInherited[++index] = inherited[j];
+						inherited[j] = null; // do not want to find it again
 					}
 				}
 			}
+			if (index > 0)
+				this.checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching
+			else if (mustImplementAbstractMethods && index == 0 && matchingInherited[0].isAbstract())
+				checkAbstractMethod(matchingInherited[0]);
 		}
 	}
 }
@@ -221,7 +259,7 @@
 		MethodBinding[] methods = superType.getMethods(selector);
 		nextMethod : for (int m = methods.length; --m >= 0;) {
 			MethodBinding method = methods[m];
-			if (method.returnType != abstractMethod.returnType || !method.areParametersEqual(abstractMethod))
+			if (!areTypesEqual(method.returnType, abstractMethod.returnType) || !areParametersEqual(method, abstractMethod))
 				continue nextMethod;
 			if (method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())
 				continue nextMethod;
@@ -246,9 +284,11 @@
 */
 private void computeInheritedMethods() {
 	this.inheritedMethods = new HashtableOfObject(51); // maps method selectors to an array of methods... must search to match paramaters & return type
-	ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
-	int lastPosition = 0;
-	interfacesToVisit[lastPosition] = type.superInterfaces();
+	ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[3][];
+	int lastPosition = -1;
+	ReferenceBinding[] itsInterfaces = type.superInterfaces();
+	if (itsInterfaces != NoSuperInterfaces)
+		interfacesToVisit[++lastPosition] = itsInterfaces;
 
 	ReferenceBinding superType = this.type.isClass()
 		? this.type.superclass()
@@ -258,21 +298,20 @@
 
 	while (superType != null) {
 		if (superType.isValidBinding()) {
-			ReferenceBinding[] itsInterfaces = superType.superInterfaces();
-			if (itsInterfaces != NoSuperInterfaces) {
+			if ((itsInterfaces = superType.superInterfaces()) != NoSuperInterfaces) {
 				if (++lastPosition == interfacesToVisit.length)
 					System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
 				interfacesToVisit[lastPosition] = itsInterfaces;
 			}
 
-			MethodBinding[] methods = superType.methods();
+			MethodBinding[] methods = superType.unResolvedMethods();
 			nextMethod : for (int m = methods.length; --m >= 0;) {
 				MethodBinding method = methods[m];
-				if (!(method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())) { // look at all methods which are NOT private or constructors or default abstract
+				if (!(method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())) {
 					MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(method.selector);
 					if (existingMethods != null) {
 						for (int i = 0, length = existingMethods.length; i < length; i++) {
-							if (method.returnType == existingMethods[i].returnType && method.areParametersEqual(existingMethods[i])) {
+							if (areTypesEqual(method.returnType, existingMethods[i].returnType) && areParametersEqual(method, existingMethods[i])) {
 								if (method.isDefault() && method.isAbstract() && method.declaringClass.fPackage != type.fPackage)
 									checkPackagePrivateAbstractMethod(method);
 								continue nextMethod;
@@ -281,12 +320,12 @@
 					}
 					if (nonVisibleDefaultMethods != null)
 						for (int i = 0; i < nonVisibleCount; i++)
-							if (method.returnType == nonVisibleDefaultMethods[i].returnType
-								&& CharOperation.equals(method.selector, nonVisibleDefaultMethods[i].selector)
-								&& method.areParametersEqual(nonVisibleDefaultMethods[i])) 
+							if (CharOperation.equals(method.selector, nonVisibleDefaultMethods[i].selector)
+								&& areTypesEqual(method.returnType, nonVisibleDefaultMethods[i].returnType)
+								&& areParametersEqual(method, nonVisibleDefaultMethods[i])) 
 									continue nextMethod;
 
-					if (!(method.isDefault() && method.declaringClass.fPackage != type.fPackage)) { // ignore methods which have default visibility and are NOT defined in another package
+					if (!method.isDefault() || method.declaringClass.fPackage == type.fPackage) {
 						if (existingMethods == null)
 							existingMethods = new MethodBinding[1];
 						else
@@ -308,7 +347,7 @@
 						MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(method.selector);
 						if (current != null) { // non visible methods cannot be overridden so a warning is issued
 							foundMatch : for (int i = 0, length = current.length; i < length; i++) {
-								if (method.returnType == current[i].returnType && method.areParametersEqual(current[i])) {
+								if (areTypesEqual(method.returnType, current[i].returnType) && areParametersEqual(method, current[i])) {
 									this.problemReporter().overridesPackageDefaultMethod(current[i], method);
 									break foundMatch;
 								}
@@ -328,14 +367,13 @@
 			if ((superType.tagBits & InterfaceVisited) == 0) {
 				superType.tagBits |= InterfaceVisited;
 				if (superType.isValidBinding()) {
-					ReferenceBinding[] itsInterfaces = superType.superInterfaces();
-					if (itsInterfaces != NoSuperInterfaces) {
+					if ((itsInterfaces = superType.superInterfaces()) != NoSuperInterfaces) {
 						if (++lastPosition == interfacesToVisit.length)
 							System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
 						interfacesToVisit[lastPosition] = itsInterfaces;
 					}
 
-					MethodBinding[] methods = superType.methods();
+					MethodBinding[] methods = superType.unResolvedMethods();
 					for (int m = methods.length; --m >= 0;) { // Interface methods are all abstract public
 						MethodBinding method = methods[m];
 						MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(method.selector);
@@ -427,13 +465,27 @@
 		reporter.referenceContext = currentMethod.sourceMethod();
 	return reporter;
 }
+ReferenceBinding[] resolvedExceptionTypesFor(MethodBinding method) {
+	ReferenceBinding[] exceptions = method.thrownExceptions;
+	if ((method.modifiers & CompilerModifiers.AccUnresolved) == 0)
+		return exceptions;
+
+	if (!(method.declaringClass instanceof BinaryTypeBinding))
+		return TypeConstants.NoExceptions; // safety check
+	BinaryTypeBinding binaryType = (BinaryTypeBinding) method.declaringClass;
+
+	for (int i = exceptions.length; --i >= 0;)
+		if (exceptions[i] instanceof UnresolvedReferenceBinding)
+			exceptions[i] = (ReferenceBinding) binaryType.resolveType(exceptions[i]);
+	return exceptions;
+}
 private ReferenceBinding runtimeException() {
 	if (runtimeException == null)
 		this.runtimeException = this.type.scope.getJavaLangRuntimeException();
 	return runtimeException;
 }
-public void verify(SourceTypeBinding type) {
-	this.type = type;
+public void verify(SourceTypeBinding someType) {
+	this.type = someType;
 	this.computeMethods();
 	this.computeInheritedMethods();
 	this.checkMethods();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
index 5327917..b824150 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
@@ -58,23 +58,23 @@
 	/* Add a new synthetic argument for <enclosingType>.
 	* Answer the new argument or the existing argument if one already existed.
 	*/
-	public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding enclosingType) {
+	public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding targetEnclosingType) {
 		SyntheticArgumentBinding synthLocal = null;
 		if (enclosingInstances == null) {
-			synthLocal = new SyntheticArgumentBinding(enclosingType);
+			synthLocal = new SyntheticArgumentBinding(targetEnclosingType);
 			enclosingInstances = new SyntheticArgumentBinding[] {synthLocal};
 		} else {
 			int size = enclosingInstances.length;
 			int newArgIndex = size;
 			for (int i = size; --i >= 0;) {
-				if (enclosingInstances[i].type == enclosingType)
+				if (enclosingInstances[i].type == targetEnclosingType)
 					return enclosingInstances[i]; // already exists
-				if (this.enclosingType() == enclosingType)
+				if (this.enclosingType() == targetEnclosingType)
 					newArgIndex = 0;
 			}
 			SyntheticArgumentBinding[] newInstances = new SyntheticArgumentBinding[size + 1];
 			System.arraycopy(enclosingInstances, 0, newInstances, newArgIndex == 0 ? 1 : 0, size);
-			newInstances[newArgIndex] = synthLocal = new SyntheticArgumentBinding(enclosingType);
+			newInstances[newArgIndex] = synthLocal = new SyntheticArgumentBinding(targetEnclosingType);
 			enclosingInstances = newInstances;
 		}
 		//System.out.println("Adding synth arg for enclosing type: " + new String(enclosingType.readableName()) + " to: " + new String(this.readableName()));
@@ -98,12 +98,12 @@
 	/* Add a new synthetic argument and field for <enclosingType>.
 	* Answer the new argument or the existing argument if one already existed.
 	*/
-	public SyntheticArgumentBinding addSyntheticArgumentAndField(ReferenceBinding enclosingType) {
-		SyntheticArgumentBinding synthLocal = addSyntheticArgument(enclosingType);
+	public SyntheticArgumentBinding addSyntheticArgumentAndField(ReferenceBinding targetEnclosingType) {
+		SyntheticArgumentBinding synthLocal = addSyntheticArgument(targetEnclosingType);
 		if (synthLocal == null) return null;
 	
 		if (synthLocal.matchingField == null)
-			synthLocal.matchingField = addSyntheticField(enclosingType);
+			synthLocal.matchingField = addSyntheticField(targetEnclosingType);
 		return synthLocal;
 	}
 
@@ -114,10 +114,9 @@
 	
 		int slotSize = 0; 
 		// insert enclosing instances first, followed by the outerLocals
-		SyntheticArgumentBinding[] enclosingInstances = this.syntheticEnclosingInstances();
-		int enclosingInstancesCount = enclosingInstances == null ? 0 : enclosingInstances.length;
+		int enclosingInstancesCount = this.enclosingInstances == null ? 0 : this.enclosingInstances.length;
 		for (int i = 0; i < enclosingInstancesCount; i++){
-			SyntheticArgumentBinding argument = enclosingInstances[i];
+			SyntheticArgumentBinding argument = this.enclosingInstances[i];
 			// position the enclosing instance synthetic arg
 			argument.resolvedPosition = slotSize + 1; // shift by 1 to leave room for aload0==this
 			if (slotSize + 1 > 0xFF) { // no more than 255 words of arguments
@@ -132,10 +131,9 @@
 		this.enclosingInstancesSlotSize = slotSize; 
 		
 		slotSize = 0; // reset, outer local are not positionned yet, since will be appended to user arguments
-		SyntheticArgumentBinding[] outerLocals = this.syntheticOuterLocalVariables();
-		int outerLocalsCount = outerLocals == null ? 0 : outerLocals.length;
+		int outerLocalsCount = this.outerLocalVariables == null ? 0 : this.outerLocalVariables.length;
 			for (int i = 0; i < outerLocalsCount; i++){
-			SyntheticArgumentBinding argument = outerLocals[i];
+			SyntheticArgumentBinding argument = this.outerLocalVariables[i];
 			// do NOT position the outerlocal synthetic arg yet,  since will be appended to user arguments
 			if ((argument.type == LongBinding) || (argument.type == DoubleBinding)){
 				slotSize += 2;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
index 6b968d7..c2f6aa4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
@@ -21,6 +21,7 @@
 	HashtableOfType knownTypes;
 	HashtableOfPackage knownPackages;
 protected PackageBinding() {
+	// for creating problem package
 }
 public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment) {
 	this.compoundName = compoundName;
@@ -65,10 +66,10 @@
 	if (!environment.isPackage(this.compoundName, name))
 		return null;
 
-	char[][] compoundName = CharOperation.arrayConcat(this.compoundName, name);
-	PackageBinding newPackageBinding = new PackageBinding(compoundName, this, environment);
-	addPackage(newPackageBinding);
-	return newPackageBinding;
+	char[][] subPkgCompoundName = CharOperation.arrayConcat(this.compoundName, name);
+	PackageBinding subPackageBinding = new PackageBinding(subPkgCompoundName, this, environment);
+	addPackage(subPackageBinding);
+	return subPackageBinding;
 }
 /* Answer the subpackage named name; ask the oracle for the package if its not in the cache.
 * Answer null if it could not be resolved.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
index afa3635..8f8a288 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
@@ -11,7 +11,7 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 public class ProblemReferenceBinding extends ReferenceBinding {
-	public Binding original;
+	public ReferenceBinding original;
 	private int problemId;
 // NOTE: must only answer the subset of the name related to the problem
 
@@ -22,12 +22,12 @@
 	this(new char[][] {name}, null, problemId);
 }
 
-public ProblemReferenceBinding(char[][] compoundName, Binding original, int problemId) {
+public ProblemReferenceBinding(char[][] compoundName, ReferenceBinding original, int problemId) {
 	this.compoundName = compoundName;
 	this.original = original;
 	this.problemId = problemId;
 }
-public ProblemReferenceBinding(char[] name, Binding original, int problemId) {
+public ProblemReferenceBinding(char[] name, ReferenceBinding original, int problemId) {
 	this(new char[][] {name}, original, problemId);
 }
 /* API
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index ed890ec..6087785 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -341,7 +341,7 @@
 public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
 	return null;
 }
-public FieldBinding getField(char[] fieldName) {
+public FieldBinding getField(char[] fieldName, boolean needResolve) {
 	return null;
 }
 /**
@@ -554,24 +554,21 @@
 */
 
 public char[] qualifiedSourceName() {
-	if (isMemberType()) {
+	if (isMemberType())
 		return CharOperation.concat(enclosingType().qualifiedSourceName(), sourceName(), '.');
-	} else {
-		return sourceName();
-	}
+	return sourceName();
 }
+
 public char[] readableName() /*java.lang.Object*/ {
 	if (isMemberType())
 		return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
-	else
-		return CharOperation.concatWith(compoundName, '.');
+	return CharOperation.concatWith(compoundName, '.');
 }
 
 public char[] shortReadableName() /*Object*/ {
 	if (isMemberType())
 		return CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
-	else
-		return sourceName;
+	return sourceName;
 }
 
 /* Answer the receiver's signature.
@@ -606,4 +603,7 @@
 public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
 	return null;		// is null if no enclosing instances are required
 }
+MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
+	return methods();
+}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index b5982f1..e86ff7d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -11,38 +11,42 @@
 package org.eclipse.jdt.internal.compiler.lookup;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
 
 public abstract class Scope
-	implements
-		BaseTypes,
-		BindingIds,
-		CompilerModifiers,
-		ProblemReasons,
-		TagBits,
-		TypeConstants,
-		TypeIds {
-
-	public Scope parent;
-	public int kind;
+	implements BaseTypes, BindingIds, CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
 
 	public final static int BLOCK_SCOPE = 1;
 	public final static int METHOD_SCOPE = 2;
 	public final static int CLASS_SCOPE = 3;
 	public final static int COMPILATION_UNIT_SCOPE = 4;
+
+	public int kind;
+	public Scope parent;
+
 	protected Scope(int kind, Scope parent) {
 		this.kind = kind;
 		this.parent = parent;
 	}
 
-	public abstract ProblemReporter problemReporter();
+	/* Answer an int describing the relationship between the given types.
+	*
+	* 		NotRelated 
+	* 		EqualOrMoreSpecific : left is compatible with right
+	* 		MoreGeneric : right is compatible with left
+	*/
+	public static int compareTypes(TypeBinding left, TypeBinding right) {
+		if (left.isCompatibleWith(right))
+			return EqualOrMoreSpecific;
+		if (right.isCompatibleWith(left))
+			return MoreGeneric;
+		return NotRelated;
+	}
 
 	// Internal use only
 	protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) {
@@ -60,20 +64,6 @@
 		return true;
 	}
 
-	/* Answer an int describing the relationship between the given types.
-	*
-	* 		NotRelated 
-	* 		EqualOrMoreSpecific : left is compatible with right
-	* 		MoreGeneric : right is compatible with left
-	*/
-	public static int compareTypes(TypeBinding left, TypeBinding right) {
-		if (left.isCompatibleWith(right))
-			return EqualOrMoreSpecific;
-		if (right.isCompatibleWith(left))
-			return MoreGeneric;
-		return NotRelated;
-	}
-
 	/* Answer an int describing the relationship between the given type and unchecked exceptions.
 	*
 	* 	NotRelated 
@@ -137,6 +127,60 @@
 		return ((CompilationUnitScope) unitScope).environment;
 	}
 
+	// abstract method lookup lookup (since maybe missing default abstract methods)
+	public MethodBinding findDefaultAbstractMethod(
+		ReferenceBinding receiverType, 
+		char[] selector,
+		TypeBinding[] argumentTypes,
+		InvocationSite invocationSite,
+		ReferenceBinding classHierarchyStart,
+		MethodBinding matchingMethod,
+		ObjectVector found) {
+
+		int startFoundSize = found.size;
+		ReferenceBinding currentType = classHierarchyStart;
+		while (currentType != null) {
+			matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
+			currentType = currentType.superclass();
+		}
+		int foundSize = found.size;
+		if (foundSize == startFoundSize) {
+			if (matchingMethod != null) compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions);
+			return matchingMethod; // maybe null
+		}
+		MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
+		int candidatesCount = 0;
+		// argument type compatibility check
+		for (int i = startFoundSize; i < foundSize; i++) {
+			MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
+			if (areParametersAssignable(methodBinding.parameters, argumentTypes))
+				candidates[candidatesCount++] = methodBinding;
+		}
+		if (candidatesCount == 1) {
+			compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
+			return candidates[0]; 
+		}
+		if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
+			int argLength = argumentTypes.length;
+			nextMethod : for (int i = 0; i < foundSize; i++) {
+				MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
+				TypeBinding[] params = methodBinding.parameters;
+				int paramLength = params.length;
+				nextArg: for (int a = 0; a < argLength; a++) {
+					TypeBinding arg = argumentTypes[a];
+					for (int p = 0; p < paramLength; p++)
+						if (params[p] == arg)
+							continue nextArg;
+					continue nextMethod;
+				}
+				return methodBinding;
+			}
+			return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
+		}
+		// no need to check for visibility - interface methods are public
+		return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
+	}
+
 	// Internal use only
 	public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) {
 		if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
@@ -185,7 +229,7 @@
 	
 		If no visible field is discovered, null is answered.
 	*/
-	public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
+	public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) {
 		if (receiverType.isBaseType()) return null;
 		if (receiverType.isArrayType()) {
 			TypeBinding leafType = receiverType.leafComponentType();
@@ -194,7 +238,7 @@
 					return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ReceiverTypeNotVisible);
 			}
 			if (CharOperation.equals(fieldName, LENGTH))
-				return ArrayBinding.LengthField;
+				return ArrayBinding.ArrayLength;
 			return null;
 		}
 
@@ -204,7 +248,7 @@
 		if (!currentType.canBeSeenBy(this))
 			return new ProblemFieldBinding(currentType, fieldName, ReceiverTypeNotVisible);
 
-		FieldBinding field = currentType.getField(fieldName);
+		FieldBinding field = currentType.getField(fieldName, true /*resolve*/);
 		if (field != null) {
 			if (field.canBeSeenBy(currentType, invocationSite, this))
 				return field;
@@ -235,7 +279,7 @@
 			if ((currentType = currentType.superclass()) == null)
 				break;
 
-			if ((field = currentType.getField(fieldName)) != null) {
+			if ((field = currentType.getField(fieldName, needResolve)) != null) {
 				keepLooking = false;
 				if (field.canBeSeenBy(receiverType, invocationSite, this)) {
 					if (visibleField == null)
@@ -258,7 +302,7 @@
 					if ((anInterface.tagBits & InterfaceVisited) == 0) {
 						// if interface as not already been visited
 						anInterface.tagBits |= InterfaceVisited;
-						if ((field = anInterface.getField(fieldName)) != null) {
+						if ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) {
 							if (visibleField == null) {
 								visibleField = field;
 							} else {
@@ -420,7 +464,7 @@
 
 		ReferenceBinding currentType = receiverType;
 		MethodBinding matchingMethod = null;
-		ObjectVector found = new ObjectVector();
+		ObjectVector found = new ObjectVector(); //TODO should rewrite to remove #matchingMethod since found is allocated anyway
 
 		compilationUnitScope().recordTypeReference(receiverType);
 		compilationUnitScope().recordTypeReferences(argumentTypes);
@@ -437,7 +481,7 @@
 			currentType = getJavaLangObject();
 		}
 
-		boolean isCompliant14 = compilationUnitScope().environment.options.complianceLevel >= CompilerOptions.JDK1_4;
+		boolean isCompliant14 = compilationUnitScope().environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
 		// superclass lookup
 		ReferenceBinding classHierarchyStart = currentType;
 		while (currentType != null) {
@@ -492,33 +536,50 @@
 			currentType = currentType.superclass();
 		}
 
+		// if found several candidates, then eliminate those not matching argument types
 		int foundSize = found.size;
-		if (foundSize == 0) {
-			if (matchingMethod != null && areParametersAssignable(matchingMethod.parameters, argumentTypes)) {
+		MethodBinding[] candidates = null;
+		int candidatesCount = 0;
+		boolean checkedMatchingMethod = false; // is matchingMethod meeting argument expectation ?
+		if (foundSize > 0) {
+			// argument type compatibility check
+			for (int i = 0; i < foundSize; i++) {
+				MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
+				if (areParametersAssignable(methodBinding.parameters, argumentTypes)) {
+					switch (candidatesCount) {
+						case 0: 
+							matchingMethod = methodBinding; // if only one match, reuse matchingMethod
+							checkedMatchingMethod = true; // matchingMethod is known to exist and match params here
+							break;
+						case 1:
+							candidates = new MethodBinding[foundSize]; // only lazily created if more than one match
+							candidates[0] = matchingMethod; // copy back
+							matchingMethod = null;
+							// fall through
+						default:
+							candidates[candidatesCount] = methodBinding;
+					}
+					candidatesCount++;
+				}
+			}
+		}
+		// if only one matching method left (either from start or due to elimination of rivals), then match is in matchingMethod
+		if (matchingMethod != null) {
+			if (checkedMatchingMethod || areParametersAssignable(matchingMethod.parameters, argumentTypes)) {
 				// (if no default abstract) must explicitly look for one instead, which could be a better match
 				if (!matchingMethod.canBeSeenBy(receiverType, invocationSite, this)) {
 					// ignore matching method (to be consistent with multiple matches, none visible (matching method is then null)
 					MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found);						
 					if (interfaceMethod != null) return interfaceMethod;
+					compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions);
+					return matchingMethod;
 				}
-				return matchingMethod;
 			} 
 			return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
 		}
 
-		MethodBinding[] candidates = new MethodBinding[foundSize];
-		int candidatesCount = 0;
-		// argument type compatibility check
-		for (int i = 0; i < foundSize; i++) {
-			MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
-			if (areParametersAssignable(methodBinding.parameters, argumentTypes))
-				candidates[candidatesCount++] = methodBinding;
-		}
-		if (candidatesCount == 1) {
-			compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
-			return candidates[0]; // have not checked visibility
-		}
-		if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
+		// no match was found, try to find a close match when the parameter order is wrong or missing some parameters
+		if (candidatesCount == 0) {
 			MethodBinding interfaceMethod =
 				findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
 			if (interfaceMethod != null) return interfaceMethod;
@@ -541,7 +602,7 @@
 			return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
 		}
 
-		// visibility check
+		// tiebreak using visibility check
 		int visiblesCount = 0;
 		for (int i = 0; i < candidatesCount; i++) {
 			MethodBinding methodBinding = candidates[i];
@@ -569,57 +630,55 @@
 			return mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
 		}
 	}
-
-	// abstract method lookup lookup (since maybe missing default abstract methods)
-	public MethodBinding findDefaultAbstractMethod(
-		ReferenceBinding receiverType, 
+	
+	// Internal use only
+	public MethodBinding findMethodForArray(
+		ArrayBinding receiverType,
 		char[] selector,
 		TypeBinding[] argumentTypes,
-		InvocationSite invocationSite,
-		ReferenceBinding classHierarchyStart,
-		MethodBinding matchingMethod,
-		ObjectVector found) {
+		InvocationSite invocationSite) {
 
-		int startFoundSize = found.size;
-		ReferenceBinding currentType = classHierarchyStart;
-		while (currentType != null) {
-			matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
-			currentType = currentType.superclass();
+		TypeBinding leafType = receiverType.leafComponentType();
+		if (leafType instanceof ReferenceBinding) {
+			if (!((ReferenceBinding) leafType).canBeSeenBy(this))
+				return new ProblemMethodBinding(selector, TypeConstants.NoParameters, (ReferenceBinding)leafType, ReceiverTypeNotVisible);
 		}
-		int foundSize = found.size;
-		if (foundSize == startFoundSize) return matchingMethod; // maybe null
 
-		MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
-		int candidatesCount = 0;
-		// argument type compatibility check
-		for (int i = startFoundSize; i < foundSize; i++) {
-			MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
-			if (areParametersAssignable(methodBinding.parameters, argumentTypes))
-				candidates[candidatesCount++] = methodBinding;
-		}
-		if (candidatesCount == 1) {
-			compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
-			return candidates[0]; 
-		}
-		if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
-			int argLength = argumentTypes.length;
-			nextMethod : for (int i = 0; i < foundSize; i++) {
-				MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
-				TypeBinding[] params = methodBinding.parameters;
-				int paramLength = params.length;
-				nextArg: for (int a = 0; a < argLength; a++) {
-					TypeBinding arg = argumentTypes[a];
-					for (int p = 0; p < paramLength; p++)
-						if (params[p] == arg)
-							continue nextArg;
-					continue nextMethod;
-				}
+		ReferenceBinding object = getJavaLangObject();
+		MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
+		if (methodBinding != null) {
+			// handle the method clone() specially... cannot be protected or throw exceptions
+			if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
+				return new UpdatedMethodBinding(
+					environment().options.targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0
+					(methodBinding.modifiers ^ AccProtected) | AccPublic,
+					CLONE,
+					methodBinding.returnType,
+					argumentTypes,
+					null,
+					object);
+			if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
 				return methodBinding;
-			}
-			return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
 		}
-		// no need to check for visibility - interface methods are public
-		return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
+		// answers closest approximation, may not check argumentTypes or visibility
+		methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
+		if (methodBinding == null)
+			return new ProblemMethodBinding(selector, argumentTypes, NotFound);
+		if (methodBinding.isValidBinding()) {
+			if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
+				return new ProblemMethodBinding(
+					methodBinding,
+					selector,
+					argumentTypes,
+					NotFound);
+			if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
+				return new ProblemMethodBinding(
+					methodBinding,
+					selector,
+					methodBinding.parameters,
+					NotVisible);
+		}
+		return methodBinding;
 	}
 
 	public MethodBinding findMethodInSuperInterfaces(
@@ -680,55 +739,6 @@
 		}
 		return matchingMethod;
 	}
-	
-	// Internal use only
-	public MethodBinding findMethodForArray(
-		ArrayBinding receiverType,
-		char[] selector,
-		TypeBinding[] argumentTypes,
-		InvocationSite invocationSite) {
-
-		TypeBinding leafType = receiverType.leafComponentType();
-		if (leafType instanceof ReferenceBinding) {
-			if (!((ReferenceBinding) leafType).canBeSeenBy(this))
-				return new ProblemMethodBinding(selector, MethodBinding.NoParameters, (ReferenceBinding)leafType, ReceiverTypeNotVisible);
-		}
-
-		ReferenceBinding object = getJavaLangObject();
-		MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
-		if (methodBinding != null) {
-			// handle the method clone() specially... cannot be protected or throw exceptions
-			if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
-				return new MethodBinding(
-					(methodBinding.modifiers ^ AccProtected) | AccPublic,
-					CLONE,
-					methodBinding.returnType,
-					argumentTypes,
-					null,
-					object);
-			if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
-				return methodBinding;
-		}
-		// answers closest approximation, may not check argumentTypes or visibility
-		methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
-		if (methodBinding == null)
-			return new ProblemMethodBinding(selector, argumentTypes, NotFound);
-		if (methodBinding.isValidBinding()) {
-			if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
-				return new ProblemMethodBinding(
-					methodBinding,
-					selector,
-					argumentTypes,
-					NotFound);
-			if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
-				return new ProblemMethodBinding(
-					methodBinding,
-					selector,
-					methodBinding.parameters,
-					NotVisible);
-		}
-		return methodBinding;
-	}
 
 	// Internal use only
 	public ReferenceBinding findType(
@@ -748,6 +758,11 @@
 		return typeBinding;
 	}
 
+	public LocalVariableBinding findVariable(char[] variable) {
+
+		return null;
+	}
+	
 	public TypeBinding getBaseType(char[] name) {
 		// list should be optimized (with most often used first)
 		int length = name.length;
@@ -810,6 +825,220 @@
 		return null;
 	}
 
+	/* API
+     *	
+	 *	Answer the binding that corresponds to the argument name.
+	 *	flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE, PACKAGE.
+	 *	Only bindings corresponding to the mask can be answered.
+	 *
+	 *	For example, getBinding("foo", VARIABLE, site) will answer
+	 *	the binding for the field or local named "foo" (or an error binding if none exists).
+	 *	If a type named "foo" exists, it will not be detected (and an error binding will be answered)
+	 *
+	 *	The VARIABLE mask has precedence over the TYPE mask.
+	 *
+	 *	If the VARIABLE mask is not set, neither fields nor locals will be looked for.
+	 *
+	 *	InvocationSite implements:
+	 *		isSuperAccess(); this is used to determine if the discovered field is visible.
+	 *
+	 *	Limitations: cannot request FIELD independently of LOCAL, or vice versa
+	 */
+	public Binding getBinding(char[] name, int mask, InvocationSite invocationSite, boolean needResolve) {
+			
+		Binding binding = null;
+		FieldBinding problemField = null;
+		if ((mask & VARIABLE) != 0) {
+			boolean insideStaticContext = false;
+			boolean insideConstructorCall = false;
+
+			FieldBinding foundField = null;
+			// can be a problem field which is answered if a valid field is not found
+			ProblemFieldBinding foundInsideProblem = null;
+			// inside Constructor call or inside static context
+			Scope scope = this;
+			int depth = 0;
+			int foundDepth = 0;
+			ReferenceBinding foundActualReceiverType = null;
+			done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+				switch (scope.kind) {
+					case METHOD_SCOPE :
+						MethodScope methodScope = (MethodScope) scope;
+						insideStaticContext |= methodScope.isStatic;
+						insideConstructorCall |= methodScope.isConstructorCall;
+						// Fall through... could duplicate the code below to save a cast - questionable optimization
+					case BLOCK_SCOPE :
+						LocalVariableBinding variableBinding = scope.findVariable(name);
+						// looks in this scope only
+						if (variableBinding != null) {
+							if (foundField != null && foundField.isValidBinding())
+								return new ProblemFieldBinding(
+									foundField.declaringClass,
+									name,
+									InheritedNameHidesEnclosingName);
+							if (depth > 0)
+								invocationSite.setDepth(depth);
+							return variableBinding;
+						}
+						break;
+					case CLASS_SCOPE :
+						ClassScope classScope = (ClassScope) scope;
+						SourceTypeBinding enclosingType = classScope.referenceContext.binding;
+						FieldBinding fieldBinding =
+							classScope.findField(enclosingType, name, invocationSite, needResolve);
+						// Use next line instead if willing to enable protected access accross inner types
+						// FieldBinding fieldBinding = findField(enclosingType, name, invocationSite);
+						if (fieldBinding != null) { // skip it if we did not find anything
+							if (fieldBinding.problemId() == Ambiguous) {
+								if (foundField == null || foundField.problemId() == NotVisible)
+									// supercedes any potential InheritedNameHidesEnclosingName problem
+									return fieldBinding;
+								else
+									// make the user qualify the field, likely wants the first inherited field (javac generates an ambiguous error instead)
+									return new ProblemFieldBinding(
+										fieldBinding.declaringClass,
+										name,
+										InheritedNameHidesEnclosingName);
+							}
+
+							ProblemFieldBinding insideProblem = null;
+							if (fieldBinding.isValidBinding()) {
+								if (!fieldBinding.isStatic()) {
+									if (insideConstructorCall) {
+										insideProblem =
+											new ProblemFieldBinding(
+												fieldBinding.declaringClass,
+												name,
+												NonStaticReferenceInConstructorInvocation);
+									} else if (insideStaticContext) {
+										insideProblem =
+											new ProblemFieldBinding(
+												fieldBinding.declaringClass,
+												name,
+												NonStaticReferenceInStaticContext);
+									}
+								}
+								if (enclosingType == fieldBinding.declaringClass
+									|| environment().options.complianceLevel >= ClassFileConstants.JDK1_4){
+									// found a valid field in the 'immediate' scope (ie. not inherited)
+									// OR in 1.4 mode (inherited shadows enclosing)
+									if (foundField == null) {
+										if (depth > 0){
+											invocationSite.setDepth(depth);
+											invocationSite.setActualReceiverType(enclosingType);
+										}
+										// return the fieldBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
+										return insideProblem == null ? fieldBinding : insideProblem;
+									}
+									if (foundField.isValidBinding())
+										// if a valid field was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
+										if (foundField.declaringClass != fieldBinding.declaringClass)
+											// ie. have we found the same field - do not trust field identity yet
+											return new ProblemFieldBinding(
+												fieldBinding.declaringClass,
+												name,
+												InheritedNameHidesEnclosingName);
+								}
+							}
+
+							if (foundField == null
+								|| (foundField.problemId() == NotVisible
+									&& fieldBinding.problemId() != NotVisible)) {
+								// only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is...
+								foundDepth = depth;
+								foundActualReceiverType = enclosingType;
+								foundInsideProblem = insideProblem;
+								foundField = fieldBinding;
+							}
+						}
+						depth++;
+						insideStaticContext |= enclosingType.isStatic();
+						// 1EX5I8Z - accessing outer fields within a constructor call is permitted
+						// in order to do so, we change the flag as we exit from the type, not the method
+						// itself, because the class scope is used to retrieve the fields.
+						MethodScope enclosingMethodScope = scope.methodScope();
+						insideConstructorCall =
+							enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
+						break;
+					case COMPILATION_UNIT_SCOPE :
+						break done;
+				}
+				scope = scope.parent;
+			}
+
+			if (foundInsideProblem != null)
+				return foundInsideProblem;
+			if (foundField != null) {
+				if (foundField.isValidBinding()){
+					if (foundDepth > 0){
+						invocationSite.setDepth(foundDepth);
+						invocationSite.setActualReceiverType(foundActualReceiverType);
+					}
+					return foundField;
+				}
+				problemField = foundField;
+			}
+		}
+
+		// We did not find a local or instance variable.
+		if ((mask & TYPE) != 0) {
+			if ((binding = getBaseType(name)) != null)
+				return binding;
+			binding = getTypeOrPackage(name, (mask & PACKAGE) == 0 ? TYPE : TYPE | PACKAGE);
+			if (binding.isValidBinding() || mask == TYPE)
+				return binding;
+			// answer the problem type binding if we are only looking for a type
+		} else if ((mask & PACKAGE) != 0) {
+			compilationUnitScope().recordSimpleReference(name);
+			if ((binding = environment().getTopLevelPackage(name)) != null)
+				return binding;
+		}
+		if (problemField != null) return problemField;
+		return new ProblemBinding(name, enclosingSourceType(), NotFound);
+	}
+
+	public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
+		compilationUnitScope().recordTypeReference(receiverType);
+		compilationUnitScope().recordTypeReferences(argumentTypes);
+		MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
+		if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this))
+			return methodBinding;
+		MethodBinding[] methods = receiverType.getMethods(ConstructorDeclaration.ConstantPoolName);
+		if (methods == NoMethods)
+			return new ProblemMethodBinding(
+				ConstructorDeclaration.ConstantPoolName,
+				argumentTypes,
+				NotFound);
+
+		MethodBinding[] compatible = new MethodBinding[methods.length];
+		int compatibleIndex = 0;
+		for (int i = 0, length = methods.length; i < length; i++)
+			if (areParametersAssignable(methods[i].parameters, argumentTypes))
+				compatible[compatibleIndex++] = methods[i];
+		if (compatibleIndex == 0)
+			return new ProblemMethodBinding(
+				ConstructorDeclaration.ConstantPoolName,
+				argumentTypes,
+				NotFound);
+		// need a more descriptive error... cannot convert from X to Y
+
+		MethodBinding[] visible = new MethodBinding[compatibleIndex];
+		int visibleIndex = 0;
+		for (int i = 0; i < compatibleIndex; i++) {
+			MethodBinding method = compatible[i];
+			if (method.canBeSeenBy(invocationSite, this))
+				visible[visibleIndex++] = method;
+		}
+		if (visibleIndex == 1) return visible[0];
+		if (visibleIndex == 0)
+			return new ProblemMethodBinding(
+				compatible[0],
+				ConstructorDeclaration.ConstantPoolName,
+				compatible[0].parameters,
+				NotVisible);
+		return mostSpecificClassMethodBinding(visible, visibleIndex);
+	}
+
 	public final PackageBinding getCurrentPackage() {
 		Scope scope, unitScope = this;
 		while ((scope = unitScope.parent) != null)
@@ -817,6 +1046,53 @@
 		return ((CompilationUnitScope) unitScope).fPackage;
 	}
 
+	/**
+	 * Returns the modifiers of the innermost enclosing declaration.
+	 * @return modifiers
+	 */
+	public int getDeclarationModifiers(){
+		switch(this.kind){
+			case Scope.BLOCK_SCOPE :
+			case Scope.METHOD_SCOPE :
+				MethodScope methodScope = methodScope();
+				if (!methodScope.isInsideInitializer()){
+					// check method modifiers to see if deprecated
+					MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
+					if (context != null) {
+						return context.modifiers;
+					}
+				} else {
+					SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
+
+					// inside field declaration ? check field modifier to see if deprecated
+					if (methodScope.initializedField != null) {
+						return methodScope.initializedField.modifiers;
+					}
+					if (type != null) {
+						return type.modifiers;
+					}
+				}
+				break;
+			case Scope.CLASS_SCOPE :
+				ReferenceBinding context = ((ClassScope)this).referenceType().binding;
+				if (context != null) {
+					return context.modifiers;
+				}
+				break;
+		}
+		return -1;
+	}
+
+	public FieldBinding getField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
+		FieldBinding field = findField(receiverType, fieldName, invocationSite, true /*resolve*/);
+		if (field != null) return field;
+
+		return new ProblemFieldBinding(
+			receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null,
+			fieldName,
+			NotFound);
+	}
+
 	public final ReferenceBinding getJavaIoSerializable() {
 		compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
 		ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
@@ -826,6 +1102,14 @@
 		return null; // will not get here since the above error aborts the compilation
 	}
 
+	public final ReferenceBinding getJavaLangAssertionError() {
+		compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
+		ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
+		if (type != null) return type;
+		problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
+		return null; // will not get here since the above error aborts the compilation
+	}
+
 	public final ReferenceBinding getJavaLangClass() {
 		compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
 		ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
@@ -853,14 +1137,6 @@
 		return null; // will not get here since the above error aborts the compilation
 	}
 
-	public final ReferenceBinding getJavaLangAssertionError() {
-		compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
-		ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
-		if (type != null) return type;
-		problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
-		return null; // will not get here since the above error aborts the compilation
-	}
-
 	public final ReferenceBinding getJavaLangObject() {
 		compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
 		ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
@@ -905,6 +1181,54 @@
 		return new ProblemReferenceBinding(typeName, NotFound);
 	}
 
+	public MethodBinding getMethod(TypeBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
+		if (receiverType.isArrayType())
+			return findMethodForArray((ArrayBinding) receiverType, selector, argumentTypes, invocationSite);
+		if (receiverType.isBaseType())
+			return new ProblemMethodBinding(selector, argumentTypes, NotFound);
+
+		ReferenceBinding currentType = (ReferenceBinding) receiverType;
+		if (!currentType.canBeSeenBy(this))
+			return new ProblemMethodBinding(selector, argumentTypes, ReceiverTypeNotVisible);
+
+		// retrieve an exact visible match (if possible)
+		MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite);
+		if (methodBinding != null) return methodBinding;
+
+		// answers closest approximation, may not check argumentTypes or visibility
+		methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite);
+		if (methodBinding == null)
+			return new ProblemMethodBinding(selector, argumentTypes, NotFound);
+		if (methodBinding.isValidBinding()) {
+			if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
+				return new ProblemMethodBinding(
+					methodBinding,
+					selector,
+					argumentTypes,
+					NotFound);
+			if (!methodBinding.canBeSeenBy(currentType, invocationSite, this))
+				return new ProblemMethodBinding(
+					methodBinding,
+					selector,
+					methodBinding.parameters,
+					NotVisible);
+		}
+		return methodBinding;
+	}
+
+	/* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
+	* The name provided is a simple source name (e.g., "Object" , "Point", ...)
+	*/
+	// The return type of this method could be ReferenceBinding if we did not answer base types.
+	// NOTE: We could support looking for Base Types last in the search, however any code using
+	// this feature would be extraordinarily slow.  Therefore we don't do this
+	public final TypeBinding getType(char[] name) {
+		// Would like to remove this test and require senders to specially handle base types
+		TypeBinding binding = getBaseType(name);
+		if (binding != null) return binding;
+		return (ReferenceBinding) getTypeOrPackage(name, TYPE);
+	}
+
 	/* Answer the type binding corresponding to the compoundName.
 	*
 	* NOTE: If a problem binding is returned, senders should extract the compound name
@@ -971,17 +1295,149 @@
 		return typeBinding;
 	}
 
-	/* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
-	* The name provided is a simple source name (e.g., "Object" , "Point", ...)
+	/* Internal use only 
 	*/
-	// The return type of this method could be ReferenceBinding if we did not answer base types.
-	// NOTE: We could support looking for Base Types last in the search, however any code using
-	// this feature would be extraordinarily slow.  Therefore we don't do this
-	public final TypeBinding getType(char[] name) {
-		// Would like to remove this test and require senders to specially handle base types
-		TypeBinding binding = getBaseType(name);
-		if (binding != null) return binding;
-		return (ReferenceBinding) getTypeOrPackage(name, TYPE);
+	final Binding getTypeOrPackage(char[] name, int mask) {
+		Scope scope = this;
+		ReferenceBinding foundType = null;
+		if ((mask & TYPE) == 0) {
+			Scope next = scope;
+			while ((next = scope.parent) != null)
+				scope = next;
+		} else {
+			done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+				switch (scope.kind) {
+					case METHOD_SCOPE :
+					case BLOCK_SCOPE :
+						ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
+						if (localType != null) {
+							if (foundType != null && foundType != localType)
+								return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+							return localType;
+						}
+						break;
+					case CLASS_SCOPE :
+						SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
+						// 6.5.5.1 - simple name favors member type over top-level type in same unit
+						ReferenceBinding memberType = findMemberType(name, sourceType);
+						if (memberType != null) { // skip it if we did not find anything
+							if (memberType.problemId() == Ambiguous) {
+								if (foundType == null || foundType.problemId() == NotVisible)
+									// supercedes any potential InheritedNameHidesEnclosingName problem
+									return memberType;
+								else
+									// make the user qualify the type, likely wants the first inherited type
+									return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+							}
+							if (memberType.isValidBinding()) {
+								if (sourceType == memberType.enclosingType()
+										|| environment().options.complianceLevel >= ClassFileConstants.JDK1_4) {
+									// found a valid type in the 'immediate' scope (ie. not inherited)
+									// OR in 1.4 mode (inherited shadows enclosing)
+									if (foundType == null)
+										return memberType; 
+									if (foundType.isValidBinding())
+										// if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
+										if (foundType != memberType)
+											return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+								}
+							}
+							if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
+								// only remember the memberType if its the first one found or the previous one was not visible & memberType is...
+								foundType = memberType;
+						}
+						if (CharOperation.equals(sourceType.sourceName, name)) {
+							if (foundType != null && foundType != sourceType && foundType.problemId() != NotVisible)
+								return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+							return sourceType;
+						}
+						break;
+					case COMPILATION_UNIT_SCOPE :
+						break done;
+				}
+				scope = scope.parent;
+			}
+			if (foundType != null && foundType.problemId() != NotVisible)
+				return foundType;
+		}
+
+		// at this point the scope is a compilation unit scope
+		CompilationUnitScope unitScope = (CompilationUnitScope) scope;
+		PackageBinding currentPackage = unitScope.fPackage; 
+		// ask for the imports + name
+		if ((mask & TYPE) != 0) {
+			// check single type imports.
+
+			ImportBinding[] imports = unitScope.imports;
+			if (imports != null) {
+				HashtableOfObject typeImports = unitScope.resolvedSingeTypeImports;
+				if (typeImports != null) {
+					ImportBinding typeImport = (ImportBinding) typeImports.get(name);
+					if (typeImport != null) {
+						ImportReference importReference = typeImport.reference;
+						if (importReference != null) importReference.used = true;
+						return typeImport.resolvedImport; // already know its visible
+					}
+				} else {
+					// walk all the imports since resolvedSingeTypeImports is not yet initialized
+					for (int i = 0, length = imports.length; i < length; i++) {
+						ImportBinding typeImport = imports[i];
+						if (!typeImport.onDemand) {
+							if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) {
+								if (unitScope.resolveSingleTypeImport(typeImport) != null) {
+									ImportReference importReference = typeImport.reference;
+									if (importReference != null) importReference.used = true;
+									return typeImport.resolvedImport; // already know its visible
+								}
+							}
+						}
+					}
+				}
+			}
+			// check if the name is in the current package, skip it if its a sub-package
+			unitScope.recordReference(currentPackage.compoundName, name);
+			Binding binding = currentPackage.getTypeOrPackage(name);
+			if (binding instanceof ReferenceBinding) return binding; // type is always visible to its own package
+
+			// check on demand imports
+			if (imports != null) {
+				boolean foundInImport = false;
+				ReferenceBinding type = null;
+				for (int i = 0, length = imports.length; i < length; i++) {
+					ImportBinding someImport = imports[i];
+					if (someImport.onDemand) {
+						Binding resolvedImport = someImport.resolvedImport;
+						ReferenceBinding temp = resolvedImport instanceof PackageBinding
+							? findType(name, (PackageBinding) resolvedImport, currentPackage)
+							: findDirectMemberType(name, (ReferenceBinding) resolvedImport);
+						if (temp != null) {
+							if (temp.isValidBinding()) {
+								ImportReference importReference = someImport.reference;
+								if (importReference != null) importReference.used = true;
+								if (foundInImport)
+									// Answer error binding -- import on demand conflict; name found in two import on demand packages.
+									return new ProblemReferenceBinding(name, Ambiguous);
+								type = temp;
+								foundInImport = true;
+							} else if (foundType == null) {
+								foundType = temp;
+							}
+						}
+					}
+				}
+				if (type != null) return type;
+			}
+		}
+
+		unitScope.recordSimpleReference(name);
+		if ((mask & PACKAGE) != 0) {
+			PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
+			if (packageBinding != null) return packageBinding;
+		}
+
+		// Answer error binding -- could not find name
+		if (foundType != null) return foundType; // problem type from above
+		return new ProblemReferenceBinding(name, NotFound);
 	}
 
 	// Added for code assist... NOT Public API
@@ -1036,134 +1492,37 @@
 		return typeBinding;
 	}
 
-	/* Internal use only 
+	/* Answer true if the scope is nested inside a given field declaration.
+     * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed 
+     * e.g. during name resolution.
 	*/
-	final Binding getTypeOrPackage(char[] name, int mask) {
+	public final boolean isDefinedInField(FieldBinding field) {
 		Scope scope = this;
-		ReferenceBinding foundType = null;
-		if ((mask & TYPE) == 0) {
-			Scope next = scope;
-			while ((next = scope.parent) != null)
-				scope = next;
-		} else {
-			done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
-				switch (scope.kind) {
-					case METHOD_SCOPE :
-					case BLOCK_SCOPE :
-						ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
-						if (localType != null) {
-							if (foundType != null && foundType != localType)
-								return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
-							return localType;
-						}
-						break;
-					case CLASS_SCOPE :
-						SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
-						// 6.5.5.1 - simple name favors member type over top-level type in same unit
-						ReferenceBinding memberType = findMemberType(name, sourceType);
-						if (memberType != null) { // skip it if we did not find anything
-							if (memberType.problemId() == Ambiguous) {
-								if (foundType == null || foundType.problemId() == NotVisible)
-									// supercedes any potential InheritedNameHidesEnclosingName problem
-									return memberType;
-								else
-									// make the user qualify the type, likely wants the first inherited type
-									return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
-							}
-							if (memberType.isValidBinding()) {
-								if (sourceType == memberType.enclosingType()
-										|| environment().options.complianceLevel >= CompilerOptions.JDK1_4) {
-									// found a valid type in the 'immediate' scope (ie. not inherited)
-									// OR in 1.4 mode (inherited shadows enclosing)
-									if (foundType == null)
-										return memberType; 
-									if (foundType.isValidBinding())
-										// if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
-										if (foundType != memberType)
-											return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
-								}
-							}
-							if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
-								// only remember the memberType if its the first one found or the previous one was not visible & memberType is...
-								foundType = memberType;
-						}
-						if (CharOperation.equals(sourceType.sourceName, name)) {
-							if (foundType != null && foundType != sourceType && foundType.problemId() != NotVisible)
-								return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
-							return sourceType;
-						}
-						break;
-					case COMPILATION_UNIT_SCOPE :
-						break done;
-				}
-				scope = scope.parent;
+		do {
+			if (scope instanceof MethodScope) {
+				MethodScope methodScope = (MethodScope) scope;
+				if (methodScope.initializedField == field) return true;
 			}
-			if (foundType != null && foundType.problemId() != NotVisible)
-				return foundType;
-		}
+			scope = scope.parent;
+		} while (scope != null);
+		return false;
+	}
 
-		// at this point the scope is a compilation unit scope
-		CompilationUnitScope unitScope = (CompilationUnitScope) scope;
-		PackageBinding currentPackage = unitScope.fPackage; 
-		// ask for the imports + name
-		if ((mask & TYPE) != 0) {
-			// check single type imports.
-			ImportBinding[] imports = unitScope.imports;
-			if (imports != null) {
-				// copy the list, since single type imports are removed if they cannot be resolved
-				for (int i = 0, length = imports.length; i < length; i++) {
-					ImportBinding typeImport = imports[i];
-					if (!typeImport.onDemand) {
-						if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) {
-							if (unitScope.resolveSingleTypeImport(typeImport) != null) {
-								ImportReference importReference = typeImport.reference;
-								if (importReference != null) importReference.used = true;
-								return typeImport.resolvedImport; // already know its visible
-							}
-						}
-					}
+	/* Answer true if the scope is nested inside a given method declaration
+	*/
+	public final boolean isDefinedInMethod(MethodBinding method) {
+		Scope scope = this;
+		do {
+			if (scope instanceof MethodScope) {
+				ReferenceContext refContext = ((MethodScope) scope).referenceContext;
+				if (refContext instanceof AbstractMethodDeclaration
+						&& ((AbstractMethodDeclaration)refContext).binding == method) {
+					return true;
 				}
 			}
-			// check if the name is in the current package, skip it if its a sub-package
-			unitScope.recordReference(currentPackage.compoundName, name);
-			Binding binding = currentPackage.getTypeOrPackage(name);
-			if (binding instanceof ReferenceBinding) return binding; // type is always visible to its own package
-
-			// check on demand imports
-			boolean foundInImport = false;
-			ReferenceBinding type = null;
-			if (imports != null) {
-				for (int i = 0, length = imports.length; i < length; i++) {
-					ImportBinding someImport = imports[i];
-					if (someImport.onDemand) {
-						Binding resolvedImport = someImport.resolvedImport;
-						ReferenceBinding temp = resolvedImport instanceof PackageBinding
-								? findType(name, (PackageBinding) resolvedImport, currentPackage)
-								: findDirectMemberType(name, (ReferenceBinding) resolvedImport);
-						if (temp != null && temp.isValidBinding()) {
-							ImportReference importReference = someImport.reference;
-							if (importReference != null) importReference.used = true;
-							if (foundInImport)
-								// Answer error binding -- import on demand conflict; name found in two import on demand packages.
-								return new ProblemReferenceBinding(name, Ambiguous);
-							type = temp;
-							foundInImport = true;
-						}
-					}
-				}
-			}
-			if (type != null) return type;
-		}
-
-		unitScope.recordSimpleReference(name);
-		if ((mask & PACKAGE) != 0) {
-			PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
-			if (packageBinding != null) return packageBinding;
-		}
-
-		// Answer error binding -- could not find name
-		if (foundType != null) return foundType; // problem type from above
-		return new ProblemReferenceBinding(name, NotFound);
+			scope = scope.parent;
+		} while (scope != null);
+		return false;
 	}
 
 	/* Answer whether the type is defined in the same compilation unit as the receiver
@@ -1187,44 +1546,6 @@
 				return true;
 		return false;
 	}
-
-	/* Answer true if the scope is nested inside a given field declaration.
-     * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed 
-     * e.g. during name resolution.
-	*/
-	public final boolean isDefinedInField(FieldBinding field) {
-		Scope scope = this;
-		do {
-			if (scope instanceof MethodScope) {
-				MethodScope methodScope = (MethodScope) scope;
-				ReferenceContext refContext = methodScope.referenceContext;
-				if (refContext instanceof TypeDeclaration
-						&& ((TypeDeclaration)refContext).binding == field.declaringClass
-						&& methodScope.fieldDeclarationIndex == field.id) {
-					return true;
-				}
-			}
-			scope = scope.parent;
-		} while (scope != null);
-		return false;
-	}
-
-	/* Answer true if the scope is nested inside a given method declaration
-	*/
-	public final boolean isDefinedInMethod(MethodBinding method) {
-		Scope scope = this;
-		do {
-			if (scope instanceof MethodScope) {
-				ReferenceContext refContext = ((MethodScope) scope).referenceContext;
-				if (refContext instanceof AbstractMethodDeclaration
-						&& ((AbstractMethodDeclaration)refContext).binding == method) {
-					return true;
-				}
-			}
-			scope = scope.parent;
-		} while (scope != null);
-		return false;
-	}
 		
 	/* Answer true if the scope is nested inside a given type declaration
 	*/
@@ -1241,7 +1562,7 @@
 	}
 
 	public boolean isInsideDeprecatedCode(){
-		switch(kind){
+		switch(this.kind){
 			case Scope.BLOCK_SCOPE :
 			case Scope.METHOD_SCOPE :
 				MethodScope methodScope = methodScope();
@@ -1253,18 +1574,9 @@
 					}
 				} else {
 					SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
-
 					// inside field declaration ? check field modifier to see if deprecated
-					if (methodScope.fieldDeclarationIndex != MethodScope.NotInFieldDecl) {
-						for (int i = 0; i < type.fields.length; i++){
-							if (type.fields[i].id == methodScope.fieldDeclarationIndex) {
-								// currently inside this field initialization
-								if (type.fields[i].isViewedAsDeprecated()){
-									return true;
-								}
-								break;
-							}
-						}
+					if (methodScope.initializedField != null && methodScope.initializedField.isViewedAsDeprecated()) {
+						return true;
 					}
 					if (type != null && type.isViewedAsDeprecated()) {
 						return true;
@@ -1403,6 +1715,8 @@
 		return lastMethodScope; // may answer null if no method around
 	}
 
+	public abstract ProblemReporter problemReporter();
+
 	public final CompilationUnitDeclaration referenceCompilationUnit() {
 		Scope scope, unitScope = this;
 		while ((scope = unitScope.parent) != null)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index e297cc9..09f9062 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -22,7 +22,7 @@
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 
@@ -35,16 +35,14 @@
 
 	public ClassScope scope;
 
-	// Synthetics are separated into 4 categories: methods, super methods, fields, class literals and changed declaring class bindings
-	public final static int METHOD = 0;
-	public final static int FIELD = 1;
-	public final static int CLASS_LITERAL = 2;
-	public final static int CHANGED_DECLARING_CLASS = 3;
+	// Synthetics are separated into 4 categories: methods, super methods, fields, class literals and changed declaring type bindings
+	public final static int METHOD_EMUL = 0;
+	public final static int FIELD_EMUL = 1;
+	public final static int CLASS_LITERAL_EMUL = 2;
+	public final static int RECEIVER_TYPE_EMUL = 3;
 	
 	Hashtable[] synthetics;
 	
-protected SourceTypeBinding() {
-}
 public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
 	this.compoundName = compoundName;
 	this.fPackage = fPackage;
@@ -53,6 +51,10 @@
 	this.sourceName = scope.referenceContext.name;
 	this.scope = scope;
 
+	// expect the fields & methods to be initialized correctly later
+	this.fields = NoFields;
+	this.methods = NoMethods;
+
 	computeId();
 }
 private void addDefaultAbstractMethod(MethodBinding abstractMethod) {
@@ -75,7 +77,7 @@
 	tagBits |= KnowsDefaultAbstractMethods;
 
 	if (isClass() && isAbstract()) {
-		if (fPackage.environment.options.targetJDK >= CompilerOptions.JDK1_2) return; // no longer added for post 1.2 targets
+		if (fPackage.environment.options.targetJDK >= ClassFileConstants.JDK1_2) return; // no longer added for post 1.2 targets
 
 		ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
 		int lastPosition = 0;
@@ -86,9 +88,9 @@
 			for (int j = 0, length = interfaces.length; j < length; j++) {
 				ReferenceBinding superType = interfaces[j];
 				if (superType.isValidBinding()) {
-					MethodBinding[] methods = superType.methods();
-					for (int m = methods.length; --m >= 0;) {
-						MethodBinding method = methods[m];
+					MethodBinding[] superMethods = superType.methods();
+					for (int m = superMethods.length; --m >= 0;) {
+						MethodBinding method = superMethods[m];
 						if (!implementsMethod(method))
 							addDefaultAbstractMethod(method);
 					}
@@ -112,11 +114,11 @@
 	if (synthetics == null) {
 		synthetics = new Hashtable[4];
 	}
-	if (synthetics[FIELD] == null) {
-		synthetics[FIELD] = new Hashtable(5);
+	if (synthetics[FIELD_EMUL] == null) {
+		synthetics[FIELD_EMUL] = new Hashtable(5);
 	}
 	
-	FieldBinding synthField = (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
+	FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
 	if (synthField == null) {
 		synthField = new SyntheticFieldBinding(
 			CharOperation.concat(SyntheticArgumentBinding.OuterLocalPrefix, actualOuterLocalVariable.name), 
@@ -124,8 +126,8 @@
 			AccPrivate | AccFinal | AccSynthetic, 
 			this, 
 			Constant.NotAConstant,
-			synthetics[FIELD].size());
-		synthetics[FIELD].put(actualOuterLocalVariable, synthField);
+			synthetics[FIELD_EMUL].size());
+		synthetics[FIELD_EMUL].put(actualOuterLocalVariable, synthField);
 	}
 
 	// ensure there is not already such a field defined by the user
@@ -134,7 +136,7 @@
 	do {
 		needRecheck = false;
 		FieldBinding existingField;
-		if ((existingField = this.getField(synthField.name)) != null) {
+		if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
 			TypeDeclaration typeDecl = scope.referenceContext;
 			for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
 				FieldDeclaration fieldDecl = typeDecl.fields[i];
@@ -160,11 +162,11 @@
 	if (synthetics == null) {
 		synthetics = new Hashtable[4];
 	}
-	if (synthetics[FIELD] == null) {
-		synthetics[FIELD] = new Hashtable(5);
+	if (synthetics[FIELD_EMUL] == null) {
+		synthetics[FIELD_EMUL] = new Hashtable(5);
 	}
 
-	FieldBinding synthField = (FieldBinding) synthetics[FIELD].get(enclosingType);
+	FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(enclosingType);
 	if (synthField == null) {
 		synthField = new SyntheticFieldBinding(
 			CharOperation.concat(
@@ -174,12 +176,12 @@
 			AccDefault | AccFinal | AccSynthetic,
 			this,
 			Constant.NotAConstant,
-			synthetics[FIELD].size());
-		synthetics[FIELD].put(enclosingType, synthField);
+			synthetics[FIELD_EMUL].size());
+		synthetics[FIELD_EMUL].put(enclosingType, synthField);
 	}
 	// ensure there is not already such a field defined by the user
 	FieldBinding existingField;
-	if ((existingField = this.getField(synthField.name)) != null) {
+	if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
 		TypeDeclaration typeDecl = scope.referenceContext;
 		for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
 			FieldDeclaration fieldDecl = typeDecl.fields[i];
@@ -200,25 +202,25 @@
 	if (synthetics == null) {
 		synthetics = new Hashtable[4];
 	}
-	if (synthetics[CLASS_LITERAL] == null) {
-		synthetics[CLASS_LITERAL] = new Hashtable(5);
+	if (synthetics[CLASS_LITERAL_EMUL] == null) {
+		synthetics[CLASS_LITERAL_EMUL] = new Hashtable(5);
 	}
 
 	// use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
-	FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL].get(targetType);
+	FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL_EMUL].get(targetType);
 	if (synthField == null) {
 		synthField = new SyntheticFieldBinding(
-			("class$" + synthetics[CLASS_LITERAL].size()).toCharArray(), //$NON-NLS-1$
+			("class$" + synthetics[CLASS_LITERAL_EMUL].size()).toCharArray(), //$NON-NLS-1$
 			blockScope.getJavaLangClass(),
 			AccDefault | AccStatic | AccSynthetic,
 			this,
 			Constant.NotAConstant,
-			synthetics[CLASS_LITERAL].size());
-		synthetics[CLASS_LITERAL].put(targetType, synthField);
+			synthetics[CLASS_LITERAL_EMUL].size());
+		synthetics[CLASS_LITERAL_EMUL].put(targetType, synthField);
 	}
 	// ensure there is not already such a field defined by the user
 	FieldBinding existingField;
-	if ((existingField = this.getField(synthField.name)) != null) {
+	if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
 		TypeDeclaration typeDecl = blockScope.referenceType();
 		for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
 			FieldDeclaration fieldDecl = typeDecl.fields[i];
@@ -239,11 +241,11 @@
 	if (synthetics == null) {
 		synthetics = new Hashtable[4];
 	}
-	if (synthetics[FIELD] == null) {
-		synthetics[FIELD] = new Hashtable(5);
+	if (synthetics[FIELD_EMUL] == null) {
+		synthetics[FIELD_EMUL] = new Hashtable(5);
 	}
 
-	FieldBinding synthField = (FieldBinding) synthetics[FIELD].get("assertionEmulation"); //$NON-NLS-1$
+	FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get("assertionEmulation"); //$NON-NLS-1$
 	if (synthField == null) {
 		synthField = new SyntheticFieldBinding(
 			"$assertionsDisabled".toCharArray(), //$NON-NLS-1$
@@ -251,8 +253,8 @@
 			AccDefault | AccStatic | AccSynthetic | AccFinal,
 			this,
 			Constant.NotAConstant,
-			synthetics[FIELD].size());
-		synthetics[FIELD].put("assertionEmulation", synthField); //$NON-NLS-1$
+			synthetics[FIELD_EMUL].size());
+		synthetics[FIELD_EMUL].put("assertionEmulation", synthField); //$NON-NLS-1$
 	}
 	// ensure there is not already such a field defined by the user
 	// ensure there is not already such a field defined by the user
@@ -261,7 +263,7 @@
 	do {
 		needRecheck = false;
 		FieldBinding existingField;
-		if ((existingField = this.getField(synthField.name)) != null) {
+		if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
 			TypeDeclaration typeDecl = scope.referenceContext;
 			for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
 				FieldDeclaration fieldDecl = typeDecl.fields[i];
@@ -287,15 +289,15 @@
 	if (synthetics == null) {
 		synthetics = new Hashtable[4];
 	}
-	if (synthetics[METHOD] == null) {
-		synthetics[METHOD] = new Hashtable(5);
+	if (synthetics[METHOD_EMUL] == null) {
+		synthetics[METHOD_EMUL] = new Hashtable(5);
 	}
 
 	SyntheticAccessMethodBinding accessMethod = null;
-	SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(targetField);
+	SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetField);
 	if (accessors == null) {
 		accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
-		synthetics[METHOD].put(targetField, accessors = new SyntheticAccessMethodBinding[2]);
+		synthetics[METHOD_EMUL].put(targetField, accessors = new SyntheticAccessMethodBinding[2]);
 		accessors[isReadAccess ? 0 : 1] = accessMethod;		
 	} else {
 		if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
@@ -315,15 +317,15 @@
 	if (synthetics == null) {
 		synthetics = new Hashtable[4];
 	}
-	if (synthetics[METHOD] == null) {
-		synthetics[METHOD] = new Hashtable(5);
+	if (synthetics[METHOD_EMUL] == null) {
+		synthetics[METHOD_EMUL] = new Hashtable(5);
 	}
 
 	SyntheticAccessMethodBinding accessMethod = null;
-	SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(targetMethod);
+	SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetMethod);
 	if (accessors == null) {
 		accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
-		synthetics[METHOD].put(targetMethod, accessors = new SyntheticAccessMethodBinding[2]);
+		synthetics[METHOD_EMUL].put(targetMethod, accessors = new SyntheticAccessMethodBinding[2]);
 		accessors[isSuperAccess ? 0 : 1] = accessMethod;		
 	} else {
 		if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
@@ -420,15 +422,15 @@
 			}
 		}
 	} else {
-		MethodBinding[] methods = getMethods(ConstructorDeclaration.ConstantPoolName); // takes care of duplicates & default abstract methods
-		nextMethod : for (int m = methods.length; --m >= 0;) {
-			MethodBinding method = methods[m];
-			TypeBinding[] toMatch = method.parameters;
+		MethodBinding[] constructors = getMethods(ConstructorDeclaration.ConstantPoolName); // takes care of duplicates & default abstract methods
+		nextConstructor : for (int c = constructors.length; --c >= 0;) {
+			MethodBinding constructor = constructors[c];
+			TypeBinding[] toMatch = constructor.parameters;
 			if (toMatch.length == argCount) {
 				for (int p = 0; p < argCount; p++)
 					if (toMatch[p] != argumentTypes[p])
-						continue nextMethod;
-				return method;
+						continue nextConstructor;
+				return constructor;
 			}
 		}
 	}
@@ -457,10 +459,10 @@
 			}
 		}
 	} else {
-		MethodBinding[] methods = getMethods(selector); // takes care of duplicates & default abstract methods
-		foundNothing = methods == NoMethods;
-		nextMethod : for (int m = methods.length; --m >= 0;) {
-			MethodBinding method = methods[m];
+		MethodBinding[] matchingMethods = getMethods(selector); // takes care of duplicates & default abstract methods
+		foundNothing = matchingMethods == NoMethods;
+		nextMethod : for (int m = matchingMethods.length; --m >= 0;) {
+			MethodBinding method = matchingMethods[m];
 			TypeBinding[] toMatch = method.parameters;
 			if (toMatch.length == argCount) {
 				for (int p = 0; p < argCount; p++)
@@ -483,7 +485,8 @@
 }
 // NOTE: the type of a field of a source type is resolved when needed
 
-public FieldBinding getField(char[] fieldName) {
+public FieldBinding getField(char[] fieldName, boolean needResolve) {
+	// always resolve anyway on source types
 	int fieldLength = fieldName.length;
 	for (int f = fields.length; --f >= 0;) {
 		FieldBinding field = fields[f];
@@ -625,8 +628,8 @@
 
 public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
 	
-	if (synthetics == null || synthetics[FIELD] == null) return null;
-	return (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
+	if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
+	return (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
 }
 public ReferenceBinding[] memberTypes() {
 	return memberTypes;
@@ -636,14 +639,14 @@
 	if (synthetics == null) {
 		synthetics = new Hashtable[4];
 	}
-	if (synthetics[CHANGED_DECLARING_CLASS] == null) {
-		synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
+	if (synthetics[RECEIVER_TYPE_EMUL] == null) {
+		synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
 	}
 
-	Hashtable fieldMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS].get(targetField);
+	Hashtable fieldMap = (Hashtable) synthetics[RECEIVER_TYPE_EMUL].get(targetField);
 	if (fieldMap == null) {
 		fieldMap = new Hashtable(5);
-		synthetics[CHANGED_DECLARING_CLASS].put(targetField, fieldMap);
+		synthetics[RECEIVER_TYPE_EMUL].put(targetField, fieldMap);
 	}
 	FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
 	if (updatedField == null){
@@ -658,15 +661,15 @@
 	if (synthetics == null) {
 		synthetics = new Hashtable[4];
 	}
-	if (synthetics[CHANGED_DECLARING_CLASS] == null) {
-		synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
+	if (synthetics[RECEIVER_TYPE_EMUL] == null) {
+		synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
 	}
 
 
-	Hashtable methodMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS].get(targetMethod);
+	Hashtable methodMap = (Hashtable) synthetics[RECEIVER_TYPE_EMUL].get(targetMethod);
 	if (methodMap == null) {
 		methodMap = new Hashtable(5);
-		synthetics[CHANGED_DECLARING_CLASS].put(targetMethod, methodMap);
+		synthetics[RECEIVER_TYPE_EMUL].put(targetMethod, methodMap);
 	}
 	MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
 	if (updatedMethod == null){
@@ -757,7 +760,7 @@
 	return methods;
 }
 private FieldBinding resolveTypeFor(FieldBinding field) {
-	if (field.type != null)
+	if ((field.modifiers & AccUnresolved) == 0)
 		return field;
 
 	FieldDeclaration[] fieldDecls = scope.referenceContext.fields;
@@ -766,6 +769,7 @@
 			continue;
 
 		field.type = fieldDecls[f].getTypeBinding(scope);
+		field.modifiers ^= AccUnresolved;
 		if (!field.type.isValidBinding()) {
 			scope.problemReporter().fieldTypeProblem(this, fieldDecls[f], field.type);
 			//scope.problemReporter().invalidType(fieldDecls[f].type, field.type);
@@ -882,19 +886,19 @@
 }
 public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
 	
-	if (synthetics == null || synthetics[METHOD] == null || synthetics[METHOD].size() == 0) return null;
+	if (synthetics == null || synthetics[METHOD_EMUL] == null || synthetics[METHOD_EMUL].size() == 0) return null;
 
 	// difficult to compute size up front because of the embedded arrays so assume there is only 1
 	int index = 0;
 	SyntheticAccessMethodBinding[] bindings = new SyntheticAccessMethodBinding[1];
-	Enumeration fieldsOrMethods = synthetics[METHOD].keys();
+	Enumeration fieldsOrMethods = synthetics[METHOD_EMUL].keys();
 	while (fieldsOrMethods.hasMoreElements()) {
 
 		Object fieldOrMethod = fieldsOrMethods.nextElement();
 
 		if (fieldOrMethod instanceof MethodBinding) {
 
-			SyntheticAccessMethodBinding[] methodAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(fieldOrMethod);
+			SyntheticAccessMethodBinding[] methodAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
 			int numberOfAccessors = 0;
 			if (methodAccessors[0] != null) numberOfAccessors++;
 			if (methodAccessors[1] != null) numberOfAccessors++;
@@ -907,7 +911,7 @@
 
 		} else {
 
-			SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(fieldOrMethod);
+			SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(fieldOrMethod);
 			int numberOfAccessors = 0;
 			if (fieldAccessors[0] != null) numberOfAccessors++;
 			if (fieldAccessors[1] != null) numberOfAccessors++;
@@ -936,23 +940,23 @@
 	
 	if (synthetics == null) return null;
 
-	int fieldSize = synthetics[FIELD] == null ? 0 : synthetics[FIELD].size();
-	int literalSize = synthetics[CLASS_LITERAL] == null ? 0 :synthetics[CLASS_LITERAL].size();
+	int fieldSize = synthetics[FIELD_EMUL] == null ? 0 : synthetics[FIELD_EMUL].size();
+	int literalSize = synthetics[CLASS_LITERAL_EMUL] == null ? 0 :synthetics[CLASS_LITERAL_EMUL].size();
 	int totalSize = fieldSize + literalSize;
 	if (totalSize == 0) return null;
 	FieldBinding[] bindings = new FieldBinding[totalSize];
 
 	// add innerclass synthetics
-	if (synthetics[FIELD] != null){
-		Enumeration elements = synthetics[FIELD].elements();
+	if (synthetics[FIELD_EMUL] != null){
+		Enumeration elements = synthetics[FIELD_EMUL].elements();
 		for (int i = 0; i < fieldSize; i++) {
 			SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
 			bindings[synthBinding.index] = synthBinding;
 		}
 	}
 	// add class literal synthetics
-	if (synthetics[CLASS_LITERAL] != null){
-		Enumeration elements = synthetics[CLASS_LITERAL].elements();
+	if (synthetics[CLASS_LITERAL_EMUL] != null){
+		Enumeration elements = synthetics[CLASS_LITERAL_EMUL].elements();
 		for (int i = 0; i < literalSize; i++) {
 			SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
 			bindings[fieldSize+synthBinding.index] = synthBinding;
@@ -1041,15 +1045,15 @@
 
 public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
 
-	if (synthetics == null || synthetics[FIELD] == null) return null;
-	FieldBinding field = (FieldBinding) synthetics[FIELD].get(targetEnclosingType);
+	if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
+	FieldBinding field = (FieldBinding) synthetics[FIELD_EMUL].get(targetEnclosingType);
 	if (field != null) return field;
 
 	// type compatibility : to handle cases such as
 	// class T { class M{}}
 	// class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
 	if (!onlyExactMatch){
-		Enumeration enum = synthetics[FIELD].elements();
+		Enumeration enum = synthetics[FIELD_EMUL].elements();
 		while (enum.hasMoreElements()) {
 			field = (FieldBinding) enum.nextElement();
 			if (CharOperation.prefixEquals(SyntheticArgumentBinding.EnclosingInstancePrefix, field.name)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java
index 48bdc09..6240995 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java
@@ -75,7 +75,7 @@
 				// check for collision with known methods
 				MethodBinding[] methods = declaringSourceType.methods;
 				for (int i = 0, length = methods.length; i < length; i++) {
-					if (this.selector == methods[i].selector && this.areParametersEqual(methods[i])) {
+					if (CharOperation.equals(this.selector, methods[i].selector) && this.areParametersEqual(methods[i])) {
 						needRename = true;
 						break check;
 					}
@@ -84,7 +84,7 @@
 				if (knownAccessMethods != null) {
 					for (int i = 0, length = knownAccessMethods.length; i < length; i++) {
 						if (knownAccessMethods[i] == null) continue;
-						if (this.selector == knownAccessMethods[i].selector && this.areParametersEqual(methods[i])) {
+						if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && this.areParametersEqual(methods[i])) {
 							needRename = true;
 							break check;
 						}
@@ -92,7 +92,7 @@
 				}
 			}
 			if (needRename) { // retry with a selector postfixed by a growing methodId
-				this.selector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
+				this.setSelector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
 			}
 		} while (needRename);
 	
@@ -139,28 +139,28 @@
 	 * An constructor accessor is a constructor with an extra argument (declaringClass), in case of
 	 * collision with an existing constructor, then add again an extra argument (declaringClass again).
 	 */
-	 public void initializeConstructorAccessor(MethodBinding targetConstructor) {
+	 public void initializeConstructorAccessor(MethodBinding accessedConstructor) {
 	
-		this.targetMethod = targetConstructor;
+		this.targetMethod = accessedConstructor;
 		this.modifiers = AccDefault | AccSynthetic;
-		SourceTypeBinding sourceType = (SourceTypeBinding) targetConstructor.declaringClass; 
+		SourceTypeBinding sourceType = (SourceTypeBinding) accessedConstructor.declaringClass; 
 		SyntheticAccessMethodBinding[] knownAccessMethods = 
 			sourceType.syntheticAccessMethods(); 
 		this.index = knownAccessMethods == null ? 0 : knownAccessMethods.length;
 	
-		this.selector = targetConstructor.selector;
-		this.returnType = targetConstructor.returnType;
+		this.selector = accessedConstructor.selector;
+		this.returnType = accessedConstructor.returnType;
 		this.accessType = ConstructorAccess;
-		this.parameters = new TypeBinding[targetConstructor.parameters.length + 1];
+		this.parameters = new TypeBinding[accessedConstructor.parameters.length + 1];
 		System.arraycopy(
-			targetConstructor.parameters, 
+			accessedConstructor.parameters, 
 			0, 
 			this.parameters, 
 			0, 
-			targetConstructor.parameters.length); 
-		parameters[targetConstructor.parameters.length] = 
-			targetConstructor.declaringClass; 
-		this.thrownExceptions = targetConstructor.thrownExceptions;
+			accessedConstructor.parameters.length); 
+		parameters[accessedConstructor.parameters.length] = 
+			accessedConstructor.declaringClass; 
+		this.thrownExceptions = accessedConstructor.thrownExceptions;
 		this.declaringClass = sourceType;
 	
 		// check for method collision
@@ -171,7 +171,7 @@
 				// check for collision with known methods
 				MethodBinding[] methods = sourceType.methods;
 				for (int i = 0, length = methods.length; i < length; i++) {
-					if (this.selector == methods[i].selector
+					if (CharOperation.equals(this.selector, methods[i].selector)
 						&& this.areParametersEqual(methods[i])) {
 						needRename = true;
 						break check;
@@ -182,7 +182,7 @@
 					for (int i = 0, length = knownAccessMethods.length; i < length; i++) {
 						if (knownAccessMethods[i] == null)
 							continue;
-						if (this.selector == knownAccessMethods[i].selector
+						if (CharOperation.equals(this.selector, knownAccessMethods[i].selector)
 							&& this.areParametersEqual(knownAccessMethods[i])) {
 							needRename = true;
 							break check;
@@ -207,7 +207,7 @@
 			sourceType.scope.referenceContext.methods; 
 		if (methodDecls != null) {
 			for (int i = 0, length = methodDecls.length; i < length; i++) {
-				if (methodDecls[i].binding == targetConstructor) {
+				if (methodDecls[i].binding == accessedConstructor) {
 					this.sourceStart = methodDecls[i].sourceStart;
 					return;
 				}
@@ -218,27 +218,27 @@
 	/**
 	 * An method accessor is a method with an access$N selector, where N is incremented in case of collisions.
 	 */
-	public void initializeMethodAccessor(MethodBinding targetMethod, boolean isSuperAccess, ReferenceBinding declaringClass) {
+	public void initializeMethodAccessor(MethodBinding accessedMethod, boolean isSuperAccess, ReferenceBinding receiverType) {
 		
-		this.targetMethod = targetMethod;
+		this.targetMethod = accessedMethod;
 		this.modifiers = AccDefault | AccStatic | AccSynthetic;
-		SourceTypeBinding declaringSourceType = (SourceTypeBinding) declaringClass;
+		SourceTypeBinding declaringSourceType = (SourceTypeBinding) receiverType;
 		SyntheticAccessMethodBinding[] knownAccessMethods = declaringSourceType.syntheticAccessMethods();
 		int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
 		this.index = methodId;
 	
 		this.selector = CharOperation.concat(AccessMethodPrefix, String.valueOf(methodId).toCharArray());
-		this.returnType = targetMethod.returnType;
+		this.returnType = accessedMethod.returnType;
 		this.accessType = isSuperAccess ? SuperMethodAccess : MethodAccess;
 		
-		if (targetMethod.isStatic()) {
-			this.parameters = targetMethod.parameters;
+		if (accessedMethod.isStatic()) {
+			this.parameters = accessedMethod.parameters;
 		} else {
-			this.parameters = new TypeBinding[targetMethod.parameters.length + 1];
+			this.parameters = new TypeBinding[accessedMethod.parameters.length + 1];
 			this.parameters[0] = declaringSourceType;
-			System.arraycopy(targetMethod.parameters, 0, this.parameters, 1, targetMethod.parameters.length);
+			System.arraycopy(accessedMethod.parameters, 0, this.parameters, 1, accessedMethod.parameters.length);
 		}
-		this.thrownExceptions = targetMethod.thrownExceptions;
+		this.thrownExceptions = accessedMethod.thrownExceptions;
 		this.declaringClass = declaringSourceType;
 	
 		// check for method collision
@@ -249,7 +249,7 @@
 				// check for collision with known methods
 				MethodBinding[] methods = declaringSourceType.methods;
 				for (int i = 0, length = methods.length; i < length; i++) {
-					if (this.selector == methods[i].selector && this.areParametersEqual(methods[i])) {
+					if (CharOperation.equals(this.selector, methods[i].selector) && this.areParametersEqual(methods[i])) {
 						needRename = true;
 						break check;
 					}
@@ -258,7 +258,7 @@
 				if (knownAccessMethods != null) {
 					for (int i = 0, length = knownAccessMethods.length; i < length; i++) {
 						if (knownAccessMethods[i] == null) continue;
-						if (this.selector == knownAccessMethods[i].selector && this.areParametersEqual(knownAccessMethods[i])) {
+						if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && this.areParametersEqual(knownAccessMethods[i])) {
 							needRename = true;
 							break check;
 						}
@@ -266,7 +266,7 @@
 				}
 			}
 			if (needRename) { // retry with a selector & a growing methodId
-				this.selector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
+				this.setSelector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
 			}
 		} while (needRename);
 	
@@ -274,7 +274,7 @@
 		AbstractMethodDeclaration[] methodDecls = declaringSourceType.scope.referenceContext.methods;
 		if (methodDecls != null) {
 			for (int i = 0, length = methodDecls.length; i < length; i++) {
-				if (methodDecls[i].binding == targetMethod) {
+				if (methodDecls[i].binding == accessedMethod) {
 					this.sourceStart = methodDecls[i].sourceStart;
 					return;
 				}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
index 39011c4..6fcedf1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
@@ -34,16 +34,16 @@
 }
 /* Answer true if the receiver can be instantiated
  */
-
 public boolean canBeInstantiated() {
 	return !isBaseType();
 }
-/* Answer the receiver's constant pool name.
- *
- * NOTE: This method should only be used during/after code gen.
+/**
+ *  Answer the receiver's constant pool name.
+ *  NOTE: This method should only be used during/after code gen.
+ *  e.g. 'java/lang/Object' 
  */
+public abstract char[] constantPoolName();
 
-public abstract char[] constantPoolName(); /* java/lang/Object */
 String debugName() {
 	return new String(readableName());
 }
@@ -132,4 +132,34 @@
 	return constantPoolName();
 }
 public abstract char[] sourceName();
+
+/**
+ * Match a well-known type id to its binding
+ */
+public static final TypeBinding wellKnownType(Scope scope, int id) {
+		switch (id) { 
+			case T_boolean :
+				return BooleanBinding;
+			case T_byte :
+				return ByteBinding;
+			case T_char :
+				return CharBinding;
+			case T_short :
+				return ShortBinding;
+			case T_double :
+				return DoubleBinding;
+			case T_float :
+				return FloatBinding;
+			case T_int :
+				return IntBinding;
+			case T_long :
+				return LongBinding;
+			case T_Object :
+				return scope.getJavaLangObject();
+			case T_String :
+				return scope.getJavaLangString();
+			default : 
+				return null;
+		}
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
index a602786..53fc51f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
@@ -16,6 +16,7 @@
 	ReferenceBinding resolvedType;
 UnresolvedReferenceBinding(char[][] compoundName, PackageBinding packageBinding) {
 	this.compoundName = compoundName;
+	this.sourceName = compoundName[compoundName.length - 1]; // reasonable guess
 	this.fPackage = packageBinding;
 }
 String debugName() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UpdatedMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UpdatedMethodBinding.java
new file mode 100644
index 0000000..b87e799
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UpdatedMethodBinding.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.lookup;
+
+public class UpdatedMethodBinding extends MethodBinding {
+	
+	public TypeBinding updatedDeclaringClass;
+
+	public UpdatedMethodBinding(TypeBinding updatedDeclaringClass, int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
+		super(modifiers, selector, returnType, args, exceptions, declaringClass);
+		this.updatedDeclaringClass = updatedDeclaringClass;
+	}
+	
+	public TypeBinding constantPoolDeclaringClass() {
+		return this.updatedDeclaringClass;
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
new file mode 100644
index 0000000..6fb8ef0
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
@@ -0,0 +1,918 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+
+/**
+ * Parser specialized for decoding javadoc comments
+ */
+public class JavadocParser {
+
+	// recognized tags
+	public static final char[] TAG_DEPRECATED = "deprecated".toCharArray(); //$NON-NLS-1$
+	public static final char[] TAG_PARAM = "param".toCharArray(); //$NON-NLS-1$
+	public static final char[] TAG_RETURN = "return".toCharArray(); //$NON-NLS-1$
+	public static final char[] TAG_THROWS = "throws".toCharArray(); //$NON-NLS-1$
+	public static final char[] TAG_EXCEPTION = "exception".toCharArray(); //$NON-NLS-1$
+	public static final char[] TAG_SEE = "see".toCharArray(); //$NON-NLS-1$
+	
+	// tags expected positions
+	public final static int ORDERED_TAGS_NUMBER = 3;
+	public final static int PARAM_TAG_EXPECTED_ORDER = 0;
+	public final static int THROWS_TAG_EXPECTED_ORDER = 1;
+	public final static int SEE_TAG_EXPECTED_ORDER = 2;
+	
+	// Public fields
+	public Javadoc javadoc;
+	public boolean checkJavadoc = false;
+	public Scanner scanner;
+	
+	// Private fields
+	private int currentTokenType = -1;
+	private Parser sourceParser;
+	private int index, tagSourceStart, tagSourceEnd, lineEnd;
+	private char[] source;
+	
+	// Identifier stack
+	protected int identifierPtr;
+	protected char[][] identifierStack;
+	protected int identifierLengthPtr;
+	protected int[] identifierLengthStack;
+	protected long[] identifierPositionStack;
+	// Ast stack
+	protected static int AstStackIncrement = 10;
+	protected int astPtr;
+	protected ASTNode[] astStack;
+	protected int astLengthPtr;
+	protected int[] astLengthStack;
+
+	JavadocParser(Parser sourceParser) {
+		this.sourceParser = sourceParser;
+		this.checkJavadoc = (this.sourceParser.options.getSeverity(CompilerOptions.InvalidJavadoc) != ProblemSeverities.Ignore) ||
+			(this.sourceParser.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore);
+		this.scanner = new Scanner(false, false, false, ClassFileConstants.JDK1_3, null, null);
+		this.identifierStack = new char[10][];
+		this.identifierPositionStack = new long[10];
+		this.identifierLengthStack = new int[20];
+		this.astStack = new ASTNode[20];
+		this.astLengthStack = new int[30];
+	}
+
+	/* (non-Javadoc)
+	 * Returns true if tag @deprecated is present in javadoc comment.
+	 * 
+	 * If javadoc checking is enabled, will also construct an Javadoc node, which will be stored into Parser.javadoc
+	 * slot for being consumed later on.
+	 */
+	public boolean checkDeprecation(int javadocStart, int javadocEnd) {
+
+		boolean foundDeprecated = false;
+		try {
+			this.source = this.sourceParser.scanner.source;
+			if (this.checkJavadoc) {
+				this.javadoc = new Javadoc(javadocStart, javadocEnd);
+				this.astLengthPtr = -1;
+				this.astPtr = -1;
+				this.currentTokenType = -1;
+			} else if (this.sourceParser.options.getSeverity(CompilerOptions.MissingJavadocComments) != ProblemSeverities.Ignore) {
+				this.javadoc = new Javadoc(javadocStart, javadocEnd);
+			} else {
+				this.javadoc = null;
+			}
+
+			int firstLineNumber = this.sourceParser.scanner.getLineNumber(javadocStart);
+			int lastLineNumber = this.sourceParser.scanner.getLineNumber(javadocEnd);
+
+			// scan line per line, since tags must be at beginning of lines only
+			nextLine : for (int line = firstLineNumber; line <= lastLineNumber; line++) {
+				int lineStart = line == firstLineNumber
+						? javadocStart + 3 // skip leading /**
+						: this.sourceParser.scanner.getLineStart(line);
+				this.index = lineStart;
+				this.lineEnd = line == lastLineNumber
+						? javadocEnd - 2 // remove trailing */
+						: this.sourceParser.scanner.getLineEnd(line);
+				while (this.index < this.lineEnd) {
+					char nextCharacter = readChar(); // consider unicodes
+					switch (nextCharacter) {
+						case '@' :
+							if (!this.checkJavadoc) {
+								if ((readChar() == 'd') &&
+									(readChar() == 'e') &&
+									(readChar() == 'p') &&
+									(readChar() == 'r') &&
+									(readChar() == 'e') &&
+									(readChar() == 'c') &&
+									(readChar() == 'a') &&
+									(readChar() == 't') &&
+									(readChar() == 'e') &&
+									(readChar() == 'd')) {
+									// ensure the tag is properly ended: either followed by a space, a tab, line end or asterisk.
+									nextCharacter = readChar();
+									if (Character.isWhitespace(nextCharacter) || nextCharacter == '*') {
+										foundDeprecated = true;
+										break nextLine; // done
+									}
+								}
+								continue nextLine;
+							}
+							this.scanner.resetTo(this.index, this.lineEnd);
+							this.currentTokenType = -1; // flush token cache at line begin
+							try {
+								int tk = readTokenAndConsume();
+								this.tagSourceStart = this.scanner.getCurrentTokenStartPosition();
+								this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+								switch (tk) {
+									case TerminalTokens.TokenNameIdentifier :
+										char[] tag = this.scanner.getCurrentIdentifierSource();
+										if (CharOperation.equals(tag, TAG_DEPRECATED)) {
+											foundDeprecated = true;
+										} else if (CharOperation.equals(tag, TAG_PARAM)) {
+											parseParam();
+										} else if (CharOperation.equals(tag, TAG_EXCEPTION)) {
+											parseThrows();
+										} else if (CharOperation.equals(tag, TAG_SEE)) {
+											parseSee();
+										}
+										break;
+									case TerminalTokens.TokenNamereturn :
+										parseReturn();
+										break;
+									case TerminalTokens.TokenNamethrows :
+										parseThrows();
+										break;
+								}
+							} catch (InvalidInputException e) {
+								consumeToken();
+							}
+							continue nextLine;
+						case '*' :
+							break;
+						default :
+							if (!CharOperation.isWhitespace(nextCharacter)) {
+								continue nextLine;
+							}
+					}
+				}
+			}
+		} finally {
+			if (this.checkJavadoc) {
+				updateJavadoc();
+			}
+			this.source = null; // release source as soon as finished
+		}
+		return foundDeprecated;
+	}
+
+	private void consumeToken() {
+		this.currentTokenType = -1; // flush token cache
+	}
+
+	private int getEndPosition() {
+		if (this.scanner.getCurrentTokenEndPosition() >= this.lineEnd) {
+			return this.lineEnd - 1;
+		} else {
+			return this.scanner.getCurrentTokenEndPosition();
+		}
+	}
+
+	/*
+	 * Parse argument in @see tag method reference
+	 */
+	private Expression parseArguments(TypeReference receiver) throws InvalidInputException {
+
+		// Init
+		int modulo = 0; // should be 2 for (Type,Type,...) or 3 for (Type arg,Type arg,...)
+		int iToken = 0;
+		char[] argName = null;
+		int ptr = this.astPtr;
+		int lptr = this.astLengthPtr;
+		
+		// Decide whether we have a constructor or not
+		boolean isConstructor = true;
+		if (receiver != null) {
+			char[][] receiverTokens = receiver.getTypeName();
+			char[] memberName = this.identifierStack[0];
+			isConstructor = CharOperation.equals(memberName, receiverTokens[receiverTokens.length-1]);
+		}
+
+		// Parse arguments declaration if method reference
+		nextArg : while (this.index < this.scanner.eofPosition) {
+
+			// Read argument type reference
+			TypeReference typeRef;
+			try {
+				typeRef = parseQualifiedName(false);
+			} catch (InvalidInputException e) {
+				break nextArg;
+			}
+			boolean firstArg = modulo == 0;
+			if (firstArg) { // verify position
+				if (iToken != 0)
+					break nextArg;
+			} else if ((iToken % modulo) != 0) {
+					break nextArg;
+			}
+			if (typeRef == null) {
+				if (firstArg && this.currentTokenType == TerminalTokens.TokenNameRPAREN) {
+					if (isConstructor) {
+						JavadocAllocationExpression expr = new JavadocAllocationExpression(this.identifierPositionStack[0]);
+						expr.type = receiver;
+						return expr;
+					} else {
+						JavadocMessageSend msg = new JavadocMessageSend(this.identifierStack[0], this.identifierPositionStack[0]);
+						msg.receiver = receiver;
+						return msg;
+					}
+				}
+				break nextArg;
+			}
+			int argStart = typeRef.sourceStart;
+			int argEnd = typeRef.sourceEnd;
+			iToken++;
+
+			// Read possible array declaration
+			int dim = 0;
+			if (readToken() == TerminalTokens.TokenNameLBRACKET) {
+				while (readToken() == TerminalTokens.TokenNameLBRACKET) {
+					consumeToken();
+					if (readToken() != TerminalTokens.TokenNameRBRACKET) {
+						break nextArg;
+					}
+					consumeToken();
+					dim++;
+				}
+				long pos = ((long) typeRef.sourceStart) << 32 + typeRef.sourceEnd;
+				if (typeRef instanceof JavadocSingleTypeReference) {
+					JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef;
+					typeRef = new JavadocArraySingleTypeReference(singleRef.token, dim, pos);
+				} else {
+					JavadocQualifiedTypeReference qualifRef = (JavadocQualifiedTypeReference) typeRef;
+					typeRef = new JavadocArrayQualifiedTypeReference(qualifRef, dim);
+				}
+			}
+
+			// Read argument name
+			if (readToken() == TerminalTokens.TokenNameIdentifier) {
+				consumeToken();
+				if (firstArg) { // verify position
+					if (iToken != 1)
+						break nextArg;
+				} else if ((iToken % modulo) != 1) {
+						break nextArg;
+				}
+				if (argName == null) { // verify that all arguments name are declared
+					if (!firstArg) {
+						break nextArg;
+					}
+				}
+				argName = this.scanner.getCurrentIdentifierSource();
+				argEnd = this.scanner.getCurrentTokenEndPosition();
+				iToken++;
+			} else if (argName != null) { // verify that no argument name is declared
+				break nextArg;
+			}
+			
+			// Verify token position
+			if (firstArg) {
+				modulo = iToken + 1;
+			} else {
+				if ((iToken % modulo) != (modulo - 1)) {
+					break nextArg;
+				}
+			}
+
+			// Read separator or end arguments declaration
+			int token = readToken();
+			char[] name = argName == null ? new char[0] : argName;
+			if (token == TerminalTokens.TokenNameCOMMA) {
+				// Create new argument
+				JavadocArgumentExpression expr = new JavadocArgumentExpression(name, argStart, argEnd, typeRef);
+				pushOnAstStack(expr, firstArg);
+				consumeToken();
+				iToken++;
+			} else if (token == TerminalTokens.TokenNameRPAREN) {
+				// Create new argument
+				JavadocArgumentExpression expr = new JavadocArgumentExpression(name, argStart, argEnd, typeRef);
+				pushOnAstStack(expr, firstArg);
+				int size = this.astLengthStack[this.astLengthPtr--];
+				// Build arguments array
+				JavadocArgumentExpression[] arguments = new JavadocArgumentExpression[size];
+				for (int i = (size - 1); i >= 0; i--) {
+					arguments[i] = (JavadocArgumentExpression) this.astStack[this.astPtr--];
+				}
+				// Create message send
+				if (isConstructor) {
+					JavadocAllocationExpression alloc = new JavadocAllocationExpression(this.identifierPositionStack[0]);
+					alloc.arguments = arguments;
+					alloc.type = receiver;
+					return alloc;
+				} else {
+					JavadocMessageSend msg = new JavadocMessageSend(this.identifierStack[0], this.identifierPositionStack[0], arguments);
+					msg.receiver = receiver;
+					return msg;
+				}
+			} else {
+				break nextArg;
+			}
+		}
+
+		// Invalid input: reset ast stacks pointers
+		consumeToken();
+		if (iToken > 0) {
+			this.astPtr = ptr;
+			this.astLengthPtr = lptr;
+		}
+		throw new InvalidInputException();
+	}
+
+	/*
+	 * Parse an URL link reference in @see tag
+	 */
+	private boolean parseHref() throws InvalidInputException {
+		int start = this.scanner.getCurrentTokenStartPosition();
+		//int end = this.scanner.getCurrentTokenEndPosition();
+		if (readTokenAndConsume() == TerminalTokens.TokenNameIdentifier) {
+			//end = this.index-1;
+			if (CharOperation.equals(this.scanner.getCurrentIdentifierSource(), new char[]{'a'}, false)
+					&& readTokenAndConsume() == TerminalTokens.TokenNameIdentifier) {
+				//end = this.index - 1;
+				try {
+					if (CharOperation.equals(this.scanner.getCurrentIdentifierSource(), new char[]{'h', 'r', 'e', 'f'}, false) &&
+						readTokenAndConsume() == TerminalTokens.TokenNameEQUAL &&
+						readTokenAndConsume() == TerminalTokens.TokenNameStringLiteral &&
+						readTokenAndConsume() == TerminalTokens.TokenNameGREATER) {
+						while (readTokenAndConsume() != TerminalTokens.TokenNameLESS) {
+							if (this.scanner.currentPosition >= this.lineEnd) {
+								this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd - 1);
+								return false;
+							}
+						}
+						if (readTokenAndConsume() == TerminalTokens.TokenNameDIVIDE	&&
+							readTokenAndConsume() == TerminalTokens.TokenNameIdentifier) {
+							//end = this.index - 1;
+							if (CharOperation.equals(this.scanner.getCurrentIdentifierSource(), new char[]{'a'}, false)	&&
+								readTokenAndConsume() == TerminalTokens.TokenNameGREATER) {
+								// Valid href
+								return true;
+							}
+						}
+					}
+				} catch (InvalidInputException ex) {
+					// Place to change end position for error report
+					//end = getEndPosition();
+				}
+			}
+		}
+		this.sourceParser.problemReporter().javadocInvalidSeeUrlReference(start, this.lineEnd - 1);
+		return false;
+	}
+
+	/*
+	 * Parse a method reference in @see tag
+	 */
+	private Expression parseMember(TypeReference receiver) throws InvalidInputException {
+		// Init
+		this.identifierPtr = -1;
+		this.identifierLengthPtr = -1;
+		int start = this.scanner.getCurrentTokenStartPosition();
+		
+		// Get type ref
+		TypeReference typeRef = receiver;
+		if (typeRef == null) {
+			char[] name = this.sourceParser.compilationUnit.compilationResult.compilationUnit.getMainTypeName();
+			if (name == null) {
+				throw new InvalidInputException();
+			}
+			typeRef = new JavadocSingleTypeReference(name, 0, 0, 0);
+		}
+		
+		// Get member identifier
+		if (readTokenAndConsume() == TerminalTokens.TokenNameIdentifier) {
+			pushIdentifier(true);
+			if (readTokenAndConsume() == TerminalTokens.TokenNameLPAREN) {
+				start = this.scanner.getCurrentTokenStartPosition();
+				try {
+					return parseArguments(typeRef);
+				} catch (InvalidInputException e) {
+					int end = this.scanner.getCurrentTokenEndPosition() < this.lineEnd ?
+							this.scanner.getCurrentTokenEndPosition() :
+							this.scanner.getCurrentTokenStartPosition();
+					end = end < this.lineEnd ? end : (this.lineEnd - 1);
+					this.sourceParser.problemReporter().javadocInvalidSeeReferenceArgs(start, end);
+				}
+				return null;
+			}
+			JavadocFieldReference field = new JavadocFieldReference(this.identifierStack[0], this.identifierPositionStack[0]);
+			field.receiver = typeRef;
+			field.tagSourceStart = this.tagSourceStart;
+			field.tagSourceEnd = this.tagSourceEnd;
+			return field;
+		}
+		this.sourceParser.problemReporter().javadocInvalidSeeReference(start, getEndPosition());
+		return null;
+	}
+
+	/*
+	 * Parse @param tag declaration
+	 */
+	private void parseParam() {
+
+		// Store current token state
+		int start = this.tagSourceStart;
+		int end = this.tagSourceEnd;
+
+		try {
+			// Push identifier next
+			int token = readTokenAndConsume();
+			switch (token) {
+				case TerminalTokens.TokenNameIdentifier :
+					JavadocSingleNameReference argument = new JavadocSingleNameReference(this.scanner.getCurrentIdentifierSource(),
+							this.scanner.getCurrentTokenStartPosition(),
+							this.scanner.getCurrentTokenEndPosition());
+					argument.tagSourceStart = this.tagSourceStart;
+					argument.tagSourceEnd = this.tagSourceEnd;
+					pushParamName(argument);
+					return;
+				case TerminalTokens.TokenNameEOF :
+					//end = scanner.eofPosition-2;
+					break;
+				default :
+					start = this.scanner.getCurrentTokenStartPosition();
+					end = this.scanner.getCurrentTokenEndPosition();
+					break;
+			}
+		} catch (InvalidInputException e) {
+			end = getEndPosition();
+		}
+
+		// Report problem
+		this.sourceParser.problemReporter().javadocMissingParamName(start, end);
+		consumeToken();
+	}
+
+	/*
+	 * Parse a qualified name and built a type reference if the syntax is valid.
+	 */
+	private TypeReference parseQualifiedName(boolean reset) throws InvalidInputException {
+
+		// Reset identifier stack if requested
+		if (reset) {
+			this.identifierPtr = -1;
+			this.identifierLengthPtr = -1;
+		}
+
+		// Scan tokens
+		nextToken : for (int iToken = 0; ; iToken++) {
+			int token = readToken();
+			switch (token) {
+				case TerminalTokens.TokenNameIdentifier :
+					if (((iToken % 2) > 0)) { // identifiers must be odd tokens
+						break nextToken;
+					}
+					pushIdentifier(iToken == 0);
+					consumeToken();
+					break;
+
+				case TerminalTokens.TokenNameDOT :
+					if ((iToken % 2) == 0) { // dots must be even tokens
+						throw new InvalidInputException();
+					}
+					consumeToken();
+					break;
+
+				case TerminalTokens.TokenNamevoid :
+				case TerminalTokens.TokenNameboolean :
+				case TerminalTokens.TokenNamebyte :
+				case TerminalTokens.TokenNamechar :
+				case TerminalTokens.TokenNamedouble :
+				case TerminalTokens.TokenNamefloat :
+				case TerminalTokens.TokenNameint :
+				case TerminalTokens.TokenNamelong :
+				case TerminalTokens.TokenNameshort :
+					if (iToken > 0) {
+						throw new InvalidInputException();
+					}
+					pushIdentifier(true);
+					consumeToken();
+					break nextToken;
+
+				default :
+					if (iToken == 0) {
+						return null;
+					}
+					if ((iToken % 2) == 0) { // dots must be followed by an identifier
+						throw new InvalidInputException();
+					}
+					break nextToken;
+			}
+		}
+
+		// Build type reference from read tokens
+		TypeReference typeRef = null;
+		int size = this.identifierLengthStack[this.identifierLengthPtr--];
+		if (size == 1) { // Single Type ref
+			typeRef = new JavadocSingleTypeReference(
+						this.identifierStack[this.identifierPtr],
+						this.identifierPositionStack[this.identifierPtr],
+						this.tagSourceStart,
+						this.tagSourceEnd);
+		} else if (size > 1) { // Qualified Type ref
+			char[][] tokens = new char[size][];
+			System.arraycopy(this.identifierStack, this.identifierPtr - size + 1, tokens, 0, size);
+			long[] positions = new long[size];
+			System.arraycopy(this.identifierPositionStack, this.identifierPtr - size + 1, positions, 0, size);
+			typeRef = new JavadocQualifiedTypeReference(tokens, positions, this.tagSourceStart, this.tagSourceEnd);
+		}
+		this.identifierPtr -= size;
+		return typeRef;
+	}
+
+	/*
+	 * Parse a reference in @see tag
+	 */
+	private Expression parseReference() throws InvalidInputException {
+		TypeReference typeRef = null;
+		Expression reference = null;
+		nextToken : while (this.index < this.scanner.eofPosition) {
+			int token = readToken();
+			switch (token) {
+				case TerminalTokens.TokenNameStringLiteral :
+					// @see "string"
+					int start = this.scanner.getCurrentTokenStartPosition();
+					if (typeRef == null) {
+						consumeToken();
+						try {
+							if (readToken() == TerminalTokens.TokenNameEOF) {
+								return null;
+							}
+						} catch (InvalidInputException e) {
+							// Do nothing as we want to underline from the beginning of the string
+						}
+					}
+					this.sourceParser.problemReporter().javadocInvalidSeeReference(start, this.lineEnd - 1);
+					return null;
+				case TerminalTokens.TokenNameLESS :
+					// @see "<a href="URL#Value">label</a>
+					consumeToken();
+					start = this.scanner.getCurrentTokenStartPosition();
+					if (parseHref()) {
+						if (typeRef == null) {
+							consumeToken();
+							try {
+								if (readToken() == TerminalTokens.TokenNameEOF) {
+									return null;
+								}
+							} catch (InvalidInputException e) {
+								// Do nothing as we want to underline from the beginning of the href
+							}
+						}
+						this.sourceParser.problemReporter().javadocInvalidSeeReference(start, this.lineEnd - 1);
+					}
+					return null;
+				case TerminalTokens.TokenNameERROR :
+					consumeToken();
+					if (this.scanner.currentCharacter == '#') { // @see ...#member
+						reference = parseMember(typeRef);
+						if (reference == null) {
+							return null;
+						}
+					}
+					break nextToken;
+				case TerminalTokens.TokenNameIdentifier :
+					if (typeRef == null) {
+						typeRef = parseQualifiedName(true);
+						break;
+					}
+					break nextToken;
+				default :
+					break nextToken;
+			}
+		}
+		
+		// Verify that we got a reference
+		if (reference == null) reference = typeRef;
+		if (reference == null) {
+			this.sourceParser.problemReporter().javadocMissingSeeReference(this.tagSourceStart, this.tagSourceEnd);
+			return null;
+		}
+		
+		// Verify that we're at line end
+		int start = this.scanner.getCurrentTokenStartPosition();
+		try {
+			int token = readTokenAndConsume();
+			if (token != TerminalTokens.TokenNameLPAREN) {
+				return reference;
+			}
+		} catch (InvalidInputException e) {
+			// Do nothing as we report an error after
+		}
+		this.sourceParser.problemReporter().javadocInvalidSeeReference(start, this.lineEnd - 1);
+		return null;
+	}
+	
+	/*
+	 * Parse @return tag declaration
+	 */
+	private void parseReturn() {
+		if (this.javadoc.returnStatement == null) {
+			this.javadoc.returnStatement = new JavadocReturnStatement(this.scanner.getCurrentTokenStartPosition(),
+					this.scanner.getCurrentTokenEndPosition(),
+					this.scanner.getRawTokenSourceEnd());
+		} else {
+			this.sourceParser.problemReporter().javadocDuplicatedReturnTag(
+					this.scanner.getCurrentTokenStartPosition(),
+					this.scanner.getCurrentTokenEndPosition());
+		}
+	}
+
+	/*
+	 * Parse @see tag declaration
+	 */
+	private void parseSee() {
+		int start = this.scanner.currentPosition;
+		try {
+			Expression msgRef = parseReference();
+			if (msgRef != null) {
+				pushSeeRef(msgRef);
+			}
+		} catch (InvalidInputException ex) {
+			this.sourceParser.problemReporter().javadocInvalidSeeReference(start, getEndPosition());
+		} finally {
+			consumeToken();
+		}
+	}
+
+	/*
+	 * Parse @throws tag declaration
+	 */
+	private void parseThrows() {
+		int start = this.scanner.currentPosition;
+		try {
+			TypeReference typeRef = parseQualifiedName(true);
+			if (typeRef == null) {
+				this.sourceParser.problemReporter().javadocMissingThrowsClassName(this.tagSourceStart, this.tagSourceEnd);
+			} else {
+				pushThrowName(typeRef);
+			}
+		} catch (InvalidInputException ex) {
+			this.sourceParser.problemReporter().javadocInvalidThrowsClass(start, getEndPosition());
+		} finally {
+			consumeToken();
+		}
+	}
+	
+	/*
+	 * push the consumeToken on the identifier stack. Increase the total number of identifier in the stack.
+	 */
+	private void pushIdentifier(boolean newLength) {
+
+		try {
+			this.identifierStack[++this.identifierPtr] = this.scanner.getCurrentIdentifierSource();
+			this.identifierPositionStack[this.identifierPtr] = (((long) this.scanner.startPosition) << 32)
+					+ (this.scanner.currentPosition - 1);
+		} catch (IndexOutOfBoundsException e) {
+			//---stack reallaocation (identifierPtr is correct)---
+			int oldStackLength = this.identifierStack.length;
+			char[][] oldStack = this.identifierStack;
+			this.identifierStack = new char[oldStackLength + 10][];
+			System.arraycopy(oldStack, 0, this.identifierStack, 0, oldStackLength);
+			this.identifierStack[this.identifierPtr] = this.scanner.getCurrentTokenSource();
+			// identifier position stack
+			long[] oldPos = this.identifierPositionStack;
+			this.identifierPositionStack = new long[oldStackLength + 10];
+			System.arraycopy(oldPos, 0, this.identifierPositionStack, 0, oldStackLength);
+			this.identifierPositionStack[this.identifierPtr] = (((long) this.scanner.startPosition) << 32)
+					+ (this.scanner.currentPosition - 1);
+		}
+
+		if (newLength) {
+			try {
+				this.identifierLengthStack[++this.identifierLengthPtr] = 1;
+			} catch (IndexOutOfBoundsException e) {
+				/* ---stack reallocation (identifierLengthPtr is correct)--- */
+				int oldStackLength = this.identifierLengthStack.length;
+				int oldStack[] = this.identifierLengthStack;
+				this.identifierLengthStack = new int[oldStackLength + 10];
+				System.arraycopy(oldStack, 0, this.identifierLengthStack, 0, oldStackLength);
+				this.identifierLengthStack[this.identifierLengthPtr] = 1;
+			}
+		} else {
+			this.identifierLengthStack[this.identifierLengthPtr]++;
+		}
+	}
+
+	/*
+	 * Add a new obj on top of the ast stack.
+	 * If new length is required, then add also a new length in length stack.
+	 */
+	private void pushOnAstStack(ASTNode node, boolean newLength) {
+
+		if (node == null) {
+			this.astLengthStack[++this.astLengthPtr] = 0;
+			return;
+		}
+
+		try {
+			this.astStack[++this.astPtr] = node;
+		} catch (IndexOutOfBoundsException e) {
+			int oldStackLength = this.astStack.length;
+			ASTNode[] oldStack = this.astStack;
+			this.astStack = new ASTNode[oldStackLength + AstStackIncrement];
+			System.arraycopy(oldStack, 0, this.astStack, 0, oldStackLength);
+			this.astPtr = oldStackLength;
+			this.astStack[this.astPtr] = node;
+		}
+
+		if (newLength) {
+			try {
+				this.astLengthStack[++this.astLengthPtr] = 1;
+			} catch (IndexOutOfBoundsException e) {
+				int oldStackLength = this.astLengthStack.length;
+				int[] oldPos = this.astLengthStack;
+				this.astLengthStack = new int[oldStackLength + AstStackIncrement];
+				System.arraycopy(oldPos, 0, this.astLengthStack, 0, oldStackLength);
+				this.astLengthStack[this.astLengthPtr] = 1;
+			}
+		} else {
+			this.astLengthStack[this.astLengthPtr]++;
+		}
+	}
+
+	/*
+	 * Push a param name in ast node stack.
+	 */
+	private void pushParamName(JavadocSingleNameReference arg) {
+		if (this.astLengthPtr == -1) { // First push
+			pushOnAstStack(arg, true);
+		} else {
+			// Verify that no @throws has been declared before
+			for (int i=THROWS_TAG_EXPECTED_ORDER; i<=this.astLengthPtr; i+=ORDERED_TAGS_NUMBER) {
+				if (this.astLengthStack[i] != 0) {
+					this.sourceParser.problemReporter().javadocUnexpectedTag(arg.tagSourceStart, arg.tagSourceEnd);
+					return;
+				}
+			}
+			switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) {
+				case PARAM_TAG_EXPECTED_ORDER :
+					// previous push was a @param tag => push another param name
+					pushOnAstStack(arg, false);
+					break;
+				case SEE_TAG_EXPECTED_ORDER :
+					// previous push was a @see tag => push new param name
+					pushOnAstStack(arg, true);
+					break;
+			}
+		}
+	}
+
+	/*
+	 * Push a reference statement in ast node stack.
+	 */
+	private void pushSeeRef(Statement statement) {
+		if (this.astLengthPtr == -1) { // First push
+			pushOnAstStack(null, true);
+			pushOnAstStack(null, true);
+			pushOnAstStack(statement, true);
+		} else {
+			switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) {
+				case PARAM_TAG_EXPECTED_ORDER :
+					// previous push was a @param tag => push empty @throws tag and new @see tag
+					pushOnAstStack(null, true);
+					pushOnAstStack(statement, true);
+					break;
+				case THROWS_TAG_EXPECTED_ORDER :
+					// previous push was a @throws tag => push new @see tag
+					pushOnAstStack(statement, true);
+					break;
+				case SEE_TAG_EXPECTED_ORDER :
+					// previous push was a @see tag => push another @see tag
+					pushOnAstStack(statement, false);
+					break;
+			}
+		}
+	}
+
+	private void pushThrowName(TypeReference typeRef) {
+		if (this.astLengthPtr == -1) { // First push
+			pushOnAstStack(null, true);
+			pushOnAstStack(typeRef, true);
+		} else {
+			switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) {
+				case PARAM_TAG_EXPECTED_ORDER :
+					// previous push was a @param tag => push new @throws tag
+					pushOnAstStack(typeRef, true);
+					break;
+				case THROWS_TAG_EXPECTED_ORDER :
+					// previous push was a @throws tag => push another @throws tag
+					pushOnAstStack(typeRef, false);
+					break;
+				case SEE_TAG_EXPECTED_ORDER :
+					// previous push was a @see tag => push empty @param and new @throws tags
+					pushOnAstStack(null, true);
+					pushOnAstStack(typeRef, true);
+					break;
+			}
+		}
+	}
+
+	private char readChar() {
+
+		char c = this.source[this.index++];
+		if (c == '\\') {
+			int c1, c2, c3, c4;
+			this.index++;
+			while (this.source[this.index] == 'u')
+				this.index++;
+			if (!(((c1 = Character.getNumericValue(this.source[this.index++])) > 15 || c1 < 0)
+					|| ((c2 = Character.getNumericValue(this.source[this.index++])) > 15 || c2 < 0)
+					|| ((c3 = Character.getNumericValue(this.source[this.index++])) > 15 || c3 < 0) || ((c4 = Character.getNumericValue(this.source[this.index++])) > 15 || c4 < 0))) {
+				c = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+			}
+		}
+		return c;
+	}
+
+	/*
+	 * Read token only if previous was consumed
+	 */
+	private int readToken() throws InvalidInputException {
+		if (this.currentTokenType < 0) {
+			this.currentTokenType = this.scanner.getNextToken();
+			this.index = this.scanner.currentPosition;
+		}
+		return this.currentTokenType;
+	}
+
+	private int readTokenAndConsume() throws InvalidInputException {
+		int token = readToken();
+		consumeToken();
+		return token;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		buffer.append("check javadoc: ").append(this.checkJavadoc).append("\n");	//$NON-NLS-1$ //$NON-NLS-2$
+		buffer.append("javadoc: ").append(this.javadoc).append("\n");	//$NON-NLS-1$ //$NON-NLS-2$
+		return buffer.toString();
+	}
+	/*
+	 * Fill javadoc fields with information in ast nodes stack.
+	 */
+	private void updateJavadoc() {
+		if (this.astLengthPtr == -1) {
+			return;
+		}
+
+		// Initialize arrays
+		int[] sizes = new int[ORDERED_TAGS_NUMBER];
+		for (int i=0; i<=this.astLengthPtr; i++) {
+			sizes[i%ORDERED_TAGS_NUMBER] += this.astLengthStack[i];
+		}
+		this.javadoc.references = new Expression[sizes[SEE_TAG_EXPECTED_ORDER]];
+		this.javadoc.thrownExceptions = new TypeReference[sizes[THROWS_TAG_EXPECTED_ORDER]];
+		this.javadoc.parameters = new JavadocSingleNameReference[sizes[PARAM_TAG_EXPECTED_ORDER]];
+		
+		// Store nodes in arrays
+		while (this.astLengthPtr >= 0) {
+			int ptr = this.astLengthPtr % ORDERED_TAGS_NUMBER;
+			// Starting with the stack top, so get references (eg. Expression) coming from @see declarations
+			if (ptr == SEE_TAG_EXPECTED_ORDER) {
+				int size = this.astLengthStack[this.astLengthPtr--];
+				for (int i=0; i<size; i++) {
+					this.javadoc.references[--sizes[ptr]] = (Expression) this.astStack[this.astPtr--];
+				}
+			}
+
+			// Then continuing with class names (eg. TypeReference) coming from @throw/@exception declarations
+			else if (ptr == THROWS_TAG_EXPECTED_ORDER) {
+				int size = this.astLengthStack[this.astLengthPtr--];
+				for (int i=0; i<size; i++) {
+					this.javadoc.thrownExceptions[--sizes[ptr]] = (TypeReference) this.astStack[this.astPtr--];
+				}
+			}
+
+			// Finally, finishing with parameters nales (ie. Argument) coming from @param declaration
+			else if (ptr == PARAM_TAG_EXPECTED_ORDER) {
+				int size = this.astLengthStack[this.astLengthPtr--];
+				for (int i=0; i<size; i++) {
+					this.javadoc.parameters[--sizes[ptr]] = (JavadocSingleNameReference) this.astStack[this.astPtr--];
+				}
+			}
+		}
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index c76fec5..d737891 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -12,6 +12,13 @@
 package org.eclipse.jdt.internal.compiler.parser;
 
 import java.io.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -23,17 +30,18 @@
 import org.eclipse.jdt.internal.compiler.lookup.BindingIds;
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.parser.diagnose.DiagnoseParser;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class Parser implements BindingIds, ParserBasicInformation, TerminalTokens, CompilerModifiers, OperatorIds, TypeIds {
-
 	protected ProblemReporter problemReporter;
+	protected CompilerOptions options;
 	public int firstToken ; // handle for multiple parsing goals
 	public int lastAct ; //handle for multiple parsing goals
-	protected ReferenceContext referenceContext;
+	public ReferenceContext referenceContext;
 	public int currentToken;
 	private int synchronizedBlockSourceStart;
 
@@ -43,14 +51,15 @@
 	public static boolean VERBOSE_RECOVERY = false;
 	protected boolean restartRecovery;
 	protected int listLength; // for recovering some incomplete list (interfaces, throws or parameters)
+	protected boolean hasError;
 	protected boolean hasReportedError;
+	public boolean reportSyntaxErrorIsRequired = true;
+	public boolean reportOnlyOneSyntaxError = false;
 	protected int recoveredStaticInitializerStart;
 	protected int lastIgnoredToken, nextIgnoredToken;
 	protected int lastErrorEndPosition;
+	protected boolean ignoreNextOpeningBrace;
 		
-	// 1.4 feature
-	protected boolean assertMode = false;
-	
 	//internal data for the automat 
 	protected final static int StackIncrement = 255;
 	protected int stateStackTop;
@@ -60,11 +69,11 @@
 	//ast stack
 	final static int AstStackIncrement = 100;
 	protected int astPtr;
-	protected AstNode[] astStack = new AstNode[AstStackIncrement];
+	protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
 	protected int astLengthPtr;
 	protected int[] astLengthStack;
 	public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
-	AstNode [] noAstNodes = new AstNode[AstStackIncrement];
+	ASTNode [] noAstNodes = new ASTNode[AstStackIncrement];
 	//expression stack
 	final static int ExpressionStackIncrement = 100;
 	protected int expressionPtr;
@@ -78,12 +87,13 @@
 	protected int identifierLengthPtr;
 	protected int[] identifierLengthStack;
 	protected long[] identifierPositionStack;
-	//positions , dimensions , .... (what ever is int) ..... stack
+	//positions , dimensions , .... (int stacks)
 	protected int intPtr;
 	protected int[] intStack;
 	protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
 	protected int endStatementPosition;
 	protected int lParenPos,rParenPos; //accurate only when used !
+	protected int rBraceStart, rBraceEnd, rBraceSuccessorStart; //accurate only when used !
 	//modifiers dimensions nestedType etc.......
 	protected boolean optimizeStringLiterals =true;
 	protected int modifiers;
@@ -95,270 +105,50 @@
 	protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
 	protected int dietInt = 0; // if > 0 force the none-diet-parsing mode (even if diet if requested) [field parsing with anonymous inner classes...]
 	protected int[] variablesCounter;
-	//===DATA===DATA===DATA===DATA===DATA===DATA===//
-    public final static byte rhs[] = {0,
-            2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-            2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,
-            1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-            2,2,1,1,1,1,3,4,0,1,2,1,1,1,1,
-            1,1,1,1,1,5,1,2,1,2,2,2,1,1,2,
-            2,2,4,1,1,1,1,2,1,1,1,1,1,1,1,
-            1,1,1,1,2,3,3,2,2,1,3,1,3,1,2,
-            1,1,1,3,0,3,1,1,1,1,1,1,1,4,1,
-            3,3,7,0,0,0,0,0,2,1,1,1,2,2,4,
-            4,5,4,4,2,1,2,3,3,1,3,3,1,3,1,
-            4,0,2,1,2,2,4,1,1,2,5,5,7,7,7,
-            7,2,2,3,2,2,3,1,2,1,2,1,1,2,2,
-            1,1,1,1,1,3,3,4,1,3,4,0,1,2,1,
-            1,1,1,2,3,4,0,1,1,1,1,1,1,1,1,
-            1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-            1,3,3,2,1,1,1,1,1,1,1,5,7,7,6,
-            2,3,3,4,1,2,2,1,2,3,2,5,5,7,9,
-            9,1,1,1,1,3,3,5,2,3,2,3,3,3,5,
-            1,3,4,1,2,5,2,1,1,1,1,1,1,1,3,
-            1,1,3,3,3,3,3,1,1,5,6,8,7,2,0,
-            2,0,1,3,3,4,3,4,1,2,3,2,1,1,2,
-            2,3,3,4,6,6,4,4,4,1,1,1,1,2,2,
-            0,1,1,3,3,1,3,3,1,3,3,1,6,6,5,
-            0,0,1,3,3,3,1,3,3,1,3,3,3,1,3,
-            3,3,3,3,1,3,3,1,3,1,3,1,3,1,3,
-            1,3,1,5,1,1,3,3,1,1,1,1,1,1,1,
-            1,1,1,1,1,1,1,1,0,1,0,1,0,1,0,
-            1,0,1,0,1,0,2,0,1,0,1,0,1,0,1,
-            0,1,0,1,0,1,0,2,0,0,1,0,1,0,1,
-            0,1
-    };
 
-	public  static char asb[] = null;
-	public  static char asr[] = null;
-	public  static char symbol_index[] = null;
+	// javadoc
+	public JavadocParser javadocParser;
+	public Javadoc javadoc;
+	
+	public static byte rhs[] = null;
+	public static char asb[] = null;
+	public static char asr[] = null;
+	public static char nasb[] = null;
+	public static char nasr[] = null;
+
+	public static char terminal_index[] = null;
+	public static char non_terminal_index[] = null;
+	
+	public static char term_action[] = null;
+	public static byte term_check[] = null;
+
 	private static final String UNEXPECTED_EOF = "Unexpected End Of File" ; //$NON-NLS-1$
+	private static final String INVALID_CHARACTER = "Invalid Character" ; //$NON-NLS-1$
+	private static final String EOF_TOKEN = "$eof" ; //$NON-NLS-1$
+	private static final String ERROR_TOKEN = "$error" ; //$NON-NLS-1$
 
-    public final static String name[] = { null,
-            "++", //$NON-NLS-1$
-            "--", //$NON-NLS-1$
-            "==", //$NON-NLS-1$
-            "<=", //$NON-NLS-1$
-            ">=", //$NON-NLS-1$
-            "!=", //$NON-NLS-1$
-            "<<", //$NON-NLS-1$
-            ">>", //$NON-NLS-1$
-            ">>>", //$NON-NLS-1$
-            "+=", //$NON-NLS-1$
-            "-=", //$NON-NLS-1$
-            "*=", //$NON-NLS-1$
-            "/=", //$NON-NLS-1$
-            "&=", //$NON-NLS-1$
-            "|=", //$NON-NLS-1$
-            "^=", //$NON-NLS-1$
-            "%=", //$NON-NLS-1$
-            "<<=", //$NON-NLS-1$
-            ">>=", //$NON-NLS-1$
-            ">>>=", //$NON-NLS-1$
-            "||", //$NON-NLS-1$
-            "&&", //$NON-NLS-1$
-            "+", //$NON-NLS-1$
-            "-", //$NON-NLS-1$ 
-            "!", //$NON-NLS-1$
-            "%", //$NON-NLS-1$
-            "^", //$NON-NLS-1$
-            "&", //$NON-NLS-1$
-            "*", //$NON-NLS-1$
-            "|", //$NON-NLS-1$
-            "~", //$NON-NLS-1$
-            "/", //$NON-NLS-1$
-            ">", //$NON-NLS-1$
-            "<", //$NON-NLS-1$
-            "(", //$NON-NLS-1$
-            ")", //$NON-NLS-1$
-            "{", //$NON-NLS-1$
-            "}", //$NON-NLS-1$
-            "[", //$NON-NLS-1$
-            "]", //$NON-NLS-1$
-            ";", //$NON-NLS-1$
-            "?", //$NON-NLS-1$
-            ":", //$NON-NLS-1$
-            ",", //$NON-NLS-1$
-            ".", //$NON-NLS-1$
-            "=", //$NON-NLS-1$
-            "", //$NON-NLS-1$
-            "$empty", //$NON-NLS-1$
-            "Identifier", //$NON-NLS-1$
-            "abstract", //$NON-NLS-1$
-            "assert", //$NON-NLS-1$
-            "boolean", //$NON-NLS-1$
-            "break", //$NON-NLS-1$
-            "byte", //$NON-NLS-1$
-            "case", //$NON-NLS-1$
-            "catch", //$NON-NLS-1$
-            "char", //$NON-NLS-1$
-            "class", //$NON-NLS-1$
-            "continue", //$NON-NLS-1$
-            "default", //$NON-NLS-1$
-            "do", //$NON-NLS-1$
-            "double", //$NON-NLS-1$
-            "else", //$NON-NLS-1$
-            "extends", //$NON-NLS-1$
-            "false", //$NON-NLS-1$
-            "final", //$NON-NLS-1$
-            "finally", //$NON-NLS-1$
-            "float", //$NON-NLS-1$
-            "for", //$NON-NLS-1$
-            "if", //$NON-NLS-1$
-            "implements", //$NON-NLS-1$
-            "import", //$NON-NLS-1$
-            "instanceof", //$NON-NLS-1$
-            "int", //$NON-NLS-1$
-            "interface", //$NON-NLS-1$
-            "long", //$NON-NLS-1$
-            "native", //$NON-NLS-1$
-            "new", //$NON-NLS-1$
-            "null", //$NON-NLS-1$
-            "package", //$NON-NLS-1$
-            "private", //$NON-NLS-1$
-            "protected", //$NON-NLS-1$
-            "public", //$NON-NLS-1$
-            "return", //$NON-NLS-1$
-            "short", //$NON-NLS-1$
-            "static", //$NON-NLS-1$
-            "strictfp", //$NON-NLS-1$
-            "super", //$NON-NLS-1$
-            "switch", //$NON-NLS-1$
-            "synchronized", //$NON-NLS-1$
-            "this", //$NON-NLS-1$
-            "throw", //$NON-NLS-1$
-            "throws", //$NON-NLS-1$
-            "transient", //$NON-NLS-1$
-            "true", //$NON-NLS-1$
-            "try", //$NON-NLS-1$
-            "void", //$NON-NLS-1$
-            "volatile", //$NON-NLS-1$
-            "while", //$NON-NLS-1$
-            "IntegerLiteral", //$NON-NLS-1$
-            "LongLiteral", //$NON-NLS-1$
-            "FloatingPointLiteral", //$NON-NLS-1$
-            "DoubleLiteral", //$NON-NLS-1$
-            "CharacterLiteral", //$NON-NLS-1$
-            "StringLiteral", //$NON-NLS-1$
-            UNEXPECTED_EOF, 
-            "Invalid Character", //$NON-NLS-1$
-            "Goal", //$NON-NLS-1$
-            "MethodBody", //$NON-NLS-1$
-            "ConstructorBody", //$NON-NLS-1$
-            "StaticInitializer", //$NON-NLS-1$
-            "Initializer", //$NON-NLS-1$
-            "Headers", //$NON-NLS-1$
-            "BlockStatements", //$NON-NLS-1$
-            "MethodPushModifiersHeader", //$NON-NLS-1$
-            "CatchHeader", //$NON-NLS-1$
-            "FieldDeclaration", //$NON-NLS-1$
-            "ImportDeclaration", //$NON-NLS-1$
-            "PackageDeclaration", //$NON-NLS-1$
-            "TypeDeclaration", //$NON-NLS-1$
-            "GenericMethodDeclaration", //$NON-NLS-1$
-            "ClassBodyDeclaration", //$NON-NLS-1$
-            "Expression", //$NON-NLS-1$
-            "Type", //$NON-NLS-1$
-            "PrimitiveType", //$NON-NLS-1$
-            "ReferenceType", //$NON-NLS-1$
-            "ClassOrInterfaceType", //$NON-NLS-1$
-            "ArrayType", //$NON-NLS-1$
-            "Name", //$NON-NLS-1$
-            "Dims", //$NON-NLS-1$
-            "ClassType", //$NON-NLS-1$
-            "SimpleName", //$NON-NLS-1$
-            "Header", //$NON-NLS-1$
-            "ClassHeader", //$NON-NLS-1$
-            "InterfaceHeader", //$NON-NLS-1$
-            "MethodHeader", //$NON-NLS-1$
-            "ConstructorHeader", //$NON-NLS-1$
-            "FormalParameter", //$NON-NLS-1$
-            "ImportDeclarations", //$NON-NLS-1$
-            "TypeDeclarations", //$NON-NLS-1$
-            "PackageDeclarationName", //$NON-NLS-1$
-            "SingleTypeImportDeclarationName", //$NON-NLS-1$
-            "TypeImportOnDemandDeclarationName", //$NON-NLS-1$
-            "Modifiers", //$NON-NLS-1$
-            "Modifier", //$NON-NLS-1$
-            "ClassBody", //$NON-NLS-1$
-            "ClassHeaderName", //$NON-NLS-1$
-            "InterfaceTypeList", //$NON-NLS-1$
-            "InterfaceType", //$NON-NLS-1$
-            "ClassBodyDeclarations", //$NON-NLS-1$
-            "Block", //$NON-NLS-1$
-            "VariableDeclarators", //$NON-NLS-1$
-            "VariableDeclarator", //$NON-NLS-1$
-            "VariableDeclaratorId", //$NON-NLS-1$
-            "VariableInitializer", //$NON-NLS-1$
-            "ArrayInitializer", //$NON-NLS-1$
-            "MethodHeaderName", //$NON-NLS-1$
-            "MethodHeaderParameters", //$NON-NLS-1$
-            "MethodPushModifiersHeaderName", //$NON-NLS-1$
-            "ClassTypeList", //$NON-NLS-1$
-            "ConstructorHeaderName", //$NON-NLS-1$
-            "FormalParameterList", //$NON-NLS-1$
-            "ClassTypeElt", //$NON-NLS-1$
-            "StaticOnly", //$NON-NLS-1$
-            "ExplicitConstructorInvocation",  //$NON-NLS-1$
-            "Primary", //$NON-NLS-1$
-            "InterfaceBody", //$NON-NLS-1$
-            "InterfaceHeaderName", //$NON-NLS-1$
-            "InterfaceMemberDeclarations", //$NON-NLS-1$
-            "InterfaceMemberDeclaration", //$NON-NLS-1$
-            "VariableInitializers", //$NON-NLS-1$
-            "BlockStatement", //$NON-NLS-1$
-            "Statement", //$NON-NLS-1$
-            "LocalVariableDeclaration", //$NON-NLS-1$
-            "StatementWithoutTrailingSubstatement",  //$NON-NLS-1$
-            "StatementNoShortIf",  //$NON-NLS-1$
-            "StatementExpression", //$NON-NLS-1$
-            "PostIncrementExpression", //$NON-NLS-1$
-            "PostDecrementExpression", //$NON-NLS-1$
-            "MethodInvocation", //$NON-NLS-1$
-            "ClassInstanceCreationExpression", //$NON-NLS-1$
-            "SwitchBlock", //$NON-NLS-1$
-            "SwitchBlockStatements", //$NON-NLS-1$
-            "SwitchLabels", //$NON-NLS-1$
-            "SwitchBlockStatement", //$NON-NLS-1$
-            "SwitchLabel", //$NON-NLS-1$
-            "ConstantExpression", //$NON-NLS-1$
-            "StatementExpressionList", //$NON-NLS-1$
-            "OnlySynchronized", //$NON-NLS-1$
-            "Catches", //$NON-NLS-1$
-            "Finally", //$NON-NLS-1$
-            "CatchClause", //$NON-NLS-1$
-            "PushLPAREN", //$NON-NLS-1$
-            "PushRPAREN", //$NON-NLS-1$
-            "PrimaryNoNewArray", //$NON-NLS-1$
-            "ArrayCreationWithArrayInitializer", //$NON-NLS-1$
-            "ClassInstanceCreationExpressionName", //$NON-NLS-1$
-            "ArgumentList", //$NON-NLS-1$
-            "DimWithOrWithOutExprs", //$NON-NLS-1$
-            "DimWithOrWithOutExpr", //$NON-NLS-1$
-            "DimsLoop", //$NON-NLS-1$
-            "OneDimLoop", //$NON-NLS-1$
-            "PostfixExpression", //$NON-NLS-1$
-            "UnaryExpression", //$NON-NLS-1$
-            "UnaryExpressionNotPlusMinus", //$NON-NLS-1$
-            "MultiplicativeExpression", //$NON-NLS-1$
-            "AdditiveExpression", //$NON-NLS-1$
-            "ShiftExpression", //$NON-NLS-1$
-            "RelationalExpression", //$NON-NLS-1$
-            "EqualityExpression", //$NON-NLS-1$
-            "AndExpression", //$NON-NLS-1$
-            "ExclusiveOrExpression", //$NON-NLS-1$
-            "InclusiveOrExpression", //$NON-NLS-1$
-            "ConditionalAndExpression", //$NON-NLS-1$
-            "ConditionalOrExpression", //$NON-NLS-1$
-            "ConditionalExpression", //$NON-NLS-1$
-            "AssignmentExpression", //$NON-NLS-1$
-            "AssignmentOperator",  //$NON-NLS-1$
-	};
+	public static String name[] = null;
+	public static String readableName[] = null;
     
-	public  static short check_table[] = null;
-	public  static char lhs[] =  null;
-	public  static char action[] = lhs;
+	public static short check_table[] = null;
+	public static char lhs[] =  null;
+	public static char base_action[] = lhs;
+	
+	public static char scope_prefix[] = null;
+    public static char scope_suffix[] = null;
+    public static char scope_lhs[] = null;
+    
+    public static byte scope_la[] = null;
+
+    public static char scope_state_set[] = null;
+    public static char scope_rhs[] = null;
+    public static char scope_state[] = null;
+    public static char in_symb[] = null;
+    
 	private final static String FILEPREFIX = "parser"; //$NON-NLS-1$
+	private final static String READABLE_NAMES_FILE = "readableNames"; //$NON-NLS-1$
+	private final static String READABLE_NAMES =
+		"org.eclipse.jdt.internal.compiler.parser." + READABLE_NAMES_FILE; //$NON-NLS-1$
 
 	static {
 		try{
@@ -373,11 +163,11 @@
 	public static final int CurlyBracket = 2;
 	public static final int BracketKinds = 3;
 
-public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals, boolean assertMode) {
+public Parser(ProblemReporter problemReporter, boolean optimizeStringLiterals) {
 		
 	this.problemReporter = problemReporter;
+	this.options = problemReporter.options;
 	this.optimizeStringLiterals = optimizeStringLiterals;
-	this.assertMode = assertMode;
 	this.initializeScanner();
 	astLengthStack = new int[50];
 	expressionLengthStack = new int[30];
@@ -388,6 +178,9 @@
 	realBlockStack = new int[30];
 	identifierPositionStack = new long[30];
 	variablesCounter = new int[30];
+	
+	// javadoc support
+	this.javadocParser = new JavadocParser(this);	
 }
 /**
  *
@@ -412,38 +205,58 @@
 	int searchPosition = length == 0 ? endPosition + 1 : ai.expressions[0].sourceStart;
 	try {
 		//does not work with comments(that contain '{') nor '{' describes as a unicode....		
-		while (scanner.source[--searchPosition] != '{') {
-		}
+		while (scanner.source[--searchPosition] != '{');
 	} catch (IndexOutOfBoundsException ex) {
 		//should never occur (except for strange cases like whose describe above)
 		searchPosition = (length == 0 ? endPosition : ai.expressions[0].sourceStart) - 1;
 	}
 	ai.sourceStart = searchPosition;
 }
-protected static int asi(int state) {
+public static int asi(int state) {
 
-	return asb[original_state(state)];
+	return asb[original_state(state)]; 
 }
 protected void blockReal() {
 	// See consumeLocalVariableDeclarationStatement in case of change: duplicated code
 	// increment the amount of declared variables for this block
 	realBlockStack[realBlockPtr]++;
 }
-private final static void buildFileFor(String filename, String tag, String[] tokens, boolean isShort) throws java.io.IOException {
+private final static void buildFileOfByteFor(String filename, String tag, String[] tokens) throws java.io.IOException {
 
 	//transform the String tokens into chars before dumping then into file
 
 	int i = 0;
 	//read upto the tag
-	while (!tokens[i++].equals(tag)) {}
+	while (!tokens[i++].equals(tag));
 	//read upto the }
+	
+	byte[] bytes = new byte[tokens.length]; //can't be bigger
+	int ic = 0;
+	String token;
+	while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+		int c = Integer.parseInt(token);
+		bytes[ic++] = (byte) c;
+	}
+
+	//resize
+	System.arraycopy(bytes, 0, bytes = new byte[ic], 0, ic);
+
+	buildFileForTable(filename, bytes);
+}
+private final static char[] buildFileOfIntFor(String filename, String tag, String[] tokens) throws java.io.IOException {
+
+	//transform the String tokens into chars before dumping then into file
+
+	int i = 0;
+	//read upto the tag
+	while (!tokens[i++].equals(tag));
+	//read upto the }
+	
 	char[] chars = new char[tokens.length]; //can't be bigger
 	int ic = 0;
 	String token;
 	while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
 		int c = Integer.parseInt(token);
-		if (isShort)
-			c += 32768;
 		chars[ic++] = (char) c;
 	}
 
@@ -451,6 +264,124 @@
 	System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
 
 	buildFileForTable(filename, chars);
+	return chars;
+}
+private final static void buildFileOfShortFor(String filename, String tag, String[] tokens) throws java.io.IOException {
+
+	//transform the String tokens into chars before dumping then into file
+
+	int i = 0;
+	//read upto the tag
+	while (!tokens[i++].equals(tag));
+	//read upto the }
+	
+	char[] chars = new char[tokens.length]; //can't be bigger
+	int ic = 0;
+	String token;
+	while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+		int c = Integer.parseInt(token);
+		chars[ic++] = (char) (c + 32768);
+	}
+
+	//resize
+	System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
+
+	buildFileForTable(filename, chars);
+}
+private final static String[] buildFileForName(String filename, String contents) throws java.io.IOException {
+	String[] result = new String[contents.length()];
+	result[0] = null;
+	int resultCount = 1;
+	
+	StringBuffer buffer = new StringBuffer();
+	
+	int start = contents.indexOf("name[]"); //$NON-NLS-1$
+	start = contents.indexOf('\"', start); 
+	int end = contents.indexOf("};", start); //$NON-NLS-1$
+	
+	contents = contents.substring(start, end);
+	
+	boolean addLineSeparator = false;
+	int tokenStart = -1;
+	StringBuffer currentToken = new StringBuffer();
+	for (int i = 0; i < contents.length(); i++) {
+		char c = contents.charAt(i);
+		if(c == '\"') {
+			if(tokenStart == -1) {
+				tokenStart = i + 1;	
+			} else {
+				if(addLineSeparator) {
+					buffer.append('\n');
+					result[resultCount++] = currentToken.toString();
+					currentToken = new StringBuffer();
+				}
+				String token = contents.substring(tokenStart, i);
+				if(token.equals(ERROR_TOKEN)){
+					token = INVALID_CHARACTER;
+				} else if(token.equals(EOF_TOKEN)) {
+					token = UNEXPECTED_EOF;
+				}
+				buffer.append(token);
+				currentToken.append(token);
+				addLineSeparator = true;
+				tokenStart = -1;
+			}
+		}
+		if(tokenStart == -1 && c == '+'){
+			addLineSeparator = false;
+		}
+	}
+	if(currentToken.length() > 0) {
+		result[resultCount++] = currentToken.toString();
+	}
+	
+	buildFileForTable(filename, buffer.toString().toCharArray());
+	
+	System.arraycopy(result, 0, result = new String[resultCount], 0, resultCount);
+	return result;
+}
+private static void buildFileForReadableName(
+	String file,
+	char[] newLhs,
+	char[] newNonTerminalIndex,
+	String[] newName,
+	String[] tokens) throws java.io.IOException {
+
+	ArrayList entries = new ArrayList();
+	
+	boolean[] alreadyAdded = new boolean[newName.length];
+	
+	for (int i = 0; i < tokens.length; i = i + 2) {
+		int index = newNonTerminalIndex[newLhs[Integer.parseInt(tokens[i])]];
+		StringBuffer buffer = new StringBuffer();
+		if(!alreadyAdded[index]) {
+			alreadyAdded[index] = true;
+			buffer.append(newName[index]);
+			buffer.append('=');
+			buffer.append(tokens[i+1].trim());
+			buffer.append('\n');
+			entries.add(String.valueOf(buffer));
+		}
+	}
+	int i = 1;
+	while(!INVALID_CHARACTER.equals(newName[i])) i++;
+	i++;
+	for (; i < alreadyAdded.length; i++) {
+		if(!alreadyAdded[i]) {
+			System.out.println(newName[i] + " has no readable name"); //$NON-NLS-1$
+		}
+	}
+	Collections.sort(entries);
+	buildFile(file, entries);
+}
+private final static void buildFile(String filename, List listToDump) throws java.io.IOException {
+	BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
+	for (Iterator iterator = listToDump.iterator(); iterator.hasNext(); ) {
+		writer.write(String.valueOf(iterator.next()));
+	}
+	writer.flush();
+	writer.close();
+	System.out.println(filename + " creation complete"); //$NON-NLS-1$
 }
 private final static void buildFileForTable(String filename, char[] chars) throws java.io.IOException {
 
@@ -465,7 +396,13 @@
 	stream.close();
 	System.out.println(filename + " creation complete"); //$NON-NLS-1$
 }
-public final static void buildFilesFromLPG(String dataFilename)	throws java.io.IOException {
+private final static void buildFileForTable(String filename, byte[] bytes) throws java.io.IOException {
+	java.io.FileOutputStream stream = new java.io.FileOutputStream(filename);
+	stream.write(bytes);
+	stream.close();
+	System.out.println(filename + " creation complete"); //$NON-NLS-1$
+}
+public final static void buildFilesFromLPG(String dataFilename, String dataFilename2)	throws java.io.IOException {
 
 	//RUN THIS METHOD TO GENERATE PARSER*.RSC FILES
 
@@ -490,11 +427,46 @@
 	}
 	final String prefix = FILEPREFIX;
 	i = 0;
-	buildFileFor(prefix + (++i) + ".rsc", "lhs", tokens, false); //$NON-NLS-2$ //$NON-NLS-1$
-	buildFileFor(prefix + (++i) + ".rsc", "check_table", tokens, true); //$NON-NLS-2$ //$NON-NLS-1$
-	buildFileFor(prefix + (++i) + ".rsc", "asb", tokens, false); //$NON-NLS-2$ //$NON-NLS-1$
-	buildFileFor(prefix + (++i) + ".rsc", "asr", tokens, false); //$NON-NLS-2$ //$NON-NLS-1$
-	buildFileFor(prefix + (++i) + ".rsc", "symbol_index", tokens, false); //$NON-NLS-2$ //$NON-NLS-1$
+	
+	char[] newLhs = buildFileOfIntFor(prefix + (++i) + ".rsc", "lhs", tokens); //$NON-NLS-1$ //$NON-NLS-2$
+	buildFileOfShortFor(prefix + (++i) + ".rsc", "check_table", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "asb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "asr", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "nasb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "nasr", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "terminal_index", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	char[] newNonTerminalIndex = buildFileOfIntFor(prefix + (++i) + ".rsc", "non_terminal_index", tokens); //$NON-NLS-1$ //$NON-NLS-2$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "term_action", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_prefix", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_suffix", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_lhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_state_set", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_state", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfIntFor(prefix + (++i) + ".rsc", "in_symb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	
+	buildFileOfByteFor(prefix + (++i) + ".rsc", "rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfByteFor(prefix + (++i) + ".rsc", "term_check", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	buildFileOfByteFor(prefix + (++i) + ".rsc", "scope_la", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+	
+	String[] newName = buildFileForName(prefix + (++i) + ".rsc", new String(contents)); //$NON-NLS-1$
+	
+	contents = new char[] {};
+	try {
+		contents = Util.getFileCharContent(new File(dataFilename2), null);
+	} catch (IOException ex) {
+		System.out.println(Util.bind("parser.incorrectPath")); //$NON-NLS-1$
+		return;
+	}
+	st = new java.util.StringTokenizer(new String(contents), "\t\n\r=");  //$NON-NLS-1$
+	tokens = new String[st.countTokens()];
+	i = 0;
+	while (st.hasMoreTokens()) {
+		tokens[i++] = st.nextToken();
+	}
+	buildFileForReadableName(READABLE_NAMES_FILE+".properties", newLhs, newNonTerminalIndex, newName, tokens);//$NON-NLS-1$
+	
 	System.out.println(Util.bind("parser.moveFiles")); //$NON-NLS-1$
 }
 /*
@@ -520,6 +492,8 @@
 			compilationUnit.types = null;
 			currentToken = 0;
 			listLength = 0;
+			endPosition = 0;
+			endStatementPosition = 0;
 			return element;
 		}
 		if (compilationUnit.currentPackage != null){
@@ -543,7 +517,7 @@
 						&& field.declarationSourceStart <= scanner.initialPosition
 						&& scanner.initialPosition <= field.declarationSourceEnd
 						&& scanner.eofPosition <= field.declarationSourceEnd+1){
-						element = new RecoveredInitializer((Initializer) field, null, 1, this);
+						element = new RecoveredInitializer(field, null, 1, this);
 						lastCheckPoint = field.declarationSourceStart;					
 						break;
 					}
@@ -555,7 +529,7 @@
 	if (element == null) return element;
 	
 	for(int i = 0; i <= astPtr; i++){
-		AstNode node = astStack[i];
+		ASTNode node = astStack[i];
 		if (node instanceof AbstractMethodDeclaration){
 			AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
 			if (method.declarationSourceEnd == 0){
@@ -571,7 +545,7 @@
 			Initializer initializer = (Initializer) node;
 			if (initializer.declarationSourceEnd == 0){
 				element = element.add(initializer, 1);
-				lastCheckPoint = initializer.bodyStart;				
+				lastCheckPoint = initializer.sourceStart;				
 			} else {
 				element = element.add(initializer, 0);
 				lastCheckPoint = initializer.declarationSourceEnd + 1;
@@ -612,345 +586,9 @@
 	}
 	return element;
 }
-protected static short check(int i) {
+public final static short base_check(int i) {
 	return check_table[i - (NUM_RULES + 1)];
 }
-/*
- * 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 (Character.isJavaIdentifierStart(scanner.currentCharacter)) {
-							scanner.scanIdentifierOrKeyword();
-							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;
-	}
-}
 public final void checkAndSetModifiers(int flag){
 	/*modify the current modifiers buffer.
 	When the startPosition of the modifiers is 0
@@ -966,91 +604,57 @@
 			
 	if (modifiersSourceStart < 0) modifiersSourceStart = scanner.startPosition;
 }
-public void checkAnnotation() {
+public void checkComment() {
 
-	boolean deprecated = false;
-	boolean checkDeprecated = false;
-	int lastAnnotationIndex = -1;
-
-	//since jdk1.2 look only in the last java doc comment...
-	nextComment : for (lastAnnotationIndex = scanner.commentPtr; lastAnnotationIndex >= 0; lastAnnotationIndex--){
-		//look for @deprecated into the first javadoc comment preceeding the declaration
-		int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
-		// javadoc only (non javadoc comment have negative end positions.)
-		if (modifiersSourceStart != -1 && modifiersSourceStart < commentSourceStart) {
-			continue nextComment;
-		}
-		if (scanner.commentStops[lastAnnotationIndex] < 0) {
-			continue nextComment;
-		}
-		checkDeprecated = true;
-		int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1; //stop is one over
-		char[] comment = scanner.source;
-
-		deprecated =
-			checkDeprecation(
-				commentSourceStart,
-				commentSourceEnd,
-				comment);
-		break nextComment;
+	if (this.currentElement != null && this.scanner.commentPtr >= 0) {
+		flushCommentsDefinedPriorTo(endStatementPosition); // discard obsolete comments during recovery
 	}
-	if (deprecated) {
-		checkAndSetModifiers(AccDeprecated);
+	
+	int lastComment = this.scanner.commentPtr;
+	
+	if (this.modifiersSourceStart >= 0) {
+		// eliminate comments located after modifierSourceStart if positionned
+		while (lastComment >= 0 && this.scanner.commentStarts[lastComment] > modifiersSourceStart) lastComment--;
 	}
-	// modify the modifier source start to point at the first comment
-	if (lastAnnotationIndex >= 0 && checkDeprecated) {
-		modifiersSourceStart = scanner.commentStarts[lastAnnotationIndex]; 
+	if (lastComment >= 0) {
+		// consider all remaining leading comments to be part of current declaration
+		this.modifiersSourceStart = scanner.commentStarts[0]; 
+	
+		// check deprecation in last comment if javadoc (can be followed by non-javadoc comments which are simply ignored)	
+		while (lastComment >= 0 && this.scanner.commentStops[lastComment] < 0) lastComment--; // non javadoc comment have negative end positions
+		if (lastComment >= 0) {
+			if (this.javadocParser.checkDeprecation(
+					this.scanner.commentStarts[lastComment],
+					this.scanner.commentStops[lastComment] - 1)) { //stop is one over,
+				checkAndSetModifiers(AccDeprecated);
+			}
+			this.javadoc = this.javadocParser.javadoc;	// null if check javadoc is not activated 
+		}
 	}
 }
-protected boolean checkDeprecation(
-	int commentSourceStart,
-	int commentSourceEnd,
-	char[] comment) {
-
-	boolean deprecated = false;
-	boolean oneStar = false;
-	boolean invalidate = false;
-	for (int[] index = new int[] {commentSourceStart + 3}; index[0] < commentSourceEnd - 10;) {
-		char nextCharacter = getNextCharacter(comment, index);
-		switch(nextCharacter) {
-			case '@' :
-				if ((getNextCharacter(comment, index) == 'd')
-					&& (getNextCharacter(comment, index) == 'e')
-					&& (getNextCharacter(comment, index) == 'p')
-					&& (getNextCharacter(comment, index) == 'r')
-					&& (getNextCharacter(comment, index) == 'e')
-					&& (getNextCharacter(comment, index) == 'c')
-					&& (getNextCharacter(comment, index) == 'a')
-					&& (getNextCharacter(comment, index) == 't')
-					&& (getNextCharacter(comment, index) == 'e')
-					&& (getNextCharacter(comment, index) == 'd')) {
-					// ensure the tag is properly ended: either followed by a space, a tab, line end or asterisk.
-					nextCharacter = getNextCharacter(comment, index);
-					deprecated = !invalidate && (Character.isWhitespace(nextCharacter) || nextCharacter == '*');
-					if (deprecated) {
-						return true;
-					}
-				}
-				break;
-			case '\n' :
-			case '\r' :
-			case '\f' :
-				oneStar = false;
-				invalidate = false;
-				break;
-			case '*' :
-				if (oneStar) {
-					invalidate = true;
-				}
-				oneStar = true;
-				break;
-			default :
-				if (!CharOperation.isWhitespace(nextCharacter)) {
-					invalidate = true;
-				}
+protected void checkNonExternalizedStringLiteral() {
+	if (scanner.wasNonExternalizedStringLiteral) {
+		StringLiteral[] literals = this.scanner.nonNLSStrings;
+		// could not reproduce, but this is the only NPE
+		// added preventive null check see PR 9035
+		if (literals != null) {
+			for (int i = 0, max = literals.length; i < max; i++) {
+				problemReporter().nonExternalizedStringLiteral(literals[i]);
+			}
+		}
+		scanner.wasNonExternalizedStringLiteral = false;
+	}
+}
+protected void checkNonNLSAfterBodyEnd(int declarationEnd){
+	if(scanner.currentPosition - 1 <= declarationEnd) {
+		scanner.eofPosition = declarationEnd < Integer.MAX_VALUE ? declarationEnd + 1 : declarationEnd;
+		try {
+			while(scanner.getNextToken() != TokenNameEOF);
+			checkNonExternalizedStringLiteral();
+		} catch (InvalidInputException e) {
+			// Nothing to do
 		}
 	}
-	return deprecated;
 }
 protected char getNextCharacter(char[] comment, int[] index) {
 	char nextCharacter = comment[index[0]++];
@@ -1105,12 +709,15 @@
 		pushOnExpressionStack(alloc);
 	} else {
 		dispatchDeclarationInto(length);
-		AnonymousLocalTypeDeclaration anonymousTypeDeclaration = (AnonymousLocalTypeDeclaration) astStack[astPtr];
+		TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration)astStack[astPtr];
 		anonymousTypeDeclaration.declarationSourceEnd = endStatementPosition;
 		anonymousTypeDeclaration.bodyEnd = endStatementPosition;
 		if (anonymousTypeDeclaration.allocation != null) {
 			anonymousTypeDeclaration.allocation.sourceEnd = endStatementPosition;
 		}
+		if (length == 0 && !containsComment(anonymousTypeDeclaration.bodyStart, anonymousTypeDeclaration.bodyEnd)) {
+			anonymousTypeDeclaration.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+		}
 		astPtr--;
 		astLengthPtr--;
 		
@@ -1148,7 +755,9 @@
 	}
 	if (currentToken == TokenNameLBRACE){
 		// beginning of an anonymous type
-		AnonymousLocalTypeDeclaration anonymousType = new AnonymousLocalTypeDeclaration(this.compilationUnit.compilationResult);
+		TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult);
+		anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+		anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
 		anonymousType.sourceStart = intStack[intPtr--];
 		anonymousType.sourceEnd = rParenPos; // closing parenthesis
 		lastCheckPoint = anonymousType.bodyStart = scanner.currentPosition;
@@ -1212,6 +821,9 @@
 	pushOnExpressionStack(aae);
 }
 
+protected void consumeArrayCreationHeader() {
+	// nothing to do
+}
 protected void consumeArrayCreationExpressionWithInitializer() {
 	// ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer
 	// ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer
@@ -1364,23 +976,30 @@
 	// Block ::= OpenBlock '{' BlockStatementsopt '}'
 	// simpler action for empty blocks
 
-	int length;
-	if ((length = astLengthStack[astLengthPtr--]) == 0) { // empty block 
-		pushOnAstStack(Block.EmptyWith(intStack[intPtr--], endStatementPosition));
+	int statementsLength = astLengthStack[astLengthPtr--];
+	Block block;
+	if (statementsLength == 0) { // empty block 
+		block = new Block(0);
+		block.sourceStart = intStack[intPtr--];
+		block.sourceEnd = endStatementPosition;
+		// check whether this block at least contains some comment in it
+		if (!containsComment(block.sourceStart, block.sourceEnd)) {
+			block.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+		}
 		realBlockPtr--; // still need to pop the block variable counter
 	} else {
-		Block bk = new Block(realBlockStack[realBlockPtr--]);
-		astPtr -= length;
+		block = new Block(realBlockStack[realBlockPtr--]);
+		astPtr -= statementsLength;
 		System.arraycopy(
 			astStack, 
 			astPtr + 1, 
-			bk.statements = new Statement[length], 
+			block.statements = new Statement[statementsLength], 
 			0, 
-			length); 
-		pushOnAstStack(bk);
-		bk.sourceStart = intStack[intPtr--];
-		bk.sourceEnd = endStatementPosition;
+			statementsLength); 
+		block.sourceStart = intStack[intPtr--];
+		block.sourceEnd = endStatementPosition;
 	}
+	pushOnAstStack(block);
 }
 protected void consumeBlockStatements() {
 	// BlockStatements ::= BlockStatements BlockStatement
@@ -1389,7 +1008,8 @@
 protected void consumeCaseLabel() {
 	// SwitchLabel ::= 'case' ConstantExpression ':'
 	expressionLengthPtr--;
-	pushOnAstStack(new Case(intStack[intPtr--], expressionStack[expressionPtr--]));
+	Expression expression = expressionStack[expressionPtr--];
+	pushOnAstStack(new CaseStatement(expression, expression.sourceEnd, intStack[intPtr--]));
 }
 protected void consumeCastExpression() {
 	// CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN InsideCastExpression UnaryExpression
@@ -1434,11 +1054,23 @@
 	}
 	// current element should be a block due to the presence of the opening brace
 	if (!(currentElement instanceof RecoveredBlock)){
-		return;
+		if(!(currentElement instanceof RecoveredMethod)) {
+			return;
+		}
+		RecoveredMethod rMethod = (RecoveredMethod) currentElement;
+		if(!(rMethod.methodBody == null && rMethod.bracketBalance > 0)) {
+			return;
+		}
 	}
-	// exception argument is already on astStack
-	((RecoveredBlock)currentElement).attach(
-		new RecoveredLocalVariable((Argument)astStack[astPtr--], currentElement, 0)); // insert catch variable in catch block
+	
+	Argument arg = (Argument)astStack[astPtr--];
+	// convert argument to local variable
+	LocalDeclaration localDeclaration = new LocalDeclaration(arg.name, arg.sourceStart, arg.sourceEnd);
+	localDeclaration.type = arg.type;
+	localDeclaration.declarationSourceStart = arg.declarationSourceStart;
+	localDeclaration.declarationSourceEnd = arg.declarationSourceEnd;
+	
+	currentElement = currentElement.add(localDeclaration, 0);
 	lastCheckPoint = scanner.startPosition; // force to restart at this exact position
 	restartRecovery = true; // request to restart from here on
 	lastIgnoredToken = -1;
@@ -1448,16 +1080,20 @@
 	//push an Initializer
 	//optimize the push/pop
 	nestedMethod[nestedType]--;
-	Initializer initializer = new Initializer((Block) astStack[astPtr], 0);
+	Block block = (Block) astStack[astPtr];
+	if (diet) block.bits &= ~ASTNode.UndocumentedEmptyBlockMASK; // clear bit since was diet
+	Initializer initializer = new Initializer(block, 0);
 	intPtr--; // pop sourcestart left on the stack by consumeNestedMethod.
+	initializer.bodyStart = intStack[intPtr--];
 	realBlockPtr--; // pop the block variable counter left on the stack by consumeNestedMethod
 	int javadocCommentStart = intStack[intPtr--];
 	if (javadocCommentStart != -1) {
 		initializer.declarationSourceStart = javadocCommentStart;
 	}
 	astStack[astPtr] = initializer;
+	initializer.bodyEnd = endPosition;
 	initializer.sourceEnd = endStatementPosition;
-	initializer.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition);
+	initializer.declarationSourceEnd = flushCommentsDefinedPriorTo(endStatementPosition);
 }
 protected void consumeClassBodyDeclarations() {
 	// ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration
@@ -1491,7 +1127,7 @@
 	boolean hasConstructor = typeDecl.checkConstructors(this);
 	
 	//add the default constructor when needed (interface don't have it)
-	if (!hasConstructor) {
+	if (!hasConstructor && !typeDecl.isInterface()) {
 		boolean insideFieldInitializer = false;
 		if (diet) {
 			for (int i = nestedType; i > 0; i--){
@@ -1506,11 +1142,15 @@
 
 	//always add <clinit> (will be remove at code gen time if empty)
 	if (this.scanner.containsAssertKeyword) {
-		typeDecl.bits |= AstNode.AddAssertionMASK;
+		typeDecl.bits |= ASTNode.AddAssertionMASK;
 	}
 	typeDecl.addClinit();
 	typeDecl.bodyEnd = endStatementPosition;
-	typeDecl.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition); 
+	if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) {
+		typeDecl.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+	}
+
+	typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(endStatementPosition); 
 }
 protected void consumeClassHeader() {
 	// ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt
@@ -1559,16 +1199,14 @@
 }
 protected void consumeClassHeaderName() {
 	// ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
-	TypeDeclaration typeDecl;
+	TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
 	if (nestedMethod[nestedType] == 0) {
 		if (nestedType != 0) {
-			typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
-		} else {
-			typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+			typeDecl.bits |= ASTNode.IsMemberTypeMASK;
 		}
 	} else {
 		// Record that the block has a declaration for local types
-		typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+		typeDecl.bits |= ASTNode.IsLocalTypeMASK;
 		markEnclosingMemberWithLocalType();
 		blockReal();
 	}
@@ -1602,6 +1240,9 @@
 		currentElement = currentElement.add(typeDecl, 0);
 		lastIgnoredToken = -1;
 	}
+	// javadoc
+	typeDecl.javadoc = this.javadoc;
+	this.javadoc = null;
 }
 protected void consumeClassInstanceCreationExpression() {
 	// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
@@ -1677,6 +1318,7 @@
 
 	// pop the position of the {  (body of the method) pushed in block decl
 	intPtr--;
+	intPtr--;
 
 	//statements
 	realBlockPtr--;
@@ -1730,11 +1372,17 @@
 		cd.constructorCall.sourceStart = cd.sourceStart;
 	}
 
+	if (!diet && (statements == null && constructorCall.isImplicitSuper())) {
+		if (!containsComment(cd.bodyStart, endPosition)) {
+			cd.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+		}
+	}
+
 	//watch for } that could be given as a unicode ! ( u007D is '}' )
 	// store the endPosition (position just before the '}') in case there is
 	// a trailing comment behind the end of the method
 	cd.bodyEnd = endPosition;
-	cd.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition); 
+	cd.declarationSourceEnd = flushCommentsDefinedPriorTo(endStatementPosition); 
 }
 
 protected void consumeInvalidConstructorDeclaration() {
@@ -1743,8 +1391,10 @@
 	ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
 
 	cd.bodyEnd = endPosition; // position just before the trailing semi-colon
-	cd.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition); 
+	cd.declarationSourceEnd = flushCommentsDefinedPriorTo(endStatementPosition); 
 	// report the problem and continue the parsing - narrowing the problem onto the method
+	
+	cd.modifiers |= AccSemicolonBody; // remember semi-colon body
 }
 protected void consumeConstructorHeader() {
 	// ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
@@ -1756,6 +1406,14 @@
 	}
 	// recovery
 	if (currentElement != null){
+		if (currentToken == TokenNameSEMICOLON){ // for invalid constructors
+			method.modifiers |= AccSemicolonBody;			
+			method.declarationSourceEnd = scanner.currentPosition-1;
+			method.bodyEnd = scanner.currentPosition-1;
+			if (currentElement.parseTree() == method && currentElement.parent != null) {
+				currentElement = currentElement.parent;
+			}
+		}		
 		restartRecovery = true; // used to avoid branching back into the regular automaton
 	}		
 }
@@ -1781,6 +1439,9 @@
 	//modifiers
 	cd.declarationSourceStart = intStack[intPtr--];
 	cd.modifiers = intStack[intPtr--];
+	// javadoc
+	cd.javadoc = this.javadoc;
+	this.javadoc = null;
 
 	//highlight starts at the selector starts
 	cd.sourceStart = (int) (selectorSource >>> 32);
@@ -1801,10 +1462,10 @@
 }
 protected void consumeDefaultLabel() {
 	// SwitchLabel ::= 'default' ':'
-	pushOnAstStack(new DefaultCase(intStack[intPtr--], intStack[intPtr--]));
+	pushOnAstStack(new CaseStatement(null, intStack[intPtr--], intStack[intPtr--]));
 }
 protected void consumeDefaultModifiers() {
-	checkAnnotation(); // might update modifiers with AccDeprecated
+	checkComment(); // might update modifiers with AccDeprecated
 	pushOnIntStack(modifiers); // modifiers
 	pushOnIntStack(
 		modifiersSourceStart >= 0 ? modifiersSourceStart : scanner.startPosition); 
@@ -1812,7 +1473,7 @@
 }
 protected void consumeDiet() {
 	// Diet ::= $empty
-	checkAnnotation();
+	checkComment();
 	pushOnIntStack(modifiersSourceStart); // push the start position of a javadoc comment if there is one
 	resetModifiers();
 	jumpOverMethodBody();
@@ -1825,6 +1486,11 @@
 protected void consumeDimWithOrWithOutExpr() {
 	// DimWithOrWithOutExpr ::= '[' ']'
 	pushOnExpressionStack(null);
+	
+	if(currentElement != null && currentToken == TokenNameLBRACE) {
+		ignoreNextOpeningBrace = true;
+		currentElement.bracketBalance++; 
+	}
 }
 protected void consumeDimWithOrWithOutExprs() {
 	// DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr
@@ -1857,6 +1523,8 @@
 protected void consumeEmptyClassMemberDeclaration() {
 	// ClassMemberDeclaration ::= ';'
 	pushOnAstLengthStack(0);
+	problemReporter().superfluousSemicolon(endPosition+1, endStatementPosition);
+	this.scanner.commentPtr = -1;
 }
 protected void consumeEmptyDimsopt() {
 	// Dimsopt ::= $empty
@@ -1902,6 +1570,8 @@
 protected void consumeEmptyTypeDeclaration() {
 	// TypeDeclaration ::= ';' 
 	pushOnAstLengthStack(0);
+	problemReporter().superfluousSemicolon(endPosition+1, endStatementPosition);
+	this.scanner.commentPtr = -1;	
 }
 protected void consumeEmptyTypeDeclarationsopt() {
 	// TypeDeclarationsopt ::= $empty
@@ -1910,10 +1580,10 @@
 protected void consumeEnterAnonymousClassBody() {
 	// EnterAnonymousClassBody ::= $empty
 	QualifiedAllocationExpression alloc;
-	AnonymousLocalTypeDeclaration anonymousType = 
-		new AnonymousLocalTypeDeclaration(this.compilationUnit.compilationResult); 
-	alloc = 
-		anonymousType.allocation = new QualifiedAllocationExpression(anonymousType); 
+	TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult); 
+	anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+	anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
+	alloc = anonymousType.allocation = new QualifiedAllocationExpression(anonymousType); 
 	markEnclosingMemberWithLocalType();
 	pushOnAstStack(anonymousType);
 
@@ -1954,7 +1624,7 @@
 	// EnterVariable ::= $empty
 	// do nothing by default
 
-	char[] name = identifierStack[identifierPtr];
+	char[] identifierName = identifierStack[identifierPtr];
 	long namePosition = identifierPositionStack[identifierPtr];
 	int extendedDimension = intStack[intPtr--];
 	AbstractVariableDeclaration declaration;
@@ -1963,11 +1633,11 @@
 	if (isLocalDeclaration) {
 		// create the local variable declarations
 		declaration = 
-			this.createLocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
+			this.createLocalDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition);
 	} else {
 		// create the field declaration
 		declaration = 
-			this.createFieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition); 
+			this.createFieldDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition); 
 	}
 	
 	identifierPtr--;
@@ -1991,6 +1661,11 @@
 			pushOnAstStack(type);
 			declaration.declarationSourceStart = intStack[intPtr--];
 			declaration.modifiers = intStack[intPtr--];
+			
+			// Store javadoc only on first declaration as it is the same for all ones
+			FieldDeclaration fieldDeclaration = (FieldDeclaration) declaration;
+			fieldDeclaration.javadoc = this.javadoc;
+			this.javadoc = null;
 		}
 	} else {
 		type = (TypeReference) astStack[astPtr - variableIndex];
@@ -2058,6 +1733,12 @@
 			expressionStack[expressionPtr + 1],
 			op);
 }
+protected void consumeExitTryBlock() {
+	//ExitTryBlock ::= $empty
+	if(currentElement != null) {
+		restartRecovery = true;
+	}
+}
 protected void consumeExitVariableWithInitialization() {
 	// ExitVariableWithInitialization ::= $empty
 	// do nothing by default
@@ -2111,7 +1792,7 @@
 		case 2 :
 			ecc.sourceStart = (ecc.qualification = getUnspecifiedReferenceOptimized()).sourceStart;
 			break;
-	};
+	}
 	pushOnAstStack(ecc);
 	ecc.sourceEnd = endPosition;
 }
@@ -2166,8 +1847,9 @@
 		fieldDeclaration.declarationSourceEnd = endStatementPosition; 
 		fieldDeclaration.declarationEnd = endStatementPosition;	// semi-colon included
 	}
+	
 	updateSourceDeclarationParts(variableDeclaratorsCounter);
-	int endPos = flushAnnotationsDefinedPriorTo(endStatementPosition);
+	int endPos = flushCommentsDefinedPriorTo(endStatementPosition);
 	if (endPos != endStatementPosition) {
 		for (int i = 0; i < variableDeclaratorsCounter; i++) {
 			FieldDeclaration fieldDeclaration = (FieldDeclaration) astStack[astPtr - i];
@@ -2219,14 +1901,14 @@
 	*/
 
 	identifierLengthPtr--;
-	char[] name = identifierStack[identifierPtr];
+	char[] identifierName = identifierStack[identifierPtr];
 	long namePositions = identifierPositionStack[identifierPtr--];
 	TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
 	int modifierPositions = intStack[intPtr--];
 	intPtr--;
 	Argument arg = 
 		new Argument(
-			name, 
+			identifierName, 
 			namePositions, 
 			type, 
 			intStack[intPtr + 1] & ~AccDeprecated); // modifiers
@@ -2306,11 +1988,14 @@
 	
 	//always add <clinit> (will be remove at code gen time if empty)
 	if (this.scanner.containsAssertKeyword) {
-		typeDecl.bits |= AstNode.AddAssertionMASK;
+		typeDecl.bits |= ASTNode.AddAssertionMASK;
 	}
 	typeDecl.addClinit();
 	typeDecl.bodyEnd = endStatementPosition;
-	typeDecl.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition); 
+	if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) {
+		typeDecl.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+	}
+	typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(endStatementPosition); 
 }
 protected void consumeInterfaceHeader() {
 	// InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt
@@ -2346,16 +2031,15 @@
 }
 protected void consumeInterfaceHeaderName() {
 	// InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
-	TypeDeclaration typeDecl;
+	TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+
 	if (nestedMethod[nestedType] == 0) {
 		if (nestedType != 0) {
-			typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
-		} else {
-			typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+			typeDecl.bits |= ASTNode.IsMemberTypeMASK;
 		}
 	} else {
 		// Record that the block has a declaration for local types
-		typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+		typeDecl.bits |= ASTNode.IsLocalTypeMASK;
 		markEnclosingMemberWithLocalType();
 		blockReal();
 	}
@@ -2387,6 +2071,9 @@
 		currentElement = currentElement.add(typeDecl, 0);
 		lastIgnoredToken = -1;		
 	}
+	// javadoc
+	typeDecl.javadoc = this.javadoc;
+	this.javadoc = null;
 }
 protected void consumeInterfaceMemberDeclarations() {
 	// InterfaceMemberDeclarations ::= InterfaceMemberDeclarations InterfaceMemberDeclaration
@@ -2445,6 +2132,15 @@
 	// see blockReal in case of change: duplicated code
 	// increment the amount of declared variables for this block
 	realBlockStack[realBlockPtr]++;
+	
+	// update source end to include the semi-colon
+	int variableDeclaratorsCounter = astLengthStack[astLengthPtr];
+	for (int i = variableDeclaratorsCounter - 1; i >= 0; i--) {
+		LocalDeclaration localDeclaration = (LocalDeclaration) astStack[astPtr - i];
+		localDeclaration.declarationSourceEnd = endStatementPosition; 
+		localDeclaration.declarationEnd = endStatementPosition;	// semi-colon included
+	}
+
 }
 protected void consumeMethodBody() {
 	// MethodBody ::= NestedMethod '{' BlockStatementsopt '}' 
@@ -2468,6 +2164,7 @@
 	if (isNotAbstract) {
 		// pop the position of the {  (body of the method) pushed in block decl
 		intPtr--;
+		intPtr--;
 	}
 
 	int explicitDeclarations = 0;
@@ -2475,13 +2172,14 @@
 	if (isNotAbstract) {
 		//statements
 		explicitDeclarations = realBlockStack[realBlockPtr--];
-		if ((length = astLengthStack[astLengthPtr--]) != 0)
+		if ((length = astLengthStack[astLengthPtr--]) != 0) {
 			System.arraycopy(
 				astStack, 
 				(astPtr -= length) + 1, 
 				statements = new Statement[length], 
 				0, 
 				length); 
+		}
 	}
 
 	// now we know that we have a method declaration at the top of the ast stack
@@ -2493,11 +2191,17 @@
 	// is a body when we reduce the method header
 	if (!isNotAbstract) { //remember the fact that the method has a semicolon body
 		md.modifiers |= AccSemicolonBody;
+	} else {
+		if (!diet && statements == null) {
+			if (!containsComment(md.bodyStart, endPosition)) {
+				md.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+			}
+		}
 	}
 	// store the endPosition (position just before the '}') in case there is
 	// a trailing comment behind the end of the method
 	md.bodyEnd = endPosition;
-	md.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition);
+	md.declarationSourceEnd = flushCommentsDefinedPriorTo(endStatementPosition);
 }
 protected void consumeMethodHeader() {
 	// MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
@@ -2513,7 +2217,7 @@
 			method.modifiers |= AccSemicolonBody;			
 			method.declarationSourceEnd = scanner.currentPosition-1;
 			method.bodyEnd = scanner.currentPosition-1;
-			if (currentElement.parent != null){
+			if (currentElement.parseTree() == method && currentElement.parent != null) {
 				currentElement = currentElement.parent;
 			}
 		}		
@@ -2563,6 +2267,9 @@
 	//modifiers
 	md.declarationSourceStart = intStack[intPtr--];
 	md.modifiers = intStack[intPtr--];
+	// javadoc
+	md.javadoc = this.javadoc;
+	this.javadoc = null;
 
 	//highlight starts at selector start
 	md.sourceStart = (int) (selectorSource >>> 32);
@@ -2684,40 +2391,9 @@
 	m.receiver = new SuperReference(m.sourceStart, endPosition);
 	pushOnExpressionStack(m);
 }
-protected void consumeMethodPushModifiersHeaderName() {
-	// MethodPushModifiersHeaderName ::= Modifiers Type PushModifiers 'Identifier' '('
-	// MethodPushModifiersHeaderName ::= Type PushModifiers 'Identifier' '(' 
-	MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
-
-	//name
-	md.selector = identifierStack[identifierPtr];
-	long selectorSource = identifierPositionStack[identifierPtr--];
-	identifierLengthPtr--;
-
-	//modifiers
-	md.declarationSourceStart = intStack[intPtr--];
-	md.modifiers = intStack[intPtr--];
-
-	//type
-	md.returnType = getTypeReference(intStack[intPtr--]);
-
-	//highlight starts at selector start
-	md.sourceStart = (int) (selectorSource >>> 32);
-	pushOnAstStack(md);
-	md.sourceEnd = lParenPos;
-	md.bodyStart = lParenPos + 1;
-	listLength = 0; // initialize listLength before reading parameters/throws
-
-	// recovery
-	if (currentElement != null) {
-		lastCheckPoint = md.bodyStart;
-		currentElement = currentElement.add(md, 0);
-		lastIgnoredToken = -1;		
-	}
-}
 protected void consumeModifiers() {
 	int savedModifiersSourceStart = modifiersSourceStart;	
-	checkAnnotation(); // might update modifiers with AccDeprecated
+	checkComment(); // might update modifiers with AccDeprecated
 	pushOnIntStack(modifiers); // modifiers
 	if (modifiersSourceStart >= savedModifiersSourceStart) {
 		modifiersSourceStart = savedModifiersSourceStart;
@@ -2729,6 +2405,7 @@
 	// NestedMethod ::= $empty
 	jumpOverMethodBody();
 	nestedMethod[nestedType] ++;
+	pushOnIntStack(scanner.currentPosition);
 	consumeOpenBlock();
 }
 protected void consumeNestedType() {
@@ -2776,9 +2453,9 @@
 	stored in the identifier stack. */
 
 	ImportReference impt = compilationUnit.currentPackage;
-	// flush annotations defined prior to import statements
+	// flush comments defined prior to import statements
 	impt.declarationEnd = endStatementPosition;
-	impt.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(impt.declarationSourceEnd);
+	impt.declarationSourceEnd = this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd);
 }
 protected void consumePackageDeclarationName() {
 	// PackageDeclarationName ::= 'package' Name
@@ -2799,7 +2476,7 @@
 		0, 
 		length); 
 	compilationUnit.currentPackage = 
-		impt = new ImportReference(tokens, positions, true); 
+		impt = new ImportReference(tokens, positions, true, AccDefault); 
 
 	if (currentToken == TokenNameSEMICOLON){
 		impt.declarationSourceEnd = scanner.currentPosition - 1;
@@ -2824,9 +2501,9 @@
 	// PrimaryNoNewArray ::=  PushLPAREN Expression PushRPAREN 
 	final Expression parenthesizedExpression = expressionStack[expressionPtr];
 	updateSourcePosition(parenthesizedExpression);
-	int numberOfParenthesis = (parenthesizedExpression.bits & AstNode.ParenthesizedMASK) >> AstNode.ParenthesizedSHIFT;
-	parenthesizedExpression.bits &= ~AstNode.ParenthesizedMASK;
-	parenthesizedExpression.bits |= (numberOfParenthesis + 1) << AstNode.ParenthesizedSHIFT;
+	int numberOfParenthesis = (parenthesizedExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+	parenthesizedExpression.bits &= ~ASTNode.ParenthesizedMASK;
+	parenthesizedExpression.bits |= (numberOfParenthesis + 1) << ASTNode.ParenthesizedSHIFT;
 }
 protected void consumePrimaryNoNewArrayArrayType() {
 	// PrimaryNoNewArray ::= ArrayType '.' 'class'
@@ -2874,12 +2551,6 @@
 	pushOnIntStack(0);
 }
 protected void consumePushModifiers() {
-	if ((modifiers & AccSynchronized) != 0) {
-		 /* remove the starting position of the synchronized keyword
-		  * we don't need it when synchronized is part of the modifiers
-		  */
-		intPtr--;
-	}
 	pushOnIntStack(modifiers); // modifiers
 	pushOnIntStack(modifiersSourceStart);
 	resetModifiers();
@@ -2908,908 +2579,899 @@
 	// PushRPAREN ::= ')'
 	pushOnIntStack(rParenPos);
 }
-
- // This method is part of an automatic generation : do NOT edit-modify  
+// This method is part of an automatic generation : do NOT edit-modify  
 protected void consumeRule(int act) {
-  switch ( act ) {
-    case 29 : // System.out.println("Type ::= PrimitiveType");
-		    consumePrimitiveType();  
-			break ;
- 
-    case 43 : // System.out.println("ReferenceType ::= ClassOrInterfaceType");
-		    consumeReferenceType();   
-			break ;
- 
-    case 52 : // System.out.println("QualifiedName ::= Name DOT SimpleName");
-		    consumeQualifiedName();  
-			break ;
- 
-    case 53 : // System.out.println("CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt");
-		    consumeCompilationUnit();  
-			break ;
- 
-    case 54 : // System.out.println("EnterCompilationUnit ::=");
-		    consumeEnterCompilationUnit();  
-			break ;
- 
-    case 66 : // System.out.println("CatchHeader ::= catch LPAREN FormalParameter RPAREN LBRACE");
-		    consumeCatchHeader();  
-			break ;
- 
-    case 68 : // System.out.println("ImportDeclarations ::= ImportDeclarations ImportDeclaration");
-		    consumeImportDeclarations();  
-			break ;
- 
-    case 70 : // System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration");
-		    consumeTypeDeclarations();  
-			break ;
- 
-    case 71 : // System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON");
-		     consumePackageDeclaration();  
-			break ;
- 
-    case 72 : // System.out.println("PackageDeclarationName ::= package Name");
-		     consumePackageDeclarationName();  
-			break ;
- 
-    case 75 : // System.out.println("SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName SEMICOLON");
-		    consumeSingleTypeImportDeclaration();  
-			break ;
- 
-    case 76 : // System.out.println("SingleTypeImportDeclarationName ::= import Name");
-		    consumeSingleTypeImportDeclarationName();  
-			break ;
- 
-    case 77 : // System.out.println("TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName SEMICOLON");
-		    consumeTypeImportOnDemandDeclaration();  
-			break ;
- 
-    case 78 : // System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT MULTIPLY");
-		    consumeTypeImportOnDemandDeclarationName();  
-			break ;
- 
-     case 81 : // System.out.println("TypeDeclaration ::= SEMICOLON");
-		    consumeEmptyTypeDeclaration();  
-			break ;
- 
-    case 95 : // System.out.println("ClassDeclaration ::= ClassHeader ClassBody");
-		    consumeClassDeclaration();  
-			break ;
- 
-    case 96 : // System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt");
-		    consumeClassHeader();  
-			break ;
- 
-    case 97 : // System.out.println("ClassHeaderName ::= Modifiersopt class Identifier");
-		    consumeClassHeaderName();  
-			break ;
- 
-    case 98 : // System.out.println("ClassHeaderExtends ::= extends ClassType");
-		    consumeClassHeaderExtends();  
-			break ;
- 
-    case 99 : // System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList");
-		    consumeClassHeaderImplements();  
-			break ;
- 
-    case 101 : // System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA InterfaceType");
-		    consumeInterfaceTypeList();  
-			break ;
- 
-    case 102 : // System.out.println("InterfaceType ::= ClassOrInterfaceType");
-		    consumeInterfaceType();  
-			break ;
- 
-    case 105 : // System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration");
-		    consumeClassBodyDeclarations();  
-			break ;
- 
-    case 109 : // System.out.println("ClassBodyDeclaration ::= Diet NestedMethod Block");
-		    consumeClassBodyDeclaration();  
-			break ;
- 
-    case 110 : // System.out.println("Diet ::=");
-		    consumeDiet();  
-			break ;
+	switch ( act ) {
+	case 26 : // System.out.println("Type ::= PrimitiveType");  //$NON-NLS-1$
+		consumePrimitiveType();  
+		break ;
+		
+	case 40 : // System.out.println("ReferenceType ::= ClassOrInterfaceType");  //$NON-NLS-1$
+		consumeReferenceType();   
+		break ;
+		
+	case 49 : // System.out.println("QualifiedName ::= Name DOT SimpleName");  //$NON-NLS-1$
+		consumeQualifiedName();  
+		break ;
+		
+	case 50 : // System.out.println("CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt...");  //$NON-NLS-1$
+		consumeCompilationUnit();  
+		break ;
+		
+	case 51 : // System.out.println("EnterCompilationUnit ::=");  //$NON-NLS-1$
+		consumeEnterCompilationUnit();  
+		break ;
+		
+	case 64 : // System.out.println("CatchHeader ::= catch LPAREN FormalParameter RPAREN LBRACE");  //$NON-NLS-1$
+		consumeCatchHeader();  
+		break ;
+		
+	case 66 : // System.out.println("ImportDeclarations ::= ImportDeclarations ImportDeclaration");  //$NON-NLS-1$
+		consumeImportDeclarations();  
+		break ;
+		
+	case 68 : // System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration");  //$NON-NLS-1$
+		consumeTypeDeclarations();  
+		break ;
+		
+	case 69 : // System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON");  //$NON-NLS-1$
+		consumePackageDeclaration();  
+		break ;
+		
+	case 70 : // System.out.println("PackageDeclarationName ::= package Name");  //$NON-NLS-1$
+		consumePackageDeclarationName();  
+		break ;
+		
+	case 73 : // System.out.println("SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName...");  //$NON-NLS-1$
+		consumeSingleTypeImportDeclaration();  
+		break ;
+		
+	case 74 : // System.out.println("SingleTypeImportDeclarationName ::= import Name");  //$NON-NLS-1$
+		consumeSingleTypeImportDeclarationName();  
+		break ;
+		
+	case 75 : // System.out.println("TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName");  //$NON-NLS-1$
+		consumeTypeImportOnDemandDeclaration();  
+		break ;
+		
+	case 76 : // System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT MULTIPLY");  //$NON-NLS-1$
+		consumeTypeImportOnDemandDeclarationName();  
+		break ;
+		
+	case 79 : // System.out.println("TypeDeclaration ::= SEMICOLON");  //$NON-NLS-1$
+		consumeEmptyTypeDeclaration();  
+		break ;
+		
+	case 93 : // System.out.println("ClassDeclaration ::= ClassHeader ClassBody");  //$NON-NLS-1$
+		consumeClassDeclaration();  
+		break ;
+		
+	case 94 : // System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt...");  //$NON-NLS-1$
+		consumeClassHeader();  
+		break ;
+		
+	case 95 : // System.out.println("ClassHeaderName ::= Modifiersopt class Identifier");  //$NON-NLS-1$
+		consumeClassHeaderName();  
+		break ;
+		
+	case 96 : // System.out.println("ClassHeaderExtends ::= extends ClassType");  //$NON-NLS-1$
+		consumeClassHeaderExtends();  
+		break ;
+		
+	case 97 : // System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList");  //$NON-NLS-1$
+		consumeClassHeaderImplements();  
+		break ;
+		
+	case 99 : // System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA InterfaceType");  //$NON-NLS-1$
+		consumeInterfaceTypeList();  
+		break ;
+		
+	case 100 : // System.out.println("InterfaceType ::= ClassOrInterfaceType");  //$NON-NLS-1$
+		consumeInterfaceType();  
+		break ;
+		
+	case 103 : // System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration");  //$NON-NLS-1$
+		consumeClassBodyDeclarations();  
+		break ;
+		
+	case 107 : // System.out.println("ClassBodyDeclaration ::= Diet NestedMethod Block");  //$NON-NLS-1$
+		consumeClassBodyDeclaration();  
+		break ;
+		
+	case 108 : // System.out.println("Diet ::=");  //$NON-NLS-1$
+		consumeDiet();  
+		break ;
 
-    case 111 : // System.out.println("Initializer ::= Diet NestedMethod Block");
-		    consumeClassBodyDeclaration();  
-			break ;
- 
-    case 118 : // System.out.println("ClassMemberDeclaration ::= SEMICOLON");
-		    consumeEmptyClassMemberDeclaration();  
-			break ;
+	case 109 : // System.out.println("Initializer ::= Diet NestedMethod Block");  //$NON-NLS-1$
+		consumeClassBodyDeclaration();  
+		break ;
+		
+	case 116 : // System.out.println("ClassMemberDeclaration ::= SEMICOLON");  //$NON-NLS-1$
+		consumeEmptyClassMemberDeclaration();  
+		break ;
 
-    case 119 : // System.out.println("FieldDeclaration ::= Modifiersopt Type VariableDeclarators SEMICOLON");
-		    consumeFieldDeclaration();  
-			break ;
- 
-    case 121 : // System.out.println("VariableDeclarators ::= VariableDeclarators COMMA VariableDeclarator");
-		    consumeVariableDeclarators();  
-			break ;
- 
-    case 124 : // System.out.println("EnterVariable ::=");
-		    consumeEnterVariable();  
-			break ;
- 
-    case 125 : // System.out.println("ExitVariableWithInitialization ::=");
-		    consumeExitVariableWithInitialization();  
-			break ;
- 
-    case 126 : // System.out.println("ExitVariableWithoutInitialization ::=");
-		    consumeExitVariableWithoutInitialization();  
-			break ;
- 
-    case 127 : // System.out.println("ForceNoDiet ::=");
-		    consumeForceNoDiet();  
-			break ;
- 
-    case 128 : // System.out.println("RestoreDiet ::=");
-		    consumeRestoreDiet();  
-			break ;
- 
-    case 133 : // System.out.println("MethodDeclaration ::= MethodHeader MethodBody");
-		    // set to true to consume a method with a body
-			consumeMethodDeclaration(true);   
-			break ;
- 
-    case 134 : // System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON");
-		    // set to false to consume a method without body
-			consumeMethodDeclaration(false);  
-			break ;
- 
-    case 135 : // System.out.println("MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims");
-		    consumeMethodHeader();  
-			break ;
- 
-    case 136 : // System.out.println("MethodPushModifiersHeader ::= MethodPushModifiersHeaderName MethodHeaderParameters");
-		    consumeMethodHeader();  
-			break ;
- 
-    case 137 : // System.out.println("MethodPushModifiersHeaderName ::= Modifiers Type PushModifiers Identifier LPAREN");
-		    consumeMethodPushModifiersHeaderName();  
-			break ;
- 
-    case 138 : // System.out.println("MethodPushModifiersHeaderName ::= Type PushModifiers Identifier LPAREN");
-		    consumeMethodPushModifiersHeaderName();  
-			break ;
- 
-    case 139 : // System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN");
-		    consumeMethodHeaderName();  
-			break ;
- 
-    case 140 : // System.out.println("MethodHeaderParameters ::= FormalParameterListopt RPAREN");
-		    consumeMethodHeaderParameters();  
-			break ;
- 
-    case 141 : // System.out.println("MethodHeaderExtendedDims ::= Dimsopt");
-		    consumeMethodHeaderExtendedDims();  
-			break ;
- 
-    case 142 : // System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList");
-		    consumeMethodHeaderThrowsClause();  
-			break ;
- 
-    case 143 : // System.out.println("ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters...");
-		    consumeConstructorHeader();  
-			break ;
- 
-    case 144 : // System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN");
-		    consumeConstructorHeaderName();  
-			break ;
- 
-    case 146 : // System.out.println("FormalParameterList ::= FormalParameterList COMMA FormalParameter");
-		    consumeFormalParameterList();  
-			break ;
- 
-    case 147 : // System.out.println("FormalParameter ::= Modifiersopt Type VariableDeclaratorId");
-		    // the boolean is used to know if the modifiers should be reset
- 	consumeFormalParameter();  
-			break ;
- 
-    case 149 : // System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt");
-		    consumeClassTypeList();  
-			break ;
- 
-    case 150 : // System.out.println("ClassTypeElt ::= ClassType");
-		    consumeClassTypeElt();  
-			break ;
- 
-    case 151 : // System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt RBRACE");
-		    consumeMethodBody();  
-			break ;
- 
-    case 152 : // System.out.println("NestedMethod ::=");
-		    consumeNestedMethod();  
-			break ;
- 
-    case 153 : // System.out.println("StaticInitializer ::= StaticOnly Block");
-		    consumeStaticInitializer();  
-			break ;
+	case 117 : // System.out.println("FieldDeclaration ::= Modifiersopt Type VariableDeclarators SEMICOLON");  //$NON-NLS-1$
+		consumeFieldDeclaration();  
+		break ;
+		
+	case 119 : // System.out.println("VariableDeclarators ::= VariableDeclarators COMMA VariableDeclarator");  //$NON-NLS-1$
+		consumeVariableDeclarators();  
+		break ;
+		
+	case 122 : // System.out.println("EnterVariable ::=");  //$NON-NLS-1$
+		consumeEnterVariable();  
+		break ;
+		
+	case 123 : // System.out.println("ExitVariableWithInitialization ::=");  //$NON-NLS-1$
+		consumeExitVariableWithInitialization();  
+		break ;
+		
+	case 124 : // System.out.println("ExitVariableWithoutInitialization ::=");  //$NON-NLS-1$
+		consumeExitVariableWithoutInitialization();  
+		break ;
+		
+	case 125 : // System.out.println("ForceNoDiet ::=");  //$NON-NLS-1$
+		consumeForceNoDiet();  
+		break ;
+		
+	case 126 : // System.out.println("RestoreDiet ::=");  //$NON-NLS-1$
+		consumeRestoreDiet();  
+		break ;
+		
+	case 131 : // System.out.println("MethodDeclaration ::= MethodHeader MethodBody");  //$NON-NLS-1$
+		// set to true to consume a method with a body
+		consumeMethodDeclaration(true);   
+		break ;
+		
+	case 132 : // System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON");  //$NON-NLS-1$
+		// set to false to consume a method without body
+		consumeMethodDeclaration(false);  
+		break ;
+		
+	case 133 : // System.out.println("MethodHeader ::= MethodHeaderName MethodHeaderParameters...");  //$NON-NLS-1$
+		consumeMethodHeader();  
+		break ;
+		
+	case 134 : // System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN");  //$NON-NLS-1$
+		consumeMethodHeaderName();  
+		break ;
+		
+	case 135 : // System.out.println("MethodHeaderParameters ::= FormalParameterListopt RPAREN");  //$NON-NLS-1$
+		consumeMethodHeaderParameters();  
+		break ;
+		
+	case 136 : // System.out.println("MethodHeaderExtendedDims ::= Dimsopt");  //$NON-NLS-1$
+		consumeMethodHeaderExtendedDims();  
+		break ;
+		
+	case 137 : // System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList");  //$NON-NLS-1$
+		consumeMethodHeaderThrowsClause();  
+		break ;
+		
+	case 138 : // System.out.println("ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters");  //$NON-NLS-1$
+		consumeConstructorHeader();  
+		break ;
+		
+	case 139 : // System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN");  //$NON-NLS-1$
+		consumeConstructorHeaderName();  
+		break ;
+		
+	case 141 : // System.out.println("FormalParameterList ::= FormalParameterList COMMA FormalParameter");  //$NON-NLS-1$
+		consumeFormalParameterList();  
+		break ;
+		
+	case 142 : // System.out.println("FormalParameter ::= Modifiersopt Type VariableDeclaratorId");  //$NON-NLS-1$
+		// the boolean is used to know if the modifiers should be reset
+		consumeFormalParameter();  
+		break ;
+		
+	case 144 : // System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt");  //$NON-NLS-1$
+		consumeClassTypeList();  
+		break ;
+		
+	case 145 : // System.out.println("ClassTypeElt ::= ClassType");  //$NON-NLS-1$
+		consumeClassTypeElt();  
+		break ;
+		
+	case 146 : // System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt RBRACE");  //$NON-NLS-1$
+		consumeMethodBody();  
+		break ;
+		
+	case 147 : // System.out.println("NestedMethod ::=");  //$NON-NLS-1$
+		consumeNestedMethod();  
+		break ;
+		
+	case 148 : // System.out.println("StaticInitializer ::= StaticOnly Block");  //$NON-NLS-1$
+		consumeStaticInitializer();  
+		break ;
 
-    case 154 : // System.out.println("StaticOnly ::= static");
-		    consumeStaticOnly();  
-			break ;
- 
-    case 155 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader ConstructorBody");
-		    consumeConstructorDeclaration() ;  
-			break ;
- 
-    case 156 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON");
-		    consumeInvalidConstructorDeclaration() ;  
-			break ;
- 
-    case 157 : // System.out.println("ConstructorBody ::= NestedMethod LBRACE ConstructorBlockStatementsopt RBRACE");
-		    consumeConstructorBody();  
-			break ;
- 
-    case 160 : // System.out.println("ConstructorBlockStatementsopt ::= ExplicitConstructorInvocation BlockStatements");
-		     consumeConstructorBlockStatements();  
-			break ;
- 
-    case 161 : // System.out.println("ExplicitConstructorInvocation ::= this LPAREN ArgumentListopt RPAREN SEMICOLON");
-		    consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.This);  
-			break ;
- 
-    case 162 : // System.out.println("ExplicitConstructorInvocation ::= super LPAREN ArgumentListopt RPAREN SEMICOLON");
-		    consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.Super);  
-			break ;
- 
-    case 163 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT super LPAREN ArgumentListopt RPAREN");
-		    consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.Super);  
-			break ;
- 
-    case 164 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN ArgumentListopt RPAREN...");
-		    consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.Super);  
-			break ;
- 
-    case 165 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT this LPAREN ArgumentListopt RPAREN...");
-		    consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.This);  
-			break ;
- 
-    case 166 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN ArgumentListopt RPAREN...");
-		    consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.This);  
-			break ;
- 
-    case 167 : // System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody");
-		    consumeInterfaceDeclaration();  
-			break ;
- 
-    case 168 : // System.out.println("InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt");
-		    consumeInterfaceHeader();  
-			break ;
- 
-    case 169 : // System.out.println("InterfaceHeaderName ::= Modifiersopt interface Identifier");
-		    consumeInterfaceHeaderName();  
-			break ;
- 
-    case 171 : // System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList");
-		    consumeInterfaceHeaderExtends();  
-			break ;
- 
-    case 174 : // System.out.println("InterfaceMemberDeclarations ::= InterfaceMemberDeclarations...");
-		    consumeInterfaceMemberDeclarations();  
-			break ;
- 
-    case 175 : // System.out.println("InterfaceMemberDeclaration ::= SEMICOLON");
-		    consumeEmptyInterfaceMemberDeclaration();  
-			break ;
- 
-    case 178 : // System.out.println("InterfaceMemberDeclaration ::= InvalidMethodDeclaration");
-		    ignoreMethodBody();  
-			break ;
- 
-    case 179 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader ConstructorBody");
-		    ignoreInvalidConstructorDeclaration(true);   
-			break ;
- 
-    case 180 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader SEMICOLON");
-		    ignoreInvalidConstructorDeclaration(false);   
-			break ;
- 
-    case 186 : // System.out.println("ArrayInitializer ::= LBRACE ,opt RBRACE");
-		    consumeEmptyArrayInitializer();  
-			break ;
- 
-    case 187 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers RBRACE");
-		    consumeArrayInitializer();  
-			break ;
- 
-    case 188 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers COMMA RBRACE");
-		    consumeArrayInitializer();  
-			break ;
- 
-    case 190 : // System.out.println("VariableInitializers ::= VariableInitializers COMMA VariableInitializer");
-		    consumeVariableInitializers();  
-			break ;
- 
-    case 191 : // System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE");
-		    consumeBlock();  
-			break ;
- 
-    case 192 : // System.out.println("OpenBlock ::=");
-		    consumeOpenBlock() ;  
-			break ;
- 
-    case 194 : // System.out.println("BlockStatements ::= BlockStatements BlockStatement");
-		    consumeBlockStatements() ;  
-			break ;
- 
-    case 198 : // System.out.println("BlockStatement ::= InvalidInterfaceDeclaration");
-		    ignoreInterfaceDeclaration();  
-			break ;
- 
-    case 199 : // System.out.println("LocalVariableDeclarationStatement ::= LocalVariableDeclaration SEMICOLON");
-		    consumeLocalVariableDeclarationStatement();  
-			break ;
- 
-    case 200 : // System.out.println("LocalVariableDeclaration ::= Type PushModifiers VariableDeclarators");
-		    consumeLocalVariableDeclaration();  
-			break ;
- 
-    case 201 : // System.out.println("LocalVariableDeclaration ::= Modifiers Type PushModifiers VariableDeclarators");
-		    consumeLocalVariableDeclaration();  
-			break ;
- 
-    case 202 : // System.out.println("PushModifiers ::=");
-		    consumePushModifiers();  
-			break ;
- 
-    case 226 : // System.out.println("EmptyStatement ::= SEMICOLON");
-		    consumeEmptyStatement();  
-			break ;
- 
-    case 227 : // System.out.println("LabeledStatement ::= Identifier COLON Statement");
-		    consumeStatementLabel() ;  
-			break ;
- 
-    case 228 : // System.out.println("LabeledStatementNoShortIf ::= Identifier COLON StatementNoShortIf");
-		    consumeStatementLabel() ;  
-			break ;
- 
-     case 229 : // System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON");
-		    consumeExpressionStatement();  
-			break ;
- 
-    case 237 : // System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN Statement");
-		    consumeStatementIfNoElse();  
-			break ;
- 
-    case 238 : // System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN StatementNoShortIf else...");
-		    consumeStatementIfWithElse();  
-			break ;
- 
-    case 239 : // System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression RPAREN StatementNoShortIf...");
-		    consumeStatementIfWithElse();  
-			break ;
- 
-    case 240 : // System.out.println("SwitchStatement ::= switch OpenBlock LPAREN Expression RPAREN SwitchBlock");
-		    consumeStatementSwitch() ;  
-			break ;
- 
-    case 241 : // System.out.println("SwitchBlock ::= LBRACE RBRACE");
-		    consumeEmptySwitchBlock() ;  
-			break ;
- 
-    case 244 : // System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements SwitchLabels RBRACE");
-		    consumeSwitchBlock() ;  
-			break ;
- 
-    case 246 : // System.out.println("SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement");
-		    consumeSwitchBlockStatements() ;  
-			break ;
- 
-    case 247 : // System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements");
-		    consumeSwitchBlockStatement() ;  
-			break ;
- 
-    case 249 : // System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel");
-		    consumeSwitchLabels() ;  
-			break ;
- 
-     case 250 : // System.out.println("SwitchLabel ::= case ConstantExpression COLON");
-		    consumeCaseLabel();  
-			break ;
- 
-     case 251 : // System.out.println("SwitchLabel ::= default COLON");
-		    consumeDefaultLabel();  
-			break ;
- 
-    case 252 : // System.out.println("WhileStatement ::= while LPAREN Expression RPAREN Statement");
-		    consumeStatementWhile() ;  
-			break ;
- 
-    case 253 : // System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression RPAREN StatementNoShortIf");
-		    consumeStatementWhile() ;  
-			break ;
- 
-    case 254 : // System.out.println("DoStatement ::= do Statement while LPAREN Expression RPAREN SEMICOLON");
-		    consumeStatementDo() ;  
-			break ;
- 
-    case 255 : // System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON Expressionopt SEMICOLON...");
-		    consumeStatementFor() ;  
-			break ;
- 
-    case 256 : // System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt SEMICOLON Expressionopt SEMICOLON");
-		    consumeStatementFor() ;  
-			break ;
- 
-    case 257 : // System.out.println("ForInit ::= StatementExpressionList");
-		    consumeForInit() ;  
-			break ;
- 
-    case 261 : // System.out.println("StatementExpressionList ::= StatementExpressionList COMMA StatementExpression");
-		    consumeStatementExpressionList() ;  
-			break ;
- 
-    case 262 : // System.out.println("AssertStatement ::= assert Expression SEMICOLON");
-		    consumeSimpleAssertStatement() ;  
-			break ;
- 
-    case 263 : // System.out.println("AssertStatement ::= assert Expression COLON Expression SEMICOLON");
-		    consumeAssertStatement() ;  
-			break ;
- 
-    case 264 : // System.out.println("BreakStatement ::= break SEMICOLON");
-		    consumeStatementBreak() ;  
-			break ;
- 
-    case 265 : // System.out.println("BreakStatement ::= break Identifier SEMICOLON");
-		    consumeStatementBreakWithLabel() ;  
-			break ;
- 
-    case 266 : // System.out.println("ContinueStatement ::= continue SEMICOLON");
-		    consumeStatementContinue() ;  
-			break ;
- 
-    case 267 : // System.out.println("ContinueStatement ::= continue Identifier SEMICOLON");
-		    consumeStatementContinueWithLabel() ;  
-			break ;
- 
-    case 268 : // System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON");
-		    consumeStatementReturn() ;  
-			break ;
- 
-    case 269 : // System.out.println("ThrowStatement ::= throw Expression SEMICOLON");
-		    consumeStatementThrow();
- 
-			break ;
- 
-    case 270 : // System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN Expression RPAREN Block");
-		    consumeStatementSynchronized();  
-			break ;
- 
-    case 271 : // System.out.println("OnlySynchronized ::= synchronized");
-		    consumeOnlySynchronized();  
-			break ;
- 
-    case 272 : // System.out.println("TryStatement ::= try Block Catches");
-		    consumeStatementTry(false);  
-			break ;
- 
-    case 273 : // System.out.println("TryStatement ::= try Block Catchesopt Finally");
-		    consumeStatementTry(true);  
-			break ;
- 
-    case 275 : // System.out.println("Catches ::= Catches CatchClause");
-		    consumeCatches();  
-			break ;
- 
-    case 276 : // System.out.println("CatchClause ::= catch LPAREN FormalParameter RPAREN Block");
-		    consumeStatementCatch() ;  
-			break ;
- 
-    case 278 : // System.out.println("PushLPAREN ::= LPAREN");
-		    consumeLeftParen();  
-			break ;
- 
-    case 279 : // System.out.println("PushRPAREN ::= RPAREN");
-		    consumeRightParen();  
-			break ;
- 
-    case 284 : // System.out.println("PrimaryNoNewArray ::= this");
-		    consumePrimaryNoNewArrayThis();  
-			break ;
- 
-    case 285 : // System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN");
-		    consumePrimaryNoNewArray();  
-			break ;
- 
-    case 288 : // System.out.println("PrimaryNoNewArray ::= Name DOT this");
-		    consumePrimaryNoNewArrayNameThis();  
-			break ;
- 
-    case 289 : // System.out.println("PrimaryNoNewArray ::= Name DOT super");
-		    consumePrimaryNoNewArrayNameSuper();  
-			break ;
- 
-    case 290 : // System.out.println("PrimaryNoNewArray ::= Name DOT class");
-		    consumePrimaryNoNewArrayName();  
-			break ;
- 
-    case 291 : // System.out.println("PrimaryNoNewArray ::= ArrayType DOT class");
-		    consumePrimaryNoNewArrayArrayType();  
-			break ;
- 
-    case 292 : // System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class");
-		    consumePrimaryNoNewArrayPrimitiveType();  
-			break ;
- 
-    case 295 : // System.out.println("AllocationHeader ::= new ClassType LPAREN ArgumentListopt RPAREN");
-		    consumeAllocationHeader();  
-			break ;
- 
-    case 296 : // System.out.println("ClassInstanceCreationExpression ::= new ClassType LPAREN ArgumentListopt RPAREN...");
-		    consumeClassInstanceCreationExpression();  
-			break ;
- 
-    case 297 : // System.out.println("ClassInstanceCreationExpression ::= Primary DOT new SimpleName LPAREN...");
-		    consumeClassInstanceCreationExpressionQualified() ;  
-			break ;
- 
-    case 298 : // System.out.println("ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName new...");
-		    consumeClassInstanceCreationExpressionQualified() ;  
-			break ;
- 
-    case 299 : // System.out.println("ClassInstanceCreationExpressionName ::= Name DOT");
-		    consumeClassInstanceCreationExpressionName() ;  
-			break ;
- 
-    case 300 : // System.out.println("ClassBodyopt ::=");
-		    consumeClassBodyopt();  
-			break ;
- 
-    case 302 : // System.out.println("EnterAnonymousClassBody ::=");
-		    consumeEnterAnonymousClassBody();  
-			break ;
- 
-    case 304 : // System.out.println("ArgumentList ::= ArgumentList COMMA Expression");
-		    consumeArgumentList();  
-			break ;
- 
-    case 305 : // System.out.println("ArrayCreationWithoutArrayInitializer ::= new PrimitiveType DimWithOrWithOutExprs");
-		    consumeArrayCreationExpressionWithoutInitializer();  
-			break ;
- 
-    case 306 : // System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType DimWithOrWithOutExprs...");
-		    consumeArrayCreationExpressionWithInitializer();  
-			break ;
- 
-    case 307 : // System.out.println("ArrayCreationWithoutArrayInitializer ::= new ClassOrInterfaceType...");
-		    consumeArrayCreationExpressionWithoutInitializer();  
-			break ;
- 
-    case 308 : // System.out.println("ArrayCreationWithArrayInitializer ::= new ClassOrInterfaceType...");
-		    consumeArrayCreationExpressionWithInitializer();  
-			break ;
- 
-    case 310 : // System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr");
-		    consumeDimWithOrWithOutExprs();  
-			break ;
- 
-     case 312 : // System.out.println("DimWithOrWithOutExpr ::= LBRACKET RBRACKET");
-		    consumeDimWithOrWithOutExpr();  
-			break ;
- 
-     case 313 : // System.out.println("Dims ::= DimsLoop");
-		    consumeDims();  
-			break ;
- 
-     case 316 : // System.out.println("OneDimLoop ::= LBRACKET RBRACKET");
-		    consumeOneDimLoop();  
-			break ;
- 
-    case 317 : // System.out.println("FieldAccess ::= Primary DOT Identifier");
-		    consumeFieldAccess(false);  
-			break ;
- 
-    case 318 : // System.out.println("FieldAccess ::= super DOT Identifier");
-		    consumeFieldAccess(true);  
-			break ;
- 
-    case 319 : // System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN");
-		    consumeMethodInvocationName();  
-			break ;
- 
-    case 320 : // System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN ArgumentListopt RPAREN");
-		    consumeMethodInvocationPrimary();  
-			break ;
- 
-    case 321 : // System.out.println("MethodInvocation ::= super DOT Identifier LPAREN ArgumentListopt RPAREN");
-		    consumeMethodInvocationSuper();  
-			break ;
- 
-    case 322 : // System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET");
-		    consumeArrayAccess(true);  
-			break ;
- 
-    case 323 : // System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression RBRACKET");
-		    consumeArrayAccess(false);  
-			break ;
-    case 324 : // System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer LBRACKET Expression RBRACKET");
-		    consumeArrayAccess(false);  
-			break ;
- 
-    case 326 : // System.out.println("PostfixExpression ::= Name");
-		    consumePostfixExpression();  
-			break ;
- 
-    case 329 : // System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS");
-		    consumeUnaryExpression(OperatorExpression.PLUS,true);  
-			break ;
- 
-    case 330 : // System.out.println("PostDecrementExpression ::= PostfixExpression MINUS_MINUS");
-		    consumeUnaryExpression(OperatorExpression.MINUS,true);  
-			break ;
- 
-    case 331 : // System.out.println("PushPosition ::=");
-		    consumePushPosition();  
-			break ;
- 
-    case 334 : // System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression");
-		    consumeUnaryExpression(OperatorExpression.PLUS);  
-			break ;
- 
-    case 335 : // System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression");
-		    consumeUnaryExpression(OperatorExpression.MINUS);  
-			break ;
- 
-    case 337 : // System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition UnaryExpression");
-		    consumeUnaryExpression(OperatorExpression.PLUS,false);  
-			break ;
- 
-    case 338 : // System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition UnaryExpression");
-		    consumeUnaryExpression(OperatorExpression.MINUS,false);  
-			break ;
- 
-    case 340 : // System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition UnaryExpression");
-		    consumeUnaryExpression(OperatorExpression.TWIDDLE);  
-			break ;
- 
-    case 341 : // System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition UnaryExpression");
-		    consumeUnaryExpression(OperatorExpression.NOT);  
-			break ;
- 
-    case 343 : // System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN InsideCastExpression");
-		    consumeCastExpression();  
-			break ;
- 
-    case 344 : // System.out.println("CastExpression ::= PushLPAREN Name Dims PushRPAREN InsideCastExpression...");
-		    consumeCastExpression();  
-			break ;
- 
-    case 345 : // System.out.println("CastExpression ::= PushLPAREN Expression PushRPAREN InsideCastExpressionLL1...");
-		    consumeCastExpressionLL1();  
-			break ;
- 
-    case 346 : // System.out.println("InsideCastExpression ::=");
-		    consumeInsideCastExpression();  
-			break ;
- 
-    case 347 : // System.out.println("InsideCastExpressionLL1 ::=");
-		    consumeInsideCastExpressionLL1();  
-			break ;
- 
-    case 349 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression MULTIPLY UnaryExpression");
-		    consumeBinaryExpression(OperatorExpression.MULTIPLY);  
-			break ;
- 
-    case 350 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression DIVIDE UnaryExpression");
-		    consumeBinaryExpression(OperatorExpression.DIVIDE);  
-			break ;
- 
-    case 351 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression REMAINDER UnaryExpression");
-		    consumeBinaryExpression(OperatorExpression.REMAINDER);  
-			break ;
- 
-    case 353 : // System.out.println("AdditiveExpression ::= AdditiveExpression PLUS MultiplicativeExpression");
-		    consumeBinaryExpression(OperatorExpression.PLUS);  
-			break ;
- 
-    case 354 : // System.out.println("AdditiveExpression ::= AdditiveExpression MINUS MultiplicativeExpression");
-		    consumeBinaryExpression(OperatorExpression.MINUS);  
-			break ;
- 
-    case 356 : // System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT AdditiveExpression");
-		    consumeBinaryExpression(OperatorExpression.LEFT_SHIFT);  
-			break ;
- 
-    case 357 : // System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT AdditiveExpression");
-		    consumeBinaryExpression(OperatorExpression.RIGHT_SHIFT);  
-			break ;
- 
-    case 358 : // System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT AdditiveExpression");
-		    consumeBinaryExpression(OperatorExpression.UNSIGNED_RIGHT_SHIFT);  
-			break ;
- 
-    case 360 : // System.out.println("RelationalExpression ::= RelationalExpression LESS ShiftExpression");
-		    consumeBinaryExpression(OperatorExpression.LESS);  
-			break ;
- 
-    case 361 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER ShiftExpression");
-		    consumeBinaryExpression(OperatorExpression.GREATER);  
-			break ;
- 
-    case 362 : // System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL ShiftExpression");
-		    consumeBinaryExpression(OperatorExpression.LESS_EQUAL);  
-			break ;
- 
-    case 363 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER_EQUAL ShiftExpression");
-		    consumeBinaryExpression(OperatorExpression.GREATER_EQUAL);  
-			break ;
- 
-    case 364 : // System.out.println("RelationalExpression ::= RelationalExpression instanceof ReferenceType");
-		    consumeInstanceOfExpression(OperatorExpression.INSTANCEOF);  
-			break ;
- 
-    case 366 : // System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL RelationalExpression");
-		    consumeEqualityExpression(OperatorExpression.EQUAL_EQUAL);  
-			break ;
- 
-    case 367 : // System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL RelationalExpression");
-		    consumeEqualityExpression(OperatorExpression.NOT_EQUAL);  
-			break ;
- 
-    case 369 : // System.out.println("AndExpression ::= AndExpression AND EqualityExpression");
-		    consumeBinaryExpression(OperatorExpression.AND);  
-			break ;
- 
-    case 371 : // System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR AndExpression");
-		    consumeBinaryExpression(OperatorExpression.XOR);  
-			break ;
- 
-    case 373 : // System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR ExclusiveOrExpression");
-		    consumeBinaryExpression(OperatorExpression.OR);  
-			break ;
- 
-    case 375 : // System.out.println("ConditionalAndExpression ::= ConditionalAndExpression AND_AND InclusiveOrExpression");
-		    consumeBinaryExpression(OperatorExpression.AND_AND);  
-			break ;
- 
-    case 377 : // System.out.println("ConditionalOrExpression ::= ConditionalOrExpression OR_OR ConditionalAndExpression");
-		    consumeBinaryExpression(OperatorExpression.OR_OR);  
-			break ;
- 
-    case 379 : // System.out.println("ConditionalExpression ::= ConditionalOrExpression QUESTION Expression COLON...");
-		    consumeConditionalExpression(OperatorExpression.QUESTIONCOLON) ;  
-			break ;
- 
-    case 382 : // System.out.println("Assignment ::= PostfixExpression AssignmentOperator AssignmentExpression");
-		    consumeAssignment();  
-			break ;
- 
-    case 384 : // System.out.println("Assignment ::= InvalidArrayInitializerAssignement");
-		    ignoreExpressionAssignment(); 
-			break ;
- 
-    case 385 : // System.out.println("AssignmentOperator ::= EQUAL");
-		    consumeAssignmentOperator(EQUAL);  
-			break ;
- 
-    case 386 : // System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL");
-		    consumeAssignmentOperator(MULTIPLY);  
-			break ;
- 
-    case 387 : // System.out.println("AssignmentOperator ::= DIVIDE_EQUAL");
-		    consumeAssignmentOperator(DIVIDE);  
-			break ;
- 
-    case 388 : // System.out.println("AssignmentOperator ::= REMAINDER_EQUAL");
-		    consumeAssignmentOperator(REMAINDER);  
-			break ;
- 
-    case 389 : // System.out.println("AssignmentOperator ::= PLUS_EQUAL");
-		    consumeAssignmentOperator(PLUS);  
-			break ;
- 
-    case 390 : // System.out.println("AssignmentOperator ::= MINUS_EQUAL");
-		    consumeAssignmentOperator(MINUS);  
-			break ;
- 
-    case 391 : // System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL");
-		    consumeAssignmentOperator(LEFT_SHIFT);  
-			break ;
- 
-    case 392 : // System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL");
-		    consumeAssignmentOperator(RIGHT_SHIFT);  
-			break ;
- 
-    case 393 : // System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL");
-		    consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);  
-			break ;
- 
-    case 394 : // System.out.println("AssignmentOperator ::= AND_EQUAL");
-		    consumeAssignmentOperator(AND);  
-			break ;
- 
-    case 395 : // System.out.println("AssignmentOperator ::= XOR_EQUAL");
-		    consumeAssignmentOperator(XOR);  
-			break ;
- 
-    case 396 : // System.out.println("AssignmentOperator ::= OR_EQUAL");
-		    consumeAssignmentOperator(OR);  
-			break ;
- 
-    case 403 : // System.out.println("Expressionopt ::=");
-		    consumeEmptyExpression();  
-			break ;
- 
-    case 407 : // System.out.println("ImportDeclarationsopt ::=");
-		    consumeEmptyImportDeclarationsopt();  
-			break ;
- 
-    case 408 : // System.out.println("ImportDeclarationsopt ::= ImportDeclarations");
-		    consumeImportDeclarationsopt();  
-			break ;
- 
-    case 409 : // System.out.println("TypeDeclarationsopt ::=");
-		    consumeEmptyTypeDeclarationsopt();  
-			break ;
- 
-    case 410 : // System.out.println("TypeDeclarationsopt ::= TypeDeclarations");
-		    consumeTypeDeclarationsopt();  
-			break ;
- 
-    case 411 : // System.out.println("ClassBodyDeclarationsopt ::=");
-		    consumeEmptyClassBodyDeclarationsopt();  
-			break ;
- 
-    case 412 : // System.out.println("ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations");
-		    consumeClassBodyDeclarationsopt();  
-			break ;
- 
-     case 413 : // System.out.println("Modifiersopt ::=");
-		    consumeDefaultModifiers();  
-			break ;
- 
-    case 414 : // System.out.println("Modifiersopt ::= Modifiers");
-		    consumeModifiers();  
-			break ;
- 
-    case 415 : // System.out.println("BlockStatementsopt ::=");
-		    consumeEmptyBlockStatementsopt();  
-			break ;
- 
-     case 417 : // System.out.println("Dimsopt ::=");
-		    consumeEmptyDimsopt();  
-			break ;
- 
-     case 419 : // System.out.println("ArgumentListopt ::=");
-		    consumeEmptyArgumentListopt();  
-			break ;
- 
-    case 423 : // System.out.println("FormalParameterListopt ::=");
-		    consumeFormalParameterListopt();  
-			break ;
- 
-     case 427 : // System.out.println("InterfaceMemberDeclarationsopt ::=");
-		    consumeEmptyInterfaceMemberDeclarationsopt();  
-			break ;
- 
-     case 428 : // System.out.println("InterfaceMemberDeclarationsopt ::= NestedType InterfaceMemberDeclarations");
-		    consumeInterfaceMemberDeclarationsopt();  
-			break ;
- 
-    case 429 : // System.out.println("NestedType ::=");
-		    consumeNestedType();  
-			break ;
+	case 149 : // System.out.println("StaticOnly ::= static");  //$NON-NLS-1$
+		consumeStaticOnly();  
+		break ;
+		
+	case 150 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader MethodBody");  //$NON-NLS-1$
+		consumeConstructorDeclaration() ;  
+		break ;
+		
+	case 151 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON");  //$NON-NLS-1$
+		consumeInvalidConstructorDeclaration() ;  
+		break ;
+		
+	case 152 : // System.out.println("ExplicitConstructorInvocation ::= this LPAREN ArgumentListopt RPAREN");  //$NON-NLS-1$
+		consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.This);  
+		break ;
+		
+	case 153 : // System.out.println("ExplicitConstructorInvocation ::= super LPAREN ArgumentListopt...");  //$NON-NLS-1$
+		consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.Super);  
+		break ;
+		
+	case 154 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT super LPAREN...");  //$NON-NLS-1$
+		consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.Super);  
+		break ;
+		
+	case 155 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN...");  //$NON-NLS-1$
+		consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.Super);  
+		break ;
+		
+	case 156 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT this LPAREN...");  //$NON-NLS-1$
+		consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.This);  
+		break ;
+		
+	case 157 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN...");  //$NON-NLS-1$
+		consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.This);  
+		break ;
+		
+	case 158 : // System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody");  //$NON-NLS-1$
+		consumeInterfaceDeclaration();  
+		break ;
+		
+	case 159 : // System.out.println("InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt");  //$NON-NLS-1$
+		consumeInterfaceHeader();  
+		break ;
+		
+	case 160 : // System.out.println("InterfaceHeaderName ::= Modifiersopt interface Identifier");  //$NON-NLS-1$
+		consumeInterfaceHeaderName();  
+		break ;
+		
+	case 162 : // System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList");  //$NON-NLS-1$
+		consumeInterfaceHeaderExtends();  
+		break ;
+		
+	case 165 : // System.out.println("InterfaceMemberDeclarations ::= InterfaceMemberDeclarations...");  //$NON-NLS-1$
+		consumeInterfaceMemberDeclarations();  
+		break ;
+		
+	case 166 : // System.out.println("InterfaceMemberDeclaration ::= SEMICOLON");  //$NON-NLS-1$
+		consumeEmptyInterfaceMemberDeclaration();  
+		break ;
+		
+	case 169 : // System.out.println("InterfaceMemberDeclaration ::= InvalidMethodDeclaration");  //$NON-NLS-1$
+		ignoreMethodBody();  
+		break ;
+		
+	case 170 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader MethodBody");  //$NON-NLS-1$
+		ignoreInvalidConstructorDeclaration(true);   
+		break ;
+		
+	case 171 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader SEMICOLON");  //$NON-NLS-1$
+		ignoreInvalidConstructorDeclaration(false);   
+		break ;
+		
+	case 177 : // System.out.println("ArrayInitializer ::= LBRACE ,opt RBRACE");  //$NON-NLS-1$
+		consumeEmptyArrayInitializer();  
+		break ;
+		
+	case 178 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers RBRACE");  //$NON-NLS-1$
+		consumeArrayInitializer();  
+		break ;
+		
+	case 179 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers COMMA RBRACE");  //$NON-NLS-1$
+		consumeArrayInitializer();  
+		break ;
+		
+	case 181 : // System.out.println("VariableInitializers ::= VariableInitializers COMMA...");  //$NON-NLS-1$
+		consumeVariableInitializers();  
+		break ;
+		
+	case 182 : // System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE");  //$NON-NLS-1$
+		consumeBlock();  
+		break ;
+		
+	case 183 : // System.out.println("OpenBlock ::=");  //$NON-NLS-1$
+		consumeOpenBlock() ;  
+		break ;
+		
+	case 185 : // System.out.println("BlockStatements ::= BlockStatements BlockStatement");  //$NON-NLS-1$
+		consumeBlockStatements() ;  
+		break ;
+		
+	case 189 : // System.out.println("BlockStatement ::= InvalidInterfaceDeclaration");  //$NON-NLS-1$
+		ignoreInterfaceDeclaration();  
+		break ;
+		
+	case 190 : // System.out.println("LocalVariableDeclarationStatement ::= LocalVariableDeclaration...");  //$NON-NLS-1$
+		consumeLocalVariableDeclarationStatement();  
+		break ;
+		
+	case 191 : // System.out.println("LocalVariableDeclaration ::= Type PushModifiers VariableDeclarators");  //$NON-NLS-1$
+		consumeLocalVariableDeclaration();  
+		break ;
+		
+	case 192 : // System.out.println("LocalVariableDeclaration ::= Modifiers Type PushModifiers...");  //$NON-NLS-1$
+		consumeLocalVariableDeclaration();  
+		break ;
+		
+	case 193 : // System.out.println("PushModifiers ::=");  //$NON-NLS-1$
+		consumePushModifiers();  
+		break ;
+		
+	case 217 : // System.out.println("EmptyStatement ::= SEMICOLON");  //$NON-NLS-1$
+		consumeEmptyStatement();  
+		break ;
+		
+	case 218 : // System.out.println("LabeledStatement ::= Identifier COLON Statement");  //$NON-NLS-1$
+		consumeStatementLabel() ;  
+		break ;
+		
+	case 219 : // System.out.println("LabeledStatementNoShortIf ::= Identifier COLON StatementNoShortIf");  //$NON-NLS-1$
+		consumeStatementLabel() ;  
+		break ;
+		
+	case 220 : // System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON");  //$NON-NLS-1$
+		consumeExpressionStatement();  
+		break ;
+		
+	case 229 : // System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN Statement");  //$NON-NLS-1$
+		consumeStatementIfNoElse();  
+		break ;
+		
+	case 230 : // System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN...");  //$NON-NLS-1$
+		consumeStatementIfWithElse();  
+		break ;
+		
+	case 231 : // System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression RPAREN...");  //$NON-NLS-1$
+		consumeStatementIfWithElse();  
+		break ;
+		
+	case 232 : // System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN OpenBlock...");  //$NON-NLS-1$
+		consumeStatementSwitch() ;  
+		break ;
+		
+	case 233 : // System.out.println("SwitchBlock ::= LBRACE RBRACE");  //$NON-NLS-1$
+		consumeEmptySwitchBlock() ;  
+		break ;
+		
+	case 236 : // System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements SwitchLabels RBRACE");  //$NON-NLS-1$
+		consumeSwitchBlock() ;  
+		break ;
+		
+	case 238 : // System.out.println("SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement");  //$NON-NLS-1$
+		consumeSwitchBlockStatements() ;  
+		break ;
+		
+	case 239 : // System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements");  //$NON-NLS-1$
+		consumeSwitchBlockStatement() ;  
+		break ;
+		
+	case 241 : // System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel");  //$NON-NLS-1$
+		consumeSwitchLabels() ;  
+		break ;
+		
+	case 242 : // System.out.println("SwitchLabel ::= case ConstantExpression COLON");  //$NON-NLS-1$
+		consumeCaseLabel();  
+		break ;
+		
+	case 243 : // System.out.println("SwitchLabel ::= default COLON");  //$NON-NLS-1$
+		consumeDefaultLabel();  
+		break ;
+		
+	case 244 : // System.out.println("WhileStatement ::= while LPAREN Expression RPAREN Statement");  //$NON-NLS-1$
+		consumeStatementWhile() ;  
+		break ;
+		
+	case 245 : // System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression RPAREN...");  //$NON-NLS-1$
+		consumeStatementWhile() ;  
+		break ;
+		
+	case 246 : // System.out.println("DoStatement ::= do Statement while LPAREN Expression RPAREN...");  //$NON-NLS-1$
+		consumeStatementDo() ;  
+		break ;
+		
+	case 247 : // System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON Expressionopt...");  //$NON-NLS-1$
+		consumeStatementFor() ;  
+		break ;
+		
+	case 248 : // System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt SEMICOLON...");  //$NON-NLS-1$
+		consumeStatementFor() ;  
+		break ;
+		
+	case 249 : // System.out.println("ForInit ::= StatementExpressionList");  //$NON-NLS-1$
+		consumeForInit() ;  
+		break ;
+		
+	case 253 : // System.out.println("StatementExpressionList ::= StatementExpressionList COMMA...");  //$NON-NLS-1$
+		consumeStatementExpressionList() ;  
+		break ;
+		
+	case 254 : // System.out.println("AssertStatement ::= assert Expression SEMICOLON");  //$NON-NLS-1$
+		consumeSimpleAssertStatement() ;  
+		break ;
+		
+	case 255 : // System.out.println("AssertStatement ::= assert Expression COLON Expression SEMICOLON");  //$NON-NLS-1$
+		consumeAssertStatement() ;  
+		break ;
+		
+	case 256 : // System.out.println("BreakStatement ::= break SEMICOLON");  //$NON-NLS-1$
+		consumeStatementBreak() ;  
+		break ;
+		
+	case 257 : // System.out.println("BreakStatement ::= break Identifier SEMICOLON");  //$NON-NLS-1$
+		consumeStatementBreakWithLabel() ;  
+		break ;
+		
+	case 258 : // System.out.println("ContinueStatement ::= continue SEMICOLON");  //$NON-NLS-1$
+		consumeStatementContinue() ;  
+		break ;
+		
+	case 259 : // System.out.println("ContinueStatement ::= continue Identifier SEMICOLON");  //$NON-NLS-1$
+		consumeStatementContinueWithLabel() ;  
+		break ;
+		
+	case 260 : // System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON");  //$NON-NLS-1$
+		consumeStatementReturn() ;  
+		break ;
+		
+	case 261 : // System.out.println("ThrowStatement ::= throw Expression SEMICOLON");  //$NON-NLS-1$
+		consumeStatementThrow();
+		
+		break ;
+		
+	case 262 : // System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN Expression RPAREN");  //$NON-NLS-1$
+		consumeStatementSynchronized();  
+		break ;
+		
+	case 263 : // System.out.println("OnlySynchronized ::= synchronized");  //$NON-NLS-1$
+		consumeOnlySynchronized();  
+		break ;
+		
+	case 264 : // System.out.println("TryStatement ::= try TryBlock Catches");  //$NON-NLS-1$
+		consumeStatementTry(false);  
+		break ;
+		
+	case 265 : // System.out.println("TryStatement ::= try TryBlock Catchesopt Finally");  //$NON-NLS-1$
+		consumeStatementTry(true);  
+		break ;
+		
+	case 267 : // System.out.println("ExitTryBlock ::=");  //$NON-NLS-1$
+		consumeExitTryBlock();  
+		break ;
+		
+	case 269 : // System.out.println("Catches ::= Catches CatchClause");  //$NON-NLS-1$
+		consumeCatches();  
+		break ;
+		
+	case 270 : // System.out.println("CatchClause ::= catch LPAREN FormalParameter RPAREN Block");  //$NON-NLS-1$
+		consumeStatementCatch() ;  
+		break ;
+		
+	case 272 : // System.out.println("PushLPAREN ::= LPAREN");  //$NON-NLS-1$
+		consumeLeftParen();  
+		break ;
+		
+	case 273 : // System.out.println("PushRPAREN ::= RPAREN");  //$NON-NLS-1$
+		consumeRightParen();  
+		break ;
+		
+	case 278 : // System.out.println("PrimaryNoNewArray ::= this");  //$NON-NLS-1$
+		consumePrimaryNoNewArrayThis();  
+		break ;
+		
+	case 279 : // System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN");  //$NON-NLS-1$
+		consumePrimaryNoNewArray();  
+		break ;
+		
+	case 282 : // System.out.println("PrimaryNoNewArray ::= Name DOT this");  //$NON-NLS-1$
+		consumePrimaryNoNewArrayNameThis();  
+		break ;
+		
+	case 283 : // System.out.println("PrimaryNoNewArray ::= Name DOT super");  //$NON-NLS-1$
+		consumePrimaryNoNewArrayNameSuper();  
+		break ;
+		
+	case 284 : // System.out.println("PrimaryNoNewArray ::= Name DOT class");  //$NON-NLS-1$
+		consumePrimaryNoNewArrayName();  
+		break ;
+		
+	case 285 : // System.out.println("PrimaryNoNewArray ::= ArrayType DOT class");  //$NON-NLS-1$
+		consumePrimaryNoNewArrayArrayType();  
+		break ;
+		
+	case 286 : // System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class");  //$NON-NLS-1$
+		consumePrimaryNoNewArrayPrimitiveType();  
+		break ;
+		
+	case 289 : // System.out.println("AllocationHeader ::= new ClassType LPAREN ArgumentListopt RPAREN");  //$NON-NLS-1$
+		consumeAllocationHeader();  
+		break ;
+		
+	case 290 : // System.out.println("ClassInstanceCreationExpression ::= new ClassType LPAREN...");  //$NON-NLS-1$
+		consumeClassInstanceCreationExpression();  
+		break ;
+		
+	case 291 : // System.out.println("ClassInstanceCreationExpression ::= Primary DOT new SimpleName...");  //$NON-NLS-1$
+		consumeClassInstanceCreationExpressionQualified() ;  
+		break ;
+		
+	case 292 : // System.out.println("ClassInstanceCreationExpression ::=...");  //$NON-NLS-1$
+		consumeClassInstanceCreationExpressionQualified() ;  
+		break ;
+		
+	case 293 : // System.out.println("ClassInstanceCreationExpressionName ::= Name DOT");  //$NON-NLS-1$
+		consumeClassInstanceCreationExpressionName() ;  
+		break ;
+		
+	case 294 : // System.out.println("ClassBodyopt ::=");  //$NON-NLS-1$
+		consumeClassBodyopt();  
+		break ;
+		
+	case 296 : // System.out.println("EnterAnonymousClassBody ::=");  //$NON-NLS-1$
+		consumeEnterAnonymousClassBody();  
+		break ;
+		
+	case 298 : // System.out.println("ArgumentList ::= ArgumentList COMMA Expression");  //$NON-NLS-1$
+		consumeArgumentList();  
+		break ;
+		
+	case 299 : // System.out.println("ArrayCreationHeader ::= new PrimitiveType DimWithOrWithOutExprs");  //$NON-NLS-1$
+		consumeArrayCreationHeader();  
+		break ;
+		
+	case 300 : // System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType...");  //$NON-NLS-1$
+		consumeArrayCreationHeader();  
+		break ;
+		
+	case 301 : // System.out.println("ArrayCreationWithoutArrayInitializer ::= new PrimitiveType...");  //$NON-NLS-1$
+		consumeArrayCreationExpressionWithoutInitializer();  
+		break ;
+		
+	case 302 : // System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType...");  //$NON-NLS-1$
+		consumeArrayCreationExpressionWithInitializer();  
+		break ;
+		
+	case 303 : // System.out.println("ArrayCreationWithoutArrayInitializer ::= new ClassOrInterfaceType...");  //$NON-NLS-1$
+		consumeArrayCreationExpressionWithoutInitializer();  
+		break ;
+		
+	case 304 : // System.out.println("ArrayCreationWithArrayInitializer ::= new ClassOrInterfaceType...");  //$NON-NLS-1$
+		consumeArrayCreationExpressionWithInitializer();  
+		break ;
+		
+	case 306 : // System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr");  //$NON-NLS-1$
+		consumeDimWithOrWithOutExprs();  
+		break ;
+		
+	case 308 : // System.out.println("DimWithOrWithOutExpr ::= LBRACKET RBRACKET");  //$NON-NLS-1$
+		consumeDimWithOrWithOutExpr();  
+		break ;
+		
+	case 309 : // System.out.println("Dims ::= DimsLoop");  //$NON-NLS-1$
+		consumeDims();  
+		break ;
+		
+	case 312 : // System.out.println("OneDimLoop ::= LBRACKET RBRACKET");  //$NON-NLS-1$
+		consumeOneDimLoop();  
+		break ;
+		
+	case 313 : // System.out.println("FieldAccess ::= Primary DOT Identifier");  //$NON-NLS-1$
+		consumeFieldAccess(false);  
+		break ;
+		
+	case 314 : // System.out.println("FieldAccess ::= super DOT Identifier");  //$NON-NLS-1$
+		consumeFieldAccess(true);  
+		break ;
+		
+	case 315 : // System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN");  //$NON-NLS-1$
+		consumeMethodInvocationName();  
+		break ;
+		
+	case 316 : // System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN ArgumentListopt");  //$NON-NLS-1$
+		consumeMethodInvocationPrimary();  
+		break ;
+		
+	case 317 : // System.out.println("MethodInvocation ::= super DOT Identifier LPAREN ArgumentListopt...");  //$NON-NLS-1$
+		consumeMethodInvocationSuper();  
+		break ;
+		
+	case 318 : // System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET");  //$NON-NLS-1$
+		consumeArrayAccess(true);  
+		break ;
+		
+	case 319 : // System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression RBRACKET");  //$NON-NLS-1$
+		consumeArrayAccess(false);  
+		break ;
+		
+	case 320 : // System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer LBRACKET...");  //$NON-NLS-1$
+		consumeArrayAccess(false);  
+		break ;
+		
+	case 322 : // System.out.println("PostfixExpression ::= Name");  //$NON-NLS-1$
+		consumePostfixExpression();  
+		break ;
+		
+	case 325 : // System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS");  //$NON-NLS-1$
+		consumeUnaryExpression(OperatorIds.PLUS,true);  
+		break ;
+		
+	case 326 : // System.out.println("PostDecrementExpression ::= PostfixExpression MINUS_MINUS");  //$NON-NLS-1$
+		consumeUnaryExpression(OperatorIds.MINUS,true);  
+		break ;
+		
+	case 327 : // System.out.println("PushPosition ::=");  //$NON-NLS-1$
+		consumePushPosition();  
+		break ;
+		
+	case 330 : // System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression");  //$NON-NLS-1$
+		consumeUnaryExpression(OperatorIds.PLUS);  
+		break ;
+		
+	case 331 : // System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression");  //$NON-NLS-1$
+		consumeUnaryExpression(OperatorIds.MINUS);  
+		break ;
+		
+	case 333 : // System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition UnaryExpression");  //$NON-NLS-1$
+		consumeUnaryExpression(OperatorIds.PLUS,false);  
+		break ;
+		
+	case 334 : // System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition UnaryExpression");  //$NON-NLS-1$
+		consumeUnaryExpression(OperatorIds.MINUS,false);  
+		break ;
+		
+	case 336 : // System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition UnaryExpression");  //$NON-NLS-1$
+		consumeUnaryExpression(OperatorIds.TWIDDLE);  
+		break ;
+		
+	case 337 : // System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition UnaryExpression");  //$NON-NLS-1$
+		consumeUnaryExpression(OperatorIds.NOT);  
+		break ;
+		
+	case 339 : // System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN...");  //$NON-NLS-1$
+		consumeCastExpression();  
+		break ;
+		
+	case 340 : // System.out.println("CastExpression ::= PushLPAREN Name Dims PushRPAREN...");  //$NON-NLS-1$
+		consumeCastExpression();  
+		break ;
+		
+	case 341 : // System.out.println("CastExpression ::= PushLPAREN Expression PushRPAREN...");  //$NON-NLS-1$
+		consumeCastExpressionLL1();  
+		break ;
+		
+	case 342 : // System.out.println("InsideCastExpression ::=");  //$NON-NLS-1$
+		consumeInsideCastExpression();  
+		break ;
+		
+	case 343 : // System.out.println("InsideCastExpressionLL1 ::=");  //$NON-NLS-1$
+		consumeInsideCastExpressionLL1();  
+		break ;
+		
+	case 345 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression MULTIPLY...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.MULTIPLY);  
+		break ;
+		
+	case 346 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression DIVIDE...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.DIVIDE);  
+		break ;
+		
+	case 347 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression REMAINDER...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.REMAINDER);  
+		break ;
+		
+	case 349 : // System.out.println("AdditiveExpression ::= AdditiveExpression PLUS...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.PLUS);  
+		break ;
+		
+	case 350 : // System.out.println("AdditiveExpression ::= AdditiveExpression MINUS...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.MINUS);  
+		break ;
+		
+	case 352 : // System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT AdditiveExpression");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.LEFT_SHIFT);  
+		break ;
+		
+	case 353 : // System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT AdditiveExpression");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);  
+		break ;
+		
+	case 354 : // System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);  
+		break ;
+		
+	case 356 : // System.out.println("RelationalExpression ::= RelationalExpression LESS ShiftExpression");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.LESS);  
+		break ;
+		
+	case 357 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.GREATER);  
+		break ;
+		
+	case 358 : // System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.LESS_EQUAL);  
+		break ;
+		
+	case 359 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER_EQUAL...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.GREATER_EQUAL);  
+		break ;
+		
+	case 360 : // System.out.println("RelationalExpression ::= RelationalExpression instanceof...");  //$NON-NLS-1$
+		consumeInstanceOfExpression(OperatorIds.INSTANCEOF);  
+		break ;
+		
+	case 362 : // System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL...");  //$NON-NLS-1$
+		consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);  
+		break ;
+		
+	case 363 : // System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL...");  //$NON-NLS-1$
+		consumeEqualityExpression(OperatorIds.NOT_EQUAL);  
+		break ;
+		
+	case 365 : // System.out.println("AndExpression ::= AndExpression AND EqualityExpression");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.AND);  
+		break ;
+		
+	case 367 : // System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR AndExpression");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.XOR);  
+		break ;
+		
+	case 369 : // System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.OR);  
+		break ;
+		
+	case 371 : // System.out.println("ConditionalAndExpression ::= ConditionalAndExpression AND_AND...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.AND_AND);  
+		break ;
+		
+	case 373 : // System.out.println("ConditionalOrExpression ::= ConditionalOrExpression OR_OR...");  //$NON-NLS-1$
+		consumeBinaryExpression(OperatorIds.OR_OR);  
+		break ;
+		
+	case 375 : // System.out.println("ConditionalExpression ::= ConditionalOrExpression QUESTION...");  //$NON-NLS-1$
+		consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;  
+		break ;
+		
+	case 378 : // System.out.println("Assignment ::= PostfixExpression AssignmentOperator...");  //$NON-NLS-1$
+		consumeAssignment();  
+		break ;
+		
+	case 380 : // System.out.println("Assignment ::= InvalidArrayInitializerAssignement");  //$NON-NLS-1$
+		ignoreExpressionAssignment(); 
+		break ;
+		
+	case 381 : // System.out.println("AssignmentOperator ::= EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(EQUAL);  
+		break ;
+		
+	case 382 : // System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(MULTIPLY);  
+		break ;
+		
+	case 383 : // System.out.println("AssignmentOperator ::= DIVIDE_EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(DIVIDE);  
+		break ;
+		
+	case 384 : // System.out.println("AssignmentOperator ::= REMAINDER_EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(REMAINDER);  
+		break ;
+		
+	case 385 : // System.out.println("AssignmentOperator ::= PLUS_EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(PLUS);  
+		break ;
+		
+	case 386 : // System.out.println("AssignmentOperator ::= MINUS_EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(MINUS);  
+		break ;
+		
+	case 387 : // System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(LEFT_SHIFT);  
+		break ;
+		
+	case 388 : // System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(RIGHT_SHIFT);  
+		break ;
+		
+	case 389 : // System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);  
+		break ;
+		
+	case 390 : // System.out.println("AssignmentOperator ::= AND_EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(AND);  
+		break ;
+		
+	case 391 : // System.out.println("AssignmentOperator ::= XOR_EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(XOR);  
+		break ;
+		
+	case 392 : // System.out.println("AssignmentOperator ::= OR_EQUAL");  //$NON-NLS-1$
+		consumeAssignmentOperator(OR);  
+		break ;
+		
+	case 399 : // System.out.println("Expressionopt ::=");  //$NON-NLS-1$
+		consumeEmptyExpression();  
+		break ;
+		
+	case 403 : // System.out.println("ImportDeclarationsopt ::=");  //$NON-NLS-1$
+		consumeEmptyImportDeclarationsopt();  
+		break ;
+		
+	case 404 : // System.out.println("ImportDeclarationsopt ::= ImportDeclarations");  //$NON-NLS-1$
+		consumeImportDeclarationsopt();  
+		break ;
+		
+	case 405 : // System.out.println("TypeDeclarationsopt ::=");  //$NON-NLS-1$
+		consumeEmptyTypeDeclarationsopt();  
+		break ;
+		
+	case 406 : // System.out.println("TypeDeclarationsopt ::= TypeDeclarations");  //$NON-NLS-1$
+		consumeTypeDeclarationsopt();  
+		break ;
+		
+	case 407 : // System.out.println("ClassBodyDeclarationsopt ::=");  //$NON-NLS-1$
+		consumeEmptyClassBodyDeclarationsopt();  
+		break ;
+		
+	case 408 : // System.out.println("ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations");  //$NON-NLS-1$
+		consumeClassBodyDeclarationsopt();  
+		break ;
+		
+	case 409 : // System.out.println("Modifiersopt ::=");  //$NON-NLS-1$
+		consumeDefaultModifiers();  
+		break ;
+		
+	case 410 : // System.out.println("Modifiersopt ::= Modifiers");  //$NON-NLS-1$
+		consumeModifiers();  
+		break ;
+		
+	case 411 : // System.out.println("BlockStatementsopt ::=");  //$NON-NLS-1$
+		consumeEmptyBlockStatementsopt();  
+		break ;
+		
+	case 413 : // System.out.println("Dimsopt ::=");  //$NON-NLS-1$
+		consumeEmptyDimsopt();  
+		break ;
+		
+	case 415 : // System.out.println("ArgumentListopt ::=");  //$NON-NLS-1$
+		consumeEmptyArgumentListopt();  
+		break ;
+		
+	case 419 : // System.out.println("FormalParameterListopt ::=");  //$NON-NLS-1$
+		consumeFormalParameterListopt();  
+		break ;
+		
+	case 423 : // System.out.println("InterfaceMemberDeclarationsopt ::=");  //$NON-NLS-1$
+		consumeEmptyInterfaceMemberDeclarationsopt();  
+		break ;
+		
+	case 424 : // System.out.println("InterfaceMemberDeclarationsopt ::= NestedType...");  //$NON-NLS-1$
+		consumeInterfaceMemberDeclarationsopt();  
+		break ;
+		
+	case 425 : // System.out.println("NestedType ::=");  //$NON-NLS-1$
+		consumeNestedType();  
+		break ;
 
-     case 430 : // System.out.println("ForInitopt ::=");
-		    consumeEmptyForInitopt();  
-			break ;
- 
-     case 432 : // System.out.println("ForUpdateopt ::=");
-		    consumeEmptyForUpdateopt();  
-			break ;
- 
-     case 436 : // System.out.println("Catchesopt ::=");
-		    consumeEmptyCatchesopt();  
-			break ;
- 
+	case 426 : // System.out.println("ForInitopt ::=");  //$NON-NLS-1$
+		consumeEmptyForInitopt();  
+		break ;
+		
+	case 428 : // System.out.println("ForUpdateopt ::=");  //$NON-NLS-1$
+		consumeEmptyForUpdateopt();  
+		break ;
+		
+	case 432 : // System.out.println("Catchesopt ::=");  //$NON-NLS-1$
+		consumeEmptyCatchesopt();  
+		break ;
+		
 	}
 } 
-	
 protected void consumeSimpleAssertStatement() {
 	// AssertStatement ::= 'assert' Expression ';'
 	expressionLengthPtr--;
@@ -3820,10 +3482,10 @@
 	// SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'
 
 	ImportReference impt = (ImportReference) astStack[astPtr];
-	// flush annotations defined prior to import statements
+	// flush comments defined prior to import statements
 	impt.declarationEnd = endStatementPosition;
 	impt.declarationSourceEnd = 
-		this.flushAnnotationsDefinedPriorTo(impt.declarationSourceEnd); 
+		this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd); 
 
 	// recovery
 	if (currentElement != null) {
@@ -3846,7 +3508,7 @@
 	long[] positions = new long[length];
 	System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
 	System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
-	pushOnAstStack(impt = new ImportReference(tokens, positions, false));
+	pushOnAstStack(impt = new ImportReference(tokens, positions, false, AccDefault));
 
 	if (currentToken == TokenNameSEMICOLON){
 		impt.declarationSourceEnd = scanner.currentPosition - 1;
@@ -3869,14 +3531,14 @@
 	// BreakStatement ::= 'break' ';'
 	// break pushs a position on intStack in case there is no label
 
-	pushOnAstStack(new Break(null, intStack[intPtr--], endPosition));
+	pushOnAstStack(new BreakStatement(null, intStack[intPtr--], endPosition));
 }
 protected void consumeStatementBreakWithLabel() {
 	// BreakStatement ::= 'break' Identifier ';'
 	// break pushs a position on intStack in case there is no label
 
 	pushOnAstStack(
-		new Break(
+		new BreakStatement(
 			identifierStack[identifierPtr--],
 			intStack[intPtr--],
 			endPosition)); 
@@ -3899,7 +3561,7 @@
 	// continue pushs a position on intStack in case there is no label
 
 	pushOnAstStack(
-		new Continue(
+		new ContinueStatement(
 			null,
 			intStack[intPtr--],
 			endPosition));
@@ -3909,7 +3571,7 @@
 	// continue pushs a position on intStack in case there is no label
 
 	pushOnAstStack(
-		new Continue(
+		new ContinueStatement(
 			identifierStack[identifierPtr--], 
 			intStack[intPtr--], 
 			endPosition)); 
@@ -3921,26 +3583,14 @@
 	//the 'while' pushes a value on intStack that we need to remove
 	intPtr--;
 
-	//optimize the push/pop
-	Statement action = (Statement) astStack[astPtr];
-	if (action instanceof EmptyStatement
-		&& problemReporter.options.complianceLevel <= CompilerOptions.JDK1_3) {
-		expressionLengthPtr--;
-		astStack[astPtr] = 
-			new DoStatement(
-				expressionStack[expressionPtr--], 
-				null, 
-				intStack[intPtr--], 
-				endPosition); 
-	} else {
-		expressionLengthPtr--;
-		astStack[astPtr] = 
-			new DoStatement(
-				expressionStack[expressionPtr--], 
-				action, 
-				intStack[intPtr--], 
-				endPosition); 
-	}
+	Statement statement = (Statement) astStack[astPtr];
+	expressionLengthPtr--;
+	astStack[astPtr] = 
+		new DoStatement(
+			expressionStack[expressionPtr--], 
+			statement, 
+			intStack[intPtr--], 
+			endPosition); 
 }
 protected void consumeStatementExpressionList() {
 	// StatementExpressionList ::= StatementExpressionList ',' StatementExpression
@@ -3953,16 +3603,11 @@
 	int length;
 	Expression cond = null;
 	Statement[] inits, updates;
-	Statement action;
 	boolean scope = true;
 
 	//statements
-	astLengthPtr--; // we need to consume it
-	action = (Statement) astStack[astPtr--];
-	if (action instanceof EmptyStatement
-		&& problemReporter.options.complianceLevel <= CompilerOptions.JDK1_3) {
-		action = null;
-	}
+	astLengthPtr--;
+	Statement statement = (Statement) astStack[astPtr--];
 
 	//updates are on the expresion stack
 	if ((length = expressionLengthStack[expressionLengthPtr--]) == 0) {
@@ -4004,13 +3649,13 @@
 				0, 
 				length); 
 		}
-	};
+	}
 	pushOnAstStack(
 		new ForStatement(
 			inits, 
 			cond, 
 			updates, 
-			action, 
+			statement, 
 			scope, 
 			intStack[intPtr--], 
 			endStatementPosition)); 
@@ -4021,42 +3666,28 @@
 	//optimize the push/pop
 	expressionLengthPtr--;
 	Statement thenStatement = (Statement) astStack[astPtr];
-	if (thenStatement instanceof EmptyStatement) {
-		astStack[astPtr] = 
-			new IfStatement(
-				expressionStack[expressionPtr--], 
-				Block.None, 
-				intStack[intPtr--], 
-				endStatementPosition); 
-	} else {
-		astStack[astPtr] = 
-			new IfStatement(
-				expressionStack[expressionPtr--], 
-				thenStatement, 
-				intStack[intPtr--], 
-				endStatementPosition); 
-	}
+	astStack[astPtr] = 
+		new IfStatement(
+			expressionStack[expressionPtr--], 
+			thenStatement, 
+			intStack[intPtr--], 
+			endStatementPosition); 
 }
 protected void consumeStatementIfWithElse() {
 	// IfThenElseStatement ::=  'if' '(' Expression ')' StatementNoShortIf 'else' Statement
 	// IfThenElseStatementNoShortIf ::=  'if' '(' Expression ')' StatementNoShortIf 'else' StatementNoShortIf
 
-	astLengthPtr--; // optimized {..., Then, Else } ==> {..., If }
 	expressionLengthPtr--;
+
+	// optimized {..., Then, Else } ==> {..., If }
+	astLengthPtr--;
+
 	//optimize the push/pop
-	Statement elseStatement = (Statement) astStack[astPtr--];
-	Statement thenStatement = (Statement) astStack[astPtr];
-	if (elseStatement instanceof EmptyStatement) {
-		elseStatement = Block.None;
-	}
-	if (thenStatement instanceof EmptyStatement) {
-		thenStatement = Block.None;
-	}
-	astStack[astPtr] = 
+	astStack[--astPtr] = 
 		new IfStatement(
 			expressionStack[expressionPtr--], 
-			thenStatement, 
-			elseStatement, 
+			(Statement) astStack[astPtr], 
+			(Statement) astStack[astPtr + 1], 
 			intStack[intPtr--], 
 			endStatementPosition); 
 }
@@ -4065,23 +3696,13 @@
 	// LabeledStatementNoShortIf ::= 'Identifier' ':' StatementNoShortIf
 
 	//optimize push/pop
-
 	Statement stmt = (Statement) astStack[astPtr];
-	if (stmt instanceof EmptyStatement) {
-		astStack[astPtr] = 
-			new LabeledStatement(
-				identifierStack[identifierPtr], 
-				Block.None, 
-				(int) (identifierPositionStack[identifierPtr--] >>> 32), 
-				endStatementPosition); 
-	} else {
-		astStack[astPtr] = 
-			new LabeledStatement(
-				identifierStack[identifierPtr], 
-				stmt, 
-				(int) (identifierPositionStack[identifierPtr--] >>> 32), 
-				endStatementPosition); 
-	}
+	astStack[astPtr] = 
+		new LabeledStatement(
+			identifierStack[identifierPtr], 
+			stmt, 
+			(int) (identifierPositionStack[identifierPtr--] >>> 32), 
+			endStatementPosition); 
 	identifierLengthPtr--;
 }
 protected void consumeStatementReturn() {
@@ -4107,23 +3728,26 @@
 	//if some declaration occurs.
 
 	int length;
-	SwitchStatement s = new SwitchStatement();
+	SwitchStatement switchStatement = new SwitchStatement();
 	expressionLengthPtr--;
-	s.testExpression = expressionStack[expressionPtr--];
+	switchStatement.expression = expressionStack[expressionPtr--];
 	if ((length = astLengthStack[astLengthPtr--]) != 0) {
 		astPtr -= length;
 		System.arraycopy(
 			astStack, 
 			astPtr + 1, 
-			s.statements = new Statement[length], 
+			switchStatement.statements = new Statement[length], 
 			0, 
 			length); 
 	}
-	s.explicitDeclarations = realBlockStack[realBlockPtr--];
-	pushOnAstStack(s);
-	intPtr--; // because of OpenBlock
-	s.sourceStart = intStack[intPtr--];
-	s.sourceEnd = endStatementPosition;
+	switchStatement.explicitDeclarations = realBlockStack[realBlockPtr--];
+	pushOnAstStack(switchStatement);
+	switchStatement.blockStart = intStack[intPtr--];
+	switchStatement.sourceStart = intStack[intPtr--];
+	switchStatement.sourceEnd = endStatementPosition;
+	if (length == 0 && !containsComment(switchStatement.blockStart, switchStatement.sourceEnd)) {
+		switchStatement.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+	}
 }
 protected void consumeStatementSynchronized() {
 	// SynchronizedStatement ::= OnlySynchronized '(' Expression ')' Block
@@ -4135,7 +3759,7 @@
 		astStack[++astPtr] = 
 			new SynchronizedStatement(
 				expressionStack[expressionPtr--], 
-				Block.None, 
+				null, 
 				intStack[intPtr--], 
 				endStatementPosition); 
 	} else {
@@ -4192,44 +3816,29 @@
 	// WhileStatement ::= 'while' '(' Expression ')' Statement
 	// WhileStatementNoShortIf ::= 'while' '(' Expression ')' StatementNoShortIf
 
-	Statement action = (Statement) astStack[astPtr];
 	expressionLengthPtr--;
-	if (action instanceof Block) {
-		astStack[astPtr] = 
-			new WhileStatement(
-				expressionStack[expressionPtr--], 
-				action, 
-				intStack[intPtr--], 
-				endStatementPosition); 
-	} else {
-		if (action instanceof EmptyStatement
-			&& problemReporter.options.complianceLevel <= CompilerOptions.JDK1_3) {
-			astStack[astPtr] = 
-				new WhileStatement(
-					expressionStack[expressionPtr--], 
-					null, 
-					intStack[intPtr--], 
-					endPosition); 
-		} else {
-			astStack[astPtr] = 
-				new WhileStatement(
-					expressionStack[expressionPtr--], 
-					action, 
-					intStack[intPtr--], 
-					endPosition); 
-		}
-	}
+	Statement statement = (Statement) astStack[astPtr];
+	astStack[astPtr] = 
+		new WhileStatement(
+			expressionStack[expressionPtr--], 
+			statement, 
+			intStack[intPtr--], 
+			endStatementPosition); 
 }
 protected void consumeStaticInitializer() {
 	// StaticInitializer ::=  StaticOnly Block
 	//push an Initializer
 	//optimize the push/pop
-	Initializer initializer = new Initializer((Block) astStack[astPtr], AccStatic);
+	Block block = (Block) astStack[astPtr];
+	if (diet) block.bits &= ~ASTNode.UndocumentedEmptyBlockMASK; // clear bit set since was diet
+	Initializer initializer = new Initializer(block, AccStatic);
 	astStack[astPtr] = initializer;
 	initializer.sourceEnd = endStatementPosition;	
-	initializer.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition);
+	initializer.declarationSourceEnd = flushCommentsDefinedPriorTo(endStatementPosition);
 	nestedMethod[nestedType] --;
 	initializer.declarationSourceStart = intStack[intPtr--];
+	initializer.bodyStart = intStack[intPtr--];
+	initializer.bodyEnd = endPosition;
 	
 	// recovery
 	if (currentElement != null){
@@ -4241,10 +3850,11 @@
 protected void consumeStaticOnly() {
 	// StaticOnly ::= 'static'
 	int savedModifiersSourceStart = modifiersSourceStart;
-	checkAnnotation(); // might update declaration source start
+	checkComment(); // might update declaration source start
 	if (modifiersSourceStart >= savedModifiersSourceStart) {
 		modifiersSourceStart = savedModifiersSourceStart;
 	}
+	pushOnIntStack(scanner.currentPosition);
 	pushOnIntStack(
 		modifiersSourceStart >= 0 ? modifiersSourceStart : scanner.startPosition);
 	jumpOverMethodBody();
@@ -4275,34 +3885,24 @@
 protected void consumeToken(int type) {
 	/* remember the last consumed value */
 	/* try to minimize the number of build values */
-	if (scanner.wasNonExternalizedStringLiteral) {
-		StringLiteral[] literals = this.scanner.nonNLSStrings;
-		// could not reproduce, but this is the only NPE
-		// added preventive null check see PR 9035
-		if (literals != null) {
-			for (int i = 0, max = literals.length; i < max; i++) {
-				problemReporter().nonExternalizedStringLiteral(literals[i]);
-			}
-		}
-		scanner.wasNonExternalizedStringLiteral = false;
-	}
-	// clear the commentPtr of the scanner in case we read something different from a modifier
-	switch(type) {
-		case TokenNameabstract :
-		case TokenNamestrictfp :
-		case TokenNamefinal :
-		case TokenNamenative :
-		case TokenNameprivate :
-		case TokenNameprotected :
-		case TokenNamepublic :
-		case TokenNametransient :
-		case TokenNamevolatile :
-		case TokenNamestatic :
-		case TokenNamesynchronized :
-			break;
-		default:
-			scanner.commentPtr = -1;
-	}
+	checkNonExternalizedStringLiteral();
+//	// clear the commentPtr of the scanner in case we read something different from a modifier
+//	switch(type) {
+//		case TokenNameabstract :
+//		case TokenNamestrictfp :
+//		case TokenNamefinal :
+//		case TokenNamenative :
+//		case TokenNameprivate :
+//		case TokenNameprotected :
+//		case TokenNamepublic :
+//		case TokenNametransient :
+//		case TokenNamevolatile :
+//		case TokenNamestatic :
+//		case TokenNamesynchronized :
+//			break;
+//		default:
+//			scanner.commentPtr = -1;
+//	}
 	//System.out.println(scanner.toStringAction(type));
 	switch (type) {
 		case TokenNameIdentifier :
@@ -4311,14 +3911,14 @@
 				long positions = identifierPositionStack[identifierPtr];
 				problemReporter().useAssertAsAnIdentifier((int) (positions >>> 32), (int) positions);
 			}
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNameinterface :
 			adjustInterfaceModifiers();
 			//'class' is pushing two int (positions) on the stack ==> 'interface' needs to do it too....
-			pushOnIntStack(scanner.startPosition);
 			pushOnIntStack(scanner.currentPosition - 1);			
-			scanner.commentPtr = -1;
+			pushOnIntStack(scanner.startPosition);
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNameabstract :
 			checkAndSetModifiers(AccAbstract);
@@ -4359,7 +3959,7 @@
 			pushIdentifier(-T_void);
 			pushOnIntStack(scanner.currentPosition - 1);				
 			pushOnIntStack(scanner.startPosition);
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 			//push a default dimension while void is not part of the primitive
 			//declaration baseType and so takes the place of a type without getting into
@@ -4368,49 +3968,49 @@
 			pushIdentifier(-T_boolean);
 			pushOnIntStack(scanner.currentPosition - 1);				
 			pushOnIntStack(scanner.startPosition);		
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNamebyte :
 			pushIdentifier(-T_byte);
 			pushOnIntStack(scanner.currentPosition - 1);				
 			pushOnIntStack(scanner.startPosition);					
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNamechar :
 			pushIdentifier(-T_char);
 			pushOnIntStack(scanner.currentPosition - 1);				
 			pushOnIntStack(scanner.startPosition);					
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNamedouble :
 			pushIdentifier(-T_double);
 			pushOnIntStack(scanner.currentPosition - 1);				
 			pushOnIntStack(scanner.startPosition);					
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNamefloat :
 			pushIdentifier(-T_float);
 			pushOnIntStack(scanner.currentPosition - 1);				
 			pushOnIntStack(scanner.startPosition);					
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNameint :
 			pushIdentifier(-T_int);
 			pushOnIntStack(scanner.currentPosition - 1);				
 			pushOnIntStack(scanner.startPosition);					
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNamelong :
 			pushIdentifier(-T_long);
 			pushOnIntStack(scanner.currentPosition - 1);				
 			pushOnIntStack(scanner.startPosition);					
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNameshort :
 			pushIdentifier(-T_short);
 			pushOnIntStack(scanner.currentPosition - 1);				
 			pushOnIntStack(scanner.startPosition);					
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 			//==============================
 		case TokenNameIntegerLiteral :
@@ -4419,7 +4019,7 @@
 					scanner.getCurrentTokenSource(), 
 					scanner.startPosition, 
 					scanner.currentPosition - 1)); 
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNameLongLiteral :
 			pushOnExpressionStack(
@@ -4427,7 +4027,7 @@
 					scanner.getCurrentTokenSource(), 
 					scanner.startPosition, 
 					scanner.currentPosition - 1)); 
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNameFloatingPointLiteral :
 			pushOnExpressionStack(
@@ -4435,7 +4035,7 @@
 					scanner.getCurrentTokenSource(), 
 					scanner.startPosition, 
 					scanner.currentPosition - 1)); 
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNameDoubleLiteral :
 			pushOnExpressionStack(
@@ -4443,7 +4043,7 @@
 					scanner.getCurrentTokenSource(), 
 					scanner.startPosition, 
 					scanner.currentPosition - 1)); 
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNameCharacterLiteral :
 			pushOnExpressionStack(
@@ -4451,7 +4051,7 @@
 					scanner.getCurrentTokenSource(), 
 					scanner.startPosition, 
 					scanner.currentPosition - 1)); 
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNameStringLiteral :
 			StringLiteral stringLiteral = new StringLiteral(
@@ -4459,12 +4059,12 @@
 					scanner.startPosition, 
 					scanner.currentPosition - 1); 
 			pushOnExpressionStack(stringLiteral); 
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNamefalse :
 			pushOnExpressionStack(
 				new FalseLiteral(scanner.startPosition, scanner.currentPosition - 1)); 
-			scanner.commentPtr = -1;
+//			scanner.commentPtr = -1;
 			break;
 		case TokenNametrue :
 			pushOnExpressionStack(
@@ -4484,7 +4084,6 @@
 		case TokenNameimport :
 		case TokenNamepackage :
 		case TokenNamethrow :
-		case TokenNamenew :
 		case TokenNamedo :
 		case TokenNameif :
 		case TokenNamefor :
@@ -4497,6 +4096,11 @@
 		case TokenNamecase :
 			pushOnIntStack(scanner.startPosition);
 			break;
+		case TokenNamenew :
+			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=40954
+			resetModifiers();
+			pushOnIntStack(scanner.startPosition);
+			break;
 		case TokenNameclass :
 			pushOnIntStack(scanner.currentPosition - 1);
 			pushOnIntStack(scanner.startPosition);
@@ -4593,10 +4197,10 @@
 	// TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName ';'
 
 	ImportReference impt = (ImportReference) astStack[astPtr];
-	// flush annotations defined prior to import statements
+	// flush comments defined prior to import statements
 	impt.declarationEnd = endStatementPosition;
 	impt.declarationSourceEnd = 
-		this.flushAnnotationsDefinedPriorTo(impt.declarationSourceEnd); 
+		this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd); 
 
 	// recovery
 	if (currentElement != null) {
@@ -4619,7 +4223,7 @@
 	long[] positions = new long[length];
 	System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
 	System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
-	pushOnAstStack(impt = new ImportReference(tokens, positions, true));
+	pushOnAstStack(impt = new ImportReference(tokens, positions, true, AccDefault));
 
 	if (currentToken == TokenNameSEMICOLON){
 		impt.declarationSourceEnd = scanner.currentPosition - 1;
@@ -4713,15 +4317,51 @@
 	// VariableInitializers ::= VariableInitializers ',' VariableInitializer
 	concatExpressionLists();
 }
+/**
+ * Given the current comment stack, answer whether some comment is available in a certain exclusive range
+ * 
+ * @param sourceStart int
+ * @param sourceEnd int
+ * @return boolean
+ */
+public boolean containsComment(int sourceStart, int sourceEnd) {
+	int iComment = this.scanner.commentPtr;
+	for (; iComment >= 0; iComment--) {
+		int commentStart = this.scanner.commentStarts[iComment];
+		// ignore comments before start
+		if (commentStart < sourceStart) continue;
+		// ignore comments after end
+		if (commentStart > sourceEnd) continue;
+		return true;
+	}
+	return false;
+}
+public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, CompilationResult compilationResult) {
+	MethodDeclaration m = new MethodDeclaration(compilationResult);
+	m.sourceStart = c.sourceStart;
+	m.sourceEnd = c.sourceEnd;
+	m.bodyStart = c.bodyStart;
+	m.bodyEnd = c.bodyEnd;
+	m.declarationSourceEnd = c.declarationSourceEnd;
+	m.declarationSourceStart = c.declarationSourceStart;
+	m.selector = c.selector;
+	m.statements = c.statements;
+	m.modifiers = c.modifiers;
+	m.arguments = c.arguments;
+	m.thrownExceptions = c.thrownExceptions;
+	m.explicitDeclarations = c.explicitDeclarations;
+	m.returnType = null;
+	return m;
+}
 protected TypeReference copyDims(TypeReference typeRef, int dim) {
 	return typeRef.copyDims(dim);
 }
-protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
-	return new FieldDeclaration(null, name, sourceStart, sourceEnd); // TODO: (olivier) why don't we persist the initialization expression?
+protected FieldDeclaration createFieldDeclaration(char[] fieldDeclarationName, int sourceStart, int sourceEnd) {
+	return new FieldDeclaration(fieldDeclarationName, sourceStart, sourceEnd);
 }
 
-protected LocalDeclaration createLocalDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
-	return new LocalDeclaration(null, name, sourceStart, sourceEnd); // TODO: (olivier) why don't we persist the initialization expression?
+protected LocalDeclaration createLocalDeclaration(char[] localDeclarationName, int sourceStart, int sourceEnd) {
+	return new LocalDeclaration(localDeclarationName, sourceStart, sourceEnd);
 }
 
 public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
@@ -4751,7 +4391,7 @@
 	int[] flag = new int[length + 1]; //plus one -- see <HERE>
 	int size1 = 0, size2 = 0, size3 = 0;
 	for (int i = length - 1; i >= 0; i--) {
-		AstNode astNode = astStack[astPtr--];
+		ASTNode astNode = astStack[astPtr--];
 		if (astNode instanceof AbstractMethodDeclaration) {
 			//methods and constructors have been regrouped into one single list
 			flag[i] = 3;
@@ -4775,7 +4415,7 @@
 	if (size2 != 0)
 		typeDecl.methods = new AbstractMethodDeclaration[size2];
 	if (size3 != 0)
-		typeDecl.memberTypes = new MemberTypeDeclaration[size3];
+		typeDecl.memberTypes = new TypeDeclaration[size3];
 
 	//arrays fill up
 	size1 = size2 = size3 = 0;
@@ -4813,7 +4453,7 @@
 						size3 - length2, 
 						length2); 
 					break;
-			};
+			}
 			flagI = flag[start = end];
 		}
 	}
@@ -4847,22 +4487,20 @@
 	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]);
-		}
+	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]);
 	}
 	return compilationUnit;
 }
 /*
- * Flush annotations defined prior to a given positions.
+ * Flush comments defined prior to a given positions.
  *
- * Note: annotations are stacked in syntactical order
+ * Note: comments are stacked in syntactical order
  *
  * Either answer given <position>, or the end position of a comment line 
  * immediately following the <position> (same line)
@@ -4872,13 +4510,13 @@
  * } // end of method foo
  */
  
-public int flushAnnotationsDefinedPriorTo(int position) {
+public int flushCommentsDefinedPriorTo(int position) {
 
-	int lastAnnotationIndex = scanner.commentPtr;
-	if (lastAnnotationIndex < 0) return position; // no comment
+	int lastCommentIndex = scanner.commentPtr;
+	if (lastCommentIndex < 0) return position; // no comment
 
 	// compute the index of the first obsolete comment
-	int index = lastAnnotationIndex;
+	int index = lastCommentIndex;
 	int validCount = 0;
 	while (index >= 0){
 		int commentEnd = scanner.commentStops[index];
@@ -4972,7 +4610,7 @@
 	}
 	return positions;
 }
-	protected void getMethodBodies(CompilationUnitDeclaration unit) {
+	public void getMethodBodies(CompilationUnitDeclaration unit) {
 		//fill the methods bodies in order for the code to be generated
 
 		if (unit == null) return;
@@ -4983,13 +4621,37 @@
 			// if initial diet parse did not work, no need to dig into method bodies.
 		}
 
+		if ((unit.bits & ASTNode.HasAllMethodBodies) != 0)
+			return; //work already done ...
+
 		//real parse of the method....
-		this.scanner.setSource(
-			unit.compilationResult.compilationUnit.getContents());
+		char[] contents = unit.compilationResult.compilationUnit.getContents();
+		this.scanner.setSource(contents);
+		
+		// save existing values to restore them at the end of the parsing process
+		// see bug 47079 for more details
+		int[] oldLineEnds = this.scanner.lineEnds;
+		int oldLinePtr = this.scanner.linePtr;
+
+		final int[] lineSeparatorPositions = unit.compilationResult.lineSeparatorPositions;
+		this.scanner.lineEnds = lineSeparatorPositions;
+		this.scanner.linePtr = lineSeparatorPositions.length - 1;
+
+		if (this.javadocParser.checkJavadoc) {
+			this.javadocParser.scanner.setSource(contents);
+		}
 		if (unit.types != null) {
 			for (int i = unit.types.length; --i >= 0;)
 				unit.types[i].parseMethod(this, unit);
 		}
+		
+		// tag unit has having read bodies
+		unit.bits |= ASTNode.HasAllMethodBodies;
+
+		// this is done to prevent any side effects on the compilation unit result
+		// line separator positions array.
+		this.scanner.lineEnds = oldLineEnds;
+		this.scanner.linePtr = oldLinePtr;
 	}
 protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
 This variable is a type reference and dim will be its dimensions*/
@@ -5039,12 +4701,12 @@
 				ref.sourceEnd = endPosition;
 			}
 		}
-	};
+	}
 	return ref;
 }
 protected Expression getTypeReference(Expression exp) {
 	
-	exp.bits &= ~AstNode.RestrictiveFlagMASK;
+	exp.bits &= ~ASTNode.RestrictiveFlagMASK;
 	exp.bits |= TYPE;
 	return exp;
 }
@@ -5065,11 +4727,14 @@
 		char[][] tokens = new char[length][];
 		identifierPtr -= length;
 		System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+		long[] positions = new long[length];
+		System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
 		ref = 
 			new QualifiedNameReference(tokens, 
+				positions,
 				(int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
 				(int) identifierPositionStack[identifierPtr + length]); // sourceEnd
-	};
+	}
 	return ref;
 }
 protected NameReference getUnspecifiedReferenceOptimized() {
@@ -5088,7 +4753,7 @@
 			new SingleNameReference(
 				identifierStack[identifierPtr], 
 				identifierPositionStack[identifierPtr--]); 
-		ref.bits &= ~AstNode.RestrictiveFlagMASK;
+		ref.bits &= ~ASTNode.RestrictiveFlagMASK;
 		ref.bits |= LOCAL | FIELD;
 		return ref;
 	}
@@ -5102,15 +4767,24 @@
 	char[][] tokens = new char[length][];
 	identifierPtr -= length;
 	System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+	long[] positions = new long[length];
+	System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
 	ref = new QualifiedNameReference(
-			tokens, 
+			tokens,
+			positions, 
 			(int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
 			(int) identifierPositionStack[identifierPtr + length]); // sourceEnd
-	ref.bits &= ~AstNode.RestrictiveFlagMASK;
+	ref.bits &= ~ASTNode.RestrictiveFlagMASK;
 	ref.bits |= LOCAL | FIELD;
 	return ref;
 }
-public void goForBlockStatementsOrMethodHeaders() {
+public void goForBlockStatementsopt() {
+	//tells the scanner to go for block statements opt parsing
+
+	firstToken = TokenNameTWIDDLE;
+	scanner.recordLineSeparator = false;
+}
+public void goForBlockStatementsOrCatchHeader() {
 	//tells the scanner to go for block statements or method headers parsing 
 
 	firstToken = TokenNameMULTIPLY;
@@ -5131,17 +4805,11 @@
 	scanner.recordLineSeparator = true;
 	scanner.currentLine= null;
 }
-public void goForConstructorBody(){
-	//tells the scanner to go for compilation unit parsing
-
-	firstToken = TokenNameEQUAL_EQUAL ;
-	scanner.recordLineSeparator = false;
-}
 public void goForExpression() {
 	//tells the scanner to go for an expression parsing
 
 	firstToken = TokenNameREMAINDER;
-	scanner.recordLineSeparator = false;
+	scanner.recordLineSeparator = true; // recovery goals must record line separators
 }
 public void goForFieldDeclaration(){
 	//tells the scanner to go for field declaration parsing
@@ -5159,7 +4827,7 @@
 	//tells the scanner to go for headers only parsing
 
 	firstToken = TokenNameUNSIGNED_RIGHT_SHIFT;
-	scanner.recordLineSeparator = true;
+	scanner.recordLineSeparator = true; // recovery goals must record line separators
 }
 public void goForImportDeclaration(){
 	//tells the scanner to go for import declaration parsing
@@ -5191,1259 +4859,6 @@
 	firstToken = TokenNamePLUS;
 	scanner.recordLineSeparator = true;
 }
-public final static void grammar(){
-/*
---main options
-%options ACTION, AN=JavaAction.java, GP=java, 
-%options FILE-PREFIX=java, ESCAPE=$, PREFIX=TokenName, OUTPUT-SIZE=125 ,
-%options NOGOTO-DEFAULT, SINGLE-PRODUCTIONS, LALR=1 , TABLE=TIME , 
-
---error recovering options.....
-%options ERROR_MAPS 
-
---grammar understanding options
-%options first follow
-%options TRACE=FULL ,
-%options VERBOSE
-
---Usefull macros helping reading/writing semantic actions
-$Define 
-$putCase 
-/.    case $rule_number : // System.out.println("$rule_text");  
-		   ./
-
-$break
-/. 
-			break ;
-./
-
--- here it starts really ------------------------------------------
-$Terminals
-
-	Identifier
-
-	abstract assert boolean break byte case catch char class 
-	continue default do double else extends false final finally float
-	for if implements import instanceof int
-	interface long native new null package private
-	protected public return short static strictfp super switch
-	synchronized this throw throws transient true try void
-	volatile while
-
-	IntegerLiteral
-	LongLiteral
-	FloatingPointLiteral
-	DoubleLiteral
-	CharacterLiteral
-	StringLiteral
-
-	PLUS_PLUS
-	MINUS_MINUS
-	EQUAL_EQUAL
-	LESS_EQUAL
-	GREATER_EQUAL
-	NOT_EQUAL
-	LEFT_SHIFT
-	RIGHT_SHIFT
-	UNSIGNED_RIGHT_SHIFT
-	PLUS_EQUAL
-	MINUS_EQUAL
-	MULTIPLY_EQUAL
-	DIVIDE_EQUAL
-	AND_EQUAL
-	OR_EQUAL
-	XOR_EQUAL
-	REMAINDER_EQUAL
-	LEFT_SHIFT_EQUAL
-	RIGHT_SHIFT_EQUAL
-	UNSIGNED_RIGHT_SHIFT_EQUAL
-	OR_OR
-	AND_AND
-	PLUS
-	MINUS
-	NOT
-	REMAINDER
-	XOR
-	AND
-	MULTIPLY
-	OR
-	TWIDDLE
-	DIVIDE
-	GREATER
-	LESS
-	LPAREN
-	RPAREN
-	LBRACE
-	RBRACE
-	LBRACKET
-	RBRACKET
-	SEMICOLON
-	QUESTION
-	COLON
-	COMMA
-	DOT
-	EQUAL
-
---    BodyMarker
-
-$Alias
-
-	'++'   ::= PLUS_PLUS
-	'--'   ::= MINUS_MINUS
-	'=='   ::= EQUAL_EQUAL
-	'<='   ::= LESS_EQUAL
-	'>='   ::= GREATER_EQUAL
-	'!='   ::= NOT_EQUAL
-	'<<'   ::= LEFT_SHIFT
-	'>>'   ::= RIGHT_SHIFT
-	'>>>'  ::= UNSIGNED_RIGHT_SHIFT
-	'+='   ::= PLUS_EQUAL
-	'-='   ::= MINUS_EQUAL
-	'*='   ::= MULTIPLY_EQUAL
-	'/='   ::= DIVIDE_EQUAL
-	'&='   ::= AND_EQUAL
-	'|='   ::= OR_EQUAL
-	'^='   ::= XOR_EQUAL
-	'%='   ::= REMAINDER_EQUAL
-	'<<='  ::= LEFT_SHIFT_EQUAL
-	'>>='  ::= RIGHT_SHIFT_EQUAL
-	'>>>=' ::= UNSIGNED_RIGHT_SHIFT_EQUAL
-	'||'   ::= OR_OR
-	'&&'   ::= AND_AND
-
-	'+'    ::= PLUS
-	'-'    ::= MINUS
-	'!'    ::= NOT
-	'%'    ::= REMAINDER
-	'^'    ::= XOR
-	'&'    ::= AND
-	'*'    ::= MULTIPLY
-	'|'    ::= OR
-	'~'    ::= TWIDDLE
-	'/'    ::= DIVIDE
-	'>'    ::= GREATER
-	'<'    ::= LESS
-	'('    ::= LPAREN
-	')'    ::= RPAREN
-	'{'    ::= LBRACE
-	'}'    ::= RBRACE
-	'['    ::= LBRACKET
-	']'    ::= RBRACKET
-	';'    ::= SEMICOLON
-	'?'    ::= QUESTION
-	':'    ::= COLON
-	','    ::= COMMA
-	'.'    ::= DOT
-	'='    ::= EQUAL
-	
-$Start
-	Goal
-
-$Rules
-
-/. // This method is part of an automatic generation : do NOT edit-modify  
-protected void consumeRule(int act) {
-  switch ( act ) {
-./
-
-
-
-Goal ::= '++' CompilationUnit
-Goal ::= '--' MethodBody
-Goal ::= '==' ConstructorBody
--- Initializer
-Goal ::= '>>' StaticInitializer
-Goal ::= '>>' Initializer
--- error recovery
-Goal ::= '>>>' Headers
-Goal ::= '*' BlockStatements
-Goal ::= '*' MethodPushModifiersHeader
-Goal ::= '*' CatchHeader
--- JDOM
-Goal ::= '&&' FieldDeclaration
-Goal ::= '||' ImportDeclaration
-Goal ::= '?' PackageDeclaration
-Goal ::= '+' TypeDeclaration
-Goal ::= '/' GenericMethodDeclaration
-Goal ::= '&' ClassBodyDeclaration
--- code snippet
-Goal ::= '%' Expression
--- completion parser
-Goal ::= '!' ConstructorBlockStatementsopt
-Goal ::= '~' BlockStatementsopt
-
-Literal -> IntegerLiteral
-Literal -> LongLiteral
-Literal -> FloatingPointLiteral
-Literal -> DoubleLiteral
-Literal -> CharacterLiteral
-Literal -> StringLiteral
-Literal -> null
-Literal -> BooleanLiteral
-BooleanLiteral -> true
-BooleanLiteral -> false
-
--------------------------------------------------------------
--------------------------------------------------------------
---a Type results in both a push of its dimension(s) and its name(s).
-
-Type ::= PrimitiveType
- /.$putCase consumePrimitiveType(); $break ./
-Type -> ReferenceType
-
-PrimitiveType -> NumericType
-NumericType -> IntegralType
-NumericType -> FloatingPointType
-
-PrimitiveType -> 'boolean'
-PrimitiveType -> 'void'
-IntegralType -> 'byte'
-IntegralType -> 'short'
-IntegralType -> 'int'
-IntegralType -> 'long'
-IntegralType -> 'char'
-FloatingPointType -> 'float'
-FloatingPointType -> 'double'
-
-ReferenceType ::= ClassOrInterfaceType
-/.$putCase consumeReferenceType();  $break ./
-ReferenceType -> ArrayType -- here a push of dimensions is done, that explains the two previous push 0
-
-ClassOrInterfaceType -> Name
-
---
--- These rules have been rewritten to avoid some conflicts introduced
--- by adding the 1.1 features
---
--- ArrayType ::= PrimitiveType '[' ']'
--- ArrayType ::= Name '[' ']'
--- ArrayType ::= ArrayType '[' ']'
---
-
-ArrayType ::= PrimitiveType Dims
-ArrayType ::= Name Dims
-
-ClassType -> ClassOrInterfaceType
-
-
---------------------------------------------------------------
---------------------------------------------------------------
-
-Name -> SimpleName
-Name -> QualifiedName
-
-SimpleName -> 'Identifier'
-
-QualifiedName ::= Name '.' SimpleName 
-/.$putCase consumeQualifiedName(); $break ./
-
-CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt TypeDeclarationsopt
-/.$putCase consumeCompilationUnit(); $break ./
-
-EnterCompilationUnit ::= $empty
-/.$putCase consumeEnterCompilationUnit(); $break ./
-
-Headers -> Header
-Headers ::= Headers Header
-
-Header -> ImportDeclaration
-Header -> PackageDeclaration
-Header -> ClassHeader
-Header -> InterfaceHeader
-Header -> StaticInitializer
-Header -> MethodHeader
-Header -> ConstructorHeader
-Header -> FieldDeclaration
-Header -> AllocationHeader
-
-CatchHeader ::= 'catch' '(' FormalParameter ')' '{'
-/.$putCase consumeCatchHeader(); $break ./
-
-ImportDeclarations -> ImportDeclaration
-ImportDeclarations ::= ImportDeclarations ImportDeclaration 
-/.$putCase consumeImportDeclarations(); $break ./
-
-TypeDeclarations -> TypeDeclaration
-TypeDeclarations ::= TypeDeclarations TypeDeclaration
-/.$putCase consumeTypeDeclarations(); $break ./
-
-PackageDeclaration ::= PackageDeclarationName ';'
-/.$putCase  consumePackageDeclaration(); $break ./
-
-PackageDeclarationName ::= 'package' Name
-/.$putCase  consumePackageDeclarationName(); $break ./
-
-ImportDeclaration -> SingleTypeImportDeclaration
-ImportDeclaration -> TypeImportOnDemandDeclaration
-
-SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'
-/.$putCase consumeSingleTypeImportDeclaration(); $break ./
-			  
-SingleTypeImportDeclarationName ::= 'import' Name
-/.$putCase consumeSingleTypeImportDeclarationName(); $break ./
-			  
-TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName ';'
-/.$putCase consumeTypeImportOnDemandDeclaration(); $break ./
-
-TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
-/.$putCase consumeTypeImportOnDemandDeclarationName(); $break ./
-
-TypeDeclaration -> ClassDeclaration
-TypeDeclaration -> InterfaceDeclaration
--- this declaration in part of a list od declaration and we will
--- use and optimized list length calculation process 
--- thus we decrement the number while it will be incremend.....
-TypeDeclaration ::= ';' 
-/. $putCase consumeEmptyTypeDeclaration(); $break ./
-
---18.7 Only in the LALR(1) Grammar
-
-Modifiers ::= Modifier
-Modifiers ::= Modifiers Modifier
-
-Modifier -> 'public' 
-Modifier -> 'protected'
-Modifier -> 'private'
-Modifier -> 'static'
-Modifier -> 'abstract'
-Modifier -> 'final'
-Modifier -> 'native'
-Modifier -> 'synchronized'
-Modifier -> 'transient'
-Modifier -> 'volatile'
-Modifier -> 'strictfp'
-
---18.8 Productions from 8: Class Declarations
---ClassModifier ::=
---      'abstract'
---    | 'final'
---    | 'public'
---18.8.1 Productions from 8.1: Class Declarations
-
-ClassDeclaration ::= ClassHeader ClassBody
-/.$putCase consumeClassDeclaration(); $break ./
-
-ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt
-/.$putCase consumeClassHeader(); $break ./
-
-ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
-/.$putCase consumeClassHeaderName(); $break ./
-
-ClassHeaderExtends ::= 'extends' ClassType
-/.$putCase consumeClassHeaderExtends(); $break ./
-
-ClassHeaderImplements ::= 'implements' InterfaceTypeList
-/.$putCase consumeClassHeaderImplements(); $break ./
-
-InterfaceTypeList -> InterfaceType
-InterfaceTypeList ::= InterfaceTypeList ',' InterfaceType
-/.$putCase consumeInterfaceTypeList(); $break ./
-
-InterfaceType ::= ClassOrInterfaceType
-/.$putCase consumeInterfaceType(); $break ./
-
-ClassBody ::= '{' ClassBodyDeclarationsopt '}'
-
-ClassBodyDeclarations ::= ClassBodyDeclaration
-ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration
-/.$putCase consumeClassBodyDeclarations(); $break ./
-
-ClassBodyDeclaration -> ClassMemberDeclaration
-ClassBodyDeclaration -> StaticInitializer
-ClassBodyDeclaration -> ConstructorDeclaration
---1.1 feature
-ClassBodyDeclaration ::= Diet NestedMethod Block
-/.$putCase consumeClassBodyDeclaration(); $break ./
-Diet ::= $empty
-/.$putCase consumeDiet(); $break./
-
-Initializer ::= Diet NestedMethod Block
-/.$putCase consumeClassBodyDeclaration(); $break ./
-
-ClassMemberDeclaration -> FieldDeclaration
-ClassMemberDeclaration -> MethodDeclaration
---1.1 feature
-ClassMemberDeclaration -> ClassDeclaration
---1.1 feature
-ClassMemberDeclaration -> InterfaceDeclaration
-
--- Empty declarations are not valid Java ClassMemberDeclarations.
--- However, since the current (2/14/97) Java compiler accepts them 
--- (in fact, some of the official tests contain this erroneous
--- syntax)
-
-GenericMethodDeclaration -> MethodDeclaration
-GenericMethodDeclaration -> ConstructorDeclaration
-
-ClassMemberDeclaration ::= ';'
-/.$putCase consumeEmptyClassMemberDeclaration(); $break./
-
---18.8.2 Productions from 8.3: Field Declarations
---VariableModifier ::=
---      'public'
---    | 'protected'
---    | 'private'
---    | 'static'
---    | 'final'
---    | 'transient'
---    | 'volatile'
-
-FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
-/.$putCase consumeFieldDeclaration(); $break ./
-
-VariableDeclarators -> VariableDeclarator 
-VariableDeclarators ::= VariableDeclarators ',' VariableDeclarator
-/.$putCase consumeVariableDeclarators(); $break ./
-
-VariableDeclarator ::= VariableDeclaratorId EnterVariable ExitVariableWithoutInitialization
-
-VariableDeclarator ::= VariableDeclaratorId EnterVariable '=' ForceNoDiet VariableInitializer RestoreDiet ExitVariableWithInitialization
-
-EnterVariable ::= $empty
-/.$putCase consumeEnterVariable(); $break ./
-
-ExitVariableWithInitialization ::= $empty
-/.$putCase consumeExitVariableWithInitialization(); $break ./
-
-ExitVariableWithoutInitialization ::= $empty
-/.$putCase consumeExitVariableWithoutInitialization(); $break ./
-
-ForceNoDiet ::= $empty
-/.$putCase consumeForceNoDiet(); $break ./
-RestoreDiet ::= $empty
-/.$putCase consumeRestoreDiet(); $break ./
-
-VariableDeclaratorId ::= 'Identifier' Dimsopt
-
-VariableInitializer -> Expression
-VariableInitializer -> ArrayInitializer
-
---18.8.3 Productions from 8.4: Method Declarations
---MethodModifier ::=
---      'public'
---    | 'protected'
---    | 'private'
---    | 'static'
---    | 'abstract'
---    | 'final'
---    | 'native'
---    | 'synchronized'
---
-
-MethodDeclaration -> AbstractMethodDeclaration
-MethodDeclaration ::= MethodHeader MethodBody 
-/.$putCase // set to true to consume a method with a body
-  consumeMethodDeclaration(true);  $break ./
-
-AbstractMethodDeclaration ::= MethodHeader ';'
-/.$putCase // set to false to consume a method without body
-  consumeMethodDeclaration(false); $break ./
-
-MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims MethodHeaderThrowsClauseopt
-/.$putCase consumeMethodHeader(); $break ./
-
-MethodPushModifiersHeader ::= MethodPushModifiersHeaderName MethodHeaderParameters MethodHeaderExtendedDims MethodHeaderThrowsClauseopt
-/.$putCase consumeMethodHeader(); $break ./
-
-MethodPushModifiersHeaderName ::= Modifiers Type PushModifiers 'Identifier' '(' 
-/.$putCase consumeMethodPushModifiersHeaderName(); $break ./
-
-MethodPushModifiersHeaderName ::= Type PushModifiers 'Identifier' '(' 
-/.$putCase consumeMethodPushModifiersHeaderName(); $break ./
-
-MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
-/.$putCase consumeMethodHeaderName(); $break ./
-
-MethodHeaderParameters ::= FormalParameterListopt ')'
-/.$putCase consumeMethodHeaderParameters(); $break ./
-
-MethodHeaderExtendedDims ::= Dimsopt
-/.$putCase consumeMethodHeaderExtendedDims(); $break ./
-
-MethodHeaderThrowsClause ::= 'throws' ClassTypeList
-/.$putCase consumeMethodHeaderThrowsClause(); $break ./
-
-ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
-/.$putCase consumeConstructorHeader(); $break ./
-
-ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('
-/.$putCase consumeConstructorHeaderName(); $break ./
-
-FormalParameterList -> FormalParameter
-FormalParameterList ::= FormalParameterList ',' FormalParameter
-/.$putCase consumeFormalParameterList(); $break ./
-
---1.1 feature
-FormalParameter ::= Modifiersopt Type VariableDeclaratorId
-/.$putCase // the boolean is used to know if the modifiers should be reset
- 	consumeFormalParameter(); $break ./
-
-ClassTypeList -> ClassTypeElt
-ClassTypeList ::= ClassTypeList ',' ClassTypeElt
-/.$putCase consumeClassTypeList(); $break ./
-
-ClassTypeElt ::= ClassType
-/.$putCase consumeClassTypeElt(); $break ./
-
-
-MethodBody ::= NestedMethod '{' BlockStatementsopt '}' 
-/.$putCase consumeMethodBody(); $break ./
-
-NestedMethod ::= $empty
-/.$putCase consumeNestedMethod(); $break ./
-
---18.8.4 Productions from 8.5: Static Initializers
-
-StaticInitializer ::=  StaticOnly Block
-/.$putCase consumeStaticInitializer(); $break./
-
-StaticOnly ::= 'static'
-/.$putCase consumeStaticOnly(); $break ./
-
---18.8.5 Productions from 8.6: Constructor Declarations
---ConstructorModifier ::=
---      'public'
---    | 'protected'
---    | 'private'
---
---
-ConstructorDeclaration ::= ConstructorHeader ConstructorBody
-/.$putCase consumeConstructorDeclaration() ; $break ./ 
-
--- These rules are added to be able to parse constructors with no body
-ConstructorDeclaration ::= ConstructorHeader ';'
-/.$putCase consumeInvalidConstructorDeclaration() ; $break ./ 
-
--- the rules ExplicitConstructorInvocationopt has been expanded
--- in the rule below in order to make the grammar lalr(1).
--- ConstructorBody ::= '{' ExplicitConstructorInvocationopt BlockStatementsopt '}'
--- Other inlining has occured into the next rule too....
-
-ConstructorBody ::= NestedMethod  '{' ConstructorBlockStatementsopt '}'
-/.$putCase consumeConstructorBody(); $break ./
-
-ConstructorBlockStatementsopt -> BlockStatementsopt
-
-ConstructorBlockStatementsopt -> ExplicitConstructorInvocation
-
-ConstructorBlockStatementsopt ::= ExplicitConstructorInvocation BlockStatements
-/.$putCase  consumeConstructorBlockStatements(); $break ./
-
-ExplicitConstructorInvocation ::= 'this' '(' ArgumentListopt ')' ';'
-/.$putCase consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.This); $break ./
-
-ExplicitConstructorInvocation ::= 'super' '(' ArgumentListopt ')' ';'
-/.$putCase consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.Super); $break ./
-
---1.1 feature
-ExplicitConstructorInvocation ::= Primary '.' 'super' '(' ArgumentListopt ')' ';'
-/.$putCase consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.Super); $break ./
-
---1.1 feature
-ExplicitConstructorInvocation ::= Name '.' 'super' '(' ArgumentListopt ')' ';'
-/.$putCase consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.Super); $break ./
-
---1.1 feature
-ExplicitConstructorInvocation ::= Primary '.' 'this' '(' ArgumentListopt ')' ';'
-/.$putCase consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.This); $break ./
-
---1.1 feature
-ExplicitConstructorInvocation ::= Name '.' 'this' '(' ArgumentListopt ')' ';'
-/.$putCase consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.This); $break ./
-
---18.9 Productions from 9: Interface Declarations
-
---18.9.1 Productions from 9.1: Interface Declarations
---InterfaceModifier ::=
---      'public'
---    | 'abstract'
---
-InterfaceDeclaration ::= InterfaceHeader InterfaceBody
-/.$putCase consumeInterfaceDeclaration(); $break ./
-
-InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt
-/.$putCase consumeInterfaceHeader(); $break ./
-
-InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
-/.$putCase consumeInterfaceHeaderName(); $break ./
-
--- This rule will be used to accept inner local interface and then report a relevant error message
-InvalidInterfaceDeclaration -> InterfaceHeader InterfaceBody
-
-InterfaceHeaderExtends ::= 'extends' InterfaceTypeList
-/.$putCase consumeInterfaceHeaderExtends(); $break ./
-
-InterfaceBody ::= '{' InterfaceMemberDeclarationsopt '}' 
-
-InterfaceMemberDeclarations -> InterfaceMemberDeclaration
-InterfaceMemberDeclarations ::= InterfaceMemberDeclarations InterfaceMemberDeclaration
-/.$putCase consumeInterfaceMemberDeclarations(); $break ./
-
---same as for class members
-InterfaceMemberDeclaration ::= ';'
-/.$putCase consumeEmptyInterfaceMemberDeclaration(); $break ./
-
--- This rule is added to be able to parse non abstract method inside interface and then report a relevent error message
-InvalidMethodDeclaration -> MethodHeader MethodBody
-
-InterfaceMemberDeclaration -> ConstantDeclaration
-InterfaceMemberDeclaration ::= InvalidMethodDeclaration
-/.$putCase ignoreMethodBody(); $break ./
-
--- These rules are added to be able to parse constructors inside interface and then report a relevent error message
-InvalidConstructorDeclaration ::= ConstructorHeader ConstructorBody
-/.$putCase ignoreInvalidConstructorDeclaration(true);  $break ./
-
-InvalidConstructorDeclaration ::= ConstructorHeader ';'
-/.$putCase ignoreInvalidConstructorDeclaration(false);  $break ./
-
-InterfaceMemberDeclaration -> AbstractMethodDeclaration
-InterfaceMemberDeclaration -> InvalidConstructorDeclaration
- 
---1.1 feature
-InterfaceMemberDeclaration -> ClassDeclaration
---1.1 feature
-InterfaceMemberDeclaration -> InterfaceDeclaration
-
-ConstantDeclaration -> FieldDeclaration
-
-ArrayInitializer ::= '{' ,opt '}'
-/.$putCase consumeEmptyArrayInitializer(); $break ./
-ArrayInitializer ::= '{' VariableInitializers '}'
-/.$putCase consumeArrayInitializer(); $break ./
-ArrayInitializer ::= '{' VariableInitializers , '}'
-/.$putCase consumeArrayInitializer(); $break ./
-
-VariableInitializers ::= VariableInitializer
-VariableInitializers ::= VariableInitializers ',' VariableInitializer
-/.$putCase consumeVariableInitializers(); $break ./
-
-Block ::= OpenBlock '{' BlockStatementsopt '}'
-/.$putCase consumeBlock(); $break ./
-OpenBlock ::= $empty
-/.$putCase consumeOpenBlock() ; $break ./
-
-BlockStatements -> BlockStatement
-BlockStatements ::= BlockStatements BlockStatement
-/.$putCase consumeBlockStatements() ; $break ./
-
-BlockStatement -> LocalVariableDeclarationStatement
-BlockStatement -> Statement
---1.1 feature
-BlockStatement -> ClassDeclaration
-BlockStatement ::= InvalidInterfaceDeclaration
-/.$putCase ignoreInterfaceDeclaration(); $break ./
-
-LocalVariableDeclarationStatement ::= LocalVariableDeclaration ';'
-/.$putCase consumeLocalVariableDeclarationStatement(); $break ./
-
-LocalVariableDeclaration ::= Type PushModifiers VariableDeclarators
-/.$putCase consumeLocalVariableDeclaration(); $break ./
-
--- 1.1 feature
--- The modifiers part of this rule makes the grammar more permissive. 
--- The only modifier here is final. We put Modifiers to allow multiple modifiers
--- This will require to check the validity of the modifier
-
-LocalVariableDeclaration ::= Modifiers Type PushModifiers VariableDeclarators
-/.$putCase consumeLocalVariableDeclaration(); $break ./
-
-PushModifiers ::= $empty
-/.$putCase consumePushModifiers(); $break ./
-
-Statement -> StatementWithoutTrailingSubstatement
-Statement -> LabeledStatement
-Statement -> IfThenStatement
-Statement -> IfThenElseStatement
-Statement -> WhileStatement
-Statement -> ForStatement
-
-StatementNoShortIf -> StatementWithoutTrailingSubstatement
-StatementNoShortIf -> LabeledStatementNoShortIf
-StatementNoShortIf -> IfThenElseStatementNoShortIf
-StatementNoShortIf -> WhileStatementNoShortIf
-StatementNoShortIf -> ForStatementNoShortIf
-
-StatementWithoutTrailingSubstatement -> AssertStatement
-StatementWithoutTrailingSubstatement -> Block
-StatementWithoutTrailingSubstatement -> EmptyStatement
-StatementWithoutTrailingSubstatement -> ExpressionStatement
-StatementWithoutTrailingSubstatement -> SwitchStatement
-StatementWithoutTrailingSubstatement -> DoStatement
-StatementWithoutTrailingSubstatement -> BreakStatement
-StatementWithoutTrailingSubstatement -> ContinueStatement
-StatementWithoutTrailingSubstatement -> ReturnStatement
-StatementWithoutTrailingSubstatement -> SynchronizedStatement
-StatementWithoutTrailingSubstatement -> ThrowStatement
-StatementWithoutTrailingSubstatement -> TryStatement
-
-EmptyStatement ::= ';'
-/.$putCase consumeEmptyStatement(); $break ./
-
-LabeledStatement ::= 'Identifier' ':' Statement
-/.$putCase consumeStatementLabel() ; $break ./
-
-LabeledStatementNoShortIf ::= 'Identifier' ':' StatementNoShortIf
-/.$putCase consumeStatementLabel() ; $break ./
-
-ExpressionStatement ::= StatementExpression ';'
-/. $putCase consumeExpressionStatement(); $break ./
-
-StatementExpression ::= Assignment
-StatementExpression ::= PreIncrementExpression
-StatementExpression ::= PreDecrementExpression
-StatementExpression ::= PostIncrementExpression
-StatementExpression ::= PostDecrementExpression
-StatementExpression ::= MethodInvocation
-StatementExpression ::= ClassInstanceCreationExpression
-
-IfThenStatement ::=  'if' '(' Expression ')' Statement
-/.$putCase consumeStatementIfNoElse(); $break ./
-
-IfThenElseStatement ::=  'if' '(' Expression ')' StatementNoShortIf 'else' Statement
-/.$putCase consumeStatementIfWithElse(); $break ./
-
-IfThenElseStatementNoShortIf ::=  'if' '(' Expression ')' StatementNoShortIf 'else' StatementNoShortIf
-/.$putCase consumeStatementIfWithElse(); $break ./
-
-SwitchStatement ::= 'switch' OpenBlock '(' Expression ')' SwitchBlock
-/.$putCase consumeStatementSwitch() ; $break ./
-
-SwitchBlock ::= '{' '}'
-/.$putCase consumeEmptySwitchBlock() ; $break ./
-
-SwitchBlock ::= '{' SwitchBlockStatements '}'
-SwitchBlock ::= '{' SwitchLabels '}'
-SwitchBlock ::= '{' SwitchBlockStatements SwitchLabels '}'
-/.$putCase consumeSwitchBlock() ; $break ./
-
-SwitchBlockStatements -> SwitchBlockStatement
-SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement
-/.$putCase consumeSwitchBlockStatements() ; $break ./
-
-SwitchBlockStatement ::= SwitchLabels BlockStatements
-/.$putCase consumeSwitchBlockStatement() ; $break ./
-
-SwitchLabels -> SwitchLabel
-SwitchLabels ::= SwitchLabels SwitchLabel
-/.$putCase consumeSwitchLabels() ; $break ./
-
-SwitchLabel ::= 'case' ConstantExpression ':'
-/. $putCase consumeCaseLabel(); $break ./
-
-SwitchLabel ::= 'default' ':'
-/. $putCase consumeDefaultLabel(); $break ./
-
-WhileStatement ::= 'while' '(' Expression ')' Statement
-/.$putCase consumeStatementWhile() ; $break ./
-
-WhileStatementNoShortIf ::= 'while' '(' Expression ')' StatementNoShortIf
-/.$putCase consumeStatementWhile() ; $break ./
-
-DoStatement ::= 'do' Statement 'while' '(' Expression ')' ';'
-/.$putCase consumeStatementDo() ; $break ./
-
-ForStatement ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' Statement
-/.$putCase consumeStatementFor() ; $break ./
-ForStatementNoShortIf ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' StatementNoShortIf
-/.$putCase consumeStatementFor() ; $break ./
-
---the minus one allows to avoid a stack-to-stack transfer
-ForInit ::= StatementExpressionList
-/.$putCase consumeForInit() ; $break ./
-ForInit -> LocalVariableDeclaration
-
-ForUpdate -> StatementExpressionList
-
-StatementExpressionList -> StatementExpression
-StatementExpressionList ::= StatementExpressionList ',' StatementExpression
-/.$putCase consumeStatementExpressionList() ; $break ./
-
--- 1.4 feature
-AssertStatement ::= 'assert' Expression ';'
-/.$putCase consumeSimpleAssertStatement() ; $break ./
-
-AssertStatement ::= 'assert' Expression ':' Expression ';'
-/.$putCase consumeAssertStatement() ; $break ./
-          
-BreakStatement ::= 'break' ';'
-/.$putCase consumeStatementBreak() ; $break ./
-
-BreakStatement ::= 'break' Identifier ';'
-/.$putCase consumeStatementBreakWithLabel() ; $break ./
-
-ContinueStatement ::= 'continue' ';'
-/.$putCase consumeStatementContinue() ; $break ./
-
-ContinueStatement ::= 'continue' Identifier ';'
-/.$putCase consumeStatementContinueWithLabel() ; $break ./
-
-ReturnStatement ::= 'return' Expressionopt ';'
-/.$putCase consumeStatementReturn() ; $break ./
-
-ThrowStatement ::= 'throw' Expression ';'
-/.$putCase consumeStatementThrow();
-$break ./
-
-SynchronizedStatement ::= OnlySynchronized '(' Expression ')'    Block
-/.$putCase consumeStatementSynchronized(); $break ./
-OnlySynchronized ::= 'synchronized'
-/.$putCase consumeOnlySynchronized(); $break ./
-
-
-TryStatement ::= 'try'    Block Catches
-/.$putCase consumeStatementTry(false); $break ./
-TryStatement ::= 'try'    Block Catchesopt Finally
-/.$putCase consumeStatementTry(true); $break ./
-
-Catches -> CatchClause
-Catches ::= Catches CatchClause
-/.$putCase consumeCatches(); $break ./
-
-CatchClause ::= 'catch' '(' FormalParameter ')'    Block
-/.$putCase consumeStatementCatch() ; $break ./
-
-Finally ::= 'finally'    Block
-
---18.12 Productions from 14: Expressions
-
---for source positionning purpose
-PushLPAREN ::= '('
-/.$putCase consumeLeftParen(); $break ./
-PushRPAREN ::= ')'
-/.$putCase consumeRightParen(); $break ./
-
-Primary -> PrimaryNoNewArray
-Primary -> ArrayCreationWithArrayInitializer
-Primary -> ArrayCreationWithoutArrayInitializer
-
-PrimaryNoNewArray -> Literal
-PrimaryNoNewArray ::= 'this'
-/.$putCase consumePrimaryNoNewArrayThis(); $break ./
-
-PrimaryNoNewArray ::=  PushLPAREN Expression PushRPAREN 
-/.$putCase consumePrimaryNoNewArray(); $break ./
-
-PrimaryNoNewArray -> ClassInstanceCreationExpression
-PrimaryNoNewArray -> FieldAccess
---1.1 feature
-PrimaryNoNewArray ::= Name '.' 'this'
-/.$putCase consumePrimaryNoNewArrayNameThis(); $break ./
-PrimaryNoNewArray ::= Name '.' 'super'
-/.$putCase consumePrimaryNoNewArrayNameSuper(); $break ./
-
---1.1 feature
---PrimaryNoNewArray ::= Type '.' 'class'   
---inline Type in the previous rule in order to make the grammar LL1 instead 
--- of LL2. The result is the 3 next rules.
-PrimaryNoNewArray ::= Name '.' 'class'
-/.$putCase consumePrimaryNoNewArrayName(); $break ./
-
-PrimaryNoNewArray ::= ArrayType '.' 'class'
-/.$putCase consumePrimaryNoNewArrayArrayType(); $break ./
-
-PrimaryNoNewArray ::= PrimitiveType '.' 'class'
-/.$putCase consumePrimaryNoNewArrayPrimitiveType(); $break ./
-
-PrimaryNoNewArray -> MethodInvocation
-PrimaryNoNewArray -> ArrayAccess
-
---1.1 feature
---
--- In Java 1.0 a ClassBody could not appear at all in a
--- ClassInstanceCreationExpression.
---
-
-AllocationHeader ::= 'new' ClassType '(' ArgumentListopt ')'
-/.$putCase consumeAllocationHeader(); $break ./
-
-ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
-/.$putCase consumeClassInstanceCreationExpression(); $break ./
---1.1 feature
-
-ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
-/.$putCase consumeClassInstanceCreationExpressionQualified() ; $break ./
-
---1.1 feature
-ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
-/.$putCase consumeClassInstanceCreationExpressionQualified() ; $break ./
-
-ClassInstanceCreationExpressionName ::= Name '.'
-/.$putCase consumeClassInstanceCreationExpressionName() ; $break ./
-
-ClassBodyopt ::= $empty --test made using null as contents
-/.$putCase consumeClassBodyopt(); $break ./
-ClassBodyopt ::= EnterAnonymousClassBody ClassBody
-
-EnterAnonymousClassBody ::= $empty
-/.$putCase consumeEnterAnonymousClassBody(); $break ./
-
-ArgumentList ::= Expression
-ArgumentList ::= ArgumentList ',' Expression
-/.$putCase consumeArgumentList(); $break ./
-
-ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs
-/.$putCase consumeArrayCreationExpressionWithoutInitializer(); $break ./
-
-ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer
-/.$putCase consumeArrayCreationExpressionWithInitializer(); $break ./
-
-ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs
-/.$putCase consumeArrayCreationExpressionWithoutInitializer(); $break ./
-
-ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer
-/.$putCase consumeArrayCreationExpressionWithInitializer(); $break ./
-
-DimWithOrWithOutExprs ::= DimWithOrWithOutExpr
-DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr
-/.$putCase consumeDimWithOrWithOutExprs(); $break ./
-
-DimWithOrWithOutExpr ::= '[' Expression ']'
-DimWithOrWithOutExpr ::= '[' ']'
-/. $putCase consumeDimWithOrWithOutExpr(); $break ./
--- -----------------------------------------------
-
-Dims ::= DimsLoop
-/. $putCase consumeDims(); $break ./
-DimsLoop -> OneDimLoop
-DimsLoop ::= DimsLoop OneDimLoop
-OneDimLoop ::= '[' ']'
-/. $putCase consumeOneDimLoop(); $break ./
-
-FieldAccess ::= Primary '.' 'Identifier'
-/.$putCase consumeFieldAccess(false); $break ./
-
-FieldAccess ::= 'super' '.' 'Identifier'
-/.$putCase consumeFieldAccess(true); $break ./
-
-MethodInvocation ::= Name '(' ArgumentListopt ')'
-/.$putCase consumeMethodInvocationName(); $break ./
-
-MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
-/.$putCase consumeMethodInvocationPrimary(); $break ./
-
-MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
-/.$putCase consumeMethodInvocationSuper(); $break ./
-
-ArrayAccess ::= Name '[' Expression ']'
-/.$putCase consumeArrayAccess(true); $break ./
-ArrayAccess ::= PrimaryNoNewArray '[' Expression ']'
-/.$putCase consumeArrayAccess(false); $break ./
-ArrayAccess ::= ArrayCreationWithArrayInitializer '[' Expression ']'
-/.$putCase consumeArrayAccess(false); $break ./
-
-PostfixExpression -> Primary
-PostfixExpression ::= Name
-/.$putCase consumePostfixExpression(); $break ./
-PostfixExpression -> PostIncrementExpression
-PostfixExpression -> PostDecrementExpression
-
-PostIncrementExpression ::= PostfixExpression '++'
-/.$putCase consumeUnaryExpression(OperatorExpression.PLUS,true); $break ./
-
-PostDecrementExpression ::= PostfixExpression '--'
-/.$putCase consumeUnaryExpression(OperatorExpression.MINUS,true); $break ./
-
---for source managment purpose
-PushPosition ::= $empty
- /.$putCase consumePushPosition(); $break ./
-
-UnaryExpression -> PreIncrementExpression
-UnaryExpression -> PreDecrementExpression
-UnaryExpression ::= '+' PushPosition UnaryExpression
-/.$putCase consumeUnaryExpression(OperatorExpression.PLUS); $break ./
-UnaryExpression ::= '-' PushPosition UnaryExpression
-/.$putCase consumeUnaryExpression(OperatorExpression.MINUS); $break ./
-UnaryExpression -> UnaryExpressionNotPlusMinus
-
-PreIncrementExpression ::= '++' PushPosition UnaryExpression
-/.$putCase consumeUnaryExpression(OperatorExpression.PLUS,false); $break ./
-
-PreDecrementExpression ::= '--' PushPosition UnaryExpression
-/.$putCase consumeUnaryExpression(OperatorExpression.MINUS,false); $break ./
-
-UnaryExpressionNotPlusMinus -> PostfixExpression
-UnaryExpressionNotPlusMinus ::= '~' PushPosition UnaryExpression
-/.$putCase consumeUnaryExpression(OperatorExpression.TWIDDLE); $break ./
-UnaryExpressionNotPlusMinus ::= '!' PushPosition UnaryExpression
-/.$putCase consumeUnaryExpression(OperatorExpression.NOT); $break ./
-UnaryExpressionNotPlusMinus -> CastExpression
-
-CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN InsideCastExpression UnaryExpression
-/.$putCase consumeCastExpression(); $break ./
- CastExpression ::= PushLPAREN Name Dims PushRPAREN InsideCastExpression UnaryExpressionNotPlusMinus
-/.$putCase consumeCastExpression(); $break ./
--- Expression is here only in order to make the grammar LL1
-CastExpression ::= PushLPAREN Expression PushRPAREN InsideCastExpressionLL1 UnaryExpressionNotPlusMinus
-/.$putCase consumeCastExpressionLL1(); $break ./
-
-InsideCastExpression ::= $empty
-/.$putCase consumeInsideCastExpression(); $break ./
-InsideCastExpressionLL1 ::= $empty
-/.$putCase consumeInsideCastExpressionLL1(); $break ./
-
-MultiplicativeExpression -> UnaryExpression
-MultiplicativeExpression ::= MultiplicativeExpression '*' UnaryExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.MULTIPLY); $break ./
-MultiplicativeExpression ::= MultiplicativeExpression '/' UnaryExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.DIVIDE); $break ./
-MultiplicativeExpression ::= MultiplicativeExpression '%' UnaryExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.REMAINDER); $break ./
-
-AdditiveExpression -> MultiplicativeExpression
-AdditiveExpression ::= AdditiveExpression '+' MultiplicativeExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.PLUS); $break ./
-AdditiveExpression ::= AdditiveExpression '-' MultiplicativeExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.MINUS); $break ./
-
-ShiftExpression -> AdditiveExpression
-ShiftExpression ::= ShiftExpression '<<'  AdditiveExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.LEFT_SHIFT); $break ./
-ShiftExpression ::= ShiftExpression '>>'  AdditiveExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.RIGHT_SHIFT); $break ./
-ShiftExpression ::= ShiftExpression '>>>' AdditiveExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.UNSIGNED_RIGHT_SHIFT); $break ./
-
-RelationalExpression -> ShiftExpression
-RelationalExpression ::= RelationalExpression '<'  ShiftExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.LESS); $break ./
-RelationalExpression ::= RelationalExpression '>'  ShiftExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.GREATER); $break ./
-RelationalExpression ::= RelationalExpression '<=' ShiftExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.LESS_EQUAL); $break ./
-RelationalExpression ::= RelationalExpression '>=' ShiftExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.GREATER_EQUAL); $break ./
-RelationalExpression ::= RelationalExpression 'instanceof' ReferenceType
-/.$putCase consumeInstanceOfExpression(OperatorExpression.INSTANCEOF); $break ./
-
-EqualityExpression -> RelationalExpression
-EqualityExpression ::= EqualityExpression '==' RelationalExpression
-/.$putCase consumeEqualityExpression(OperatorExpression.EQUAL_EQUAL); $break ./
-EqualityExpression ::= EqualityExpression '!=' RelationalExpression
-/.$putCase consumeEqualityExpression(OperatorExpression.NOT_EQUAL); $break ./
-
-AndExpression -> EqualityExpression
-AndExpression ::= AndExpression '&' EqualityExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.AND); $break ./
-
-ExclusiveOrExpression -> AndExpression
-ExclusiveOrExpression ::= ExclusiveOrExpression '^' AndExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.XOR); $break ./
-
-InclusiveOrExpression -> ExclusiveOrExpression
-InclusiveOrExpression ::= InclusiveOrExpression '|' ExclusiveOrExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.OR); $break ./
-
-ConditionalAndExpression -> InclusiveOrExpression
-ConditionalAndExpression ::= ConditionalAndExpression '&&' InclusiveOrExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.AND_AND); $break ./
-
-ConditionalOrExpression -> ConditionalAndExpression
-ConditionalOrExpression ::= ConditionalOrExpression '||' ConditionalAndExpression
-/.$putCase consumeBinaryExpression(OperatorExpression.OR_OR); $break ./
-
-ConditionalExpression -> ConditionalOrExpression
-ConditionalExpression ::= ConditionalOrExpression '?' Expression ':' ConditionalExpression
-/.$putCase consumeConditionalExpression(OperatorExpression.QUESTIONCOLON) ; $break ./
-
-AssignmentExpression -> ConditionalExpression
-AssignmentExpression -> Assignment
-
-Assignment ::= PostfixExpression AssignmentOperator AssignmentExpression
-/.$putCase consumeAssignment(); $break ./
-
--- this rule is added to parse an array initializer in a assigment and then report a syntax error knowing the exact senario
-InvalidArrayInitializerAssignement ::= PostfixExpression AssignmentOperator ArrayInitializer
-Assignment ::= InvalidArrayInitializerAssignement
-/.$putcase ignoreExpressionAssignment();$break ./
-
-AssignmentOperator ::= '='
-/.$putCase consumeAssignmentOperator(EQUAL); $break ./
-AssignmentOperator ::= '*='
-/.$putCase consumeAssignmentOperator(MULTIPLY); $break ./
-AssignmentOperator ::= '/='
-/.$putCase consumeAssignmentOperator(DIVIDE); $break ./
-AssignmentOperator ::= '%='
-/.$putCase consumeAssignmentOperator(REMAINDER); $break ./
-AssignmentOperator ::= '+='
-/.$putCase consumeAssignmentOperator(PLUS); $break ./
-AssignmentOperator ::= '-='
-/.$putCase consumeAssignmentOperator(MINUS); $break ./
-AssignmentOperator ::= '<<='
-/.$putCase consumeAssignmentOperator(LEFT_SHIFT); $break ./
-AssignmentOperator ::= '>>='
-/.$putCase consumeAssignmentOperator(RIGHT_SHIFT); $break ./
-AssignmentOperator ::= '>>>='
-/.$putCase consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT); $break ./
-AssignmentOperator ::= '&='
-/.$putCase consumeAssignmentOperator(AND); $break ./
-AssignmentOperator ::= '^='
-/.$putCase consumeAssignmentOperator(XOR); $break ./
-AssignmentOperator ::= '|='
-/.$putCase consumeAssignmentOperator(OR); $break ./
-
-Expression -> AssignmentExpression
-
-ConstantExpression -> Expression
-
--- The following rules are for optional nonterminals.
---
-
-PackageDeclarationopt -> $empty 
-PackageDeclarationopt -> PackageDeclaration
-
-ClassHeaderExtendsopt ::= $empty
-ClassHeaderExtendsopt -> ClassHeaderExtends
-
-Expressionopt ::= $empty
-/.$putCase consumeEmptyExpression(); $break ./
-Expressionopt -> Expression
-
-
----------------------------------------------------------------------------------------
---
--- The rules below are for optional terminal symbols.  An optional comma,
--- is only used in the context of an array initializer - It is a
--- "syntactic sugar" that otherwise serves no other purpose. By contrast,
--- an optional identifier is used in the definition of a break and 
--- continue statement. When the identifier does not appear, a NULL
--- is produced. When the identifier is present, the user should use the
--- corresponding TOKEN(i) method. See break statement as an example.
---
----------------------------------------------------------------------------------------
-
-,opt -> $empty
-,opt -> ,
-
-ImportDeclarationsopt ::= $empty
-/.$putCase consumeEmptyImportDeclarationsopt(); $break ./
-ImportDeclarationsopt ::= ImportDeclarations
-/.$putCase consumeImportDeclarationsopt(); $break ./
-
-
-TypeDeclarationsopt ::= $empty
-/.$putCase consumeEmptyTypeDeclarationsopt(); $break ./
-TypeDeclarationsopt ::= TypeDeclarations
-/.$putCase consumeTypeDeclarationsopt(); $break ./
-
-ClassBodyDeclarationsopt ::= $empty
-/.$putCase consumeEmptyClassBodyDeclarationsopt(); $break ./
-ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations
-/.$putCase consumeClassBodyDeclarationsopt(); $break ./
-
-Modifiersopt ::= $empty 
-/. $putCase consumeDefaultModifiers(); $break ./
-Modifiersopt ::= Modifiers 
-/.$putCase consumeModifiers(); $break ./ 
-
-BlockStatementsopt ::= $empty
-/.$putCase consumeEmptyBlockStatementsopt(); $break ./
-BlockStatementsopt -> BlockStatements
-
-Dimsopt ::= $empty
-/. $putCase consumeEmptyDimsopt(); $break ./
-Dimsopt -> Dims
-
-ArgumentListopt ::= $empty
-/. $putCase consumeEmptyArgumentListopt(); $break ./
-ArgumentListopt -> ArgumentList
-
-MethodHeaderThrowsClauseopt ::= $empty
-MethodHeaderThrowsClauseopt -> MethodHeaderThrowsClause
-   
-FormalParameterListopt ::= $empty
-/.$putcase consumeFormalParameterListopt(); $break ./
-FormalParameterListopt -> FormalParameterList
-
-ClassHeaderImplementsopt ::= $empty
-ClassHeaderImplementsopt -> ClassHeaderImplements
-
-InterfaceMemberDeclarationsopt ::= $empty
-/. $putCase consumeEmptyInterfaceMemberDeclarationsopt(); $break ./
-InterfaceMemberDeclarationsopt ::= NestedType InterfaceMemberDeclarations
-/. $putCase consumeInterfaceMemberDeclarationsopt(); $break ./
-
-NestedType ::= $empty 
-/.$putCase consumeNestedType(); $break./
-
-ForInitopt ::= $empty
-/. $putCase consumeEmptyForInitopt(); $break ./
-ForInitopt -> ForInit
-
-ForUpdateopt ::= $empty
-/. $putCase consumeEmptyForUpdateopt(); $break ./
- ForUpdateopt -> ForUpdate
-
-InterfaceHeaderExtendsopt ::= $empty
-InterfaceHeaderExtendsopt -> InterfaceHeaderExtends
-
-Catchesopt ::= $empty
-/. $putCase consumeEmptyCatchesopt(); $break ./
-Catchesopt -> Catches
-
-/.	}
-} ./
-
----------------------------------------------------------------------------------------
-
-$names
-
--- BodyMarker ::= '"class Identifier { ... MethodHeader "'
-
--- void ::= 'void'
-
-PLUS_PLUS ::=    '++'   
-MINUS_MINUS ::=    '--'   
-EQUAL_EQUAL ::=    '=='   
-LESS_EQUAL ::=    '<='   
-GREATER_EQUAL ::=    '>='   
-NOT_EQUAL ::=    '!='   
-LEFT_SHIFT ::=    '<<'   
-RIGHT_SHIFT ::=    '>>'   
-UNSIGNED_RIGHT_SHIFT ::=    '>>>'  
-PLUS_EQUAL ::=    '+='   
-MINUS_EQUAL ::=    '-='   
-MULTIPLY_EQUAL ::=    '*='   
-DIVIDE_EQUAL ::=    '/='   
-AND_EQUAL ::=    '&='   
-OR_EQUAL ::=    '|='   
-XOR_EQUAL ::=    '^='   
-REMAINDER_EQUAL ::=    '%='   
-LEFT_SHIFT_EQUAL ::=    '<<='  
-RIGHT_SHIFT_EQUAL ::=    '>>='  
-UNSIGNED_RIGHT_SHIFT_EQUAL ::=    '>>>=' 
-OR_OR ::=    '||'   
-AND_AND ::=    '&&'   
-
-PLUS ::=    '+'    
-MINUS ::=    '-'    
-NOT ::=    '!'    
-REMAINDER ::=    '%'    
-XOR ::=    '^'    
-AND ::=    '&'    
-MULTIPLY ::=    '*'    
-OR ::=    '|'    
-TWIDDLE ::=    '~'    
-DIVIDE ::=    '/'    
-GREATER ::=    '>'    
-LESS ::=    '<'    
-LPAREN ::=    '('    
-RPAREN ::=    ')'    
-LBRACE ::=    '{'    
-RBRACE ::=    '}'    
-LBRACKET ::=    '['    
-RBRACKET ::=    ']'    
-SEMICOLON ::=    ';'    
-QUESTION ::=    '?'    
-COLON ::=    ':'    
-COMMA ::=    ','    
-DOT ::=    '.'    
-EQUAL ::=    '='    
-
-$end
--- need a carriage return after the $end
-*/
-}
 protected void ignoreExpressionAssignment() {
 	// Assignment ::= InvalidArrayInitializerAssignement
 	// encoded operator would be: intStack[intPtr]
@@ -6465,7 +4880,7 @@
 		dispatchDeclarationInto(length);
 	}
 	
-	flushAnnotationsDefinedPriorTo(endStatementPosition);
+	flushCommentsDefinedPriorTo(endStatementPosition);
 
 	// report the problem and continue parsing
 	TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
@@ -6494,9 +4909,6 @@
 	astStack : MethodDeclaration
 	identifierStack :
 	*/
-
-	//must provide a default constructor call when needed
-
 	if (hasBody) {
 		// pop the position of the {  (body of the method) pushed in block decl
 		intPtr--;
@@ -6511,6 +4923,12 @@
 	if (hasBody && ((length = astLengthStack[astLengthPtr--]) != 0)) {
 		astPtr -= length;
 	}
+	ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) astStack[astPtr];
+	constructorDeclaration.bodyEnd = endStatementPosition;
+	constructorDeclaration.declarationSourceEnd = flushCommentsDefinedPriorTo(endStatementPosition);
+	if (!hasBody) {
+		constructorDeclaration.modifiers |= AccSemicolonBody;
+	}
 }
 protected void ignoreMethodBody() {
 	// InterfaceMemberDeclaration ::= InvalidMethodDeclaration
@@ -6539,7 +4957,7 @@
 	//watch for } that could be given as a unicode ! ( u007D is '}' )
 	MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
 	md.bodyEnd = endPosition;
-	md.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition);
+	md.declarationSourceEnd = flushCommentsDefinedPriorTo(endStatementPosition);
 
 	// report the problem and continue the parsing - narrowing the problem onto the method
 	problemReporter().abstractMethodNeedingNoBody(md);
@@ -6567,7 +4985,7 @@
 	
 	int astLength = astStack.length;
 	if (noAstNodes.length < astLength){
-		noAstNodes = new AstNode[astLength];
+		noAstNodes = new ASTNode[astLength];
 		//System.out.println("Resized AST stacks : "+ astLength);
 		
 	}
@@ -6584,6 +5002,9 @@
 	scanner.commentPtr = -1;
 	scanner.foundTaskCount = 0;
 	scanner.eofPosition = Integer.MAX_VALUE;
+	scanner.wasNonExternalizedStringLiteral = false;
+	scanner.nonNLSStrings = null;
+	scanner.currentLine = null;	
 
 	resetModifiers();
 
@@ -6596,16 +5017,19 @@
 	lastIgnoredToken = -1;
 	lastErrorEndPosition = -1;
 	listLength = 0;
+	
+	rBraceStart = 0;
+	rBraceEnd = 0;
+	rBraceSuccessorStart = 0;
 }
 public void initializeScanner(){
-	CompilerOptions options = this.problemReporter.options;
 	this.scanner = new Scanner(
 		false /*comment*/, 
 		false /*whitespace*/, 
-		options.getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /*nls*/, 
-		this.assertMode /*assert*/, 
-		options.taskTags/*taskTags*/,
-		options.taskPriorites/*taskPriorities*/);
+		this.options.getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /*nls*/, 
+		this.options.sourceLevel /*sourceLevel*/, 
+		this.options.taskTags/*taskTags*/,
+		this.options.taskPriorites/*taskPriorities*/);
 }
 public final static void initTables() throws java.io.IOException {
 
@@ -6619,8 +5043,31 @@
 	}
 	asb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
 	asr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	symbol_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
-	action = lhs;
+	nasb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	nasr = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	non_terminal_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	term_action = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	
+	scope_prefix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_suffix = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_lhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_state_set = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_rhs = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_state = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	in_symb = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	
+	rhs = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	term_check = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	scope_la = readByteTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	
+	name = readNameTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+	readableName = readReadableNameTable(READABLE_NAMES);
+	
+	base_action = lhs;
+}
+public static int in_symbol(int state) {
+	return in_symb[original_state(state)];
 }
 public final void jumpOverMethodBody() {
 	//on diet parsing.....do not buffer method statements
@@ -6635,26 +5082,26 @@
 protected void markEnclosingMemberWithLocalType() {
 	if (this.currentElement != null) return; // this is already done in the recovery code
 	for (int i = this.astPtr; i >= 0; i--) {
-		AstNode node = this.astStack[i];
+		ASTNode node = this.astStack[i];
 		if (node instanceof AbstractMethodDeclaration 
 				|| node instanceof FieldDeclaration
 				|| node instanceof TypeDeclaration) { // mark type for now: all initializers will be marked when added to this type
-			node.bits |= AstNode.HasLocalTypeMASK;
+			node.bits |= ASTNode.HasLocalTypeMASK;
 			return;
 		}
 	}
 	// default to reference context (case of parse method body)
 	if (this.referenceContext instanceof AbstractMethodDeclaration
 			|| this.referenceContext instanceof TypeDeclaration) {
-		((AstNode)this.referenceContext).bits |= AstNode.HasLocalTypeMASK;
+		((ASTNode)this.referenceContext).bits |= ASTNode.HasLocalTypeMASK;
 	}
 }
 protected void markInitializersWithLocalType(TypeDeclaration type) {
-	if (type.fields == null || (type.bits & AstNode.HasLocalTypeMASK) == 0) return;
+	if (type.fields == null || (type.bits & ASTNode.HasLocalTypeMASK) == 0) return;
 	for (int i = 0, length = type.fields.length; i < length; i++) {
 		FieldDeclaration field = type.fields[i];
 		if (field instanceof Initializer) {
-			field.bits |= AstNode.HasLocalTypeMASK;
+			field.bits |= ASTNode.HasLocalTypeMASK;
 		}
 	}
 }
@@ -6675,6 +5122,7 @@
 	/* if about to restart, then no need to shift token */
 	if (restartRecovery){
 		lastIgnoredToken = -1;
+		scanner.currentLine = null;
 		return true;
 	}
 	
@@ -6696,6 +5144,7 @@
 	
 	if (nextIgnoredToken == TokenNameEOF) { // no more recovery after this point
 		if (currentToken == TokenNameEOF) { // already tried one iteration on EOF
+			scanner.currentLine = null;
 			return false;
 		}
 	}
@@ -6706,6 +5155,7 @@
 	scanner.currentPosition = pos;
 	scanner.commentPtr = -1;
 	scanner.foundTaskCount = 0;
+	scanner.currentLine = null;
 
 	return true;
 
@@ -6790,11 +5240,14 @@
 			m.arguments = new Expression[length], 
 			0, 
 			length); 
-	};
+	}
 	return m;
 }
-protected static int ntAction(int state, int sym) {
-	return action[state + sym];
+public static int nasi(int state) {
+	return nasb[original_state(state)];
+}
+public static int ntAction(int state, int sym) {
+	return base_action[state + sym];
 }
 private final void optimizedConcatNodeLists() {
 	/*back from a recursive loop. Virtualy group the
@@ -6817,7 +5270,7 @@
 	astLengthStack[--astLengthPtr]++;
 }
 protected static int original_state(int state) {
-	return -check(state);
+	return -base_check(state);
 }
 /*main loop of the automat
 When a rule is reduced, the method consumeRule(int) is called with the number
@@ -6826,7 +5279,10 @@
 // (int)asr[asi(act)]
 // name[symbol_index[currentKind]]
 protected void parse() {
-
+	boolean isDietParse = diet;
+	int oldFirstToken = getFirstToken();
+	hasError = false;
+	
 	hasReportedError = false;
 	int act = START_STATE;
 	stateStackTop = -1;
@@ -6840,45 +5296,29 @@
 			stack = new int[oldStackLength + StackIncrement];
 			System.arraycopy(oldStack, 0, stack, 0, oldStackLength);
 			stack[stateStackTop] = act;
-		};
+		}
 
 		act = tAction(act, currentToken);
 
 		if (act == ERROR_ACTION || restartRecovery) {
 			int errorPos = scanner.currentPosition;
 			if (!hasReportedError){
-				this.reportSyntaxError(ERROR_ACTION, currentToken, stateStackTop);
-				hasReportedError = true;
+				hasError = true;
 			}
 			if (resumeOnSyntaxError()) {
 				if (act == ERROR_ACTION) lastErrorEndPosition = errorPos;
-				act = START_STATE;
-				stateStackTop = -1;
-				currentToken = getFirstToken();
-				continue ProcessTerminals;
-			} else {
-				act = ERROR_ACTION;
-			}	break ProcessTerminals;
-		}
-		if (act <= NUM_RULES)
-			stateStackTop--;
-		else
-			if (act > ERROR_ACTION) { /* shift-reduce */
-				consumeToken(currentToken);
-				if (currentElement != null) this.recoveryTokenCheck();
-				try{
-					currentToken = scanner.getNextToken();
-				} catch(InvalidInputException e){
-					if (!hasReportedError){
-						this.problemReporter().scannerError(this, e.getMessage());
-						hasReportedError = true;
-					}
-					lastCheckPoint = scanner.currentPosition;
-					restartRecovery = true;
-				}					
-				act -= ERROR_ACTION;
-			} else
-				if (act < ACCEPT_ACTION) { /* shift */
+					act = START_STATE;
+					stateStackTop = -1;
+					currentToken = getFirstToken();
+					continue ProcessTerminals;
+				} else {
+					act = ERROR_ACTION;
+				}	break ProcessTerminals;
+			}
+			if (act <= NUM_RULES)
+				stateStackTop--;
+			else
+				if (act > ERROR_ACTION) { /* shift-reduce */
 					consumeToken(currentToken);
 					if (currentElement != null) this.recoveryTokenCheck();
 					try{
@@ -6891,10 +5331,25 @@
 						lastCheckPoint = scanner.currentPosition;
 						restartRecovery = true;
 					}					
-					continue ProcessTerminals;
+					act -= ERROR_ACTION;
 				} else
-					break ProcessTerminals;
-
+					if (act < ACCEPT_ACTION) { /* shift */
+						consumeToken(currentToken);
+						if (currentElement != null) this.recoveryTokenCheck();
+						try{
+							currentToken = scanner.getNextToken();
+						} catch(InvalidInputException e){
+							if (!hasReportedError){
+								this.problemReporter().scannerError(this, e.getMessage());
+								hasReportedError = true;
+							}
+							lastCheckPoint = scanner.currentPosition;
+							restartRecovery = true;
+						}					
+						continue ProcessTerminals;
+					} else
+						break ProcessTerminals;
+			
 		ProcessNonTerminals : do { /* reduce */
 			consumeRule(act);
 			stateStackTop -= (rhs[act] - 1);
@@ -6902,9 +5357,73 @@
 		} while (act <= NUM_RULES);
 	}
 	endParse(act);
+	
+	if(reportSyntaxErrorIsRequired && hasError) {
+		reportSyntaxErrors(isDietParse, oldFirstToken);
+	}
 }
 // A P I
-
+protected void reportSyntaxErrors(boolean isDietParse, int oldFirstToken) {
+	if(referenceContext instanceof MethodDeclaration) {
+		MethodDeclaration methodDeclaration = (MethodDeclaration) referenceContext;
+		if(methodDeclaration.errorInSignature){
+			return;
+		}
+	}
+	compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
+	scanner.recordLineSeparator = false;
+	
+	int start = scanner.initialPosition;
+	int end = scanner.eofPosition <= Integer.MAX_VALUE ? scanner.eofPosition - 1 : scanner.eofPosition;
+	if(isDietParse) {
+		TypeDeclaration[] types = this.compilationUnit.types;
+		
+		int[][] intervalToSkip = org.eclipse.jdt.internal.compiler.parser.diagnose.RangeUtil.computeDietRange(types);
+		DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end, intervalToSkip[0], intervalToSkip[1], intervalToSkip[2]);
+		diagnoseParser.diagnoseParse();
+		
+		reportSyntaxErrorsForSkippedMethod(types);
+		scanner.resetTo(start, end);
+	} else {
+		DiagnoseParser diagnoseParser = new DiagnoseParser(this, oldFirstToken, start, end);
+		diagnoseParser.diagnoseParse();
+	}
+}
+private void reportSyntaxErrorsForSkippedMethod(TypeDeclaration[] types){
+	if(types != null) {
+		for (int i = 0; i < types.length; i++) {
+			TypeDeclaration[] memberTypes = types[i].memberTypes;
+			if(memberTypes != null) {
+				reportSyntaxErrorsForSkippedMethod(memberTypes);
+			}
+			
+			AbstractMethodDeclaration[] methods = types[i].methods;
+			if(methods != null) {
+				for (int j = 0; j < methods.length; j++) {
+					AbstractMethodDeclaration method = methods[j];
+					if(methods[j].errorInSignature) {
+						DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameDIVIDE, method.declarationSourceStart, method.declarationSourceEnd);
+						diagnoseParser.diagnoseParse();
+					}
+				}
+			}
+			
+			FieldDeclaration[] fields = types[i].fields;
+			if (fields != null) {
+				int length = fields.length;
+				for (int j = 0; j < length; j++) {
+					if (fields[j] instanceof Initializer) {
+						Initializer initializer = (Initializer)fields[j];
+						if(initializer.errorInSignature){
+							DiagnoseParser diagnoseParser = new DiagnoseParser(this, TokenNameRIGHT_SHIFT, initializer.declarationSourceStart, initializer.declarationSourceEnd);
+							diagnoseParser.diagnoseParse();
+						}
+					}
+				}
+			}
+		}
+	}
+}
 public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
 	//only parse the method body of cd
 	//fill out its statements
@@ -6912,13 +5431,14 @@
 	//convert bugs into parse error
 
 	initialize();
-	goForConstructorBody();
+	goForBlockStatementsopt();
 	nestedMethod[nestedType]++;
-
+	pushOnRealBlockStack(0);
+	
 	referenceContext = cd;
 	compilationUnit = unit;
 
-	scanner.resetTo(cd.sourceEnd + 1, cd.declarationSourceEnd);
+	scanner.resetTo(cd.bodyStart, cd.bodyEnd);
 	try {
 		parse();
 	} catch (AbortCompilation ex) {
@@ -6927,6 +5447,8 @@
 		nestedMethod[nestedType]--;
 	}
 
+	checkNonNLSAfterBodyEnd(cd.declarationSourceEnd);
+	
 	if (lastAct == ERROR_ACTION) {
 		initialize();
 		return;
@@ -6958,6 +5480,9 @@
 		}
 	} else {
 		cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+		if (!containsComment(cd.bodyStart, cd.bodyEnd)) {
+			cd.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+		}		
 	}
 
 	if (cd.constructorCall.sourceEnd == 0) {
@@ -7000,14 +5525,14 @@
 	field.initialization = expressionStack[expressionPtr];
 	
 	// mark field with local type if one was found during parsing
-	if ((type.bits & AstNode.HasLocalTypeMASK) != 0) {
-		field.bits |= AstNode.HasLocalTypeMASK;
+	if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
+		field.bits |= ASTNode.HasLocalTypeMASK;
 	}	
 }
 // A P I
 
 public void parse(
-	Initializer ini, 
+	Initializer initializer, 
 	TypeDeclaration type, 
 	CompilationUnitDeclaration unit) {
 	//only parse the method body of md
@@ -7016,13 +5541,14 @@
 	//convert bugs into parse error
 
 	initialize();
-	goForInitializer();
+	goForBlockStatementsopt();
 	nestedMethod[nestedType]++;
-
+	pushOnRealBlockStack(0);
+	
 	referenceContext = type;
 	compilationUnit = unit;
 
-	scanner.resetTo(ini.sourceStart, ini.sourceEnd); // just on the beginning {
+	scanner.resetTo(initializer.bodyStart, initializer.bodyEnd); // just on the beginning {
 	try {
 		parse();
 	} catch (AbortCompilation ex) {
@@ -7031,15 +5557,27 @@
 		nestedMethod[nestedType]--;
 	}
 
+	checkNonNLSAfterBodyEnd(initializer.declarationSourceEnd);
+	
 	if (lastAct == ERROR_ACTION) {
 		return;
 	}
-
-	ini.block = ((Initializer) astStack[astPtr]).block;
+	
+	//refill statements
+	initializer.block.explicitDeclarations = realBlockStack[realBlockPtr--];
+	int length;
+	if ((length = astLengthStack[astLengthPtr--]) > 0) {
+		System.arraycopy(astStack, (astPtr -= length) + 1, initializer.block.statements = new Statement[length], 0, length); 
+	} else {
+		// check whether this block at least contains some comment in it
+		if (!containsComment(initializer.block.sourceStart, initializer.block.sourceEnd)) {
+			initializer.block.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+		}
+	}
 	
 	// mark initializer with local type if one was found during parsing
-	if ((type.bits & AstNode.HasLocalTypeMASK) != 0) {
-		ini.bits |= AstNode.HasLocalTypeMASK;
+	if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
+		initializer.bits |= ASTNode.HasLocalTypeMASK;
 	}	
 }
 // A P I
@@ -7058,13 +5596,14 @@
 		return;
 
 	initialize();
-	goForMethodBody();
+	goForBlockStatementsopt();
 	nestedMethod[nestedType]++;
+	pushOnRealBlockStack(0);
 
 	referenceContext = md;
 	compilationUnit = unit;
 
-	scanner.resetTo(md.sourceEnd + 1, md.declarationSourceEnd); 
+	scanner.resetTo(md.bodyStart, md.bodyEnd);
 	// reset the scanner to parser from { down to }
 	try {
 		parse();
@@ -7074,6 +5613,8 @@
 		nestedMethod[nestedType]--;		
 	}
 
+	checkNonNLSAfterBodyEnd(md.declarationSourceEnd);
+	
 	if (lastAct == ERROR_ACTION) {
 		return;
 	}
@@ -7081,13 +5622,18 @@
 	//refill statements
 	md.explicitDeclarations = realBlockStack[realBlockPtr--];
 	int length;
-	if ((length = astLengthStack[astLengthPtr--]) != 0)
+	if ((length = astLengthStack[astLengthPtr--]) != 0) {
 		System.arraycopy(
 			astStack, 
 			(astPtr -= length) + 1, 
 			md.statements = new Statement[length], 
 			0, 
 			length); 
+	} else {
+		if (!containsComment(md.bodyStart, md.bodyEnd)) {
+			md.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+		}
+	}
 }
 // A P I
 
@@ -7096,29 +5642,7 @@
 	CompilationResult compilationResult) {
 	// parses a compilation unit and manages error handling (even bugs....)
 
-	CompilationUnitDeclaration unit;
-	try {
-		/* automaton initialization */
-		initialize();
-		goForCompilationUnit();
-
-		/* scanner initialization */
-		scanner.setSource(sourceUnit.getContents());
-
-		/* unit creation */
-		referenceContext = 
-			compilationUnit = 
-				new CompilationUnitDeclaration(
-					problemReporter, 
-					compilationResult, 
-					scanner.source.length);
-		/* run automaton */
-		parse();
-	} finally {
-		unit = compilationUnit;
-		compilationUnit = null; // reset parser
-	}
-	return unit;
+	return parse(sourceUnit, compilationResult, -1, -1/*parse without reseting the scanner*/);
 }
 // A P I
 
@@ -7135,9 +5659,16 @@
 		initialize();
 		goForCompilationUnit();
 
-		/* scanner initialization */
-		scanner.setSource(sourceUnit.getContents());
-		scanner.resetTo(start, end);
+		/* scanners initialization */
+		char[] contents = sourceUnit.getContents();
+		scanner.setSource(contents);
+		if (end != -1) scanner.resetTo(start, end);
+		if (this.javadocParser.checkJavadoc) {
+			this.javadocParser.scanner.setSource(contents);
+			if (end != -1) {
+				this.javadocParser.scanner.resetTo(start, end);
+			}
+		}
 		/* unit creation */
 		referenceContext = 
 			compilationUnit = 
@@ -7150,6 +5681,8 @@
 	} finally {
 		unit = compilationUnit;
 		compilationUnit = null; // reset parser
+		// tag unit has having read bodies
+		if (!this.diet) unit.bits |= ASTNode.HasAllMethodBodies;		
 	}
 	return unit;
 }
@@ -7157,6 +5690,8 @@
  * 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.
+ * 
+ * @return ProblemReporter
  */
 public ProblemReporter problemReporter(){
 	if (scanner.recordLineSeparator) {
@@ -7187,7 +5722,7 @@
 		System.arraycopy(oldPos, 0, identifierPositionStack, 0, oldStackLength);
 		identifierPositionStack[identifierPtr] = 
 			(((long) scanner.startPosition) << 32) + (scanner.currentPosition - 1); 
-	};
+	}
 
 	try {
 		identifierLengthStack[++identifierLengthPtr] = 1;
@@ -7198,7 +5733,7 @@
 		identifierLengthStack = new int[oldStackLength + 10];
 		System.arraycopy(oldStack, 0, identifierLengthStack, 0, oldStackLength);
 		identifierLengthStack[identifierLengthPtr] = 1;
-	};
+	}
 
 }
 protected void pushIdentifier(int flag) {
@@ -7216,7 +5751,7 @@
 		identifierLengthStack = new int[oldStackLength + 10];
 		System.arraycopy(oldStack, 0, identifierLengthStack, 0, oldStackLength);
 		identifierLengthStack[identifierLengthPtr] = flag;
-	};
+	}
 
 }
 protected void pushOnAstLengthStack(int pos) {
@@ -7230,7 +5765,7 @@
 		astLengthStack[astLengthPtr] = pos;
 	}
 }
-protected void pushOnAstStack(AstNode node) {
+protected void pushOnAstStack(ASTNode node) {
 	/*add a new obj on top of the ast stack
 	astPtr points on the top*/
 
@@ -7238,8 +5773,8 @@
 		astStack[++astPtr] = node;
 	} catch (IndexOutOfBoundsException e) {
 		int oldStackLength = astStack.length;
-		AstNode[] oldStack = astStack;
-		astStack = new AstNode[oldStackLength + AstStackIncrement];
+		ASTNode[] oldStack = astStack;
+		astStack = new ASTNode[oldStackLength + AstStackIncrement];
 		System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
 		astPtr = oldStackLength;
 		astStack[astPtr] = node;
@@ -7302,6 +5837,19 @@
 		intStack[intPtr] = pos;
 	}
 }
+protected void pushOnRealBlockStack(int i){
+	
+	try {
+		realBlockStack[++realBlockPtr] = i;
+	} catch (IndexOutOfBoundsException e) {
+		//realBlockPtr is correct 
+		int oldStackLength = realBlockStack.length;
+		int oldStack[] = realBlockStack;
+		realBlockStack = new int[oldStackLength + StackIncrement];
+		System.arraycopy(oldStack, 0, realBlockStack, 0, oldStackLength);
+		realBlockStack[realBlockPtr] = i;
+	}
+}
 protected static char[] readTable(String filename) throws java.io.IOException {
 
 	//files are located at Parser.class directory
@@ -7318,6 +5866,7 @@
 		try {
 			stream.close();
 		} catch (IOException e) {
+			// ignore
 		}
 	}
 
@@ -7338,6 +5887,67 @@
 	}
 	return chars;
 }
+protected static byte[] readByteTable(String filename) throws java.io.IOException {
+
+	//files are located at Parser.class directory
+
+	InputStream stream = Parser.class.getResourceAsStream(filename);
+	if (stream == null) {
+		throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
+	}
+	byte[] bytes = null;
+	try {
+		stream = new BufferedInputStream(stream);
+		bytes = Util.getInputStreamAsByteArray(stream, -1);
+	} finally {
+		try {
+			stream.close();
+		} catch (IOException e) {
+			// ignore
+		}
+	}
+	return bytes;
+}
+protected static String[] readReadableNameTable(String filename) {
+	String[] result = new String[name.length];
+
+	ResourceBundle bundle;
+	try {
+		bundle = ResourceBundle.getBundle(filename, Locale.getDefault());
+	} catch(MissingResourceException e) {
+		System.out.println("Missing resource : " + filename.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+		throw e;
+	}
+	for (int i = 0; i < NT_OFFSET + 1; i++) {
+		result[i] = name[i];
+	}
+	for (int i = NT_OFFSET; i < name.length; i++) {
+		try {
+			String n = bundle.getString(name[i]);
+			if(n != null && n.length() > 0) {
+				result[i] = n;
+			} else {
+				result[i] = name[i];
+			}
+		} catch(MissingResourceException e) {
+			result[i] = name[i];
+		}
+	}
+	return result;
+}
+	
+protected static String[] readNameTable(String filename) throws java.io.IOException {
+	char[] contents = readTable(filename);
+	char[][] nameAsChar = CharOperation.splitOn('\n', contents);
+
+	String[] result = new String[nameAsChar.length + 1];
+	result[0] = null;
+	for (int i = 0; i < nameAsChar.length; i++) {
+		result[i + 1] = new String(nameAsChar[i]);
+	}
+	
+	return result;
+}
 public void recoveryExitFromVariable() {
 	if(currentElement != null && currentElement.parent != null) {
 		if(currentElement instanceof RecoveredLocalVariable) {
@@ -7359,132 +5969,41 @@
  */
 public void recoveryTokenCheck() {
 	switch (currentToken) {
-		case TokenNameLBRACE : {
-			RecoveredElement newElement = 
-				currentElement.updateOnOpeningBrace(scanner.currentPosition - 1);
+		case TokenNameLBRACE : 
+			RecoveredElement newElement = null;
+			if(!ignoreNextOpeningBrace) {
+				newElement = currentElement.updateOnOpeningBrace(scanner.startPosition - 1, scanner.currentPosition - 1);
+			}
 			lastCheckPoint = scanner.currentPosition;				
 			if (newElement != null){ // null means nothing happened
 				restartRecovery = true; // opening brace detected
 				currentElement = newElement;
 			}
 			break;
-		}
-		case TokenNameRBRACE : {
-			endPosition = this.flushAnnotationsDefinedPriorTo(scanner.currentPosition - 1);
-			RecoveredElement newElement =
-				currentElement.updateOnClosingBrace(scanner.startPosition, scanner.currentPosition -1);
+		
+		case TokenNameRBRACE : 
+			this.rBraceStart = scanner.startPosition - 1;
+			this.rBraceEnd = scanner.currentPosition - 1;
+			endPosition = this.flushCommentsDefinedPriorTo(this.rBraceEnd);
+			newElement =
+				currentElement.updateOnClosingBrace(scanner.startPosition, this.rBraceEnd);
 				lastCheckPoint = scanner.currentPosition;
 			if (newElement != currentElement){
 				currentElement = newElement;
 			}
-		}
-	}
-}
-protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
-
-	/* remember current scanner position */
-	int startPos = scanner.startPosition;
-	int currentPos = scanner.currentPosition;
-	
-	String[] expectings;
-	String tokenName = name[symbol_index[currentKind]];
-
-	//fetch all "accurate" possible terminals that could recover the error
-	int start, end = start = asi(stack[stateStackTop]);
-	while (asr[end] != 0)
-		end++;
-	int length = end - start;
-	expectings = new String[length];
-	if (length != 0) {
-		char[] indexes = new char[length];
-		System.arraycopy(asr, start, indexes, 0, length);
-		for (int i = 0; i < length; i++) {
-			expectings[i] = name[symbol_index[indexes[i]]];
-		}
-	}
-
-	//if the pb is an EOF, try to tell the user that they are some 
-	if (tokenName.equals(UNEXPECTED_EOF)) {
-		if (!this.checkAndReportBracketAnomalies(problemReporter())) {
-			char[] tokenSource;
-			try {
-				tokenSource = this.scanner.getCurrentTokenSource();
-			} catch (Exception e) {
-				tokenSource = new char[] {};
+			break;
+		case TokenNameSEMICOLON :
+			endStatementPosition = scanner.currentPosition - 1;
+			endPosition = scanner.startPosition - 1; 
+			// fall through
+		default : {
+			if (this.rBraceEnd > this.rBraceSuccessorStart && scanner.currentPosition != scanner.startPosition){
+				this.rBraceSuccessorStart = scanner.startPosition;
 			}
-			problemReporter().parseError(
-				this.scanner.startPosition, 
-				this.scanner.currentPosition - 1, 
-				tokenSource, 
-				tokenName, 
-				expectings); 
-		}
-	} else { //the next test is HEAVILY grammar DEPENDENT.
-		if ((length == 14)
-			&& (expectings[0] == "=") //$NON-NLS-1$
-			&& (expectings[1] == "*=") //$NON-NLS-1$
-			&& (expressionPtr > -1)) {
-				switch(currentKind) {
-					case TerminalTokens.TokenNameSEMICOLON:
-					case TerminalTokens.TokenNamePLUS:
-					case TerminalTokens.TokenNameMINUS:
-					case TerminalTokens.TokenNameDIVIDE:
-					case TerminalTokens.TokenNameREMAINDER:
-					case TerminalTokens.TokenNameMULTIPLY:
-					case TerminalTokens.TokenNameLEFT_SHIFT:
-					case TerminalTokens.TokenNameRIGHT_SHIFT:
-					case TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT:
-					case TerminalTokens.TokenNameLESS:
-					case TerminalTokens.TokenNameGREATER:
-					case TerminalTokens.TokenNameLESS_EQUAL:
-					case TerminalTokens.TokenNameGREATER_EQUAL:
-					case TerminalTokens.TokenNameEQUAL_EQUAL:
-					case TerminalTokens.TokenNameNOT_EQUAL:
-					case TerminalTokens.TokenNameXOR:
-					case TerminalTokens.TokenNameAND:
-					case TerminalTokens.TokenNameOR:
-					case TerminalTokens.TokenNameOR_OR:
-					case TerminalTokens.TokenNameAND_AND:
-						// the ; is not the expected token ==> it ends a statement when an expression is not ended
-						problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
-						break;
-					case TerminalTokens.TokenNameRBRACE :
-						problemReporter().missingSemiColon(expressionStack[expressionPtr]);
-						break;
-					default:
-						char[] tokenSource;
-						try {
-							tokenSource = this.scanner.getCurrentTokenSource();
-						} catch (Exception e) {
-							tokenSource = new char[] {};
-						}
-						problemReporter().parseError(
-							this.scanner.startPosition, 
-							this.scanner.currentPosition - 1, 
-							tokenSource, 
-							tokenName, 
-							expectings); 
-						this.checkAndReportBracketAnomalies(problemReporter());
-				}
-		} else {
-			char[] tokenSource;
-			try {
-				tokenSource = this.scanner.getCurrentTokenSource();
-			} catch (Exception e) {
-				tokenSource = new char[] {};
-			}
-			problemReporter().parseError(
-				this.scanner.startPosition, 
-				this.scanner.currentPosition - 1, 
-				tokenSource, 
-				tokenName, 
-				expectings); 
-			this.checkAndReportBracketAnomalies(problemReporter());
+			break;
 		}
 	}
-	/* reset scanner where it was */
-	scanner.startPosition = startPos;
-	scanner.currentPosition = currentPos;
+	ignoreNextOpeningBrace = false;
 }
 protected void resetModifiers() {
 	modifiers = AccDefault;
@@ -7525,7 +6044,9 @@
 	this.resetStacks();
 	
 	/* attempt to move checkpoint location */
-	if (!this.moveRecoveryCheckpoint()) return false;
+	if (!this.moveRecoveryCheckpoint()) {
+		return false;
+	}
 
 	// only look for headers
 	if (referenceContext instanceof CompilationUnitDeclaration){
@@ -7560,40 +6081,40 @@
 	/* attempt to reset state in order to resume to parse loop */
 	return this.resumeAfterRecovery();
 }
-protected static int tAction(int state, int sym) {
-	return action[check(state + sym) == sym ? state + sym : state];
+public static int tAction(int state, int sym) {
+	return term_action[term_check[base_action[state]+sym] == sym ? base_action[state] + sym : base_action[state]];
 }
 public String toString() {
 
 	String s = "identifierStack : char[][] = {"; //$NON-NLS-1$
 	for (int i = 0; i <= identifierPtr; i++) {
 		s = s + "\"" + String.valueOf(identifierStack[i]) + "\","; //$NON-NLS-1$ //$NON-NLS-2$
-	};
+	}
 	s = s + "}\n"; //$NON-NLS-1$
 
 	s = s + "identierLengthStack : int[] = {"; //$NON-NLS-1$
 	for (int i = 0; i <= identifierLengthPtr; i++) {
 		s = s + identifierLengthStack[i] + ","; //$NON-NLS-1$
-	};
+	}
 	s = s + "}\n"; //$NON-NLS-1$
 
 	s = s + "astLengthStack : int[] = {"; //$NON-NLS-1$
 	for (int i = 0; i <= astLengthPtr; i++) {
 		s = s + astLengthStack[i] + ","; //$NON-NLS-1$
-	};
+	}
 	s = s + "}\n"; //$NON-NLS-1$
 	s = s + "astPtr : int = " + String.valueOf(astPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
 
 	s = s + "intStack : int[] = {"; //$NON-NLS-1$
 	for (int i = 0; i <= intPtr; i++) {
 		s = s + intStack[i] + ","; //$NON-NLS-1$
-	};
+	}
 	s = s + "}\n"; //$NON-NLS-1$
 
 	s = s + "expressionLengthStack : int[] = {"; //$NON-NLS-1$
 	for (int i = 0; i <= expressionLengthPtr; i++) {
 		s = s + expressionLengthStack[i] + ","; //$NON-NLS-1$
-	};
+	}
 	s = s + "}\n"; //$NON-NLS-1$
 
 	s = s + "expressionPtr : int = " + String.valueOf(expressionPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
index 4907ff9..c39e8d9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
@@ -15,19 +15,22 @@
 
 public interface ParserBasicInformation {
 
-    public final static int
-      NT_OFFSET         = 308,
-      SCOPE_UBOUND      = -1,
-      SCOPE_SIZE        = 0,
-      LA_STATE_OFFSET   = 17759,
+	public final static int
+      ERROR_SYMBOL      = 105,
+      MAX_NAME_LENGTH   = 36,
+      NUM_STATES        = 597,
+      NT_OFFSET         = 105,
+      SCOPE_UBOUND      = 63,
+      SCOPE_SIZE        = 64,
+      LA_STATE_OFFSET   = 5981,
       MAX_LA            = 1,
-      NUM_RULES         = 437,
-      NUM_TERMINALS     = 104,
-      NUM_NON_TERMINALS = 204,
+      NUM_RULES         = 433,
+      NUM_TERMINALS     = 105,
+      NUM_NON_TERMINALS = 203,
       NUM_SYMBOLS       = 308,
-      START_STATE       = 16034,
-      EOFT_SYMBOL       = 114,
-      EOLT_SYMBOL       = 105,
-      ACCEPT_ACTION     = 17758,
-      ERROR_ACTION      = 17759;
+      START_STATE       = 529,
+      EOFT_SYMBOL       = 54,
+      EOLT_SYMBOL       = 54,
+      ACCEPT_ACTION     = 5980,
+      ERROR_ACTION      = 5981;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java
index a4bdb7c..30ac6c1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java
@@ -15,7 +15,7 @@
  */
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Block;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
@@ -41,21 +41,21 @@
 /*
  * Record a nested block declaration 
  */
-public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalance) {
+public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
 
 	/* do not consider a nested block starting passed the block end (if set)
 		it must be belonging to an enclosing block */
-	if (blockDeclaration.sourceEnd != 0 
-		&& nestedBlockDeclaration.sourceStart > blockDeclaration.sourceEnd){
-		return this.parent.add(nestedBlockDeclaration, bracketBalance);
+	if (this.blockDeclaration.sourceEnd != 0 
+		&& nestedBlockDeclaration.sourceStart > this.blockDeclaration.sourceEnd){
+		return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
 	}
 			
-	RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalance);
+	RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue);
 
 	// if we have a pending Argument, promote it into the new block
-	if (pendingArgument != null){
-		element.attach(pendingArgument);
-		pendingArgument = null;
+	if (this.pendingArgument != null){
+		element.attach(this.pendingArgument);
+		this.pendingArgument = null;
 	}
 	this.attach(element);
 	if (nestedBlockDeclaration.sourceEnd == 0) return element;
@@ -64,13 +64,13 @@
 /*
  * Record a local declaration 
  */
-public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalance) {
-	return this.add(localDeclaration, bracketBalance, false);
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
+	return this.add(localDeclaration, bracketBalanceValue, false);
 }
 /*
  * Record a local declaration 
  */
-public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalance, boolean delegatedByParent) {
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue, boolean delegatedByParent) {
 
 	/* local variables inside method can only be final and non void */
 /*	
@@ -90,20 +90,20 @@
 */	
 		/* do not consider a local variable starting passed the block end (if set)
 		it must be belonging to an enclosing block */
-	if (blockDeclaration.sourceEnd != 0 
-		&& localDeclaration.declarationSourceStart > blockDeclaration.sourceEnd){
+	if (this.blockDeclaration.sourceEnd != 0 
+		&& localDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){
 
 		if (delegatedByParent){
 			return this; //ignore
 		} else {
-			return this.parent.add(localDeclaration, bracketBalance);
+			return this.parent.add(localDeclaration, bracketBalanceValue);
 		}
 	}
 
-	RecoveredLocalVariable element = new RecoveredLocalVariable(localDeclaration, this, bracketBalance);
+	RecoveredLocalVariable element = new RecoveredLocalVariable(localDeclaration, this, bracketBalanceValue);
 
 	if (localDeclaration instanceof Argument){
-		pendingArgument = element;
+		this.pendingArgument = element;
 		return this;
 	}
 	
@@ -114,55 +114,55 @@
 /*
  * Record a statement declaration 
  */
-public RecoveredElement add(Statement statement, int bracketBalance) {
-	return this.add(statement, bracketBalance, false);
+public RecoveredElement add(Statement stmt, int bracketBalanceValue) {
+	return this.add(stmt, bracketBalanceValue, false);
 }
 
 /*
  * Record a statement declaration 
  */
-public RecoveredElement add(Statement statement, int bracketBalance, boolean delegatedByParent) {
+public RecoveredElement add(Statement stmt, int bracketBalanceValue, boolean delegatedByParent) {
 
 	/* do not consider a nested block starting passed the block end (if set)
 		it must be belonging to an enclosing block */
-	if (blockDeclaration.sourceEnd != 0 
-		&& statement.sourceStart > blockDeclaration.sourceEnd){
+	if (this.blockDeclaration.sourceEnd != 0 
+		&& stmt.sourceStart > this.blockDeclaration.sourceEnd){
 			
 		if (delegatedByParent){
 			return this; //ignore
 		} else {
-			return this.parent.add(statement, bracketBalance);
+			return this.parent.add(stmt, bracketBalanceValue);
 		}			
 	}
 			
-	RecoveredStatement element = new RecoveredStatement(statement, this, bracketBalance);
+	RecoveredStatement element = new RecoveredStatement(stmt, this, bracketBalanceValue);
 	this.attach(element);
-	if (statement.sourceEnd == 0) return element;
+	if (stmt.sourceEnd == 0) return element;
 	return this;	
 }
 /*
  * Addition of a type to an initializer (act like inside method body)
  */
-public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance) {
-	return this.add(typeDeclaration, bracketBalance, false);
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
+	return this.add(typeDeclaration, bracketBalanceValue, false);
 }
 /*
  * Addition of a type to an initializer (act like inside method body)
  */
-public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance, boolean delegatedByParent) {
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue, boolean delegatedByParent) {
 
 	/* do not consider a type starting passed the block end (if set)
 		it must be belonging to an enclosing block */
-	if (blockDeclaration.sourceEnd != 0 
-		&& typeDeclaration.declarationSourceStart > blockDeclaration.sourceEnd){
+	if (this.blockDeclaration.sourceEnd != 0 
+		&& typeDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){
 		if (delegatedByParent){
 			return this; //ignore
 		} else {
-			return this.parent.add(typeDeclaration, bracketBalance);
+			return this.parent.add(typeDeclaration, bracketBalanceValue);
 		}
 	}
 			
-	RecoveredStatement element = new RecoveredType(typeDeclaration, this, bracketBalance);
+	RecoveredStatement element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
 	this.attach(element);
 	if (typeDeclaration.declarationSourceEnd == 0) return element;
 	return this;
@@ -172,31 +172,31 @@
  */
 void attach(RecoveredStatement recoveredStatement) {
 
-	if (statements == null) {
-		statements = new RecoveredStatement[5];
-		statementCount = 0;
+	if (this.statements == null) {
+		this.statements = new RecoveredStatement[5];
+		this.statementCount = 0;
 	} else {
-		if (statementCount == statements.length) {
+		if (this.statementCount == this.statements.length) {
 			System.arraycopy(
-				statements, 
+				this.statements, 
 				0, 
-				(statements = new RecoveredStatement[2 * statementCount]), 
+				(this.statements = new RecoveredStatement[2 * this.statementCount]), 
 				0, 
-				statementCount); 
+				this.statementCount); 
 		}
 	}
-	statements[statementCount++] = recoveredStatement;
+	this.statements[this.statementCount++] = recoveredStatement;
 }
 /* 
  * Answer the associated parsed structure
  */
-public AstNode parseTree(){
-	return blockDeclaration;
+public ASTNode parseTree(){
+	return this.blockDeclaration;
 }
 public String toString(int tab) {
 	StringBuffer result = new StringBuffer(tabString(tab));
 	result.append("Recovered block:\n"); //$NON-NLS-1$
-	result.append(blockDeclaration.toString(tab + 1));
+	this.blockDeclaration.print(tab + 1, result);
 	if (this.statements != null) {
 		for (int i = 0; i < this.statementCount; i++) {
 			result.append("\n"); //$NON-NLS-1$
@@ -211,14 +211,14 @@
 public Block updatedBlock(){
 
 	// if block was not marked to be preserved or empty, then ignore it
-	if (!preserveContent || statementCount == 0) return null;
+	if (!this.preserveContent || this.statementCount == 0) return null;
 
-	Statement[] updatedStatements = new Statement[statementCount];
+	Statement[] updatedStatements = new Statement[this.statementCount];
 	int updatedCount = 0;
 	
 	// only collect the non-null updated statements
-	for (int i = 0; i < statementCount; i++){
-		Statement updatedStatement = statements[i].updatedStatement();
+	for (int i = 0; i < this.statementCount; i++){
+		Statement updatedStatement = this.statements[i].updatedStatement();
 		if (updatedStatement != null){
 			updatedStatements[updatedCount++] = updatedStatement;
 		}
@@ -226,14 +226,14 @@
 	if (updatedCount == 0) return null; // not interesting block
 
 	// resize statement collection if necessary
-	if (updatedCount != statementCount){
-		blockDeclaration.statements = new Statement[updatedCount];
-		System.arraycopy(updatedStatements, 0, blockDeclaration.statements, 0, updatedCount);
+	if (updatedCount != this.statementCount){
+		this.blockDeclaration.statements = new Statement[updatedCount];
+		System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount);
 	} else {
-		blockDeclaration.statements = updatedStatements;
+		this.blockDeclaration.statements = updatedStatements;
 	}
 
-	return blockDeclaration;
+	return this.blockDeclaration;
 }
 /*
  * Rebuild a statement from the nested structure which is in scope
@@ -247,19 +247,19 @@
  * in which case both the currentElement is exited
  */
 public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
-	if ((--bracketBalance <= 0) && (parent != null)){
-		this.updateSourceEndIfNecessary(braceEnd);
+	if ((--this.bracketBalance <= 0) && (this.parent != null)){
+		this.updateSourceEndIfNecessary(braceStart, braceEnd);
 
 		/* if the block is the method body, then it closes the method too */
 		RecoveredMethod method = enclosingMethod();
 		if (method != null && method.methodBody == this){
-			return parent.updateOnClosingBrace(braceStart, braceEnd);
+			return this.parent.updateOnClosingBrace(braceStart, braceEnd);
 		}
 		RecoveredInitializer initializer = enclosingInitializer();
 		if (initializer != null && initializer.initializerBody == this){
-			return parent.updateOnClosingBrace(braceStart, braceEnd);
+			return this.parent.updateOnClosingBrace(braceStart, braceEnd);
 		}
-		return parent;
+		return this.parent;
 	}
 	return this;
 }
@@ -267,7 +267,7 @@
  * An opening brace got consumed, might be the expected opening one of the current element,
  * in which case the bodyStart is updated.
  */
-public RecoveredElement updateOnOpeningBrace(int currentPosition){
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
 
 	// create a nested block
 	Block block = new Block(0);
@@ -287,14 +287,14 @@
 public Statement updateStatement(){
 
 	// if block was closed or empty, then ignore it
-	if (this.blockDeclaration.sourceEnd != 0 || statementCount == 0) return null;
+	if (this.blockDeclaration.sourceEnd != 0 || this.statementCount == 0) return null;
 
-	Statement[] updatedStatements = new Statement[statementCount];
+	Statement[] updatedStatements = new Statement[this.statementCount];
 	int updatedCount = 0;
 	
 	// only collect the non-null updated statements
-	for (int i = 0; i < statementCount; i++){
-		Statement updatedStatement = statements[i].updatedStatement();
+	for (int i = 0; i < this.statementCount; i++){
+		Statement updatedStatement = this.statements[i].updatedStatement();
 		if (updatedStatement != null){
 			updatedStatements[updatedCount++] = updatedStatement;
 		}
@@ -302,20 +302,20 @@
 	if (updatedCount == 0) return null; // not interesting block
 
 	// resize statement collection if necessary
-	if (updatedCount != statementCount){
-		blockDeclaration.statements = new Statement[updatedCount];
-		System.arraycopy(updatedStatements, 0, blockDeclaration.statements, 0, updatedCount);
+	if (updatedCount != this.statementCount){
+		this.blockDeclaration.statements = new Statement[updatedCount];
+		System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount);
 	} else {
-		blockDeclaration.statements = updatedStatements;
+		this.blockDeclaration.statements = updatedStatements;
 	}
 
-	return blockDeclaration;
+	return this.blockDeclaration;
 }
 
 /*
  * Record a field declaration 
  */
-public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalance) {
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
 
 	/* local variables inside method can only be final and non void */
 	char[][] fieldTypeName; 
@@ -324,14 +324,14 @@
 		|| ((fieldTypeName = fieldDeclaration.type.getTypeName()).length == 1 // non void
 			&& CharOperation.equals(fieldTypeName[0], VoidBinding.sourceName()))){ 
 		this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1));
-		return this.parent.add(fieldDeclaration, bracketBalance);
+		return this.parent.add(fieldDeclaration, bracketBalanceValue);
 	}
 	
 	/* do not consider a local variable starting passed the block end (if set)
 		it must be belonging to an enclosing block */
-	if (blockDeclaration.sourceEnd != 0 
-		&& fieldDeclaration.declarationSourceStart > blockDeclaration.sourceEnd){
-		return this.parent.add(fieldDeclaration, bracketBalance);
+	if (this.blockDeclaration.sourceEnd != 0 
+		&& fieldDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){
+		return this.parent.add(fieldDeclaration, bracketBalanceValue);
 	}
 
 	// ignore the added field, since indicates a local variable behind recovery point
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java
index 0d13637..ca80ccc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java
@@ -14,7 +14,7 @@
  * Internal structure for parsing recovery 
  */
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Block;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
@@ -39,92 +39,92 @@
 /*
  *	Record a method declaration
  */
-public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalance) {
+public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
 
 	/* default behavior is to delegate recording to parent if any */
-	if (parent == null) {
+	if (this.parent == null) {
 		return this; // ignore
 	} else {
 		this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(methodDeclaration.declarationSourceStart - 1));	
-		return this.parent.add(methodDeclaration, bracketBalance);
+		return this.parent.add(methodDeclaration, bracketBalanceValue);
 	}
 }
 /*
  * Record a nested block declaration
  */
-public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalance) {
+public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
 
 	/* default behavior is to delegate recording to parent if any */
-	if (parent == null) {
+	if (this.parent == null) {
 		return this; // ignore
 	} else {
 		this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(nestedBlockDeclaration.sourceStart - 1));	
-		return this.parent.add(nestedBlockDeclaration, bracketBalance);
+		return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
 	}
 }
 /*
  * Record a field declaration
  */
-public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalance) {
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
 
 	/* default behavior is to delegate recording to parent if any */
-	if (parent == null) {
+	if (this.parent == null) {
 		return this; // ignore
 	} else {
 		this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1));	
-		return this.parent.add(fieldDeclaration, bracketBalance);
+		return this.parent.add(fieldDeclaration, bracketBalanceValue);
 	}
 }
 /*
  *	Record an import reference
  */
-public RecoveredElement add(ImportReference importReference, int bracketBalance){
+public RecoveredElement add(ImportReference importReference, int bracketBalanceValue){
 
 	/* default behavior is to delegate recording to parent if any */
-	if (parent == null) {
+	if (this.parent == null) {
 		return this; // ignore
 	} else {
 		this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(importReference.declarationSourceStart - 1));	
-		return this.parent.add(importReference, bracketBalance);
+		return this.parent.add(importReference, bracketBalanceValue);
 	}
 }
 /*
  * Record a local declaration
  */
-public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalance) {
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
 
 	/* default behavior is to delegate recording to parent if any */
-	if (parent == null) {
+	if (this.parent == null) {
 		return this; // ignore
 	} else {
 		this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1));	
-		return this.parent.add(localDeclaration, bracketBalance);
+		return this.parent.add(localDeclaration, bracketBalanceValue);
 	}
 }
 /*
  * Record a statement
  */
-public RecoveredElement add(Statement statement, int bracketBalance) {
+public RecoveredElement add(Statement statement, int bracketBalanceValue) {
 
 	/* default behavior is to delegate recording to parent if any */
-	if (parent == null) {
+	if (this.parent == null) {
 		return this; // ignore
 	} else {
 		this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(statement.sourceStart - 1));	
-		return this.parent.add(statement, bracketBalance);
+		return this.parent.add(statement, bracketBalanceValue);
 	}
 }
 /*
  *	Record a type declaration
  */
-public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance){
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue){
 
 	/* default behavior is to delegate recording to parent if any */
-	if (parent == null) {
+	if (this.parent == null) {
 		return this; // ignore
 	} else {
 		this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1));	
-		return this.parent.add(typeDeclaration, bracketBalance);
+		return this.parent.add(typeDeclaration, bracketBalanceValue);
 	}
 }
 /*
@@ -191,7 +191,7 @@
 /* 
  * Answer the associated parsed structure
  */
-public AstNode parseTree(){
+public ASTNode parseTree(){
 	return null;
 }
 /*
@@ -285,15 +285,16 @@
  * is about to disappear because of restarting recovery
  */
 public void updateFromParserState(){
+	// default implementation: do nothing
 }
 /*
  * A closing brace got consumed, might have closed the current element,
  * in which case both the currentElement is exited
  */
 public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
-	if ((--bracketBalance <= 0) && (parent != null)){
-		this.updateSourceEndIfNecessary(braceEnd);
-		return parent;
+	if ((--this.bracketBalance <= 0) && (this.parent != null)){
+		this.updateSourceEndIfNecessary(braceStart, braceEnd);
+		return this.parent;
 	}
 	return this;
 }
@@ -301,9 +302,10 @@
  * An opening brace got consumed, might be the expected opening one of the current element,
  * in which case the bodyStart is updated.
  */
-public RecoveredElement updateOnOpeningBrace(int braceEnd){
+/*public RecoveredElement updateOnOpeningBrace(int braceEnd){return null;}*/
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
 
-	if (bracketBalance++ == 0){
+	if (this.bracketBalance++ == 0){
 		this.updateBodyStart(braceEnd + 1);
 		return this;
 	}
@@ -313,10 +315,15 @@
  * Final update the corresponding parse node
  */
 public void updateParseTree(){
+	// default implementation: do nothing
 }
 /*
  * Update the declarationSourceEnd of the corresponding parse node
  */
+public void updateSourceEndIfNecessary(int braceStart, int braceEnd){
+	// default implementation: do nothing
+}
 public void updateSourceEndIfNecessary(int sourceEnd){
+	this.updateSourceEndIfNecessary(sourceEnd + 1, sourceEnd);
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java
index 7924977..fd600d1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java
@@ -13,9 +13,8 @@
 /**
  * Internal field structure for parsing recovery 
  */
-import org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
@@ -40,10 +39,10 @@
  * Record an expression statement if field is expecting an initialization expression,
  * used for completion inside field initializers.
  */
-public RecoveredElement add(Statement statement, int bracketBalance) {
+public RecoveredElement add(Statement statement, int bracketBalanceValue) {
 
 	if (this.alreadyCompletedFieldInitialization || !(statement instanceof Expression)) {
-		return super.add(statement, bracketBalance);
+		return super.add(statement, bracketBalanceValue);
 	} else {
 		this.alreadyCompletedFieldInitialization = true;
 		this.fieldDeclaration.initialization = (Expression)statement;
@@ -57,12 +56,12 @@
  * and the type is an anonymous type.
  * Used for completion inside field initializers.
  */
-public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance) {
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
 
 	if (this.alreadyCompletedFieldInitialization 
-			|| !(typeDeclaration instanceof AnonymousLocalTypeDeclaration)
+			|| ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) == 0)
 			|| (this.fieldDeclaration.declarationSourceEnd != 0 && typeDeclaration.sourceStart > this.fieldDeclaration.declarationSourceEnd)) {
-		return super.add(typeDeclaration, bracketBalance);
+		return super.add(typeDeclaration, bracketBalanceValue);
 	} else { 
 		// Prepare anonymous type list
 		if (this.anonymousTypes == null) {
@@ -79,7 +78,7 @@
 			}
 		}
 		// Store type declaration as an anonymous type
-		RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalance);
+		RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
 		this.anonymousTypes[this.anonymousTypeCount++] = element;
 		return element;
 	}
@@ -87,7 +86,7 @@
 /* 
  * Answer the associated parsed structure
  */
-public AstNode parseTree(){
+public ASTNode parseTree(){
 	return fieldDeclaration;
 }
 /*
@@ -99,7 +98,7 @@
 public String toString(int tab){
 	StringBuffer buffer = new StringBuffer(tabString(tab));
 	buffer.append("Recovered field:\n"); //$NON-NLS-1$
-	buffer.append(fieldDeclaration.toString(tab + 1));
+	buffer.append(fieldDeclaration.print(tab + 1, buffer));
 	if (this.anonymousTypes != null) {
 		for (int i = 0; i < this.anonymousTypeCount; i++){
 			buffer.append("\n"); //$NON-NLS-1$
@@ -113,11 +112,10 @@
 	if (this.anonymousTypes != null && fieldDeclaration.initialization == null) {
 		for (int i = 0; i < this.anonymousTypeCount; i++){
 			if (anonymousTypes[i].preserveContent){
-				fieldDeclaration.initialization = 
-					((AnonymousLocalTypeDeclaration)this.anonymousTypes[i].updatedTypeDeclaration()).allocation;
+				fieldDeclaration.initialization = this.anonymousTypes[i].updatedTypeDeclaration().allocation;
 			}
 		}
-		if (this.anonymousTypeCount > 0) fieldDeclaration.bits |= AstNode.HasLocalTypeMASK;
+		if (this.anonymousTypeCount > 0) fieldDeclaration.bits |= ASTNode.HasLocalTypeMASK;
 	}
 	return fieldDeclaration;
 }
@@ -142,7 +140,7 @@
  * An opening brace got consumed, might be the expected opening one of the current element,
  * in which case the bodyStart is updated.
  */
-public RecoveredElement updateOnOpeningBrace(int currentPosition){
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
 	if (fieldDeclaration.declarationSourceEnd == 0 
 		&& fieldDeclaration.type instanceof ArrayTypeReference
 		&& !alreadyCompletedFieldInitialization){
@@ -150,8 +148,8 @@
 		return null; // no update is necessary	(array initializer)
 	}
 	// might be an array initializer
-	this.updateSourceEndIfNecessary(currentPosition - 1);	
-	return this.parent.updateOnOpeningBrace(currentPosition);	
+	this.updateSourceEndIfNecessary(braceStart - 1, braceEnd - 1);	
+	return this.parent.updateOnOpeningBrace(braceStart, braceEnd);	
 }
 public void updateParseTree(){
 	this.updatedFieldDeclaration();
@@ -159,10 +157,10 @@
 /*
  * Update the declarationSourceEnd of the corresponding parse node
  */
-public void updateSourceEndIfNecessary(int sourceEnd){
+public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
 	if (this.fieldDeclaration.declarationSourceEnd == 0) {
-		this.fieldDeclaration.declarationSourceEnd = sourceEnd;
-		this.fieldDeclaration.declarationEnd = sourceEnd;
+		this.fieldDeclaration.declarationSourceEnd = bodyEnd;
+		this.fieldDeclaration.declarationEnd = bodyEnd;
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredImport.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredImport.java
index e6a8aa3..495c25a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredImport.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredImport.java
@@ -13,7 +13,7 @@
 /**
  * Internal import structure for parsing recovery 
  */
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
 
 public class RecoveredImport extends RecoveredElement {
@@ -26,7 +26,7 @@
 /* 
  * Answer the associated parsed structure
  */
-public AstNode parseTree(){
+public ASTNode parseTree(){
 	return importReference;
 }
 /*
@@ -48,10 +48,10 @@
 /*
  * Update the declarationSourceEnd of the corresponding parse node
  */
-public void updateSourceEndIfNecessary(int sourceEnd){
+public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
 	if (this.importReference.declarationSourceEnd == 0) {
-		this.importReference.declarationSourceEnd = sourceEnd;
-		this.importReference.declarationEnd = sourceEnd;
+		this.importReference.declarationSourceEnd = bodyEnd;
+		this.importReference.declarationEnd = bodyEnd;
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
index 1eaf4b0..83bceaf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
@@ -14,12 +14,11 @@
  * Internal initializer structure for parsing recovery 
  */
 import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Block;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Initializer;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.LocalTypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
@@ -41,7 +40,7 @@
 /*
  * Record a nested block declaration
  */
-public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalance) {
+public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
 
 	/* default behavior is to delegate recording to parent if any,
 	do not consider elements passed the known end (if set)
@@ -53,7 +52,7 @@
 		if (this.parent == null){
 			return this; // ignore
 		} else {
-			return this.parent.add(nestedBlockDeclaration, bracketBalance);
+			return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
 		}
 	}
 	/* consider that if the opening brace was not found, it is there */
@@ -62,14 +61,14 @@
 		this.bracketBalance++;
 	}
 
-	initializerBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalance);
+	initializerBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue);
 	if (nestedBlockDeclaration.sourceEnd == 0) return initializerBody;
 	return this;
 }
 /*
  * Record a field declaration (act like inside method body)
  */
-public RecoveredElement add(FieldDeclaration newFieldDeclaration, int bracketBalance) {
+public RecoveredElement add(FieldDeclaration newFieldDeclaration, int bracketBalanceValue) {
 
 	/* local variables inside initializer can only be final and non void */
 	char[][] fieldTypeName;
@@ -81,7 +80,7 @@
 			return this; // ignore
 		} else {
 			this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(newFieldDeclaration.declarationSourceStart - 1));
-			return this.parent.add(newFieldDeclaration, bracketBalance);
+			return this.parent.add(newFieldDeclaration, bracketBalanceValue);
 		}
 	}
 
@@ -95,7 +94,7 @@
 		if (this.parent == null) {
 			return this; // ignore
 		} else {
-			return this.parent.add(newFieldDeclaration, bracketBalance);
+			return this.parent.add(newFieldDeclaration, bracketBalanceValue);
 		}
 	}
 	// still inside initializer, treat as local variable
@@ -104,7 +103,7 @@
 /*
  * Record a local declaration - regular method should have been created a block body
  */
-public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalance) {
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
 
 	/* do not consider a type starting passed the type end (if set)
 		it must be belonging to an enclosing type */
@@ -113,19 +112,19 @@
 		if (parent == null) {
 			return this; // ignore
 		} else {
-			return this.parent.add(localDeclaration, bracketBalance);
+			return this.parent.add(localDeclaration, bracketBalanceValue);
 		}
 	}
 	/* method body should have been created */
 	Block block = new Block(0);
-	block.sourceStart = ((Initializer)fieldDeclaration).bodyStart;
+	block.sourceStart = ((Initializer)fieldDeclaration).sourceStart;
 	RecoveredElement element = this.add(block, 1);
-	return element.add(localDeclaration, bracketBalance);	
+	return element.add(localDeclaration, bracketBalanceValue);	
 }
 /*
  * Record a statement - regular method should have been created a block body
  */
-public RecoveredElement add(Statement statement, int bracketBalance) {
+public RecoveredElement add(Statement statement, int bracketBalanceValue) {
 
 	/* do not consider a statement starting passed the initializer end (if set)
 		it must be belonging to an enclosing type */
@@ -134,16 +133,16 @@
 		if (parent == null) {
 			return this; // ignore
 		} else {
-			return this.parent.add(statement, bracketBalance);
+			return this.parent.add(statement, bracketBalanceValue);
 		}
 	}
 	/* initializer body should have been created */
 	Block block = new Block(0);
-	block.sourceStart = ((Initializer)fieldDeclaration).bodyStart;
+	block.sourceStart = ((Initializer)fieldDeclaration).sourceStart;
 	RecoveredElement element = this.add(block, 1);
-	return element.add(statement, bracketBalance);	
+	return element.add(statement, bracketBalanceValue);	
 }
-public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance) {
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
 
 	/* do not consider a type starting passed the type end (if set)
 		it must be belonging to an enclosing type */
@@ -152,15 +151,15 @@
 		if (parent == null) {
 			return this; // ignore
 		} else {
-			return this.parent.add(typeDeclaration, bracketBalance);
+			return this.parent.add(typeDeclaration, bracketBalanceValue);
 		}
 	}
-	if (typeDeclaration instanceof LocalTypeDeclaration){
+	if ((typeDeclaration.bits & ASTNode.IsLocalTypeMASK) != 0){
 		/* method body should have been created */
 		Block block = new Block(0);
-		block.sourceStart = ((Initializer)fieldDeclaration).bodyStart;
+		block.sourceStart = ((Initializer)fieldDeclaration).sourceStart;
 		RecoveredElement element = this.add(block, 1);
-		return element.add(typeDeclaration, bracketBalance);	
+		return element.add(typeDeclaration, bracketBalanceValue);	
 	}	
 	if (localTypes == null) {
 		localTypes = new RecoveredType[5];
@@ -175,7 +174,7 @@
 				localTypeCount); 
 		}
 	}
-	RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalance);
+	RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
 	localTypes[localTypeCount++] = element;
 
 	/* consider that if the opening brace was not found, it is there */
@@ -188,7 +187,7 @@
 public String toString(int tab) {
 	StringBuffer result = new StringBuffer(tabString(tab));
 	result.append("Recovered initializer:\n"); //$NON-NLS-1$
-	result.append(this.fieldDeclaration.toString(tab + 1));
+	result.append(this.fieldDeclaration.print(tab + 1, result));
 	if (this.initializerBody != null) {
 		result.append("\n"); //$NON-NLS-1$
 		result.append(this.initializerBody.toString(tab + 1));
@@ -202,7 +201,7 @@
 		if (block != null){
 			((Initializer)fieldDeclaration).block = block;
 		}
-		if (this.localTypeCount > 0) fieldDeclaration.bits |= AstNode.HasLocalTypeMASK;
+		if (this.localTypeCount > 0) fieldDeclaration.bits |= ASTNode.HasLocalTypeMASK;
 
 	}	
 	if (fieldDeclaration.sourceEnd == 0){
@@ -216,7 +215,7 @@
  */
 public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
 	if ((--bracketBalance <= 0) && (parent != null)){
-		this.updateSourceEndIfNecessary(braceEnd);
+		this.updateSourceEndIfNecessary(braceStart, braceEnd);
 		return parent;
 	}
 	return this;
@@ -225,18 +224,26 @@
  * An opening brace got consumed, might be the expected opening one of the current element,
  * in which case the bodyStart is updated.
  */
-public RecoveredElement updateOnOpeningBrace(int currentPosition){
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
 	bracketBalance++;
 	return this; // request to restart
 }
 /*
  * Update the declarationSourceEnd of the corresponding parse node
  */
-public void updateSourceEndIfNecessary(int sourceEnd){
+public void updateSourceEndIfNecessary(int braceStart, int braceEnd){
 	if (this.fieldDeclaration.declarationSourceEnd == 0) {
-		this.fieldDeclaration.sourceEnd = sourceEnd;
-		this.fieldDeclaration.declarationSourceEnd = sourceEnd;
-		this.fieldDeclaration.declarationEnd = sourceEnd;
+		Initializer initializer = (Initializer)fieldDeclaration;
+		if(parser().rBraceSuccessorStart >= braceEnd) {
+			initializer.declarationSourceEnd = parser().rBraceEnd;
+			initializer.bodyEnd = parser().rBraceStart;
+		} else {
+			initializer.declarationSourceEnd = braceEnd;
+			initializer.bodyEnd  = braceStart - 1;
+		}
+		if(initializer.block != null) {
+			initializer.block.sourceEnd = initializer.declarationSourceEnd;
+		}
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredLocalVariable.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredLocalVariable.java
index b3bd778..ca16192 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredLocalVariable.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredLocalVariable.java
@@ -14,7 +14,7 @@
  * Internal local variable structure for parsing recovery 
  */
 import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
@@ -31,22 +31,22 @@
 /*
  * Record an expression statement if local variable is expecting an initialization expression. 
  */
-public RecoveredElement add(Statement statement, int bracketBalance) {
+public RecoveredElement add(Statement stmt, int bracketBalanceValue) {
 
-	if (this.alreadyCompletedLocalInitialization || !(statement instanceof Expression)) {
-		return super.add(statement, bracketBalance);
+	if (this.alreadyCompletedLocalInitialization || !(stmt instanceof Expression)) {
+		return super.add(stmt, bracketBalanceValue);
 	} else {
 		this.alreadyCompletedLocalInitialization = true;
-		this.localDeclaration.initialization = (Expression)statement;
-		this.localDeclaration.declarationSourceEnd = statement.sourceEnd;
-		this.localDeclaration.declarationEnd = statement.sourceEnd;
+		this.localDeclaration.initialization = (Expression)stmt;
+		this.localDeclaration.declarationSourceEnd = stmt.sourceEnd;
+		this.localDeclaration.declarationEnd = stmt.sourceEnd;
 		return this;
 	}
 }
 /* 
  * Answer the associated parsed structure
  */
-public AstNode parseTree(){
+public ASTNode parseTree(){
 	return localDeclaration;
 }
 /*
@@ -56,7 +56,7 @@
 	return this.localDeclaration.declarationSourceEnd;
 }
 public String toString(int tab) {
-	return tabString(tab) + "Recovered local variable:\n" + localDeclaration.toString(tab + 1); //$NON-NLS-1$
+	return tabString(tab) + "Recovered local variable:\n" + localDeclaration.print(tab + 1, new StringBuffer(10)); //$NON-NLS-1$
 }
 public Statement updatedStatement(){
 	return localDeclaration;
@@ -82,7 +82,7 @@
  * An opening brace got consumed, might be the expected opening one of the current element,
  * in which case the bodyStart is updated.
  */
-public RecoveredElement updateOnOpeningBrace(int currentPosition){
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
 	if (localDeclaration.declarationSourceEnd == 0 
 		&& localDeclaration.type instanceof ArrayTypeReference
 		&& !alreadyCompletedLocalInitialization){
@@ -90,8 +90,8 @@
 		return null; // no update is necessary	(array initializer)
 	}
 	// might be an array initializer
-	this.updateSourceEndIfNecessary(currentPosition - 1);	
-	return this.parent.updateOnOpeningBrace(currentPosition);	
+	this.updateSourceEndIfNecessary(braceStart - 1, braceEnd - 1);	
+	return this.parent.updateOnOpeningBrace(braceStart, braceEnd);	
 }
 public void updateParseTree(){
 	this.updatedStatement();
@@ -99,10 +99,10 @@
 /*
  * Update the declarationSourceEnd of the corresponding parse node
  */
-public void updateSourceEndIfNecessary(int sourceEnd){
+public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
 	if (this.localDeclaration.declarationSourceEnd == 0) {
-		this.localDeclaration.declarationSourceEnd = sourceEnd;
-		this.localDeclaration.declarationEnd = sourceEnd;	
+		this.localDeclaration.declarationSourceEnd = bodyEnd;
+		this.localDeclaration.declarationEnd = bodyEnd;	
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
index 6b5814c..26f1306 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
@@ -13,13 +13,12 @@
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Block;
 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.LocalTypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
 import org.eclipse.jdt.internal.compiler.ast.SuperReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -52,7 +51,7 @@
 /*
  * Record a nested block declaration
  */
-public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalance) {
+public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
 
 	/* default behavior is to delegate recording to parent if any,
 	do not consider elements passed the known end (if set)
@@ -64,7 +63,7 @@
 				if (this.parent == null){
 					return this; // ignore
 				} else {
-					return this.parent.add(nestedBlockDeclaration, bracketBalance);
+					return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
 				}
 	}
 	/* consider that if the opening brace was not found, it is there */
@@ -73,14 +72,14 @@
 		this.bracketBalance++;
 	}
 
-	methodBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalance);
+	methodBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue);
 	if (nestedBlockDeclaration.sourceEnd == 0) return methodBody;
 	return this;
 }
 /*
  * Record a field declaration
  */
-public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalance) {
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
 
 	/* local variables inside method can only be final and non void */
 	char[][] fieldTypeName; 
@@ -93,7 +92,7 @@
 			return this; // ignore
 		} else {
 			this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1));
-			return this.parent.add(fieldDeclaration, bracketBalance);
+			return this.parent.add(fieldDeclaration, bracketBalanceValue);
 		}
 	}
 	/* default behavior is to delegate recording to parent if any,
@@ -106,7 +105,7 @@
 		if (this.parent == null){
 			return this; // ignore
 		} else {
-			return this.parent.add(fieldDeclaration, bracketBalance);
+			return this.parent.add(fieldDeclaration, bracketBalanceValue);
 		}
 	}
 	/* consider that if the opening brace was not found, it is there */
@@ -120,7 +119,7 @@
 /*
  * Record a local declaration - regular method should have been created a block body
  */
-public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalance) {
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
 
 	/* local variables inside method can only be final and non void */
 /*	
@@ -146,7 +145,7 @@
 		if (this.parent == null) {
 			return this; // ignore
 		} else {
-			return this.parent.add(localDeclaration, bracketBalance);
+			return this.parent.add(localDeclaration, bracketBalanceValue);
 		}
 	}
 	if (methodBody == null){
@@ -159,14 +158,14 @@
 			}
 			this.bracketBalance = 1;
 		}
-		return currentBlock.add(localDeclaration, bracketBalance);
+		return currentBlock.add(localDeclaration, bracketBalanceValue);
 	}
-	return methodBody.add(localDeclaration, bracketBalance, true);
+	return methodBody.add(localDeclaration, bracketBalanceValue, true);
 }
 /*
  * Record a statement - regular method should have been created a block body
  */
-public RecoveredElement add(Statement statement, int bracketBalance) {
+public RecoveredElement add(Statement statement, int bracketBalanceValue) {
 
 	/* do not consider a type starting passed the type end (if set)
 		it must be belonging to an enclosing type */
@@ -176,7 +175,7 @@
 		if (this.parent == null) {
 			return this; // ignore
 		} else {
-			return this.parent.add(statement, bracketBalance);
+			return this.parent.add(statement, bracketBalanceValue);
 		}
 	}
 	if (methodBody == null){
@@ -189,11 +188,11 @@
 			}
 			this.bracketBalance = 1;
 		}
-		return currentBlock.add(statement, bracketBalance);
+		return currentBlock.add(statement, bracketBalanceValue);
 	}
-	return methodBody.add(statement, bracketBalance, true);	
+	return methodBody.add(statement, bracketBalanceValue, true);	
 }
-public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance) {
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
 
 	/* do not consider a type starting passed the type end (if set)
 		it must be belonging to an enclosing type */
@@ -203,16 +202,16 @@
 		if (this.parent == null) {
 			return this; // ignore
 		} else {
-			return this.parent.add(typeDeclaration, bracketBalance);
+			return this.parent.add(typeDeclaration, bracketBalanceValue);
 		}
 	}
-	if (typeDeclaration instanceof LocalTypeDeclaration){
+	if ((typeDeclaration.bits & ASTNode.IsLocalTypeMASK) != 0){
 		if (methodBody == null){
 			Block block = new Block(0);
 			block.sourceStart = methodDeclaration.bodyStart;
 			this.add(block, 1);
 		}
-		return methodBody.add(typeDeclaration, bracketBalance, true);	
+		return methodBody.add(typeDeclaration, bracketBalanceValue, true);	
 	}	
 	if (localTypes == null) {
 		localTypes = new RecoveredType[5];
@@ -227,7 +226,7 @@
 				localTypeCount); 
 		}
 	}
-	RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalance);
+	RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
 	localTypes[localTypeCount++] = element;
 
 	/* consider that if the opening brace was not found, it is there */
@@ -243,7 +242,7 @@
 /* 
  * Answer the associated parsed structure
  */
-public AstNode parseTree(){
+public ASTNode parseTree(){
 	return methodDeclaration;
 }
 /*
@@ -255,7 +254,7 @@
 public String toString(int tab) {
 	StringBuffer result = new StringBuffer(tabString(tab));
 	result.append("Recovered method:\n"); //$NON-NLS-1$
-	result.append(this.methodDeclaration.toString(tab + 1));
+	result.append(this.methodDeclaration.print(tab + 1, result));
 	if (this.localTypes != null) {
 		for (int i = 0; i < this.localTypeCount; i++) {
 			result.append("\n"); //$NON-NLS-1$
@@ -302,7 +301,7 @@
 			}
 		}
 	}
-	if (localTypeCount > 0) methodDeclaration.bits |= AstNode.HasLocalTypeMASK;
+	if (localTypeCount > 0) methodDeclaration.bits |= ASTNode.HasLocalTypeMASK;
 	return methodDeclaration;
 }
 /*
@@ -402,7 +401,7 @@
  * An opening brace got consumed, might be the expected opening one of the current element,
  * in which case the bodyStart is updated.
  */
-public RecoveredElement updateOnOpeningBrace(int braceEnd){
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
 
 	/* in case the opening brace is close enough to the signature */
 	if (bracketBalance == 0){
@@ -419,7 +418,7 @@
 				bracketBalance = 1; // pretend the brace was already there
 		}
 	}	
-	return super.updateOnOpeningBrace(braceEnd);
+	return super.updateOnOpeningBrace(braceStart, braceEnd);
 }
 public void updateParseTree(){
 	this.updatedMethodDeclaration();
@@ -427,10 +426,15 @@
 /*
  * Update the declarationSourceEnd of the corresponding parse node
  */
-public void updateSourceEndIfNecessary(int sourceEnd){
+public void updateSourceEndIfNecessary(int braceStart, int braceEnd){
 	if (this.methodDeclaration.declarationSourceEnd == 0) {
-		this.methodDeclaration.declarationSourceEnd = sourceEnd;
-		this.methodDeclaration.bodyEnd = sourceEnd;
+		if(parser().rBraceSuccessorStart >= braceEnd) {
+			this.methodDeclaration.declarationSourceEnd = parser().rBraceEnd;
+			this.methodDeclaration.bodyEnd = parser().rBraceStart;
+		} else {
+			this.methodDeclaration.declarationSourceEnd = braceEnd;
+			this.methodDeclaration.bodyEnd  = braceStart - 1;
+		}
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java
index ab9efd7..f83a456 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java
@@ -13,7 +13,7 @@
 /**
  * Internal statement structure for parsing recovery 
  */
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
 
 public class RecoveredStatement extends RecoveredElement {
@@ -26,7 +26,7 @@
 /* 
  * Answer the associated parsed structure
  */
-public AstNode parseTree(){
+public ASTNode parseTree(){
 	return statement;
 }
 /*
@@ -36,7 +36,7 @@
 	return this.statement.sourceEnd;
 }
 public String toString(int tab){
-	return tabString(tab) + "Recovered statement:\n" + statement.toString(tab + 1); //$NON-NLS-1$
+	return tabString(tab) + "Recovered statement:\n" + statement.print(tab + 1, new StringBuffer(10)); //$NON-NLS-1$
 }
 public Statement updatedStatement(){
 	return statement;
@@ -47,8 +47,8 @@
 /*
  * Update the declarationSourceEnd of the corresponding parse node
  */
-public void updateSourceEndIfNecessary(int sourceEnd){
+public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
 	if (this.statement.sourceEnd == 0)	
-		this.statement.sourceEnd = sourceEnd;
+		this.statement.sourceEnd = bodyEnd;
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
index 960feb9..d171276 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
@@ -11,13 +11,10 @@
 package org.eclipse.jdt.internal.compiler.parser;
 
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.Block;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Initializer;
-import org.eclipse.jdt.internal.compiler.ast.LocalTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MemberTypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Statement;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
@@ -48,13 +45,13 @@
 		this.bracketBalance++;
 	}
 }
-public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalance) {
+public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
 
 	/* do not consider a method starting passed the type end (if set)
 		it must be belonging to an enclosing type */
 	if (typeDeclaration.declarationSourceEnd != 0 
 		&& methodDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd){
-		return this.parent.add(methodDeclaration, bracketBalance);
+		return this.parent.add(methodDeclaration, bracketBalanceValue);
 	}
 
 	if (methods == null) {
@@ -70,7 +67,7 @@
 				methodCount); 
 		}
 	}
-	RecoveredMethod element = new RecoveredMethod(methodDeclaration, this, bracketBalance, this.recoveringParser);
+	RecoveredMethod element = new RecoveredMethod(methodDeclaration, this, bracketBalanceValue, this.recoveringParser);
 	methods[methodCount++] = element;
 
 	/* consider that if the opening brace was not found, it is there */
@@ -82,20 +79,20 @@
 	if (methodDeclaration.declarationSourceEnd == 0) return element;
 	return this;
 }
-public RecoveredElement add(Block nestedBlockDeclaration,int bracketBalance) {
+public RecoveredElement add(Block nestedBlockDeclaration,int bracketBalanceValue) {
 	int modifiers = AccDefault;
 	if(this.parser().recoveredStaticInitializerStart != 0) {
 		modifiers = AccStatic;
 	}
-	return this.add(new Initializer(nestedBlockDeclaration, modifiers), bracketBalance);
+	return this.add(new Initializer(nestedBlockDeclaration, modifiers), bracketBalanceValue);
 }
-public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalance) {
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
 	
 	/* do not consider a field starting passed the type end (if set)
 	it must be belonging to an enclosing type */
 	if (typeDeclaration.declarationSourceEnd != 0
 		&& fieldDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd) {
-		return this.parent.add(fieldDeclaration, bracketBalance);
+		return this.parent.add(fieldDeclaration, bracketBalanceValue);
 	}
 	if (fields == null) {
 		fields = new RecoveredField[5];
@@ -111,8 +108,8 @@
 		}
 	}
 	RecoveredField element = fieldDeclaration.isField() 
-								? new RecoveredField(fieldDeclaration, this, bracketBalance)
-								: new RecoveredInitializer(fieldDeclaration, this, bracketBalance);
+								? new RecoveredField(fieldDeclaration, this, bracketBalanceValue)
+								: new RecoveredInitializer(fieldDeclaration, this, bracketBalanceValue);
 	fields[fieldCount++] = element;
 
 	/* consider that if the opening brace was not found, it is there */
@@ -124,23 +121,23 @@
 	if (fieldDeclaration.declarationSourceEnd == 0) return element;
 	return this;
 }
-public RecoveredElement add(TypeDeclaration memberTypeDeclaration, int bracketBalance) {
+public RecoveredElement add(TypeDeclaration memberTypeDeclaration, int bracketBalanceValue) {
 
 	/* do not consider a type starting passed the type end (if set)
 		it must be belonging to an enclosing type */
 	if (typeDeclaration.declarationSourceEnd != 0 
 		&& memberTypeDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd){
-		return this.parent.add(memberTypeDeclaration, bracketBalance);
+		return this.parent.add(memberTypeDeclaration, bracketBalanceValue);
 	}
 	
-	if (memberTypeDeclaration instanceof AnonymousLocalTypeDeclaration){
+	if ((memberTypeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0){
 		if (this.methodCount > 0) {
 			// add it to the last method body
 			RecoveredMethod lastMethod = this.methods[this.methodCount-1];
 			lastMethod.methodDeclaration.bodyEnd = 0; // reopen method
 			lastMethod.methodDeclaration.declarationSourceEnd = 0; // reopen method
 			lastMethod.bracketBalance++; // expect one closing brace
-			return lastMethod.add(typeDeclaration, bracketBalance);
+			return lastMethod.add(typeDeclaration, bracketBalanceValue);
 		} else {
 			// ignore
 			return this;
@@ -160,7 +157,7 @@
 				memberTypeCount); 
 		}
 	}
-	RecoveredType element = new RecoveredType(memberTypeDeclaration, this, bracketBalance);
+	RecoveredType element = new RecoveredType(memberTypeDeclaration, this, bracketBalanceValue);
 	memberTypes[memberTypeCount++] = element;
 
 	/* consider that if the opening brace was not found, it is there */
@@ -210,7 +207,7 @@
 /* 
  * Answer the associated parsed structure
  */
-public AstNode parseTree(){
+public ASTNode parseTree(){
 	return typeDeclaration;
 }
 /*
@@ -222,11 +219,11 @@
 public String toString(int tab) {
 	StringBuffer result = new StringBuffer(tabString(tab));
 	result.append("Recovered type:\n"); //$NON-NLS-1$
-	if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
+	if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
 		result.append(tabString(tab));
 		result.append(" "); //$NON-NLS-1$
 	}
-	result.append(typeDeclaration.toString(tab + 1));
+	result.append(typeDeclaration.print(tab + 1, result));
 	if (this.memberTypes != null) {
 		for (int i = 0; i < this.memberTypeCount; i++) {
 			result.append("\n"); //$NON-NLS-1$
@@ -257,15 +254,14 @@
 public Statement updatedStatement(){
 
 	// ignore closed anonymous type
-	if (typeDeclaration instanceof AnonymousLocalTypeDeclaration
-		&& !this.preserveContent){
+	if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0 && !this.preserveContent){
 		return null;
 	}
 		
 	TypeDeclaration updatedType = this.updatedTypeDeclaration();
-	if (updatedType instanceof AnonymousLocalTypeDeclaration){
+	if ((updatedType.bits & ASTNode.IsAnonymousTypeMASK) != 0){
 		/* in presence of an anonymous type, we want the full allocation expression */
-		return ((AnonymousLocalTypeDeclaration)updatedType).allocation;
+		return updatedType.allocation;
 	}
 	return updatedType;
 }
@@ -274,18 +270,18 @@
 	/* update member types */
 	if (memberTypeCount > 0){
 		int existingCount = typeDeclaration.memberTypes == null ? 0 : typeDeclaration.memberTypes.length;
-		MemberTypeDeclaration[] memberTypeDeclarations = new MemberTypeDeclaration[existingCount + memberTypeCount];
+		TypeDeclaration[] memberTypeDeclarations = new TypeDeclaration[existingCount + memberTypeCount];
 		if (existingCount > 0){
 			System.arraycopy(typeDeclaration.memberTypes, 0, memberTypeDeclarations, 0, existingCount);
 		}
 		// may need to update the declarationSourceEnd of the last type
 		if (memberTypes[memberTypeCount - 1].typeDeclaration.declarationSourceEnd == 0){
-			int bodyEnd = bodyEnd();
-			memberTypes[memberTypeCount - 1].typeDeclaration.declarationSourceEnd = bodyEnd;
-			memberTypes[memberTypeCount - 1].typeDeclaration.bodyEnd =  bodyEnd;
+			int bodyEndValue = bodyEnd();
+			memberTypes[memberTypeCount - 1].typeDeclaration.declarationSourceEnd = bodyEndValue;
+			memberTypes[memberTypeCount - 1].typeDeclaration.bodyEnd =  bodyEndValue;
 		}
 		for (int i = 0; i < memberTypeCount; i++){
-			memberTypeDeclarations[existingCount + i] = (MemberTypeDeclaration)memberTypes[i].updatedTypeDeclaration();
+			memberTypeDeclarations[existingCount + i] = memberTypes[i].updatedTypeDeclaration();
 		}
 		typeDeclaration.memberTypes = memberTypeDeclarations;
 	}
@@ -320,9 +316,9 @@
 		}
 		// may need to update the declarationSourceEnd of the last method
 		if (methods[methodCount - 1].methodDeclaration.declarationSourceEnd == 0){
-			int bodyEnd = bodyEnd();
-			methods[methodCount - 1].methodDeclaration.declarationSourceEnd = bodyEnd;
-			methods[methodCount - 1].methodDeclaration.bodyEnd = bodyEnd;
+			int bodyEndValue = bodyEnd();
+			methods[methodCount - 1].methodDeclaration.declarationSourceEnd = bodyEndValue;
+			methods[methodCount - 1].methodDeclaration.bodyEnd = bodyEndValue;
 		}
 		for (int i = 0; i < methodCount; i++){
 			AbstractMethodDeclaration updatedMethod = methods[i].updatedMethodDeclaration();			
@@ -364,45 +360,23 @@
 		}
 		typeDeclaration.methods = methodDeclarations;
 	} else {
-		if (!hasConstructor) {// if was already reduced, then constructor
+		if (!hasConstructor && !typeDeclaration.isInterface()) {// if was already reduced, then constructor
 			boolean insideFieldInitializer = false;
-			RecoveredElement parent = this.parent; 
-			while (parent != null){
-				if (parent instanceof RecoveredField){
+			RecoveredElement parentElement = this.parent; 
+			while (parentElement != null){
+				if (parentElement instanceof RecoveredField){
 						insideFieldInitializer = true;
 						break; 
 				}
-				parent = parent.parent;
+				parentElement = parentElement.parent;
 			}
 			typeDeclaration.createsInternalConstructor(!parser().diet || insideFieldInitializer, true);
 		} 
 	}
-	/* might need to cast itself into a MemberTypeDeclaration or a LocalTypeDeclaration */
-	TypeDeclaration newTypeDeclaration = null;
-	if ((typeDeclaration instanceof TypeDeclaration) && (parent instanceof RecoveredType)){
-		newTypeDeclaration = new MemberTypeDeclaration(typeDeclaration.compilationResult);
-	} else {
-		if ((typeDeclaration instanceof TypeDeclaration) && (parent instanceof RecoveredMethod)){
-			newTypeDeclaration = new LocalTypeDeclaration(typeDeclaration.compilationResult);
-		}
-	}
-	/* copy slots into new type */
-	if (newTypeDeclaration != null){
-		newTypeDeclaration.modifiers = typeDeclaration.modifiers;
-		newTypeDeclaration.modifiersSourceStart = typeDeclaration.modifiersSourceStart;
-		newTypeDeclaration.name = typeDeclaration.name;
-		newTypeDeclaration.superclass = typeDeclaration.superclass;
-		newTypeDeclaration.superInterfaces = typeDeclaration.superInterfaces;
-		newTypeDeclaration.fields = typeDeclaration.fields;
-		newTypeDeclaration.methods = typeDeclaration.methods;
-		newTypeDeclaration.memberTypes = typeDeclaration.memberTypes;
-		newTypeDeclaration.ignoreFurtherInvestigation = typeDeclaration.ignoreFurtherInvestigation;
-		newTypeDeclaration.maxFieldCount = typeDeclaration.maxFieldCount;
-		newTypeDeclaration.declarationSourceStart = typeDeclaration.declarationSourceStart;
-		newTypeDeclaration.declarationSourceEnd = typeDeclaration.declarationSourceEnd;
-		newTypeDeclaration.bodyEnd = typeDeclaration.bodyEnd;
-		newTypeDeclaration.bodyStart = typeDeclaration.bodyStart;
-		typeDeclaration = newTypeDeclaration;
+	if (parent instanceof RecoveredType){
+		typeDeclaration.bits |= ASTNode.IsMemberTypeMASK;
+	} else if (parent instanceof RecoveredMethod){
+		typeDeclaration.bits |= ASTNode.IsLocalTypeMASK;
 	}
 	return typeDeclaration;
 }
@@ -444,7 +418,7 @@
  */
 public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
 	if ((--bracketBalance <= 0) && (parent != null)){
-		this.updateSourceEndIfNecessary(braceEnd);
+		this.updateSourceEndIfNecessary(braceStart, braceEnd);
 		this.bodyEnd = braceStart - 1;
 		return parent;
 	}
@@ -454,7 +428,7 @@
  * An opening brace got consumed, might be the expected opening one of the current element,
  * in which case the bodyStart is updated.
  */
-public RecoveredElement updateOnOpeningBrace(int braceEnd){
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
 	/* in case the opening brace is not close enough to the signature, ignore it */
 	if (bracketBalance == 0){
 		/*
@@ -484,9 +458,10 @@
 			init = new Initializer(block, AccStatic);
 			init.declarationSourceStart = parser.recoveredStaticInitializerStart;
 		}
+		init.bodyStart = parser.scanner.currentPosition;
 		return this.add(init, 1);
 	}
-	return super.updateOnOpeningBrace(braceEnd);
+	return super.updateOnOpeningBrace(braceStart, braceEnd);
 }
 public void updateParseTree(){
 	this.updatedTypeDeclaration();
@@ -494,11 +469,11 @@
 /*
  * Update the declarationSourceEnd of the corresponding parse node
  */
-public void updateSourceEndIfNecessary(int sourceEnd){
+public void updateSourceEndIfNecessary(int start, int end){
 	if (this.typeDeclaration.declarationSourceEnd == 0){
 		this.bodyEnd = 0;
-		this.typeDeclaration.declarationSourceEnd = sourceEnd;
-		this.typeDeclaration.bodyEnd = sourceEnd;
+		this.typeDeclaration.declarationSourceEnd = end;
+		this.typeDeclaration.bodyEnd = end;
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
index 3ca9a5e..11d59fa 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
@@ -14,12 +14,10 @@
  * Internal field structure for parsing recovery 
  */
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.LocalTypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 
 public class RecoveredUnit extends RecoveredElement {
@@ -37,57 +35,57 @@
 /*
  *	Record a method declaration: should be attached to last type
  */
-public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalance) {
+public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
 
 	/* attach it to last type - if any */
-	if (typeCount > 0){
-		RecoveredType type = this.types[typeCount -1];
+	if (this.typeCount > 0){
+		RecoveredType type = this.types[this.typeCount -1];
 		type.bodyEnd = 0; // reset position
 		type.typeDeclaration.declarationSourceEnd = 0; // reset position
 		type.typeDeclaration.bodyEnd = 0;
-		return type.add(methodDeclaration, bracketBalance);
+		return type.add(methodDeclaration, bracketBalanceValue);
 	}
 	return this; // ignore
 }
 /*
  *	Record a field declaration: should be attached to last type
  */
-public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalance) {
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
 
 	/* attach it to last type - if any */
-	if (typeCount > 0){
-		RecoveredType type = this.types[typeCount -1];
+	if (this.typeCount > 0){
+		RecoveredType type = this.types[this.typeCount -1];
 		type.bodyEnd = 0; // reset position
 		type.typeDeclaration.declarationSourceEnd = 0; // reset position
 		type.typeDeclaration.bodyEnd = 0;
-		return type.add(fieldDeclaration, bracketBalance);
+		return type.add(fieldDeclaration, bracketBalanceValue);
 	}
 	return this; // ignore
 }
-public RecoveredElement add(ImportReference importReference, int bracketBalance) {
-	if (imports == null) {
-		imports = new RecoveredImport[5];
-		importCount = 0;
+public RecoveredElement add(ImportReference importReference, int bracketBalanceValue) {
+	if (this.imports == null) {
+		this.imports = new RecoveredImport[5];
+		this.importCount = 0;
 	} else {
-		if (importCount == imports.length) {
+		if (this.importCount == this.imports.length) {
 			System.arraycopy(
-				imports, 
+				this.imports, 
 				0, 
-				(imports = new RecoveredImport[2 * importCount]), 
+				(this.imports = new RecoveredImport[2 * this.importCount]), 
 				0, 
-				importCount); 
+				this.importCount); 
 		}
 	}
-	RecoveredImport element = new RecoveredImport(importReference, this, bracketBalance);
-	imports[importCount++] = element;
+	RecoveredImport element = new RecoveredImport(importReference, this, bracketBalanceValue);
+	this.imports[this.importCount++] = element;
 
 	/* if import not finished, then import becomes current */
 	if (importReference.declarationSourceEnd == 0) return element;
 	return this;		
 }
-public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance) {
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
 	
-	if (typeDeclaration instanceof AnonymousLocalTypeDeclaration){
+	if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0){
 		if (this.typeCount > 0) {
 			// add it to the last type
 			RecoveredType lastType = this.types[this.typeCount-1];
@@ -95,24 +93,24 @@
 			lastType.typeDeclaration.bodyEnd = 0; // reopen type
 			lastType.typeDeclaration.declarationSourceEnd = 0; // reopen type
 			lastType.bracketBalance++; // expect one closing brace
-			return lastType.add(typeDeclaration, bracketBalance);
+			return lastType.add(typeDeclaration, bracketBalanceValue);
 		}
 	}
-	if (types == null) {
-		types = new RecoveredType[5];
-		typeCount = 0;
+	if (this.types == null) {
+		this.types = new RecoveredType[5];
+		this.typeCount = 0;
 	} else {
-		if (typeCount == types.length) {
+		if (this.typeCount == this.types.length) {
 			System.arraycopy(
-				types, 
+				this.types, 
 				0, 
-				(types = new RecoveredType[2 * typeCount]), 
+				(this.types = new RecoveredType[2 * this.typeCount]), 
 				0, 
-				typeCount); 
+				this.typeCount); 
 		}
 	}
-	RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalance);
-	types[typeCount++] = element;
+	RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
+	this.types[this.typeCount++] = element;
 
 	/* if type not finished, then type becomes current */
 	if (typeDeclaration.declarationSourceEnd == 0) return element;
@@ -121,8 +119,8 @@
 /* 
  * Answer the associated parsed structure
  */
-public AstNode parseTree(){
-	return unitDeclaration;
+public ASTNode parseTree(){
+	return this.unitDeclaration;
 }
 /*
  * Answer the very source end of the corresponding parse node
@@ -133,7 +131,7 @@
 public String toString(int tab) {
 	StringBuffer result = new StringBuffer(tabString(tab));
 	result.append("Recovered unit: [\n"); //$NON-NLS-1$
-	result.append(unitDeclaration.toString(tab + 1));
+	result.append(this.unitDeclaration.print(tab + 1, result));
 	result.append(tabString(tab + 1));
 	result.append("]"); //$NON-NLS-1$
 	if (this.imports != null) {
@@ -153,34 +151,34 @@
 public CompilationUnitDeclaration updatedCompilationUnitDeclaration(){
 
 	/* update imports */
-	if (importCount > 0){
-		ImportReference[] importRefences = new ImportReference[importCount];
-		for (int i = 0; i < importCount; i++){
-			importRefences[i] = imports[i].updatedImportReference();
+	if (this.importCount > 0){
+		ImportReference[] importRefences = new ImportReference[this.importCount];
+		for (int i = 0; i < this.importCount; i++){
+			importRefences[i] = this.imports[i].updatedImportReference();
 		}
-		unitDeclaration.imports = importRefences;
+		this.unitDeclaration.imports = importRefences;
 	}
 	/* update types */
-	if (typeCount > 0){
-		int existingCount = unitDeclaration.types == null ? 0 : unitDeclaration.types.length;
-		TypeDeclaration[] typeDeclarations = new TypeDeclaration[existingCount + typeCount];
+	if (this.typeCount > 0){
+		int existingCount = this.unitDeclaration.types == null ? 0 : this.unitDeclaration.types.length;
+		TypeDeclaration[] typeDeclarations = new TypeDeclaration[existingCount + this.typeCount];
 		if (existingCount > 0){
-			System.arraycopy(unitDeclaration.types, 0, typeDeclarations, 0, existingCount);
+			System.arraycopy(this.unitDeclaration.types, 0, typeDeclarations, 0, existingCount);
 		}
 		// may need to update the declarationSourceEnd of the last type
-		if (types[typeCount - 1].typeDeclaration.declarationSourceEnd == 0){
-			types[typeCount - 1].typeDeclaration.declarationSourceEnd = unitDeclaration.sourceEnd;
-			types[typeCount - 1].typeDeclaration.bodyEnd = unitDeclaration.sourceEnd;
+		if (this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd == 0){
+			this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd = this.unitDeclaration.sourceEnd;
+			this.types[this.typeCount - 1].typeDeclaration.bodyEnd = this.unitDeclaration.sourceEnd;
 		}
 		int actualCount = existingCount;
-		for (int i = 0; i < typeCount; i++){
-			TypeDeclaration typeDecl = types[i].updatedTypeDeclaration();
+		for (int i = 0; i < this.typeCount; i++){
+			TypeDeclaration typeDecl = this.types[i].updatedTypeDeclaration();
 			// filter out local types (12454)
-			if (!(typeDecl instanceof LocalTypeDeclaration)){
+			if ((typeDecl.bits & ASTNode.IsLocalTypeMASK) == 0){
 				typeDeclarations[actualCount++] = typeDecl;
 			}
 		}
-		if (actualCount != typeCount){
+		if (actualCount != this.typeCount){
 			System.arraycopy(
 				typeDeclarations, 
 				0, 
@@ -188,9 +186,9 @@
 				0, 
 				existingCount+actualCount);
 		}
-		unitDeclaration.types = typeDeclarations;
+		this.unitDeclaration.types = typeDeclarations;
 	}
-	return unitDeclaration;
+	return this.unitDeclaration;
 }
 public void updateParseTree(){
 	this.updatedCompilationUnitDeclaration();
@@ -198,8 +196,8 @@
 /*
  * Update the sourceEnd of the corresponding parse node
  */
-public void updateSourceEndIfNecessary(int sourceEnd){
+public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
 	if (this.unitDeclaration.sourceEnd == 0)
-		this.unitDeclaration.sourceEnd = sourceEnd;
+		this.unitDeclaration.sourceEnd = bodyEnd;
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
index e980d3f..eca9401 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
@@ -12,9 +12,10 @@
 
 import java.util.Iterator;
 
-import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 
 /**
  * IMPORTANT NOTE: Internal Scanner implementation. It is mirrored in 
@@ -134,8 +135,6 @@
 	public /*static*/ final char[][][][] charArray_length = 
 		new char[OptimizedLength][TableSize][InternalTableSize][]; 
 	// support for detecting non-externalized string literals
-	int currentLineNr= -1;
-	int previousLineNr= -1;
 	NLSLine currentLine= null;
 	public static final String TAG_PREFIX= "//$NON-NLS-"; //$NON-NLS-1$
 	public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length();
@@ -166,26 +165,26 @@
 	public static final int BracketKinds = 3;
 
 public Scanner() {
-	this(false /*comment*/, false /*whitespace*/, false /*nls*/, false /*assert*/, null/*taskTag*/, null/*taskPriorities*/);
+	this(false /*comment*/, false /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/);
 }
+
 public Scanner(
 	boolean tokenizeComments, 
 	boolean tokenizeWhiteSpace, 
 	boolean checkNonExternalizedStringLiterals, 
-	boolean assertMode,
+	long sourceLevel,
 	char[][] taskTags,
 	char[][] taskPriorities) {
-		
+
 	this.eofPosition = Integer.MAX_VALUE;
 	this.tokenizeComments = tokenizeComments;
 	this.tokenizeWhiteSpace = tokenizeWhiteSpace;
 	this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
-	this.assertMode = assertMode;
+	this.assertMode = sourceLevel >= ClassFileConstants.JDK1_4;
 	this.taskTags = taskTags;
 	this.taskPriorities = taskPriorities;
 }
 
-
 public  final boolean atEnd() {
 	// This code is not relevant if source is 
 	// Only a part of the real stream input
@@ -193,106 +192,124 @@
 	return source.length == currentPosition;
 }
 
-private void checkNonExternalizeString()  throws InvalidInputException {
-	if (currentLine == null)
+private void checkNonExternalizedString() {
+	if (currentLine == null) 
 		return;
 	parseTags(currentLine);
 }
 
 // chech presence of task: tags
 public void checkTaskTag(int commentStart, int commentEnd) {
-
+	char[] src = this.source;
+	
 	// only look for newer task: tags
-	if (this.foundTaskCount > 0 && this.foundTaskPositions[this.foundTaskCount-1][0] >= commentStart) {
+	if (this.foundTaskCount > 0
+		&& this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) {
 		return;
 	}
 	int foundTaskIndex = this.foundTaskCount;
-	nextChar: for (int i = commentStart; i < commentEnd && i < this.eofPosition; i++) {
-
+	char previous = '/';
+	nextChar : for (
+		int i = commentStart + 1; i < commentEnd && i < this.eofPosition; i++) {
 		char[] tag = null;
 		char[] priority = null;
-		
 		// check for tag occurrence
-		nextTag: for (int itag = 0; itag < this.taskTags.length; itag++){
+		nextTag : for (int itag = 0; itag < this.taskTags.length; itag++) {
 			tag = this.taskTags[itag];
-			priority = 
-				this.taskPriorities != null && itag < this.taskPriorities.length ?
-				this.taskPriorities[itag] :
-				null;
 			int tagLength = tag.length;
-			for (int t = 0; t < tagLength; t++){
-				if (this.source[i+t] != tag[t]) continue nextTag;
+			if (tagLength == 0) continue nextTag;
+
+			// ensure tag is not leaded with letter if tag starts with a letter
+			if (Character.isLetterOrDigit(tag[0])) {
+				if (Character.isLetterOrDigit(previous)) {
+					continue nextTag;
+				}
 			}
 
-			if (this.foundTaskTags == null){
+			for (int t = 0; t < tagLength; t++) {
+				if (src[i + t] != tag[t])
+					continue nextTag;
+			}
+			// ensure tag is not followed with letter if tag finishes with a letter
+			if (i+tagLength < commentEnd && Character.isLetterOrDigit(src[i+tagLength-1])) {
+				if (Character.isLetterOrDigit(src[i + tagLength]))
+					continue nextTag;
+			}
+			if (this.foundTaskTags == null) {
 				this.foundTaskTags = new char[5][];
 				this.foundTaskMessages = new char[5][];
 				this.foundTaskPriorities = new char[5][];
 				this.foundTaskPositions = new int[5][];
 			} else if (this.foundTaskCount == this.foundTaskTags.length) {
-				System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount*2][], 0, this.foundTaskCount);
-				System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount*2][], 0, this.foundTaskCount);
-				System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount*2][], 0, this.foundTaskCount);
-				System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount*2][], 0, this.foundTaskCount);
+				System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
+				System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
+				System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
+				System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, this.foundTaskCount);
 			}
+			
+			priority = this.taskPriorities != null && itag < this.taskPriorities.length
+						? this.taskPriorities[itag]
+						: null;
+			
 			this.foundTaskTags[this.foundTaskCount] = tag;
 			this.foundTaskPriorities[this.foundTaskCount] = priority;
-			this.foundTaskPositions[this.foundTaskCount] = new int[]{ i, i+tagLength-1 };
+			this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 };
 			this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR;
 			this.foundTaskCount++;
-			
-			i += tagLength-1; // will be incremented when looping
+			i += tagLength - 1; // will be incremented when looping
+			break nextTag;
 		}
+		previous = src[i];
 	}
-	
 	for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
 		// retrieve message start and end positions
 		int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length;
-		int max_value = i + 1 < this.foundTaskCount ? this.foundTaskPositions[i + 1][0] - 1 : commentEnd-1; // at most beginning of next task
-		if (max_value < msgStart) max_value = msgStart; // would only occur if tag is before EOF.
+		int max_value = i + 1 < this.foundTaskCount
+				? this.foundTaskPositions[i + 1][0] - 1
+				: commentEnd - 1;
+		// at most beginning of next task
+		if (max_value < msgStart) {
+			max_value = msgStart; // would only occur if tag is before EOF.
+		}
 		int end = -1;
 		char c;
-		
-		for (int j = msgStart; j < max_value; j++){
-			if ((c = this.source[j]) == '\n' || c == '\r'){
-				end = j-1;
+		for (int j = msgStart; j < max_value; j++) {
+			if ((c = src[j]) == '\n' || c == '\r') {
+				end = j - 1;
 				break;
 			}
 		}
-		
-		if (end == -1){
-			for (int j = max_value; j > msgStart; j--){
-				if ((c = this.source[j]) == '*') {
-					end = j-1;
+		if (end == -1) {
+			for (int j = max_value; j > msgStart; j--) {
+				if ((c = src[j]) == '*') {
+					end = j - 1;
 					break;
 				}
 			}
-			if (end == -1) end = max_value;
+			if (end == -1)
+				end = max_value;
 		}
-
-		if (msgStart == end) continue; // empty
-				
+		if (msgStart == end)
+			continue; // empty
 		// trim the message
-		while (CharOperation.isWhitespace(source[end]) && msgStart <= end) end--;
-		while (CharOperation.isWhitespace(source[msgStart]) && msgStart <= end) msgStart++;
-
+		while (CharOperation.isWhitespace(src[end]) && msgStart <= end)
+			end--;
+		while (CharOperation.isWhitespace(src[msgStart]) && msgStart <= end)
+			msgStart++;
 		// update the end position of the task
 		this.foundTaskPositions[i][1] = end;
-		
 		// get the message source
-		final int messageLength = end-msgStart+1;
+		final int messageLength = end - msgStart + 1;
 		char[] message = new char[messageLength];
-
-		System.arraycopy(source, msgStart, message, 0, messageLength);
+		System.arraycopy(src, msgStart, message, 0, messageLength);
 		this.foundTaskMessages[i] = message;
 	}
 }
-
 public char[] getCurrentIdentifierSource() {
 	//return the token REAL source (aka unicodes are precomputed)
 
 	char[] result;
-	if (withoutUnicodePtr != 0)
+	if (withoutUnicodePtr != 0) {
 		//0 is used as a fast test flag so the real first char is in position 1
 		System.arraycopy(
 			withoutUnicodeBuffer, 
@@ -300,8 +317,9 @@
 			result = new char[withoutUnicodePtr], 
 			0, 
 			withoutUnicodePtr); 
-	else {
+	} else {
 		int length = currentPosition - startPosition;
+		if (length == this.source.length) return this.source;
 		switch (length) { // see OptimizedLength
 			case 1 :
 				return optimizedCurrentTokenSource1();
@@ -376,6 +394,13 @@
 	return tokenSource;	
 }
 	
+public final char[] getRawTokenSourceEnd() {
+	int length = this.eofPosition - this.currentPosition;
+	char[] sourceEnd = new char[length];
+	System.arraycopy(source, this.currentPosition, sourceEnd, 0, length);
+	return sourceEnd;	
+}
+	
 public int getCurrentTokenStartPosition(){
 	return this.startPosition;
 }
@@ -389,11 +414,14 @@
  */
 public final int getLineEnd(int lineNumber) {
 
-	if (lineEnds == null) return -1;
-	if (lineNumber >= lineEnds.length) return -1;
-	if (lineNumber <= 0) return -1;
-	
-	if (lineNumber == lineEnds.length - 1) return eofPosition;
+	if (lineEnds == null) 
+		return -1;
+	if (lineNumber > lineEnds.length+1) 
+		return -1;
+	if (lineNumber <= 0) 
+		return -1;
+	if (lineNumber == lineEnds.length + 1) 
+		return eofPosition;
 	return lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line
 }
 
@@ -414,16 +442,75 @@
  * e.g.	getLineStart(1) --> 0	indicates that the first line starts at character 0.
  *
  * In case the given line number is inconsistent, answers -1.
+ * 
+ * @param lineNumber int
+ * @return int
  */
 public final int getLineStart(int lineNumber) {
 
-	if (lineEnds == null) return -1;
-	if (lineNumber >= lineEnds.length) return -1;
-	if (lineNumber <= 0) return -1;
+	if (lineEnds == null) 
+		return -1;
+	if (lineNumber > lineEnds.length + 1) 
+		return -1;
+	if (lineNumber <= 0) 
+		return -1;
 	
-	if (lineNumber == 1) return initialPosition;
+	if (lineNumber == 1) 
+		return initialPosition;
 	return lineEnds[lineNumber-2]+1; // next line start one character behind the lineEnd of the previous line
 }
+public final int getNextChar() {
+	try {
+		if (((currentCharacter = source[currentPosition++]) == '\\')
+			&& (source[currentPosition] == 'u')) {
+			//-------------unicode traitement ------------
+			int c1, c2, c3, c4;
+			int unicodeSize = 6;
+			currentPosition++;
+			while (source[currentPosition] == 'u') {
+				currentPosition++;
+				unicodeSize++;
+			}
+
+			if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+				|| c1 < 0)
+				|| ((c2 = Character.getNumericValue(source[currentPosition++])) > 15 || c2 < 0)
+				|| ((c3 = Character.getNumericValue(source[currentPosition++])) > 15 || c3 < 0)
+				|| ((c4 = Character.getNumericValue(source[currentPosition++])) > 15 || c4 < 0)) {
+				return -1;
+			}
+
+			currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+
+			unicodeAsBackSlash = currentCharacter == '\\';
+
+			//need the unicode buffer
+			if (withoutUnicodePtr == 0) {
+				//buffer all the entries that have been left aside....
+				withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
+				System.arraycopy(
+					source, 
+					startPosition, 
+					withoutUnicodeBuffer, 
+					1, 
+					withoutUnicodePtr); 
+			}
+			//fill the buffer with the char
+			withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+			return currentCharacter;
+
+		} //-------------end unicode traitement--------------
+		else {
+			unicodeAsBackSlash = false;
+			if (withoutUnicodePtr != 0) {
+				withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+			}
+			return currentCharacter;
+		}
+	} catch (IndexOutOfBoundsException e) {
+		return -1;
+	}
+}
 public final boolean getNextChar(char testedChar) {
 	//BOOLEAN
 	//handle the case of unicode.
@@ -783,7 +870,6 @@
 	}
 }
 public int getNextToken() throws InvalidInputException {
-
 	this.wasAcr = false;
 	if (diet) {
 		jumpOverMethodBody();
@@ -822,7 +908,7 @@
 				} else {
 					offset = 1;
 					if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
-						checkNonExternalizeString();
+						checkNonExternalizedString();
 						if (recordLineSeparator) {
 							pushLineSeparator();
 						} else {
@@ -1229,7 +1315,7 @@
 								recordComment(false);
 								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
 								if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
-									checkNonExternalizeString();
+									checkNonExternalizedString();
 									if (recordLineSeparator) {
 										if (isUnicode) {
 											pushUnicodeLineSeparator();
@@ -1244,16 +1330,18 @@
 									return TokenNameCOMMENT_LINE;
 								}
 							} catch (IndexOutOfBoundsException e) {
+								currentPosition--;
 								recordComment(false);
-								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition-1);
+								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
 								if (tokenizeComments) {
-									this.currentPosition--; // reset one character behind
 									return TokenNameCOMMENT_LINE;
+								} else {
+									this.currentPosition++; 
 								}
 							}
 							break;
 						}
-						if (test > 0) { //traditional and annotation comment
+						if (test > 0) { //traditional and javadoc comment
 							try { //get the next char
 								boolean isJavadoc = false, star = false;
 								boolean isUnicode = false;
@@ -1275,7 +1363,7 @@
 									star = true;
 								}
 								if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
-									checkNonExternalizeString();
+									checkNonExternalizedString();
 									if (recordLineSeparator) {
 										if (!isUnicode) {
 											pushLineSeparator();
@@ -1298,10 +1386,14 @@
 									if (source[currentPosition] == '\\')
 										currentPosition++; //jump over the \\
 								}
+								// empty comment is not a javadoc /**/
+								if (currentCharacter == '/') { 
+									isJavadoc = false;
+								}
 								//loop until end of comment */
 								while ((currentCharacter != '/') || (!star)) {
 									if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
-										checkNonExternalizeString();
+										checkNonExternalizedString();
 										if (recordLineSeparator) {
 											if (!isUnicode) {
 												pushLineSeparator();
@@ -1457,7 +1549,8 @@
 							try {
 								scanEscapeCharacter();
 							} catch (InvalidInputException ex) {
-							};
+								// ignore
+							}
 						} else {
 							try { // consume next character
 								unicodeAsBackSlash = false;
@@ -1470,7 +1563,8 @@
 									}
 								}
 							} catch (InvalidInputException ex) {
-							};
+								// ignore
+							}
 						}
 						getNextChar('\'');
 						break;
@@ -1488,7 +1582,8 @@
 								}
 							}
 						} catch (InvalidInputException ex) {
-						};
+								// ignore
+						}
 						while (currentCharacter != '"') {
 							if (currentCharacter == '\r'){
 								if (source[currentPosition] == '\n') currentPosition++;
@@ -1501,7 +1596,8 @@
 								try {
 									scanEscapeCharacter();
 								} catch (InvalidInputException ex) {
-								};
+									// ignore
+								}
 							}
 							try { // consume next character
 								unicodeAsBackSlash = false;
@@ -1514,7 +1610,8 @@
 									}
 								}
 							} catch (InvalidInputException ex) {
-							};
+								// ignore
+							}
 						}
 					} catch (IndexOutOfBoundsException e) {
 						return;
@@ -1588,10 +1685,11 @@
 										}
 									}
 							} catch (IndexOutOfBoundsException e) {
-							} //an eof will them be generated
+								 //an eof will then be generated
+							}
 							break;
 						}
-						if (test > 0) { //traditional and annotation comment
+						if (test > 0) { //traditional and javadoc comment
 							isUnicode = false;
 							boolean star = false;
 							try { // consume next character
@@ -1605,9 +1703,10 @@
 									if (withoutUnicodePtr != 0) {
 										withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 									}
-								};
+								}
 							} catch (InvalidInputException ex) {
-							};
+ 								// ignore
+ 							}
 							if (currentCharacter == '*') {
 								star = true;
 							}
@@ -1689,24 +1788,24 @@
 
 				default :
 					if (Character.isJavaIdentifierStart(currentCharacter)) {
-						try {
-							scanIdentifierOrKeyword();
-						} catch (InvalidInputException ex) {
-						};
+						scanIdentifierOrKeyword();
 						break;
 					}
 					if (Character.isDigit(currentCharacter)) {
 						try {
 							scanNumber(false);
 						} catch (InvalidInputException ex) {
-						};
+ 							// ignore
+ 						}
 						break;
 					}
 			}
 		}
 		//-----------------end switch while try--------------------
 	} catch (IndexOutOfBoundsException e) {
+		// ignore
 	} catch (InvalidInputException e) {
+		// ignore
 	}
 	return;
 }
@@ -1995,7 +2094,7 @@
 	newEntry6 = max;
 	return r;	
 }
-private void parseTags(NLSLine line) throws InvalidInputException {
+private void parseTags(NLSLine line) {
 	String s = new String(getCurrentTokenSource());
 	int pos = s.indexOf(TAG_PREFIX);
 	int lineLength = line.size();
@@ -2037,7 +2136,7 @@
 	currentLine = null;
 }
 
-public final void pushLineSeparator() throws InvalidInputException {
+public final void pushLineSeparator() {
 	//see comment on isLineDelimiter(char) for the use of '\n' and '\r'
 	final int INCREMENT = 250;
 	
@@ -2050,7 +2149,8 @@
 	// cr 000D
 	if (currentCharacter == '\r') {
 		int separatorPos = currentPosition - 1;
-		if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos)) return;
+		//TODO (olivier) david - why the following line was "if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos)) return;" ?
+		if ((linePtr >= 0) && (lineEnds[linePtr] >= separatorPos)) return;
 		//System.out.println("CR-" + separatorPos);
 		try {
 			lineEnds[++linePtr] = separatorPos;
@@ -2083,7 +2183,8 @@
 				lineEnds[linePtr] = currentPosition - 1;
 			} else {
 				int separatorPos = currentPosition - 1;
-				if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos)) return;
+				//TODO (olivier) david - why the following line was "if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos)) return;" ?
+				if ((linePtr >= 0) && (lineEnds[linePtr] >= separatorPos)) return;
 				// System.out.println("LF-" + separatorPos);							
 				try {
 					lineEnds[++linePtr] = separatorPos;
@@ -2122,7 +2223,7 @@
 }
 public final void recordComment(boolean isJavadoc) {
 
-	// a new annotation comment is recorded
+	// a new comment is recorded
 	try {
 		this.commentStops[++this.commentPtr] = isJavadoc ? this.currentPosition : -this.currentPosition;
 	} catch (IndexOutOfBoundsException e) {
@@ -2141,6 +2242,13 @@
 	this.commentStarts[this.commentPtr] = this.startPosition;
 }
 
+/**
+ * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position.
+ * Beyond this position, the scanner will answer EOF tokens (<code>ITerminalSymbols.TokenNameEOF</code>).
+ * 
+ * @param begin the given start position
+ * @param end the given end position
+ */
 public void resetTo(int begin, int end) {
 	//reset the scanner to a given position where it may rescan again
 
@@ -2149,7 +2257,11 @@
 	eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
 	commentPtr = -1; // reset comment stack
 	foundTaskCount = 0;
-
+	
+//	// if resetTo is used with being > than end.
+//	if (begin > eofPosition) {
+//		begin = eofPosition;
+//	}
 }
 
 public final void scanEscapeCharacter() throws InvalidInputException {
@@ -2233,7 +2345,7 @@
 				throw new InvalidInputException(INVALID_ESCAPE);
 	}
 }
-public int scanIdentifierOrKeyword() throws InvalidInputException {
+public int scanIdentifierOrKeyword() {
 	//test keywords
 
 	//first dispatch on the first char.
@@ -2241,7 +2353,7 @@
 	//keywors with the same length AND the same first char, then do another
 	//dispatch on the second char 
 	useAssertAsAnIndentifier = false;
-	while (getNextCharAsJavaIdentifierPart()) {};
+	while (getNextCharAsJavaIdentifierPart());
 
 	int index, length;
 	char[] data;
@@ -2821,7 +2933,7 @@
 			if (Character.digit(currentCharacter, 16) == -1)
 				throw new InvalidInputException(INVALID_HEXA);
 			//---end forcing--
-			while (getNextCharAsDigit(16)) {};
+			while (getNextCharAsDigit(16));
 			if (getNextChar('l', 'L') >= 0)
 				return TokenNameLongLiteral;
 			else
@@ -2831,7 +2943,7 @@
 		//there is x or X in the number
 		//potential octal ! ... some one may write 000099.0 ! thus 00100 < 00078.0 is true !!!!! crazy language
 		if (getNextCharAsDigit()) { //-------------potential octal-----------------
-			while (getNextCharAsDigit()) {};
+			while (getNextCharAsDigit());
 
 			if (getNextChar('l', 'L') >= 0) {
 				return TokenNameLongLiteral;
@@ -2847,7 +2959,7 @@
 				boolean isInteger = true;
 				if (getNextChar('.')) { 
 					isInteger = false;
-					while (getNextCharAsDigit()) {};
+					while (getNextCharAsDigit());
 				}
 				if (getNextChar('e', 'E') >= 0) { // consume next character
 					isInteger = false;
@@ -2875,7 +2987,7 @@
 					}
 					if (!Character.isDigit(currentCharacter))
 						throw new InvalidInputException(INVALID_FLOAT);
-					while (getNextCharAsDigit()) {};
+					while (getNextCharAsDigit());
 				}
 				if (getNextChar('f', 'F') >= 0)
 					return TokenNameFloatingPointLiteral;
@@ -2888,13 +3000,13 @@
 		}
 	}
 
-	while (getNextCharAsDigit()) {};
+	while (getNextCharAsDigit());
 
 	if ((!dotPrefix) && (getNextChar('l', 'L') >= 0))
 		return TokenNameLongLiteral;
 
 	if ((!dotPrefix) && (getNextChar('.'))) { //decimal part that can be empty
-		while (getNextCharAsDigit()) {};
+		while (getNextCharAsDigit());
 		floating = true;
 	}
 
@@ -2927,7 +3039,7 @@
 		}
 		if (!Character.isDigit(currentCharacter))
 			throw new InvalidInputException(INVALID_FLOAT);
-		while (getNextCharAsDigit()) {};
+		while (getNextCharAsDigit());
 	}
 
 	if (getNextChar('d', 'D') >= 0)
@@ -2941,7 +3053,8 @@
 }
 /**
  * Search the line number corresponding to a specific position
- *
+ * @param position int
+ * @return int
  */
 public final int getLineNumber(int position) {
 
@@ -2967,27 +3080,29 @@
 	}
 	return m+2;
 }
-public final void setSource(char[] source){
+public final void setSource(char[] sourceString){
 	//the source-buffer is set to sourceString
 
-	if (source == null) {
+	int sourceLength;
+	if (sourceString == null) {
 		this.source = CharOperation.NO_CHAR;
+		sourceLength = 0;
 	} else {
-		this.source = source;
+		this.source = sourceString;
+		sourceLength = sourceString.length;
 	}
 	startPosition = -1;
-	eofPosition = source.length;
+	eofPosition = sourceLength;
 	initialPosition = currentPosition = 0;
 	containsAssertKeyword = false;
-	withoutUnicodeBuffer = new char[this.source.length];
-
+	withoutUnicodeBuffer = new char[sourceLength]; // TODO (philippe) should only allocate when needed
 }
 
 public String toString() {
 	if (startPosition == source.length)
 		return "EOF\n\n" + new String(source); //$NON-NLS-1$
 	if (currentPosition > source.length)
-		return "behind the EOF :-( ....\n\n" + new String(source); //$NON-NLS-1$
+		return "behind the EOF\n\n" + new String(source); //$NON-NLS-1$
 
 	char front[] = new char[startPosition];
 	System.arraycopy(source, 0, front, 0, startPosition);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/SourceFieldDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/SourceFieldDeclaration.java
index fe97ea5..8cc8955 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/SourceFieldDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/SourceFieldDeclaration.java
@@ -10,16 +10,14 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.parser;
 
-import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 
 public class SourceFieldDeclaration extends FieldDeclaration {
 	public int fieldEndPosition;
 public SourceFieldDeclaration(
-	Expression initialization, 
 	char[] name, 
 	int sourceStart, 
 	int sourceEnd) {
-	super(initialization, name, sourceStart, sourceEnd);
+	super(name, sourceStart, sourceEnd);
 }
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
index a45c709..bf8049f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
@@ -25,6 +25,7 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
 import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
@@ -33,28 +34,36 @@
 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.MemberTypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.env.ISourceField;
+import org.eclipse.jdt.internal.compiler.env.ISourceImport;
 import org.eclipse.jdt.internal.compiler.env.ISourceMethod;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 
 public class SourceTypeConverter implements CompilerModifiers {
 	
-	private boolean needFieldInitialization;
+	public static final int FIELD = 0x01;
+	public static final int CONSTRUCTOR = 0x02;
+	public static final int METHOD = 0x04;
+	public static final int MEMBER_TYPE = 0x08;
+	public static final int FIELD_INITIALIZATION = 0x10;
+	public static final int FIELD_AND_METHOD = FIELD | CONSTRUCTOR | METHOD;
+	public static final int NONE = 0;
+	
+	private int flags;
 	private CompilationUnitDeclaration unit;
 	private Parser parser;
 	private ProblemReporter problemReporter;
 	
-	private SourceTypeConverter(boolean needFieldInitialization, ProblemReporter problemReporter) {
-		this.needFieldInitialization = needFieldInitialization;
+	private SourceTypeConverter(int flags, ProblemReporter problemReporter) {
+		this.flags = flags;
 		this.problemReporter = problemReporter;
 	}
 
@@ -66,18 +75,12 @@
 	 */
 	public static CompilationUnitDeclaration buildCompilationUnit(
 		ISourceType[] sourceTypes,
-		boolean needFieldsAndMethods,
-		boolean needMemberTypes,
-		boolean needFieldInitialization,
+		int flags,
 		ProblemReporter problemReporter,
 		CompilationResult compilationResult) {
 			
 		return 
-			new SourceTypeConverter(needFieldInitialization, problemReporter).convert(
-				sourceTypes, 
-				needFieldsAndMethods,
-				needMemberTypes,
-				compilationResult);
+			new SourceTypeConverter(flags, problemReporter).convert(sourceTypes, compilationResult);
 	}
 
 	/*
@@ -85,16 +88,12 @@
 	 * The argument types are then all grouped in the same unit. The argument types must 
 	 * at least contain one type.
 	 */
-	private CompilationUnitDeclaration convert(
-		ISourceType[] sourceTypes,
-		boolean needFieldsAndMethods,
-		boolean needMemberTypes,
-		CompilationResult compilationResult) {
+	private CompilationUnitDeclaration convert(ISourceType[] sourceTypes, CompilationResult compilationResult) {
 		ISourceType sourceType = sourceTypes[0];
 		if (sourceType.getName() == null)
 			return null; // do a basic test that the sourceType is valid
 
-		this.unit = new CompilationUnitDeclaration(problemReporter, compilationResult, 0);
+		this.unit = new CompilationUnitDeclaration(this.problemReporter, compilationResult, 0);
 		// not filled at this point
 
 		/* only positions available */
@@ -106,18 +105,25 @@
 			&& sourceType.getPackageName().length > 0)
 			// if its null then it is defined in the default package
 			this.unit.currentPackage =
-				createImportReference(sourceType.getPackageName(), start, end);
-		char[][] importNames = sourceType.getImports();
-		int importCount = importNames == null ? 0 : importNames.length;
+				createImportReference(sourceType.getPackageName(), start, end, false, AccDefault);
+		ISourceImport[]  sourceImports = sourceType.getImports();
+		int importCount = sourceImports == null ? 0 : sourceImports.length;
 		this.unit.imports = new ImportReference[importCount];
-		for (int i = 0; i < importCount; i++)
-			this.unit.imports[i] = createImportReference(importNames[i], start, end);
+		for (int i = 0; i < importCount; i++) {
+			ISourceImport sourceImport = sourceImports[i];
+			this.unit.imports[i] = createImportReference(
+				sourceImport.getName(), 
+				sourceImport.getDeclarationSourceStart(),
+				sourceImport.getDeclarationSourceEnd(),
+				sourceImport.onDemand(),
+				sourceImport.getModifiers());
+		}
 		/* convert type(s) */
 		int typeCount = sourceTypes.length;
 		this.unit.types = new TypeDeclaration[typeCount];
 		for (int i = 0; i < typeCount; i++) {
 			this.unit.types[i] =
-				convert(sourceTypes[i], needFieldsAndMethods, needMemberTypes, compilationResult);
+				convert(sourceTypes[i], compilationResult);
 		}
 		return this.unit;
 	}
@@ -140,16 +146,12 @@
 		field.declarationSourceEnd = sourceField.getDeclarationSourceEnd();
 		field.modifiers = sourceField.getModifiers();
 
-		if (this.needFieldInitialization) {
+		if ((this.flags & FIELD_INITIALIZATION) != 0) {
 			/* conversion of field constant */
 			char[] initializationSource = sourceField.getInitializationSource();
 			if (initializationSource != null) {
 				if (this.parser == null) {
-					this.parser = 
-						new Parser(
-							this.problemReporter, 
-							true, 
-							this.problemReporter.options.sourceLevel >= CompilerOptions.JDK1_4);
+					this.parser = new Parser(this.problemReporter, true);
 				}
 				this.parser.parse(field, type, this.unit, initializationSource);
 			}
@@ -216,20 +218,12 @@
 
 	/*
 	 * Convert a source element type into a parsed type declaration
-	 *
-	 * Can optionally ignore fields & methods
 	 */
-	private TypeDeclaration convert(
-		ISourceType sourceType,
-		boolean needFieldsAndMethods,
-		boolean needMemberTypes,
-		CompilationResult compilationResult) {
+	private TypeDeclaration convert(ISourceType sourceType, CompilationResult compilationResult) {
 		/* create type declaration - can be member type */
-		TypeDeclaration type;
-		if (sourceType.getEnclosingType() == null) {
-			type = new TypeDeclaration(compilationResult);
-		} else {
-			type = new MemberTypeDeclaration(compilationResult);
+		TypeDeclaration type = type = new TypeDeclaration(compilationResult);
+		if (sourceType.getEnclosingType() != null) {
+			type.bits |= ASTNode.IsMemberTypeMASK;
 		}
 		type.name = sourceType.getName();
 		int start, end; // only positions available
@@ -251,59 +245,72 @@
 			type.superInterfaces[i] = createTypeReference(interfaceNames[i], start, end);
 		}
 		/* convert member types */
-		if (needMemberTypes) {
+		if ((this.flags & MEMBER_TYPE) != 0) {
 			ISourceType[] sourceMemberTypes = sourceType.getMemberTypes();
 			int sourceMemberTypeCount =
 				sourceMemberTypes == null ? 0 : sourceMemberTypes.length;
-			type.memberTypes = new MemberTypeDeclaration[sourceMemberTypeCount];
+			type.memberTypes = new TypeDeclaration[sourceMemberTypeCount];
 			for (int i = 0; i < sourceMemberTypeCount; i++) {
-				type.memberTypes[i] =
-					(MemberTypeDeclaration) convert(sourceMemberTypes[i],
-						needFieldsAndMethods,
-						true,
-						compilationResult);
+				type.memberTypes[i] = convert(sourceMemberTypes[i], compilationResult);
 			}
 		}
-		/* convert fields and methods */
-		if (needFieldsAndMethods) {
-			/* convert fields */
+
+		/* convert fields */
+		if ((this.flags & FIELD) != 0) {
 			ISourceField[] sourceFields = sourceType.getFields();
 			int sourceFieldCount = sourceFields == null ? 0 : sourceFields.length;
 			type.fields = new FieldDeclaration[sourceFieldCount];
 			for (int i = 0; i < sourceFieldCount; i++) {
 				type.fields[i] = convert(sourceFields[i], type);
 			}
+		}
 
-			/* convert methods - need to add default constructor if necessary */
+		/* convert methods - need to add default constructor if necessary */
+		boolean needConstructor = (this.flags & CONSTRUCTOR) != 0;
+		boolean needMethod = (this.flags & METHOD) != 0;
+		if (needConstructor || needMethod) {
+			
 			ISourceMethod[] sourceMethods = sourceType.getMethods();
 			int sourceMethodCount = sourceMethods == null ? 0 : sourceMethods.length;
-
+	
 			/* source type has a constructor ?           */
 			/* by default, we assume that one is needed. */
-			int neededCount = 0;
-			if (!type.isInterface()) {
-				neededCount = 1;
+			int extraConstructor = 0;
+			int methodCount = 0;
+			boolean isInterface = type.isInterface();
+			if (!isInterface) {
+				extraConstructor = needConstructor ? 1 : 0;
 				for (int i = 0; i < sourceMethodCount; i++) {
 					if (sourceMethods[i].isConstructor()) {
-						neededCount = 0;
-						// Does not need the extra constructor since one constructor already exists.
-						break;
+						if (needConstructor) {
+							extraConstructor = 0; // Does not need the extra constructor since one constructor already exists.
+							methodCount++;
+						}
+					} else if (needMethod) {
+						methodCount++;
 					}
 				}
+			} else {
+				methodCount = needMethod ? sourceMethodCount : 0;
 			}
-			type.methods = new AbstractMethodDeclaration[sourceMethodCount + neededCount];
-			if (neededCount != 0) { // add default constructor in first position
+			type.methods = new AbstractMethodDeclaration[methodCount + extraConstructor];
+			if (extraConstructor != 0) { // add default constructor in first position
 				type.methods[0] = type.createsInternalConstructor(false, false);
 			}
-			boolean isInterface = type.isInterface();
+			int index = 0;
 			for (int i = 0; i < sourceMethodCount; i++) {
-				AbstractMethodDeclaration method =convert(sourceMethods[i], compilationResult);
-				if (isInterface || method.isAbstract()) { // fix-up flag 
-					method.modifiers |= AccSemicolonBody;
+				ISourceMethod sourceMethod = sourceMethods[i];
+				boolean isConstructor = sourceMethod.isConstructor();
+				if ((isConstructor && needConstructor) || (!isConstructor && needMethod)) {
+					AbstractMethodDeclaration method =convert(sourceMethod, compilationResult);
+					if (isInterface || method.isAbstract()) { // fix-up flag 
+						method.modifiers |= AccSemicolonBody;
+					}
+					type.methods[extraConstructor + index++] = method;
 				}
-				type.methods[neededCount + i] = method;
 			}
 		}
+		
 		return type;
 	}
 
@@ -313,29 +320,21 @@
 	private ImportReference createImportReference(
 		char[] importName,
 		int start,
-		int end) {
-
-		/* count identifiers */
-		int max = importName.length;
-		int identCount = 0;
-		for (int i = 0; i < max; i++) {
-			if (importName[i] == '.')
-				identCount++;
-		}
-		/* import on demand? */
-		boolean onDemand = importName[max - 1] == '*';
-		if (!onDemand)
-			identCount++; // one more ident than dots
-
-		long[] positions = new long[identCount];
+		int end, 
+		boolean onDemand,
+		int modifiers) {
+	
+		char[][] qImportName = CharOperation.splitOn('.', importName);
+		long[] positions = new long[qImportName.length];
 		long position = (long) start << 32 + end;
-		for (int i = 0; i < identCount; i++) {
-			positions[i] = position;
+		for (int i = 0; i < qImportName.length; i++) {
+			positions[i] = position; // dummy positions
 		}
 		return new ImportReference(
-			CharOperation.splitOn('.', importName, 0, max - (onDemand ? 2 : 0)),
+			qImportName,
 			positions,
-			onDemand);
+			onDemand,
+			modifiers);
 	}
 
 	/*
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
index e4869db..9a24cf8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
@@ -36,110 +36,110 @@
 		TokenNameCOMMENT_BLOCK = 1002,
 		TokenNameCOMMENT_JAVADOC = 1003;
 	
-    int
-      TokenNameIdentifier = 6,
-      TokenNameabstract = 99,
-      TokenNameassert = 121,
-      TokenNameboolean = 25,
-      TokenNamebreak = 122,
-      TokenNamebyte = 26,
-      TokenNamecase = 211,
-      TokenNamecatch = 225,
-      TokenNamechar = 27,
-      TokenNameclass = 166,
-      TokenNamecontinue = 123,
-      TokenNamedefault = 212,
-      TokenNamedo = 124,
-      TokenNamedouble = 28,
-      TokenNameelse = 213,
-      TokenNameextends = 243,
+	int
+      TokenNameIdentifier = 28,
+      TokenNameabstract = 60,
+      TokenNameassert = 71,
+      TokenNameboolean = 31,
+      TokenNamebreak = 72,
+      TokenNamebyte = 32,
+      TokenNamecase = 83,
+      TokenNamecatch = 86,
+      TokenNamechar = 33,
+      TokenNameclass = 81,
+      TokenNamecontinue = 73,
+      TokenNamedefault = 84,
+      TokenNamedo = 74,
+      TokenNamedouble = 34,
+      TokenNameelse = 87,
+      TokenNameextends = 91,
       TokenNamefalse = 44,
-      TokenNamefinal = 100,
-      TokenNamefinally = 226,
-      TokenNamefloat = 29,
-      TokenNamefor = 125,
-      TokenNameif = 126,
-      TokenNameimplements = 268,
-      TokenNameimport = 191,
-      TokenNameinstanceof = 16,
-      TokenNameint = 30,
-      TokenNameinterface = 169,
-      TokenNamelong = 31,
-      TokenNamenative = 101,
-      TokenNamenew = 40,
+      TokenNamefinal = 61,
+      TokenNamefinally = 88,
+      TokenNamefloat = 35,
+      TokenNamefor = 75,
+      TokenNameif = 76,
+      TokenNameimplements = 103,
+      TokenNameimport = 82,
+      TokenNameinstanceof = 13,
+      TokenNameint = 36,
+      TokenNameinterface = 89,
+      TokenNamelong = 37,
+      TokenNamenative = 62,
+      TokenNamenew = 41,
       TokenNamenull = 45,
-      TokenNamepackage = 214,
-      TokenNameprivate = 102,
-      TokenNameprotected = 103,
-      TokenNamepublic = 104,
-      TokenNamereturn = 127,
-      TokenNameshort = 32,
-      TokenNamestatic = 97,
-      TokenNamestrictfp = 105,
+      TokenNamepackage = 85,
+      TokenNameprivate = 63,
+      TokenNameprotected = 64,
+      TokenNamepublic = 65,
+      TokenNamereturn = 77,
+      TokenNameshort = 38,
+      TokenNamestatic = 57,
+      TokenNamestrictfp = 66,
       TokenNamesuper = 42,
-      TokenNameswitch = 128,
-      TokenNamesynchronized = 88,
+      TokenNameswitch = 78,
+      TokenNamesynchronized = 55,
       TokenNamethis = 43,
-      TokenNamethrow = 129,
-      TokenNamethrows = 227,
-      TokenNametransient = 106,
+      TokenNamethrow = 79,
+      TokenNamethrows = 104,
+      TokenNametransient = 67,
       TokenNametrue = 46,
-      TokenNametry = 130,
-      TokenNamevoid = 33,
-      TokenNamevolatile = 107,
-      TokenNamewhile = 120,
+      TokenNametry = 80,
+      TokenNamevoid = 39,
+      TokenNamevolatile = 68,
+      TokenNamewhile = 70,
       TokenNameIntegerLiteral = 47,
       TokenNameLongLiteral = 48,
       TokenNameFloatingPointLiteral = 49,
       TokenNameDoubleLiteral = 50,
       TokenNameCharacterLiteral = 51,
       TokenNameStringLiteral = 52,
-      TokenNamePLUS_PLUS = 3,
-      TokenNameMINUS_MINUS = 4,
-      TokenNameEQUAL_EQUAL = 23,
-      TokenNameLESS_EQUAL = 17,
-      TokenNameGREATER_EQUAL = 18,
-      TokenNameNOT_EQUAL = 24,
-      TokenNameLEFT_SHIFT = 13,
-      TokenNameRIGHT_SHIFT = 11,
-      TokenNameUNSIGNED_RIGHT_SHIFT = 12,
-      TokenNamePLUS_EQUAL = 170,
-      TokenNameMINUS_EQUAL = 171,
-      TokenNameMULTIPLY_EQUAL = 172,
-      TokenNameDIVIDE_EQUAL = 173,
-      TokenNameAND_EQUAL = 174,
-      TokenNameOR_EQUAL = 175,
-      TokenNameXOR_EQUAL = 176,
-      TokenNameREMAINDER_EQUAL = 177,
-      TokenNameLEFT_SHIFT_EQUAL = 178,
-      TokenNameRIGHT_SHIFT_EQUAL = 179,
-      TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 180,
-      TokenNameOR_OR = 73,
-      TokenNameAND_AND = 72,
+      TokenNamePLUS_PLUS = 7,
+      TokenNameMINUS_MINUS = 8,
+      TokenNameEQUAL_EQUAL = 18,
+      TokenNameLESS_EQUAL = 14,
+      TokenNameGREATER_EQUAL = 15,
+      TokenNameNOT_EQUAL = 19,
+      TokenNameLEFT_SHIFT = 11,
+      TokenNameRIGHT_SHIFT = 9,
+      TokenNameUNSIGNED_RIGHT_SHIFT = 10,
+      TokenNamePLUS_EQUAL = 92,
+      TokenNameMINUS_EQUAL = 93,
+      TokenNameMULTIPLY_EQUAL = 94,
+      TokenNameDIVIDE_EQUAL = 95,
+      TokenNameAND_EQUAL = 96,
+      TokenNameOR_EQUAL = 97,
+      TokenNameXOR_EQUAL = 98,
+      TokenNameREMAINDER_EQUAL = 99,
+      TokenNameLEFT_SHIFT_EQUAL = 100,
+      TokenNameRIGHT_SHIFT_EQUAL = 101,
+      TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL = 102,
+      TokenNameOR_OR = 24,
+      TokenNameAND_AND = 25,
       TokenNamePLUS = 1,
       TokenNameMINUS = 2,
-      TokenNameNOT = 75,
-      TokenNameREMAINDER = 8,
-      TokenNameXOR = 68,
-      TokenNameAND = 38,
-      TokenNameMULTIPLY = 7,
-      TokenNameOR = 71,
-      TokenNameTWIDDLE = 76,
-      TokenNameDIVIDE = 9,
-      TokenNameGREATER = 19,
-      TokenNameLESS = 20,
-      TokenNameLPAREN = 10,
-      TokenNameRPAREN = 81,
-      TokenNameLBRACE = 111,
-      TokenNameRBRACE = 86,
-      TokenNameLBRACKET = 14,
-      TokenNameRBRACKET = 119,
-      TokenNameSEMICOLON = 41,
-      TokenNameQUESTION = 74,
-      TokenNameCOLON = 110,
-      TokenNameCOMMA = 82,
-      TokenNameDOT = 5,
-      TokenNameEQUAL = 167,
-      TokenNameEOF = 114,
-      TokenNameERROR = 308;
+      TokenNameNOT = 58,
+      TokenNameREMAINDER = 5,
+      TokenNameXOR = 21,
+      TokenNameAND = 20,
+      TokenNameMULTIPLY = 4,
+      TokenNameOR = 22,
+      TokenNameTWIDDLE = 56,
+      TokenNameDIVIDE = 6,
+      TokenNameGREATER = 16,
+      TokenNameLESS = 17,
+      TokenNameLPAREN = 27,
+      TokenNameRPAREN = 29,
+      TokenNameLBRACE = 59,
+      TokenNameRBRACE = 40,
+      TokenNameLBRACKET = 12,
+      TokenNameRBRACKET = 69,
+      TokenNameSEMICOLON = 23,
+      TokenNameQUESTION = 26,
+      TokenNameCOLON = 53,
+      TokenNameCOMMA = 30,
+      TokenNameDOT = 3,
+      TokenNameEQUAL = 90,
+      TokenNameEOF = 54,
+      TokenNameERROR = 105;
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
new file mode 100644
index 0000000..7c94bc7
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
@@ -0,0 +1,2201 @@
+/*******************************************************************************
+ * 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 Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser.diagnose;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.parser.ParserBasicInformation;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+
+public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
+	private static final boolean DEBUG = false;
+	
+	private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+	private static final int STACK_INCREMENT = 256;
+	
+//	private static final int ERROR_CODE = 1;
+	private static final int BEFORE_CODE = 2;
+	private static final int INSERTION_CODE = 3;
+	private static final int INVALID_CODE = 4;
+	private static final int SUBSTITUTION_CODE = 5;
+	private static final int DELETION_CODE = 6;
+	private static final int MERGE_CODE = 7;
+	private static final int MISPLACED_CODE = 8;
+	private static final int SCOPE_CODE = 9;
+	private static final int SECONDARY_CODE = 10;
+	private static final int EOF_CODE = 11;
+
+	private static final int BUFF_UBOUND  = 31;
+	private static final int BUFF_SIZE    = 32;
+	private static final int MAX_DISTANCE = 30;
+	private static final int MIN_DISTANCE = 3;
+	
+	private LexStream lexStream;
+	private int errorToken;
+	private int errorTokenStart;
+	
+	private int currentToken = 0;
+	
+	private int stackLength;
+	private int stateStackTop;
+	private int[] stack;
+	
+	private int[] locationStack;
+	private int[] locationStartStack;
+	
+	private int tempStackTop;
+	private int[] tempStack;
+	
+	private int prevStackTop;
+	private int[] prevStack;
+	private int nextStackTop;
+	private int[] nextStack;
+	
+	private int scopeStackTop;
+    private int[] scopeIndex;
+    private int[] scopePosition;
+	
+	int[] list = new int[NUM_SYMBOLS + 1];
+	int[] buffer = new int[BUFF_SIZE];
+	
+	private static final int NIL = -1;
+	int[] stateSeen;
+	
+	int statePoolTop;
+	StateInfo[] statePool;
+	
+	private Parser parser;
+	
+	private class RepairCandidate {
+		public int symbol;
+		public int location;
+		
+		public RepairCandidate(){
+			this.symbol = 0;
+			this.location = 0;
+		}
+	}
+	
+	private class PrimaryRepairInfo {
+		public int distance;
+		public int misspellIndex;
+		public int code;
+		public int bufferPosition;
+		public int symbol;
+		
+		public PrimaryRepairInfo(){
+			this.distance = 0;
+			this.misspellIndex = 0;
+			this.code = 0;
+			this.bufferPosition = 0;
+			this.symbol = 0;
+		}
+		
+		public PrimaryRepairInfo copy(){
+			PrimaryRepairInfo c = new PrimaryRepairInfo();
+			c.distance = this.distance;
+			c.misspellIndex = this.misspellIndex;
+			c.code = this.code;
+			c.bufferPosition = this .bufferPosition;
+			c.symbol = this.symbol;
+			return c;
+			
+		}
+	}
+	
+	private class SecondaryRepairInfo {
+		public int code;
+		public int distance;
+		public int bufferPosition;
+		public int stackPosition;
+		public int numDeletions;
+		public int symbol;
+
+		boolean recoveryOnNextStack;
+	} 
+	
+	private class StateInfo {
+	    int state;
+	    int next;
+	    
+	    public StateInfo(int state, int next){
+	    	this.state = state;
+	    	this.next = next;
+	    }
+	}
+
+	public DiagnoseParser(Parser parser, int firstToken, int start, int end) {
+		this(parser, firstToken, start, end, new int[0], new int[0], new int[0]);
+	}
+
+	public DiagnoseParser(Parser parser, int firstToken, int start, int end, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip) {
+		this.parser = parser;
+		this.lexStream = new LexStream(BUFF_SIZE, parser.scanner, intervalStartToSkip, intervalEndToSkip, intervalFlagsToSkip, firstToken, start, end);
+	}
+	
+	private ProblemReporter problemReporter(){
+		return parser.problemReporter();
+	}
+
+	private void reallocateStacks()	{
+		int old_stack_length = stackLength;
+
+		stackLength += STACK_INCREMENT;
+
+		if(old_stack_length == 0){
+			stack = new int[stackLength];
+			locationStack = new int[stackLength];
+			locationStartStack = new int[stackLength];
+			tempStack = new int[stackLength];
+			prevStack = new int[stackLength];
+			nextStack = new int[stackLength];
+			scopeIndex = new int[stackLength];
+			scopePosition = new int[stackLength];
+		} else {
+			System.arraycopy(stack, 0, stack = new int[stackLength], 0, old_stack_length);
+			System.arraycopy(locationStack, 0, locationStack = new int[stackLength], 0, old_stack_length);
+			System.arraycopy(locationStartStack, 0, locationStartStack = new int[stackLength], 0, old_stack_length);
+			System.arraycopy(tempStack, 0, tempStack = new int[stackLength], 0, old_stack_length);
+			System.arraycopy(prevStack, 0, prevStack = new int[stackLength], 0, old_stack_length);
+			System.arraycopy(nextStack, 0, nextStack = new int[stackLength], 0, old_stack_length);
+			System.arraycopy(scopeIndex, 0, scopeIndex = new int[stackLength], 0, old_stack_length);
+			System.arraycopy(scopePosition, 0, scopePosition = new int[stackLength], 0, old_stack_length);
+		}
+		return;
+	}
+
+
+	public void diagnoseParse() {
+		lexStream.reset();
+
+		currentToken = lexStream.getToken();
+
+		int prev_pos;
+		int pos;
+		int next_pos;
+		int act = START_STATE;
+
+		reallocateStacks();
+
+		//
+		// Start parsing
+		//
+		stateStackTop = 0;
+		stack[stateStackTop] = act;
+
+		int tok = lexStream.kind(currentToken);
+		locationStack[stateStackTop] = currentToken;
+		locationStartStack[stateStackTop] = lexStream.start(currentToken);
+		
+		boolean forceRecoveryAfterLBracketMissing = false;
+//		int forceRecoveryToken = -1;
+
+		//
+		// Process a terminal
+		//
+		do {
+			//
+			// Synchronize state stacks and update the location stack
+			//
+			prev_pos = -1;
+			prevStackTop = -1;
+
+			next_pos = -1;
+			nextStackTop = -1;
+
+			pos = stateStackTop;
+			tempStackTop = stateStackTop - 1;
+			for (int i = 0; i <= stateStackTop; i++)
+				tempStack[i] = stack[i];
+
+			act = Parser.tAction(act, tok);
+			//
+			// When a reduce action is encountered, we compute all REDUCE
+			// and associated goto actions induced by the current token.
+			// Eventually, a SHIFT, SHIFT-REDUCE, ACCEPT or ERROR action is
+			// computed...
+			//
+			while (act <= NUM_RULES) {
+				do {
+					tempStackTop -= (Parser.rhs[act]-1);
+					act = Parser.ntAction(tempStack[tempStackTop], Parser.lhs[act]);
+				} while(act <= NUM_RULES);
+				//
+				// ... Update the maximum useful position of the
+				// (STATE_)STACK, push goto state into stack, and
+				// compute next action on current symbol ...
+				//
+				if (tempStackTop + 1 >= stackLength)
+					reallocateStacks();
+				pos = pos < tempStackTop ? pos : tempStackTop;
+				tempStack[tempStackTop + 1] = act;
+				act = Parser.tAction(act, tok);
+			}
+
+			//
+			// At this point, we have a shift, shift-reduce, accept or error
+			// action.  STACK contains the configuration of the state stack
+			// prior to executing any action on curtok. next_stack contains
+			// the configuration of the state stack after executing all
+			// reduce actions induced by curtok.  The variable pos indicates
+			// the highest position in STACK that is still useful after the
+			// reductions are executed.
+			//
+			while(act > ERROR_ACTION || act < ACCEPT_ACTION) { // SHIFT-REDUCE action or SHIFT action ?
+				nextStackTop = tempStackTop + 1;
+				for (int i = next_pos + 1; i <= nextStackTop; i++)
+					nextStack[i] = tempStack[i];
+
+				for (int i = pos + 1; i <= nextStackTop; i++) {
+					locationStack[i] = locationStack[stateStackTop];
+					locationStartStack[i] = locationStartStack[stateStackTop];
+				}
+
+				//
+				// If we have a shift-reduce, process it as well as
+				// the goto-reduce actions that follow it.
+				//
+				if (act > ERROR_ACTION) {
+					act -= ERROR_ACTION;
+					do {
+						nextStackTop -= (Parser.rhs[act]-1);
+						act = Parser.ntAction(nextStack[nextStackTop], Parser.lhs[act]);
+					} while(act <= NUM_RULES);
+					pos = pos < nextStackTop ? pos : nextStackTop;
+				}
+
+				if (nextStackTop + 1 >= stackLength)
+					reallocateStacks();
+
+				tempStackTop = nextStackTop;
+				nextStack[++nextStackTop] = act;
+				next_pos = nextStackTop;
+
+				//
+				// Simulate the parser through the next token without
+				// destroying STACK or next_stack.
+				//
+				currentToken = lexStream.getToken();
+				tok = lexStream.kind(currentToken);
+				act = Parser.tAction(act, tok);
+				while(act <= NUM_RULES) {
+					//
+					// ... Process all goto-reduce actions following
+					// reduction, until a goto action is computed ...
+					//
+					do {
+						int lhs_symbol = Parser.lhs[act];
+						if(DEBUG) {
+							System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]);
+						}
+						tempStackTop -= (Parser.rhs[act]-1);
+						act = (tempStackTop > next_pos
+								   ? tempStack[tempStackTop]
+								   : nextStack[tempStackTop]);
+						act = Parser.ntAction(act, lhs_symbol);
+					}   while(act <= NUM_RULES);
+
+					//
+					// ... Update the maximum useful position of the
+					// (STATE_)STACK, push GOTO state into stack, and
+					// compute next action on current symbol ...
+					//
+					if (tempStackTop + 1 >= stackLength)
+						reallocateStacks();
+
+					next_pos = next_pos < tempStackTop ? next_pos : tempStackTop;
+					tempStack[tempStackTop + 1] = act;
+					act = Parser.tAction(act, tok);
+				}
+
+//				if((tok != TokenNameRBRACE || (forceRecoveryToken != currentToken && (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0))
+//					&& (lexStream.flags(currentToken) & LexStream.IS_AFTER_JUMP) !=0) {
+//					act = ERROR_ACTION;
+//					if(forceRecoveryToken != currentToken
+//						&& (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0) {
+//						forceRecoveryAfterLBracketMissing = true;
+//						forceRecoveryToken = currentToken;
+//					}
+//				}
+				
+				//
+				// No error was detected, Read next token into
+				// PREVTOK element, advance CURTOK pointer and
+				// update stacks.
+				//
+				if (act != ERROR_ACTION) {
+					prevStackTop = stateStackTop;
+					for (int i = prev_pos + 1; i <= prevStackTop; i++)
+						prevStack[i] = stack[i];
+					prev_pos = pos;
+
+					stateStackTop = nextStackTop;
+					for (int i = pos + 1; i <= stateStackTop; i++)
+						stack[i] = nextStack[i];
+					locationStack[stateStackTop] = currentToken;
+					locationStartStack[stateStackTop] = lexStream.start(currentToken);
+					pos = next_pos;
+				}
+			}
+
+			//
+			// At this stage, either we have an ACCEPT or an ERROR
+			// action.
+			//
+			if (act == ERROR_ACTION) {
+				//
+				// An error was detected.
+				//
+				RepairCandidate candidate = errorRecovery(currentToken, forceRecoveryAfterLBracketMissing);
+				
+				forceRecoveryAfterLBracketMissing = false;
+				
+				if(parser.reportOnlyOneSyntaxError) {
+					return;
+				}
+
+				act = stack[stateStackTop];
+
+				//
+				// If the recovery was successful on a nonterminal candidate,
+				// parse through that candidate and "read" the next token.
+				//
+				if (candidate.symbol == 0) {
+					break;
+				} else if (candidate.symbol > NT_OFFSET) {
+					int lhs_symbol = candidate.symbol - NT_OFFSET;
+					if(DEBUG) {
+						System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]);
+					}
+					act = Parser.ntAction(act, lhs_symbol);
+					while(act <= NUM_RULES) {
+						stateStackTop -= (Parser.rhs[act]-1);
+						act = Parser.ntAction(stack[stateStackTop], Parser.lhs[act]);
+					}
+					stack[++stateStackTop] = act;
+					currentToken = lexStream.getToken();
+					tok = lexStream.kind(currentToken);
+					locationStack[stateStackTop] = currentToken;
+					locationStartStack[stateStackTop] = lexStream.start(currentToken);
+				} else {
+					tok = candidate.symbol;
+					locationStack[stateStackTop] = candidate.location;
+					locationStartStack[stateStackTop] = lexStream.start(candidate.location);
+				}
+			}
+		} while (act != ACCEPT_ACTION);
+
+		return;
+	}
+
+	//
+//		This routine is invoked when an error is encountered.  It
+//	   tries to diagnose the error and recover from it.  If it is
+//	   successful, the state stack, the current token and the buffer
+//	   are readjusted; i.e., after a successful recovery,
+//	   state_stack_top points to the location in the state stack
+//	   that contains the state on which to recover; curtok
+//	   identifies the symbol on which to recover.
+//
+//	   Up to three configurations may be available when this routine
+//	   is invoked. PREV_STACK may contain the sequence of states
+//	   preceding any action on prevtok, STACK always contains the
+//	   sequence of states preceding any action on curtok, and
+//	   NEXT_STACK may contain the sequence of states preceding any
+//	   action on the successor of curtok.
+//
+	private RepairCandidate errorRecovery(int error_token, boolean forcedError) {
+		this.errorToken = error_token;
+		this.errorTokenStart = lexStream.start(error_token);
+		
+		int prevtok = lexStream.previous(error_token);
+		int prevtokKind = lexStream.kind(prevtok);
+		
+		if(forcedError) {
+			int name_index = Parser.terminal_index[TokenNameLBRACE];
+
+			reportError(INSERTION_CODE, name_index, prevtok, prevtok);
+			
+			RepairCandidate candidate = new RepairCandidate();
+			candidate.symbol = TokenNameLBRACE;
+			candidate.location = error_token;
+			lexStream.reset(error_token);
+			
+			stateStackTop = nextStackTop;
+			for (int j = 0; j <= stateStackTop; j++) {
+				stack[j] = nextStack[j];
+			}
+			locationStack[stateStackTop] = error_token;
+			locationStartStack[stateStackTop] = lexStream.start(error_token);
+			
+			return candidate;
+		}
+
+		//
+		// Try primary phase recoveries. If not successful, try secondary
+		// phase recoveries.  If not successful and we are at end of the
+		// file, we issue the end-of-file error and quit. Otherwise, ...
+		//
+		RepairCandidate candidate = primaryPhase(error_token);
+		if (candidate.symbol != 0) {
+			return candidate;
+		}
+
+		candidate = secondaryPhase(error_token);
+		if (candidate.symbol != 0) {
+			return candidate;
+		}
+
+		if (lexStream.kind(error_token) == EOFT_SYMBOL) {
+			reportError(EOF_CODE,
+						Parser.terminal_index[EOFT_SYMBOL],
+						prevtok,
+						prevtok);
+			candidate.symbol = 0;
+			candidate.location = error_token;
+			return candidate;
+		}
+
+		//
+		// At this point, primary and (initial attempt at) secondary
+		// recovery did not work.  We will now get into "panic mode" and
+		// keep trying secondary phase recoveries until we either find
+		// a successful recovery or have consumed the remaining input
+		// tokens.
+		//
+		while(lexStream.kind(buffer[BUFF_UBOUND]) != EOFT_SYMBOL) {
+			candidate = secondaryPhase(buffer[MAX_DISTANCE - MIN_DISTANCE + 2]);
+			if (candidate.symbol != 0) {
+				return candidate;
+			}
+		}
+
+		//
+		// We reached the end of the file while panicking. Delete all
+		// remaining tokens in the input.
+		//
+		int i;
+		for (i = BUFF_UBOUND; lexStream.kind(buffer[i]) == EOFT_SYMBOL; i--);
+
+		reportError(DELETION_CODE,
+					Parser.terminal_index[prevtokKind],//Parser.terminal_index[lexStream.kind(prevtok)],
+					error_token,
+					buffer[i]);
+
+		candidate.symbol = 0;
+		candidate.location = buffer[i];
+
+		return candidate;
+	}
+
+//
+//	   This function tries primary and scope recovery on each
+//	   available configuration.  If a successful recovery is found
+//	   and no secondary phase recovery can do better, a diagnosis is
+//	   issued, the configuration is updated and the function returns
+//	   "true".  Otherwise, it returns "false".
+//
+	private RepairCandidate primaryPhase(int error_token) {
+		PrimaryRepairInfo repair = new PrimaryRepairInfo();
+		RepairCandidate candidate = new RepairCandidate();
+
+		//
+		// Initialize the buffer.
+		//
+		int i = (nextStackTop >= 0 ? 3 : 2);
+		buffer[i] = error_token;
+
+		for (int j = i; j > 0; j--)
+			buffer[j - 1] = lexStream.previous(buffer[j]);
+
+		for (int k = i + 1; k < BUFF_SIZE; k++)
+			buffer[k] = lexStream.next(buffer[k - 1]);
+
+		//
+		// If NEXT_STACK_TOP > 0 then the parse was successful on CURTOK
+		// and the error was detected on the successor of CURTOK. In
+		// that case, first check whether or not primary recovery is
+		// possible on next_stack ...
+		//
+		if (nextStackTop >= 0) {
+			repair.bufferPosition = 3;
+			repair = checkPrimaryDistance(nextStack, nextStackTop, repair);
+		}
+
+		//
+		// ... Next, try primary recovery on the current token...
+		//
+		PrimaryRepairInfo new_repair = repair.copy();
+
+		new_repair.bufferPosition = 2;
+		new_repair = checkPrimaryDistance(stack, stateStackTop, new_repair);
+		if (new_repair.distance > repair.distance || new_repair.misspellIndex > repair.misspellIndex) {
+			repair = new_repair;
+		}
+
+		//
+		// Finally, if prev_stack_top >= 0 then try primary recovery on
+		// the prev_stack configuration.
+		//
+		
+		if (prevStackTop >= 0) {
+			new_repair = repair.copy();
+			new_repair.bufferPosition = 1;
+			new_repair = checkPrimaryDistance(prevStack,prevStackTop, new_repair);
+			if (new_repair.distance > repair.distance || new_repair.misspellIndex > repair.misspellIndex) {
+				repair = new_repair;
+			}
+		}
+
+		//
+		// Before accepting the best primary phase recovery obtained,
+		// ensure that we cannot do better with a similar secondary
+		// phase recovery.
+		//
+		if (nextStackTop >= 0) {// next_stack available
+			if (secondaryCheck(nextStack,nextStackTop,3,repair.distance)) {
+				return candidate;
+			}
+		}
+		else if (secondaryCheck(stack, stateStackTop, 2, repair.distance)) {
+			return candidate;
+		}
+
+		//
+		// First, adjust distance if the recovery is on the error token;
+		// it is important that the adjustment be made here and not at
+		// each primary trial to prevent the distance tests from being
+		// biased in favor of deferred recoveries which have access to
+		// more input tokens...
+		//
+		repair.distance = repair.distance - repair.bufferPosition + 1;
+
+		//
+		// ...Next, adjust the distance if the recovery is a deletion or
+		// (some form of) substitution...
+		//
+		if (repair.code == INVALID_CODE      ||
+			repair.code == DELETION_CODE     ||
+			repair.code == SUBSTITUTION_CODE ||
+			repair.code == MERGE_CODE) {
+			 repair.distance--;
+		}
+
+		//
+		// ... After adjustment, check if the most successful primary
+		// recovery can be applied.  If not, continue with more radical
+		// recoveries...
+		//
+		if (repair.distance < MIN_DISTANCE) {
+			return candidate;
+		}
+
+		//
+		// When processing an insertion error, if the token preceeding
+		// the error token is not available, we change the repair code
+		// into a BEFORE_CODE to instruct the reporting routine that it
+		// indicates that the repair symbol should be inserted before
+		// the error token.
+		//
+		if (repair.code == INSERTION_CODE) {
+			if (buffer[repair.bufferPosition - 1] == 0) {
+				repair.code = BEFORE_CODE;
+			}
+		}
+
+		//
+		// Select the proper sequence of states on which to recover,
+		// update stack accordingly and call diagnostic routine.
+		//
+		if (repair.bufferPosition == 1) {
+			stateStackTop = prevStackTop;
+			for (int j = 0; j <= stateStackTop; j++) {
+				stack[j] = prevStack[j];
+			}
+		} else if (nextStackTop >= 0 && repair.bufferPosition >= 3) {
+			stateStackTop = nextStackTop;
+			for (int j = 0; j <= stateStackTop; j++) {
+				stack[j] = nextStack[j];
+			}
+			locationStack[stateStackTop] = buffer[3];
+			locationStartStack[stateStackTop] = lexStream.start(buffer[3]);
+		}
+
+		return primaryDiagnosis(repair);
+	}
+
+
+//
+//		   This function checks whether or not a given state has a
+//	   candidate, whose string representaion is a merging of the two
+//	   tokens at positions buffer_position and buffer_position+1 in
+//	   the buffer.  If so, it returns the candidate in question;
+//	   otherwise it returns 0.
+//
+	private int mergeCandidate(int state, int buffer_position) {
+		char[] name1 = lexStream.name(buffer[buffer_position]);
+		char[] name2 = lexStream.name(buffer[buffer_position + 1]);
+		
+		int len  = name1.length + name2.length;
+
+		char[] str = CharOperation.concat(name1, name2);
+
+		for (int k = Parser.asi(state); Parser.asr[k] != 0; k++) {
+			int l = Parser.terminal_index[Parser.asr[k]];
+
+			if (len == Parser.name[l].length()) {
+				char[] name = Parser.name[l].toCharArray();
+
+				if (CharOperation.equals(str, name, false)) {
+					return Parser.asr[k];
+				}
+			}
+		}
+
+		return 0;
+	}
+
+
+//
+//	   This procedure takes as arguments a parsing configuration
+//	   consisting of a state stack (stack and stack_top) and a fixed
+//	   number of input tokens (starting at buffer_position) in the
+//	   input BUFFER; and some reference arguments: repair_code,
+//	   distance, misspell_index, candidate, and stack_position
+//	   which it sets based on the best possible recovery that it
+//	   finds in the given configuration.  The effectiveness of a
+//	   a repair is judged based on two criteria:
+//
+//		 1) the number of tokens that can be parsed after the repair
+//			is applied: distance.
+//		 2) how close to perfection is the candidate that is chosen:
+//			misspell_index.
+//	   When this procedure is entered, distance, misspell_index and
+//	   repair_code are assumed to be initialized.
+//
+	private PrimaryRepairInfo checkPrimaryDistance(int stck[], int stack_top, PrimaryRepairInfo repair) {
+		int i, j, k, next_state, max_pos, act, root, symbol, tok;
+
+		//
+	    //  First, try scope and manual recovery.
+	    //
+	    PrimaryRepairInfo scope_repair = scopeTrial(stck, stack_top, repair.copy());
+	    if (scope_repair.distance > repair.distance)
+	        repair = scope_repair;
+	        
+		//
+		//  Next, try merging the error token with its successor.
+		//
+		symbol = mergeCandidate(stck[stack_top], repair.bufferPosition);
+		if (symbol != 0) {
+			j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+2);
+			if ((j > repair.distance) || (j == repair.distance && repair.misspellIndex < 10)) {
+				repair.misspellIndex = 10;
+				repair.symbol = symbol;
+				repair.distance = j;
+				repair.code = MERGE_CODE;
+			}
+		}
+
+		//
+		// Next, try deletion of the error token.
+		//
+		j = parseCheck(
+				stck,
+				stack_top,
+				lexStream.kind(buffer[repair.bufferPosition + 1]),
+				repair.bufferPosition + 2);
+		if (lexStream.kind(buffer[repair.bufferPosition]) == EOLT_SYMBOL &&
+			lexStream.afterEol(buffer[repair.bufferPosition+1])) {
+			 k = 10;
+		} else {
+			k = 0;
+		}
+		if (j > repair.distance || (j == repair.distance && k > repair.misspellIndex)) {
+			repair.misspellIndex = k;
+			repair.code = DELETION_CODE;
+			repair.distance = j;
+		}
+
+		//
+		// Update the error configuration by simulating all reduce and
+		// goto actions induced by the error token. Then assign the top
+		// most state of the new configuration to next_state.
+		//
+		next_state = stck[stack_top];
+		max_pos = stack_top;
+		tempStackTop = stack_top - 1;
+
+		tok = lexStream.kind(buffer[repair.bufferPosition]);
+		lexStream.reset(buffer[repair.bufferPosition + 1]);
+		act = Parser.tAction(next_state, tok);
+		while(act <= NUM_RULES) {
+			do {
+				tempStackTop -= (Parser.rhs[act]-1);
+				symbol = Parser.lhs[act];
+				act = (tempStackTop > max_pos
+									  ? tempStack[tempStackTop]
+									  : stck[tempStackTop]);
+				act = Parser.ntAction(act, symbol);
+			} while(act <= NUM_RULES);
+			max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+			tempStack[tempStackTop + 1] = act;
+			next_state = act;
+			act = Parser.tAction(next_state, tok);
+		}
+
+		//
+		//  Next, place the list of candidates in proper order.
+		//
+		root = 0;
+		for (i = Parser.asi(next_state); Parser.asr[i] != 0; i++) {
+			symbol = Parser.asr[i];
+			if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL) {
+				if (root == 0) {
+					list[symbol] = symbol;
+				} else {
+					list[symbol] = list[root];
+					list[root] = symbol;
+				}
+				root = symbol;
+			}
+		}
+
+		if (stck[stack_top] != next_state) {
+			for (i = Parser.asi(stck[stack_top]); Parser.asr[i] != 0; i++) {
+				symbol = Parser.asr[i];
+				if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL && list[symbol] == 0) {
+					if (root == 0) {
+						list[symbol] = symbol;
+					} else {
+						list[symbol] = list[root];
+						list[root] = symbol;
+					}
+					root = symbol;
+				}
+			}
+		}
+
+		i = list[root];
+		list[root] = 0;
+		root = i;
+
+		//
+		//  Next, try insertion for each possible candidate available in
+		// the current state, except EOFT and ERROR_SYMBOL.
+		//
+		symbol = root;
+		while(symbol != 0) {
+			if (symbol == EOLT_SYMBOL && lexStream.afterEol(buffer[repair.bufferPosition])) {
+				k = 10;
+			} else {
+				k = 0;
+			}
+			j = parseCheck(stck, stack_top, symbol, repair.bufferPosition);
+			if (j > repair.distance) {
+				repair.misspellIndex = k;
+				repair.distance = j;
+				repair.symbol = symbol;
+				repair.code = INSERTION_CODE;
+			} else if (j == repair.distance && k > repair.misspellIndex) {
+				repair.misspellIndex = k;
+				repair.distance = j;
+				repair.symbol = symbol;
+				repair.code = INSERTION_CODE;
+			} else if (j == repair.distance && k == repair.misspellIndex && isBetterSymbol(symbol, repair.symbol)) {
+				repair.misspellIndex = k;
+				repair.distance = j;
+				repair.symbol = symbol;
+				repair.code = INSERTION_CODE;
+			}
+
+			symbol = list[symbol];
+		}
+
+		//
+		//  Next, Try substitution for each possible candidate available
+		// in the current state, except EOFT and ERROR_SYMBOL.
+		//
+		symbol = root;
+		while(symbol != 0) {
+			if (symbol == EOLT_SYMBOL && lexStream.afterEol(buffer[repair.bufferPosition+1])) {
+				k = 10;
+			} else {
+				k = misspell(symbol, buffer[repair.bufferPosition]);
+			}
+			j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+1);
+			if (j > repair.distance) {
+				repair.misspellIndex = k;
+				repair.distance = j;
+				repair.symbol = symbol;
+				repair.code = SUBSTITUTION_CODE;
+			} else if (j == repair.distance && k > repair.misspellIndex) {
+				repair.misspellIndex = k;
+				repair.symbol = symbol;
+				repair.code = SUBSTITUTION_CODE;
+			} else if (j == repair.distance && k > repair.misspellIndex && isBetterSymbol(symbol, repair.symbol)) {
+				repair.misspellIndex = k;
+				repair.symbol = symbol;
+				repair.code = SUBSTITUTION_CODE;
+			}
+			i = symbol;
+			symbol = list[symbol];
+			list[i] = 0;                             // reset element
+		}
+
+
+		//
+		// Next, we try to insert a nonterminal candidate in front of the
+		// error token, or substituting a nonterminal candidate for the
+		// error token. Precedence is given to insertion.
+		//
+		 for (i = Parser.nasi(stck[stack_top]); Parser.nasr[i] != 0; i++) {
+			 symbol = Parser.nasr[i] + NT_OFFSET;
+			 j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+1);
+			 if (j > repair.distance) {
+				 repair.misspellIndex = 0;
+				 repair.distance = j;
+				 repair.symbol = symbol;
+				 repair.code = INVALID_CODE;
+			 }
+
+			 j = parseCheck(stck, stack_top, symbol, repair.bufferPosition);
+			 if ((j > repair.distance) || (j == repair.distance && repair.code == INVALID_CODE)) {
+				 repair.misspellIndex = 0;
+				 repair.distance = j;
+				 repair.symbol = symbol;
+				 repair.code = INSERTION_CODE;
+			 }
+		 }
+
+		return repair;
+	}
+
+
+//
+//	   This procedure is invoked to issue a diagnostic message and
+//	   adjust the input buffer.  The recovery in question is either
+//	   the insertion of one or more scopes, the merging of the error
+//	   token with its successor, the deletion of the error token,
+//	   the insertion of a single token in front of the error token
+//	   or the substitution of another token for the error token.
+//
+	private RepairCandidate primaryDiagnosis(PrimaryRepairInfo repair) {
+		int name_index;
+
+		//
+		//  Issue diagnostic.
+		//
+		int prevtok = buffer[repair.bufferPosition - 1];
+		int	curtok  = buffer[repair.bufferPosition];
+
+		switch(repair.code) {
+			case INSERTION_CODE:
+			case BEFORE_CODE: {
+				if (repair.symbol > NT_OFFSET)
+					 name_index = getNtermIndex(stack[stateStackTop],
+												repair.symbol,
+												repair.bufferPosition);
+				else name_index = getTermIndex(stack,
+											   stateStackTop,
+											   repair.symbol,
+											   repair.bufferPosition);
+
+				int t = (repair.code == INSERTION_CODE ? prevtok : curtok);
+				reportError(repair.code, name_index, t, t);
+				break;
+			}
+			case INVALID_CODE: {
+				name_index = getNtermIndex(stack[stateStackTop],
+										   repair.symbol,
+										   repair.bufferPosition + 1);
+				reportError(repair.code, name_index, curtok, curtok);
+				break;
+			}
+			case SUBSTITUTION_CODE: {
+				if (repair.misspellIndex >= 6)
+					name_index = Parser.terminal_index[repair.symbol];
+				else
+				{
+					name_index = getTermIndex(stack, stateStackTop,
+											  repair.symbol,
+											  repair.bufferPosition + 1);
+					if (name_index != Parser.terminal_index[repair.symbol])
+						repair.code = INVALID_CODE;
+				}
+				reportError(repair.code, name_index, curtok, curtok);
+				break;
+			}
+			case MERGE_CODE: {
+				reportError(repair.code,
+							 Parser.terminal_index[repair.symbol],
+							 curtok,
+							 lexStream.next(curtok));
+				break;
+			}
+			case SCOPE_CODE: {
+	            for (int i = 0; i < scopeStackTop; i++) {
+	                reportError(repair.code,
+	                            -scopeIndex[i],
+	                            locationStack[scopePosition[i]],
+	                            prevtok,
+	                            Parser.non_terminal_index[Parser.scope_lhs[scopeIndex[i]]]);
+	            }
+	
+	            repair.symbol = Parser.scope_lhs[scopeIndex[scopeStackTop]] + NT_OFFSET;
+	            stateStackTop = scopePosition[scopeStackTop];
+	            reportError(repair.code,
+	                        -scopeIndex[scopeStackTop],
+	                        locationStack[scopePosition[scopeStackTop]],
+	                        prevtok,
+	                        getNtermIndex(stack[stateStackTop],
+	                                      repair.symbol,
+	                                      repair.bufferPosition)
+	                       );
+	            break;
+	        }
+			default: {// deletion
+				reportError(repair.code, Parser.terminal_index[ERROR_SYMBOL], curtok, curtok);
+			}
+		}
+
+		//
+		//  Update buffer.
+		//
+		RepairCandidate candidate = new RepairCandidate();
+		switch (repair.code) {
+			case INSERTION_CODE:
+			case BEFORE_CODE:
+			case SCOPE_CODE: {
+				candidate.symbol = repair.symbol;
+				candidate.location = buffer[repair.bufferPosition];
+				lexStream.reset(buffer[repair.bufferPosition]);
+				break;
+			}
+			case INVALID_CODE:
+			case SUBSTITUTION_CODE: {
+				candidate.symbol = repair.symbol;
+				candidate.location = buffer[repair.bufferPosition];
+				lexStream.reset(buffer[repair.bufferPosition + 1]);
+				break;
+			}
+			case MERGE_CODE: {
+				candidate.symbol = repair.symbol;
+				candidate.location = buffer[repair.bufferPosition];
+				lexStream.reset(buffer[repair.bufferPosition + 2]);
+				break;
+			}
+			default: {// deletion
+				candidate.location = buffer[repair.bufferPosition + 1];
+				candidate.symbol =
+						  lexStream.kind(buffer[repair.bufferPosition + 1]);
+				lexStream.reset(buffer[repair.bufferPosition + 2]);
+				break;
+			}
+		}
+
+		return candidate;
+	}
+
+
+//
+//	   This function takes as parameter an integer STACK_TOP that
+//	   points to a STACK element containing the state on which a
+//	   primary recovery will be made; the terminal candidate on which
+//	   to recover; and an integer: buffer_position, which points to
+//	   the position of the next input token in the BUFFER.  The
+//	   parser is simulated until a shift (or shift-reduce) action
+//	   is computed on the candidate.  Then we proceed to compute the
+//	   the name index of the highest level nonterminal that can
+//	   directly or indirectly produce the candidate.
+//
+	private int getTermIndex(int stck[], int stack_top, int tok, int buffer_position) {
+		//
+		// Initialize stack index of temp_stack and initialize maximum
+		// position of state stack that is still useful.
+		//
+		int act = stck[stack_top],
+			max_pos = stack_top,
+			highest_symbol = tok;
+
+		tempStackTop = stack_top - 1;
+
+		//
+		// Compute all reduce and associated actions induced by the
+		// candidate until a SHIFT or SHIFT-REDUCE is computed. ERROR
+		// and ACCEPT actions cannot be computed on the candidate in
+		// this context, since we know that it is suitable for recovery.
+		//
+		lexStream.reset(buffer[buffer_position]);
+		act = Parser.tAction(act, tok);
+		while(act <= NUM_RULES) {
+			//
+			// Process all goto-reduce actions following reduction,
+			// until a goto action is computed ...
+			//
+			do {
+				tempStackTop -= (Parser.rhs[act]-1);
+				int lhs_symbol = Parser.lhs[act];
+				act = (tempStackTop > max_pos
+									  ? tempStack[tempStackTop]
+									  : stck[tempStackTop]);
+				act = Parser.ntAction(act, lhs_symbol);
+			} while(act <= NUM_RULES);
+
+			//
+			// Compute new maximum useful position of (STATE_)stack,
+			// push goto state into the stack, and compute next
+			// action on candidate ...
+			//
+			max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+			tempStack[tempStackTop + 1] = act;
+			act = Parser.tAction(act, tok);
+		}
+
+		//
+		// At this stage, we have simulated all actions induced by the
+		// candidate and we are ready to shift or shift-reduce it. First,
+		// set tok and next_ptr appropriately and identify the candidate
+		// as the initial highest_symbol. If a shift action was computed
+		// on the candidate, update the stack and compute the next
+		// action. Next, simulate all actions possible on the next input
+		// token until we either have to shift it or are about to reduce
+		// below the initial starting point in the stack (indicated by
+		// max_pos as computed in the previous loop).  At that point,
+		// return the highest_symbol computed.
+		//
+		tempStackTop++; // adjust top of stack to reflect last goto
+						  // next move is shift or shift-reduce.
+		int threshold = tempStackTop;
+
+		tok = lexStream.kind(buffer[buffer_position]);
+		lexStream.reset(buffer[buffer_position + 1]);
+
+		if (act > ERROR_ACTION) {  // shift-reduce on candidate?
+			act -= ERROR_ACTION;
+		} else {
+			tempStack[tempStackTop + 1] = act;
+			act = Parser.tAction(act, tok);
+		}
+
+		while(act <= NUM_RULES) {
+			//
+			// Process all goto-reduce actions following reduction,
+			// until a goto action is computed ...
+			//
+			do {
+				tempStackTop -= (Parser.rhs[act]-1);
+
+				if (tempStackTop < threshold) {
+					return (highest_symbol > NT_OFFSET
+						 ? Parser.non_terminal_index[highest_symbol - NT_OFFSET]
+						 : Parser.terminal_index[highest_symbol]);
+				}
+
+				int lhs_symbol = Parser.lhs[act];
+				if (tempStackTop == threshold)
+					highest_symbol = lhs_symbol + NT_OFFSET;
+				act = (tempStackTop > max_pos
+									  ? tempStack[tempStackTop]
+									  : stck[tempStackTop]);
+				act = Parser.ntAction(act, lhs_symbol);
+			} while(act <= NUM_RULES);
+
+			tempStack[tempStackTop + 1] = act;
+			act = Parser.tAction(act, tok);
+		}
+
+		return (highest_symbol > NT_OFFSET
+							 ? Parser.non_terminal_index[highest_symbol - NT_OFFSET]
+							 : Parser.terminal_index[highest_symbol]);
+	}
+
+//
+//	   This function takes as parameter a starting state number:
+//	   start, a nonterminal symbol, A (candidate), and an integer,
+//	   buffer_position,  which points to the position of the next
+//	   input token in the BUFFER.
+//	   It returns the highest level non-terminal B such that
+//	   B =>*rm A.  I.e., there does not exists a nonterminal C such
+//	   that C =>+rm B. (Recall that for an LALR(k) grammar if
+//	   C =>+rm B, it cannot be the case that B =>+rm C)
+//
+	private int getNtermIndex(int start, int sym, int buffer_position) {
+		int highest_symbol = sym - NT_OFFSET,
+			tok = lexStream.kind(buffer[buffer_position]);
+		lexStream.reset(buffer[buffer_position + 1]);
+
+		//
+		// Initialize stack index of temp_stack and initialize maximum
+		// position of state stack that is still useful.
+		//
+		tempStackTop = 0;
+		tempStack[tempStackTop] = start;
+
+		int act = Parser.ntAction(start, highest_symbol);
+		if (act > NUM_RULES) { // goto action?
+			tempStack[tempStackTop + 1] = act;
+			act = Parser.tAction(act, tok);
+		}
+
+		while(act <= NUM_RULES) {
+			//
+			// Process all goto-reduce actions following reduction,
+			// until a goto action is computed ...
+			//
+			do {
+				tempStackTop -= (Parser.rhs[act]-1);
+				if (tempStackTop < 0)
+					return Parser.non_terminal_index[highest_symbol];
+				if (tempStackTop == 0)
+					highest_symbol = Parser.lhs[act];
+				act = Parser.ntAction(tempStack[tempStackTop], Parser.lhs[act]);
+			} while(act <= NUM_RULES);
+			tempStack[tempStackTop + 1] = act;
+			act = Parser.tAction(act, tok);
+		}
+
+		return Parser.non_terminal_index[highest_symbol];
+	}
+
+	private boolean isBetterSymbol(int symbol, int actualSymbol) {
+//		switch (actualSymbol) {
+//			case TokenNameinterface :
+//				if(symbol == TokenNameclass) {
+//					return true;
+//				}
+//				break;
+//		}
+		return false;
+	}
+
+//
+//		   Check whether or not there is a high probability that a
+//	   given string is a misspelling of another.
+//	   Certain singleton symbols (such as ":" and ";") are also
+//	   considered to be misspelling of each other.
+//
+	private int misspell(int sym, int tok) {
+		
+
+		//
+		//
+		//
+		char[] name = Parser.name[Parser.terminal_index[sym]].toCharArray();
+		int n = name.length;
+		char[] s1 = new char[n + 1];
+		for (int k = 0; k < n; k++) {
+			char c = name[k];
+			s1[k] = Character.toLowerCase(c);
+		}
+		s1[n] = '\0';
+
+		//
+		//
+		//
+		char[] tokenName = lexStream.name(tok);
+		int len = tokenName.length;
+		int m = len < MAX_NAME_LENGTH ? len : MAX_NAME_LENGTH;
+		char[] s2 = new char[m + 1];
+		for (int k = 0; k < m; k++) {
+			char c = tokenName[k];
+			s2[k] = Character.toLowerCase(c);
+		}
+		s2[m] = '\0';
+
+		//
+		//  Singleton mispellings:
+		//
+		//  ;      <---->     ,
+		//
+		//  ;      <---->     :
+		//
+		//  .      <---->     ,
+		//
+		//  '      <---->     "
+		//
+		//
+		if (n == 1  &&  m == 1) {
+			if ((s1[0] == ';'  &&  s2[0] == ',')  ||
+				(s1[0] == ','  &&  s2[0] == ';')  ||
+				(s1[0] == ';'  &&  s2[0] == ':')  ||
+				(s1[0] == ':'  &&  s2[0] == ';')  ||
+				(s1[0] == '.'  &&  s2[0] == ',')  ||
+				(s1[0] == ','  &&  s2[0] == '.')  ||
+				(s1[0] == '\'' &&  s2[0] == '\"')  ||
+				(s1[0] == '\"'  &&  s2[0] == '\'')) {
+					return 3;
+			}
+		}
+
+		//
+		// Scan the two strings. Increment "match" count for each match.
+		// When a transposition is encountered, increase "match" count
+		// by two but count it as an error. When a typo is found, skip
+		// it and count it as an error. Otherwise we have a mismatch; if
+		// one of the strings is longer, increment its index, otherwise,
+		// increment both indices and continue.
+		//
+		// This algorithm is an adaptation of a boolean misspelling
+		// algorithm proposed by Juergen Uhl.
+		//
+		int count = 0;
+		int prefix_length = 0;
+		int num_errors = 0;
+
+		int i = 0;
+		int j = 0;
+		while ((i < n)  &&  (j < m)) {
+			if (s1[i] == s2[j]) {
+				count++;
+				i++;
+				j++;
+				if (num_errors == 0) {
+					prefix_length++;
+				}
+			} else if (s1[i+1] == s2[j]  &&  s1[i] == s2[j+1]) {
+				count += 2;
+				i += 2;
+				j += 2;
+				num_errors++;
+			} else if (s1[i+1] == s2[j+1]) {
+				i++;
+				j++;
+				num_errors++;
+			} else {
+				if ((n - i) > (m - j)) {
+					 i++;
+				} else if ((m - j) > (n - i)) {
+					 j++;
+				} else {
+					i++;
+					j++;
+				}
+				num_errors++;
+			}
+		}
+
+		if (i < n  ||  j < m)
+			num_errors++;
+
+		if (num_errors > ((n < m ? n : m) / 6 + 1))
+			 count = prefix_length;
+
+		return(count * 10 / ((n < len ? len : n) + num_errors));
+	}
+	
+	private PrimaryRepairInfo scopeTrial(int stck[], int stack_top, PrimaryRepairInfo repair) {
+	    stateSeen = new int[stackLength];
+	    for (int i = 0; i < stackLength; i++)
+	        stateSeen[i] = NIL;
+	    
+	    statePoolTop = 0;
+	    statePool = new StateInfo[stackLength];
+	
+	    scopeTrialCheck(stck, stack_top, repair, 0);
+	
+	    stateSeen = null;
+	    statePoolTop = 0;
+	
+	    repair.code = SCOPE_CODE;
+	    repair.misspellIndex = 10;
+	
+	    return repair;
+	}
+	
+	private void scopeTrialCheck(int stck[], int stack_top, PrimaryRepairInfo repair, int indx) {
+		int act = stck[stack_top];
+	
+	    for (int i = stateSeen[stack_top]; i != NIL; i = statePool[i].next) {
+	        if (statePool[i].state == act) return;
+	    }
+
+	    int old_state_pool_top = statePoolTop++;
+	    if(statePoolTop >= statePool.length) {
+	    	System.arraycopy(statePool, 0, statePool = new StateInfo[statePoolTop * 2], 0, statePoolTop);
+	    }
+	    
+	    statePool[old_state_pool_top] = new StateInfo(act, stateSeen[stack_top]);
+	    stateSeen[stack_top] = old_state_pool_top;
+	
+	    for (int i = 0; i < SCOPE_SIZE; i++) {
+	        //
+	        // Use the scope lookahead symbol to force all reductions
+	        // inducible by that symbol.
+	        //
+	        act = stck[stack_top];
+	        tempStackTop = stack_top - 1;
+	        int max_pos = stack_top;
+	        int tok = Parser.scope_la[i];
+	        lexStream.reset(buffer[repair.bufferPosition]);
+	        act = Parser.tAction(act, tok);
+	        while(act <= NUM_RULES) {
+	            //
+	            // ... Process all goto-reduce actions following
+	            // reduction, until a goto action is computed ...
+	            //
+	            do  {
+	                tempStackTop -= (Parser.rhs[act]-1);
+	                int lhs_symbol = Parser.lhs[act];
+	                act =  (tempStackTop > max_pos
+	                            ?  tempStack[tempStackTop]
+	                            :  stck[tempStackTop]);
+	                act = Parser.ntAction(act, lhs_symbol);
+	            }  while(act <= NUM_RULES);
+	            if (tempStackTop + 1 >= stackLength)
+	                return;
+	            max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+	            tempStack[tempStackTop + 1] = act;
+	            act = Parser.tAction(act, tok);
+	        }
+	
+	        //
+	        // If the lookahead symbol is parsable, then we check
+	        // whether or not we have a match between the scope
+	        // prefix and the transition symbols corresponding to
+	        // the states on top of the stack.
+	        //
+	        if (act != ERROR_ACTION) {
+	        	int j, k;
+	            k = Parser.scope_prefix[i];
+	            for (j = tempStackTop + 1;
+	                 j >= (max_pos + 1) &&
+	                 Parser.in_symbol(tempStack[j]) == Parser.scope_rhs[k]; j--) {
+	                 k++;
+	            }
+	            if (j == max_pos) {
+	                for (j = max_pos;
+	                     j >= 1 && Parser.in_symbol(stck[j]) == Parser.scope_rhs[k];
+	                     j--) {
+	                    k++;
+	                }
+	            }
+	            //
+	            // If the prefix matches, check whether the state
+	            // newly exposed on top of the stack, (after the
+	            // corresponding prefix states are popped from the
+	            // stack), is in the set of "source states" for the
+	            // scope in question and that it is at a position
+	            // below the threshold indicated by MARKED_POS.
+	            //
+	            int marked_pos = (max_pos < stack_top ? max_pos + 1 : stack_top);
+	            if (Parser.scope_rhs[k] == 0 && j < marked_pos) { // match?
+	                int stack_position = j;
+	                for (j = Parser.scope_state_set[i];
+	                     stck[stack_position] != Parser.scope_state[j] &&
+	                     Parser.scope_state[j] != 0;
+	                     j++);
+	                //
+	                // If the top state is valid for scope recovery,
+	                // the left-hand side of the scope is used as
+	                // starting symbol and we calculate how far the
+	                // parser can advance within the forward context
+	                // after parsing the left-hand symbol.
+	                //
+	                if (Parser.scope_state[j] != 0) {     // state was found
+	                    int previous_distance = repair.distance;
+	                    int distance = parseCheck(stck,
+	                                          stack_position,
+	                                          Parser.scope_lhs[i]+NT_OFFSET,
+	                                          repair.bufferPosition);
+	                    //
+	                    // if the recovery is not successful, we
+	                    // update the stack with all actions induced
+	                    // by the left-hand symbol, and recursively
+	                    // call SCOPE_TRIAL_CHECK to try again.
+	                    // Otherwise, the recovery is successful. If
+	                    // the new distance is greater than the
+	                    // initial SCOPE_DISTANCE, we update
+	                    // SCOPE_DISTANCE and set scope_stack_top to INDX
+	                    // to indicate the number of scopes that are
+	                    // to be applied for a succesful  recovery.
+	                    // NOTE that this procedure cannot get into
+	                    // an infinite loop, since each prefix match
+	                    // is guaranteed to take us to a lower point
+	                    // within the stack.
+	                    //
+	                    if ((distance - repair.bufferPosition + 1) < MIN_DISTANCE) {
+	                        int top = stack_position;
+	                        act = Parser.ntAction(stck[top], Parser.scope_lhs[i]);
+	                        while(act <= NUM_RULES) {
+	                            top -= (Parser.rhs[act]-1);
+	                            act = Parser.ntAction(stck[top], Parser.lhs[act]);
+	                        }
+	                        top++;
+	
+	                        j = act;
+	                        act = stck[top];  // save
+	                        stck[top] = j;    // swap
+	                        scopeTrialCheck(stck, top, repair, indx+1);
+	                        stck[top] = act; // restore
+	                    } else if (distance > repair.distance) {
+	                        scopeStackTop = indx;
+	                        repair.distance = distance;
+	                    }
+	
+	                    if (lexStream.kind(buffer[repair.bufferPosition]) == EOFT_SYMBOL &&
+	                        repair.distance == previous_distance) {
+	                        scopeStackTop = indx;
+	                        repair.distance = MAX_DISTANCE;
+	                    }
+	
+	                    //
+	                    // If this scope recovery has beaten the
+	                    // previous distance, then we have found a
+	                    // better recovery (or this recovery is one
+	                    // of a list of scope recoveries). Record
+	                    // its information at the proper location
+	                    // (INDX) in SCOPE_INDEX and SCOPE_STACK.
+	                    //
+	                    if (repair.distance > previous_distance) {
+	                        scopeIndex[indx] = i;
+	                        scopePosition[indx] = stack_position;
+	                        return;
+	                    }
+	                }
+	            }
+	        }
+	    }
+	}
+//
+//	   This function computes the ParseCheck distance for the best
+//	   possible secondary recovery for a given configuration that
+//	   either deletes none or only one symbol in the forward context.
+//	   If the recovery found is more effective than the best primary
+//	   recovery previously computed, then the function returns true.
+//	   Only misplacement, scope and manual recoveries are attempted;
+//	   simple insertion or substitution of a nonterminal are tried
+//	   in CHECK_PRIMARY_DISTANCE as part of primary recovery.
+//
+	private boolean secondaryCheck(int stck[], int stack_top, int buffer_position, int distance) {
+		int top, j;
+
+		for (top = stack_top - 1; top >= 0; top--) {
+			j = parseCheck(stck, top,
+						   lexStream.kind(buffer[buffer_position]),
+						   buffer_position + 1);
+			if (((j - buffer_position + 1) > MIN_DISTANCE) && (j > distance))
+				return true;
+		}
+		
+		PrimaryRepairInfo repair = new PrimaryRepairInfo();
+	    repair.bufferPosition = buffer_position + 1;
+	    repair.distance = distance;
+	    repair = scopeTrial(stck, stack_top, repair);
+	    if ((repair.distance - buffer_position) > MIN_DISTANCE && repair.distance > distance)
+	         return true;
+		return false;
+	}
+
+
+//
+//	   Secondary_phase is a boolean function that checks whether or
+//	   not some form of secondary recovery is applicable to one of
+//	   the error configurations. First, if "next_stack" is available,
+//	   misplacement and secondary recoveries are attempted on it.
+//	   Then, in any case, these recoveries are attempted on "stack".
+//	   If a successful recovery is found, a diagnosis is issued, the
+//	   configuration is updated and the function returns "true".
+//	   Otherwise, the function returns false.
+//
+	private RepairCandidate secondaryPhase(int error_token) {
+		SecondaryRepairInfo repair = new SecondaryRepairInfo();
+		SecondaryRepairInfo misplaced = new SecondaryRepairInfo();
+
+		RepairCandidate candidate = new RepairCandidate();
+
+		int i, j, k, top;
+		int	next_last_index = 0;
+		int	last_index;
+
+		candidate.symbol = 0;
+
+		repair.code = 0;
+		repair.distance = 0;
+		repair.recoveryOnNextStack = false;
+
+		misplaced.distance = 0;
+		misplaced.recoveryOnNextStack = false;
+
+		//
+		// If the next_stack is available, try misplaced and secondary
+		// recovery on it first.
+		//
+		if (nextStackTop >= 0) {
+			int  save_location;
+
+			buffer[2] = error_token;
+			buffer[1] = lexStream.previous(buffer[2]);
+			buffer[0] = lexStream.previous(buffer[1]);
+
+			for (k = 3; k < BUFF_UBOUND; k++)
+				buffer[k] = lexStream.next(buffer[k - 1]);
+
+			buffer[BUFF_UBOUND] = lexStream.badtoken();// elmt not available
+
+			//
+			// If we are at the end of the input stream, compute the
+			// index position of the first EOFT symbol (last useful
+			// index).
+			//
+			for (next_last_index = MAX_DISTANCE - 1;
+				 next_last_index >= 1 &&
+				 lexStream.kind(buffer[next_last_index]) == EOFT_SYMBOL;
+				 next_last_index--);
+			next_last_index = next_last_index + 1;
+
+			save_location = locationStack[nextStackTop];
+			int save_location_start = locationStartStack[nextStackTop];
+			locationStack[nextStackTop] = buffer[2];
+			locationStartStack[nextStackTop] = lexStream.start(buffer[2]);
+			misplaced.numDeletions = nextStackTop;
+			misplaced = misplacementRecovery(nextStack, nextStackTop,
+											 next_last_index,
+											 misplaced, true);
+			if (misplaced.recoveryOnNextStack)
+				misplaced.distance++;
+
+			repair.numDeletions = nextStackTop + BUFF_UBOUND;
+			repair = secondaryRecovery(nextStack, nextStackTop,
+									   next_last_index,
+									   repair, true);
+			if (repair.recoveryOnNextStack)
+				repair.distance++;
+
+			locationStack[nextStackTop] = save_location;
+			locationStartStack[nextStackTop] = save_location_start;
+		} else {            // next_stack not available, initialize ...
+			misplaced.numDeletions = stateStackTop;
+			repair.numDeletions = stateStackTop + BUFF_UBOUND;
+		}
+
+		//
+		// Try secondary recovery on the "stack" configuration.
+		//
+		buffer[3] = error_token;
+
+		buffer[2] = lexStream.previous(buffer[3]);
+		buffer[1] = lexStream.previous(buffer[2]);
+		buffer[0] = lexStream.previous(buffer[1]);
+
+		for (k = 4; k < BUFF_SIZE; k++)
+			buffer[k] = lexStream.next(buffer[k - 1]);
+
+		for (last_index = MAX_DISTANCE - 1;
+			 last_index >= 1 && lexStream.kind(buffer[last_index]) == EOFT_SYMBOL;
+			 last_index--);
+		last_index++;
+
+		misplaced = misplacementRecovery(stack, stateStackTop,
+										 last_index,
+										 misplaced, false);
+
+		repair = secondaryRecovery(stack, stateStackTop,
+								   last_index, repair, false);
+
+		//
+		// If a successful misplaced recovery was found, compare it with
+		// the most successful secondary recovery.  If the misplaced
+		// recovery either deletes fewer symbols or parse-checks further
+		// then it is chosen.
+		//
+		if (misplaced.distance > MIN_DISTANCE) {
+			if (misplaced.numDeletions <= repair.numDeletions ||
+			   (misplaced.distance - misplaced.numDeletions) >=
+			   (repair.distance - repair.numDeletions)) {
+				repair.code = MISPLACED_CODE;
+				repair.stackPosition = misplaced.stackPosition;
+				repair.bufferPosition = 2;
+				repair.numDeletions = misplaced.numDeletions;
+				repair.distance = misplaced.distance;
+				repair.recoveryOnNextStack = misplaced.recoveryOnNextStack;
+			}
+		}
+
+		//
+		// If the successful recovery was on next_stack, update: stack,
+		// buffer, location_stack and last_index.
+		//
+		if (repair.recoveryOnNextStack) {
+			stateStackTop = nextStackTop;
+			for (i = 0; i <= stateStackTop; i++)
+				stack[i] = nextStack[i];
+
+			buffer[2] = error_token;
+			buffer[1] = lexStream.previous(buffer[2]);
+			buffer[0] = lexStream.previous(buffer[1]);
+
+			for (k = 3; k < BUFF_UBOUND; k++)
+				buffer[k] = lexStream.next(buffer[k - 1]);
+
+			buffer[BUFF_UBOUND] = lexStream.badtoken();// elmt not available
+
+			locationStack[nextStackTop] = buffer[2];
+			locationStartStack[nextStackTop] = lexStream.start(buffer[2]);
+			last_index = next_last_index;
+		}
+
+	    //
+	    // Next, try scope recoveries after deletion of one, two, three,
+	    // four ... buffer_position tokens from the input stream.
+	    //
+	    if (repair.code == SECONDARY_CODE || repair.code == DELETION_CODE) {
+	        PrimaryRepairInfo scope_repair = new PrimaryRepairInfo();
+	
+	        scope_repair.distance = 0;
+	        for (scope_repair.bufferPosition = 2;
+	             scope_repair.bufferPosition <= repair.bufferPosition &&
+	             repair.code != SCOPE_CODE; scope_repair.bufferPosition++) {
+	            scope_repair = scopeTrial(stack, stateStackTop, scope_repair);
+	            j = (scope_repair.distance == MAX_DISTANCE
+	                                        ? last_index
+	                                        : scope_repair.distance);
+	            k = scope_repair.bufferPosition - 1;
+	            if ((j - k) > MIN_DISTANCE && (j - k) > (repair.distance - repair.numDeletions)) {
+	                repair.code = SCOPE_CODE;
+	                i = scopeIndex[scopeStackTop];       // upper bound
+	                repair.symbol = Parser.scope_lhs[i] + NT_OFFSET;
+	                repair.stackPosition = stateStackTop;
+	                repair.bufferPosition = scope_repair.bufferPosition;
+	            }
+	        }
+	    }
+	
+	    //
+	    // If no successful recovery is found and we have reached the
+	    // end of the file, check whether or not scope recovery is
+	    // applicable at the end of the file after discarding some
+	    // states.
+	    //
+	    if (repair.code == 0 && lexStream.kind(buffer[last_index]) == EOFT_SYMBOL) {
+	        PrimaryRepairInfo scope_repair = new PrimaryRepairInfo();
+	
+	        scope_repair.bufferPosition = last_index;
+	        scope_repair.distance = 0;
+	        for (top = stateStackTop;
+	             top >= 0 && repair.code == 0; top--)
+	        {
+	            scope_repair = scopeTrial(stack, top, scope_repair);
+	            if (scope_repair.distance > 0)
+	            {
+	                repair.code = SCOPE_CODE;
+	                i = scopeIndex[scopeStackTop];    // upper bound
+	                repair.symbol = Parser.scope_lhs[i] + NT_OFFSET;
+	                repair.stackPosition = top;
+	                repair.bufferPosition = scope_repair.bufferPosition;
+	            }
+	        }
+	    }
+
+		//
+		// If a successful repair was not found, quit!  Otherwise, issue
+		// diagnosis and adjust configuration...
+		//
+		if (repair.code == 0)
+			return candidate;
+
+		secondaryDiagnosis(repair);
+
+		//
+		// Update buffer based on number of elements that are deleted.
+		//
+		switch(repair.code) {
+			case MISPLACED_CODE:
+				 candidate.location = buffer[2];
+				 candidate.symbol = lexStream.kind(buffer[2]);
+				 lexStream.reset(lexStream.next(buffer[2]));
+
+				 break;
+
+			case DELETION_CODE:
+				 candidate.location = buffer[repair.bufferPosition];
+				 candidate.symbol =
+						   lexStream.kind(buffer[repair.bufferPosition]);
+				 lexStream.reset(lexStream.next(buffer[repair.bufferPosition]));
+
+				 break;
+
+		default: // SCOPE_CODE || SECONDARY_CODE
+				 candidate.symbol = repair.symbol;
+				 candidate.location = buffer[repair.bufferPosition];
+				 lexStream.reset(buffer[repair.bufferPosition]);
+
+				 break;
+		}
+
+		return candidate;
+	}
+
+
+//
+//	   This boolean function checks whether or not a given
+//	   configuration yields a better misplacement recovery than
+//	   the best misplacement recovery computed previously.
+//
+	private SecondaryRepairInfo misplacementRecovery(int stck[], int stack_top, int last_index, SecondaryRepairInfo repair, boolean stack_flag) {
+		int  previous_loc = buffer[2];
+		int stack_deletions = 0;
+
+		for (int top = stack_top - 1; top >= 0; top--) {
+			if (locationStack[top] < previous_loc) {
+				stack_deletions++;
+			}
+			previous_loc = locationStack[top];
+
+			int j = parseCheck(stck, top, lexStream.kind(buffer[2]), 3);
+			if (j == MAX_DISTANCE) {
+				 j = last_index;
+			}
+			if ((j > MIN_DISTANCE) && (j - stack_deletions) > (repair.distance - repair.numDeletions)) {
+				repair.stackPosition = top;
+				repair.distance = j;
+				repair.numDeletions = stack_deletions;
+				repair.recoveryOnNextStack = stack_flag;
+			}
+		}
+
+		return repair;
+	}
+
+
+//
+//	   This boolean function checks whether or not a given
+//	   configuration yields a better secondary recovery than the
+//	   best misplacement recovery computed previously.
+//
+	private SecondaryRepairInfo secondaryRecovery(int stck[],int stack_top, int last_index, SecondaryRepairInfo repair, boolean stack_flag) {
+		int previous_loc;
+		int stack_deletions = 0;
+		
+		previous_loc = buffer[2];
+		for (int top = stack_top; top >= 0 && repair.numDeletions >= stack_deletions; top--) {
+			if (locationStack[top] < previous_loc) {
+				stack_deletions++;
+			}
+			previous_loc = locationStack[top];
+
+			for (int i = 2;
+				 i <= (last_index - MIN_DISTANCE + 1) &&
+				 (repair.numDeletions >= (stack_deletions + i - 1)); i++) {
+				int j = parseCheck(stck, top, lexStream.kind(buffer[i]), i + 1);
+
+				if (j == MAX_DISTANCE) {
+					 j = last_index;
+				}
+				if ((j - i + 1) > MIN_DISTANCE) {
+					int k = stack_deletions + i - 1;
+					if ((k < repair.numDeletions) ||
+						(j - k) > (repair.distance - repair.numDeletions) ||
+						((repair.code == SECONDARY_CODE) && (j - k) == (repair.distance - repair.numDeletions))) {
+						repair.code = DELETION_CODE;
+						repair.distance = j;
+						repair.stackPosition = top;
+						repair.bufferPosition = i;
+						repair.numDeletions = k;
+						repair.recoveryOnNextStack = stack_flag;
+					}
+				}
+
+				for (int l = Parser.nasi(stck[top]); l >= 0 && Parser.nasr[l] != 0; l++) {
+					int symbol = Parser.nasr[l] + NT_OFFSET;
+					j = parseCheck(stck, top, symbol, i);
+					if (j == MAX_DISTANCE) {
+						 j = last_index;
+					}
+					if ((j - i + 1) > MIN_DISTANCE) {
+						int k = stack_deletions + i - 1;
+						if (k < repair.numDeletions || (j - k) > (repair.distance - repair.numDeletions)) {
+							repair.code = SECONDARY_CODE;
+							repair.symbol = symbol;
+							repair.distance = j;
+							repair.stackPosition = top;
+							repair.bufferPosition = i;
+							repair.numDeletions = k;
+							repair.recoveryOnNextStack = stack_flag;
+						}
+					}
+				}
+			}
+		}
+
+		return repair;
+	}
+
+
+//
+//	   This procedure is invoked to issue a secondary diagnosis and
+//	   adjust the input buffer.  The recovery in question is either
+//	   an automatic scope recovery, a manual scope recovery, a
+//	   secondary substitution or a secondary deletion.
+//
+	private void secondaryDiagnosis(SecondaryRepairInfo repair) {
+		switch(repair.code) {
+			case SCOPE_CODE: {
+	            if (repair.stackPosition < stateStackTop) {
+	                reportError(DELETION_CODE,
+	                            Parser.terminal_index[ERROR_SYMBOL],
+	                            locationStack[repair.stackPosition],
+	                            buffer[1]);
+	            }
+	            for (int i = 0; i < scopeStackTop; i++) {
+	                reportError(SCOPE_CODE,
+	                            -scopeIndex[i],
+	                            locationStack[scopePosition[i]],
+	                            buffer[1],
+	                            Parser.non_terminal_index[Parser.scope_lhs[scopeIndex[i]]]);
+	            }
+	
+	            repair.symbol = Parser.scope_lhs[scopeIndex[scopeStackTop]] + NT_OFFSET;
+	            stateStackTop = scopePosition[scopeStackTop];
+	            reportError(SCOPE_CODE,
+	                        -scopeIndex[scopeStackTop],
+	                        locationStack[scopePosition[scopeStackTop]],
+	                        buffer[1],
+	                        getNtermIndex(stack[stateStackTop],
+	                                      repair.symbol,
+	                                      repair.bufferPosition)
+	                       );
+	            break;
+	        }
+			default: {
+				reportError(repair.code,
+							(repair.code == SECONDARY_CODE
+										  ? getNtermIndex(stack[repair.stackPosition],
+														  repair.symbol,
+														  repair.bufferPosition)
+										  : Parser.terminal_index[ERROR_SYMBOL]),
+							locationStack[repair.stackPosition],
+							buffer[repair.bufferPosition - 1]);
+				stateStackTop = repair.stackPosition;
+			}
+		}
+	}
+
+
+
+
+//
+//	   Try to parse until first_token and all tokens in BUFFER have
+//	   been consumed, or an error is encountered. Return the number
+//	   of tokens that were expended before the parse blocked.
+//
+	private int parseCheck(int stck[], int stack_top, int first_token, int buffer_position) {
+		int max_pos;
+		int indx;
+		int ct;
+		int act;
+
+		//
+		// Initialize pointer for temp_stack and initialize maximum
+		// position of state stack that is still useful.
+		//
+		act = stck[stack_top];
+		if (first_token > NT_OFFSET) {
+			tempStackTop = stack_top;
+			max_pos = stack_top;
+			indx = buffer_position;
+			ct = lexStream.kind(buffer[indx]);
+			lexStream.reset(lexStream.next(buffer[indx]));
+			int lhs_symbol = first_token - NT_OFFSET;
+			act = Parser.ntAction(act, lhs_symbol);
+			if (act <= NUM_RULES) {
+				do {
+					tempStackTop -= (Parser.rhs[act]-1);
+					lhs_symbol = Parser.lhs[act];
+					act = (tempStackTop > max_pos
+										  ? tempStack[tempStackTop]
+										  : stck[tempStackTop]);
+					act = Parser.ntAction(act, lhs_symbol);
+				} while(act <= NUM_RULES);
+	
+				max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+			}
+		} else {
+			tempStackTop = stack_top - 1;
+			max_pos = tempStackTop;
+			indx = buffer_position - 1;
+			ct = first_token;
+			lexStream.reset(buffer[buffer_position]);
+		}
+
+		process_terminal: for (;;) {
+			if (++tempStackTop >= stackLength)  // Stack overflow!!!
+				return indx;
+			tempStack[tempStackTop] = act;
+
+			act = Parser.tAction(act, ct);
+
+			if (act <= NUM_RULES) {               // reduce action
+				tempStackTop--;
+			} else if (act < ACCEPT_ACTION ||     // shift action
+					 act > ERROR_ACTION) {        // shift-reduce action
+				if (indx == MAX_DISTANCE)
+					return indx;
+				indx++;
+				ct = lexStream.kind(buffer[indx]);
+				lexStream.reset(lexStream.next(buffer[indx]));
+				if (act > ERROR_ACTION) {
+					 act -= ERROR_ACTION;
+				} else {
+					continue process_terminal;
+				}
+			} else if (act == ACCEPT_ACTION) {           // accept action
+				 return MAX_DISTANCE;
+			} else {
+				return indx;                         // error action
+			}
+
+			process_non_terminal:
+			do {
+				tempStackTop -= (Parser.rhs[act]-1);
+				int lhs_symbol = Parser.lhs[act];
+				act = (tempStackTop > max_pos
+									  ? tempStack[tempStackTop]
+									  : stck[tempStackTop]);
+				act = Parser.ntAction(act, lhs_symbol);
+			} while(act <= NUM_RULES);
+
+			max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+		} // process_terminal;
+	}
+	private void reportError(int msgCode, int nameIndex, int leftToken, int rightToken) {
+		reportError(msgCode, nameIndex, leftToken, rightToken, 0);
+	}
+
+	private void reportError(int msgCode, int nameIndex, int leftToken, int rightToken, int scopeNameIndex) {
+		int lToken = (leftToken > rightToken ? rightToken : leftToken);
+
+		if (lToken < rightToken) {
+			reportSecondaryError(msgCode, nameIndex, lToken, rightToken, scopeNameIndex);
+		} else {
+			reportPrimaryError(msgCode, nameIndex, rightToken, scopeNameIndex);
+		}
+	}
+	private void reportPrimaryError(int msgCode, int nameIndex, int token, int scopeNameIndex) {
+		String name;
+		if (nameIndex >= 0) {
+			name = Parser.readableName[nameIndex];
+		} else {
+			name = EMPTY_STRING;
+		}
+
+		int errorStart = lexStream.start(token);
+		int errorEnd = lexStream.end(token);
+		int currentKind = lexStream.kind(token);
+		String errorTokenName = Parser.name[Parser.terminal_index[lexStream.kind(token)]];
+		char[] errorTokenSource = lexStream.name(token);
+
+		switch(msgCode) {
+			case BEFORE_CODE:
+				problemReporter().parseErrorInsertBeforeToken(
+					errorStart, 
+					errorEnd, 
+					currentKind,
+					errorTokenSource, 
+					errorTokenName, 
+					name);
+				 break;
+			case INSERTION_CODE:
+				problemReporter().parseErrorInsertAfterToken(
+					errorStart, 
+					errorEnd, 
+					currentKind,
+					errorTokenSource, 
+					errorTokenName, 
+					name);  
+				 break;
+			case DELETION_CODE:
+				problemReporter().parseErrorDeleteToken(
+					errorStart, 
+					errorEnd, 
+					currentKind,
+					errorTokenSource, 
+					errorTokenName);
+				break;
+			case INVALID_CODE:
+				if (name.length() == 0) {
+					problemReporter().parseErrorReplaceToken(
+						errorStart, 
+						errorEnd, 
+						currentKind,
+						errorTokenSource, 
+						errorTokenName, 
+						name);
+				} else {
+					problemReporter().parseErrorInvalidToken(
+						errorStart, 
+						errorEnd, 
+						currentKind,
+						errorTokenSource, 
+						errorTokenName, 
+						name);
+				}
+				break;
+			case SUBSTITUTION_CODE:
+				problemReporter().parseErrorReplaceToken(
+					errorStart, 
+					errorEnd, 
+					currentKind,
+					errorTokenSource, 
+					errorTokenName, 
+					name); 
+				 break;
+			case SCOPE_CODE:
+				StringBuffer buf = new StringBuffer();
+				for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) {
+					buf.append(Parser.readableName[Parser.scope_rhs[i]]);
+					if (Parser.scope_rhs[i + 1] != 0) // any more symbols to print?
+						buf.append(' ');
+						
+				}
+
+				if (scopeNameIndex != 0) {
+					problemReporter().parseErrorInsertToComplete(
+						errorStart, 
+						errorEnd,
+						buf.toString(),
+						Parser.readableName[scopeNameIndex]);
+				} else {
+					problemReporter().parseErrorInsertToCompleteScope(
+						errorStart, 
+						errorEnd,
+						buf.toString()); 
+				}
+				
+				break;
+			case EOF_CODE:
+				problemReporter().parseErrorUnexpectedEnd(
+					errorStart, 
+					errorEnd); 
+				break;
+			case MERGE_CODE:
+				problemReporter().parseErrorMergeTokens(
+					errorStart, 
+					errorEnd,
+					name);
+				break;
+			case MISPLACED_CODE:
+				problemReporter().parseErrorMisplacedConstruct(
+					errorStart, 
+					errorEnd);
+				break;
+			default:
+				if (name.length() == 0) {
+					problemReporter().parseErrorNoSuggestion(
+						errorStart, 
+						errorEnd, 
+						currentKind,
+						errorTokenSource, 
+						errorTokenName);
+				} else {
+					problemReporter().parseErrorReplaceToken(
+						errorStart, 
+						errorEnd, 
+						currentKind,
+						errorTokenSource, 
+						errorTokenName, 
+						name); 
+				}
+				break;
+		}
+	}
+
+	private void reportSecondaryError(int msgCode,	int nameIndex,	int leftToken,	int rightToken, int scopeNameIndex) {
+		String name;
+		if (nameIndex >= 0) {
+			name = Parser.readableName[nameIndex];
+		} else {
+			name = EMPTY_STRING;	
+		}
+
+		int errorStart = -1;
+		if(lexStream.isInsideStream(leftToken)) {
+			errorStart = lexStream.start(leftToken);
+		} else {
+			if(leftToken == errorToken) {
+				errorStart = errorTokenStart;
+			} else {
+				for (int i = 0; i <= stateStackTop; i++) {
+					if(locationStack[i] == leftToken) {
+						errorStart = locationStartStack[i];
+					}
+				}
+			}
+			if(errorStart == -1) {
+				errorStart = lexStream.start(rightToken);
+			}
+		}
+		int errorEnd = lexStream.end(rightToken);
+		
+		switch(msgCode) {
+			case MISPLACED_CODE:
+				problemReporter().parseErrorMisplacedConstruct(
+					errorStart, 
+					errorEnd); 
+				break;
+			case SCOPE_CODE:
+				// error start is on the last token start
+				errorStart = lexStream.start(rightToken);
+			
+	            StringBuffer buf = new StringBuffer();
+	            for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) {
+	                buf.append(Parser.readableName[Parser.scope_rhs[i]]);
+	                if (Parser.scope_rhs[i+1] != 0)
+	                     buf.append(' ');
+	            }
+	            if (scopeNameIndex != 0) {
+	                problemReporter().parseErrorInsertToComplete(
+						errorStart, 
+						errorEnd,
+						buf.toString(),
+						Parser.readableName[scopeNameIndex]);
+	            } else {
+	            	problemReporter().parseErrorInsertToCompletePhrase(
+						errorStart, 
+						errorEnd,
+						buf.toString()); 
+	            }
+	            break;
+			case MERGE_CODE:
+				problemReporter().parseErrorMergeTokens(
+					errorStart, 
+					errorEnd,
+					name);
+				break;
+			case DELETION_CODE:
+				problemReporter().parseErrorDeleteTokens(
+					errorStart, 
+					errorEnd);
+				break;
+			default:
+				if (name.length() == 0) {
+					problemReporter().parseErrorNoSuggestionForTokens(
+						errorStart, 
+						errorEnd);
+				} else {
+					problemReporter().parseErrorReplaceTokens(
+						errorStart, 
+						errorEnd,
+						name);
+				}
+		}
+		return;
+	}
+
+	public String toString() {
+		StringBuffer res = new StringBuffer();
+		
+		res.append(lexStream.toString());
+		
+		return res.toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/LexStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/LexStream.java
new file mode 100644
index 0000000..af65612
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/LexStream.java
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * 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 Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser.diagnose;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+public class LexStream implements TerminalTokens {
+	public static final int IS_AFTER_JUMP = 1;
+	public static final int LBRACE_MISSING = 2;
+		
+	public class Token{
+		int kind;
+		char[] name;
+		int start;
+		int end;
+		int line;
+		int flags;
+		
+		public String toString() {
+			StringBuffer buffer = new StringBuffer();
+			buffer.append(name).append('[').append(kind).append(']');
+			buffer.append('{').append(start).append(',').append(end).append('}').append(line);
+			return buffer.toString();
+		}
+
+	}
+
+	private int tokenCacheIndex;
+	private int tokenCacheEOFIndex;
+	private Token[] tokenCache;
+
+	private int currentIndex = -1;
+
+	private Scanner scanner;
+	private int[] intervalStartToSkip;
+	private int[] intervalEndToSkip;
+	private int[] intervalFlagsToSkip;
+	
+	private int previousInterval = -1;
+	
+	public LexStream(int size, Scanner scanner, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip, int firstToken, int init, int eof) {
+		this.tokenCache = new Token[size];
+		this.tokenCacheIndex = 0;
+		this.tokenCacheEOFIndex = Integer.MAX_VALUE;
+		this.tokenCache[0] = new Token();
+		this.tokenCache[0].kind = firstToken;
+		this.tokenCache[0].name = CharOperation.NO_CHAR;
+		this.tokenCache[0].start = init;
+		this.tokenCache[0].end = init;
+		this.tokenCache[0].line = 0;
+		
+		this.intervalStartToSkip = intervalStartToSkip;
+		this.intervalEndToSkip = intervalEndToSkip;
+		this.intervalFlagsToSkip = intervalFlagsToSkip;
+		
+		scanner.resetTo(init, eof);
+		this.scanner = scanner;
+	}
+	
+	private void readTokenFromScanner(){
+		int length = tokenCache.length;
+		boolean tokenNotFound = true;
+		
+		while(tokenNotFound) {
+			try {
+				int tokenKind =  scanner.getNextToken();
+				if(tokenKind != TokenNameEOF) {
+					int start = scanner.getCurrentTokenStartPosition();
+					int end = scanner.getCurrentTokenEndPosition();
+					if(!RangeUtil.isInInterval(start, end, intervalStartToSkip, intervalEndToSkip)) {
+						Token token = new Token();
+						token.kind = tokenKind;
+						token.name = scanner.getCurrentTokenSource();
+						token.start = start;
+						token.end = end;
+						token.line = scanner.getLineNumber(end);
+						
+						int pInterval = RangeUtil.getPreviousInterval(start, end, intervalStartToSkip, intervalEndToSkip);
+						if(pInterval != previousInterval && (intervalFlagsToSkip[previousInterval + 1] & RangeUtil.IGNORE) == 0){
+							token.flags = IS_AFTER_JUMP;
+							if((intervalFlagsToSkip[pInterval] & RangeUtil.LBRACE_MISSING) != 0){
+								token.flags |= LBRACE_MISSING;
+							}
+						}
+						previousInterval = pInterval;
+
+						tokenCache[++tokenCacheIndex % length] = token;
+						
+						tokenNotFound = false;
+					}
+				} else {
+					int start = scanner.getCurrentTokenStartPosition();
+					int end = scanner.getCurrentTokenEndPosition();
+					Token token = new Token();
+					token.kind = tokenKind;
+					token.name = CharOperation.NO_CHAR;
+					token.start = start;
+					token.end = end;
+					token.line = scanner.getLineNumber(end);
+					
+					tokenCache[++tokenCacheIndex % length] = token;
+					
+					tokenCacheEOFIndex = tokenCacheIndex;
+					tokenNotFound = false;
+				}
+			} catch (InvalidInputException e) {
+				// return next token
+			}
+		}
+	}
+	
+	public Token token(int index) {
+		if(index < 0) {
+			Token eofToken = new Token();
+			eofToken.kind = TokenNameEOF;
+			eofToken.name = CharOperation.NO_CHAR;
+			return eofToken;
+		}
+		if(this.tokenCacheEOFIndex >= 0 && index > this.tokenCacheEOFIndex) {
+			return token(this.tokenCacheEOFIndex);
+		}
+		int length = tokenCache.length;
+		if(index > this.tokenCacheIndex) {
+			int tokensToRead = index - this.tokenCacheIndex;
+			while(tokensToRead-- != 0) {
+				readTokenFromScanner();
+			}
+		} else if(this.tokenCacheIndex - length >= index) {
+			return null;
+		}
+		
+		return tokenCache[index % length];
+	}
+	
+	
+	
+	public int getToken() {
+		return currentIndex = next(currentIndex);
+	}
+	
+	public int previous(int tokenIndex) {
+		return tokenIndex > 0 ? tokenIndex - 1 : 0;
+	}
+
+	public int next(int tokenIndex) {
+		return tokenIndex < this.tokenCacheEOFIndex ? tokenIndex + 1 : this.tokenCacheEOFIndex;
+	}
+
+	public boolean afterEol(int i) {
+		return i < 1 ? true : line(i - 1) < line(i);
+	}
+	
+	public void reset() {
+		currentIndex = -1;
+	}
+	
+	public void reset(int i) {
+		currentIndex = previous(i);
+	}
+
+	public int badtoken() {
+		return 0;
+	}
+
+	public int kind(int tokenIndex) {
+		return token(tokenIndex).kind;
+	}
+	
+	public char[] name(int tokenIndex) {
+		return token(tokenIndex).name;
+	}
+
+	public int line(int tokenIndex) {
+		return token(tokenIndex).line;
+	}
+	
+	public int start(int tokenIndex) {
+		return token(tokenIndex).start;
+	}
+	
+	public int end(int tokenIndex) {
+		return token(tokenIndex).end;
+	}
+	
+	public int flags(int tokenIndex) {
+		return token(tokenIndex).flags;
+	}
+	
+	public boolean isInsideStream(int index) {
+		if(this.tokenCacheEOFIndex >= 0 && index > this.tokenCacheEOFIndex) {
+			return false;
+		} else if(index > this.tokenCacheIndex) {
+			return true;
+		} else if(this.tokenCacheIndex - tokenCache.length >= index) {
+			return false;
+		} else {
+			return true;
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		StringBuffer res = new StringBuffer();
+		
+		String source = new String(scanner.source);
+		if(currentIndex < 0) {
+			res.append(source);
+		} else {
+			Token token = token(currentIndex);
+			int curtokKind = token.kind;
+			int curtokStart = token.start;
+			int curtokEnd = token.end;
+			
+			int previousEnd = -1;
+			for (int i = 0; i < intervalStartToSkip.length; i++) {
+				int intervalStart = intervalStartToSkip[i];
+				int intervalEnd = intervalEndToSkip[i];
+				
+				if(curtokStart >= previousEnd && curtokEnd <= intervalStart) {
+					res.append(source.substring(previousEnd + 1, curtokStart));
+					res.append('<');
+					res.append('#');
+					res.append(source.substring(curtokStart, curtokEnd + 1));
+					res.append('#');
+					res.append('>');
+					res.append(source.substring(curtokEnd+1, intervalStart));
+				} else {
+					res.append(source.substring(previousEnd + 1, intervalStart));
+				}
+				res.append('<');
+				res.append('@');
+				res.append(source.substring(intervalStart, intervalEnd + 1));
+				res.append('@');
+				res.append('>');
+				
+				previousEnd = intervalEnd;
+			}
+			if(curtokStart >= previousEnd) {
+				res.append(source.substring(previousEnd + 1, curtokStart));
+				res.append('<');
+				res.append('#');
+				if(curtokKind == TokenNameEOF) {
+					res.append("EOF#>"); //$NON-NLS-1$
+				} else {
+					res.append(source.substring(curtokStart, curtokEnd + 1));
+					res.append('#');
+					res.append('>');
+					res.append(source.substring(curtokEnd+1));
+				}
+			} else {
+				res.append(source.substring(previousEnd + 1));
+			}
+		}
+		
+		return res.toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java
new file mode 100644
index 0000000..1064eb0
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * 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 Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser.diagnose;
+
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+
+public class RangeUtil {
+	
+	// flags
+	public static final int NO_FLAG = 0;
+	public static final int LBRACE_MISSING = 1;
+	public static final int IGNORE = 2;
+	
+	static class RangeResult {
+		private static final int INITIAL_SIZE = 10;
+		int pos;
+		int[] intervalStarts;
+		int[] intervalEnds;
+		int[] intervalFlags;
+		
+		RangeResult() {
+			this.pos = 0;
+			this.intervalStarts = new int[INITIAL_SIZE];
+			this.intervalEnds = new int[INITIAL_SIZE];
+			this.intervalFlags = new int[INITIAL_SIZE];
+		}
+		
+		void addInterval(int start, int end){
+			addInterval(start, end, NO_FLAG);
+		}
+		
+		void addInterval(int start, int end, int flags){
+			if(pos >= intervalStarts.length) {
+				System.arraycopy(intervalStarts, 0, intervalStarts = new int[pos * 2], 0, pos);
+				System.arraycopy(intervalEnds, 0, intervalEnds = new int[pos * 2], 0, pos);
+				System.arraycopy(intervalFlags, 0, intervalFlags = new int[pos * 2], 0, pos);
+			}
+			intervalStarts[pos] = start;
+			intervalEnds[pos] = end;
+			intervalFlags[pos] = flags;
+			pos++;
+		}
+		
+		int[][] getRanges() {
+			int[] resultStarts = new int[pos];
+			int[] resultEnds = new int[pos];
+			int[] resultFlags = new int[pos];
+			
+			System.arraycopy(intervalStarts, 0, resultStarts, 0, pos);
+			System.arraycopy(intervalEnds, 0, resultEnds, 0, pos);
+			System.arraycopy(intervalFlags, 0, resultFlags, 0, pos);
+
+			if (resultStarts.length > 1) {
+				quickSort(resultStarts, resultEnds, resultFlags, 0, resultStarts.length - 1);
+			}
+			return new int[][]{resultStarts, resultEnds, resultFlags};
+		}
+		
+		private void quickSort(int[] list, int[] list2, int[] list3, int left, int right) {
+			int original_left= left;
+			int original_right= right;
+			int mid= list[(left + right) / 2];
+			do {
+				while (compare(list[left], mid) < 0) {
+					left++;
+				}
+				while (compare(mid, list[right]) < 0) {
+					right--;
+				}
+				if (left <= right) {
+					int tmp= list[left];
+					list[left]= list[right];
+					list[right]= tmp;
+					
+					tmp = list2[left];
+					list2[left]= list2[right];
+					list2[right]= tmp;
+					
+					tmp = list3[left];
+					list3[left]= list3[right];
+					list3[right]= tmp;
+					
+					left++;
+					right--;
+				}
+			} while (left <= right);
+			
+			if (original_left < right) {
+				quickSort(list, list2, list3, original_left, right);
+			}
+			if (left < original_right) {
+				quickSort(list, list2, list3, left, original_right);
+			}
+		}
+		
+		private int compare(int i1, int i2) {
+			return i1 - i2;
+		}
+	}
+	
+	
+	
+	public static boolean containsErrorInSignature(AbstractMethodDeclaration method){
+		return method.sourceEnd + 1 == method.bodyStart	|| method.bodyEnd == method.declarationSourceEnd;
+	}
+
+	public static int[][] computeDietRange(TypeDeclaration[] types) {
+		if(types == null || types.length == 0) {
+			return new int[3][0];
+		} else {
+			RangeResult result = new RangeResult();
+			computeDietRange0(types, result);
+			return result.getRanges();
+		}
+	}
+	
+	private static void computeDietRange0(TypeDeclaration[] types, RangeResult result) {
+		for (int j = 0; j < types.length; j++) {
+			//members
+			TypeDeclaration[] memberTypeDeclarations = types[j].memberTypes;
+			if(memberTypeDeclarations != null && memberTypeDeclarations.length > 0) {
+				computeDietRange0(types[j].memberTypes, result);
+			}
+			//methods
+			AbstractMethodDeclaration[] methods = types[j].methods;
+			if (methods != null) {
+				int length = methods.length;
+				for (int i = 0; i < length; i++) {
+					AbstractMethodDeclaration method = methods[i];
+					if(containsIgnoredBody(method)) {
+						if(containsErrorInSignature(method)) {
+							method.errorInSignature = true;
+							result.addInterval(method.declarationSourceStart, method.declarationSourceEnd, IGNORE);
+						} else {
+							int flags = method.sourceEnd + 1 == method.bodyStart ? LBRACE_MISSING : NO_FLAG;
+							result.addInterval(method.bodyStart, method.bodyEnd, flags);
+						}
+					}
+				}
+			}
+	
+			//initializers
+			FieldDeclaration[] fields = types[j].fields;
+			if (fields != null) {
+				int length = fields.length;
+				for (int i = 0; i < length; i++) {
+					if (fields[i] instanceof Initializer) {
+						Initializer initializer = (Initializer)fields[i];
+						if(initializer.declarationSourceEnd == initializer.bodyEnd){
+							initializer.errorInSignature = true;
+							result.addInterval(initializer.declarationSourceStart, initializer.declarationSourceEnd, IGNORE);
+						} else {
+							result.addInterval(initializer.bodyStart, initializer.bodyEnd);
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	public static boolean isInInterval(int start, int end, int[] intervalStart, int[] intervalEnd) {
+		int length = intervalStart.length;
+		for (int i = 0; i < length; i++) {
+			if(intervalStart[i] <= start && intervalEnd[i] >= end) {
+				return true;
+			} else if(intervalStart[i] > end) {
+				return false;
+			}
+		}
+		return false;
+	}
+	
+	public static int getPreviousInterval(int start, int end, int[] intervalStart, int[] intervalEnd) {
+		int length = intervalStart.length;
+		for (int i = 0; i < length; i++) {
+			if(intervalStart[i] > end) {
+				return i - 1;
+			}
+		}
+		return length - 1;
+	}
+	
+	public static boolean containsIgnoredBody(AbstractMethodDeclaration method){
+		return !method.isDefaultConstructor()
+			&& !method.isClinit()
+			&& (method.modifiers & CompilerModifiers.AccSemicolonBody) == 0;
+	}
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
index 6edc226..a35d6d8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser10.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser10.rsc
new file mode 100644
index 0000000..57084e8
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser10.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser11.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser11.rsc
new file mode 100644
index 0000000..4ed7d3b
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser11.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
new file mode 100644
index 0000000..a114c91
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc
new file mode 100644
index 0000000..6b56156
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser13.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
new file mode 100644
index 0000000..e701a9e
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
new file mode 100644
index 0000000..4497913
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
new file mode 100644
index 0000000..0046bb9
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
new file mode 100644
index 0000000..ca3af17
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
new file mode 100644
index 0000000..66f0156
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc
new file mode 100644
index 0000000..0f1c471
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser19.rsc
@@ -0,0 +1 @@
+WWEEE;;X(((5EV5(((((S5F ZZ
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
index 26e416e..3d7327b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
new file mode 100644
index 0000000..8dc5ace
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
index 7b3e30a..81f96e1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
index 45d144e..2842e17 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
index bb9b124..26aa971 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
new file mode 100644
index 0000000..69c1580
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser7.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser7.rsc
new file mode 100644
index 0000000..a4e445a
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser7.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
new file mode 100644
index 0000000..8ce79a7
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
new file mode 100644
index 0000000..6f68468
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
Binary files differ
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.properties
new file mode 100644
index 0000000..ecc98bf
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.properties
@@ -0,0 +1,202 @@
+,opt=,
+AbstractMethodDeclaration=AbstractMethodDeclaration
+AdditiveExpression=Expression
+AllocationHeader=AllocationHeader
+AndExpression=Expression
+ArgumentList=ArgumentList
+ArgumentListopt=ArgumentList
+ArrayAccess=ArrayAccess
+ArrayCreationHeader=ArrayCreationHeader
+ArrayCreationWithArrayInitializer=ArrayCreationWithArrayInitializer
+ArrayCreationWithoutArrayInitializer=ArrayCreationWithoutArrayInitializer
+ArrayInitializer=ArrayInitializer
+ArrayType=ArrayType
+AssertStatement=AssertStatement
+Assignment=Assignment
+AssignmentExpression=Expression
+AssignmentOperator=AssignmentOperator
+Block=Block
+BlockStatement=BlockStatement
+BlockStatements=BlockStatements
+BlockStatementsopt=BlockStatements
+BooleanLiteral=BooleanLiteral
+BreakStatement=BreakStatement
+CastExpression=CastExpression
+CatchClause=CatchClause
+CatchHeader=CatchHeader
+Catches=Catches
+Catchesopt=Catches
+ClassBody=ClassBody
+ClassBodyDeclaration=ClassBodyDeclaration
+ClassBodyDeclarations=ClassBodyDeclarations
+ClassBodyDeclarationsopt=ClassBodyDeclarations
+ClassBodyopt=ClassBody
+ClassDeclaration=ClassDeclaration
+ClassHeader=ClassHeader
+ClassHeaderExtends=ClassHeaderExtends
+ClassHeaderExtendsopt=ClassHeaderExtends
+ClassHeaderImplements=ClassHeaderImplements
+ClassHeaderImplementsopt=ClassHeaderImplements
+ClassHeaderName=ClassHeaderName
+ClassInstanceCreationExpression=ClassInstanceCreationExpression
+ClassInstanceCreationExpressionName=ClassInstanceCreationExpressionName
+ClassMemberDeclaration=ClassMemberDeclaration
+ClassOrInterfaceType=Type
+ClassType=ClassType
+ClassTypeElt=ClassType
+ClassTypeList=ClassTypeList
+CompilationUnit=CompilationUnit
+ConditionalAndExpression=Expression
+ConditionalExpression=Expression
+ConditionalOrExpression=Expression
+ConstantDeclaration=ConstantDeclaration
+ConstantExpression=ConstantExpression
+ConstructorDeclaration=ConstructorDeclaration
+ConstructorHeader=ConstructorHeader
+ConstructorHeaderName=ConstructorHeaderName
+ContinueStatement=ContinueStatement
+Diet=Diet
+DimWithOrWithOutExpr=Dimension
+DimWithOrWithOutExprs=Dimensions
+Dims=Dimensions
+DimsLoop=Dimensions
+Dimsopt=Dimensions
+DoStatement=DoStatement
+EmptyStatement=EmptyStatement
+EnterAnonymousClassBody=EnterAnonymousClassBody
+EnterCompilationUnit=EnterCompilationUnit
+EnterVariable=EnterVariable
+EqualityExpression=Expression
+ExclusiveOrExpression=Expression
+ExitTryBlock=ExitTryBlock
+ExitVariableWithInitialization=ExitVariableWithInitialization
+ExitVariableWithoutInitialization=ExitVariableWithoutInitialization
+ExplicitConstructorInvocation=ExplicitConstructorInvocation
+Expression=Expression
+ExpressionStatement=Statement
+Expressionopt=Expression
+FieldAccess=FieldAccess
+FieldDeclaration=FieldDeclaration
+Finally=Finally
+FloatingPointType=FloatingPointType
+ForInit=ForInit
+ForInitopt=ForInit
+ForStatement=ForStatement
+ForStatementNoShortIf=ForStatement
+ForUpdate=ForUpdate
+ForUpdateopt=ForUpdate
+ForceNoDiet=ForceNoDiet
+FormalParameter=FormalParameter
+FormalParameterList=FormalParameterList
+FormalParameterListopt=FormalParameterList
+GenericMethodDeclaration=GenericMethodDeclaration
+Goal=Goal
+Header=Header
+Headers=Headers
+IfThenElseStatement=IfStatement
+IfThenElseStatementNoShortIf=IfStatement
+IfThenStatement=IfStatement
+ImportDeclaration=ImportDeclaration
+ImportDeclarations=ImportDeclarations
+ImportDeclarationsopt=ImportDeclarations
+InclusiveOrExpression=Expression
+Initializer=Initializer
+InsideCastExpression=InsideCastExpression
+InsideCastExpressionLL1=InsideCastExpression
+IntegralType=IntegralType
+InterfaceBody=InterfaceBody
+InterfaceDeclaration=InterfaceDeclaration
+InterfaceHeader=InterfaceHeader
+InterfaceHeaderExtends=InterfaceHeaderExtends
+InterfaceHeaderExtendsopt=InterfaceHeaderExtends
+InterfaceHeaderName=InterfaceHeaderName
+InterfaceMemberDeclaration=InterfaceMemberDeclaration
+InterfaceMemberDeclarations=InterfaceMemberDeclarations
+InterfaceMemberDeclarationsopt=InterfaceMemberDeclarations
+InterfaceType=InterfaceType
+InterfaceTypeList=InterfaceTypeList
+InvalidArrayInitializerAssignement=ArrayInitializerAssignement
+InvalidConstructorDeclaration=InvalidConstructorDeclaration
+InvalidInterfaceDeclaration=InvalidInterfaceDeclaration
+InvalidMethodDeclaration=InvalidMethodDeclaration
+LabeledStatement=LabeledStatement
+LabeledStatementNoShortIf=LabeledStatement
+Literal=Literal
+LocalVariableDeclaration=LocalVariableDeclaration
+LocalVariableDeclarationStatement=LocalVariableDeclarationStatement
+MethodBody=MethodBody
+MethodDeclaration=MethodDeclaration
+MethodHeader=MethodHeader
+MethodHeaderExtendedDims=MethodHeaderExtendedDims
+MethodHeaderName=MethodHeaderName
+MethodHeaderParameters=MethodHeaderParameters
+MethodHeaderThrowsClause=MethodHeaderThrowsClause
+MethodHeaderThrowsClauseopt=MethodHeaderThrowsClause
+MethodInvocation=MethodInvocation
+Modifier=Modifier
+Modifiers=Modifiers
+Modifiersopt=Modifiers
+MultiplicativeExpression=Expression
+Name=Name
+NestedMethod=NestedMethod
+NestedType=NestedType
+NumericType=NumericType
+OneDimLoop=Dimension
+OnlySynchronized=OnlySynchronized
+OpenBlock=OpenBlock
+PackageDeclaration=PackageDeclaration
+PackageDeclarationName=PackageDeclarationName
+PackageDeclarationopt=PackageDeclaration
+PostDecrementExpression=PostDecrementExpression
+PostIncrementExpression=PostIncrementExpression
+PostfixExpression=Expression
+PreDecrementExpression=PreDecrementExpression
+PreIncrementExpression=PreIncrementExpression
+Primary=Expression
+PrimaryNoNewArray=Expression
+PrimitiveType=PrimitiveType
+PushLPAREN=(
+PushModifiers=PushModifiers
+PushPosition=PushPosition
+PushRPAREN=)
+QualifiedName=QualifiedName
+ReferenceType=ReferenceType
+RelationalExpression=Expression
+RestoreDiet=RestoreDiet
+ReturnStatement=ReturnStatement
+ShiftExpression=Expression
+SimpleName=SimpleName
+SingleTypeImportDeclaration=SingleTypeImportDeclaration
+SingleTypeImportDeclarationName=SingleTypeImportDeclarationName
+Statement=Statement
+StatementExpression=Expression
+StatementExpressionList=StatementExpressionList
+StatementNoShortIf=Statement
+StatementWithoutTrailingSubstatement=Statement
+StaticInitializer=StaticInitializer
+StaticOnly=StaticOnly
+SwitchBlock=SwitchBlock
+SwitchBlockStatement=SwitchBlockStatement
+SwitchBlockStatements=SwitchBlockStatements
+SwitchLabel=SwitchLabel
+SwitchLabels=SwitchLabels
+SwitchStatement=SwitchStatement
+SynchronizedStatement=SynchronizedStatement
+ThrowStatement=ThrowStatement
+TryBlock=Block
+TryStatement=TryStatement
+Type=Type
+TypeDeclaration=TypeDeclaration
+TypeDeclarations=TypeDeclarations
+TypeDeclarationsopt=TypeDeclarations
+TypeImportOnDemandDeclaration=TypeImportOnDemandDeclaration
+TypeImportOnDemandDeclarationName=TypeImportOnDemandDeclarationName
+UnaryExpression=Expression
+UnaryExpressionNotPlusMinus=Expression
+VariableDeclarator=VariableDeclarator
+VariableDeclaratorId=VariableDeclaratorId
+VariableDeclarators=VariableDeclarators
+VariableInitializer=VariableInitializer
+VariableInitializers=VariableInitializers
+WhileStatement=WhileStatement
+WhileStatementNoShortIf=WhileStatement
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java
index 799840a..f170b62 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java
@@ -30,7 +30,7 @@
 
 	public AbortCompilation() {
 
-		this((CompilationResult)null);
+		this(null);
 	}
 
 	public AbortCompilation(int problemId, String[] problemArguments, String[] messageArguments) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblem.java
index 635428f..fb6ce8f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblem.java
@@ -11,7 +11,6 @@
 package org.eclipse.jdt.internal.compiler.problem;
 
 import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class DefaultProblem implements ProblemSeverities, IProblem {
@@ -42,8 +41,7 @@
 		this.endPosition = endPosition;
 		this.line = line;
 	}
-
-	public String errorReportSource(ICompilationUnit compilationUnit) {
+	public String errorReportSource(char[] unitSource) {
 		//extra from the source the innacurate     token
 		//and "highlight" it using some underneath ^^^^^
 		//put some context around too.
@@ -52,73 +50,47 @@
 
 		//sanity .....
 		if ((startPosition > endPosition)
-			|| ((startPosition <= 0) && (endPosition <= 0)))
+			|| ((startPosition < 0) && (endPosition < 0)))
 			return Util.bind("problem.noSourceInformation"); //$NON-NLS-1$
 
+		StringBuffer errorBuffer = new StringBuffer(" "); //$NON-NLS-1$
+		errorBuffer.append(Util.bind("problem.atLine", String.valueOf(line))); //$NON-NLS-1$
+		errorBuffer.append("\n\t"); //$NON-NLS-1$
+		
+		char c;
 		final char SPACE = '\u0020';
 		final char MARK = '^';
 		final char TAB = '\t';
-		char[] source = compilationUnit.getContents();
 		//the next code tries to underline the token.....
 		//it assumes (for a good display) that token source does not
 		//contain any \r \n. This is false on statements ! 
 		//(the code still works but the display is not optimal !)
 
-		//compute the how-much-char we are displaying around the inaccurate token
-		int begin = startPosition >= source.length ? source.length - 1 : startPosition;
-		int relativeStart = 0;
-		int end = endPosition >= source.length ? source.length - 1 : endPosition;
-		int relativeEnd = 0;
-		label : for (relativeStart = 0;; relativeStart++) {
-			if (begin == 0)
-				break label;
-			if ((source[begin - 1] == '\n') || (source[begin - 1] == '\r'))
-				break label;
-			begin--;
+		// expand to line limits
+		int length = unitSource.length, begin, end;
+		for (begin = startPosition >= length ? length - 1 : startPosition; begin > 0; begin--) {
+			if ((c = unitSource[begin - 1]) == '\n' || c == '\r') break;
 		}
-		label : for (relativeEnd = 0;; relativeEnd++) {
-			if ((end + 1) >= source.length)
-				break label;
-			if ((source[end + 1] == '\r') || (source[end + 1] == '\n')) {
-				break label;
-			}
-			end++;
+		for (end = endPosition >= length ? length - 1 : endPosition ; end+1 < length; end++) {
+			if ((c = unitSource[end + 1]) == '\r' || c == '\n') break;
 		}
-		//extract the message form the source
-		char[] extract = new char[end - begin + 1];
-		System.arraycopy(source, begin, extract, 0, extract.length);
-		char c;
-		//remove all SPACE and TAB that begin the error message...
-		int trimLeftIndex = 0;
-		while (((c = extract[trimLeftIndex++]) == TAB) || (c == SPACE)) {
-		};
-		System.arraycopy(
-			extract,
-			trimLeftIndex - 1,
-			extract = new char[extract.length - trimLeftIndex + 1],
-			0,
-			extract.length);
-		relativeStart -= trimLeftIndex;
-		//buffer spaces and tabs in order to reach the error position
-		int pos = 0;
-		char[] underneath = new char[extract.length]; // can't be bigger
-		for (int i = 0; i <= relativeStart; i++) {
-			if (extract[i] == TAB) {
-				underneath[pos++] = TAB;
-			} else {
-				underneath[pos++] = SPACE;
-			}
+		
+		// trim left and right spaces/tabs
+		while ((c = unitSource[begin]) == ' ' || c == '\t') begin++;
+		//while ((c = unitSource[end]) == ' ' || c == '\t') end--; TODO (philippe) should also trim right, but all tests are to be updated
+		
+		// copy source
+		errorBuffer.append(unitSource, begin, end-begin+1);
+		errorBuffer.append("\n\t"); //$NON-NLS-1$
+		
+		// compute underline
+		for (int i = begin; i <startPosition; i++) {
+			errorBuffer.append((unitSource[i] == TAB) ? TAB : SPACE);
 		}
-		//mark the error position
-		for (int i = startPosition;
-			i <= (endPosition >= source.length ? source.length - 1 : endPosition);
-			i++)
-			underneath[pos++] = MARK;
-		//resize underneathto remove 'null' chars
-		System.arraycopy(underneath, 0, underneath = new char[pos], 0, pos);
-
-		return " " + Util.bind("problem.atLine", String.valueOf(line)) 	//$NON-NLS-2$ //$NON-NLS-1$
-			+ "\n\t" + new String(extract) + "\n\t" + new String(underneath); //$NON-NLS-2$ //$NON-NLS-1$
+		for (int i = startPosition; i <= (endPosition >= length ? length - 1 : endPosition); i++) {
+			errorBuffer.append(MARK);
+		}
+		return errorBuffer.toString();
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.java
index 87a3c0e..f38687a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.java
@@ -17,16 +17,21 @@
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class DefaultProblemFactory implements IProblemFactory {
 
-
+	public static final int MAX_MESSAGES = 500;
+	
 	public String[] messageTemplates;
 	private Locale locale;
 	private static String[] DEFAULT_LOCALE_TEMPLATES;
 	private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
 	private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
 
+public DefaultProblemFactory() {
+	this(Locale.getDefault());
+}
 /**
  * @param loc the locale used to get the right message
  */
@@ -91,8 +96,10 @@
 }
 public final String getLocalizedMessage(int id, String[] problemArguments) {
 	StringBuffer output = new StringBuffer(80);
-	String message = 
-		messageTemplates[(id & IProblem.IgnoreCategoriesMask)]; 
+	if ((id & IProblem.Javadoc) != 0) {
+		output.append(messageTemplates[IProblem.JavadocMessagePrefix & IProblem.IgnoreCategoriesMask]);
+	}
+	String message = messageTemplates[id & IProblem.IgnoreCategoriesMask]; 
 	if (message == null) {
 		return "Unable to retrieve the error message for problem id: " //$NON-NLS-1$
 			+ (id & IProblem.IgnoreCategoriesMask)
@@ -116,9 +123,13 @@
 				} catch (NumberFormatException nfe) {
 					output.append(message.substring(end + 1, start + 1));
 				} catch (ArrayIndexOutOfBoundsException e) {
-					return "Corrupted compiler resources for problem id: " //$NON-NLS-1$
+					return "Cannot bind message for problem (id: " //$NON-NLS-1$
 						+ (id & IProblem.IgnoreCategoriesMask)
-						+ ". Check compiler resources.";  //$NON-NLS-1$
+						+ ") \""  //$NON-NLS-1$
+						+ message
+						+ "\" with arguments: {" //$NON-NLS-1$
+						+ Util.toString(problemArguments)
+						+"}"; //$NON-NLS-1$
 				}
 			} else {
 				output.append(message.substring(end, length));
@@ -152,7 +163,7 @@
 		System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + loc); //$NON-NLS-1$//$NON-NLS-2$
 		throw e;
 	}
-	String[] templates = new String[500];
+	String[] templates = new String[MAX_MESSAGES];
 	for (int i = 0, max = templates.length; i < max; i++) {
 		try {
 			templates[i] = bundle.getString(String.valueOf(i));
@@ -163,7 +174,4 @@
 	return templates;
 }
 
-public DefaultProblemFactory() {
-	this(Locale.getDefault());
-}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index e0bc26f..9c136b8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -10,23 +10,21 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.problem;
 
-import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
-import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.env.IConstants;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
-import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.compiler.parser.Parser;
-import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class ProblemReporter extends ProblemHandler implements ProblemReasons {
 	
 	public ReferenceContext referenceContext;
+	
 public ProblemReporter(IErrorHandlingPolicy policy, CompilerOptions options, IProblemFactory problemFactory) {
 	super(policy, options, problemFactory);
 }
@@ -40,7 +38,7 @@
 		0,
 		0);
 }
-public void abortDueToInternalError(String errorMessage, AstNode location) {
+public void abortDueToInternalError(String errorMessage, ASTNode location) {
 	String[] arguments = new String[] {errorMessage};
 	this.handle(
 		IProblem.Unclassified,
@@ -112,7 +110,7 @@
 		method,
 		method.compilationResult());
 }
-public void alreadyDefinedLabel(char[] labelName, AstNode location) {
+public void alreadyDefinedLabel(char[] labelName, ASTNode location) {
 	String[] arguments = new String[] {new String(labelName)};
 	this.handle(
 		IProblem.DuplicateLabel,
@@ -173,8 +171,8 @@
 	}
 	this.handle(
 		id,
-		new String[] {new String(methodDecl.selector), arg.name(), new String(expectedType.readableName())},
-		new String[] {new String(methodDecl.selector), arg.name(), new String(expectedType.shortReadableName())},
+		new String[] {new String(methodDecl.selector), new String(arg.name), new String(expectedType.readableName())},
+		new String[] {new String(methodDecl.selector), new String(arg.name), new String(expectedType.shortReadableName())},
 		arg.type.sourceStart,
 		arg.type.sourceEnd);
 }
@@ -248,7 +246,7 @@
 		expression.sourceStart,
 		expression.sourceEnd);
 }
-public void cannotAssignToFinalField(FieldBinding field, AstNode location) {
+public void cannotAssignToFinalField(FieldBinding field, ASTNode location) {
 	this.handle(
 		IProblem.FinalFieldAssignment,
 		new String[] {
@@ -260,7 +258,7 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void cannotAssignToFinalLocal(LocalVariableBinding local, AstNode location) {
+public void cannotAssignToFinalLocal(LocalVariableBinding local, ASTNode location) {
 	String[] arguments = new String[] { new String(local.readableName())};
 	this.handle(
 		IProblem.NonBlankFinalLocalAssignment,
@@ -269,7 +267,7 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void cannotAssignToFinalOuterLocal(LocalVariableBinding local, AstNode location) {
+public void cannotAssignToFinalOuterLocal(LocalVariableBinding local, ASTNode location) {
 	String[] arguments = new String[] {new String(local.readableName())};
 	this.handle(
 		IProblem.FinalOuterLocalAssignment,
@@ -320,7 +318,7 @@
 		typeRef.sourceStart,
 		typeRef.sourceEnd);
 }
-public void cannotReferToNonFinalOuterLocal(LocalVariableBinding local, AstNode location) {
+public void cannotReferToNonFinalOuterLocal(LocalVariableBinding local, ASTNode location) {
 	String[] arguments =new String[]{ new String(local.readableName())};
 	this.handle(
 		IProblem.OuterLocalMustBeFinal,
@@ -329,7 +327,7 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void cannotReturnInInitializer(AstNode location) {
+public void cannotReturnInInitializer(ASTNode location) {
 	this.handle(
 		IProblem.CannotReturnInInitializer,
 		NoArgument,
@@ -353,7 +351,7 @@
 		exceptionType.sourceStart,
 		exceptionType.sourceEnd);
 }
-public void cannotUseSuperInJavaLangObject(AstNode reference) {
+public void cannotUseSuperInJavaLangObject(ASTNode reference) {
 	this.handle(
 		IProblem.ObjectHasNoSuperclass,
 		NoArgument,
@@ -423,196 +421,173 @@
 //	}
 
 	// if not then check whether it is a configurable problem
-	int errorThreshold = options.errorThreshold;
-	int warningThreshold = options.warningThreshold;
-	
 	switch(problemId){
 
-		case IProblem.UnreachableCatch :
-		case IProblem.CodeCannotBeReached :
-			if ((errorThreshold & CompilerOptions.UnreachableCode) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.UnreachableCode) != 0){
-				return Warning;
-			}
-			return Ignore;
-
 		case IProblem.MaskedCatch : 
-			if ((errorThreshold & CompilerOptions.MaskedCatchBlock) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.MaskedCatchBlock) != 0){
-				return Warning;
-			}
-			return Ignore;
-			
-/*
-		case Never Used  :
-			if ((errorThreshold & ParsingOptionalError) != 0){
-				return Error;
-			}
-			if ((warningThreshold & ParsingOptionalError) != 0){
-				return Warning;
-			}
-			return Ignore;
-*/
-		case IProblem.ImportNotFound :
-		case IProblem.ImportNotVisible :
-		case IProblem.ImportAmbiguous :
-		case IProblem.ImportInternalNameProvided :
-		case IProblem.ImportInheritedNameHidesEnclosingName :
-		case IProblem.DuplicateImport :
-		case IProblem.ConflictingImport :
-		case IProblem.CannotImportPackage :
-			if ((errorThreshold & CompilerOptions.ImportProblem) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.ImportProblem) != 0){
-				return Warning;
-			}
-			return Ignore;
-			
+			return this.options.getSeverity(CompilerOptions.MaskedCatchBlock);
+
 		case IProblem.UnusedImport :
-			// if import problem are disabled, then ignore
-			if ((errorThreshold & CompilerOptions.ImportProblem) == 0 
-				&& (warningThreshold & CompilerOptions.ImportProblem) == 0){
-				return Ignore;
-			}
-			if ((errorThreshold & CompilerOptions.UnusedImport) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.UnusedImport) != 0){
-				return Warning;
-			}
-			return Ignore;
+			return this.options.getSeverity(CompilerOptions.UnusedImport);
 			
 		case IProblem.MethodButWithConstructorName :
-			if ((errorThreshold & CompilerOptions.MethodWithConstructorName) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.MethodWithConstructorName) != 0){
-				return Warning;
-			}
-			return Ignore;
+			return this.options.getSeverity(CompilerOptions.MethodWithConstructorName);
 		
 		case IProblem.OverridingNonVisibleMethod :
-			if ((errorThreshold & CompilerOptions.OverriddenPackageDefaultMethod) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.OverriddenPackageDefaultMethod) != 0){
-				return Warning;
-			}
-			return Ignore;
+			return this.options.getSeverity(CompilerOptions.OverriddenPackageDefaultMethod);
 
 		case IProblem.IncompatibleReturnTypeForNonInheritedInterfaceMethod :
 		case IProblem.IncompatibleExceptionInThrowsClauseForNonInheritedInterfaceMethod :
-			if ((errorThreshold & CompilerOptions.IncompatibleNonInheritedInterfaceMethod) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.IncompatibleNonInheritedInterfaceMethod) != 0){
-				return Warning;
-			}
-			return Ignore;
+			return this.options.getSeverity(CompilerOptions.IncompatibleNonInheritedInterfaceMethod);
 
 		case IProblem.OverridingDeprecatedMethod :				
 		case IProblem.UsingDeprecatedType :				
 		case IProblem.UsingDeprecatedMethod :
 		case IProblem.UsingDeprecatedConstructor :
 		case IProblem.UsingDeprecatedField :
-			if ((errorThreshold & CompilerOptions.UsingDeprecatedAPI) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.UsingDeprecatedAPI) != 0){
-				return Warning;
-			}
-			return Ignore;
+			return this.options.getSeverity(CompilerOptions.UsingDeprecatedAPI);
 		
 		case IProblem.LocalVariableIsNeverUsed :
-			if ((errorThreshold & CompilerOptions.UnusedLocalVariable) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.UnusedLocalVariable) != 0){
-				return Warning;
-			}
-			return Ignore;
+			return this.options.getSeverity(CompilerOptions.UnusedLocalVariable);
 		
 		case IProblem.ArgumentIsNeverUsed :
-			if ((errorThreshold & CompilerOptions.UnusedArgument) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.UnusedArgument) != 0){
-				return Warning;
-			}
-			return Ignore;
+			return this.options.getSeverity(CompilerOptions.UnusedArgument);
 
 		case IProblem.NoImplicitStringConversionForCharArrayExpression :
-			if ((errorThreshold & CompilerOptions.NoImplicitStringConversion) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.NoImplicitStringConversion) != 0){
-				return Warning;
-			}
-			return Ignore;
+			return this.options.getSeverity(CompilerOptions.NoImplicitStringConversion);
 
 		case IProblem.NeedToEmulateFieldReadAccess :
 		case IProblem.NeedToEmulateFieldWriteAccess :
 		case IProblem.NeedToEmulateMethodAccess :
 		case IProblem.NeedToEmulateConstructorAccess :			
-			if ((errorThreshold & CompilerOptions.AccessEmulation) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.AccessEmulation) != 0){
-				return Warning;
-			}
-			return Ignore;
+			return this.options.getSeverity(CompilerOptions.AccessEmulation);
+
 		case IProblem.NonExternalizedStringLiteral :
-			if ((errorThreshold & CompilerOptions.NonExternalizedString) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.NonExternalizedString) != 0){
-				return Warning;
-			}
-			return Ignore;
+			return this.options.getSeverity(CompilerOptions.NonExternalizedString);
+
 		case IProblem.UseAssertAsAnIdentifier :
-			if ((errorThreshold & CompilerOptions.AssertUsedAsAnIdentifier) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.AssertUsedAsAnIdentifier) != 0){
-				return Warning;
-			}
-			return Ignore;		
+			return this.options.getSeverity(CompilerOptions.AssertUsedAsAnIdentifier);
+
 		case IProblem.NonStaticAccessToStaticMethod :
 		case IProblem.NonStaticAccessToStaticField :
-			if ((errorThreshold & CompilerOptions.StaticAccessReceiver) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.StaticAccessReceiver) != 0){
-				return Warning;
-			}
-			return Ignore;		
+			return this.options.getSeverity(CompilerOptions.NonStaticAccessToStatic);
+
+		case IProblem.IndirectAccessToStaticMethod :
+		case IProblem.IndirectAccessToStaticField :
+		case IProblem.IndirectAccessToStaticType :
+			return this.options.getSeverity(CompilerOptions.IndirectStaticAccess);
+
 		case IProblem.AssignmentHasNoEffect:
-			if ((errorThreshold & CompilerOptions.NoEffectAssignment) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.NoEffectAssignment) != 0){
-				return Warning;
-			}
-			return Ignore;		
+			return this.options.getSeverity(CompilerOptions.NoEffectAssignment);
+
 		case IProblem.UnusedPrivateConstructor:
 		case IProblem.UnusedPrivateMethod:
 		case IProblem.UnusedPrivateField:
 		case IProblem.UnusedPrivateType:
-			if ((errorThreshold & CompilerOptions.UnusedPrivateMember) != 0){
-				return Error;
-			}
-			if ((warningThreshold & CompilerOptions.UnusedPrivateMember) != 0){
-				return Warning;
-			}
-			return Ignore;		
-		
+			return this.options.getSeverity(CompilerOptions.UnusedPrivateMember);
+
 		case IProblem.Task :
 			return Warning;			
+
+		case IProblem.LocalVariableHidingLocalVariable:
+		case IProblem.LocalVariableHidingField:
+		case IProblem.ArgumentHidingLocalVariable:
+		case IProblem.ArgumentHidingField:
+			return this.options.getSeverity(CompilerOptions.LocalVariableHiding);
+
+		case IProblem.FieldHidingLocalVariable:
+		case IProblem.FieldHidingField:
+			return this.options.getSeverity(CompilerOptions.FieldHiding);
+
+		case IProblem.PossibleAccidentalBooleanAssignment:
+			return this.options.getSeverity(CompilerOptions.AccidentalBooleanAssign);
+
+		case IProblem.SuperfluousSemicolon:
+			return this.options.getSeverity(CompilerOptions.SuperfluousSemicolon);
+
+		case IProblem.UndocumentedEmptyBlock:
+			return this.options.getSeverity(CompilerOptions.UndocumentedEmptyBlock);
+			
+		case IProblem.UnnecessaryCast:
+		case IProblem.UnnecessaryArgumentCast:
+		case IProblem.UnnecessaryInstanceof:
+			return this.options.getSeverity(CompilerOptions.UnnecessaryTypeCheck);
+			
+		case IProblem.FinallyMustCompleteNormally:
+			return this.options.getSeverity(CompilerOptions.FinallyBlockNotCompleting);
+			
+		case IProblem.UnusedMethodDeclaredThrownException:
+		case IProblem.UnusedConstructorDeclaredThrownException:
+			return this.options.getSeverity(CompilerOptions.UnusedDeclaredThrownException);
+
+		case IProblem.UnqualifiedFieldAccess:
+			return this.options.getSeverity(CompilerOptions.UnqualifiedFieldAccess);
+
+		/*
+		 * Javadoc syntax errors
+		 */
+		// Javadoc explicit IDs
+		case IProblem.JavadocUnexpectedTag:
+		case IProblem.JavadocDuplicateReturnTag:
+		case IProblem.JavadocInvalidThrowsClass:
+		case IProblem.JavadocInvalidSeeReference:
+		case IProblem.JavadocInvalidSeeHref:
+		case IProblem.JavadocInvalidSeeArgs:
+			return this.options.getSeverity(CompilerOptions.InvalidJavadoc);
+
+		/*
+		 * Javadoc tags resolved references errors
+		 */
+		case IProblem.JavadocInvalidParamName:
+		case IProblem.JavadocDuplicateParamName:
+		case IProblem.JavadocMissingParamName:
+		case IProblem.JavadocInvalidThrowsClassName:
+		case IProblem.JavadocDuplicateThrowsClassName:
+		case IProblem.JavadocMissingThrowsClassName:
+		case IProblem.JavadocMissingSeeReference:
+		// Javadoc implicit IDs for deprecatedField(...)
+		case IProblem.Javadoc | IProblem.UsingDeprecatedField:
+		// Javadoc implicit IDs for deprecatedMethod(...)
+		case IProblem.Javadoc | IProblem.UsingDeprecatedConstructor:
+		case IProblem.Javadoc | IProblem.UsingDeprecatedMethod:
+		// Javadoc implicit IDs for deprecatedType(...)
+		case IProblem.Javadoc | IProblem.UsingDeprecatedType:
+		// Javadoc implicit IDs for invalidField(...)
+		case IProblem.Javadoc | IProblem.UndefinedField:
+		case IProblem.Javadoc | IProblem.NotVisibleField:
+		case IProblem.Javadoc | IProblem.AmbiguousField:
+		// Javadoc implicit IDs for invalidConstructor(...)
+		case IProblem.Javadoc | IProblem.UndefinedConstructor:
+		case IProblem.Javadoc | IProblem.NotVisibleConstructor:
+		// Javadoc implicit IDs for invalidMethod(...)
+		case IProblem.Javadoc | IProblem.UndefinedMethod:
+		case IProblem.Javadoc | IProblem.NotVisibleMethod:
+		case IProblem.Javadoc | IProblem.ParameterMismatch:
+		// Javadoc implicit IDs for invalidType(...)
+		case IProblem.Javadoc | IProblem.UndefinedType:
+		case IProblem.Javadoc | IProblem.NotVisibleType:
+		// Javadoc implicit IDs for errorNoMethodFor(...)
+		case IProblem.Javadoc | IProblem.NoMessageSendOnArrayType:
+		case IProblem.Javadoc | IProblem.NoMessageSendOnBaseType:
+			if (!this.options.reportInvalidJavadocTags)
+				return ProblemSeverities.Ignore;
+			else
+				return this.options.getSeverity(CompilerOptions.InvalidJavadoc);
+
+		/*
+		 * Javadoc missing tags errors
+		 */
+		case IProblem.JavadocMissingParamTag:
+		case IProblem.JavadocMissingReturnTag:
+		case IProblem.JavadocMissingThrowsTag:
+			return this.options.getSeverity(CompilerOptions.MissingJavadocTags);
+
+		/*
+		 * Missing Javadoc errors
+		 */
+		case IProblem.JavadocMissing:
+			return this.options.getSeverity(CompilerOptions.MissingJavadocComments);
+
+		// by default problems are errors.
 		default:
 			return Error;
 	}
@@ -634,19 +609,19 @@
 		importRef.sourceStart,
 		importRef.sourceEnd);
 }
-public void constantOutOfFormat(NumberLiteral lit) {
+public void constantOutOfFormat(NumberLiteral literal) {
 	// the literal is not in a correct format
 	// this code is called on IntLiteral and LongLiteral 
 	// example 000811 ...the 8 is uncorrect.
 
-	if ((lit instanceof LongLiteral) || (lit instanceof IntLiteral)) {
-		char[] source = lit.source();
+	if ((literal instanceof LongLiteral) || (literal instanceof IntLiteral)) {
+		char[] source = literal.source();
 		try {
 			final String Radix;
 			final int radix;
 			if ((source[1] == 'x') || (source[1] == 'X')) {
 				radix = 16;
-				Radix = "Hexa"; //$NON-NLS-1$
+				Radix = "Hex"; //$NON-NLS-1$
 			} else {
 				radix = 8;
 				Radix = "Octal"; //$NON-NLS-1$
@@ -659,34 +634,36 @@
 					break label;
 				}
 			}
-			String[] arguments = new String[] {Radix + " " + new String(source) + " (digit " + new String(new char[] {source[place]}) + ")"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			String[] arguments = new String[] {
+				new String(literal.literalType(null).readableName()), // numeric literals do not need scope to reach type
+				Radix + " " + new String(source) + " (digit " + new String(new char[] {source[place]}) + ")"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 
 			this.handle(
 				IProblem.NumericValueOutOfRange,
 				arguments,
 				arguments,
-				lit.sourceStart,
-				lit.sourceEnd);
+				literal.sourceStart,
+				literal.sourceEnd);
 			return;
-		} catch (IndexOutOfBoundsException ex) {}
+		} catch (IndexOutOfBoundsException ex) {
+			// should never happen
+		}
 	
 		// just in case .... use a predefined error..
 		// we should never come here...(except if the code changes !)
-		this.constantOutOfRange(lit);
+		this.constantOutOfRange(literal, literal.literalType(null)); // numeric literals do not need scope to reach type
 	}
 }
-public void constantOutOfRange(Literal lit) {
-	// lit is some how out of range of it declared type
-	// example 9999999999999999999999999999999999999999999999999999999999999999999
-	String[] arguments = new String[] {new String(lit.source())};
+public void constantOutOfRange(Literal literal, TypeBinding literalType) {
+	String[] arguments = new String[] {new String(literalType.readableName()), new String(literal.source())};
 	this.handle(
 		IProblem.NumericValueOutOfRange,
 		arguments,
 		arguments,
-		lit.sourceStart,
-		lit.sourceEnd);
+		literal.sourceStart,
+		literal.sourceEnd);
 }
-public void deprecatedField(FieldBinding field, AstNode location) {
+public void deprecatedField(FieldBinding field, ASTNode location) {
 	this.handle(
 		IProblem.UsingDeprecatedField,
 		new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
@@ -694,23 +671,24 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void deprecatedMethod(MethodBinding method, AstNode location) {
-	if (method.isConstructor())
+public void deprecatedMethod(MethodBinding method, ASTNode location) {
+	if (method.isConstructor()) {
 		this.handle(
 			IProblem.UsingDeprecatedConstructor,
 			new String[] {new String(method.declaringClass.readableName()), parametersAsString(method)},
 			new String[] {new String(method.declaringClass.shortReadableName()), parametersAsShortString(method)},
 			location.sourceStart,
 			location.sourceEnd);
-	else
+	} else {
 		this.handle(
 			IProblem.UsingDeprecatedMethod,
 			new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
 			new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
 			location.sourceStart,
 			location.sourceEnd);
+	}
 }
-public void deprecatedType(TypeBinding type, AstNode location) {
+public void deprecatedType(TypeBinding type, ASTNode location) {
 	if (location == null) return; // 1G828DN - no type ref for synthetic arguments
 	this.handle(
 		IProblem.UsingDeprecatedType,
@@ -719,16 +697,15 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void duplicateCase(Case statement, Constant constant) {
-	String[] arguments = new String[] {String.valueOf(constant.intValue())};
+public void duplicateCase(CaseStatement caseStatement) {
 	this.handle(
 		IProblem.DuplicateCase,
-		arguments,
-		arguments,
-		statement.sourceStart,
-		statement.sourceEnd);
+		NoArgument,
+		NoArgument,
+		caseStatement.sourceStart,
+		caseStatement.sourceEnd);
 }
-public void duplicateDefaultCase(DefaultCase statement) {
+public void duplicateDefaultCase(ASTNode statement) {
 	this.handle(
 		IProblem.DuplicateDefaultCase,
 		NoArgument,
@@ -739,8 +716,8 @@
 public void duplicateFieldInType(SourceTypeBinding type, FieldDeclaration fieldDecl) {
 	this.handle(
 		IProblem.DuplicateField,
-		new String[] {new String(type.sourceName()), fieldDecl.name()},
-		new String[] {new String(type.shortReadableName()), fieldDecl.name()},
+		new String[] {new String(type.sourceName()), new String(fieldDecl.name)},
+		new String[] {new String(type.shortReadableName()), new String(fieldDecl.name)},
 		fieldDecl.sourceStart,
 		fieldDecl.sourceEnd);
 }
@@ -762,7 +739,7 @@
 		reference.sourceStart,
 		reference.sourceEnd);
 }
-public void duplicateInitializationOfFinalLocal(LocalVariableBinding local, AstNode location) {
+public void duplicateInitializationOfFinalLocal(LocalVariableBinding local, ASTNode location) {
 	String[] arguments = new String[] { new String(local.readableName())};
 	this.handle(
 		IProblem.DuplicateFinalLocalInitialization,
@@ -785,11 +762,11 @@
 	this.handle(
 		new Problem(
 			DuplicateModifierForField,
-			new String[] {fieldDecl.name()},
+			new String[] {new String(fieldDecl.name)},
 			fieldDecl.modifiers.sourceStart,
 			fieldDecl.modifiers.sourceEnd));
 */
-	String[] arguments = new String[] {fieldDecl.name()};
+	String[] arguments = new String[] {new String(fieldDecl.name)};
 	this.handle(
 		IProblem.DuplicateModifierForField,
 		arguments,
@@ -815,7 +792,7 @@
 		type.sourceEnd());
 }
 public void duplicateModifierForVariable(LocalDeclaration localDecl, boolean complainForArgument) {
-	String[] arguments = new String[] {localDecl.name()};
+	String[] arguments = new String[] {new String(localDecl.name)};
 	this.handle(
 		complainForArgument
 			? IProblem.DuplicateModifierForArgument 
@@ -869,14 +846,21 @@
 		shortBuffer.append(new String(params[i].shortReadableName()));
 	}
 
+	int id = recType.isArrayType() ? IProblem.NoMessageSendOnArrayType : IProblem.NoMessageSendOnBaseType;
+	/*
+	if ((messageSend.bits & ASTNode.InsideJavadoc) != 0) {
+		id |= IProblem.Javadoc;
+		if (!reportInvalidJavadocTagsVisibility()) return;
+	}
+	*/
 	this.handle(
-		recType.isArrayType() ? IProblem.NoMessageSendOnArrayType : IProblem.NoMessageSendOnBaseType,
+		id,
 		new String[] {new String(recType.readableName()), new String(messageSend.selector), buffer.toString()},
 		new String[] {new String(recType.shortReadableName()), new String(messageSend.selector), shortBuffer.toString()},
 		messageSend.sourceStart,
 		messageSend.sourceEnd);
 }
-public void errorThisSuperInStatic(AstNode reference) {
+public void errorThisSuperInStatic(ASTNode reference) {
 	String[] arguments = new String[] {reference.isSuper() ? "super" : "this"}; //$NON-NLS-2$ //$NON-NLS-1$
 	this.handle(
 		IProblem.ThisInStaticContext,
@@ -924,6 +908,36 @@
 		expression.sourceStart,
 		expression.sourceEnd);
 }
+public void fieldHiding(FieldDeclaration fieldDecl, Binding hiddenVariable) {
+	FieldBinding field = fieldDecl.binding;
+	if (hiddenVariable instanceof LocalVariableBinding) {
+		this.handle(
+			IProblem.FieldHidingLocalVariable,
+			new String[] {new String(field.declaringClass.readableName()), new String(field.name) },
+			new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name) },
+			fieldDecl.sourceStart,
+			fieldDecl.sourceEnd);
+	} else if (hiddenVariable instanceof FieldBinding) {
+		FieldBinding hiddenField = (FieldBinding) hiddenVariable;
+		this.handle(
+			IProblem.FieldHidingField,
+			new String[] {new String(field.declaringClass.readableName()), new String(field.name) , new String(hiddenField.declaringClass.readableName())  },
+			new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name) , new String(hiddenField.declaringClass.shortReadableName()) },
+			fieldDecl.sourceStart,
+			fieldDecl.sourceEnd);
+	}
+}
+private int fieldLocation(FieldBinding field, ASTNode node) {
+	if (node instanceof QualifiedNameReference) {
+		QualifiedNameReference ref = (QualifiedNameReference) node;
+		FieldBinding[] bindings = ref.otherBindings;
+		if (bindings != null)
+			for (int i = bindings.length; --i >= 0;)
+				if (bindings[i] == field)
+					return (int) ref.sourcePositions[i + 1]; // first position is for the primary field
+	}
+	return node.sourceEnd;
+}
 public void fieldsOrThisBeforeConstructorInvocation(ThisReference reference) {
 	this.handle(
 		IProblem.ThisSuperDuringConstructorInvocation,
@@ -958,11 +972,19 @@
 	}
 	this.handle(
 		id,
-		new String[] {fieldDecl.name(), new String(type.sourceName()), new String(expectedType.readableName())},
-		new String[] {fieldDecl.name(), new String(type.sourceName()), new String(expectedType.shortReadableName())},
+		new String[] {new String(fieldDecl.name), new String(type.sourceName()), new String(expectedType.readableName())},
+		new String[] {new String(fieldDecl.name), new String(type.sourceName()), new String(expectedType.shortReadableName())},
 		fieldDecl.type.sourceStart,
 		fieldDecl.type.sourceEnd);
 }
+public void finallyMustCompleteNormally(Block finallyBlock) {
+	this.handle(
+		IProblem.FinallyMustCompleteNormally,
+		NoArgument,
+		NoArgument,
+		finallyBlock.sourceStart,
+		finallyBlock.sourceEnd);
+}
 public void finalMethodCannotBeOverridden(MethodBinding currentMethod, MethodBinding inheritedMethod) {
 	this.handle(
 		// Cannot override the final method from %1
@@ -984,7 +1006,6 @@
 // use this private API when the compilation unit result can be found through the
 // reference context. Otherwise, use the other API taking a problem and a compilation result
 // as arguments
-
 private void handle(
 	int problemId, 
 	String[] problemArguments,
@@ -998,14 +1019,13 @@
 			messageArguments,
 			problemStartPosition,
 			problemEndPosition,
-			referenceContext, 
-			referenceContext == null ? null : referenceContext.compilationResult()); 
-	referenceContext = null;
+			this.referenceContext, 
+			this.referenceContext == null ? null : this.referenceContext.compilationResult()); 
+	this.referenceContext = null;
 }
 // use this private API when the compilation unit result can be found through the
 // reference context. Otherwise, use the other API taking a problem and a compilation result
 // as arguments
-
 private void handle(
 	int problemId, 
 	String[] problemArguments,
@@ -1021,9 +1041,9 @@
 			severity,
 			problemStartPosition,
 			problemEndPosition,
-			referenceContext, 
-			referenceContext == null ? null : referenceContext.compilationResult()); 
-	referenceContext = null;
+			this.referenceContext, 
+			this.referenceContext == null ? null : this.referenceContext.compilationResult()); 
+	this.referenceContext = null;
 }
 // use this private API when the compilation unit result cannot be found through the
 // reference context. 
@@ -1042,9 +1062,21 @@
 			messageArguments,
 			problemStartPosition,
 			problemEndPosition,
-			referenceContext, 
+			this.referenceContext, 
 			unitResult); 
-	referenceContext = null;
+	this.referenceContext = null;
+}
+public void hiddenCatchBlock(ReferenceBinding exceptionType, ASTNode location) {
+	this.handle(
+		IProblem.MaskedCatch,
+		new String[] {
+			new String(exceptionType.readableName()),
+		 }, 
+		new String[] {
+			new String(exceptionType.shortReadableName()),
+		 }, 
+		location.sourceStart,
+		location.sourceEnd);
 }
 public void hidingEnclosingType(TypeDeclaration typeDecl) {
 	String[] arguments = new String[] {new String(typeDecl.name)};
@@ -1117,7 +1149,7 @@
 		type.sourceEnd());
 }
 public void illegalModifierCombinationFinalVolatileForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
-	String[] arguments = new String[] {fieldDecl.name()};
+	String[] arguments = new String[] {new String(fieldDecl.name)};
 
 	this.handle(
 		IProblem.IllegalModifierCombinationFinalVolatileForField,
@@ -1137,7 +1169,7 @@
 		type.sourceEnd());
 }
 public void illegalModifierForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
-	String[] arguments = new String[] {fieldDecl.name()};
+	String[] arguments = new String[] {new String(fieldDecl.name)};
 	this.handle(
 		IProblem.IllegalModifierForField,
 		arguments,
@@ -1155,7 +1187,7 @@
 		type.sourceEnd());
 }
 public void illegalModifierForInterfaceField(ReferenceBinding type, FieldDeclaration fieldDecl) {
-	String[] arguments = new String[] {fieldDecl.name()};
+	String[] arguments = new String[] {new String(fieldDecl.name)};
 	this.handle(
 		IProblem.IllegalModifierForInterfaceField,
 		arguments,
@@ -1209,7 +1241,7 @@
 		methodDecl.sourceEnd);
 }
 public void illegalModifierForVariable(LocalDeclaration localDecl, boolean complainAsArgument) {
-	String[] arguments = new String[] {localDecl.name()};
+	String[] arguments = new String[] {new String(localDecl.name)};
 	this.handle(
 		complainAsArgument
 			? IProblem.IllegalModifierForArgument
@@ -1219,7 +1251,7 @@
 		localDecl.sourceStart,
 		localDecl.sourceEnd);
 }
-public void illegalPrimitiveOrArrayTypeForEnclosingInstance(TypeBinding enclosingType, AstNode location) {
+public void illegalPrimitiveOrArrayTypeForEnclosingInstance(TypeBinding enclosingType, ASTNode location) {
 	this.handle(
 		IProblem.IllegalPrimitiveOrArrayTypeForEnclosingInstance,
 		new String[] {new String(enclosingType.readableName())},
@@ -1237,7 +1269,7 @@
 		type.sourceEnd());
 }
 public void illegalVisibilityModifierCombinationForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
-	String[] arguments = new String[] {new String(fieldDecl.name())};
+	String[] arguments = new String[] {new String(fieldDecl.name)};
 	this.handle(
 		IProblem.IllegalVisibilityModifierCombinationForField,
 		arguments,
@@ -1272,7 +1304,7 @@
 		type.sourceStart(),
 		type.sourceEnd());
 }
-public void illegalVoidExpression(AstNode location) {
+public void illegalVoidExpression(ASTNode location) {
 	this.handle(
 		IProblem.InvalidVoidExpression,
 		NoArgument,
@@ -1304,14 +1336,11 @@
 			needImplementation(); // want to fail to see why we were here...
 			return;
 	}
-	String argument;
-	if(expectedImport instanceof ProblemReferenceBinding) {
-		argument = CharOperation.toString(((ProblemReferenceBinding)expectedImport).compoundName);
-	} else {
-		argument = CharOperation.toString(importRef.tokens);
-	}
-	String[] arguments = new String[]{argument};
-	this.handle(id, arguments, arguments, importRef.sourceStart, importRef.sourceEnd);
+	char[][] tokens = expectedImport instanceof ProblemReferenceBinding
+		? ((ProblemReferenceBinding) expectedImport).compoundName
+		: importRef.tokens;
+	String[] arguments = new String[]{CharOperation.toString(tokens)};
+	this.handle(id, arguments, arguments, importRef.sourceStart, (int) importRef.sourcePositions[tokens.length - 1]);
 }
 public void incompatibleExceptionInThrowsClause(SourceTypeBinding type, MethodBinding currentMethod, MethodBinding inheritedMethod, ReferenceBinding exceptionType) {
 	if (type == currentMethod.declaringClass) {
@@ -1409,6 +1438,30 @@
 		expression.dimensions[index + 1].sourceStart,
 		expression.dimensions[index + 1].sourceEnd);
 }
+public void indirectAccessToStaticField(ASTNode location, FieldBinding field){
+	this.handle(
+		IProblem.IndirectAccessToStaticField,
+		new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
+		new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
+		location.sourceStart,
+		fieldLocation(field, location));
+}
+public void indirectAccessToStaticMethod(ASTNode location, MethodBinding method) {
+	this.handle(
+		IProblem.IndirectAccessToStaticMethod,
+		new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
+		new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+		location.sourceStart,
+		location.sourceEnd);
+}
+public void indirectAccessToStaticType(ASTNode location, ReferenceBinding type) {
+	this.handle(
+		IProblem.IndirectAccessToStaticMethod,
+		new String[] {new String(type.enclosingType().readableName()), new String(type.sourceName) },
+		new String[] {new String(type.enclosingType().shortReadableName()), new String(type.sourceName) },
+		location.sourceStart,
+		location.sourceEnd);
+}
 public void incorrectSwitchType(Expression expression, TypeBinding testType) {
 	this.handle(
 		IProblem.IncorrectSwitchType,
@@ -1432,7 +1485,7 @@
 		// The inherited method %1 cannot hide the public abstract method in %2
 		IProblem.InheritedMethodReducesVisibility,
 		new String[] {
-			new String(concreteSignature.toString()),
+			concreteSignature.toString(),
 			new String(abstractMethods[0].declaringClass.readableName())},
 		new String[] {
 			new String(shortSignature.toString()),
@@ -1475,7 +1528,7 @@
 		fieldDecl.sourceStart,
 		fieldDecl.sourceEnd);
 }
-public void innerTypesCannotDeclareStaticInitializers(ReferenceBinding innerType, AstNode location) {
+public void innerTypesCannotDeclareStaticInitializers(ReferenceBinding innerType, ASTNode location) {
 	this.handle(
 		IProblem.CannotDefineStaticInitializerInLocalType,
 		new String[] {new String(innerType.readableName())},
@@ -1503,7 +1556,7 @@
 		fieldDecl.sourceStart,
 		fieldDecl.sourceEnd);
 }
-public void invalidBreak(AstNode location) {
+public void invalidBreak(ASTNode location) {
 	this.handle(
 		IProblem.InvalidBreak,
 		NoArgument,
@@ -1514,39 +1567,39 @@
 public void invalidConstructor(Statement statement, MethodBinding targetConstructor) {
 
 	boolean insideDefaultConstructor = 
-		(referenceContext instanceof ConstructorDeclaration)
-			&& ((ConstructorDeclaration)referenceContext).isDefaultConstructor();
+		(this.referenceContext instanceof ConstructorDeclaration)
+			&& ((ConstructorDeclaration)this.referenceContext).isDefaultConstructor();
 	boolean insideImplicitConstructorCall =
 		(statement instanceof ExplicitConstructorCall)
 			&& (((ExplicitConstructorCall) statement).accessMode == ExplicitConstructorCall.ImplicitSuper);
 
-	int flag = IProblem.UndefinedConstructor; //default...
+	int id = IProblem.UndefinedConstructor; //default...
 	switch (targetConstructor.problemId()) {
 		case NotFound :
 			if (insideDefaultConstructor){
-				flag = IProblem.UndefinedConstructorInDefaultConstructor;
+				id = IProblem.UndefinedConstructorInDefaultConstructor;
 			} else if (insideImplicitConstructorCall){
-				flag = IProblem.UndefinedConstructorInImplicitConstructorCall;
+				id = IProblem.UndefinedConstructorInImplicitConstructorCall;
 			} else {
-				flag = IProblem.UndefinedConstructor;
+				id = IProblem.UndefinedConstructor;
 			}
 			break;
 		case NotVisible :
 			if (insideDefaultConstructor){
-				flag = IProblem.NotVisibleConstructorInDefaultConstructor;
+				id = IProblem.NotVisibleConstructorInDefaultConstructor;
 			} else if (insideImplicitConstructorCall){
-				flag = IProblem.NotVisibleConstructorInImplicitConstructorCall;
+				id = IProblem.NotVisibleConstructorInImplicitConstructorCall;
 			} else {
-				flag = IProblem.NotVisibleConstructor;
+				id = IProblem.NotVisibleConstructor;
 			}
 			break;
 		case Ambiguous :
 			if (insideDefaultConstructor){
-				flag = IProblem.AmbiguousConstructorInDefaultConstructor;
+				id = IProblem.AmbiguousConstructorInDefaultConstructor;
 			} else if (insideImplicitConstructorCall){
-				flag = IProblem.AmbiguousConstructorInImplicitConstructorCall;
+				id = IProblem.AmbiguousConstructorInImplicitConstructorCall;
 			} else {
-				flag = IProblem.AmbiguousConstructor;
+				id = IProblem.AmbiguousConstructor;
 			}
 			break;
 		case NoError : // 0
@@ -1555,15 +1608,24 @@
 			break;
 	}
 
-	
 	this.handle(
-		flag,
+		id,
 		new String[] {new String(targetConstructor.declaringClass.readableName()), parametersAsString(targetConstructor)},
 		new String[] {new String(targetConstructor.declaringClass.shortReadableName()), parametersAsShortString(targetConstructor)},
 		statement.sourceStart,
 		statement.sourceEnd);
 }
-public void invalidContinue(AstNode location) {
+
+public void invalidExplicitConstructorCall(ASTNode location) {
+	
+	this.handle(
+		IProblem.InvalidExplicitConstructorCall,
+		NoArgument,
+		NoArgument,
+		location.sourceStart,
+		location.sourceEnd);
+}
+public void invalidContinue(ASTNode location) {
 	this.handle(
 		IProblem.InvalidContinue,
 		NoArgument,
@@ -1610,35 +1672,34 @@
 		expression.sourceEnd);
 }
 public void invalidField(FieldReference fieldRef, TypeBinding searchedType) {
-	int severity = Error;
-	int flag = IProblem.UndefinedField;
+	int id = IProblem.UndefinedField;
 	FieldBinding field = fieldRef.binding;
 	switch (field.problemId()) {
 		case NotFound :
-			flag = IProblem.UndefinedField;
+			id = IProblem.UndefinedField;
 /* also need to check that the searchedType is the receiver type
 			if (searchedType.isHierarchyInconsistent())
 				severity = SecondaryError;
 */
 			break;
 		case NotVisible :
-			flag = IProblem.NotVisibleField;
+			id = IProblem.NotVisibleField;
 			break;
 		case Ambiguous :
-			flag = IProblem.AmbiguousField;
+			id = IProblem.AmbiguousField;
 			break;
 		case NonStaticReferenceInStaticContext :
-			flag = IProblem.NonStaticFieldFromStaticInvocation;
+			id = IProblem.NonStaticFieldFromStaticInvocation;
 			break;
 		case NonStaticReferenceInConstructorInvocation :
-			flag = IProblem.InstanceFieldDuringConstructorInvocation;
+			id = IProblem.InstanceFieldDuringConstructorInvocation;
 			break;
 		case InheritedNameHidesEnclosingName :
-			flag = IProblem.InheritedFieldHidesEnclosingName;
+			id = IProblem.InheritedFieldHidesEnclosingName;
 			break;
 		case ReceiverTypeNotVisible :
 			this.handle(
-				IProblem.NotVisibleType,
+				IProblem.NotVisibleType, // cannot occur in javadoc comments
 				new String[] {new String(searchedType.leafComponentType().readableName())},
 				new String[] {new String(searchedType.leafComponentType().shortReadableName())},
 				fieldRef.receiver.sourceStart,
@@ -1653,33 +1714,32 @@
 
 	String[] arguments = new String[] {new String(field.readableName())};
 	this.handle(
-		flag,
+		id,
 		arguments,
 		arguments,
-		severity,
 		fieldRef.sourceStart,
 		fieldRef.sourceEnd);
 }
 public void invalidField(NameReference nameRef, FieldBinding field) {
-	int flag = IProblem.UndefinedField;
+	int id = IProblem.UndefinedField;
 	switch (field.problemId()) {
 		case NotFound :
-			flag = IProblem.UndefinedField;
+			id = IProblem.UndefinedField;
 			break;
 		case NotVisible :
-			flag = IProblem.NotVisibleField;
+			id = IProblem.NotVisibleField;
 			break;
 		case Ambiguous :
-			flag = IProblem.AmbiguousField;
+			id = IProblem.AmbiguousField;
 			break;
 		case NonStaticReferenceInStaticContext :
-			flag = IProblem.NonStaticFieldFromStaticInvocation;
+			id = IProblem.NonStaticFieldFromStaticInvocation;
 			break;
 		case NonStaticReferenceInConstructorInvocation :
-			flag = IProblem.InstanceFieldDuringConstructorInvocation;
+			id = IProblem.InstanceFieldDuringConstructorInvocation;
 			break;
 		case InheritedNameHidesEnclosingName :
-			flag = IProblem.InheritedFieldHidesEnclosingName;
+			id = IProblem.InheritedFieldHidesEnclosingName;
 			break;
 		case ReceiverTypeNotVisible :
 			this.handle(
@@ -1696,7 +1756,7 @@
 	}
 	String[] arguments = new String[] {new String(field.readableName())};
 	this.handle(
-		flag,
+		id,
 		arguments,
 		arguments,
 		nameRef.sourceStart,
@@ -1723,33 +1783,33 @@
 				CharOperation.toString(CharOperation.subarray(nameRef.tokens, 0, index)),
 				new String(nameRef.tokens[index])},
 			nameRef.sourceStart,
-			nameRef.sourceEnd);
+			(int) nameRef.sourcePositions[index]);
 		return;
 	}
 
-	int flag = IProblem.UndefinedField;
+	int id = IProblem.UndefinedField;
 	switch (field.problemId()) {
 		case NotFound :
-			flag = IProblem.UndefinedField;
+			id = IProblem.UndefinedField;
 /* also need to check that the searchedType is the receiver type
 			if (searchedType.isHierarchyInconsistent())
 				severity = SecondaryError;
 */
 			break;
 		case NotVisible :
-			flag = IProblem.NotVisibleField;
+			id = IProblem.NotVisibleField;
 			break;
 		case Ambiguous :
-			flag = IProblem.AmbiguousField;
+			id = IProblem.AmbiguousField;
 			break;
 		case NonStaticReferenceInStaticContext :
-			flag = IProblem.NonStaticFieldFromStaticInvocation;
+			id = IProblem.NonStaticFieldFromStaticInvocation;
 			break;
 		case NonStaticReferenceInConstructorInvocation :
-			flag = IProblem.InstanceFieldDuringConstructorInvocation;
+			id = IProblem.InstanceFieldDuringConstructorInvocation;
 			break;
 		case InheritedNameHidesEnclosingName :
-			flag = IProblem.InheritedFieldHidesEnclosingName;
+			id = IProblem.InheritedFieldHidesEnclosingName;
 			break;
 		case ReceiverTypeNotVisible :
 			this.handle(
@@ -1766,11 +1826,11 @@
 	}
 	String[] arguments = new String[] {CharOperation.toString(CharOperation.subarray(nameRef.tokens, 0, index + 1))};
 	this.handle(
-		flag, 
+		id, 
 		arguments,
 		arguments,
 		nameRef.sourceStart, 
-		nameRef.sourceEnd); 
+		(int) nameRef.sourcePositions[index]);
 }
 public void invalidMethod(MessageSend messageSend, MethodBinding method) {
 	// CODE should be UPDATED according to error coding in the different method binding errors
@@ -1782,29 +1842,29 @@
 	//	InstanceMethodDuringConstructorInvocation
 	// StaticMethodRequested
 
-	int flag = IProblem.UndefinedMethod; //default...
+	int id = IProblem.UndefinedMethod; //default...
 	switch (method.problemId()) {
 		case NotFound :
-			flag = IProblem.UndefinedMethod;
+			id = IProblem.UndefinedMethod;
 			break;
 		case NotVisible :
-			flag = IProblem.NotVisibleMethod;
+			id = IProblem.NotVisibleMethod;
 			break;
 		case Ambiguous :
-			flag = IProblem.AmbiguousMethod;
+			id = IProblem.AmbiguousMethod;
 			break;
 		case InheritedNameHidesEnclosingName :
-			flag = IProblem.InheritedMethodHidesEnclosingName;
+			id = IProblem.InheritedMethodHidesEnclosingName;
 			break;
 		case NonStaticReferenceInConstructorInvocation :
-			flag = IProblem.InstanceMethodDuringConstructorInvocation;
+			id = IProblem.InstanceMethodDuringConstructorInvocation;
 			break;
 		case NonStaticReferenceInStaticContext :
-			flag = IProblem.StaticMethodRequested;
+			id = IProblem.StaticMethodRequested;
 			break;
 		case ReceiverTypeNotVisible :
 			this.handle(
-				IProblem.NotVisibleType,
+				IProblem.NotVisibleType,	// cannot occur in javadoc comments
 				new String[] {new String(method.declaringClass.leafComponentType().readableName())},
 				new String[] {new String(method.declaringClass.leafComponentType().shortReadableName())},
 				messageSend.receiver.sourceStart,
@@ -1817,7 +1877,7 @@
 			break;
 	}
 
-	if (flag == IProblem.UndefinedMethod) {
+	if (id == IProblem.UndefinedMethod) {
 		ProblemMethodBinding problemMethod = (ProblemMethodBinding) method;
 		if (problemMethod.closestMatch != null) {
 				String closestParameterTypeNames = parametersAsString(problemMethod.closestMatch);
@@ -1828,8 +1888,9 @@
 					closestParameterTypeShortNames = closestParameterTypeNames;
 					parameterTypeShortNames = parameterTypeNames;
 				}
+				id = IProblem.ParameterMismatch;
 				this.handle(
-					IProblem.ParameterMismatch,
+					id,
 					new String[] {
 						new String(problemMethod.closestMatch.declaringClass.readableName()),
 						new String(problemMethod.closestMatch.selector),
@@ -1849,7 +1910,7 @@
 	}
 
 	this.handle(
-		flag,
+		id,
 		new String[] {
 			new String(method.declaringClass.readableName()),
 			new String(method.selector), parametersAsString(method)},
@@ -1915,7 +1976,7 @@
 		expression.sourceStart,
 		expression.sourceEnd);
 }
-public void invalidParenthesizedExpression(AstNode reference) {
+public void invalidParenthesizedExpression(ASTNode reference) {
 	this.handle(
 		IProblem.InvalidParenthesizedExpression,
 		NoArgument,
@@ -1985,36 +2046,42 @@
 			superinterfaceRef.sourceStart,
 			superinterfaceRef.sourceEnd);
 }
-public void invalidType(AstNode location, TypeBinding type) {
-	int flag = IProblem.UndefinedType; // default
+public void invalidType(ASTNode location, TypeBinding type) {
+	int id = IProblem.UndefinedType; // default
 	switch (type.problemId()) {
 		case NotFound :
-			flag = IProblem.UndefinedType;
+			id = IProblem.UndefinedType;
 			break;
 		case NotVisible :
-			flag = IProblem.NotVisibleType;
+			id = IProblem.NotVisibleType;
 			break;
 		case Ambiguous :
-			flag = IProblem.AmbiguousType;
+			id = IProblem.AmbiguousType;
 			break;
 		case InternalNameProvided :
-			flag = IProblem.InternalTypeNameProvided;
+			id = IProblem.InternalTypeNameProvided;
 			break;
 		case InheritedNameHidesEnclosingName :
-			flag = IProblem.InheritedTypeHidesEnclosingName;
+			id = IProblem.InheritedTypeHidesEnclosingName;
 			break;
 		case NoError : // 0
 		default :
 			needImplementation(); // want to fail to see why we were here...
 			break;
 	}
-
+	
+	int end = location.sourceEnd;
+	if (location instanceof QualifiedNameReference) {
+		QualifiedNameReference ref = (QualifiedNameReference) location;
+		if (ref.indexOfFirstFieldBinding >= 1)
+			end = (int) ref.sourcePositions[ref.indexOfFirstFieldBinding - 1];
+	}
 	this.handle(
-		flag,
+		id,
 		new String[] {new String(type.readableName())},
 		new String[] {new String(type.shortReadableName())},
 		location.sourceStart,
-		location.sourceEnd);
+		end);
 }
 public void invalidTypeReference(Expression expression) {
 	this.handle(
@@ -2041,7 +2108,7 @@
 		expression.sourceEnd);
 }
 public void isClassPathCorrect(char[][] wellKnownTypeName, CompilationUnitDeclaration compUnitDecl) {
-	referenceContext = compUnitDecl;
+	this.referenceContext = compUnitDecl;
 	String[] arguments = new String[] {CharOperation.toString(wellKnownTypeName)};
 	this.handle(
 		IProblem.IsClassPathCorrect,
@@ -2051,13 +2118,389 @@
 		compUnitDecl == null ? 0 : compUnitDecl.sourceStart,
 		compUnitDecl == null ? 1 : compUnitDecl.sourceEnd);
 }
-public void maskedExceptionHandler(ReferenceBinding exceptionType, AstNode location) {
+public void javadocDuplicatedReturnTag(int sourceStart, int sourceEnd){
+	this.handle(IProblem.JavadocDuplicateReturnTag, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocDeprecatedField(FieldBinding field, ASTNode location, int modifiers) {
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		this.handle(
+			IProblem.UsingDeprecatedField|IProblem.Javadoc,
+			new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
+			new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
+			location.sourceStart,
+			location.sourceEnd);
+	}
+}
+public void javadocDeprecatedMethod(MethodBinding method, ASTNode location, int modifiers) {
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		if (method.isConstructor()) {
+			this.handle(
+				IProblem.UsingDeprecatedConstructor|IProblem.Javadoc,
+				new String[] {new String(method.declaringClass.readableName()), parametersAsString(method)},
+				new String[] {new String(method.declaringClass.shortReadableName()), parametersAsShortString(method)},
+				location.sourceStart,
+				location.sourceEnd);
+		} else {
+			this.handle(
+				IProblem.UsingDeprecatedMethod|IProblem.Javadoc,
+				new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
+				new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+				location.sourceStart,
+				location.sourceEnd);
+		}
+	}
+}
+public void javadocDeprecatedType(TypeBinding type, ASTNode location, int modifiers) {
+	if (location == null) return; // 1G828DN - no type ref for synthetic arguments
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		this.handle(
+			IProblem.UsingDeprecatedType|IProblem.Javadoc,
+			new String[] {new String(type.readableName())},
+			new String[] {new String(type.shortReadableName())},
+			location.sourceStart,
+			location.sourceEnd);
+	}
+}
+public void javadocDuplicatedParamTag(JavadocSingleNameReference param, int modifiers) {
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		String[] arguments = new String[] {String.valueOf(param.token)};
+		this.handle(IProblem.JavadocDuplicateParamName, arguments, arguments, param.sourceStart, param.sourceEnd);
+	}
+}
+public void javadocDuplicatedThrowsClassName(TypeReference typeReference, int modifiers) {
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		String[] arguments = new String[] {String.valueOf(typeReference.resolvedType.sourceName())};
+		this.handle(IProblem.JavadocDuplicateThrowsClassName, arguments, arguments, typeReference.sourceStart, typeReference.sourceEnd);
+	}
+}
+public void javadocErrorNoMethodFor(MessageSend messageSend, TypeBinding recType, TypeBinding[] params, int modifiers) {
+	StringBuffer buffer = new StringBuffer();
+	StringBuffer shortBuffer = new StringBuffer();
+	for (int i = 0, length = params.length; i < length; i++) {
+		if (i != 0){
+			buffer.append(", "); //$NON-NLS-1$
+			shortBuffer.append(", "); //$NON-NLS-1$
+		}
+		buffer.append(new String(params[i].readableName()));
+		shortBuffer.append(new String(params[i].shortReadableName()));
+	}
+
+	int id = recType.isArrayType() ? IProblem.NoMessageSendOnArrayType : IProblem.NoMessageSendOnBaseType;
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		this.handle(
+			id|IProblem.Javadoc,
+			new String[] {new String(recType.readableName()), new String(messageSend.selector), buffer.toString()},
+			new String[] {new String(recType.shortReadableName()), new String(messageSend.selector), shortBuffer.toString()},
+			messageSend.sourceStart,
+			messageSend.sourceEnd);
+	}
+}
+public void javadocInvalidConstructor(Statement statement, MethodBinding targetConstructor, int modifiers) {
+
+	if (!javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		return;
+	}
+	boolean insideDefaultConstructor = 
+		(this.referenceContext instanceof ConstructorDeclaration)
+			&& ((ConstructorDeclaration)this.referenceContext).isDefaultConstructor();
+	boolean insideImplicitConstructorCall =
+		(statement instanceof ExplicitConstructorCall)
+			&& (((ExplicitConstructorCall) statement).accessMode == ExplicitConstructorCall.ImplicitSuper);
+
+	int id = IProblem.UndefinedConstructor; //default...
+	switch (targetConstructor.problemId()) {
+		case NotFound :
+			if (insideDefaultConstructor){
+				id = IProblem.UndefinedConstructorInDefaultConstructor;
+			} else if (insideImplicitConstructorCall){
+				id = IProblem.UndefinedConstructorInImplicitConstructorCall;
+			} else {
+				id = IProblem.UndefinedConstructor;
+			}
+			break;
+		case NotVisible :
+			if (insideDefaultConstructor){
+				id = IProblem.NotVisibleConstructorInDefaultConstructor;
+			} else if (insideImplicitConstructorCall){
+				id = IProblem.NotVisibleConstructorInImplicitConstructorCall;
+			} else {
+				id = IProblem.NotVisibleConstructor;
+			}
+			break;
+		case Ambiguous :
+			if (insideDefaultConstructor){
+				id = IProblem.AmbiguousConstructorInDefaultConstructor;
+			} else if (insideImplicitConstructorCall){
+				id = IProblem.AmbiguousConstructorInImplicitConstructorCall;
+			} else {
+				id = IProblem.AmbiguousConstructor;
+			}
+			break;
+		case NoError : // 0
+		default :
+			needImplementation(); // want to fail to see why we were here...
+			break;
+	}
+
 	this.handle(
-		IProblem.MaskedCatch,
-		NoArgument,
-		NoArgument,
-		location.sourceStart,
-		location.sourceEnd);
+		id|IProblem.Javadoc,
+		new String[] {new String(targetConstructor.declaringClass.readableName()), parametersAsString(targetConstructor)},
+		new String[] {new String(targetConstructor.declaringClass.shortReadableName()), parametersAsShortString(targetConstructor)},
+		statement.sourceStart,
+		statement.sourceEnd);
+}
+public void javadocInvalidField(FieldReference fieldRef, TypeBinding searchedType, int modifiers) {
+	int id = IProblem.UndefinedField;
+	FieldBinding field = fieldRef.binding;
+	switch (field.problemId()) {
+		case NotFound :
+			id = IProblem.UndefinedField;
+			break;
+		case NotVisible :
+			id = IProblem.NotVisibleField;
+			break;
+		case Ambiguous :
+			id = IProblem.AmbiguousField;
+			break;
+		case NoError : // 0
+		default :
+			needImplementation(); // want to fail to see why we were here...
+			break;
+	}
+
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		String[] arguments = new String[] {new String(field.readableName())};
+		handle(id|IProblem.Javadoc, arguments, arguments, fieldRef.sourceStart, fieldRef.sourceEnd);
+	}
+}
+public void javadocInvalidMethod(MessageSend messageSend, MethodBinding method, int modifiers) {
+	if (!javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		return;
+	}
+	int id = IProblem.UndefinedMethod; //default...
+	switch (method.problemId()) {
+		case NotFound :
+			id = IProblem.UndefinedMethod;
+			break;
+		case NotVisible :
+			id = IProblem.NotVisibleMethod;
+			break;
+		case Ambiguous :
+			id = IProblem.AmbiguousMethod;
+			break;
+		case NoError : // 0
+		default :
+			needImplementation(); // want to fail to see why we were here...
+			break;
+	}
+
+	if (id == IProblem.UndefinedMethod) {
+		ProblemMethodBinding problemMethod = (ProblemMethodBinding) method;
+		if (problemMethod.closestMatch != null) {
+				String closestParameterTypeNames = parametersAsString(problemMethod.closestMatch);
+				String parameterTypeNames = parametersAsString(method);
+				String closestParameterTypeShortNames = parametersAsShortString(problemMethod.closestMatch);
+				String parameterTypeShortNames = parametersAsShortString(method);
+				if (closestParameterTypeShortNames.equals(parameterTypeShortNames)){
+					closestParameterTypeShortNames = closestParameterTypeNames;
+					parameterTypeShortNames = parameterTypeNames;
+				}
+				this.handle(
+					IProblem.ParameterMismatch|IProblem.Javadoc,
+					new String[] {
+						new String(problemMethod.closestMatch.declaringClass.readableName()),
+						new String(problemMethod.closestMatch.selector),
+						closestParameterTypeNames,
+						parameterTypeNames 
+					},
+					new String[] {
+						new String(problemMethod.closestMatch.declaringClass.shortReadableName()),
+						new String(problemMethod.closestMatch.selector),
+						closestParameterTypeShortNames,
+						parameterTypeShortNames
+					},
+					(int) (messageSend.nameSourcePosition >>> 32),
+					(int) messageSend.nameSourcePosition);
+				return;
+		}
+	}
+
+	this.handle(
+		id|IProblem.Javadoc,
+		new String[] {
+			new String(method.declaringClass.readableName()),
+			new String(method.selector), parametersAsString(method)},
+		new String[] {
+			new String(method.declaringClass.shortReadableName()),
+			new String(method.selector), parametersAsShortString(method)},
+		(int) (messageSend.nameSourcePosition >>> 32),
+		(int) messageSend.nameSourcePosition);
+}
+public void javadocInvalidParamName(JavadocSingleNameReference param, int modifiers) {
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		String[] arguments = new String[] {String.valueOf(param.token)};
+		this.handle(IProblem.JavadocInvalidParamName, arguments, arguments, param.sourceStart, param.sourceEnd);
+	}
+}
+public void javadocInvalidSeeReference(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidSeeReference, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidSeeReferenceArgs(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidSeeArgs, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidSeeUrlReference(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidSeeHref, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidThrowsClass(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocInvalidThrowsClass, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidThrowsClassName(TypeReference typeReference, int modifiers) {
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		String[] arguments = new String[] {String.valueOf(typeReference.resolvedType.sourceName())};
+		this.handle(IProblem.JavadocInvalidThrowsClassName, arguments, arguments, typeReference.sourceStart, typeReference.sourceEnd);
+	}
+}
+public void javadocInvalidType(ASTNode location, TypeBinding type, int modifiers) {
+	if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+		int id = IProblem.UndefinedType; // default
+		switch (type.problemId()) {
+			case NotFound :
+				id = IProblem.UndefinedType;
+				break;
+			case NotVisible :
+				id = IProblem.NotVisibleType;
+				break;
+			case Ambiguous :
+				id = IProblem.AmbiguousType;
+				break;
+			case InternalNameProvided :
+				id = IProblem.InternalTypeNameProvided;
+				break;
+			case NoError : // 0
+			default :
+				needImplementation(); // want to fail to see why we were here...
+				break;
+		}
+		this.handle(
+			id|IProblem.Javadoc,
+			new String[] {new String(type.readableName())},
+			new String[] {new String(type.shortReadableName())},
+			location.sourceStart,
+			location.sourceEnd);
+	}
+}
+public void javadocMissing(int sourceStart, int sourceEnd, int modifiers){
+	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+	boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocComments) != ProblemSeverities.Ignore)
+					&& (!overriding || this.options.reportMissingJavadocCommentsOverriding);
+	if (report) {
+		String arg = javadocVisibilityArgument(this.options.reportMissingJavadocCommentsVisibility, modifiers);
+		if (arg != null) {
+			String[] arguments = new String[] { arg };
+			this.handle(IProblem.JavadocMissing, arguments, arguments, sourceStart, sourceEnd);
+		}
+	}
+}
+public void javadocMissingParamName(int sourceStart, int sourceEnd){
+	this.handle(IProblem.JavadocMissingParamName, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocMissingParamTag(Argument param, int modifiers) {
+	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+	boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore)
+					&& (!overriding || this.options.reportMissingJavadocTagsOverriding);
+	if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) {
+		String[] arguments = new String[] { String.valueOf(param.name) };
+		this.handle(IProblem.JavadocMissingParamTag, arguments, arguments, param.sourceStart, param.sourceEnd);
+	}
+}
+public void javadocMissingReturnTag(int sourceStart, int sourceEnd, int modifiers){
+	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+	boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore)
+					&& (!overriding || this.options.reportMissingJavadocTagsOverriding);
+	if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) {
+		this.handle(IProblem.JavadocMissingReturnTag, NoArgument, NoArgument, sourceStart, sourceEnd);
+	}
+}
+public void javadocMissingSeeReference(int sourceStart, int sourceEnd){
+	this.handle(IProblem.JavadocMissingSeeReference, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocMissingThrowsClassName(int sourceStart, int sourceEnd){
+	this.handle(IProblem.JavadocMissingThrowsClassName, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocMissingThrowsTag(TypeReference typeRef, int modifiers){
+	boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+	boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore)
+					&& (!overriding || this.options.reportMissingJavadocTagsOverriding);
+	if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) {
+		String[] arguments = new String[] { String.valueOf(typeRef.resolvedType.sourceName()) };
+		this.handle(IProblem.JavadocMissingThrowsTag, arguments, arguments, typeRef.sourceStart, typeRef.sourceEnd);
+	}
+}
+public void javadocUnexpectedTag(int sourceStart, int sourceEnd) {
+	this.handle(IProblem.JavadocUnexpectedTag, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+private boolean javadocVisibility(int visibility, int modifiers) {
+	switch (modifiers & CompilerModifiers.AccVisibilityMASK) {
+		case IConstants.AccPublic :
+			return true;
+		case IConstants.AccProtected:
+			return (visibility != IConstants.AccPublic);
+		case IConstants.AccDefault:
+			return (visibility == IConstants.AccDefault || visibility == IConstants.AccPrivate);
+		case IConstants.AccPrivate:
+			return (visibility == IConstants.AccPrivate);
+	}
+	return true;
+}
+private String javadocVisibilityArgument(int visibility, int modifiers) {
+	String argument = null;
+	switch (modifiers & CompilerModifiers.AccVisibilityMASK) {
+		case IConstants.AccPublic :
+			argument = CompilerOptions.PUBLIC;
+			break;
+		case IConstants.AccProtected:
+			if (visibility != IConstants.AccPublic) {
+				argument = CompilerOptions.PROTECTED;
+			}
+			break;
+		case IConstants.AccDefault:
+			if (visibility == IConstants.AccDefault || visibility == IConstants.AccPrivate) {
+				argument = CompilerOptions.DEFAULT;
+			}
+			break;
+		case IConstants.AccPrivate:
+			if (visibility == IConstants.AccPrivate) {
+				argument = CompilerOptions.PRIVATE;
+			}
+			break;
+	}
+	return argument;
+}
+public void localVariableHiding(LocalDeclaration local, Binding hiddenVariable, boolean  isSpecialArgHidingField) {
+	if (hiddenVariable instanceof LocalVariableBinding) {
+		String[] arguments = new String[] {new String(local.name)  };
+		this.handle(
+			(local instanceof Argument) 
+				? IProblem.ArgumentHidingLocalVariable 
+				: IProblem.LocalVariableHidingLocalVariable,
+			arguments,
+			arguments,
+			local.sourceStart,
+			local.sourceEnd);
+	} else if (hiddenVariable instanceof FieldBinding) {
+		if (isSpecialArgHidingField && !this.options.reportSpecialParameterHidingField){
+			return;
+		}
+		FieldBinding field = (FieldBinding) hiddenVariable;
+		this.handle(
+			(local instanceof Argument)
+				? IProblem.ArgumentHidingField
+				: IProblem.LocalVariableHidingField,
+			new String[] {new String(local.name) , new String(field.declaringClass.readableName()) },
+			new String[] {new String(local.name), new String(field.declaringClass.shortReadableName()) },
+			local.sourceStart,
+			local.sourceEnd);
+	}
 }
 public void methodNeedingAbstractModifier(MethodDeclaration methodDecl) {
 	this.handle(
@@ -2069,7 +2512,7 @@
 }
 public void methodNeedingNoBody(MethodDeclaration methodDecl) {
 	this.handle(
-		((methodDecl.modifiers & CompilerModifiers.AccNative) != 0) ? IProblem.BodyForNativeMethod : IProblem.BodyForAbstractMethod,
+		((methodDecl.modifiers & IConstants.AccNative) != 0) ? IProblem.BodyForNativeMethod : IProblem.BodyForAbstractMethod,
 		NoArgument,
 		NoArgument,
 		methodDecl.sourceStart,
@@ -2083,20 +2526,6 @@
 		methodDecl.sourceStart,
 		methodDecl.sourceEnd);
 }
-//public void missingEnclosingInstanceSpecification(ReferenceBinding enclosingType, AstNode location) {
-//	boolean insideConstructorCall =
-//		(location instanceof ExplicitConstructorCall)
-//			&& (((ExplicitConstructorCall) location).accessMode == ExplicitConstructorCall.ImplicitSuper);
-//
-//	this.handle(
-//		insideConstructorCall
-//			? IProblem.MissingEnclosingInstanceForConstructorCall
-//			: IProblem.MissingEnclosingInstance,
-//		new String[] {new String(enclosingType.readableName())},
-//		new String[] {new String(enclosingType.shortReadableName())},
-//		location.sourceStart,
-//		location.sourceEnd);
-//}
 public void missingReturnType(AbstractMethodDeclaration methodDecl) {
 	this.handle(
 		IProblem.MissingReturnType,
@@ -2151,7 +2580,7 @@
 public void needImplementation() {
 	this.abortDueToInternalError(Util.bind("abort.missingCode")); //$NON-NLS-1$
 }
-public void needToEmulateFieldReadAccess(FieldBinding field, AstNode location) {
+public void needToEmulateFieldReadAccess(FieldBinding field, ASTNode location) {
 	this.handle(
 		IProblem.NeedToEmulateFieldReadAccess,
 		new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
@@ -2159,7 +2588,7 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void needToEmulateFieldWriteAccess(FieldBinding field, AstNode location) {
+public void needToEmulateFieldWriteAccess(FieldBinding field, ASTNode location) {
 	this.handle(
 		IProblem.NeedToEmulateFieldWriteAccess,
 		new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
@@ -2169,7 +2598,7 @@
 }
 public void needToEmulateMethodAccess(
 	MethodBinding method, 
-	AstNode location) {
+	ASTNode location) {
 
 	if (method.isConstructor())
 		this.handle(
@@ -2209,7 +2638,7 @@
 		typeDecl.sourceStart,
 		typeDecl.sourceEnd);
 }
-public void noMoreAvailableSpaceForArgument(LocalVariableBinding local, AstNode location) {
+public void noMoreAvailableSpaceForArgument(LocalVariableBinding local, ASTNode location) {
 	String[] arguments = new String[]{ new String(local.name) };
 	this.handle(
 		local instanceof SyntheticArgumentBinding
@@ -2221,7 +2650,7 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void noMoreAvailableSpaceForLocal(LocalVariableBinding local, AstNode location) {
+public void noMoreAvailableSpaceForLocal(LocalVariableBinding local, ASTNode location) {
 	String[] arguments = new String[]{ new String(local.name) };
 	this.handle(
 		IProblem.TooManyLocalVariableSlots,
@@ -2231,7 +2660,23 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void noSuchEnclosingInstance(TypeBinding targetType, AstNode location, boolean isConstructorCall) {
+public void nonStaticAccessToStaticMethod(ASTNode location, MethodBinding method) {
+	this.handle(
+		IProblem.NonStaticAccessToStaticMethod,
+		new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
+		new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+		location.sourceStart,
+		location.sourceEnd);
+}
+public void nonStaticAccessToStaticField(ASTNode location, FieldBinding field) {
+	this.handle(
+		IProblem.NonStaticAccessToStaticField,
+		new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
+		new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
+		location.sourceStart,
+		fieldLocation(field, location));
+}
+public void noSuchEnclosingInstance(TypeBinding targetType, ASTNode location, boolean isConstructorCall) {
 
 	int id;
 
@@ -2397,12 +2842,13 @@
 public void parseError(
 	int startPosition, 
 	int endPosition, 
+	int currentToken,
 	char[] currentTokenSource, 
 	String errorTokenName, 
 	String[] possibleTokens) {
 		
 	if (possibleTokens.length == 0) { //no suggestion available
-		if (isKeyword(currentTokenSource)) {
+		if (isKeyword(currentToken)) {
 			String[] arguments = new String[] {new String(currentTokenSource)};
 			this.handle(
 				IProblem.ParsingErrorOnKeywordNoSuggestion,
@@ -2435,7 +2881,7 @@
 		list.append('"');
 	}
 
-	if (isKeyword(currentTokenSource)) {
+	if (isKeyword(currentToken)) {
 		String[] arguments = new String[] {new String(currentTokenSource), list.toString()};
 		this.handle(
 			IProblem.ParsingErrorOnKeyword,
@@ -2447,13 +2893,8 @@
 		return;
 	}
 	//extract the literal when it's a literal  
-	if ((errorTokenName.equals("IntegerLiteral")) || //$NON-NLS-1$
-		(errorTokenName.equals("LongLiteral")) || //$NON-NLS-1$
-		(errorTokenName.equals("FloatingPointLiteral")) || //$NON-NLS-1$
-		(errorTokenName.equals("DoubleLiteral")) || //$NON-NLS-1$
-		(errorTokenName.equals("StringLiteral")) || //$NON-NLS-1$
-		(errorTokenName.equals("CharacterLiteral")) || //$NON-NLS-1$
-		(errorTokenName.equals("Identifier"))) { //$NON-NLS-1$
+	if (isLiteral(currentToken) ||
+		isIdentifier(currentToken)) { //$NON-NLS-1$
 			errorTokenName = new String(currentTokenSource);
 	}
 
@@ -2466,6 +2907,15 @@
 		startPosition,
 		endPosition);
 }
+public void possibleAccidentalBooleanAssignment(Assignment assignment) {
+	String[] arguments = new String[] {};
+	this.handle(
+		IProblem.PossibleAccidentalBooleanAssignment,
+		arguments,
+		arguments,
+		assignment.sourceStart,
+		assignment.sourceEnd);
+}
 public void publicClassMustMatchFileName(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) {
 	this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit
 	String[] arguments = new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)};
@@ -2617,7 +3067,7 @@
 		scanner.currentPosition - 1,
 		parser.compilationUnit.compilationResult);
 }
-public void shouldReturn(TypeBinding returnType, AstNode location) {
+public void shouldReturn(TypeBinding returnType, ASTNode location) {
 	this.handle(
 		IProblem.ShouldReturnValue,
 		new String[] { new String (returnType.readableName())},
@@ -2653,32 +3103,14 @@
 			currentMethod.sourceStart(),
 			currentMethod.sourceEnd());
 }
-public void staticFieldAccessToNonStaticVariable(FieldReference fieldRef, FieldBinding field) {
+public void staticFieldAccessToNonStaticVariable(ASTNode location, FieldBinding field) {
 	String[] arguments = new String[] {new String(field.readableName())};
 	this.handle(
 		IProblem.NonStaticFieldFromStaticInvocation,
 		arguments,
 		arguments,
-		fieldRef.sourceStart,
-		fieldRef.sourceEnd); 
-}
-public void staticFieldAccessToNonStaticVariable(QualifiedNameReference nameRef, FieldBinding field){
-	String[] arguments = new String[] {new String(field.readableName())};
-	this.handle(
-		IProblem.NonStaticFieldFromStaticInvocation,
-		arguments,
-		arguments,
-		nameRef.sourceStart,
-		nameRef.sourceEnd);
-}
-public void staticFieldAccessToNonStaticVariable(SingleNameReference nameRef, FieldBinding field) {
-	String[] arguments = new String[] {new String(field.readableName())};
-	this.handle(
-		IProblem.NonStaticFieldFromStaticInvocation,
-		arguments,
-		arguments,
-		nameRef.sourceStart,
-		nameRef.sourceEnd);
+		location.sourceStart,
+		fieldLocation(field, location)); 
 }
 public void staticInheritedMethodConflicts(SourceTypeBinding type, MethodBinding concreteMethod, MethodBinding[] abstractMethods) {
 	this.handle(
@@ -2694,7 +3126,7 @@
 		type.sourceStart(),
 		type.sourceEnd());
 }
-public void stringConstantIsExceedingUtf8Limit(AstNode location) {
+public void stringConstantIsExceedingUtf8Limit(ASTNode location) {
 	this.handle(
 		IProblem.StringConstantIsExceedingUtf8Limit,
 		NoArgument,
@@ -2710,6 +3142,14 @@
 		superclassRef.sourceStart,
 		superclassRef.sourceEnd);
 }
+public void superfluousSemicolon(int sourceStart, int sourceEnd) {
+	this.handle(
+		IProblem.SuperfluousSemicolon,
+		NoArgument,
+		NoArgument,
+		sourceStart,
+		sourceEnd);	
+}
 public void superinterfaceMustBeAnInterface(SourceTypeBinding type, TypeDeclaration typeDecl, ReferenceBinding superType) {
 	this.handle(
 		IProblem.SuperInterfaceMustBeAnInterface,
@@ -2726,7 +3166,7 @@
 		start,
 		end);
 }
-public void tooManyDimensions(AstNode expression) {
+public void tooManyDimensions(ASTNode expression) {
 	this.handle(
 		IProblem.TooManyArrayDimensions,
 		NoArgument,
@@ -2779,7 +3219,7 @@
 		typeDecl.sourceEnd,
 		compUnitDecl.compilationResult);
 }
-public void typeMismatchError(TypeBinding resultType, TypeBinding expectedType, AstNode location) {
+public void typeMismatchError(TypeBinding resultType, TypeBinding expectedType, ASTNode location) {
 	String resultTypeName = new String(resultType.readableName());
 	String expectedTypeName = new String(expectedType.readableName());
 	String resultTypeShortName = new String(resultType.shortReadableName());
@@ -2820,8 +3260,17 @@
 		statement.sourceStart,
 		statement.sourceEnd);
 }
+public void undocumentedEmptyBlock(int blockStart, int blockEnd) {
+	String[] arguments = new String[] {};
+	this.handle(
+		IProblem.UndocumentedEmptyBlock,
+		arguments,
+		arguments,
+		blockStart,
+		blockEnd);
+}
 public void unexpectedStaticModifierForField(SourceTypeBinding type, FieldDeclaration fieldDecl) {
-	String[] arguments = new String[] {fieldDecl.name()};
+	String[] arguments = new String[] {new String(fieldDecl.name)};
 	this.handle(
 		IProblem.UnexpectedStaticModifierForField,
 		arguments,
@@ -2838,11 +3287,11 @@
 		methodDecl.sourceStart,
 		methodDecl.sourceEnd);
 }
-public void unhandledException(TypeBinding exceptionType, AstNode location) {
+public void unhandledException(TypeBinding exceptionType, ASTNode location) {
 
 	boolean insideDefaultConstructor = 
-		(referenceContext instanceof ConstructorDeclaration)
-			&& ((ConstructorDeclaration)referenceContext).isDefaultConstructor();
+		(this.referenceContext instanceof ConstructorDeclaration)
+			&& ((ConstructorDeclaration)this.referenceContext).isDefaultConstructor();
 	boolean insideImplicitConstructorCall =
 		(location instanceof ExplicitConstructorCall)
 			&& (((ExplicitConstructorCall) location).accessMode == ExplicitConstructorCall.ImplicitSuper);
@@ -2858,16 +3307,16 @@
 		location.sourceStart,
 		location.sourceEnd);
 }
-public void uninitializedBlankFinalField(FieldBinding binding, AstNode location) {
+public void uninitializedBlankFinalField(FieldBinding binding, ASTNode location) {
 	String[] arguments = new String[] {new String(binding.readableName())};
 	this.handle(
 		IProblem.UninitializedBlankFinalField,
 		arguments,
 		arguments,
 		location.sourceStart,
-		location.sourceEnd);
+		fieldLocation(binding, location));
 }
-public void uninitializedLocalVariable(LocalVariableBinding binding, AstNode location) {
+public void uninitializedLocalVariable(LocalVariableBinding binding, ASTNode location) {
 	String[] arguments = new String[] {new String(binding.readableName())};
 	this.handle(
 		IProblem.UninitializedLocalVariable,
@@ -2877,7 +3326,6 @@
 		location.sourceEnd);
 }
 public void unmatchedBracket(int position, ReferenceContext context, CompilationResult compilationResult) {
-
 	this.handle(
 		IProblem.UnmatchedBracket, 
 		NoArgument,
@@ -2887,6 +3335,41 @@
 		context,
 		compilationResult);
 }
+public void unnecessaryCast(CastExpression castExpression) {
+	TypeBinding castedExpressionType = castExpression.expression.resolvedType;
+	this.handle(
+		IProblem.UnnecessaryCast,
+		new String[]{ new String(castedExpressionType.readableName()), new String(castExpression.resolvedType.readableName())},
+		new String[]{ new String(castedExpressionType.shortReadableName()), new String(castExpression.resolvedType.shortReadableName())},
+		castExpression.sourceStart,
+		castExpression.sourceEnd);
+}
+public void unnecessaryCastForArgument(CastExpression castExpression, TypeBinding parameterType) {
+	TypeBinding castedExpressionType = castExpression.expression.resolvedType;
+	this.handle(
+		IProblem.UnnecessaryArgumentCast,
+		new String[]{ new String(castedExpressionType.readableName()), new String(castExpression.resolvedType.readableName()), new String(parameterType.readableName())},
+		new String[]{ new String(castedExpressionType.shortReadableName()), new String(castExpression.resolvedType.shortReadableName()), new String(parameterType.shortReadableName())},
+		castExpression.sourceStart,
+		castExpression.sourceEnd);
+}
+public void unnecessaryInstanceof(InstanceOfExpression instanceofExpression, TypeBinding checkType) {
+	TypeBinding expressionType = instanceofExpression.expression.resolvedType;
+	this.handle(
+		IProblem.UnnecessaryInstanceof,
+		new String[]{ new String(expressionType.readableName()), new String(checkType.readableName())},
+		new String[]{ new String(expressionType.shortReadableName()), new String(checkType.shortReadableName())},
+		instanceofExpression.sourceStart,
+		instanceofExpression.sourceEnd);
+}
+public void unqualifiedFieldAccess(NameReference reference, FieldBinding field) {
+	this.handle(
+		IProblem.UnqualifiedFieldAccess,
+		new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
+		new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
+		reference.sourceStart,
+		reference.sourceEnd);
+}
 public void unnecessaryEnclosingInstanceSpecification(Expression expression, ReferenceBinding targetType) {
 	this.handle(
 		IProblem.IllegalEnclosingInstanceSpecification,
@@ -2895,19 +3378,15 @@
 		expression.sourceStart,
 		expression.sourceEnd);
 }
-public void unnecessaryReceiverForStaticMethod(AstNode location, MethodBinding method) {
+public void unreachableCatchBlock(ReferenceBinding exceptionType, ASTNode location) {
 	this.handle(
-		IProblem.NonStaticAccessToStaticMethod,
-		new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
-		new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
-		location.sourceStart,
-		location.sourceEnd);
-}
-public void unnecessaryReceiverForStaticField(AstNode location, FieldBinding field) {
-	this.handle(
-		IProblem.NonStaticAccessToStaticField,
-		new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
-		new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
+		IProblem.UnreachableCatch,
+		new String[] {
+			new String(exceptionType.readableName()),
+		 }, 
+		new String[] {
+			new String(exceptionType.shortReadableName()),
+		 }, 
 		location.sourceStart,
 		location.sourceEnd);
 }
@@ -2919,14 +3398,6 @@
 		statement.sourceStart,
 		statement.sourceEnd);
 }
-public void unreachableExceptionHandler(ReferenceBinding exceptionType, AstNode location) {
-	this.handle(
-		IProblem.UnreachableCatch,
-		NoArgument,
-		NoArgument,
-		location.sourceStart,
-		location.sourceEnd);
-}
 public void unresolvableReference(NameReference nameRef, Binding binding) {
 	int severity = Error;
 /* also need to check that the searchedType is the receiver type
@@ -2937,17 +3408,23 @@
 	}
 */
 	String[] arguments = new String[] {new String(binding.readableName())};
+	int end = nameRef.sourceEnd;
+	if (nameRef instanceof QualifiedNameReference) {
+		QualifiedNameReference ref = (QualifiedNameReference) nameRef;
+		if (ref.indexOfFirstFieldBinding >= 1)
+			end = (int) ref.sourcePositions[ref.indexOfFirstFieldBinding - 1];
+	}
 	this.handle(
 		IProblem.UndefinedName,
 		arguments,
 		arguments,
 		severity,
 		nameRef.sourceStart,
-		nameRef.sourceEnd);
+		end);
 }
 public void unusedArgument(LocalDeclaration localDecl) {
 
-	String[] arguments = new String[] {localDecl.name()};
+	String[] arguments = new String[] {new String(localDecl.name)};
 	this.handle(
 		IProblem.ArgumentIsNeverUsed,
 		arguments,
@@ -2955,6 +3432,41 @@
 		localDecl.sourceStart,
 		localDecl.sourceEnd);
 }
+public void unusedDeclaredThrownException(ReferenceBinding exceptionType, AbstractMethodDeclaration method, ASTNode location) {
+	if (method.isConstructor()) {
+		this.handle(
+			IProblem.UnusedConstructorDeclaredThrownException,
+			new String[] {
+				new String(method.binding.declaringClass.readableName()),
+				parametersAsString(method.binding),
+				new String(exceptionType.readableName()),
+			 }, 
+			new String[] {
+				new String(method.binding.declaringClass.shortReadableName()),
+				parametersAsShortString(method.binding),
+				new String(exceptionType.shortReadableName()),
+			 }, 
+			location.sourceStart,
+			location.sourceEnd);
+	} else {
+		this.handle(
+			IProblem.UnusedMethodDeclaredThrownException,
+			new String[] {
+				new String(method.binding.declaringClass.readableName()),
+				new String(method.selector),
+				parametersAsString(method.binding),
+				new String(exceptionType.readableName()),
+			 }, 
+			new String[] {
+				new String(method.binding.declaringClass.shortReadableName()),
+				new String(method.selector),
+				parametersAsShortString(method.binding),
+				new String(exceptionType.shortReadableName()),
+			 }, 
+			location.sourceStart,
+			location.sourceEnd);
+	}
+}
 public void unusedImport(ImportReference importRef) {
 	String[] arguments = new String[] { CharOperation.toString(importRef.tokens) };
 	this.handle(
@@ -2965,7 +3477,7 @@
 		importRef.sourceEnd); 
 }
 public void unusedLocalVariable(LocalDeclaration localDecl) {
-	String[] arguments = new String[] {localDecl.name()};
+	String[] arguments = new String[] {new String(localDecl.name)};
 	this.handle(
 		IProblem.LocalVariableIsNeverUsed,
 		arguments,
@@ -3003,7 +3515,7 @@
 	if (CharOperation.equals(TypeConstants.SERIALVERSIONUID, field.name)
 			&& field.isStatic()
 			&& field.isFinal()
-			&& TypeBinding.LongBinding == field.type) {
+			&& BaseTypes.LongBinding == field.type) {
 				return; // do not report unused serialVersionUID field
 		}
 	this.handle(
@@ -3027,7 +3539,7 @@
 	
 	// no report for serialization support 'void readObject(ObjectInputStream)'
 	if (!method.isStatic()
-			&& TypeBinding.VoidBinding == method.returnType
+			&& BaseTypes.VoidBinding == method.returnType
 			&& method.parameters.length == 1
 			&& method.parameters[0].dimensions() == 0
 			&& CharOperation.equals(method.selector, TypeConstants.READOBJECT)
@@ -3036,7 +3548,7 @@
 	}
 	// no report for serialization support 'void writeObject(ObjectOutputStream)'
 	if (!method.isStatic()
-			&& TypeBinding.VoidBinding == method.returnType
+			&& BaseTypes.VoidBinding == method.returnType
 			&& method.parameters.length == 1
 			&& method.parameters[0].dimensions() == 0
 			&& CharOperation.equals(method.selector, TypeConstants.WRITEOBJECT)
@@ -3045,14 +3557,14 @@
 	}
 	// no report for serialization support 'Object readResolve()'
 	if (!method.isStatic()
-			&& TypeBinding.T_Object == method.returnType.id
+			&& TypeIds.T_Object == method.returnType.id
 			&& method.parameters.length == 0
 			&& CharOperation.equals(method.selector, TypeConstants.READRESOLVE)) {
 		return;
 	}
 	// no report for serialization support 'Object writeReplace()'
 	if (!method.isStatic()
-			&& TypeBinding.T_Object == method.returnType.id
+			&& TypeIds.T_Object == method.returnType.id
 			&& method.parameters.length == 0
 			&& CharOperation.equals(method.selector, TypeConstants.WRITEREPLACE)) {
 		return;
@@ -3126,20 +3638,7 @@
 		currentMethod.sourceStart(),
 		currentMethod.sourceEnd());
 }
-public void wrongSequenceOfExceptionTypesError(TryStatement statement, int under, int upper) {
-	//the two catch block under and upper are in an incorrect order.
-	//under should be define BEFORE upper in the source
-
-	TypeReference typeRef = statement.catchArguments[under].type;
-	this.handle(
-		IProblem.UnreachableCatch,
-		NoArgument,
-		NoArgument,
-		typeRef.sourceStart,
-		typeRef.sourceEnd);
-}
-
-public void nonExternalizedStringLiteral(AstNode location) {
+public void nonExternalizedStringLiteral(ASTNode location) {
 	this.handle(
 		IProblem.NonExternalizedStringLiteral,
 		NoArgument,
@@ -3168,96 +3667,337 @@
 		typeDeclaration.sourceEnd);
 }
 
-private boolean isKeyword(char[] tokenSource) {
-	/*
-	 * This code is heavily grammar dependant
-	 */
-
-	if (tokenSource == null) {
-		return false;
-	}
-	try {
-		Scanner scanner = new Scanner();
-		scanner.setSource(tokenSource);
-		int token = scanner.getNextToken();
-		char[] currentKeyword;
-		try {
-			currentKeyword = scanner.getCurrentIdentifierSource();
-		} catch (ArrayIndexOutOfBoundsException e) {
+private boolean isKeyword(int token) {
+	switch(token) {
+		case TerminalTokens.TokenNameabstract:
+		case TerminalTokens.TokenNameassert:
+		case TerminalTokens.TokenNamebyte:
+		case TerminalTokens.TokenNamebreak:
+		case TerminalTokens.TokenNameboolean:
+		case TerminalTokens.TokenNamecase:
+		case TerminalTokens.TokenNamechar:
+		case TerminalTokens.TokenNamecatch:
+		case TerminalTokens.TokenNameclass:
+		case TerminalTokens.TokenNamecontinue:
+		case TerminalTokens.TokenNamedo:
+		case TerminalTokens.TokenNamedouble:
+		case TerminalTokens.TokenNamedefault:
+		case TerminalTokens.TokenNameelse:
+		case TerminalTokens.TokenNameextends:
+		case TerminalTokens.TokenNamefor:
+		case TerminalTokens.TokenNamefinal:
+		case TerminalTokens.TokenNamefloat:
+		case TerminalTokens.TokenNamefalse:
+		case TerminalTokens.TokenNamefinally:
+		case TerminalTokens.TokenNameif:
+		case TerminalTokens.TokenNameint:
+		case TerminalTokens.TokenNameimport:
+		case TerminalTokens.TokenNameinterface:
+		case TerminalTokens.TokenNameimplements:
+		case TerminalTokens.TokenNameinstanceof:
+		case TerminalTokens.TokenNamelong:
+		case TerminalTokens.TokenNamenew:
+		case TerminalTokens.TokenNamenull:
+		case TerminalTokens.TokenNamenative:
+		case TerminalTokens.TokenNamepublic:
+		case TerminalTokens.TokenNamepackage:
+		case TerminalTokens.TokenNameprivate:
+		case TerminalTokens.TokenNameprotected:
+		case TerminalTokens.TokenNamereturn:
+		case TerminalTokens.TokenNameshort:
+		case TerminalTokens.TokenNamesuper:
+		case TerminalTokens.TokenNamestatic:
+		case TerminalTokens.TokenNameswitch:
+		case TerminalTokens.TokenNamestrictfp:
+		case TerminalTokens.TokenNamesynchronized:
+		case TerminalTokens.TokenNametry:
+		case TerminalTokens.TokenNamethis:
+		case TerminalTokens.TokenNametrue:
+		case TerminalTokens.TokenNamethrow:
+		case TerminalTokens.TokenNamethrows:
+		case TerminalTokens.TokenNametransient:
+		case TerminalTokens.TokenNamevoid:
+		case TerminalTokens.TokenNamevolatile:
+		case TerminalTokens.TokenNamewhile:
+			return true;
+		default: 
 			return false;
-		}
-		int nextToken= scanner.getNextToken();
-		if (nextToken == TerminalTokens.TokenNameEOF
-			&& scanner.startPosition == scanner.source.length) { // to handle case where we had an ArrayIndexOutOfBoundsException 
-															     // while reading the last token
-			switch(token) {
-				case Scanner.TokenNameERROR:
-					if (CharOperation.equals("goto".toCharArray(), currentKeyword) ||CharOperation.equals("const".toCharArray(), currentKeyword)) { //$NON-NLS-1$ //$NON-NLS-2$
-						return true;
-					} else {
-						return false;
-					}
-				case Scanner.TokenNameabstract:
-				case Scanner.TokenNameassert:
-				case Scanner.TokenNamebyte:
-				case Scanner.TokenNamebreak:
-				case Scanner.TokenNameboolean:
-				case Scanner.TokenNamecase:
-				case Scanner.TokenNamechar:
-				case Scanner.TokenNamecatch:
-				case Scanner.TokenNameclass:
-				case Scanner.TokenNamecontinue:
-				case Scanner.TokenNamedo:
-				case Scanner.TokenNamedouble:
-				case Scanner.TokenNamedefault:
-				case Scanner.TokenNameelse:
-				case Scanner.TokenNameextends:
-				case Scanner.TokenNamefor:
-				case Scanner.TokenNamefinal:
-				case Scanner.TokenNamefloat:
-				case Scanner.TokenNamefalse:
-				case Scanner.TokenNamefinally:
-				case Scanner.TokenNameif:
-				case Scanner.TokenNameint:
-				case Scanner.TokenNameimport:
-				case Scanner.TokenNameinterface:
-				case Scanner.TokenNameimplements:
-				case Scanner.TokenNameinstanceof:
-				case Scanner.TokenNamelong:
-				case Scanner.TokenNamenew:
-				case Scanner.TokenNamenull:
-				case Scanner.TokenNamenative:
-				case Scanner.TokenNamepublic:
-				case Scanner.TokenNamepackage:
-				case Scanner.TokenNameprivate:
-				case Scanner.TokenNameprotected:
-				case Scanner.TokenNamereturn:
-				case Scanner.TokenNameshort:
-				case Scanner.TokenNamesuper:
-				case Scanner.TokenNamestatic:
-				case Scanner.TokenNameswitch:
-				case Scanner.TokenNamestrictfp:
-				case Scanner.TokenNamesynchronized:
-				case Scanner.TokenNametry:
-				case Scanner.TokenNamethis:
-				case Scanner.TokenNametrue:
-				case Scanner.TokenNamethrow:
-				case Scanner.TokenNamethrows:
-				case Scanner.TokenNametransient:
-				case Scanner.TokenNamevoid:
-				case Scanner.TokenNamevolatile:
-				case Scanner.TokenNamewhile:
-					return true;
-				default: 
-					return false;
-			}
-		} else {
-			return false;
-		}
 	}
-	catch (InvalidInputException e) {
-		return false;
-	}
-	
 }
+
+private boolean isLiteral(int token) {
+	switch(token) {
+		case TerminalTokens.TokenNameIntegerLiteral:
+		case TerminalTokens.TokenNameLongLiteral:
+		case TerminalTokens.TokenNameFloatingPointLiteral:
+		case TerminalTokens.TokenNameDoubleLiteral:
+		case TerminalTokens.TokenNameStringLiteral:
+		case TerminalTokens.TokenNameCharacterLiteral:
+			return true;
+		default: 
+			return false;
+	}
+}
+
+private boolean isIdentifier(int token) {
+	return token == TerminalTokens.TokenNameIdentifier;
+}
+
+private void syntaxError(
+	int id,
+	int startPosition, 
+	int endPosition, 
+	int currentKind,
+	char[] currentTokenSource, 
+	String errorTokenName, 
+	String expectedToken) {
+
+	String eTokenName;
+	if (isKeyword(currentKind) ||
+		isLiteral(currentKind) ||
+		isIdentifier(currentKind)) { //$NON-NLS-1$
+			eTokenName = new String(currentTokenSource);
+	} else {
+		eTokenName = errorTokenName;
+	}
+
+	String[] arguments;
+	if(expectedToken != null) {
+		arguments = new String[] {eTokenName, expectedToken};
+	} else {
+		arguments = new String[] {eTokenName};
+	}
+	this.handle(
+		id,
+		arguments,
+		arguments,
+		startPosition,
+		endPosition);
+}
+
+public void parseErrorInsertBeforeToken(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName,
+	String expectedToken){
+	this.syntaxError(
+		IProblem.ParsingErrorInsertTokenBefore,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName, 
+		expectedToken); 
+}
+public void parseErrorInsertAfterToken(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName,
+	String expectedToken){
+	this.syntaxError(
+		IProblem.ParsingErrorInsertTokenAfter,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName, 
+		expectedToken); 
+}
+public void parseErrorDeleteToken(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName){
+	this.syntaxError(
+		IProblem.ParsingErrorDeleteToken,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName,
+		null); 
+}
+public void parseErrorReplaceToken(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName,
+	String expectedToken){
+	this.syntaxError(
+		IProblem.ParsingError,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName, 
+		expectedToken); 
+}
+public void parseErrorInvalidToken(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName,
+	String expectedToken){
+	this.syntaxError(
+		IProblem.ParsingErrorInvalidToken,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName, 
+		expectedToken); 
+}
+public void parseErrorUnexpectedEnd(
+	int start,
+	int end){
+		
+	String[] arguments;
+	if(this.referenceContext instanceof ConstructorDeclaration) {
+		arguments = new String[] {Util.bind("parser.endOfConstructor")}; //$NON-NLS-1$
+	} else if(this.referenceContext instanceof MethodDeclaration) {
+		arguments = new String[] {Util.bind("parser.endOfMethod")}; //$NON-NLS-1$
+	} else if(this.referenceContext instanceof TypeDeclaration) {
+		arguments = new String[] {Util.bind("parser.endOfInitializer")}; //$NON-NLS-1$
+	} else {
+		arguments = new String[] {Util.bind("parser.endOfFile")}; //$NON-NLS-1$
+	}
+	this.handle(
+		IProblem.ParsingErrorUnexpectedEOF,
+		arguments,
+		arguments,
+		start,
+		end);
+}
+public void parseErrorMergeTokens(
+	int start,
+	int end,
+	String expectedToken){
+	String[] arguments = new String[] {expectedToken};
+	this.handle(
+		IProblem.ParsingErrorMergeTokens,
+		arguments,
+		arguments,
+		start,
+		end);
+}
+public void parseErrorMisplacedConstruct(
+	int start,
+	int end){
+	this.handle(
+		IProblem.ParsingErrorMisplacedConstruct,
+		NoArgument,
+		NoArgument,
+		start,
+		end);
+}
+public void parseErrorNoSuggestion(
+	int start,
+	int end,
+	int currentKind,
+	char[] errorTokenSource,
+	String errorTokenName){
+	this.syntaxError(
+		IProblem.ParsingErrorNoSuggestion,
+		start, 
+		end, 
+		currentKind,
+		errorTokenSource, 
+		errorTokenName,
+		null); 
+}
+public void parseErrorDeleteTokens(
+	int start,
+	int end){
+	this.handle(
+		IProblem.ParsingErrorDeleteTokens,
+		NoArgument,
+		NoArgument,
+		start,
+		end);
+}
+public void parseErrorNoSuggestionForTokens(
+	int start,
+	int end){
+	this.handle(
+		IProblem.ParsingErrorNoSuggestionForTokens,
+		NoArgument,
+		NoArgument,
+		start,
+		end);
+}
+public void parseErrorReplaceTokens(
+	int start,
+	int end,
+	String expectedToken){
+	String[] arguments = new String[] {expectedToken};
+	this.handle(
+		IProblem.ParsingErrorReplaceTokens,
+		arguments,
+		arguments,
+		start,
+		end);
+}
+public void parseErrorInsertToComplete(
+	int start,
+	int end,
+	String inserted,
+	String completed){
+	String[] arguments = new String[] {inserted, completed};
+	this.handle(
+		IProblem.ParsingErrorInsertToComplete,
+		arguments,
+		arguments,
+		start,
+		end);
+}
+public void parseErrorInsertToCompleteScope(
+	int start,
+	int end,
+	String inserted){
+	String[] arguments = new String[] {inserted};
+	this.handle(
+		IProblem.ParsingErrorInsertToCompleteScope,
+		arguments,
+		arguments,
+		start,
+		end);
+}
+public void parseErrorInsertToCompletePhrase(
+	int start,
+	int end,
+	String inserted){
+	String[] arguments = new String[] {inserted};
+	this.handle(
+		IProblem.ParsingErrorInsertToCompletePhrase,
+		arguments,
+		arguments,
+		start,
+		end);
+}
+public void wrongSequenceOfExceptionTypesError(TryStatement statement, TypeBinding exceptionType, int under, TypeBinding hidingExceptionType) {
+	//the two catch block under and upper are in an incorrect order.
+	//under should be define BEFORE upper in the source
+
+	TypeReference typeRef = statement.catchArguments[under].type;
+	this.handle(
+		IProblem.InvalidCatchBlockSequence,
+		new String[] {
+			new String(exceptionType.readableName()),
+			new String(hidingExceptionType.readableName()),
+		 }, 
+		new String[] {
+			new String(exceptionType.shortReadableName()),
+			new String(hidingExceptionType.shortReadableName()),
+		 }, 
+		typeRef.sourceStart,
+		typeRef.sourceEnd);
+}
+
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java
index 1177c69..a89eac9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java
@@ -17,9 +17,7 @@
  *	(internal only)
  */
 public class ShouldNotImplement extends RuntimeException {
-public ShouldNotImplement(){
-}
-public ShouldNotImplement(String message){
-	super(message);
-}
+	public ShouldNotImplement(String message) {
+		super(message);
+	}
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index 1882fd4..ca0e724 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -14,12 +14,13 @@
 3 = The type {0} is not visible
 4 = The type {0} is ambiguous
 5 = The type {0} is deprecated
-6 = The type {0} is an incorrectly specified nested type; replace the ''$'' with ''.''
+6 = The nested type {0} cannot be referenced using its binary name
 7 = The private type {0} is never used locally
 
 15 = Incompatible operand types {0} and {1}
 16 = Incompatible conditional operand types {0} and {1}
 17 = Type mismatch: cannot convert from {0} to {1}
+18 = The static member type {0}.{1} should be accessed directly
 
 20 = No enclosing instance of type {0} is accessible to invoke the super constructor. Must define a constructor and explicitly qualify its super constructor invocation with an instance of {0} (e.g. x.super() where x is an instance of {0}).
 21 = No enclosing instance of type {0} is accessible. Must qualify the allocation with an enclosing instance of type {0} (e.g. x.new A() where x is an instance of {0}).
@@ -59,12 +60,20 @@
 74 = Cannot make a static reference to the non-static field {0}
 75 = Cannot reference a field before it is defined
 76 = The static field {0}.{1} should be accessed in a static way
-77 = The private field {0}.{1} is never used locally
-
+77 = The private field {0}.{1} is never read locally
+78 = The static field {0}.{1} should be accessed directly
+79 = Unqualified access to the field {0}.{1} 
 80 = The final field {0}.{1} cannot be assigned. It must be blank in this context, not qualified and not in compound assignment
 81 = The blank final field {0} may not have been initialized
 82 = The final field {0} may already have been assigned
 
+90 = The local variable {0} is hiding another local variable defined in an enclosing type scope
+91 = The local variable {0} is hiding a field from type {1}
+92 = The field {0}.{1} is hiding another local variable defined in an enclosing type scope
+93 = The field {0}.{1} is hiding a field from type {2}
+94 = The argument {0} is hiding another local variable defined in an enclosing type scope
+95 = The argument {0} is hiding a field from type {1}
+
 100 = The method {1}({2}) is undefined for the type {0}
 101 = The method {1}({2}) from the type {0} is not visible
 102 = The method {1}({2}) is ambiguous for the type {0}
@@ -84,6 +93,7 @@
 116 = Cannot invoke {1}({2}) on the array type {0}
 117 = The static method {1}({2}) from the type {0} should be accessed in a static way
 118 = The private method {1}({2}) from the type {0} is never used locally
+119 = The static method {1}({2}) from the type {0} should be accessed directly 
 
 130 = The constructor {0}({1}) is undefined
 131 = The constructor {0}({1}) is not visible
@@ -94,7 +104,7 @@
 136 = Cannot refer to an instance method while explicitly invoking a constructor
 137 = Recursive constructor invocation {0}({1})
 138 = Cannot refer to ''this'' nor ''super'' while explicitly invoking a constructor
-
+139 = Constructor call must be the first statement in a constructor
 140 = Implicit super constructor {0}({1}) is undefined for default constructor. Must define an explicit constructor
 141 = Implicit super constructor {0}({1}) is not visible for default constructor. Must define an explicit constructor
 142 = Implicit super constructor {0}({1}) is ambiguous for default constructor. Must define an explicit constructor
@@ -108,9 +118,9 @@
 151 = Must explicitly convert the char[] to a String
 152 = String constant is exceeding the limit of 65535 bytes of UTF8 encoding
 153 = case expressions must be constant expressions
-154 = {0} is out of range 
+154 = The literal {1} of type {0} is out of range 
 156 = Cannot cast from {0} to {1}
-157 = The type {0} cannot be instantiated
+157 = Cannot instantiate the type {0}, since it is not a concrete class
 158 = Cannot define dimension expressions when an array initializer is provided
 159 = Variable must provide either dimension expressions or an array initializer
 160 = The operator {0} is undefined for the argument type(s) {1}
@@ -118,12 +128,12 @@
 162 = Cannot return from within an initializer
 163 = Initializer does not complete normally
 164 = Expression must return a value
-165 = Catch block is hidden by another one in the same try statement
+165 = Unreachable catch block for {0}. Only more specific exceptions are thrown and handled by previous catch block(s).
 166 = The default case is already defined
-167 = Unreachable catch block
+167 = Unreachable catch block for {0}. This exception is never thrown from the try statement body
 168 = Unhandled exception type {0}
 169 = case constant must be a char, byte, short, or int instead of {0}
-170 = Duplicate case {0}
+170 = Duplicate case
 171 = Duplicate label {0}
 172 = break cannot be used outside of a loop or a switch
 173 = continue cannot be used outside of a loop
@@ -132,6 +142,15 @@
 176 = null is not a valid argument for the synchronized statement
 177 = Cannot throw null
 178 = The assignment to variable {0} has no effect
+179 = Possible accidental assignment in place of a comparison. A condition expression should not be reduced to an assignment
+180 = Unnecessary semicolon
+181 = Unnecessary cast to type {1} for expression of type {0}
+182 = Unnecessary cast to type {1} for expression of type {0}. It is already compatible with the argument type {2}
+183 = The expression of type {0} is already an instance of type {1}
+184 = finally block does not complete normally
+185 = The declared exception {3} is not actually thrown by the method {1}({2}) from type {0}
+186 = The declared exception {2} is not actually thrown by the constructor {0}({1})
+187 = Unreachable catch block for {0}. It is already handled by the catch block for {1}
 
 190 = Read access to enclosing field {0}.{1} is emulated by a synthetic accessor method. Increasing its visibility will improve your performance
 191 = Write access to enclosing field {0}.{1} is emulated by a synthetic accessor method. Increasing its visibility will improve your performance
@@ -160,6 +179,20 @@
 224 = Missing semicolon
 225 = Invalid parenthesized expression
 
+230 = Syntax error on token "{0}", {1} expected before this token
+231 = Syntax error on token "{0}", {1} expected after this token
+232 = Syntax error on token "{0}", delete this token
+233 = Syntax error on tokens, delete these tokens
+234 = Syntax error on tokens, they can be merge to form {0}
+235 = Syntax error on token "{0}", invalid {1}
+236 = Syntax error on token(s), misplaced construct(s)
+237 = Syntax error on tokens, {0} expected instead
+238 = Syntax error on tokens, no accurate correction available
+239 = Syntax error, unexpected {0}
+240 = Syntax error, insert "{0}" to complete {1}
+241 = Syntax error, insert "{0}" to complete scope
+242 = Syntax error, insert "{0}" to complete phrase
+
 250 = Unexpected end of file
 251 = Invalid hex literal number
 252 = Invalid octal literal number
@@ -196,7 +229,7 @@
 321 = The package {0} collides with a type
 322 = The type {1} collides with a package
 323 = The type {1} is already defined
-324 = This compilation unit indirectly references the missing type {0} (typically some required class file is referencing a type outside the classpath)
+324 = The type {0} cannot be resolved. It is indirectly referenced from required .class files.
 325 = The public type {1} must be defined in its own file
 326 = A package must be specified in {0} or a default package created
 327 = The hierarchy of the type {0} is inconsistent
@@ -206,12 +239,12 @@
 330 = {0} cannot be resolved or is not a valid superclass
 331 = Superclass {0} is not visible
 332 = Superclass {0} is ambiguous
-333 = Superclass {0} is an incorrectly specified nested type; replace the ''$'' with ''.''
+333 = Superclass {0} cannot be referenced using its binary name
 334 = Superclass {0} is defined in an inherited type and an enclosing scope
 335 = {0} cannot be resolved or is not a valid superinterface
 336 = Superinterface {0} is not visible
 337 = Superinterface {0} is ambiguous
-338 = Superinterface {0} is an incorrectly specified nested type; replace the ''$'' with ''.''
+338 = Superinterface {0} cannot be referenced using its binary name
 339 = Superinterface {0} is defined in an inherited type and an enclosing scope
 340 = Duplicate field {0}.{1}
 341 = Duplicate modifier for the field {0}
@@ -224,7 +257,7 @@
 350 = {2} cannot be resolved (or is not a valid type) for the field {1}.{0}
 351 = The type {2} is not visible for the field {1}.{0}
 352 = The type {2} is ambiguous for the field {1}.{0}
-353 = The field type {2} is an incorrectly specified nested type; replace the ''$'' with ''.''
+353 = The field type {2} cannot be referenced using its binary name
 354 = The field type {2} is defined in an inherited type and an enclosing scope
 355 = Duplicate method {0} in type {1}
 356 = Illegal modifier for argument {0}; only final is permitted
@@ -244,17 +277,17 @@
 370 = {2} cannot be resolved (or is not a valid type) for the argument {1} of the method {0}
 371 = The type {2} is not visible for the argument {1} of the method {0}
 372 = The type {2} is ambiguous for the argument {1} of the method {0}
-373 = The argument type {2} is an incorrectly specified nested type; replace the ''$'' with ''.''
+373 = The argument type {2} cannot be referenced using its binary name
 374 = The argument type {2} is defined in an inherited type and an enclosing scope
 375 = {1} cannot be resolved (or is not an exception type) for the method {0}
 376 = The exception type {1} is not visible for the method {0}
 377 = The exception type {1} is ambiguous for the method {0}
-378 = The exception type {1} is an incorrectly specified nested type; replace the ''$'' with ''.''
+378 = The exception type {1} cannot be referenced using its binary name
 379 = The exception type {1} is defined in an inherited type and an enclosing scope
 380 = {1} cannot be resolved (or is not a valid return type) for the method {0}
 381 = The return type {1} is not visible for the method {0}
 382 = The return type {1} is ambiguous for the method {0}
-383 = The return type {1} is an incorrectly specified nested type; replace the ''$'' with ''.''
+383 = The return type {1} cannot be referenced using its binary name
 384 = The return type {1} is defined in an inherited type and an enclosing scope
 385 = The import {0} conflicts with a type defined in the same file
 386 = The import {0} collides with another imported type
@@ -263,8 +296,8 @@
 390 = The import {0} cannot be resolved
 391 = The imported type {0} is not visible
 392 = The imported type {0} is ambiguous
-393 = The type {0} is an incorrectly specified nested type; replace the ''$'' with ''.''
-394 = The type {0} is defined in an inherited type and an enclosing scope
+393 = The imported type {0} cannot be referenced using its binary name
+394 = The imported type {0} is defined in an inherited type and an enclosing scope
 395 = Duplicate modifier for the variable {0}
 396 = Illegal modifier for the variable {0}; only final is permitted
 
@@ -297,3 +330,24 @@
 440 = ''assert'' should not be used as an identifier, since it is a reserved keyword from source level 1.4 on
 
 450 = {0} {1}
+
+460 = Empty block should be documented
+
+470 = Unexpected tag
+471 = Missing tag for parameter {0}
+472 = Missing parameter name
+473 = Duplicate tag for parameter
+474 = Parameter {0} is not declared
+475 = Missing tag for return type
+476 = Duplicate tag for return type
+477 = Missing tag for declared exception {0}
+478 = Missing class name
+479 = Invalid class name
+480 = Duplicate tag for thrown exception
+481 = Exception {0} is not declared
+482 = Missing reference
+483 = Invalid reference
+484 = Invalid URL link format
+485 = Invalid parameters declaration
+486 = Missing comment for {0} declaration
+489 = Javadoc: 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java
new file mode 100644
index 0000000..f9ad603
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.compiler.util;
+
+public interface SuffixConstants {
+	public final static String EXTENSION_class = "class"; //$NON-NLS-1$
+	public final static String EXTENSION_CLASS = "CLASS"; //$NON-NLS-1$
+	public final static String EXTENSION_java = "java"; //$NON-NLS-1$
+	public final static String EXTENSION_JAVA = "JAVA"; //$NON-NLS-1$
+	
+	public final static String SUFFIX_STRING_class = "." + EXTENSION_class; //$NON-NLS-1$
+	public final static String SUFFIX_STRING_CLASS = "." + EXTENSION_CLASS; //$NON-NLS-1$
+	public final static String SUFFIX_STRING_java = "." + EXTENSION_java; //$NON-NLS-1$
+	public final static String SUFFIX_STRING_JAVA = "." + EXTENSION_JAVA; //$NON-NLS-1$
+	
+	public final static char[] SUFFIX_class = SUFFIX_STRING_class.toCharArray();
+	public final static char[] SUFFIX_CLASS = SUFFIX_STRING_CLASS.toCharArray();
+	public final static char[] SUFFIX_java = SUFFIX_STRING_java.toCharArray();
+	public final static char[] SUFFIX_JAVA = SUFFIX_STRING_JAVA.toCharArray();
+	
+	public final static String EXTENSION_jar = "jar"; //$NON-NLS-1$
+	public final static String EXTENSION_JAR = "JAR"; //$NON-NLS-1$
+	public final static String EXTENSION_zip = "zip"; //$NON-NLS-1$
+	public final static String EXTENSION_ZIP = "ZIP"; //$NON-NLS-1$
+
+	public final static String SUFFIX_STRING_jar = "." + EXTENSION_jar; //$NON-NLS-1$
+	public final static String SUFFIX_STRING_JAR = "." + EXTENSION_JAR; //$NON-NLS-1$
+	public final static String SUFFIX_STRING_zip = "." + EXTENSION_zip; //$NON-NLS-1$
+	public final static String SUFFIX_STRING_ZIP = "." + EXTENSION_ZIP; //$NON-NLS-1$
+
+	public final static char[] SUFFIX_jar = SUFFIX_STRING_jar.toCharArray();
+	public final static char[] SUFFIX_JAR = SUFFIX_STRING_JAR.toCharArray();
+	public final static char[] SUFFIX_zip = SUFFIX_STRING_zip.toCharArray(); 
+	public final static char[] SUFFIX_ZIP = SUFFIX_STRING_ZIP.toCharArray();
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
index 15578ea..04267ba 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
@@ -25,23 +25,19 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 
-public class Util {
+public class Util implements SuffixConstants {
+
+	public interface Displayable {
+		String displayString(Object o);
+	}
 
 	public static String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
 	public static char[] LINE_SEPARATOR_CHARS = LINE_SEPARATOR.toCharArray();
-	public final static char[] SUFFIX_class = ".class".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_CLASS = ".CLASS".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_java = ".java".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_JAVA = ".JAVA".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_jar = ".jar".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_JAR = ".JAR".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_zip = ".zip".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_ZIP = ".ZIP".toCharArray(); //$NON-NLS-1$
-		
+	
 	private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
 	private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
 	private static final int DEFAULT_READING_SIZE = 8192;
-	
+
 	/* Bundle containing messages */
 	protected static ResourceBundle bundle;
 	private final static String bundleName =
@@ -83,31 +79,42 @@
 			CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
 		message = new String(messageWithNoDoubleQuotes);
 
-		if (bindings == null)
-			return message;
-
 		int length = message.length();
 		int start = -1;
 		int end = length;
-		StringBuffer output = new StringBuffer(80);
+		StringBuffer output = null;
 		while (true) {
 			if ((end = message.indexOf('{', start)) > -1) {
+				if (output == null) output = new StringBuffer(80);
 				output.append(message.substring(start + 1, end));
 				if ((start = message.indexOf('}', end)) > -1) {
 					int index = -1;
 					try {
 						index = Integer.parseInt(message.substring(end + 1, start));
 						output.append(bindings[index]);
-					} catch (NumberFormatException nfe) {
-						output.append(message.substring(end + 1, start + 1));
+					} catch (NumberFormatException nfe) { // could be nested message ID {compiler.name}
+						String argId = message.substring(end + 1, start);
+						boolean done = false;
+						if (!id.equals(argId)) {
+							String argMessage = null;
+							try {
+								argMessage = bundle.getString(argId);
+								output.append(argMessage);
+								done = true;
+							} catch (MissingResourceException e) {
+								// ignore
+							}
+						}
+						if (!done) output.append(message.substring(end + 1, start + 1));
 					} catch (ArrayIndexOutOfBoundsException e) {
-						output.append("{missing " + Integer.toString(index) + "}");	//$NON-NLS-2$ //$NON-NLS-1$
+						output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
 					}
 				} else {
 					output.append(message.substring(end, length));
 					break;
 				}
 			} else {
+				if (output == null) return message;
 				output.append(message.substring(start + 1, length));
 				break;
 			}
@@ -153,6 +160,7 @@
 				try {
 					stream.close();
 				} catch (IOException e) {
+					// ignore
 				}
 			}
 		}
@@ -172,6 +180,7 @@
 				try {
 					stream.close();
 				} catch (IOException e) {
+					// ignore
 				}
 			}
 		}
@@ -320,6 +329,7 @@
 				try {
 					stream.close();
 				} catch (IOException e) {
+					// ignore
 				}
 			}
 		}
@@ -369,6 +379,21 @@
 		return true;		
 	}	
 	/**
+	 * Returns true iff str.toLowerCase().endsWith(".class")
+	 * implementation is not creating extra strings.
+	 */
+	public final static boolean isClassFileName(char[] name) {
+		int nameLength = name == null ? 0 : name.length;
+		int suffixLength = SUFFIX_CLASS.length;
+		if (nameLength < suffixLength) return false;
+
+		for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+			char c = name[offset + i];
+			if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false;
+		}
+		return true;		
+	}	
+	/**
 	 * Returns true iff str.toLowerCase().endsWith(".java")
 	 * implementation is not creating extra strings.
 	 */
@@ -384,4 +409,58 @@
 		}
 		return true;		
 	}
+	/**
+	 * Returns true iff str.toLowerCase().endsWith(".java")
+	 * implementation is not creating extra strings.
+	 */
+	public final static boolean isJavaFileName(char[] name) {
+		int nameLength = name == null ? 0 : name.length;
+		int suffixLength = SUFFIX_JAVA.length;
+		if (nameLength < suffixLength) return false;
+
+		for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+			char c = name[offset + i];
+			if (c != SUFFIX_java[i] && c != SUFFIX_JAVA[i]) return false;
+		}
+		return true;		
+	}
+	/**
+	 * Converts an array of Objects into String.
+	 */
+	public static String toString(Object[] objects) {
+		return toString(objects, 
+			new Displayable(){ 
+				public String displayString(Object o) { 
+					if (o == null) return "null"; //$NON-NLS-1$
+					return o.toString(); 
+				}
+			});
+	}
+
+	/**
+	 * Converts an array of Objects into String.
+	 */
+	public static String toString(Object[] objects, Displayable renderer) {
+		if (objects == null) return ""; //$NON-NLS-1$
+		StringBuffer buffer = new StringBuffer(10);
+		for (int i = 0; i < objects.length; i++){
+			if (i > 0) buffer.append(", "); //$NON-NLS-1$
+			buffer.append(renderer.displayString(objects[i]));
+		}
+		return buffer.toString();
+	}
+
+	/**
+	 * Converts a boolean value into Boolean.
+	 * @param bool The boolean to convert
+	 * @return The corresponding Boolean object (TRUE or FALSE).
+	 */
+	public static Boolean toBoolean(boolean bool) {
+		if (bool) {
+			return Boolean.TRUE;
+		} else {
+			return Boolean.FALSE;
+		}
+	}
+	
 }
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/messages.properties
index 99a6994..5165944 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/messages.properties
@@ -47,17 +47,16 @@
 parser.regularParse = REGULAR PARSE
 parser.missingFile = missing file {0}
 parser.corruptedFile = corrupted file {0}
+parser.endOfFile = end of file
+parser.endOfConstructor = end of constructor
+parser.endOfMethod = end of method
+parser.endOfInitializer = end of initializer
 
 ### binding
 binding.subclass = anonymous subclass of {0}
 binding.implementation = anonymous implementation of {0}
 
 ### ast
-ast.missingStatement = Missing statement code generation implementation
-ast.variableShouldProvide = Assignment variable should provide an implementation for flow analysis
-ast.compoundPreShouldProvide = Compound pre assignments  should provide an implementation for code generation
-ast.compoundVariableShouldProvide = Compound assignment variable  should provide an implementation for code generation
-ast.postIncrShouldProvide = Post increment variable  should provide an implementation for code generation
 ast.missingCode = Missing code gen implementation
 
 ### constant
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
index 0ed77a6..af6c582 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
@@ -13,15 +13,21 @@
 
 import java.util.Map;
 
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
+import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.NameLookup;
 
 /**
  * Umbrella owner and abstract syntax tree node factory.
@@ -63,12 +69,12 @@
  * subclassed.
  * </p>
  * 
- * @see #parseCompilationUnit
+ * @see #parseCompilationUnit(ICompilationUnit, boolean)
  * @see ASTNode
  * @since 2.0
  */
 public final class AST {
-	
+
 	/**
 	 * Internal modification count; initially 0; increases monotonically
 	 * <b>by one or more</b> as the AST is successively modified.
@@ -84,7 +90,7 @@
 	/**
 	 * Creates a new, empty abstract syntax tree using default options.
 	 * 
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public AST() {
 		this(JavaCore.getDefaultOptions());
@@ -107,14 +113,14 @@
 	 * 
 	 * @param options the table of options (key type: <code>String</code>;
 	 *    value type: <code>String</code>)
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public AST(Map options) {
 		this.scanner = new Scanner(
 			true /*comment*/, 
 			true /*whitespace*/, 
 			false /*nls*/, 
-			JavaCore.VERSION_1_4.equals(options.get(JavaCore.COMPILER_SOURCE)) /*assert*/, 
+			JavaCore.VERSION_1_4.equals(options.get(JavaCore.COMPILER_SOURCE)) ? ClassFileConstants.JDK1_4 : ClassFileConstants.JDK1_3 /*sourceLevel*/, 
 			null/*taskTag*/, 
 			null/*taskPriorities*/);
 	}
@@ -178,7 +184,6 @@
 		modCount++;	
 	}
 
-	
 	/**
 	 * Parses the source string of the given Java model compilation unit element
 	 * and creates and returns a corresponding abstract syntax tree. The source 
@@ -236,12 +241,89 @@
 	 * @see ASTNode#getLength()
 	 */
 	public static CompilationUnit parseCompilationUnit(
-			ICompilationUnit unit,
-			boolean resolveBindings) {
+		ICompilationUnit unit,
+		boolean resolveBindings) {
+
+		return parseCompilationUnit(unit, resolveBindings, DefaultWorkingCopyOwner.PRIMARY);
+	}
+	
+	/**
+	 * Parses the source string of the given Java model compilation unit element
+	 * and creates and returns a corresponding abstract syntax tree. The source 
+	 * string is obtained from the Java model element using
+	 * <code>ICompilationUnit.getSource()</code>.
+	 * <p>
+	 * The returned compilation unit node is the root node of a new AST.
+	 * Each node in the subtree carries source range(s) information relating back
+	 * to positions in the source string (the source string is not remembered
+	 * with the AST).
+	 * The source range usually begins at the first character of the first token 
+	 * corresponding to the node; leading whitespace and comments are <b>not</b>
+	 * included. The source range usually extends through the last character of
+	 * the last token corresponding to the node; trailing whitespace and
+	 * comments are <b>not</b> included. There are a handful of exceptions
+	 * (including compilation units and the various body declarations); the
+	 * specification for these node type spells out the details.
+	 * Source ranges nest properly: the source range for a child is always
+	 * within the source range of its parent, and the source ranges of sibling
+	 * nodes never overlap.
+	 * If a syntax error is detected while parsing, the relevant node(s) of the
+	 * tree will be flagged as <code>MALFORMED</code>.
+	 * </p>
+	 * <p>
+	 * If <code>resolveBindings</code> is <code>true</code>, the various names
+	 * and types appearing in the compilation unit can be resolved to "bindings"
+	 * by calling the <code>resolveBinding</code> methods. These bindings 
+	 * draw connections between the different parts of a program, and 
+	 * generally afford a more powerful vantage point for clients who wish to
+	 * analyze a program's structure more deeply. These bindings come at a 
+	 * considerable cost in both time and space, however, and should not be
+	 * requested frivolously. The additional space is not reclaimed until the 
+	 * AST, all its nodes, and all its bindings become garbage. So it is very
+	 * important to not retain any of these objects longer than absolutely
+	 * necessary. Bindings are resolved at the time the AST is created. Subsequent
+	 * modifications to the AST do not affect the bindings returned by
+	 * <code>resolveBinding</code> methods in any way; these methods return the
+	 * same binding as before the AST was modified (including modifications
+	 * that rearrange subtrees by reparenting nodes).
+	 * If <code>resolveBindings</code> is <code>false</code>, the analysis 
+	 * does not go beyond parsing and building the tree, and all 
+	 * <code>resolveBinding</code> methods return <code>null</code> from the 
+	 * outset.
+	 * </p>
+	 * <p>
+	 * When bindings are created, instead of considering compilation units on disk only
+	 * one can supply a <code>WorkingCopyOwner</code>. Working copies owned 
+	 * by this owner take precedence over the underlying compilation units when looking
+	 * up names and drawing the connections.
+	 * </p>
+	 * 
+	 * @param unit the Java model compilation unit whose source code is to be parsed
+	 * @param resolveBindings <code>true</code> if bindings are wanted, 
+	 *   and <code>false</code> if bindings are not of interest
+	 * @param owner the owner of working copies that take precedence over underlying 
+	 *   compilation units
+	 * @return the compilation unit node
+	 * @exception IllegalArgumentException if the given Java element does not 
+	 * exist or if its source string cannot be obtained
+	 * @see ASTNode#getFlags()
+	 * @see ASTNode#MALFORMED
+	 * @see ASTNode#getStartPosition()
+	 * @see ASTNode#getLength()
+	 * @see WorkingCopyOwner
+	 * @since 3.0
+	 */
+	public static CompilationUnit parseCompilationUnit(
+		ICompilationUnit unit,
+		boolean resolveBindings,
+		WorkingCopyOwner owner) {
 				
 		if (unit == null) {
 			throw new IllegalArgumentException();
 		}
+		if (owner == null) {
+			throw new IllegalArgumentException();
+		}
 		
 		char[] source = null;
 		try {
@@ -252,10 +334,17 @@
 		}
 
 		if (resolveBindings) {
+			NameLookup lookup = null;
+			CompilationUnitDeclaration compilationUnitDeclaration = null;
 			try {
-				CompilationUnitDeclaration compilationUnitDeclaration = CompilationUnitResolver.resolve(
-					unit,
-					new AbstractSyntaxTreeVisitorAdapter());
+				// set the units to look inside
+				lookup = ((JavaProject)unit.getJavaProject()).getNameLookup();
+				JavaModelManager manager = JavaModelManager.getJavaModelManager();
+				ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+				lookup.setUnitsToLookInside(workingCopies);
+				
+				// parse and resolve
+				compilationUnitDeclaration = CompilationUnitResolver.resolve(unit, false/*don't cleanup*/, source);
 				ASTConverter converter = new ASTConverter(unit.getJavaProject().getOptions(true), true);
 				AST ast = new AST();
 				BindingResolver resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope);
@@ -272,6 +361,13 @@
 				 * Therefore all binding resolution will return null.
 				 */
 				return parseCompilationUnit(source);			
+			} finally {
+				if (compilationUnitDeclaration != null) {
+					compilationUnitDeclaration.cleanUp();
+				}
+				if (lookup != null) {
+					lookup.setUnitsToLookInside(null);
+				}
 			}
 		} else {
 			return parseCompilationUnit(source);
@@ -339,53 +435,148 @@
 	public static CompilationUnit parseCompilationUnit(
 		IClassFile classFile,
 		boolean resolveBindings) {
-			if (classFile == null) {
-				throw new IllegalArgumentException();
-			}
-			char[] source = null;
-			String sourceString = null;
-			try {
-				sourceString = classFile.getSource();
-			} catch (JavaModelException e) {
-				throw new IllegalArgumentException();
-			}
-			if (sourceString == null) {
-				throw new IllegalArgumentException();
-			}
-			source = sourceString.toCharArray();
-			if (!resolveBindings) {
-				return AST.parseCompilationUnit(source);
-			}
-			StringBuffer buffer = new StringBuffer(".java"); //$NON-NLS-1$
 			
-			String classFileName = classFile.getElementName(); // this includes the trailing .class
-			buffer.insert(0, classFileName.toCharArray(), 0, classFileName.indexOf('.'));
-			IJavaProject project = classFile.getJavaProject();
-			try {
-				CompilationUnitDeclaration compilationUnitDeclaration =
-					CompilationUnitResolver.resolve(
-						source,
-						CharOperation.splitOn('.', classFile.getType().getPackageFragment().getElementName().toCharArray()),
-						buffer.toString(),
-						project,
-						new AbstractSyntaxTreeVisitorAdapter());
-				ASTConverter converter = new ASTConverter(project.getOptions(true), true);
-				AST ast = new AST();
-				BindingResolver resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope);
-				ast.setBindingResolver(resolver);
-				converter.setAST(ast);
+		return parseCompilationUnit(classFile, resolveBindings, DefaultWorkingCopyOwner.PRIMARY);
+	}
+	
+	/**
+	 * Parses the source string corresponding to the given Java class file
+	 * element and creates and returns a corresponding abstract syntax tree.
+	 * The source string is obtained from the Java model element using
+	 * <code>IClassFile.getSource()</code>, and is only available for a class
+	 * files with attached source.
+	 * <p>
+	 * The returned compilation unit node is the root node of a new AST.
+	 * Each node in the subtree carries source range(s) information relating back
+	 * to positions in the source string (the source string is not remembered
+	 * with the AST).
+	 * The source range usually begins at the first character of the first token 
+	 * corresponding to the node; leading whitespace and comments are <b>not</b>
+	 * included. The source range usually extends through the last character of
+	 * the last token corresponding to the node; trailing whitespace and
+	 * comments are <b>not</b> included. There are a handful of exceptions
+	 * (including compilation units and the various body declarations); the
+	 * specification for these node type spells out the details.
+	 * Source ranges nest properly: the source range for a child is always
+	 * within the source range of its parent, and the source ranges of sibling
+	 * nodes never overlap.
+	 * If a syntax error is detected while parsing, the relevant node(s) of the
+	 * tree will be flagged as <code>MALFORMED</code>.
+	 * </p>
+	 * <p>
+	 * If <code>resolveBindings</code> is <code>true</code>, the various names
+	 * and types appearing in the compilation unit can be resolved to "bindings"
+	 * by calling the <code>resolveBinding</code> methods. These bindings 
+	 * draw connections between the different parts of a program, and 
+	 * generally afford a more powerful vantage point for clients who wish to
+	 * analyze a program's structure more deeply. These bindings come at a 
+	 * considerable cost in both time and space, however, and should not be
+	 * requested frivolously. The additional space is not reclaimed until the 
+	 * AST, all its nodes, and all its bindings become garbage. So it is very
+	 * important to not retain any of these objects longer than absolutely
+	 * necessary. Bindings are resolved at the time the AST is created. Subsequent
+	 * modifications to the AST do not affect the bindings returned by
+	 * <code>resolveBinding</code> methods in any way; these methods return the
+	 * same binding as before the AST was modified (including modifications
+	 * that rearrange subtrees by reparenting nodes).
+	 * If <code>resolveBindings</code> is <code>false</code>, the analysis 
+	 * does not go beyond parsing and building the tree, and all 
+	 * <code>resolveBinding</code> methods return <code>null</code> from the 
+	 * outset.
+	 * </p>
+	 * <p>
+	 * When bindings are created, instead of considering compilation units on disk only
+	 * one can supply a <code>WorkingCopyOwner</code>. Working copies owned 
+	 * by this owner take precedence over the underlying compilation units when looking
+	 * up names and drawing the connections.
+	 * </p>
+	 * 
+	 * @param classFile the Java model compilation unit whose source code is to be parsed
+	 * @param resolveBindings <code>true</code> if bindings are wanted, 
+	 *   and <code>false</code> if bindings are not of interest
+	 * @param owner the owner of working copies that take precedence over underlying 
+	 *   compilation units
+	 * @return the compilation unit node
+	 * @exception IllegalArgumentException if the given Java element does not 
+	 * exist or if its source string cannot be obtained
+	 * @see ASTNode#getFlags()
+	 * @see ASTNode#MALFORMED
+	 * @see ASTNode#getStartPosition()
+	 * @see ASTNode#getLength()
+	 * @see WorkingCopyOwner
+	 * @since 3.0
+	 */
+	public static CompilationUnit parseCompilationUnit(
+		IClassFile classFile,
+		boolean resolveBindings,
+		WorkingCopyOwner owner) {
 			
-				CompilationUnit cu = converter.convert(compilationUnitDeclaration, source);
-				cu.setLineEndTable(compilationUnitDeclaration.compilationResult.lineSeparatorPositions);
-				resolver.storeModificationCount(ast.modificationCount());
-				return cu;
-			} catch(JavaModelException e) {
-				/* if a JavaModelException is thrown trying to retrieve the name environment
-				 * then we simply do a parsing without creating bindings.
-				 * Therefore all binding resolution will return null.
-				 */
-				return parseCompilationUnit(source);			
+		if (classFile == null) {
+			throw new IllegalArgumentException();
+		}
+		if (owner == null) {
+			throw new IllegalArgumentException();
+		}
+		char[] source = null;
+		String sourceString = null;
+		try {
+			sourceString = classFile.getSource();
+		} catch (JavaModelException e) {
+			throw new IllegalArgumentException();
+		}
+		if (sourceString == null) {
+			throw new IllegalArgumentException();
+		}
+		source = sourceString.toCharArray();
+		if (!resolveBindings) {
+			return AST.parseCompilationUnit(source);
+		}
+		StringBuffer buffer = new StringBuffer(SuffixConstants.SUFFIX_STRING_java);
+		
+		String classFileName = classFile.getElementName(); // this includes the trailing .class
+		buffer.insert(0, classFileName.toCharArray(), 0, classFileName.indexOf('.'));
+		IJavaProject project = classFile.getJavaProject();
+		NameLookup lookup = null;
+		CompilationUnitDeclaration compilationUnitDeclaration = null;
+		try {
+			// set the units to look inside
+			lookup = ((JavaProject)project).getNameLookup();
+			JavaModelManager manager = JavaModelManager.getJavaModelManager();
+			ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+			lookup.setUnitsToLookInside(workingCopies);
+			
+			// parse and resolve
+			compilationUnitDeclaration =
+				CompilationUnitResolver.resolve(
+					source,
+					CharOperation.splitOn('.', classFile.getType().getPackageFragment().getElementName().toCharArray()),
+					buffer.toString(),
+					project,
+					false/*don't cleanup*/);
+			ASTConverter converter = new ASTConverter(project.getOptions(true), true);
+			AST ast = new AST();
+			BindingResolver resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope);
+			ast.setBindingResolver(resolver);
+			converter.setAST(ast);
+		
+			CompilationUnit cu = converter.convert(compilationUnitDeclaration, source);
+			cu.setLineEndTable(compilationUnitDeclaration.compilationResult.lineSeparatorPositions);
+			resolver.storeModificationCount(ast.modificationCount());
+			return cu;
+		} catch(JavaModelException e) {
+			/* if a JavaModelException is thrown trying to retrieve the name environment
+			 * then we simply do a parsing without creating bindings.
+			 * Therefore all binding resolution will return null.
+			 */
+			return parseCompilationUnit(source);			
+		} finally {
+			if (compilationUnitDeclaration != null) {
+				compilationUnitDeclaration.cleanUp();
 			}
+			if (lookup != null) {
+				lookup.setUnitsToLookInside(null);
+			}
+		}
 	}
 			
 	/**
@@ -455,6 +646,88 @@
 		char[] source,
 		String unitName,
 		IJavaProject project) {
+		
+		return parseCompilationUnit(source, unitName, project, DefaultWorkingCopyOwner.PRIMARY);
+	}
+				
+	/**
+	 * Parses the given string as the hypothetical contents of the named
+	 * compilation unit and creates and returns a corresponding abstract syntax tree.
+	 * <p>
+	 * The returned compilation unit node is the root node of a new AST.
+	 * Each node in the subtree carries source range(s) information relating back
+	 * to positions in the given source string (the given source string itself
+	 * is not remembered with the AST).
+	 * The source range usually begins at the first character of the first token 
+	 * corresponding to the node; leading whitespace and comments are <b>not</b>
+	 * included. The source range usually extends through the last character of
+	 * the last token corresponding to the node; trailing whitespace and
+	 * comments are <b>not</b> included. There are a handful of exceptions
+	 * (including compilation units and the various body declarations); the
+	 * specification for these node type spells out the details.
+	 * Source ranges nest properly: the source range for a child is always
+	 * within the source range of its parent, and the source ranges of sibling
+	 * nodes never overlap.
+	 * If a syntax error is detected while parsing, the relevant node(s) of the
+	 * tree will be flagged as <code>MALFORMED</code>.
+	 * </p>
+	 * <p>
+	 * If the given project is not <code>null</code>, the various names
+	 * and types appearing in the compilation unit can be resolved to "bindings"
+	 * by calling the <code>resolveBinding</code> methods. These bindings 
+	 * draw connections between the different parts of a program, and 
+	 * generally afford a more powerful vantage point for clients who wish to
+	 * analyze a program's structure more deeply. These bindings come at a 
+	 * considerable cost in both time and space, however, and should not be
+	 * requested frivolously. The additional space is not reclaimed until the 
+	 * AST, all its nodes, and all its bindings become garbage. So it is very
+	 * important to not retain any of these objects longer than absolutely
+	 * necessary. Bindings are resolved at the time the AST is created. Subsequent
+	 * modifications to the AST do not affect the bindings returned by
+	 * <code>resolveBinding</code> methods in any way; these methods return the
+	 * same binding as before the AST was modified (including modifications
+	 * that rearrange subtrees by reparenting nodes).
+	 * If the given project is <code>null</code>, the analysis 
+	 * does not go beyond parsing and building the tree, and all 
+	 * <code>resolveBinding</code> methods return <code>null</code> from the 
+	 * outset.
+	 * </p>
+	 * <p>
+	 * When bindings are created, instead of considering compilation units on disk only
+	 * one can supply a <code>WorkingCopyOwner</code>. Working copies owned 
+	 * by this owner take precedence over the underlying compilation units when looking
+	 * up names and drawing the connections.
+	 * </p>
+	 * <p>
+	 * The name of the compilation unit must be supplied for resolving bindings.
+	 * This name should include the ".java" suffix and match the name of the main
+	 * (public) class or interface declared in the source. For example, if the source
+	 * declares a public class named "Foo", the name of the compilation should be
+	 * "Foo.java". For the purposes of resolving bindings, types declared in the
+	 * source string hide types by the same name available through the classpath
+	 * of the given project.
+	 * </p>
+	 * 
+	 * @param source the string to be parsed as a Java compilation unit
+	 * @param unitName the name of the compilation unit that would contain the source
+	 *    string, or <code>null</code> if <code>javaProject</code> is also <code>null</code>
+	 * @param project the Java project used to resolve names, or 
+	 *    <code>null</code> if bindings are not resolved
+	 * @param owner the owner of working copies that take precedence over underlying 
+	 *   compilation units
+	 * @return the compilation unit node
+	 * @see ASTNode#getFlags()
+	 * @see ASTNode#MALFORMED
+	 * @see ASTNode#getStartPosition()
+	 * @see ASTNode#getLength()
+	 * @see WorkingCopyOwner
+	 * @since 3.0
+	 */
+	public static CompilationUnit parseCompilationUnit(
+		char[] source,
+		String unitName,
+		IJavaProject project,
+		WorkingCopyOwner owner) {
 			
 		if (source == null) {
 			throw new IllegalArgumentException();
@@ -466,14 +739,26 @@
 			// this just reduces to the other simplest case
 			return parseCompilationUnit(source);
 		}
+		if (owner == null) {
+			throw new IllegalArgumentException();
+		}
 	
+		NameLookup lookup = null;
+		CompilationUnitDeclaration compilationUnitDeclaration = null;
 		try {
-			CompilationUnitDeclaration compilationUnitDeclaration =
+			// set the units to look inside
+			lookup = ((JavaProject)project).getNameLookup();
+			JavaModelManager manager = JavaModelManager.getJavaModelManager();
+			ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+			lookup.setUnitsToLookInside(workingCopies);
+				
+				// parse and resolve
+			compilationUnitDeclaration =
 				CompilationUnitResolver.resolve(
 					source,
 					unitName,
 					project,
-					new AbstractSyntaxTreeVisitorAdapter());
+					false/*don't cleanup*/);
 			ASTConverter converter = new ASTConverter(project.getOptions(true), true);
 			AST ast = new AST();
 			BindingResolver resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope);
@@ -490,6 +775,13 @@
 			 * Therefore all binding resolution will return null.
 			 */
 			return parseCompilationUnit(source);			
+		} finally {
+			if (compilationUnitDeclaration != null) {
+				compilationUnitDeclaration.cleanUp();
+			}
+			if (lookup != null) {
+				lookup.setUnitsToLookInside(null);
+			}
 		}
 	}
 	  	
@@ -520,6 +812,7 @@
 	 * </p>
 	 * 
 	 * @param source the string to be parsed as a Java compilation unit
+	 * @return CompilationUnit
 	 * @see ASTNode#getFlags()
 	 * @see ASTNode#MALFORMED
 	 * @see ASTNode#getStartPosition()
@@ -545,6 +838,300 @@
 	}
 
 	/**
+	 * Parses the source string of the given Java model compilation unit element
+	 * and creates and returns an abridged abstract syntax tree. This method
+	 * differs from
+	 * {@link #parseCompilationUnit(ICompilationUnit,boolean)
+	 * parseCompilationUnit(ICompilationUnit,boolean)} only in 
+	 * that the resulting AST does not have nodes for the entire compilation
+	 * unit. Rather, the AST is only fleshed out for the node that include
+	 * the given source position. This kind of limited AST is sufficient for
+	 * certain purposes but totally unsuitable for others. In places where it
+	 * can be used, the limited AST offers the advantage of being smaller and
+	 * faster to faster to construct.
+	 * </p>
+	 * <p>
+	 * The resulting AST always includes nodes for all of the compilation unit's
+	 * package, import, and top-level type declarations. It also always contains
+	 * nodes for all the body declarations for those top-level types, as well
+	 * as body declarations for any member types. However, some of the body
+	 * declarations may be abridged. In particular, the statements ordinarily
+	 * found in the body of a method declaration node will not be included
+	 * (the block will be empty) unless the source position falls somewhere
+	 * within the source range of that method declaration node. The same is true
+	 * for initializer declarations; the statements ordinarily found in the body
+	 * of initializer node will not be included unless the source position falls
+	 * somewhere within the source range of that initializer declaration node.
+	 * Field declarations are never abridged. Note that the AST for the body of
+	 * that one unabridged method (or initializer) is 100% complete; it has all
+	 * its statements, including any local or anonymous type declarations 
+	 * embedded within them. When the the given position is not located within
+	 * the source range of any body declaration of a top-level type, the AST
+	 * returned is a skeleton that includes nodes for all and only the major
+	 * declarations; this kind of AST is still quite useful because it contains
+	 * all the constructs that introduce names visible to the world outside the
+	 * compilation unit.
+	 * </p>
+	 * <p>
+	 * In all other respects, this method works the same as
+	 * {@link #parseCompilationUnit(ICompilationUnit,boolean)
+	 * parseCompilationUnit(ICompilationUnit,boolean)}.
+	 * The source string is obtained from the Java model element using
+	 * <code>ICompilationUnit.getSource()</code>.
+	 * </p>
+	 * <p>
+	 * The returned compilation unit node is the root node of a new AST.
+	 * Each node in the subtree carries source range(s) information relating back
+	 * to positions in the source string (the source string is not remembered
+	 * with the AST).
+	 * The source range usually begins at the first character of the first token 
+	 * corresponding to the node; leading whitespace and comments are <b>not</b>
+	 * included. The source range usually extends through the last character of
+	 * the last token corresponding to the node; trailing whitespace and
+	 * comments are <b>not</b> included.
+	 * If a syntax error is detected while parsing, the relevant node(s) of the
+	 * tree will be flagged as <code>MALFORMED</code>.
+	 * </p>
+	 * <p>
+	 * If <code>resolveBindings</code> is <code>true</code>, the various names
+	 * and types appearing in the method declaration can be resolved to "bindings"
+	 * by calling the <code>resolveBinding</code> methods. These bindings 
+	 * draw connections between the different parts of a program, and 
+	 * generally afford a more powerful vantage point for clients who wish to
+	 * analyze a program's structure more deeply. These bindings come at a 
+	 * considerable cost in both time and space, however, and should not be
+	 * requested frivolously. The additional space is not reclaimed until the 
+	 * AST, all its nodes, and all its bindings become garbage. So it is very
+	 * important to not retain any of these objects longer than absolutely
+	 * necessary. Bindings are resolved at the time the AST is created. Subsequent
+	 * modifications to the AST do not affect the bindings returned by
+	 * <code>resolveBinding</code> methods in any way; these methods return the
+	 * same binding as before the AST was modified (including modifications
+	 * that rearrange subtrees by reparenting nodes).
+	 * If <code>resolveBindings</code> is <code>false</code>, the analysis 
+	 * does not go beyond parsing and building the tree, and all 
+	 * <code>resolveBinding</code> methods return <code>null</code> from the 
+	 * outset.
+	 * </p>
+	 * 
+	 * @param unit the Java model compilation unit whose source code is to be parsed
+	 * @param position a position into the corresponding body declaration
+	 * @param resolveBindings <code>true</code> if bindings are wanted, 
+	 *   and <code>false</code> if bindings are not of interest
+	 * @return the abridged compilation unit node
+	 * @exception IllegalArgumentException if the given Java element does not 
+	 * exist or if its source string cannot be obtained
+	 * @see ASTNode#getFlags()
+	 * @see ASTNode#MALFORMED
+	 * @see ASTNode#getStartPosition()
+	 * @see ASTNode#getLength()
+	 * @since 3.0
+	 */
+	public static CompilationUnit parsePartialCompilationUnit(
+		ICompilationUnit unit,
+		int position,
+		boolean resolveBindings) {
+			return parsePartialCompilationUnit(unit, position, resolveBindings, DefaultWorkingCopyOwner.PRIMARY);
+	}
+
+	/**
+	/**
+	 * Parses the source string of the given Java model compilation unit element
+	 * and creates and returns an abridged abstract syntax tree. This method
+	 * differs from
+	 * {@link #parseCompilationUnit(ICompilationUnit,boolean,WorkingCopyOwner)
+	 * parseCompilationUnit(ICompilationUnit,boolean,WorkingCopyOwner)} only in 
+	 * that the resulting AST does not have nodes for the entire compilation
+	 * unit. Rather, the AST is only fleshed out for the node that include
+	 * the given source position. This kind of limited AST is sufficient for
+	 * certain purposes but totally unsuitable for others. In places where it
+	 * can be used, the limited AST offers the advantage of being smaller and
+	 * faster to faster to construct.
+	 * </p>
+	 * <p>
+	 * The resulting AST always includes nodes for all of the compilation unit's
+	 * package, import, and top-level type declarations. It also always contains
+	 * nodes for all the body declarations for those top-level types, as well
+	 * as body declarations for any member types. However, some of the body
+	 * declarations may be abridged. In particular, the statements ordinarily
+	 * found in the body of a method declaration node will not be included
+	 * (the block will be empty) unless the source position falls somewhere
+	 * within the source range of that method declaration node. The same is true
+	 * for initializer declarations; the statements ordinarily found in the body
+	 * of initializer node will not be included unless the source position falls
+	 * somewhere within the source range of that initializer declaration node.
+	 * Field declarations are never abridged. Note that the AST for the body of
+	 * that one unabridged method (or initializer) is 100% complete; it has all
+	 * its statements, including any local or anonymous type declarations 
+	 * embedded within them. When the the given position is not located within
+	 * the source range of any body declaration of a top-level type, the AST
+	 * returned is a skeleton that includes nodes for all and only the major
+	 * declarations; this kind of AST is still quite useful because it contains
+	 * all the constructs that introduce names visible to the world outside the
+	 * compilation unit.
+	 * </p>
+	 * <p>
+	 * In all other respects, this method works the same as
+	 * {@link #parseCompilationUnit(ICompilationUnit,boolean,WorkingCopyOwner)
+	 * parseCompilationUnit(ICompilationUnit,boolean,WorkingCopyOwner)}.
+	 * The source string is obtained from the Java model element using
+	 * <code>ICompilationUnit.getSource()</code>.
+	 * </p>
+	 * <p>
+	 * The returned compilation unit node is the root node of a new AST.
+	 * Each node in the subtree carries source range(s) information relating back
+	 * to positions in the source string (the source string is not remembered
+	 * with the AST).
+	 * The source range usually begins at the first character of the first token 
+	 * corresponding to the node; leading whitespace and comments are <b>not</b>
+	 * included. The source range usually extends through the last character of
+	 * the last token corresponding to the node; trailing whitespace and
+	 * comments are <b>not</b> included.
+	 * If a syntax error is detected while parsing, the relevant node(s) of the
+	 * tree will be flagged as <code>MALFORMED</code>.
+	 * </p>
+	 * <p>
+	 * If <code>resolveBindings</code> is <code>true</code>, the various names
+	 * and types appearing in the method declaration can be resolved to "bindings"
+	 * by calling the <code>resolveBinding</code> methods. These bindings 
+	 * draw connections between the different parts of a program, and 
+	 * generally afford a more powerful vantage point for clients who wish to
+	 * analyze a program's structure more deeply. These bindings come at a 
+	 * considerable cost in both time and space, however, and should not be
+	 * requested frivolously. The additional space is not reclaimed until the 
+	 * AST, all its nodes, and all its bindings become garbage. So it is very
+	 * important to not retain any of these objects longer than absolutely
+	 * necessary. Bindings are resolved at the time the AST is created. Subsequent
+	 * modifications to the AST do not affect the bindings returned by
+	 * <code>resolveBinding</code> methods in any way; these methods return the
+	 * same binding as before the AST was modified (including modifications
+	 * that rearrange subtrees by reparenting nodes).
+	 * If <code>resolveBindings</code> is <code>false</code>, the analysis 
+	 * does not go beyond parsing and building the tree, and all 
+	 * <code>resolveBinding</code> methods return <code>null</code> from the 
+	 * outset.
+	 * </p>
+	 * <p>
+	 * When bindings are created, instead of considering compilation units on disk only
+	 * one can supply a <code>WorkingCopyOwner</code>. Working copies owned 
+	 * by this owner take precedence over the underlying compilation units when looking
+	 * up names and drawing the connections.
+	 * </p>
+	 * 
+	 * @param unit the Java model compilation unit whose source code is to be parsed
+	 * @param position a position into the corresponding body declaration
+	 * @param resolveBindings <code>true</code> if bindings are wanted, 
+	 *   and <code>false</code> if bindings are not of interest
+	 * @param owner the owner of working copies that take precedence over underlying 
+	 *   compilation units
+	 * @return the abridged compilation unit node
+	 * @exception IllegalArgumentException if the given Java element does not 
+	 * exist or the source range is null or if its source string cannot be obtained
+	 * @see ASTNode#getFlags()
+	 * @see ASTNode#MALFORMED
+	 * @see ASTNode#getStartPosition()
+	 * @see ASTNode#getLength()
+	 * @since 3.0
+	 */
+	public static CompilationUnit parsePartialCompilationUnit(
+		ICompilationUnit unit,
+		int position,
+		boolean resolveBindings,
+		WorkingCopyOwner owner) {
+				
+		if (unit == null) {
+			throw new IllegalArgumentException();
+		}
+		if (owner == null) {
+			throw new IllegalArgumentException();
+		}
+		
+		char[] source = null;
+		try {
+			source = unit.getSource().toCharArray();
+		} catch(JavaModelException e) {
+			// no source, then we cannot build anything
+			throw new IllegalArgumentException();
+		}
+
+		NodeSearcher searcher = new NodeSearcher(position);
+
+		final Map options = unit.getJavaProject().getOptions(true);
+		if (resolveBindings) {
+			NameLookup lookup = null;
+			CompilationUnitDeclaration compilationUnitDeclaration = null;
+			try {
+				// set the units to look inside
+				lookup = ((JavaProject)unit.getJavaProject()).getNameLookup();
+				JavaModelManager manager = JavaModelManager.getJavaModelManager();
+				ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+				lookup.setUnitsToLookInside(workingCopies);
+
+				// parse and resolve
+				compilationUnitDeclaration = CompilationUnitResolver.resolve(
+					unit,
+					searcher,
+					false/*don't cleanup*/,
+					source);
+				
+				ASTConverter converter = new ASTConverter(options, true);
+				AST ast = new AST();
+				BindingResolver resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope);
+				ast.setBindingResolver(resolver);
+				converter.setAST(ast);
+			
+				CompilationUnit compilationUnit = converter.convert(compilationUnitDeclaration, source);
+				compilationUnit.setLineEndTable(compilationUnitDeclaration.compilationResult.lineSeparatorPositions);
+				resolver.storeModificationCount(ast.modificationCount());
+				return compilationUnit;
+			} catch(JavaModelException e) {
+				/* if a JavaModelException is thrown trying to retrieve the name environment
+				 * then we simply do a parsing without creating bindings.
+				 * Therefore all binding resolution will return null.
+				 */
+				CompilationUnitDeclaration compilationUnitDeclaration2 = CompilationUnitResolver.parse(
+					source,
+					searcher,
+					options);
+				
+				ASTConverter converter = new ASTConverter(options, false);
+				AST ast = new AST();
+				final BindingResolver resolver = new BindingResolver();
+				ast.setBindingResolver(resolver);
+				converter.setAST(ast);
+	
+				CompilationUnit compilationUnit = converter.convert(compilationUnitDeclaration2, source);
+				compilationUnit.setLineEndTable(compilationUnitDeclaration2.compilationResult.lineSeparatorPositions);
+				resolver.storeModificationCount(ast.modificationCount());
+				return compilationUnit;
+			} finally {
+				if (compilationUnitDeclaration != null) {
+					compilationUnitDeclaration.cleanUp();
+				}
+				if (lookup != null) {
+					lookup.setUnitsToLookInside(null);
+				}
+			}
+		} else {
+			CompilationUnitDeclaration compilationUnitDeclaration = CompilationUnitResolver.parse(
+				source,
+				searcher,
+				options);
+			
+			ASTConverter converter = new ASTConverter(options, false);
+			AST ast = new AST();
+			final BindingResolver resolver = new BindingResolver();
+			ast.setBindingResolver(resolver);
+			converter.setAST(ast);
+
+			CompilationUnit compilationUnit = converter.convert(compilationUnitDeclaration, source);
+			compilationUnit.setLineEndTable(compilationUnitDeclaration.compilationResult.lineSeparatorPositions);
+			resolver.storeModificationCount(ast.modificationCount());
+			return compilationUnit;
+		}
+	}
+	
+	/**
 	 * The binding resolver for this AST. Initially a binding resolver that
 	 * does not resolve names at all.
 	 */
@@ -577,14 +1164,16 @@
 	 * <li><code>"float"</code></li>
 	 * <li><code>"double"</code></li>
 	 * <li><code>"void"</code></li>
+	 * <li><code>"java.lang.Class"</code></li>
+	 * <li><code>"java.lang.Cloneable"</code></li>
+	 * <li><code>"java.lang.Error"</code></li>
+	 * <li><code>"java.lang.Exception"</code></li>
 	 * <li><code>"java.lang.Object"</code></li>
+	 * <li><code>"java.lang.RuntimeException"</code></li>
 	 * <li><code>"java.lang.String"</code></li>
 	 * <li><code>"java.lang.StringBuffer"</code></li>
 	 * <li><code>"java.lang.Throwable"</code></li>
-	 * <li><code>"java.lang.Exception"</code></li>
-	 * <li><code>"java.lang.RuntimeException"</code></li>
-	 * <li><code>"java.lang.Error"</code></li>
-	 * <li><code>"java.lang.Class"</code></li>
+	 * <li><code>"java.io.Serializable"</code></li>
 	 * </ul>
 	 * </p>
 	 * 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
index 9d3e69c..7449f11 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
@@ -20,7 +20,8 @@
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
-import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.IConstants;
 import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
@@ -43,7 +44,7 @@
 					true /*comment*/,
 					false /*whitespace*/,
 					false /*nls*/,
-					JavaCore.VERSION_1_4.equals(options.get(JavaCore.COMPILER_SOURCE)) /*assert*/, 
+					JavaCore.VERSION_1_4.equals(options.get(JavaCore.COMPILER_SOURCE)) ? ClassFileConstants.JDK1_4 : ClassFileConstants.JDK1_3 /*sourceLevel*/, 
 					null /*taskTags*/,
 					null/*taskPriorities*/);
 	}
@@ -52,7 +53,7 @@
 		this.ast = ast;
 	}
 	
-	public CompilationUnit convert(CompilationUnitDeclaration unit, char[] source) {
+	public CompilationUnit convert(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration unit, char[] source) {
 		this.compilationUnitSource = source;
 		scanner.setSource(source);
 		CompilationUnit compilationUnit = this.ast.newCompilationUnit();
@@ -65,7 +66,7 @@
 			PackageDeclaration packageDeclaration = convertPackage(unit);
 			compilationUnit.setPackage(packageDeclaration);
 		}
-		ImportReference[] imports = unit.imports;
+		org.eclipse.jdt.internal.compiler.ast.ImportReference[] imports = unit.imports;
 		if (imports != null) {
 			int importLength = imports.length;
 			for (int i = 0; i < importLength; i++) {
@@ -90,8 +91,8 @@
 		return compilationUnit;
 	}
 	
-	public PackageDeclaration convertPackage(CompilationUnitDeclaration compilationUnitDeclaration) {
-		ImportReference importReference = compilationUnitDeclaration.currentPackage;
+	public PackageDeclaration convertPackage(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration compilationUnitDeclaration) {
+		org.eclipse.jdt.internal.compiler.ast.ImportReference importReference = compilationUnitDeclaration.currentPackage;
 		PackageDeclaration packageDeclaration = this.ast.newPackageDeclaration();
 		char[][] tokens = importReference.tokens;
 		int length = importReference.tokens.length;
@@ -114,7 +115,7 @@
 		return packageDeclaration;
 	}
 	
-	public ImportDeclaration convertImport(ImportReference importReference) {
+	public ImportDeclaration convertImport(org.eclipse.jdt.internal.compiler.ast.ImportReference importReference) {
 		ImportDeclaration importDeclaration = this.ast.newImportDeclaration();
 		boolean onDemand = importReference.onDemand;
 		char[][] tokens = importReference.tokens;
@@ -141,8 +142,8 @@
 	public TypeDeclaration convert(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
 		TypeDeclaration typeDecl = this.ast.newTypeDeclaration();
 		int modifiers = typeDeclaration.modifiers;
-		modifiers &= ~org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers.AccInterface; // remove AccInterface flags
-		modifiers &= org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers.AccJustFlag;
+		modifiers &= ~IConstants.AccInterface; // remove AccInterface flags
+		modifiers &= CompilerModifiers.AccJustFlag;
 		/**
 		 * http://dev.eclipse.org/bugs/show_bug.cgi?id=13233
 		 * This handles cases where the parser built nodes with invalid modifiers.
@@ -171,7 +172,7 @@
 			typeDecl.setSuperclass(convert(typeDeclaration.superclass));
 		}
 		
-		TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+		org.eclipse.jdt.internal.compiler.ast.TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
 		if (superInterfaces != null) {
 			for (int index = 0, length = superInterfaces.length; index < length; index++) {
 				typeDecl.superInterfaces().add(convert(superInterfaces[index]));
@@ -180,19 +181,19 @@
 		
 		buildBodyDeclarations(typeDeclaration, typeDecl);
 		setJavaDocComment(typeDecl);
-		if (resolveBindings) {
+		if (this.resolveBindings) {
 			recordNodes(typeDecl, typeDeclaration);
 			recordNodes(typeName, typeDeclaration);
 			typeDecl.resolveBinding();
 		}
 		return typeDecl;
 	}
-
+	
 	private void buildBodyDeclarations(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration, TypeDeclaration typeDecl) {
 		// add body declaration in the lexical order
-		MemberTypeDeclaration[] members = typeDeclaration.memberTypes;
+		org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] members = typeDeclaration.memberTypes;
 		org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = typeDeclaration.fields;
-		AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+		org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = typeDeclaration.methods;
 		
 		int fieldsLength = fields == null? 0 : fields.length;
 		int methodsLength = methods == null? 0 : methods.length;
@@ -205,8 +206,8 @@
 			|| (membersIndex < membersLength)
 			|| (methodsIndex < methodsLength)) {
 			org.eclipse.jdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
-			AbstractMethodDeclaration nextMethodDeclaration = null;
-			MemberTypeDeclaration nextMemberDeclaration = null;
+			org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
 		
 			int position = Integer.MAX_VALUE;
 			int nextDeclarationType = -1;
@@ -273,31 +274,31 @@
 	
 	private void checkAndAddMultipleLocalDeclaration(org.eclipse.jdt.internal.compiler.ast.Statement[] stmts, int index, List blockStatements) {
 		if (index > 0
-		    && stmts[index - 1] instanceof LocalDeclaration) {
-		    	LocalDeclaration local1 = (LocalDeclaration) stmts[index - 1];
-		    	LocalDeclaration local2 = (LocalDeclaration) stmts[index];
+		    && stmts[index - 1] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
+		    	org.eclipse.jdt.internal.compiler.ast.LocalDeclaration local1 = (org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) stmts[index - 1];
+		    	org.eclipse.jdt.internal.compiler.ast.LocalDeclaration local2 = (org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) stmts[index];
 			   if (local1.declarationSourceStart == local2.declarationSourceStart) {
 					// we have a multiple local declarations
 					// We retrieve the existing VariableDeclarationStatement to add the new VariableDeclarationFragment
 					VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) blockStatements.get(blockStatements.size() - 1);
-					variableDeclarationStatement.fragments().add(convertToVariableDeclarationFragment((LocalDeclaration)stmts[index]));
+					variableDeclarationStatement.fragments().add(convertToVariableDeclarationFragment((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
 			   } else {
 					// we can create a new FieldDeclaration
-					blockStatements.add(convertToVariableDeclarationStatement((LocalDeclaration)stmts[index]));
+					blockStatements.add(convertToVariableDeclarationStatement((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
 			   }
 		} else {
 			// we can create a new FieldDeclaration
-			blockStatements.add(convertToVariableDeclarationStatement((LocalDeclaration)stmts[index]));
+			blockStatements.add(convertToVariableDeclarationStatement((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)stmts[index]));
 		}
 	}
 
-	public Name convert(TypeReference typeReference) {
+	public Name convert(org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference) {
 		char[][] typeName = typeReference.getTypeName();
 		int length = typeName.length;
 		Name name = null;
 		if (length > 1) {
 			// QualifiedName
-			QualifiedTypeReference qualifiedTypeReference = (QualifiedTypeReference) typeReference;
+			org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference qualifiedTypeReference = (org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference;
 			long[] positions = qualifiedTypeReference.sourcePositions;			
 			name = setQualifiedNameNameAndSourceRanges(typeName, positions, typeReference);
 		} else {
@@ -310,7 +311,7 @@
 		return name;
 	}
 	
-	public SimpleName convert(SingleNameReference nameReference) {
+	public SimpleName convert(org.eclipse.jdt.internal.compiler.ast.SingleNameReference nameReference) {
 		SimpleName name = this.ast.newSimpleName(new String(nameReference.token));		
 		if (this.resolveBindings) {
 			recordNodes(name, nameReference);
@@ -319,13 +320,11 @@
 		return name;
 	}
 
-	public Name convert(QualifiedNameReference nameReference) {
-		char[][] typeName = nameReference.tokens;
-		long[] positions = scanAllIdentifiersPositions(nameReference.sourceStart, nameReference.sourceEnd, typeName.length);
-		return setQualifiedNameNameAndSourceRanges(typeName, positions, nameReference);
+	public Name convert(org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference nameReference) {
+		return setQualifiedNameNameAndSourceRanges(nameReference.tokens, nameReference.sourcePositions, nameReference);
 	}
 
-	private QualifiedName setQualifiedNameNameAndSourceRanges(char[][] typeName, long[] positions, AstNode node) {
+	private QualifiedName setQualifiedNameNameAndSourceRanges(char[][] typeName, long[] positions, org.eclipse.jdt.internal.compiler.ast.ASTNode node) {
 		int length = typeName.length;
 		SimpleName firstToken = this.ast.newSimpleName(new String(typeName[0]));
 		firstToken.index = length - 1;
@@ -374,14 +373,14 @@
 		return name;
 	}
 	
-	public Expression convert(ThisReference reference) {
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.ThisReference reference) {
 		if (reference.isImplicitThis()) {
 			// There is no source associated with an implicit this
 			return null;
-		} else if (reference instanceof QualifiedSuperReference) {
-			return convert((QualifiedSuperReference) reference);
-		} else if (reference instanceof QualifiedThisReference) {
-			return convert((QualifiedThisReference) reference);
+		} else if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) reference);
+		} else if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference) reference);
 		}  else {
 			ThisExpression thisExpression = this.ast.newThisExpression();
 			thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
@@ -393,7 +392,7 @@
 		}
 	}
 
-	public ThisExpression convert(QualifiedThisReference reference) {
+	public ThisExpression convert(org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference reference) {
 		ThisExpression thisExpression = this.ast.newThisExpression();
 		thisExpression.setSourceRange(reference.sourceStart, reference.sourceEnd - reference.sourceStart + 1);
 		thisExpression.setQualifier(convert(reference.qualification));
@@ -404,11 +403,11 @@
 		return thisExpression;
 	}
 
-	public Name convert(QualifiedSuperReference reference) {
+	public Name convert(org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference reference) {
 		return convert(reference.qualification);
 	}
 
-	public ArrayAccess convert(ArrayReference reference) {
+	public ArrayAccess convert(org.eclipse.jdt.internal.compiler.ast.ArrayReference reference) {
 		ArrayAccess arrayAccess = this.ast.newArrayAccess();
 		if (this.resolveBindings) {
 			recordNodes(arrayAccess, reference);
@@ -419,14 +418,14 @@
 		return arrayAccess;
 	}
 	
-	public Expression convert(FieldReference reference) {
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.FieldReference reference) {
 		if (reference.receiver.isSuper()) {
 			SuperFieldAccess superFieldAccess = this.ast.newSuperFieldAccess();
 			if (this.resolveBindings) {
 				recordNodes(superFieldAccess, reference);
 			}
-			if (reference.receiver instanceof QualifiedSuperReference) {
-				Name qualifier = convert((QualifiedSuperReference) reference.receiver);
+			if (reference.receiver instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) {
+				Name qualifier = convert((org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) reference.receiver);
 				superFieldAccess.setQualifier(qualifier);
 				if (this.resolveBindings) {
 					recordNodes(qualifier, reference.receiver);
@@ -462,82 +461,33 @@
 		}
 	}
 	
-	public Expression convert(Reference reference) {
-		if (reference instanceof NameReference) {
-			return convert((NameReference) reference);
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.Reference reference) {
+		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.NameReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.NameReference) reference);
 		}
-		if (reference instanceof ThisReference) {
-			return convert((ThisReference) reference);
+		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.ThisReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ThisReference) reference);
 		}
-		if (reference instanceof ArrayReference) {
-			return convert((ArrayReference) reference);
+		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.ArrayReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ArrayReference) reference);
 		}
-		if (reference instanceof FieldReference) {
-			return convert((FieldReference) reference);
+		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.FieldReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.FieldReference) reference);
 		}
 		throw new IllegalArgumentException("Not yet implemented: convert(" + reference.getClass() + ")");//$NON-NLS-1$//$NON-NLS-2$
 	}
 						
-	public Name convert(NameReference reference) {
-		if (reference instanceof QualifiedNameReference) {
-			return convert((QualifiedNameReference) reference);
+	public Name convert(org.eclipse.jdt.internal.compiler.ast.NameReference reference) {
+		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference) reference);
 		}
-		if (reference instanceof SingleNameReference) {
-			return convert((SingleNameReference) reference);
+		if (reference instanceof org.eclipse.jdt.internal.compiler.ast.SingleNameReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.SingleNameReference) reference);
 		}
 		throw new IllegalArgumentException("Not yet implemented: convert(" + reference.getClass() + ")");//$NON-NLS-1$//$NON-NLS-2$
 	}	
 
-	public TypeDeclaration convert(MemberTypeDeclaration typeDeclaration) {
-		TypeDeclaration typeDecl = this.ast.newTypeDeclaration();
-		int modifiers = typeDeclaration.modifiers;
-		modifiers &= ~org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers.AccInterface; // remove AccInterface flags
-		modifiers &= org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers.AccJustFlag;
-		/**
-		 * http://dev.eclipse.org/bugs/show_bug.cgi?id=13233
-		 * This handles cases where the parser built nodes with invalid modifiers.
-		 */
-		try {
-			// AccJustFlag doesn't flush Modifier.TRANSIENT or Modifier.VOLATILE.
-			// Therefore we need to handle these cases
-			typeDecl.setModifiers(modifiers);
-		} catch(IllegalArgumentException e) {
-			int legalModifiers =
-				Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED
-				| Modifier.STATIC | Modifier.FINAL | Modifier.ABSTRACT
-				| Modifier.STRICTFP;
-			typeDecl.setModifiers(modifiers & legalModifiers);
-			typeDecl.setFlags(ASTNode.MALFORMED);
-		}
-		typeDecl.setInterface(typeDeclaration.isInterface());
-		SimpleName typeName = this.ast.newSimpleName(new String(typeDeclaration.name));
-		typeName.setSourceRange(typeDeclaration.sourceStart, typeDeclaration.sourceEnd - typeDeclaration.sourceStart + 1);
-		typeDecl.setName(typeName);
-		typeDecl.setSourceRange(typeDeclaration.declarationSourceStart, typeDeclaration.bodyEnd - typeDeclaration.declarationSourceStart + 1);
-		
-		// need to set the superclass and super interfaces here since we cannot distinguish them at
-		// the type references level.
-		if (typeDeclaration.superclass != null) {
-			typeDecl.setSuperclass(convert(typeDeclaration.superclass));
-		}
-		
-		TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
-		if (superInterfaces != null) {
-			for (int index = 0, length = superInterfaces.length; index < length; index++) {
-				typeDecl.superInterfaces().add(convert(superInterfaces[index]));
-			}
-		}
-		buildBodyDeclarations(typeDeclaration, typeDecl);
-		setJavaDocComment(typeDecl);
-		if (this.resolveBindings) {
-			recordNodes(typeDecl, typeDeclaration);
-			recordNodes(typeName, typeDeclaration);
-			typeDecl.resolveBinding();
-		}
-		return typeDecl;
-	}
-
-	private void completeRecord(ArrayType arrayType, AstNode astNode) {
+	private void completeRecord(ArrayType arrayType, org.eclipse.jdt.internal.compiler.ast.ASTNode astNode) {
 		ArrayType array = arrayType;
 		int dimensions = array.getDimensions();
 		for (int i = 0; i < dimensions; i++) {
@@ -549,14 +499,14 @@
 		}
 	}
 	
-	public Type convertType(TypeReference typeReference) {
+	public Type convertType(org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference) {
 		Type type = null;				
 		int sourceStart = -1;
 		int length = 0;
 		int dimensions = typeReference.dimensions();
-		if (typeReference instanceof SingleTypeReference) {
+		if (typeReference instanceof org.eclipse.jdt.internal.compiler.ast.SingleTypeReference) {
 			// this is either an ArrayTypeReference or a SingleTypeReference
-			char[] name = ((SingleTypeReference) typeReference).getTypeName()[0];
+			char[] name = ((org.eclipse.jdt.internal.compiler.ast.SingleTypeReference) typeReference).getTypeName()[0];
 			sourceStart = typeReference.sourceStart;
 			length = typeReference.sourceEnd - typeReference.sourceStart + 1;
 			if (dimensions != 0) {
@@ -607,9 +557,9 @@
 				}
 			}
 		} else {
-			char[][] name = ((QualifiedTypeReference) typeReference).getTypeName();
+			char[][] name = ((org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference).getTypeName();
 			int nameLength = name.length;
-			long[] positions = ((QualifiedTypeReference) typeReference).sourcePositions;
+			long[] positions = ((org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference) typeReference).sourcePositions;
 			sourceStart = (int)(positions[0]>>>32);
 			length = (int)(positions[nameLength - 1] & 0xFFFFFFFF) - sourceStart + 1;
 			Name qualifiedName = this.setQualifiedNameNameAndSourceRanges(name, positions, typeReference);
@@ -638,7 +588,7 @@
 		return type;
 	}
 		
-	public MethodDeclaration convert(AbstractMethodDeclaration methodDeclaration) {
+	public MethodDeclaration convert(org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration) {
 		MethodDeclaration methodDecl = this.ast.newMethodDeclaration();
 		/**
 		 * http://dev.eclipse.org/bugs/show_bug.cgi?id=13233
@@ -662,31 +612,31 @@
 		int end = retrieveIdentifierEndPosition(start, methodDeclaration.sourceEnd);
 		methodName.setSourceRange(start, end - start + 1);
 		methodDecl.setName(methodName);
-		TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
+		org.eclipse.jdt.internal.compiler.ast.TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
 		if (thrownExceptions != null) {
 			int thrownExceptionsLength = thrownExceptions.length;
 			for (int i = 0; i < thrownExceptionsLength; i++) {
 				methodDecl.thrownExceptions().add(convert(thrownExceptions[i]));
 			}
 		}
-		Argument[] parameters = methodDeclaration.arguments;
+		org.eclipse.jdt.internal.compiler.ast.Argument[] parameters = methodDeclaration.arguments;
 		if (parameters != null) {
 			int parametersLength = parameters.length;
 			for (int i = 0; i < parametersLength; i++) {
 				methodDecl.parameters().add(convert(parameters[i]));
 			}
 		}
-		ExplicitConstructorCall explicitConstructorCall = null;
+		org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall explicitConstructorCall = null;
 		if (isConstructor) {
 			// set the return type to VOID
 			PrimitiveType returnType = this.ast.newPrimitiveType(PrimitiveType.VOID);
 			returnType.setSourceRange(methodDeclaration.sourceStart, 0);
 			methodDecl.setReturnType(returnType);
-			ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+			org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration constructorDeclaration = (org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration) methodDeclaration;
 			explicitConstructorCall = constructorDeclaration.constructorCall;
 		} else {
 			org.eclipse.jdt.internal.compiler.ast.MethodDeclaration method = (org.eclipse.jdt.internal.compiler.ast.MethodDeclaration) methodDeclaration;
-			TypeReference typeReference = method.returnType;
+			org.eclipse.jdt.internal.compiler.ast.TypeReference typeReference = method.returnType;
 			if (typeReference != null) {
 				Type returnType = convertType(typeReference);
 				// get the positions of the right parenthesis
@@ -699,39 +649,73 @@
 		int declarationSourceStart = methodDeclaration.declarationSourceStart;
 		int declarationSourceEnd = methodDeclaration.bodyEnd;
 		methodDecl.setSourceRange(declarationSourceStart, declarationSourceEnd - declarationSourceStart + 1);
-		retrieveRightBraceOrSemiColonPosition(methodDecl);
-		
-		org.eclipse.jdt.internal.compiler.ast.Statement[] statements = methodDeclaration.statements;
-		
-		if (statements != null || explicitConstructorCall != null) {
-			Block block = this.ast.newBlock();
-			start = retrieveStartBlockPosition(methodDeclaration.sourceStart, declarationSourceEnd);
-			end = retrieveEndBlockPosition(methodDeclaration.sourceStart, this.compilationUnitSource.length);
-			block.setSourceRange(start, end - start + 1);
-			if (explicitConstructorCall != null && explicitConstructorCall.accessMode != ExplicitConstructorCall.ImplicitSuper) {
-				block.statements().add(convert(explicitConstructorCall));
-			}
-			int statementsLength = statements == null ? 0 : statements.length;
-			for (int i = 0; i < statementsLength; i++) {
-				if (statements[i] instanceof LocalDeclaration) {
-					checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
-				} else {
-					block.statements().add(convert(statements[i]));
+		int closingPosition = retrieveRightBraceOrSemiColonPosition(methodDecl, methodDeclaration);
+		if (closingPosition != -1) {
+			int startPosition = methodDecl.getStartPosition();
+			methodDecl.setSourceRange(startPosition, closingPosition - startPosition);
+
+			org.eclipse.jdt.internal.compiler.ast.Statement[] statements = methodDeclaration.statements;
+			
+			if (statements != null || explicitConstructorCall != null) {
+				start = retrieveStartBlockPosition(methodDeclaration.sourceStart, declarationSourceEnd);
+				end = retrieveEndBlockPosition(methodDeclaration.sourceStart, methodDeclaration.declarationSourceEnd);
+				if (start != -1 && end != -1) {
+					Block block = this.ast.newBlock();
+					block.setSourceRange(start, end - start + 1);
+					if (explicitConstructorCall != null && explicitConstructorCall.accessMode != org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall.ImplicitSuper) {
+						block.statements().add(convert(explicitConstructorCall));
+					}
+					int statementsLength = statements == null ? 0 : statements.length;
+					for (int i = 0; i < statementsLength; i++) {
+						if (statements[i] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
+							checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
+						} else {
+							block.statements().add(convert(statements[i]));
+						}
+					}
+					methodDecl.setBody(block);
+				}
+			} else if (!methodDeclaration.isNative() && !methodDeclaration.isAbstract()) {
+				start = retrieveStartBlockPosition(methodDeclaration.sourceStart, declarationSourceEnd);
+				end = retrieveEndBlockPosition(methodDeclaration.sourceStart, methodDeclaration.declarationSourceEnd);
+				if (start != -1 && end != -1) {
+					/*
+					 * start or end can be equal to -1 if we have an interface's method.
+					 */
+					Block block = this.ast.newBlock();
+					block.setSourceRange(start, end - start + 1);
+					methodDecl.setBody(block);
 				}
 			}
-			methodDecl.setBody(block);
-		} else if (!methodDeclaration.isNative() && !methodDeclaration.isAbstract()) {
-			start = retrieveStartBlockPosition(methodDeclaration.sourceStart, declarationSourceEnd);
-			end = retrieveEndBlockPosition(methodDeclaration.sourceStart, this.compilationUnitSource.length);
-			if (start != -1 && end != -1) {
-				/*
-				 * start or end can be equal to -1 if we have an interface's method.
-				 */
-				Block block = this.ast.newBlock();
-				block.setSourceRange(start, end - start + 1);
-				methodDecl.setBody(block);
-			}
+		} else {
+			// syntax error in this method declaration
+			if (!methodDeclaration.isNative() && !methodDeclaration.isAbstract()) {
+				start = retrieveStartBlockPosition(methodDeclaration.sourceStart, declarationSourceEnd);
+				end = methodDeclaration.bodyEnd;
+				// try to get the best end position
+				IProblem[] problems = methodDeclaration.compilationResult().problems;
+				if (problems != null) {
+					for (int i = 0, max = methodDeclaration.compilationResult().problemCount; i < max; i++) {
+						IProblem currentProblem = problems[i];
+						if (currentProblem.getSourceStart() == start && currentProblem.getID() == IProblem.ParsingErrorInsertToComplete) {
+							end = currentProblem.getSourceEnd();
+							break;
+						}
+					}
+				}
+				int startPosition = methodDecl.getStartPosition();
+				methodDecl.setSourceRange(startPosition, end - startPosition + 1);
+				if (start != -1 && end != -1) {
+					/*
+					 * start or end can be equal to -1 if we have an interface's method.
+					 */
+					Block block = this.ast.newBlock();
+					block.setSourceRange(start, end - start + 1);
+					methodDecl.setBody(block);
+				}
+			}			
 		}
+		
 		setJavaDocComment(methodDecl);
 		if (this.resolveBindings) {
 			recordNodes(methodDecl, methodDeclaration);
@@ -742,21 +726,21 @@
 	}	
 
 	public Expression convert(org.eclipse.jdt.internal.compiler.ast.Expression expression) {
-		if ((expression.bits & AstNode.ParenthesizedMASK) != 0) {
+		if ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) != 0) {
 			return convertToParenthesizedExpression(expression);
 		}
 		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CastExpression) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.CastExpression) expression);
 		}
 		// switch between all types of expression
-		if (expression instanceof ArrayAllocationExpression) {
-			return convert((ArrayAllocationExpression) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression) expression);
 		}
-		if (expression instanceof QualifiedAllocationExpression) {
-			return convert((QualifiedAllocationExpression) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression) expression);
 		}
-		if (expression instanceof AllocationExpression) {
-			return convert((AllocationExpression) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.AllocationExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.AllocationExpression) expression);
 		}
 		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ArrayInitializer) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.ArrayInitializer) expression);
@@ -767,80 +751,80 @@
 		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.PostfixExpression) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.PostfixExpression) expression);
 		}
-		if (expression instanceof CompoundAssignment) {
-			return convert((CompoundAssignment) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CompoundAssignment) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.CompoundAssignment) expression);
 		}
 		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Assignment) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.Assignment) expression);
 		}
-		if (expression instanceof ClassLiteralAccess) {
-			return convert((ClassLiteralAccess) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess) expression);
 		}
-		if (expression instanceof FalseLiteral) {
-			return convert((FalseLiteral) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.FalseLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.FalseLiteral) expression);
 		}
-		if (expression instanceof TrueLiteral) {
-			return convert((TrueLiteral) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TrueLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.TrueLiteral) expression);
 		}
 		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.NullLiteral) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.NullLiteral) expression);
 		}
-		if (expression instanceof CharLiteral) {
-			return convert((CharLiteral) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.CharLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.CharLiteral) expression);
 		}
-		if (expression instanceof DoubleLiteral) {
-			return convert((DoubleLiteral) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.DoubleLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.DoubleLiteral) expression);
 		}
-		if (expression instanceof FloatLiteral) {
-			return convert((FloatLiteral) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.FloatLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.FloatLiteral) expression);
 		}
-		if (expression instanceof IntLiteralMinValue) {
-			return convert((IntLiteralMinValue) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue) expression);
 		}
-		if (expression instanceof IntLiteral) {
-			return convert((IntLiteral) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.IntLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.IntLiteral) expression);
 		}
-		if (expression instanceof LongLiteralMinValue) {
-			return convert((LongLiteralMinValue) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue) expression);
 		}				
-		if (expression instanceof LongLiteral) {
-			return convert((LongLiteral) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.LongLiteral) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.LongLiteral) expression);
 		}
 		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral) {
-			return convert((ExtendedStringLiteral) expression);
+			return convert((org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral) expression);
 		}	
 		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.StringLiteral) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.StringLiteral) expression);
 		}				
-		if (expression instanceof AND_AND_Expression) {
-			return convert((AND_AND_Expression) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression) expression);
 		}				
-		if (expression instanceof OR_OR_Expression) {
-			return convert((OR_OR_Expression) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression) expression);
 		}				
-		if (expression instanceof EqualExpression) {
-			return convert((EqualExpression) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.EqualExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.EqualExpression) expression);
 		}				
-		if (expression instanceof BinaryExpression) {
-			return convert((BinaryExpression) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) expression);
 		}				
 		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression) expression);
 		}				
-		if (expression instanceof UnaryExpression) {
-			return convert((UnaryExpression) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.UnaryExpression) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.UnaryExpression) expression);
 		}				
 		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.ConditionalExpression) expression);
 		}				
-		if (expression instanceof MessageSend) {
-			return convert((MessageSend) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.MessageSend) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.MessageSend) expression);
 		}				
-		if (expression instanceof Reference) {
-			return convert((Reference) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.Reference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.Reference) expression);
 		}
-		if (expression instanceof TypeReference) {
-			return convert((TypeReference) expression);
+		if (expression instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.TypeReference) expression);
 		}				
 		throw new IllegalArgumentException("Not yet implemented: convert(" + expression.getClass() + ")");//$NON-NLS-1$//$NON-NLS-2$
 	}
@@ -854,14 +838,14 @@
 		adjustSourcePositionsForParent(expression);
 		removeExtraBlanks(expression);
 		// decrement the number of parenthesis
-		int numberOfParenthesis = (expression.bits & AstNode.ParenthesizedMASK) >> AstNode.ParenthesizedSHIFT;
-		expression.bits &= ~AstNode.ParenthesizedMASK;
-		expression.bits |= (numberOfParenthesis - 1) << AstNode.ParenthesizedSHIFT;
+		int numberOfParenthesis = (expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
+		expression.bits &= ~org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK;
+		expression.bits |= (numberOfParenthesis - 1) << org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedSHIFT;
 		parenthesizedExpression.setExpression(convert(expression));
 		return parenthesizedExpression;
 	}
 	
-	public ClassInstanceCreation convert(AllocationExpression expression) {
+	public ClassInstanceCreation convert(org.eclipse.jdt.internal.compiler.ast.AllocationExpression expression) {
 		ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
 		if (this.resolveBindings) {
 			recordNodes(classInstanceCreation, expression);
@@ -879,39 +863,11 @@
 		return classInstanceCreation;
 	}
 	
-	public ClassInstanceCreation convert(AnonymousLocalTypeDeclaration expression) {
-		ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
-		classInstanceCreation.setName(convert(expression.allocation.type));
-		if (expression.allocation.enclosingInstance != null) {
-			classInstanceCreation.setExpression(convert(expression.allocation.enclosingInstance));
-		}
-		int declarationSourceStart = expression.allocation.sourceStart;
-		classInstanceCreation.setSourceRange(declarationSourceStart, expression.bodyEnd - declarationSourceStart + 1);
-		org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = expression.allocation.arguments;
-		if (arguments != null) {
-			int length = arguments.length;
-			for (int i = 0; i < length; i++) {
-				classInstanceCreation.arguments().add(convert(arguments[i]));
-			}
-		}
-		AnonymousClassDeclaration anonymousClassDeclaration = this.ast.newAnonymousClassDeclaration();
-		int start = retrieveStartBlockPosition(declarationSourceStart, expression.bodyEnd);
-		anonymousClassDeclaration.setSourceRange(start, expression.bodyEnd - start + 1);
-		classInstanceCreation.setAnonymousClassDeclaration(anonymousClassDeclaration);
-		buildBodyDeclarations(expression, anonymousClassDeclaration);
-		if (this.resolveBindings) {
-			recordNodes(classInstanceCreation, expression);
-			recordNodes(anonymousClassDeclaration, expression);
-			classInstanceCreation.resolveTypeBinding();
-		}
-		return classInstanceCreation;
-	}
-
-	private void buildBodyDeclarations(AnonymousLocalTypeDeclaration expression, AnonymousClassDeclaration anonymousClassDeclaration) {
+	private void buildBodyDeclarations(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration expression, AnonymousClassDeclaration anonymousClassDeclaration) {
 		// add body declaration in the lexical order
-		MemberTypeDeclaration[] members = expression.memberTypes;
+		org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] members = expression.memberTypes;
 		org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = expression.fields;
-		AbstractMethodDeclaration[] methods = expression.methods;
+		org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration[] methods = expression.methods;
 		
 		int fieldsLength = fields == null? 0 : fields.length;
 		int methodsLength = methods == null? 0 : methods.length;
@@ -924,8 +880,8 @@
 			|| (membersIndex < membersLength)
 			|| (methodsIndex < methodsLength)) {
 			org.eclipse.jdt.internal.compiler.ast.FieldDeclaration nextFieldDeclaration = null;
-			AbstractMethodDeclaration nextMethodDeclaration = null;
-			MemberTypeDeclaration nextMemberDeclaration = null;
+			org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration nextMethodDeclaration = null;
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration nextMemberDeclaration = null;
 		
 			int position = Integer.MAX_VALUE;
 			int nextDeclarationType = -1;
@@ -968,7 +924,7 @@
 		}
 	}
 
-	public ArrayCreation convert(ArrayAllocationExpression expression) {
+	public ArrayCreation convert(org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression expression) {
 		ArrayCreation arrayCreation = this.ast.newArrayCreation();
 		if (this.resolveBindings) {
 			recordNodes(arrayCreation, expression);
@@ -1018,7 +974,7 @@
 		return arrayCreation;
 	}
 
-	public SingleVariableDeclaration convert(Argument argument) {
+	public SingleVariableDeclaration convert(org.eclipse.jdt.internal.compiler.ast.Argument argument) {
 		SingleVariableDeclaration variableDecl = this.ast.newSingleVariableDeclaration();
 		/**
 		 * http://dev.eclipse.org/bugs/show_bug.cgi?id=13233
@@ -1036,7 +992,7 @@
 		}
 		
 		variableDecl.setModifiers(argument.modifiers);
-		SimpleName name = this.ast.newSimpleName(argument.name());
+		SimpleName name = this.ast.newSimpleName(new String(argument.name));
 		int start = argument.sourceStart;
 		int nameEnd = argument.sourceEnd;
 		name.setSourceRange(start, nameEnd - start + 1);
@@ -1080,15 +1036,39 @@
 		return arrayInitializer;
 	}
 
-	public Expression convert(QualifiedAllocationExpression expression) {
-		if (expression.anonymousType != null) {
-			return convert((AnonymousLocalTypeDeclaration) expression.anonymousType);
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression allocation) {
+		if (allocation.anonymousType != null) {
+			ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
+			classInstanceCreation.setName(convert(allocation.type));
+			if (allocation.enclosingInstance != null) {
+				classInstanceCreation.setExpression(convert(allocation.enclosingInstance));
+			}
+			int declarationSourceStart = allocation.sourceStart;
+			classInstanceCreation.setSourceRange(declarationSourceStart, allocation.anonymousType.bodyEnd - declarationSourceStart + 1);
+			org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = allocation.arguments;
+			if (arguments != null) {
+				int length = arguments.length;
+				for (int i = 0; i < length; i++) {
+					classInstanceCreation.arguments().add(convert(arguments[i]));
+				}
+			}
+			AnonymousClassDeclaration anonymousClassDeclaration = this.ast.newAnonymousClassDeclaration();
+			int start = retrieveStartBlockPosition(declarationSourceStart, allocation.anonymousType.bodyEnd);
+			anonymousClassDeclaration.setSourceRange(start, allocation.anonymousType.bodyEnd - start + 1);
+			classInstanceCreation.setAnonymousClassDeclaration(anonymousClassDeclaration);
+			buildBodyDeclarations(allocation.anonymousType, anonymousClassDeclaration);
+			if (this.resolveBindings) {
+				recordNodes(classInstanceCreation, allocation.anonymousType);
+				recordNodes(anonymousClassDeclaration, allocation.anonymousType);
+				anonymousClassDeclaration.resolveBinding();
+			}
+			return classInstanceCreation;			
 		} else {
 			ClassInstanceCreation classInstanceCreation = this.ast.newClassInstanceCreation();
-			classInstanceCreation.setExpression(convert(expression.enclosingInstance));
-			classInstanceCreation.setName(convert(expression.type));
-			classInstanceCreation.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
-			org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = expression.arguments;
+			classInstanceCreation.setExpression(convert(allocation.enclosingInstance));
+			classInstanceCreation.setName(convert(allocation.type));
+			classInstanceCreation.setSourceRange(allocation.sourceStart, allocation.sourceEnd - allocation.sourceStart + 1);
+			org.eclipse.jdt.internal.compiler.ast.Expression[] arguments = allocation.arguments;
 			if (arguments != null) {
 				int length = arguments.length;
 				for (int i = 0; i < length; i++) {
@@ -1100,7 +1080,7 @@
 				}
 			}
 			if (this.resolveBindings) {
-				recordNodes(classInstanceCreation, expression);
+				recordNodes(classInstanceCreation, allocation);
 			}
 			removeTrailingCommentFromExpressionEndingWithAParen(classInstanceCreation);
 			return classInstanceCreation;
@@ -1121,47 +1101,47 @@
 		return assignment;
 	}
 
-	public Assignment convert(CompoundAssignment expression) {
+	public Assignment convert(org.eclipse.jdt.internal.compiler.ast.CompoundAssignment expression) {
 		Assignment assignment = this.ast.newAssignment();
 		Expression lhs = convert(expression.lhs);
 		assignment.setLeftHandSide(lhs);
 		int start = lhs.getStartPosition();
 		assignment.setSourceRange(start, expression.sourceEnd - start + 1);
 		switch (expression.operator) {
-			case OperatorIds.PLUS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
 				assignment.setOperator(Assignment.Operator.PLUS_ASSIGN);
 				break;
-			case OperatorIds.MINUS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
 				assignment.setOperator(Assignment.Operator.MINUS_ASSIGN);
 				break;
-			case OperatorIds.MULTIPLY :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MULTIPLY :
 				assignment.setOperator(Assignment.Operator.TIMES_ASSIGN);
 				break;
-			case OperatorIds.DIVIDE :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.DIVIDE :
 				assignment.setOperator(Assignment.Operator.DIVIDE_ASSIGN);
 				break;
-			case OperatorIds.AND :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND :
 				assignment.setOperator(Assignment.Operator.BIT_AND_ASSIGN);
 				break;
-			case OperatorIds.OR :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR :
 				assignment.setOperator(Assignment.Operator.BIT_OR_ASSIGN);
 				break;
-			case OperatorIds.XOR :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.XOR :
 				assignment.setOperator(Assignment.Operator.BIT_XOR_ASSIGN);
 				break;
-			case OperatorIds.REMAINDER :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.REMAINDER :
 				assignment.setOperator(Assignment.Operator.REMAINDER_ASSIGN);
 				break;
-			case OperatorIds.LEFT_SHIFT :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
 				assignment.setOperator(Assignment.Operator.LEFT_SHIFT_ASSIGN);
 				break;
-			case OperatorIds.RIGHT_SHIFT :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
 				assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_SIGNED_ASSIGN);
 				break;
-			case OperatorIds.UNSIGNED_RIGHT_SHIFT :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
 				assignment.setOperator(Assignment.Operator.RIGHT_SHIFT_UNSIGNED_ASSIGN);
 				break;
-		};
+		}
 		assignment.setRightHandSide(convert(expression.expression));
 		return assignment;
 	}
@@ -1174,10 +1154,10 @@
 		prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
 		prefixExpression.setOperand(convert(expression.lhs));
 		switch (expression.operator) {
-			case org.eclipse.jdt.internal.compiler.ast.PrefixExpression.PLUS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
 				prefixExpression.setOperator(PrefixExpression.Operator.INCREMENT);
 				break;
-			case org.eclipse.jdt.internal.compiler.ast.PrefixExpression.MINUS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
 				prefixExpression.setOperator(PrefixExpression.Operator.DECREMENT);
 				break;
 		}
@@ -1192,10 +1172,10 @@
 		postfixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
 		postfixExpression.setOperand(convert(expression.lhs));
 		switch (expression.operator) {
-			case org.eclipse.jdt.internal.compiler.ast.PostfixExpression.PLUS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
 				postfixExpression.setOperator(PostfixExpression.Operator.INCREMENT);
 				break;
-			case org.eclipse.jdt.internal.compiler.ast.PostfixExpression.MINUS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
 				postfixExpression.setOperator(PostfixExpression.Operator.DECREMENT);
 				break;
 		}
@@ -1207,10 +1187,10 @@
 		castExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
 		org.eclipse.jdt.internal.compiler.ast.Expression type = expression.type;
 		removeExtraBlanks(type);
-		if (type instanceof TypeReference ) {
-			castExpression.setType(convertType((TypeReference)type));
-		} else if (type instanceof NameReference) {
-			castExpression.setType(convertToType((NameReference)type));
+		if (type instanceof org.eclipse.jdt.internal.compiler.ast.TypeReference ) {
+			castExpression.setType(convertType((org.eclipse.jdt.internal.compiler.ast.TypeReference)type));
+		} else if (type instanceof org.eclipse.jdt.internal.compiler.ast.NameReference) {
+			castExpression.setType(convertToType((org.eclipse.jdt.internal.compiler.ast.NameReference)type));
 		}
 		castExpression.setExpression(convert(expression.expression));
 		if (this.resolveBindings) {
@@ -1219,7 +1199,7 @@
 		return castExpression;
 	}
 		
-	public Type convertToType(NameReference reference) {
+	public Type convertToType(org.eclipse.jdt.internal.compiler.ast.NameReference reference) {
 		Name name = convert(reference);
 		SimpleType type = this.ast.newSimpleType(name);
 		type.setSourceRange(name.getStartPosition(), name.getLength());
@@ -1228,7 +1208,7 @@
 		}
 		return type;
 	}
-	public Expression convert(ClassLiteralAccess expression) {
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess expression) {
 		TypeLiteral typeLiteral = this.ast.newTypeLiteral();
 		if (this.resolveBindings) {
 			this.recordNodes(typeLiteral, expression);
@@ -1238,7 +1218,7 @@
 		return typeLiteral;
 	}
 
-	public BooleanLiteral convert(FalseLiteral expression) {
+	public BooleanLiteral convert(org.eclipse.jdt.internal.compiler.ast.FalseLiteral expression) {
 		BooleanLiteral literal = this.ast.newBooleanLiteral(false);
 		if (this.resolveBindings) {
 			this.recordNodes(literal, expression);
@@ -1247,7 +1227,7 @@
 		return literal;	
 	}
 		
-	public BooleanLiteral convert(TrueLiteral expression) {
+	public BooleanLiteral convert(org.eclipse.jdt.internal.compiler.ast.TrueLiteral expression) {
 		BooleanLiteral literal = this.ast.newBooleanLiteral(true);
 		if (this.resolveBindings) {
 			this.recordNodes(literal, expression);
@@ -1265,7 +1245,7 @@
 		return literal;		
 	}
 
-	public CharacterLiteral convert(CharLiteral expression) {
+	public CharacterLiteral convert(org.eclipse.jdt.internal.compiler.ast.CharLiteral expression) {
 		int length = expression.sourceEnd - expression.sourceStart + 1;	
 		int sourceStart = expression.sourceStart;
 		char[] tokens = new char[length];
@@ -1280,7 +1260,7 @@
 		return literal;
 	}
 
-	public NumberLiteral convert(DoubleLiteral expression) {
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.DoubleLiteral expression) {
 		int length = expression.sourceEnd - expression.sourceStart + 1;	
 		int sourceStart = expression.sourceStart;
 		char[] tokens = new char[length];
@@ -1294,7 +1274,7 @@
 		return literal;
 	}
 
-	public NumberLiteral convert(FloatLiteral expression) {
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.FloatLiteral expression) {
 		int length = expression.sourceEnd - expression.sourceStart + 1;	
 		int sourceStart = expression.sourceStart;
 		char[] tokens = new char[length];
@@ -1308,7 +1288,7 @@
 		return literal;
 	}
 
-	public NumberLiteral convert(IntLiteral expression) {
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.IntLiteral expression) {
 		int length = expression.sourceEnd - expression.sourceStart + 1;	
 		int sourceStart = expression.sourceStart;
 		char[] tokens = new char[length];
@@ -1322,7 +1302,7 @@
 		return literal;
 	}
 
-	public NumberLiteral convert(IntLiteralMinValue expression) {
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.IntLiteralMinValue expression) {
 		int length = expression.sourceEnd - expression.sourceStart + 1;	
 		int sourceStart = expression.sourceStart;
 		char[] tokens = new char[length];
@@ -1336,7 +1316,7 @@
 		return literal;
 	}
 
-	public NumberLiteral convert(LongLiteral expression) {
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.LongLiteral expression) {
 		int length = expression.sourceEnd - expression.sourceStart + 1;	
 		int sourceStart = expression.sourceStart;
 		char[] tokens = new char[length];
@@ -1350,7 +1330,7 @@
 		return literal;
 	}
 
-	public NumberLiteral convert(LongLiteralMinValue expression) {
+	public NumberLiteral convert(org.eclipse.jdt.internal.compiler.ast.LongLiteralMinValue expression) {
 		int length = expression.sourceEnd - expression.sourceStart + 1;	
 		int sourceStart = expression.sourceStart;
 		char[] tokens = new char[length];
@@ -1378,7 +1358,7 @@
 		return literal;
 	}
 
-	public StringLiteral convert(ExtendedStringLiteral expression) {
+	public StringLiteral convert(org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral expression) {
 		expression.computeConstant();
 		StringLiteral literal = this.ast.newStringLiteral();
 		if (this.resolveBindings) {
@@ -1389,81 +1369,81 @@
 		return literal;
 	}
 	
-	public Expression convert(BinaryExpression expression) {
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.BinaryExpression expression) {
 		InfixExpression infixExpression = this.ast.newInfixExpression();
 		if (this.resolveBindings) {
 			this.recordNodes(infixExpression, expression);
 		}
 
-		int expressionOperatorID = (expression.bits & OperatorExpression.OperatorMASK) >> OperatorExpression.OperatorSHIFT;
+		int expressionOperatorID = (expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT;
 		switch (expressionOperatorID) {
-			case OperatorIds.EQUAL_EQUAL :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
 				infixExpression.setOperator(InfixExpression.Operator.EQUALS);
 				break;
-			case OperatorIds.LESS_EQUAL :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS_EQUAL :
 				infixExpression.setOperator(InfixExpression.Operator.LESS_EQUALS);
 				break;
-			case OperatorIds.GREATER_EQUAL :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER_EQUAL :
 				infixExpression.setOperator(InfixExpression.Operator.GREATER_EQUALS);
 				break;
-			case OperatorIds.NOT_EQUAL :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
 				infixExpression.setOperator(InfixExpression.Operator.NOT_EQUALS);
 				break;
-			case OperatorIds.LEFT_SHIFT :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
 				infixExpression.setOperator(InfixExpression.Operator.LEFT_SHIFT);
 				break;
-			case OperatorIds.RIGHT_SHIFT :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
 				infixExpression.setOperator(InfixExpression.Operator.RIGHT_SHIFT_SIGNED);
 				break;
-			case OperatorIds.UNSIGNED_RIGHT_SHIFT :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
 				infixExpression.setOperator(InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED);
 				break;
-			case OperatorIds.OR_OR :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR_OR :
 				infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_OR);
 				break;
-			case OperatorIds.AND_AND :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND_AND :
 				infixExpression.setOperator(InfixExpression.Operator.CONDITIONAL_AND);
 				break;
-			case OperatorIds.PLUS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
 				infixExpression.setOperator(InfixExpression.Operator.PLUS);
 				break;
-			case OperatorIds.MINUS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
 				infixExpression.setOperator(InfixExpression.Operator.MINUS);
 				break;
-			case OperatorIds.REMAINDER :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.REMAINDER :
 				infixExpression.setOperator(InfixExpression.Operator.REMAINDER);
 				break;
-			case OperatorIds.XOR :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.XOR :
 				infixExpression.setOperator(InfixExpression.Operator.XOR);
 				break;
-			case OperatorIds.AND :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND :
 				infixExpression.setOperator(InfixExpression.Operator.AND);
 				break;
-			case OperatorIds.MULTIPLY :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MULTIPLY :
 				infixExpression.setOperator(InfixExpression.Operator.TIMES);
 				break;
-			case OperatorIds.OR :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR :
 				infixExpression.setOperator(InfixExpression.Operator.OR);
 				break;
-			case OperatorIds.DIVIDE :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.DIVIDE :
 				infixExpression.setOperator(InfixExpression.Operator.DIVIDE);
 				break;
-			case OperatorIds.GREATER :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER :
 				infixExpression.setOperator(InfixExpression.Operator.GREATER);
 				break;
-			case OperatorIds.LESS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS :
 				infixExpression.setOperator(InfixExpression.Operator.LESS);
-		};
+		}
 		
-		if (expression.left instanceof BinaryExpression && ((expression.left.bits & AstNode.ParenthesizedMASK) == 0)) {
+		if (expression.left instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression && ((expression.left.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0)) {
 			// create an extended string literal equivalent => use the extended operands list
 			infixExpression.extendedOperands().add(convert(expression.right));
 			org.eclipse.jdt.internal.compiler.ast.Expression leftOperand = expression.left;
 			org.eclipse.jdt.internal.compiler.ast.Expression rightOperand = null;
 			do {
-				rightOperand = ((BinaryExpression) leftOperand).right;
-				if ((((leftOperand.bits & OperatorExpression.OperatorMASK) >> OperatorExpression.OperatorSHIFT) != expressionOperatorID && ((leftOperand.bits & AstNode.ParenthesizedMASK) == 0))
-				 || ((rightOperand instanceof BinaryExpression && ((rightOperand.bits & OperatorExpression.OperatorMASK) >> OperatorExpression.OperatorSHIFT) != expressionOperatorID) && ((rightOperand.bits & AstNode.ParenthesizedMASK) == 0))) {
+				rightOperand = ((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) leftOperand).right;
+				if ((((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID && ((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))
+				 || ((rightOperand instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression && ((rightOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) != expressionOperatorID) && ((rightOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0))) {
 				 	List extendedOperands = infixExpression.extendedOperands();
 				 	InfixExpression temp = this.ast.newInfixExpression();
 					if (this.resolveBindings) {
@@ -1503,8 +1483,8 @@
 					return infixExpression;
 				}
 				infixExpression.extendedOperands().add(0, convert(rightOperand));
-				leftOperand = ((BinaryExpression) leftOperand).left;
-			} while (leftOperand instanceof BinaryExpression && ((leftOperand.bits & AstNode.ParenthesizedMASK) == 0));
+				leftOperand = ((org.eclipse.jdt.internal.compiler.ast.BinaryExpression) leftOperand).left;
+			} while (leftOperand instanceof org.eclipse.jdt.internal.compiler.ast.BinaryExpression && ((leftOperand.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.ParenthesizedMASK) == 0));
 			Expression leftExpression = convert(leftOperand);
 			infixExpression.setLeftOperand(leftExpression);
 			infixExpression.setRightOperand((Expression)infixExpression.extendedOperands().remove(0));
@@ -1520,24 +1500,24 @@
 		return infixExpression;
 	}
 			
-	public PrefixExpression convert(UnaryExpression expression) {
+	public PrefixExpression convert(org.eclipse.jdt.internal.compiler.ast.UnaryExpression expression) {
 		PrefixExpression prefixExpression = this.ast.newPrefixExpression();
 		if (this.resolveBindings) {
 			this.recordNodes(prefixExpression, expression);
 		}
 		prefixExpression.setSourceRange(expression.sourceStart, expression.sourceEnd - expression.sourceStart + 1);
 		prefixExpression.setOperand(convert(expression.expression));
-		switch ((expression.bits & UnaryExpression.OperatorMASK) >> UnaryExpression.OperatorSHIFT) {
-			case OperatorIds.PLUS :
+		switch ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
 				prefixExpression.setOperator(PrefixExpression.Operator.PLUS);
 				break;
-			case OperatorIds.MINUS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
 				prefixExpression.setOperator(PrefixExpression.Operator.MINUS);
 				break;
-			case OperatorIds.NOT :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT :
 				prefixExpression.setOperator(PrefixExpression.Operator.NOT);
 				break;
-			case OperatorIds.TWIDDLE :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.TWIDDLE :
 				prefixExpression.setOperator(PrefixExpression.Operator.COMPLEMENT);
 		}
 		return prefixExpression;
@@ -1568,7 +1548,7 @@
 		return conditionalExpression;
 	}
 
-	public Expression convert(MessageSend expression) {
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.MessageSend expression) {
 		// will return a MethodInvocation or a SuperMethodInvocation or
 		Expression expr;
 		int sourceStart = expression.sourceStart;
@@ -1588,8 +1568,8 @@
 			superMethodInvocation.setName(name);
 			// expression.receiver is either a QualifiedSuperReference or a SuperReference
 			// so the casting cannot fail
-			if (expression.receiver instanceof QualifiedSuperReference) {
-				Name qualifier = convert((QualifiedSuperReference) expression.receiver);
+			if (expression.receiver instanceof org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) {
+				Name qualifier = convert((org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference) expression.receiver);
 				superMethodInvocation.setQualifier(qualifier);
 				if (this.resolveBindings) {
 					recordNodes(qualifier, expression.receiver);
@@ -1650,7 +1630,7 @@
 		return expr;
 	}
 
-	public Expression convert(AND_AND_Expression expression) {
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression expression) {
 		InfixExpression infixExpression = this.ast.newInfixExpression();
 		if (this.resolveBindings) {
 			recordNodes(infixExpression, expression);
@@ -1665,7 +1645,7 @@
 	
 	}
 	
-	public Expression convert(EqualExpression expression) {
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.EqualExpression expression) {
 		InfixExpression infixExpression = this.ast.newInfixExpression();
 		if (this.resolveBindings) {
 			recordNodes(infixExpression, expression);
@@ -1675,18 +1655,18 @@
 		infixExpression.setRightOperand(convert(expression.right));
 		int startPosition = leftExpression.getStartPosition();
 		infixExpression.setSourceRange(startPosition, expression.sourceEnd - startPosition + 1);
-		switch ((expression.bits & OperatorExpression.OperatorMASK) >> OperatorExpression.OperatorSHIFT) {
-			case OperatorIds.EQUAL_EQUAL :
+		switch ((expression.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorMASK) >> org.eclipse.jdt.internal.compiler.ast.ASTNode.OperatorSHIFT) {
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
 				infixExpression.setOperator(InfixExpression.Operator.EQUALS);
 				break;
-			case OperatorIds.NOT_EQUAL :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
 				infixExpression.setOperator(InfixExpression.Operator.NOT_EQUALS);
 		}
 		return infixExpression;
 	
 	}
 
-	public Expression convert(OR_OR_Expression expression) {
+	public Expression convert(org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression expression) {
 		InfixExpression infixExpression = this.ast.newInfixExpression();
 		if (this.resolveBindings) {
 			recordNodes(infixExpression, expression);
@@ -1701,8 +1681,8 @@
 	}
 
 	public Statement convert(org.eclipse.jdt.internal.compiler.ast.Statement statement) {
-		if (statement instanceof LocalDeclaration) {
-			return convertToVariableDeclarationStatement((LocalDeclaration)statement);
+		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
+			return convertToVariableDeclarationStatement((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)statement);
 		}
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.AssertStatement) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.AssertStatement) statement);
@@ -1710,17 +1690,14 @@
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.Block) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.Block) statement);
 		}
-		if (statement instanceof Break) {
-			return convert((Break) statement);
+		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.BreakStatement) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.BreakStatement) statement);
 		}
-		if (statement instanceof Continue) {
-			return convert((Continue) statement);
+		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.ContinueStatement) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ContinueStatement) statement);
 		}
-		if (statement instanceof Case) {
-			return convert((Case) statement);
-		}
-		if (statement instanceof DefaultCase) {
-			return convert((DefaultCase) statement);
+		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.CaseStatement) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.CaseStatement) statement);
 		}
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.DoStatement) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.DoStatement) statement);
@@ -1728,8 +1705,8 @@
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.EmptyStatement) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.EmptyStatement) statement);
 		}
-		if (statement instanceof ExplicitConstructorCall) {
-			return convert((ExplicitConstructorCall) statement);
+		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall) {
+			return convert((org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall) statement);
 		}
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.ForStatement) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.ForStatement) statement);
@@ -1755,12 +1732,12 @@
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.TryStatement) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.TryStatement) statement);
 		}
-		if (statement instanceof LocalTypeDeclaration) {
-			TypeDeclarationStatement typeDeclarationStatement = this.ast.newTypeDeclarationStatement(convert((LocalTypeDeclaration) statement));
+		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration 
+				&& (statement.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsLocalTypeMASK) != 0) {
+			TypeDeclarationStatement typeDeclarationStatement = this.ast.newTypeDeclarationStatement(convert((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) statement));
 			TypeDeclaration typeDecl = typeDeclarationStatement.getTypeDeclaration();
 			typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
 			return typeDeclarationStatement;
-					
 		}
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
 			TypeDeclarationStatement typeDeclarationStatement = this.ast.newTypeDeclarationStatement(convert((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) statement));
@@ -1768,12 +1745,6 @@
 			typeDeclarationStatement.setSourceRange(typeDecl.getStartPosition(), typeDecl.getLength());
 			return typeDeclarationStatement;
 		}
-		if (statement instanceof AnonymousLocalTypeDeclaration) {
-			Expression expr = convert((AnonymousLocalTypeDeclaration) statement);
-			Statement stmt = this.ast.newExpressionStatement(expr);
-			stmt.setSourceRange(expr.getStartPosition(), expr.getLength());
-			return stmt;
-		}
 		if (statement instanceof org.eclipse.jdt.internal.compiler.ast.WhileStatement) {
 			return convert((org.eclipse.jdt.internal.compiler.ast.WhileStatement) statement);
 		}
@@ -1789,8 +1760,8 @@
 
 	public AssertStatement convert(org.eclipse.jdt.internal.compiler.ast.AssertStatement statement) {
 		AssertStatement assertStatement = this.ast.newAssertStatement();
-		assertStatement.setExpression(convert(statement.assertExpression));
 		int end = statement.assertExpression.sourceEnd + 1;
+		assertStatement.setExpression(convert(statement.assertExpression));
 		org.eclipse.jdt.internal.compiler.ast.Expression exceptionArgument = statement.exceptionArgument;
 		if (exceptionArgument != null) {
 			assertStatement.setMessage(convert(exceptionArgument));
@@ -1811,7 +1782,7 @@
 		if (statements != null) {
 			int statementsLength = statements.length;
 			for (int i = 0; i < statementsLength; i++) {
-				if (statements[i] instanceof LocalDeclaration) {
+				if (statements[i] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
 					checkAndAddMultipleLocalDeclaration(statements, i, block.statements());
 				} else {
 					block.statements().add(convert(statements[i]));
@@ -1821,7 +1792,7 @@
 		return block;
 	}
 	
-	public BreakStatement convert(Break statement)  {
+	public BreakStatement convert(org.eclipse.jdt.internal.compiler.ast.BreakStatement statement)  {
 		BreakStatement breakStatement = this.ast.newBreakStatement();
 		breakStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
 		if (statement.label != null) {
@@ -1833,7 +1804,7 @@
 		return breakStatement;
 	}
 
-	public ContinueStatement convert(Continue statement)  {
+	public ContinueStatement convert(org.eclipse.jdt.internal.compiler.ast.ContinueStatement statement)  {
 		ContinueStatement continueStatement = this.ast.newContinueStatement();
 		continueStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
 		if (statement.label != null) {
@@ -1846,36 +1817,24 @@
 	}
 		
 		
-	public SwitchCase convert(Case statement) {
+	public SwitchCase convert(org.eclipse.jdt.internal.compiler.ast.CaseStatement statement) {
 		SwitchCase switchCase = this.ast.newSwitchCase();
+		org.eclipse.jdt.internal.compiler.ast.Expression constantExpression = statement.constantExpression;
+		if (constantExpression == null) {
+			switchCase.setExpression(null);
+		} else {
+			switchCase.setExpression(convert(constantExpression));
+		}
 		switchCase.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		switchCase.setExpression(convert(statement.constantExpression));
 		retrieveColonPosition(switchCase);
 		return switchCase;
 	}
 	
-	public SwitchCase convert(DefaultCase statement) {
-		SwitchCase switchCase = this.ast.newSwitchCase();
-		switchCase.setExpression(null);
-		switchCase.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
-		retrieveColonPosition(switchCase);		
-		return switchCase;
-	}
-	
 	public DoStatement convert(org.eclipse.jdt.internal.compiler.ast.DoStatement statement) {
 		DoStatement doStatement = this.ast.newDoStatement();
 		doStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
 		doStatement.setExpression(convert(statement.condition));
-		org.eclipse.jdt.internal.compiler.ast.Statement action = statement.action;
-		if (action != null) {
-			doStatement.setBody(convert(statement.action));
-		} else {
-			EmptyStatement emptyStatement = this.ast.newEmptyStatement();
-			int start = retrieveStartingSemiColonPosition(statement.sourceStart, statement.sourceEnd);
-			int end = retrieveEndingSemiColonPosition(start, statement.sourceEnd);
-			emptyStatement.setSourceRange(start, end - start + 1);
-			doStatement.setBody(emptyStatement);
-		}
+		doStatement.setBody(convert(statement.action));
 		retrieveSemiColonPosition(doStatement);
 		return doStatement;
 	}
@@ -1886,7 +1845,7 @@
 		return emptyStatement;
 	}
 	
-	public Statement convert(ExplicitConstructorCall statement) {
+	public Statement convert(org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall statement) {
 		Statement newStatement;
 		if (statement.isSuperAccess() || statement.isSuper()) {
 			SuperConstructorInvocation superConstructorInvocation = this.ast.newSuperConstructorInvocation();
@@ -1926,11 +1885,16 @@
 		org.eclipse.jdt.internal.compiler.ast.Statement[] initializations = statement.initializations;
 		if (initializations != null) {
 			// we know that we have at least one initialization
-			if (initializations[0] instanceof LocalDeclaration) {
-				VariableDeclarationExpression variableDeclarationExpression = convertToVariableDeclarationExpression((LocalDeclaration) initializations[0]);
+			if (initializations[0] instanceof org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) {
+				VariableDeclarationExpression variableDeclarationExpression = convertToVariableDeclarationExpression((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) initializations[0]);
 				int initializationsLength = initializations.length;
 				for (int i = 1; i < initializationsLength; i++) {
-					variableDeclarationExpression.fragments().add(convertToVariableDeclarationFragment((LocalDeclaration)initializations[i]));
+					variableDeclarationExpression.fragments().add(convertToVariableDeclarationFragment((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration)initializations[i]));
+				}
+				if (initializationsLength != 1) {
+					int start = variableDeclarationExpression.getStartPosition();
+					int end = ((org.eclipse.jdt.internal.compiler.ast.LocalDeclaration) initializations[initializationsLength - 1]).declarationSourceEnd;
+					variableDeclarationExpression.setSourceRange(start, end - start + 1);
 				}
 				forStatement.initializers().add(variableDeclarationExpression);
 			} else {
@@ -1950,16 +1914,7 @@
 				forStatement.updaters().add(convertToExpression(increments[i]));				
 			}
 		}
-		org.eclipse.jdt.internal.compiler.ast.Statement action = statement.action;
-		if (action != null) {
-			forStatement.setBody(convert(statement.action));
-		} else {
-			EmptyStatement emptyStatement = this.ast.newEmptyStatement();
-			int start = retrieveStartingSemiColonPosition(statement.sourceStart, compilationUnitSource.length);
-			int end = retrieveEndingSemiColonPosition(start, compilationUnitSource.length);
-			emptyStatement.setSourceRange(start, end - start + 1);
-			forStatement.setBody(emptyStatement);
-		}
+		forStatement.setBody(convert(statement.action));
 		return forStatement;
 	}
 	
@@ -1975,31 +1930,9 @@
 		IfStatement ifStatement = this.ast.newIfStatement();
 		ifStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
 		ifStatement.setExpression(convert(statement.condition));
-		org.eclipse.jdt.internal.compiler.ast.Statement thenStatement = statement.thenStatement;
-		org.eclipse.jdt.internal.compiler.ast.Statement elseStatement = statement.elseStatement;
-		if (thenStatement != null) {
-			if (thenStatement == org.eclipse.jdt.internal.compiler.ast.Block.None) {
-				EmptyStatement emptyStatement = this.ast.newEmptyStatement();
-				int start = retrieveStartingSemiColonPosition(statement.sourceStart, statement.sourceEnd);
-				int end = retrieveEndingSemiColonPosition(start, statement.sourceEnd);
-				emptyStatement.setSourceRange(start, end - start + 1);
-				ifStatement.setThenStatement(emptyStatement);
-			} else {
-				ifStatement.setThenStatement(convert(statement.thenStatement));
-			}
-		}
-		if (elseStatement != null) {
-			if (elseStatement == org.eclipse.jdt.internal.compiler.ast.Block.None) {
-				// retrieve the else position
-				EmptyStatement emptyStatement = this.ast.newEmptyStatement();
-				int start = retrieveElseEndingPosition(statement.sourceStart, statement.sourceEnd);
-				start = retrieveStartingSemiColonPosition(statement.sourceStart, statement.sourceEnd);
-				int end = retrieveEndingSemiColonPosition(start, statement.sourceEnd);
-				emptyStatement.setSourceRange(start, end - start + 1);
-				ifStatement.setElseStatement(emptyStatement);
-			} else {
-				ifStatement.setElseStatement(convert(elseStatement));
-			}
+		ifStatement.setThenStatement(convert(statement.thenStatement));
+		if (statement.elseStatement != null) {
+			ifStatement.setElseStatement(convert(statement.elseStatement));
 		}
 		return ifStatement;
 	}
@@ -2008,15 +1941,7 @@
 		LabeledStatement labeledStatement = this.ast.newLabeledStatement();
 		labeledStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);	
 		org.eclipse.jdt.internal.compiler.ast.Statement body = statement.statement;
-		if (body == org.eclipse.jdt.internal.compiler.ast.Block.None) {
-			EmptyStatement emptyStatement = this.ast.newEmptyStatement();
-			int start = retrieveStartingSemiColonPosition(statement.sourceStart, statement.sourceEnd);
-			int end = retrieveEndingSemiColonPosition(start, statement.sourceEnd);
-			emptyStatement.setSourceRange(start, end - start + 1);
-			labeledStatement.setBody(emptyStatement);
-		} else {
-			labeledStatement.setBody(convert(body));
-		}
+		labeledStatement.setBody(convert(body));
 		SimpleName name = this.ast.newSimpleName(new String(statement.label));
 		retrieveIdentifierAndSetPositions(statement.sourceStart, statement.sourceEnd, name);
 		labeledStatement.setLabel(name);
@@ -2036,7 +1961,7 @@
 	public SwitchStatement convert(org.eclipse.jdt.internal.compiler.ast.SwitchStatement statement) {
 		SwitchStatement switchStatement = this.ast.newSwitchStatement();
 		switchStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);	
-		switchStatement.setExpression(convert(statement.testExpression));
+		switchStatement.setExpression(convert(statement.expression));
 		org.eclipse.jdt.internal.compiler.ast.Statement[] statements = statement.statements;
 		if (statements != null) {
 			int statementsLength = statements.length;
@@ -2068,7 +1993,7 @@
 		tryStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);	
 
 		tryStatement.setBody(convert(statement.tryBlock));
-		Argument[] catchArguments = statement.catchArguments;
+		org.eclipse.jdt.internal.compiler.ast.Argument[] catchArguments = statement.catchArguments;
 		if (catchArguments != null) {
 			int catchArgumentsLength = catchArguments.length;
 			org.eclipse.jdt.internal.compiler.ast.Block[] catchBlocks = statement.catchBlocks;
@@ -2094,20 +2019,7 @@
 		whileStatement.setSourceRange(statement.sourceStart, statement.sourceEnd - statement.sourceStart + 1);
 		whileStatement.setExpression(convert(statement.condition));
 		org.eclipse.jdt.internal.compiler.ast.Statement action = statement.action;
-		if (action != null) {
-			whileStatement.setBody(convert(action));
-			if (!(action instanceof org.eclipse.jdt.internal.compiler.ast.Block)) {
-				// set the end position of the for statement on the semi-colon
-				retrieveSemiColonPosition(whileStatement);
-			}
-		} else {
-			EmptyStatement emptyStatement = this.ast.newEmptyStatement();
-			retrieveSemiColonPosition(whileStatement);
-			int start = retrieveStartingSemiColonPosition(statement.sourceStart, compilationUnitSource.length);
-			int end = retrieveEndingSemiColonPosition(start, compilationUnitSource.length);
-			emptyStatement.setSourceRange(start, end - start + 1);
-			whileStatement.setBody(emptyStatement);
-		}
+		whileStatement.setBody(convert(action));
 		return whileStatement;
 	}
 	
@@ -2305,6 +2217,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 	}
 
@@ -2328,45 +2241,10 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 	}
 
-	private int retrieveStartingSemiColonPosition(int start, int end) {
-		int count = 0;
-		scanner.resetTo(start, end);
-		try {
-			int token;
-			while ((token = scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameSEMICOLON:
-						if (count == 0) {
-							return scanner.startPosition;
-						}
-						break;
-					case TerminalTokens.TokenNameLBRACE :
-						count++;
-						break;
-					case TerminalTokens.TokenNameRBRACE :
-						count--;
-						break;
-					case TerminalTokens.TokenNameLPAREN :
-						count++;
-						break;
-					case TerminalTokens.TokenNameRPAREN :
-						count--;
-						break;
-					case TerminalTokens.TokenNameLBRACKET :
-						count++;
-						break;
-					case TerminalTokens.TokenNameRBRACKET :
-						count--;
-				}
-			}
-		} catch(InvalidInputException e) {
-		}
-		return -1;
-	}
-
 	private int retrieveEndingSemiColonPosition(int start, int end) {
 		int count = 0;
 		scanner.resetTo(start, end);
@@ -2399,25 +2277,11 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return -1;
 	}
 
-	private int retrieveElseEndingPosition(int start, int end) {
-		scanner.resetTo(start, end);
-		try {
-			int token;
-			while ((token = scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
-				switch(token) {
-					case TerminalTokens.TokenNameelse:
-						return scanner.currentPosition - 1;
-				}
-			}
-		} catch(InvalidInputException e) {
-		}
-		return -1;
-	}
-	
 	/**
 	 * This method is used to retrieve the array dimension declared after the
 	 * name of a local or a field declaration.
@@ -2445,6 +2309,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return dimensions;
 	}
@@ -2476,6 +2341,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return foundPosition;
 	}
@@ -2495,6 +2361,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return -1;
 	}
@@ -2521,6 +2388,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return -1;
 	}
@@ -2540,6 +2408,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return -1;
 	}
@@ -2559,6 +2428,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return -1;
 	}
@@ -2577,6 +2447,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return -1;
 	}
@@ -2596,6 +2467,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return -1;
 	}
@@ -2615,6 +2487,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return -1;
 	}	
@@ -2637,10 +2510,11 @@
 						count--;
 						if (count == 0) {
 							return scanner.currentPosition - 1;
-						};
+						}
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return -1;
 	}
@@ -2649,9 +2523,9 @@
 	 * This method is used to retrieve position before the next right brace or semi-colon.
 	 * @return int the position found.
 	 */
-	private void retrieveRightBraceOrSemiColonPosition(ASTNode node) {
+	private int retrieveRightBraceOrSemiColonPosition(MethodDeclaration node, org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration) {
 		int start = node.getStartPosition();
-		scanner.resetTo(start, this.compilationUnitSource.length);
+		scanner.resetTo(start, methodDeclaration.declarationSourceEnd);
 		try {
 			int token;
 			int braceCounter = 0;
@@ -2663,19 +2537,19 @@
 					case TerminalTokens.TokenNameRBRACE :
 						braceCounter--;
 						if (braceCounter == 0) {
-							node.setSourceRange(start, scanner.currentPosition - start);
-							return;
+							return scanner.currentPosition;
 						}
 						break;
 					case TerminalTokens.TokenNameSEMICOLON :
 						if (braceCounter == 0) {
-							node.setSourceRange(start, scanner.currentPosition - start);
-							return;
+							return scanner.currentPosition;
 						}
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
+		return -1;
 	}
 
 	/**
@@ -2715,13 +2589,14 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 		return -1;
 	}
 	
 	private VariableDeclarationFragment convertToVariableDeclarationFragment(org.eclipse.jdt.internal.compiler.ast.FieldDeclaration fieldDeclaration) {
 		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
-		SimpleName name = this.ast.newSimpleName(fieldDeclaration.name());
+		SimpleName name = this.ast.newSimpleName(new String(fieldDeclaration.name));
 		name.setSourceRange(fieldDeclaration.sourceStart, fieldDeclaration.sourceEnd - fieldDeclaration.sourceStart + 1);
 		variableDeclarationFragment.setName(name);
 		int end = retrievePositionBeforeNextCommaOrSemiColon(fieldDeclaration.sourceEnd, fieldDeclaration.declarationSourceEnd);
@@ -2743,9 +2618,9 @@
 		return variableDeclarationFragment;
 	}
 
-	private VariableDeclarationFragment convertToVariableDeclarationFragment(LocalDeclaration localDeclaration) {
+	private VariableDeclarationFragment convertToVariableDeclarationFragment(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
 		VariableDeclarationFragment variableDeclarationFragment = this.ast.newVariableDeclarationFragment();
-		SimpleName name = this.ast.newSimpleName(localDeclaration.name());
+		SimpleName name = this.ast.newSimpleName(new String(localDeclaration.name));
 		name.setSourceRange(localDeclaration.sourceStart, localDeclaration.sourceEnd - localDeclaration.sourceStart + 1);
 		variableDeclarationFragment.setName(name);
 		int end = retrievePositionBeforeNextCommaOrSemiColon(localDeclaration.sourceEnd, this.compilationUnitSource.length);
@@ -2798,7 +2673,7 @@
 		return fieldDeclaration;
 	}
 
-	private VariableDeclarationStatement convertToVariableDeclarationStatement(LocalDeclaration localDeclaration) {
+	private VariableDeclarationStatement convertToVariableDeclarationStatement(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
 		VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
 		VariableDeclarationStatement variableDeclarationStatement = this.ast.newVariableDeclarationStatement(variableDeclarationFragment);
 		if (this.resolveBindings) {
@@ -2819,11 +2694,10 @@
 			variableDeclarationStatement.setModifiers(localDeclaration.modifiers & Modifier.FINAL);
 			variableDeclarationStatement.setFlags(ASTNode.MALFORMED);
 		}
-		retrieveSemiColonPosition(variableDeclarationStatement);
 		return variableDeclarationStatement;
 	}
 	
-	private VariableDeclarationExpression convertToVariableDeclarationExpression(LocalDeclaration localDeclaration) {
+	private VariableDeclarationExpression convertToVariableDeclarationExpression(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
 		VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
 		VariableDeclarationExpression variableDeclarationExpression = this.ast.newVariableDeclarationExpression(variableDeclarationFragment);
 		if (this.resolveBindings) {
@@ -2871,16 +2745,39 @@
 					subarrayType.setSourceRange(start, end - start + 1);
 					subarrayType.setParent(null);
 					fieldDeclaration.setType(subarrayType);
+					updateInnerPositions(subarrayType, remainingDimensions);
 					this.ast.getBindingResolver().updateKey(type, subarrayType);
 				}
 			} else {
 				fieldDeclaration.setType(type);
 			}
 		} else {
+			if (type.isArrayType()) {
+				// update positions of the component types of the array type
+				int dimensions = ((ArrayType) type).getDimensions();
+				updateInnerPositions(type, dimensions);
+			}
 			fieldDeclaration.setType(type);
 		}
 	}
 
+	private void updateInnerPositions(Type type, int dimensions) {
+		if (dimensions > 1) {
+			// need to set positions for intermediate array type see 42839
+			int start = type.getStartPosition();
+			int length = type.getLength();
+			Type currentComponentType = ((ArrayType) type).getComponentType();
+			int searchedDimension = dimensions - 1;
+			int rightBracketEndPosition = start;
+			while (currentComponentType.isArrayType()) {
+				rightBracketEndPosition = retrieveProperRightBracketPosition(searchedDimension, start, start + length);
+				currentComponentType.setSourceRange(start, rightBracketEndPosition - start + 1);
+				currentComponentType = ((ArrayType) currentComponentType).getComponentType();
+				searchedDimension--;
+			}		
+		}
+	}
+
 	private void setTypeForSingleVariableDeclaration(SingleVariableDeclaration singleVariableDeclaration, Type type, int extraDimension) {
 		if (extraDimension != 0) {
 			if (type.isArrayType()) {
@@ -2904,6 +2801,7 @@
 					int end = retrieveProperRightBracketPosition(remainingDimensions, start, start + length);
 					subarrayType.setSourceRange(start, end - start + 1);
 					subarrayType.setParent(null);
+					updateInnerPositions(subarrayType, remainingDimensions);
 					singleVariableDeclaration.setType(subarrayType);
 					this.ast.getBindingResolver().updateKey(type, subarrayType);
 				}
@@ -2938,6 +2836,7 @@
 					int end = retrieveProperRightBracketPosition(remainingDimensions, start, start + length);
 					subarrayType.setSourceRange(start, end - start + 1);
 					subarrayType.setParent(null);
+					updateInnerPositions(subarrayType, remainingDimensions);
 					methodDeclaration.setReturnType(subarrayType);
 					this.ast.getBindingResolver().updateKey(type, subarrayType);
 				}
@@ -2972,6 +2871,7 @@
 					int end = retrieveProperRightBracketPosition(remainingDimensions, start, start + length);
 					subarrayType.setSourceRange(start, end - start + 1);
 					subarrayType.setParent(null);
+					updateInnerPositions(subarrayType, remainingDimensions);
 					variableDeclarationStatement.setType(subarrayType);
 					this.ast.getBindingResolver().updateKey(type, subarrayType);
 				}
@@ -3006,6 +2906,7 @@
 					int end = retrieveProperRightBracketPosition(remainingDimensions, start, start + length);
 					subarrayType.setSourceRange(start, end - start + 1);
 					subarrayType.setParent(null);
+					updateInnerPositions(subarrayType, remainingDimensions);
 					variableDeclarationExpression.setType(subarrayType);
 					this.ast.getBindingResolver().updateKey(type, subarrayType);
 				}
@@ -3038,6 +2939,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 	}
 	
@@ -3055,7 +2957,7 @@
 		unit.setProblems(resizeProblems);
 	}
 	
-	private void recordNodes(ASTNode node, org.eclipse.jdt.internal.compiler.ast.AstNode oldASTNode) {
+	private void recordNodes(ASTNode node, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) {
 		this.ast.getBindingResolver().store(node, oldASTNode);
 	}
 	
@@ -3067,7 +2969,7 @@
 		int end = expression.sourceEnd;
 		int token;
 		int trimLeftPosition = expression.sourceStart;
-		int trimRigthPosition = expression.sourceEnd;
+		int trimRightPosition = expression.sourceEnd;
 		boolean first = true;
 		Scanner removeBlankScanner = this.ast.scanner;
 		try {
@@ -3080,22 +2982,23 @@
 						if (first) {
 							trimLeftPosition = removeBlankScanner.currentPosition;
 						}
-						trimRigthPosition = removeBlankScanner.startPosition - 1;
+						trimRightPosition = removeBlankScanner.startPosition - 1;
 						break;
 					case TerminalTokens.TokenNameEOF :
 						expression.sourceStart = trimLeftPosition;
-						expression.sourceEnd = trimRigthPosition;
+						expression.sourceEnd = trimRightPosition;
 						return;
 					default :
 						/*
 						 * if we find something else than a whitespace, then we reset the trimRigthPosition
 						 * to the expression source end.
 						 */
-						trimRigthPosition = expression.sourceEnd;
+						trimRightPosition = expression.sourceEnd;
 				}
 				first = false;
 			}
 		} catch (InvalidInputException e){
+			// ignore
 		}
 	}
 	
@@ -3124,26 +3027,10 @@
 			}
 			expression.sourceEnd = scanner.startPosition - 1;
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 	}
 
-	private long[] scanAllIdentifiersPositions(int start, int end, int length) {
-		scanner.resetTo(start, end);
-		long[] positions = new long[length];
-		int token;
-		int index = 0;
-		try {
-			while((token = scanner.getNextToken()) != TerminalTokens.TokenNameEOF)  {
-				if (token == TerminalTokens.TokenNameIdentifier) {
-					positions[index] = (((long) scanner.startPosition) << 32) + (scanner.currentPosition - 1);
-					index++;
-				}
-			}
-		} catch(InvalidInputException e) {
-		}
-		return positions;
-	}
-	
 	private void retrieveIdentifierAndSetPositions(int start, int end, Name name) {
 		scanner.resetTo(start, end);
 		int token;
@@ -3157,6 +3044,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 	}
 	
@@ -3183,6 +3071,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 	}
 
@@ -3214,6 +3103,7 @@
 				}
 			}
 		} catch(InvalidInputException e) {
+			// ignore
 		}
 	}
 	
@@ -3249,45 +3139,45 @@
 	
 	private InfixExpression.Operator getOperatorFor(int operatorID) {
 		switch (operatorID) {
-			case OperatorIds.EQUAL_EQUAL :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.EQUAL_EQUAL :
 				return InfixExpression.Operator.EQUALS;
-			case OperatorIds.LESS_EQUAL :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS_EQUAL :
 				return InfixExpression.Operator.LESS_EQUALS;
-			case OperatorIds.GREATER_EQUAL :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER_EQUAL :
 				return InfixExpression.Operator.GREATER_EQUALS;
-			case OperatorIds.NOT_EQUAL :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.NOT_EQUAL :
 				return InfixExpression.Operator.NOT_EQUALS;
-			case OperatorIds.LEFT_SHIFT :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LEFT_SHIFT :
 				return InfixExpression.Operator.LEFT_SHIFT;
-			case OperatorIds.RIGHT_SHIFT :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.RIGHT_SHIFT :
 				return InfixExpression.Operator.RIGHT_SHIFT_SIGNED;
-			case OperatorIds.UNSIGNED_RIGHT_SHIFT :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.UNSIGNED_RIGHT_SHIFT :
 				return InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED;
-			case OperatorIds.OR_OR :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR_OR :
 				return InfixExpression.Operator.CONDITIONAL_OR;
-			case OperatorIds.AND_AND :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND_AND :
 				return InfixExpression.Operator.CONDITIONAL_AND;
-			case OperatorIds.PLUS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.PLUS :
 				return InfixExpression.Operator.PLUS;
-			case OperatorIds.MINUS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MINUS :
 				return InfixExpression.Operator.MINUS;
-			case OperatorIds.REMAINDER :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.REMAINDER :
 				return InfixExpression.Operator.REMAINDER;
-			case OperatorIds.XOR :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.XOR :
 				return InfixExpression.Operator.XOR;
-			case OperatorIds.AND :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.AND :
 				return InfixExpression.Operator.AND;
-			case OperatorIds.MULTIPLY :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.MULTIPLY :
 				return InfixExpression.Operator.TIMES;
-			case OperatorIds.OR :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.OR :
 				return InfixExpression.Operator.OR;
-			case OperatorIds.DIVIDE :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.DIVIDE :
 				return InfixExpression.Operator.DIVIDE;
-			case OperatorIds.GREATER :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.GREATER :
 				return InfixExpression.Operator.GREATER;
-			case OperatorIds.LESS :
+			case org.eclipse.jdt.internal.compiler.ast.OperatorIds.LESS :
 				return InfixExpression.Operator.LESS;
-		};
+		}
 		return null;
 	}
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
index 143f094..5fbe011 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
@@ -46,12 +46,6 @@
 public class ASTMatcher {
 
 	/**
-	 * Creates a new AST matcher.
-	 */
-	public ASTMatcher() {
-	}
-
-	/**
 	 * Returns whether the given lists of AST nodes match pair wise according
 	 * to <code>ASTNode.subtreeMatch</code>.
 	 * <p>
@@ -110,7 +104,7 @@
 			return false;
 		}
 		// N.B. call subtreeMatch even node1==node2!=null
-		return ((ASTNode) node1).subtreeMatch(this, (ASTNode) node2);
+		return ((ASTNode) node1).subtreeMatch(this, node2);
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
index cf3b086..72c3a74 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
@@ -1430,10 +1430,16 @@
 	/**
 	 * Returns the character index into the original source file indicating
 	 * where the source fragment corresponding to this node begins.
+	 * <p>
+	 * The parser supplies useful well-defined source ranges to the nodes it creates.
+	 * See {@link AST#parseCompilationUnit AST.parseCompilationUnit} for details
+	 * on precisely where source ranges begin and end.
+	 * </p>
 	 * 
 	 * @return the 0-based character index, or <code>-1</code>
 	 *    if no source position information is recorded for this node
 	 * @see #getLength
+	 * @see AST#parseCompilationUnit
 	 */
 	public int getStartPosition() {
 		return startPosition;
@@ -1442,10 +1448,16 @@
 	/**
 	 * Returns the length in characters of the original source file indicating
 	 * where the source fragment corresponding to this node ends.
+	 * <p>
+	 * The parser supplies useful well-defined source ranges to the nodes it creates.
+	 * See {@link AST#parseCompilationUnit AST.parseCompilationUnit} for details
+	 * on precisely where source ranges begin and end.
+	 * </p>
 	 * 
 	 * @return a (possibly 0) length, or <code>0</code>
 	 *    if no source position information is recorded for this node
 	 * @see #getStartPosition()
+	 * @see AST#parseCompilationUnit
 	 */
 	public int getLength() {
 		return length;
@@ -1454,6 +1466,10 @@
 	/**
 	 * Sets the source range of the original source file where the source
 	 * fragment corresponding to this node was found.
+	 * <p>
+	 * See {@link AST#parseCompilationUnit AST.parseCompilationUnit} for details
+	 * on precisely where source ranges begin and end.
+	 * </p>
 	 * 
 	 * @param startPosition a 0-based character index, 
 	 *    or <code>-1</code> if no source position information is 
@@ -1463,6 +1479,7 @@
 	 *    for this node
 	 * @see #getStartPosition
 	 * @see #getLength
+	 * @see AST#parseCompilationUnit
 	 */
 	public void setSourceRange(int startPosition, int length) {
 		if (startPosition >= 0 && length < 0) {
@@ -1483,8 +1500,7 @@
 	 * @return a debug string 
 	 */
 	public final String toString() {
-		// allocate a buffer that is large enough to hold an average compilation unit
-		StringBuffer buffer = new StringBuffer(6000);
+		StringBuffer buffer = new StringBuffer();
 		int p = buffer.length();
 		try {
 			appendDebugString(buffer);
@@ -1495,8 +1511,7 @@
 			buffer.append("!"); //$NON-NLS-1$
 			buffer.append(standardToString());
 		}
-		// convert to a string, but lose the extra space in the string buffer by copying
-		return new String(buffer.toString());
+		return buffer.toString();
 	}
 	
 	/**
@@ -1543,8 +1558,9 @@
 	/**
 	 * Approximate base size of an AST node instance in bytes, 
 	 * including object header and instance fields.
+	 * That is, HEADERS + (# instance vars in ASTNode)*4.
 	 */
-	static final int BASE_NODE_SIZE = HEADERS + 6 * 4;
+	static final int BASE_NODE_SIZE = HEADERS + 7 * 4;
 	
 	/**
 	 * Returns an estimate of the memory footprint in bytes of the entire 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java
index ccb0082..365b6ca 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java
@@ -34,6 +34,20 @@
 				case IProblem.ParsingError :
 				case IProblem.ParsingErrorNoSuggestion :
 					break;
+				case IProblem.ParsingErrorInsertTokenBefore :
+				case IProblem.ParsingErrorInsertTokenAfter :
+				case IProblem.ParsingErrorDeleteToken :
+				case IProblem.ParsingErrorDeleteTokens :
+				case IProblem.ParsingErrorMergeTokens :
+				case IProblem.ParsingErrorInvalidToken :
+				case IProblem.ParsingErrorMisplacedConstruct :
+				case IProblem.ParsingErrorReplaceTokens :
+				case IProblem.ParsingErrorNoSuggestionForTokens :
+				case IProblem.ParsingErrorUnexpectedEOF :
+				case IProblem.ParsingErrorInsertToComplete :
+				case IProblem.ParsingErrorInsertToCompleteScope :
+				case IProblem.ParsingErrorInsertToCompletePhrase :
+					break;
 				default:
 					continue search;
 			}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
index 113a209..846b2b6 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
@@ -107,6 +107,7 @@
 	 * @param node the node to visit
 	 */
 	public void preVisit(ASTNode node) {
+		// default implementation: do nothing
 	}
 	
 	/**
@@ -119,6 +120,7 @@
 	 * @param node the node to visit
 	 */
 	public void postVisit(ASTNode node) {
+		// default implementation: do nothing
 	}
 
 	public boolean visit(AnonymousClassDeclaration node) {
@@ -309,127 +311,189 @@
 	}
 
 	public void endVisit(AnonymousClassDeclaration node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ArrayAccess node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ArrayCreation node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ArrayInitializer node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ArrayType node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(AssertStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(Assignment node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(Block node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(BooleanLiteral node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(BreakStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(CastExpression node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(CatchClause node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(CharacterLiteral node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ClassInstanceCreation node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(CompilationUnit node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ConditionalExpression node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ConstructorInvocation node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ContinueStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(DoStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(EmptyStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ExpressionStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(FieldAccess node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(FieldDeclaration node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ForStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(IfStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ImportDeclaration node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(InfixExpression node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(InstanceofExpression node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(Initializer node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(Javadoc node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(LabeledStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(MethodDeclaration node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(MethodInvocation node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(NullLiteral node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(NumberLiteral node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(PackageDeclaration node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ParenthesizedExpression node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(PostfixExpression node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(PrefixExpression node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(PrimitiveType node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(QualifiedName node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ReturnStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(SimpleName node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(SimpleType node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(StringLiteral node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(SuperConstructorInvocation node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(SuperFieldAccess node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(SuperMethodInvocation node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(SwitchCase node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(SwitchStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(SynchronizedStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ThisExpression node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(ThrowStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(TryStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(TypeDeclaration node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(TypeDeclarationStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(TypeLiteral node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(SingleVariableDeclaration node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(VariableDeclarationExpression node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(VariableDeclarationStatement node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(VariableDeclarationFragment node) {
+		// default implementation: do nothing
 	}
 	public void endVisit(WhileStatement node) {
+		// default implementation: do nothing
 	}
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
index 0f684c1..3f01356 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
@@ -112,9 +112,7 @@
 			throw new IllegalArgumentException();
 		}
 		// an ArrayType may occur inside an ArrayType - must check cycles
-		replaceChild(
-			(ASTNode) this.componentType,
-			(ASTNode) componentType, true);
+		replaceChild(this.componentType, componentType, true);
 		this.componentType = componentType;
 	}
 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java
index 89cf529..75742a9 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Assignment.java
@@ -266,7 +266,7 @@
 			throw new IllegalArgumentException();
 		}
 		// an Assignment may occur inside a Expression - must check cycles
-		replaceChild((ASTNode) this.leftHandSide, (ASTNode) expression, true);
+		replaceChild(this.leftHandSide, expression, true);
 		this.leftHandSide = expression;
 	}
 
@@ -301,7 +301,7 @@
 			throw new IllegalArgumentException();
 		}
 		// an Assignment may occur inside a Expression - must check cycles
-		replaceChild((ASTNode) this.rightHandSide, (ASTNode) expression, true);
+		replaceChild(this.rightHandSide, expression, true);
 		this.rightHandSide = expression;
 	}
 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java
index 908e735..7d24096 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BindingResolver.java
@@ -11,7 +11,6 @@
 
 package org.eclipse.jdt.core.dom;
 
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 
 /**
@@ -31,6 +30,7 @@
 	 * Creates a binding resolver.
 	 */
 	BindingResolver() {
+		// default implementation: do nothing
 	}
 
 	/**
@@ -38,8 +38,8 @@
 	 * resolveBinding methods. If the number changed, all resolve bindings methods
 	 * simply return null.
 	 */
-	protected void storeModificationCount(long modificationCount) {
-		this.modificationCount = modificationCount;
+	protected void storeModificationCount(long modificationCounter) {
+		this.modificationCount = modificationCounter;
 	}
 	
 	/**
@@ -53,7 +53,8 @@
 	 * @param newNode the new AST node
 	 * @param oldNode the old AST node
 	 */
-	void store(ASTNode newNode, AstNode oldASTNode) {
+	void store(ASTNode newNode, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) {
+		// default implementation: do nothing
 	}
 
 	/**
@@ -289,7 +290,49 @@
 	ITypeBinding resolveExpressionType(Expression expression) {
 		return null;
 	}
-	
+
+	/**
+	 * Resolves the given field access and returns the binding for it.
+	 * <p>
+	 * The implementation of <code>FieldAccess.resolveFieldBinding</code>
+	 * forwards to this method. How the field resolves is often a function of
+	 * the context in which the field access node is embedded as well as
+	 * the field access subtree itself.
+	 * </p>
+	 * <p>
+	 * The default implementation of this method returns <code>null</code>.
+	 * Subclasses may reimplement.
+	 * </p>
+	 * 
+	 * @param fieldAccess the field access of interest
+	 * @return the binding for the given field access, or 
+	 *    <code>null</code> if no binding is available
+	 */
+	IVariableBinding resolveField(FieldAccess fieldAccess) {
+		return null;
+	}
+		
+	/**
+	 * Resolves the given super field access and returns the binding for it.
+	 * <p>
+	 * The implementation of <code>SuperFieldAccess.resolveFieldBinding</code>
+	 * forwards to this method. How the field resolves is often a function of
+	 * the context in which the super field access node is embedded as well as
+	 * the super field access subtree itself.
+	 * </p>
+	 * <p>
+	 * The default implementation of this method returns <code>null</code>.
+	 * Subclasses may reimplement.
+	 * </p>
+	 * 
+	 * @param fieldAccess the super field access of interest
+	 * @return the binding for the given field access, or 
+	 *    <code>null</code> if no binding is available
+	 */
+	IVariableBinding resolveField(SuperFieldAccess fieldAccess) {
+		return null;
+	}
+
 	/**
 	 * Resolves the given import declaration and returns the binding for it.
 	 * <p>
@@ -520,6 +563,7 @@
 	 * @param newNode the new AST node
 	 */
 	void updateKey(ASTNode node, ASTNode newNode) {
+		// default implementation: do nothing
 	}
 	
 	/**
@@ -531,9 +575,9 @@
 	 * </p>
 	 *
 	 * @param currentNode the new node
-	 * @return AstNode
+	 * @return org.eclipse.jdt.internal.compiler.ast.ASTNode
 	 */
-	AstNode getCorrespondingNode(ASTNode currentNode) {
+	org.eclipse.jdt.internal.compiler.ast.ASTNode getCorrespondingNode(ASTNode currentNode) {
 		return null;
 	} 
 
@@ -546,5 +590,6 @@
 	 * @param astNode
 	 */	
 	void recordScope(ASTNode astNode, BlockScope blockScope) {
+		// default implementation: do nothing
 	}
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java
index 64c6545..5925646 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/BodyDeclaration.java
@@ -31,9 +31,10 @@
  * </pre>
  * </p>
  * <p>
- * Most types of body declarations can carry a Javadoc comment; Initializer
- * is the only ones that does not. The source range for body declarations
- * always includes the Javadoc comment if present.
+ * All types of body declarations carry modifiers, although they differ in
+ * which modifiers are allowed. Most types of body declarations can carry a
+ * Javadoc comment; Initializer is the only ones that does not. The source range
+ * for body declarations always includes the Javadoc comment if present.
  * </p>
  * 
  * @since 2.0
@@ -47,6 +48,14 @@
 	private Javadoc optionalJavadoc = null;
 
 	/**
+	 * The modifiers; bit-wise or of Modifier flags.
+	 * Defaults to none.
+	 * 
+	 * @since 3.0
+	 */
+	private int modifiers = Modifier.NONE;
+	
+	/**
 	 * Creates a new AST node for a body declaration node owned by the 
 	 * given AST.
 	 * <p>
@@ -79,11 +88,37 @@
 		this.optionalJavadoc = javadoc;
 	}
 
+	/**
+	 * Returns the modifiers explicitly specified on this declaration.
+	 * The allowable modifiers differ for each type of body declaration.
+	 * 
+	 * @return the bit-wise or of <code>Modifier</code> constants
+	 * @see Modifier
+	 * @since 3.0
+	 */ 
+	public int getModifiers() {
+		return modifiers;
+	}
+
+	/**
+	 * Sets the modifiers explicitly specified on this declaration.
+	 * The allowable modifiers differ for each type of body declaration.
+	 * 
+	 * @return the bit-wise or of <code>Modifier</code> constants
+	 * @see Modifier
+	 * @exception IllegalArgumentException if the modifiers are illegal
+	 * @since 3.0
+	 */ 
+	public void setModifiers(int modifiers) {
+		modifying();
+		this.modifiers = modifiers;
+	}
+
 	/* (omit javadoc for this method)
 	 * Method declared on ASTNode.
 	 */
 	int memSize() {
-		return BASE_NODE_SIZE + 1 * 4;
+		return BASE_NODE_SIZE + 2 * 4;
 	}
 }
 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java
index ee53b90..0bb6720 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CharacterLiteral.java
@@ -13,6 +13,7 @@
 
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 
 /**
  * Character literal nodes.
@@ -109,7 +110,7 @@
 		try {
 			int tokenType = scanner.getNextToken();
 			switch(tokenType) {
-				case Scanner.TokenNameCharacterLiteral:
+				case TerminalTokens.TokenNameCharacterLiteral:
 					break;
 				default:
 					throw new IllegalArgumentException();
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
index eebaa57..7c4c87e 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
@@ -191,7 +191,7 @@
 	}
 
 	/**
-	 * Returns the live list of nodes for the import declaration of this 
+	 * Returns the live list of nodes for the import declarations of this 
 	 * compilation unit, in order of appearance.
 	 * 
 	 * @return the live list of import declaration nodes
@@ -202,7 +202,7 @@
 	}
 	
 	/**
-	 * Returns the live list of nodes for the top-level type declaration of this 
+	 * Returns the live list of nodes for the top-level type declarations of this 
 	 * compilation unit, in order of appearance.
 	 * 
 	 * @return the live list of top-level type declaration
@@ -225,7 +225,7 @@
 	 * <li></li>
 	 * <li>package - a <code>PackageDeclaration</code></li>
 	 * <li>class or interface - a <code>TypeDeclaration</code> or a
-	 *    <code>ClassInstanceCreation</code> (for anonymous classes) </li>
+	 *    <code>AnonymousClassDeclaration</code> (for anonymous classes) </li>
 	 * <li>primitive type - none</li>
 	 * <li>array type - none</li>
 	 * <li>field - a <code>VariableDeclarationFragment</code> in a 
@@ -269,7 +269,7 @@
 	 * <li></li>
 	 * <li>package - a <code>PackageDeclaration</code></li>
 	 * <li>class or interface - a <code>TypeDeclaration</code> or a
-	 *    <code>ClassInstanceCreation</code> (for anonymous classes) </li>
+	 *    <code>AnonymousClassDeclaration</code> (for anonymous classes) </li>
 	 * <li>primitive type - none</li>
 	 * <li>array type - none</li>
 	 * <li>field - a <code>VariableDeclarationFragment</code> in a 
@@ -282,6 +282,11 @@
 	 * <li>constructor - a <code>MethodDeclaration</code> </li>
 	 * </ul>
 	 * </p>
+	 * <p>
+	 * Note that as explained in {@link IBinding#getkey IBinding.getkey}
+	 * there may be no keys for finding the declaring node for local variables,
+	 * local or anonymous classes, etc.
+	 * </p>
 	 * 
 	 * @param key the binding key, or <code>null</code>
 	 * @return the corresponding node where a binding with the given
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
index 8279887..9f24933 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
@@ -17,10 +17,10 @@
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
 import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
@@ -48,7 +48,7 @@
 	 *      specify the rules for handling problems (stop on first error or accumulate
 	 *      them all) and at the same time perform some actions such as opening a dialog
 	 *      in UI when compiling interactively.
-	 *      @see org.eclipse.jdt.internal.compiler.api.problem.DefaultErrorHandlingPolicies
+	 *      @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
 	 * 
 	 *	@param settings The settings to use for the resolution.
 	 *      
@@ -56,7 +56,7 @@
 	 *      Component which will receive and persist all compilation results and is intended
 	 *      to consume them as they are produced. Typically, in a batch compiler, it is 
 	 *      responsible for writing out the actual .class files to the file system.
-	 *      @see org.eclipse.jdt.internal.compiler.api.CompilationResult
+	 *      @see org.eclipse.jdt.internal.compiler.CompilationResult
 	 *
 	 *  @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
 	 *      Factory used inside the compiler to create problem descriptors. It allows the
@@ -74,7 +74,7 @@
 
 		super(environment, policy, settings, requestor, problemFactory, false);
 	}
-
+	
 	/**
 	 * Add additional source types
 	 */
@@ -85,9 +85,9 @@
 		CompilationUnitDeclaration unit =
 			SourceTypeConverter.buildCompilationUnit(
 				sourceTypes,//sourceTypes[0] is always toplevel here
-				true, // need field and methods
-				true, // need member types
-				false, // no need for field initialization
+				SourceTypeConverter.FIELD_AND_METHOD // need field and methods
+				| SourceTypeConverter.MEMBER_TYPE // need member types
+				| SourceTypeConverter.FIELD_INITIALIZATION, // need field initialization: see bug 40476
 				lookupEnvironment.problemReporter,
 				result);
 
@@ -97,6 +97,51 @@
 		}
 	}
 
+	private static Parser createDomParser(ProblemReporter problemReporter) {
+		
+		return new Parser(problemReporter, false) {
+			// old annotation style check which doesn't include all leading comments into declaration
+			// for backward compatibility with 2.1 DOM 
+			public void checkComment() {
+
+				if (this.currentElement != null && this.scanner.commentPtr >= 0) {
+					flushCommentsDefinedPriorTo(endStatementPosition); // discard obsolete comments
+				}
+				boolean deprecated = false;
+				boolean checkDeprecated = false;
+				int lastCommentIndex = -1;
+			
+				//since jdk1.2 look only in the last java doc comment...
+				nextComment : for (lastCommentIndex = scanner.commentPtr; lastCommentIndex >= 0; lastCommentIndex--){
+					//look for @deprecated into the first javadoc comment preceeding the declaration
+					int commentSourceStart = scanner.commentStarts[lastCommentIndex];
+					// javadoc only (non javadoc comment have negative end positions.)
+					if (modifiersSourceStart != -1 && modifiersSourceStart < commentSourceStart) {
+						continue nextComment;
+					}
+					if (scanner.commentStops[lastCommentIndex] < 0) {
+						continue nextComment;
+					}
+					checkDeprecated = true;
+					int commentSourceEnd = scanner.commentStops[lastCommentIndex] - 1; //stop is one over
+			
+					deprecated =
+						this.javadocParser.checkDeprecation(commentSourceStart, commentSourceEnd);
+					this.javadoc = this.javadocParser.javadoc;
+					break nextComment;
+				}
+				if (deprecated) {
+					checkAndSetModifiers(AccDeprecated);
+				}
+				// modify the modifier source start to point at the first comment
+				if (lastCommentIndex >= 0 && checkDeprecated) {
+					modifiersSourceStart = scanner.commentStarts[lastCommentIndex]; 
+				}
+
+			}
+		};
+	}
+
 	/*
 	 *  Low-level API performing the actual compilation
 	 */
@@ -131,13 +176,45 @@
 	protected static ICompilerRequestor getRequestor() {
 		return new ICompilerRequestor() {
 			public void acceptResult(CompilationResult compilationResult) {
+				// do nothing
 			}
 		};
 	}
 
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.Compiler#initializeParser()
+	 */
+	public void initializeParser() {
+		this.parser = createDomParser(this.problemReporter);
+	}
+	/*
+	 * Compiler crash recovery in case of unexpected runtime exceptions
+	 */
+	protected void handleInternalException(
+			Throwable internalException,
+			CompilationUnitDeclaration unit,
+			CompilationResult result) {
+		super.handleInternalException(internalException, unit, result);
+		if (unit != null) {
+			removeUnresolvedBindings(unit);
+		}
+	}
+	
+	/*
+	 * Compiler recovery in case of internal AbortCompilation event
+	 */
+	protected void handleInternalException(
+			AbortCompilation abortException,
+			CompilationUnitDeclaration unit) {
+		super.handleInternalException(abortException, unit);
+		if (unit != null) {
+			removeUnresolvedBindings(unit);
+		}
+	}	
 	public static CompilationUnitDeclaration resolve(
 		ICompilationUnit unitElement,
-		IAbstractSyntaxTreeVisitor visitor)
+		boolean cleanUp,
+		char[] source)
 		throws JavaModelException {
 
 		char[] fileName = unitElement.getElementName().toCharArray();
@@ -148,7 +225,7 @@
 				getHandlingPolicy(),
 				project.getOptions(true),
 				getRequestor(),
-				getProblemFactory(fileName, visitor));
+				new DefaultProblemFactory());
 
 		CompilationUnitDeclaration unit = null;
 		try {
@@ -163,7 +240,7 @@
 			unit =
 				compilationUnitVisitor.resolve(
 					new BasicCompilationUnit(
-						unitElement.getSource().toCharArray(),
+						source,
 						expectedPackageName,
 						new String(fileName),
 						encoding),
@@ -172,7 +249,7 @@
 					true); // generate code
 			return unit;
 		} finally {
-			if (unit != null) {
+			if (cleanUp && unit != null) {
 				unit.cleanUp();
 			}
 		}
@@ -183,14 +260,11 @@
 			throw new IllegalArgumentException();
 		}
 		CompilerOptions compilerOptions = new CompilerOptions(settings);
-		Parser parser =
-			new Parser(
-				new ProblemReporter(
+		Parser parser = createDomParser(
+			new ProblemReporter(
 					DefaultErrorHandlingPolicies.proceedWithAllProblems(), 
 					compilerOptions, 
-					new DefaultProblemFactory(Locale.getDefault())),
-			false,
-			compilerOptions.sourceLevel >= CompilerOptions.JDK1_4);
+					new DefaultProblemFactory()));
 		org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = 
 			new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(
 				source, 
@@ -215,43 +289,61 @@
 		return compilationUnitDeclaration;
 	}
 
-	protected static IProblemFactory getProblemFactory(final char[] fileName, final IAbstractSyntaxTreeVisitor visitor) {
-
-		return new DefaultProblemFactory(Locale.getDefault()) {
-			public IProblem createProblem(
-				char[] originatingFileName,
-				int problemId,
-				String[] problemArguments,
-				String[] messageArguments,
-				int severity,
-				int startPosition,
-				int endPosition,
-				int lineNumber) {
-
-				IProblem problem =
-					super.createProblem(
-						originatingFileName,
-						problemId,
-						problemArguments,
-						messageArguments,
-						severity,
-						startPosition,
-						endPosition,
-						lineNumber);
-				// only consider problems associated with resolved file
-				if (CharOperation.equals(originatingFileName, fileName)){
-					visitor.acceptProblem(problem);
-				}
-				return problem;
-			}
-		};
+	public static CompilationUnitDeclaration parse(char[] source, NodeSearcher nodeSearcher, Map settings) {
+		if (source == null) {
+			throw new IllegalArgumentException();
+		}
+		CompilerOptions compilerOptions = new CompilerOptions(settings);
+		Parser parser = createDomParser(
+			new ProblemReporter(
+					DefaultErrorHandlingPolicies.proceedWithAllProblems(), 
+					compilerOptions, 
+					new DefaultProblemFactory()));
+		org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = 
+			new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(
+				source, 
+				"", //$NON-NLS-1$
+				compilerOptions.defaultEncoding);
+		CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit));
+		
+		if (compilationUnitDeclaration.ignoreMethodBodies) {
+			compilationUnitDeclaration.ignoreFurtherInvestigation = true;
+			// if initial diet parse did not work, no need to dig into method bodies.
+			return null; 
+		}
+		
+		int searchPosition = nodeSearcher.position;
+		if (searchPosition < 0 || searchPosition > source.length) {
+			// the position is out of range. There is no need to search for a node.
+ 			return compilationUnitDeclaration;
+		}
+	
+		compilationUnitDeclaration.traverse(nodeSearcher, compilationUnitDeclaration.scope);
+		
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
+ 		if (node == null) {
+ 			return compilationUnitDeclaration;
+ 		}
+ 		
+ 		org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
+ 		
+		if (node instanceof AbstractMethodDeclaration) {
+			((AbstractMethodDeclaration)node).parseStatements(parser, compilationUnitDeclaration);
+		} else if (enclosingTypeDeclaration != null) {
+			if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
+				((org.eclipse.jdt.internal.compiler.ast.Initializer) node).parseStatements(parser, enclosingTypeDeclaration, compilationUnitDeclaration);
+			} else {  					
+				((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)node).parseMethod(parser, compilationUnitDeclaration);
+			} 				
+		}
+		
+		return compilationUnitDeclaration;
 	}
-
 	public static CompilationUnitDeclaration resolve(
 		char[] source,
 		String unitName,
 		IJavaProject javaProject,
-		IAbstractSyntaxTreeVisitor visitor)
+		boolean cleanUp)
 		throws JavaModelException {
 	
 		CompilationUnitResolver compilationUnitVisitor =
@@ -260,7 +352,7 @@
 				getHandlingPolicy(),
 				javaProject.getOptions(true),
 				getRequestor(),
-				getProblemFactory(unitName.toCharArray(), visitor));
+				new DefaultProblemFactory());
 	
 		CompilationUnitDeclaration unit = null;
 		try {
@@ -278,7 +370,52 @@
 					true); // generate code
 			return unit;
 		} finally {
-			if (unit != null) {
+			if (cleanUp && unit != null) {
+				unit.cleanUp();
+			}
+		}
+	}
+
+	public static CompilationUnitDeclaration resolve(
+		ICompilationUnit unitElement,
+		NodeSearcher nodeSearcher,
+		boolean cleanUp,
+		char[] source)
+		throws JavaModelException {
+
+		CompilationUnitDeclaration unit = null;
+		try {
+			char[] fileName = unitElement.getElementName().toCharArray();
+			IJavaProject project = unitElement.getJavaProject();
+			CompilationUnitResolver compilationUnitVisitor =
+				new CompilationUnitResolver(
+					getNameEnvironment(unitElement),
+					getHandlingPolicy(),
+					project.getOptions(true),
+					getRequestor(),
+					new DefaultProblemFactory());
+	
+			String encoding = project.getOption(JavaCore.CORE_ENCODING, true);
+	
+			IPackageFragment packageFragment = (IPackageFragment)unitElement.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
+			char[][] expectedPackageName = null;
+			if (packageFragment != null){
+				expectedPackageName = CharOperation.splitOn('.', packageFragment.getElementName().toCharArray());
+			}
+		
+			unit = compilationUnitVisitor.resolve(
+				new BasicCompilationUnit(
+					source,
+					expectedPackageName,
+					new String(fileName),
+					encoding),
+				nodeSearcher,
+				true, // method verification
+				true, // analyze code
+				true); // generate code
+			return unit;
+		} finally {
+			if (cleanUp && unit != null) {
 				unit.cleanUp();
 			}
 		}
@@ -289,7 +426,7 @@
 		char[][] packageName,
 		String unitName,
 		IJavaProject javaProject,
-		IAbstractSyntaxTreeVisitor visitor)
+		boolean cleanUp)
 		throws JavaModelException {
 	
 		CompilationUnitResolver compilationUnitVisitor =
@@ -298,7 +435,7 @@
 				getHandlingPolicy(),
 				javaProject.getOptions(true),
 				getRequestor(),
-				getProblemFactory(unitName.toCharArray(), visitor));
+				new DefaultProblemFactory());
 	
 		CompilationUnitDeclaration unit = null;
 		try {
@@ -313,13 +450,211 @@
 						encoding),
 					true, // method verification
 					true, // analyze code
-					true); // generate code
+					true); // generate code					
 			return unit;
 		} finally {
-			if (unit != null) {
+			if (cleanUp && unit != null) {
 				unit.cleanUp();
 			}
 		}
-	}	
+	}
+	/*
+	 * When unit result is about to be accepted, removed back pointers
+	 * to unresolved bindings
+	 */
+	public void removeUnresolvedBindings(CompilationUnitDeclaration compilationUnitDeclaration) {
+		final org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+		if (types != null) {
+			for (int i = 0, max = types.length; i < max; i++) {
+				removeUnresolvedBindings(types[i]);
+			}
+		}
+	}
+	private void removeUnresolvedBindings(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration type) {
+		final org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] memberTypes = type.memberTypes;
+		if (memberTypes != null) {
+			for (int i = 0, max = memberTypes.length; i < max; i++){
+				removeUnresolvedBindings(memberTypes[i]);
+			}
+		}
+		if (type.binding != null && (type.binding.modifiers & CompilerModifiers.AccUnresolved) != 0) {
+			type.binding = null;
+		}
+		
+		final org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = type.fields;
+		if (fields != null) {
+			for (int i = 0, max = fields.length; i < max; i++){
+				if (fields[i].binding != null && (fields[i].binding.modifiers & CompilerModifiers.AccUnresolved) != 0) {
+					fields[i].binding = null;
+				}
+			}
+		}
 	
+		final AbstractMethodDeclaration[] methods = type.methods;
+		if (methods != null) {
+			for (int i = 0, max = methods.length; i < max; i++){
+				if (methods[i].binding !=  null && (methods[i].binding.modifiers & CompilerModifiers.AccUnresolved) != 0) {
+					methods[i].binding = null;
+				}
+			}
+		}
+	}
+
+	/**
+	 * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+	 */
+	public CompilationUnitDeclaration resolve(
+			org.eclipse.jdt.internal.compiler.env.ICompilationUnit compilationUnit,
+			NodeSearcher nodeSearcher,
+			boolean verifyMethods,
+			boolean analyzeCode,
+			boolean generateCode) {
+
+		CompilationUnitDeclaration unit = null;
+		try {
+
+			parseThreshold = 0; // will request a diet parse
+			beginToCompile(new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] { compilationUnit});
+			// process all units (some more could be injected in the loop by the lookup environment)
+			unit = unitsToProcess[0];
+
+			int searchPosition = nodeSearcher.position;
+			if (searchPosition >= 0 && searchPosition <= compilationUnit.getContents().length) {
+				unit.traverse(nodeSearcher, unit.scope);
+				
+				org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
+				
+	 			if (node != null) {
+					org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
+	  				if (node instanceof AbstractMethodDeclaration) {
+						((AbstractMethodDeclaration)node).parseStatements(parser, unit);
+	 				} else if (enclosingTypeDeclaration != null) {
+						if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
+		 					((org.eclipse.jdt.internal.compiler.ast.Initializer) node).parseStatements(parser, enclosingTypeDeclaration, unit);
+	 					} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {  					
+							((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)node).parseMethod(parser, unit);
+						} 				
+	 				}
+	 			}
+			}
+			if (unit.scope != null) {
+				// fault in fields & methods
+				unit.scope.faultInTypes();
+				if (unit.scope != null && verifyMethods) {
+					// http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
+ 					// verify inherited methods
+					unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
+				}
+				// type checking
+				unit.resolve();		
+
+				// flow analysis
+				if (analyzeCode) unit.analyseCode();
+		
+				// code generation
+				if (generateCode) unit.generateCode();
+			}
+			if (unitsToProcess != null) unitsToProcess[0] = null; // release reference to processed unit declaration
+			requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+			return unit;
+		} catch (AbortCompilation e) {
+			this.handleInternalException(e, unit);
+			return null;
+		} catch (Error e) {
+			this.handleInternalException(e, unit, null);
+			throw e; // rethrow
+		} catch (RuntimeException e) {
+			this.handleInternalException(e, unit, null);
+			throw e; // rethrow
+		} finally {
+			// No reset is performed there anymore since,
+			// within the CodeAssist (or related tools),
+			// the compiler may be called *after* a call
+			// to this resolve(...) method. And such a call
+			// needs to have a compiler with a non-empty
+			// environment.
+			// this.reset();
+		}
+	}
+	/**
+	 * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+	 */
+	public CompilationUnitDeclaration resolve(
+			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit, 
+			boolean verifyMethods,
+			boolean analyzeCode,
+			boolean generateCode) {
+				
+		return resolve(
+			null,
+			sourceUnit,
+			verifyMethods,
+			analyzeCode,
+			generateCode);
+	}
+
+	/**
+	 * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+	 */
+	public CompilationUnitDeclaration resolve(
+			CompilationUnitDeclaration unit, 
+			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit, 
+			boolean verifyMethods,
+			boolean analyzeCode,
+			boolean generateCode) {
+				
+		try {
+			if (unit == null) {
+				// build and record parsed units
+				parseThreshold = 0; // will request a full parse
+				beginToCompile(new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] { sourceUnit });
+				// process all units (some more could be injected in the loop by the lookup environment)
+				unit = unitsToProcess[0];
+			} else {
+				// initial type binding creation
+				lookupEnvironment.buildTypeBindings(unit);
+
+				// binding resolution
+				lookupEnvironment.completeTypeBindings();
+			}
+			this.parser.getMethodBodies(unit);
+			if (unit.scope != null) {
+				// fault in fields & methods
+				unit.scope.faultInTypes();
+				if (unit.scope != null && verifyMethods) {
+					// http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
+ 					// verify inherited methods
+					unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
+				}
+				// type checking
+				unit.resolve();		
+
+				// flow analysis
+				if (analyzeCode) unit.analyseCode();
+		
+				// code generation
+				if (generateCode) unit.generateCode();
+			}
+			if (unitsToProcess != null) unitsToProcess[0] = null; // release reference to processed unit declaration
+			requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+			return unit;
+		} catch (AbortCompilation e) {
+			this.handleInternalException(e, unit);
+			return unit == null ? unitsToProcess[0] : unit;
+		} catch (Error e) {
+			this.handleInternalException(e, unit, null);
+			throw e; // rethrow
+		} catch (RuntimeException e) {
+			this.handleInternalException(e, unit, null);
+			throw e; // rethrow
+		} finally {
+			// No reset is performed there anymore since,
+			// within the CodeAssist (or related tools),
+			// the compiler may be called *after* a call
+			// to this resolve(...) method. And such a call
+			// needs to have a compiler with a non-empty
+			// environment.
+			// this.reset();
+		}
+	}
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
index 795ade4..0525611 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
@@ -50,11 +50,6 @@
 	Map bindingKeysToAstNodes;
 	
 	/**
-	 * This map is used to get a binding from its ast node
-	 */
-	Map astNodesToBindings;
-	
-	/**
 	 * This map is used to retrieve the corresponding block scope for a ast node
 	 */
 	Map astNodesToBlockScope;
@@ -71,7 +66,6 @@
 		this.newAstToOldAst = new HashMap();
 		this.compilerBindingsToASTBindings = new HashMap();
 		this.bindingsToAstNodes = new HashMap();
-		this.astNodesToBindings = new HashMap();
 		this.astNodesToBlockScope = new HashMap();
 		this.bindingKeysToAstNodes = new HashMap();
 	}
@@ -88,7 +82,7 @@
 	 * Method declared on BindingResolver.
 	 */
 	IBinding resolveName(Name name) {
-		AstNode node = (AstNode) this.newAstToOldAst.get(name);
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(name);
 		int index = name.index;
 		if (node instanceof QualifiedNameReference) {
 			QualifiedNameReference qualifiedNameReference = (QualifiedNameReference) node;
@@ -128,7 +122,7 @@
 									case ProblemReasons.NonStaticReferenceInStaticContext :
 										ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
 										if (declaringClass != null) {
-											FieldBinding exactBinding = declaringClass.getField(tokens[tokens.length - 1]);
+											FieldBinding exactBinding = declaringClass.getField(tokens[tokens.length - 1], true /*resolve*/);
 											if (exactBinding != null) {
 												IVariableBinding variableBinding = (IVariableBinding) this.compilerBindingsToASTBindings.get(exactBinding);
 												if (variableBinding != null) {
@@ -206,7 +200,7 @@
 			if (types == null || types.length == 0) {
 				return null;
 			}
-			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration type = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) types[0];
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration type = types[0];
 			if (type != null) {
 				ITypeBinding typeBinding = this.getTypeBinding(type.binding);
 				if (typeBinding != null) {
@@ -248,7 +242,7 @@
 								case ProblemReasons.NonStaticReferenceInStaticContext :
 								case ProblemReasons.NonStaticReferenceInConstructorInvocation :
 									ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
-									FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name);
+									FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
 									if (exactBinding != null) {
 										IVariableBinding variableBinding2 = (IVariableBinding) this.compilerBindingsToASTBindings.get(exactBinding);
 										if (variableBinding2 != null) {
@@ -274,7 +268,7 @@
 		} else if (node instanceof SingleTypeReference) {
 			SingleTypeReference singleTypeReference = (SingleTypeReference) node;
 			org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding = singleTypeReference.resolvedType;
-			if (binding != null && binding instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding) {
+			if (binding != null) {
 				return this.getTypeBinding(binding.leafComponentType());
 			}
 		} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.FieldDeclaration) {
@@ -292,7 +286,7 @@
 	 */
 	ITypeBinding resolveType(Type type) {
 		// retrieve the old ast node
-		AstNode node = (AstNode) this.newAstToOldAst.get(type);
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
 		org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding = null;
 		if (node != null) {
 			if (node instanceof TypeReference) {
@@ -325,7 +319,7 @@
 			}
 		} else if (type.isPrimitiveType()) {
 			if (((PrimitiveType) type).getPrimitiveTypeCode() == PrimitiveType.VOID) {
-				return this.getTypeBinding(BaseTypeBinding.VoidBinding);
+				return this.getTypeBinding(BaseTypes.VoidBinding);
 			}
 		}
 		return null;
@@ -361,7 +355,11 @@
 			return this.getTypeBinding(this.scope.getJavaLangError());
 		} else if ("java.lang.Class".equals(name)) {//$NON-NLS-1$ 
 			return this.getTypeBinding(this.scope.getJavaLangClass());
-	    } else {
+	    } else if ("java.lang.Cloneable".equals(name)) {//$NON-NLS-1$ 
+			return this.getTypeBinding(this.scope.getJavaLangCloneable());
+		} else if ("java.io.Serializable".equals(name)) {//$NON-NLS-1$ 
+			return this.getTypeBinding(this.scope.getJavaIoSerializable());
+		} else {
 			return null;
 		}
 	}
@@ -417,16 +415,7 @@
 		if (oldNode instanceof MessageSend) {
 			MessageSend messageSend = (MessageSend) oldNode;
 			if (messageSend != null) {
-				IMethodBinding methodBinding = this.getMethodBinding(messageSend.binding);
-				if (methodBinding == null) {
-					return null;
-				}
-				this.bindingsToAstNodes.put(methodBinding, method);
-				String key = methodBinding.getKey();
-				if (key != null) {
-					this.bindingKeysToAstNodes.put(key, method);				
-				}
-				return methodBinding;
+				return this.getMethodBinding(messageSend.binding);
 			}
 		}
 		return null;
@@ -439,16 +428,7 @@
 		if (oldNode instanceof MessageSend) {
 			MessageSend messageSend = (MessageSend) oldNode;
 			if (messageSend != null) {
-				IMethodBinding methodBinding = this.getMethodBinding(messageSend.binding);
-				if (methodBinding == null) {
-					return null;
-				}
-				this.bindingsToAstNodes.put(methodBinding, method);
-				String key = methodBinding.getKey();
-				if (key != null) {
-					this.bindingKeysToAstNodes.put(key, method);				
-				}
-				return methodBinding;
+				return this.getMethodBinding(messageSend.binding);
 			}
 		}
 		return null;
@@ -511,7 +491,7 @@
 	 */
 	ITypeBinding resolveExpressionType(Expression expression) {
 		if (expression instanceof ClassInstanceCreation) {
-			AstNode astNode = (AstNode) this.newAstToOldAst.get(expression);
+			org.eclipse.jdt.internal.compiler.ast.ASTNode astNode = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
 			if (astNode instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
 				org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) astNode;
 				if (typeDeclaration != null) {
@@ -643,16 +623,44 @@
 	}
 
 	/*
+	 * @see BindingResolver#resolveField(FieldAccess)
+	 */
+	IVariableBinding resolveField(FieldAccess fieldAccess) {
+		Object oldNode = this.newAstToOldAst.get(fieldAccess);
+		if (oldNode instanceof FieldReference) {
+			FieldReference fieldReference = (FieldReference) oldNode;
+			if (fieldReference != null) {
+				return this.getVariableBinding(fieldReference.binding);
+			}
+		}
+		return null;
+	}
+
+	/*
+	 * @see BindingResolver#resolveField(SuperFieldAccess)
+	 */
+	IVariableBinding resolveField(SuperFieldAccess fieldAccess) {
+		Object oldNode = this.newAstToOldAst.get(fieldAccess);
+		if (oldNode instanceof FieldReference) {
+			FieldReference fieldReference = (FieldReference) oldNode;
+			if (fieldReference != null) {
+				return this.getVariableBinding(fieldReference.binding);
+			}
+		}
+		return null;
+	}
+
+	/*
 	 * @see BindingResolver#resolveImport(ImportDeclaration)
 	 */
 	IBinding resolveImport(ImportDeclaration importDeclaration) {
-		AstNode node = (AstNode) this.newAstToOldAst.get(importDeclaration);
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(importDeclaration);
 		if (node instanceof ImportReference) {
 			ImportReference importReference = (ImportReference) node;
 			if (importReference.onDemand) {
 				Binding binding = this.scope.getTypeOrPackage(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length));
 				if (binding != null) {
-					if (binding.bindingType() == Binding.PACKAGE) {
+					if (binding.bindingType() == BindingIds.PACKAGE) {
 						IPackageBinding packageBinding = this.getPackageBinding((org.eclipse.jdt.internal.compiler.lookup.PackageBinding) binding);
 						if (packageBinding == null) {
 							return null;
@@ -682,7 +690,7 @@
 	 * @see BindingResolver#resolvePackage(PackageDeclaration)
 	 */
 	IPackageBinding resolvePackage(PackageDeclaration pkg) {
-		AstNode node = (AstNode) this.newAstToOldAst.get(pkg);
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(pkg);
 		if (node instanceof ImportReference) {
 			ImportReference importReference = (ImportReference) node;
 			Binding binding = this.scope.getTypeOrPackage(CharOperation.subarray(importReference.tokens, 0, importReference.tokens.length));
@@ -722,7 +730,7 @@
 	/*
 	 * Method declared on BindingResolver.
 	 */
-	void store(ASTNode node, AstNode oldASTNode) {
+	void store(ASTNode node, org.eclipse.jdt.internal.compiler.ast.ASTNode oldASTNode) {
 		this.newAstToOldAst.put(node, oldASTNode);
 	}
 	
@@ -782,7 +790,7 @@
 		if (binding != null) {
 			return binding;
 		}
-		binding = new PackageBinding(this, packageBinding);
+		binding = new PackageBinding(packageBinding);
 		this.compilerBindingsToASTBindings.put(packageBinding, binding);
 		return binding;
 	}
@@ -810,7 +818,7 @@
 						case ProblemReasons.NonStaticReferenceInStaticContext :
 						case ProblemReasons.NonStaticReferenceInConstructorInvocation :
 							ReferenceBinding declaringClass = problemFieldBinding.declaringClass;
-							FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name);
+							FieldBinding exactBinding = declaringClass.getField(problemFieldBinding.name, true /*resolve*/);
 							if (exactBinding != null) {
 								IVariableBinding variableBinding2 = (IVariableBinding) this.compilerBindingsToASTBindings.get(exactBinding);
 								if (variableBinding2 != null) {
@@ -873,9 +881,9 @@
 	 * @see BindingResolver#resolveConstructor(ClassInstanceCreation)
 	 */
 	IMethodBinding resolveConstructor(ClassInstanceCreation expression) {
-		AstNode node = (AstNode) this.newAstToOldAst.get(expression);
-		if (node instanceof AnonymousLocalTypeDeclaration) {
-			AnonymousLocalTypeDeclaration anonymousLocalTypeDeclaration = (AnonymousLocalTypeDeclaration) node;
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
+		if (node != null && (node.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsAnonymousTypeMASK) != 0) {
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
 			return this.getMethodBinding(anonymousLocalTypeDeclaration.allocation.binding);
 		} else if (node instanceof AllocationExpression) {
 			return this.getMethodBinding(((AllocationExpression)node).binding);
@@ -887,7 +895,7 @@
 	 * @see BindingResolver#resolveConstructor(ConstructorInvocation)
 	 */
 	IMethodBinding resolveConstructor(ConstructorInvocation expression) {
-		AstNode node = (AstNode) this.newAstToOldAst.get(expression);
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
 		if (node instanceof ExplicitConstructorCall) {
 			ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
 			return this.getMethodBinding(explicitConstructorCall.binding);
@@ -899,7 +907,7 @@
 	 * @see BindingResolver#resolveConstructor(SuperConstructorInvocation)
 	 */
 	IMethodBinding resolveConstructor(SuperConstructorInvocation expression) {
-		AstNode node = (AstNode) this.newAstToOldAst.get(expression);
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(expression);
 		if (node instanceof ExplicitConstructorCall) {
 			ExplicitConstructorCall explicitConstructorCall = (ExplicitConstructorCall) node;
 			return this.getMethodBinding(explicitConstructorCall.binding);
@@ -910,9 +918,9 @@
 	 * @see BindingResolver#resolveType(AnonymousClassDeclaration)
 	 */
 	ITypeBinding resolveType(AnonymousClassDeclaration type) {
-		final Object node = this.newAstToOldAst.get(type);
-		if (node instanceof org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration) {
-			org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration anonymousLocalTypeDeclaration = (org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration) node;
+		org.eclipse.jdt.internal.compiler.ast.ASTNode node = (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(type);
+		if (node != null && (node.bits & org.eclipse.jdt.internal.compiler.ast.ASTNode.IsAnonymousTypeMASK) != 0) {
+			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration anonymousLocalTypeDeclaration = (org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) node;
 			if (anonymousLocalTypeDeclaration != null) {
 				ITypeBinding typeBinding = this.getTypeBinding(anonymousLocalTypeDeclaration.binding);
 				if (typeBinding == null) {
@@ -929,8 +937,8 @@
 		return null;
 	}
 
-	AstNode getCorrespondingNode(ASTNode currentNode) {
-		return (AstNode) this.newAstToOldAst.get(currentNode);
+	org.eclipse.jdt.internal.compiler.ast.ASTNode getCorrespondingNode(ASTNode currentNode) {
+		return (org.eclipse.jdt.internal.compiler.ast.ASTNode) this.newAstToOldAst.get(currentNode);
 	} 
 	/**
 	 * @see org.eclipse.jdt.core.dom.BindingResolver#recordScope(ASTNode, BlockScope)
@@ -938,5 +946,4 @@
 	void recordScope(ASTNode astNode, BlockScope blockScope) {
 		this.astNodesToBlockScope.put(astNode, blockScope);
 	}
-
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java
index 6903a0e..f898130 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DoStatement.java
@@ -140,6 +140,14 @@
 	
 	/**
 	 * Sets the body of this do statement.
+	 * <p>
+	 * Special note: The Java language does not allow a local variable declaration
+	 * to appear as the body of a do statement (they may only appear within a
+	 * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+	 * as the body of a <code>DoStatement</code>. To get something that will
+	 * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+	 * inside a <code>Block</code>.
+	 * </p>
 	 * 
 	 * @param statement the body statement node
 	 * @exception IllegalArgumentException if:
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java
index bbb1cdd..d822738 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldAccess.java
@@ -149,7 +149,7 @@
 			throw new IllegalArgumentException();
 		}
 		// a FieldAccess may occur inside an Expression - must check cycles
-		replaceChild((ASTNode) this.expression, (ASTNode) expression, true);
+		replaceChild(this.expression, expression, true);
 		this.expression = expression;
 	}
 
@@ -195,6 +195,22 @@
 		return BASE_NODE_SIZE + 2 * 4;
 	}
 	
+	/**
+	 * Resolves and returns the binding for the field accessed by this
+	 * expression.
+	 * <p>
+	 * Note that bindings are generally unavailable unless requested when the
+	 * AST is being built.
+	 * </p>
+	 *
+	 * @return the variable binding, or <code>null</code> if the binding cannot
+	 * be resolved
+	 * @since 3.0
+	 */
+	public IVariableBinding resolveFieldBinding() {
+		return getAST().getBindingResolver().resolveField(this);
+	}
+	
 	/* (omit javadoc for this method)
 	 * Method declared on ASTNode.
 	 */
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java
index ea06be1..680b7af 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/FieldDeclaration.java
@@ -46,12 +46,6 @@
 		| Modifier.TRANSIENT;
 
 	/**
-	 * The modifiers; bit-wise or of Modifier flags.
-	 * Defaults to none.
-	 */
-	private int modifiers = Modifier.NONE;
-		
-	/**
 	 * The base type; lazily initialized; defaults to an unspecified,
 	 * legal type.
 	 */
@@ -93,7 +87,7 @@
 		FieldDeclaration result = new FieldDeclaration(target);
 		result.setSourceRange(this.getStartPosition(), this.getLength());
 		result.setJavadoc(
-			(Javadoc) ASTNode.copySubtree(target,(ASTNode) getJavadoc()));
+			(Javadoc) ASTNode.copySubtree(target, getJavadoc()));
 		result.setModifiers(getModifiers());
 		result.setType((Type) getType().clone(target));
 		result.fragments().addAll(
@@ -127,33 +121,30 @@
 	 * Returns the modifiers explicitly specified on this declaration.
 	 * <p>
 	 * The following modifiers are valid for fields: public, private, protected,
-	 * static, final, volatile, and transient.
+	 * static, final, volatile, and transient. Note that deprecated is not included.
 	 * </p>
 	 * 
-	 * @return the bit-wise or of <code>Modifier</code> constants
-	 * @see Modifier
+	 * @since 2.0
 	 */ 
 	public int getModifiers() {
-		return modifiers;
+		// method needed only for javadoc
+		return super.getModifiers();
 	}
 
 	/**
 	 * Sets the modifiers explicitly specified on this declaration.
 	 * <p>
 	 * The following modifiers are valid for fields: public, private, protected,
-	 * static, final, volatile, and transient.
+	 * static, final, volatile, and transient. Note that deprecated is not included.
 	 * </p>
 	 * 
-	 * @return the bit-wise or of <code>Modifier</code> constants
-	 * @see Modifier
-	 * @exception IllegalArgumentException if the modifiers are illegal
+	 * @since 2.0
 	 */ 
 	public void setModifiers(int modifiers) {
 		if ((modifiers & ~LEGAL_MODIFIERS) != 0) {
 			throw new IllegalArgumentException();
 		}
-		modifying();
-		this.modifiers = modifiers;
+		super.setModifiers(modifiers);
 	}
 
 	/**
@@ -230,7 +221,7 @@
 	 * Method declared on ASTNode.
 	 */
 	int memSize() {
-		return super.memSize() + 3 * 4;
+		return super.memSize() + 2 * 4;
 	}
 	
 	/* (omit javadoc for this method)
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java
index 6ae1220..cf6eaf9 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ForStatement.java
@@ -193,6 +193,14 @@
 	
 	/**
 	 * Sets the body of this for statement.
+	 * <p>
+	 * Special note: The Java language does not allow a local variable declaration
+	 * to appear as the body of a for statement (they may only appear within a
+	 * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+	 * as the body of a <code>ForStatement</code>. To get something that will
+	 * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+	 * inside a <code>Block</code>.
+	 * </p>
 	 * 
 	 * @param statement the body statement node
 	 * @exception IllegalArgumentException if:
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java
index 18805af..784966c 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IBinding.java
@@ -109,10 +109,17 @@
 	/**
 	 * Returns whether this binding is synthetic. A synthetic binding is one that
 	 * was made up by the compiler, rather than something declared in the 
-	 * source code.
+	 * source code. Note that default constructors (the 0-argument constructor that
+	 * the compiler generates for class declarations with no explicit constructors
+	 * declarations) are not generally considered synthetic (although they
+	 * may be if the class itself is synthetic). 
+	 * But see {@link IMethodBinding#isDefaultConstructor IMethodBinding.isDefaultConstructor}
+	 * for cases where the compiled-generated default constructor can be recognized
+	 * instead.
 	 * 
 	 * @return <code>true</code> if this binding is synthetic, and 
 	 *    <code>false</code> otherwise
+	 * @see IMethodBinding#isDefaultConstructor
 	 */
 	public boolean isSynthetic();
 	
@@ -144,12 +151,13 @@
 	 *   type, and the keys of the parameter types</li>
 	 * <li>constructors - the key of its declaring class, and the 
 	 *   keys of the parameter types</li>
+	 * <li>local variables - the name of the local variable, the index of the 
+	 *   declaring block relative to its parent, the key of its method</li>
+	 * <li>local types - the name of the type, the index of the declaring
+	 *   block relative to its parent, the key of its method</li>
+	 * <li>anonymous types - the occurence count of the anonymous 
+	 *   type relative to its declaring type, the key of its declaring type</li>
 	 * </ul>
-	 * Some bindings, like ones that correspond to declarations occurring
-	 * within the body of a method, are problematic because of the lack of
-	 * any universally acceptable way of assigning keys that are both
-	 * predictable and stable. The keys for bindings to local variables, 
-	 * local types, etc. is unspecified, and may be <code>null</code>.
 	 * </p>
 	 * 
 	 * @return the key for this binding, or <code>null</code> if none
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java
index 99e4b61..b42da6c 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IMethodBinding.java
@@ -29,6 +29,30 @@
 	 *    and <code>false</code> if this is the binding for a method
 	 */ 
 	public boolean isConstructor();
+
+	/**
+	 * Returns whether this binding is known to be a compiler-generated 
+	 * default constructor. 
+	 * <p>
+	 * This method returns <code>false</code> for:
+	 * <ul>
+	 * <li>methods</li>
+	 * <li>constructors with more than one parameter</li>
+	 * <li>0-argument constructors where the binding information was obtained
+	 * from a Java source file containing an explicit 0-argument constructor
+	 * declaration</li>
+	 * <li>0-argument constructors where the binding information was obtained
+	 * from a Java class file (it is not possible to determine from a
+	 * class file whether a 0-argument constructor was present in the source
+	 * code versus generated automatically by a Java compiler)</li>
+	 * </ul>
+	 * 
+	 * @return <code>true</code> if this is known to be the binding for a 
+	 * compiler-generated default constructor, and <code>false</code>
+	 * otherwise
+	 * @since 3.0
+	 */ 
+	public boolean isDefaultConstructor();
 	
 	/**
 	 * Returns the name of the method declared in this binding. The method name
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
index 1708962..bd8202a 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
@@ -23,137 +23,85 @@
  * @since 2.0
  */
 public interface ITypeBinding extends IBinding {
-	
-	/**
-	 * Returns whether this type binding represents a primitive type.
-	 * <p>
-	 * There are nine predefined type bindings to represent the eight primitive
-	 * types and <code>void</code>. These have the same names as the primitive
-	 * types that they represent, namely boolean, byte, char, short, int,
-	 * long, float, and double, and void.
-	 * </p>
-	 * <p>
-	 * The set of primitive types is mutually exclusive with the sets of
-	 * array types, with the sets of class and interface types, and with the null type.
-	 * </p>
-	 * 
-	 * @return <code>true</code> if this type binding is for a primitive type,
-	 *   and <code>false</code> otherwise
-	 *
-	 * @see #isArray()
-	 * @see #isClass()
-	 * @see #isInterface()
-	 */
-	public boolean isPrimitive();
 
 	/**
-	 * Returns whether this type binding represents the null type.
+	 * Returns the binary name of this type binding.
+	 * The binary name of a class is defined in the Java Language 
+	 * Specification 2nd edition, section 13.1.
 	 * <p>
-	 * The null type is the type of a <code>NullLiteral</code> node.
+	 * Note that in some cases, the binary name may be unavailable.
+	 * This may happen, for example, for a local type declared in 
+	 * unreachable code.
 	 * </p>
-	 * <p>
-	 * The null type is mutually exclusive with the sets of
-	 * array types, with the sets of class and interface types, and 
-	 * with the set of primitive types .
-	 * </p>
+	 *
+	 * @return the binary name of this type, or <code>null</code> 
+	 * if the binary name is unknown
+	 * @since 3.0
+	 */
+	public String getBinaryName();
+	
+	/**
+	 * Returns a list of bindings representing all the fields declared
+	 * as members of this class or interface. These include public, 
+	 * protected, default (package-private) access, and private fields declared
+	 * by the class, but excludes inherited fields. Synthetic fields may or
+	 * may not be included.
+	 * Returns an empty list if the class or interface declares no fields,
+	 * or if this type binding represents a primitive type or an array type 
+	 * (the implicit <code>length</code> field of array types is not considered
+	 * to be a declared field). The resulting bindings are in no particular 
+	 * order.
 	 * 
-	 * @return <code>true</code> if this type binding is for the null type,
-	 *   and <code>false</code> otherwise
+	 * @return the list of bindings for the field members of this type,
+	 *   or the empty list if this type does not have field members or is an
+	 *   array type, primitive type, or the null type
 	 */
-	public boolean isNullType();
+	public IVariableBinding[] getDeclaredFields();
 	
 	/**
-	 * Returns whether this type binding represents an array type.
-	 * <p>
-	 * The set of array types is mutually exclusive with the sets of
-	 * primitive types and with the sets of class and interface types.
-	 * </p>
-	 *
-	 * @return <code>true</code> if this type binding is for an array type,
-	 *   and <code>false</code> otherwise
-	 * @see #isClass()
-	 * @see #isInterface()
-	 * @see #isPrimitive()
-	 */
-	public boolean isArray();
-	
-	/**
-	 * Returns the binding representing the element type of this array type,
-	 * or <code>null</code> if this is not an array type binding. The element
-	 * type of an array is never itself an array type.
-	 *
-	 * @return the element type binding, or <code>null</code> if this is
-	 *   not an array type
-	 */
-	public ITypeBinding getElementType();
-	
-	/**
-	 * Returns the dimensionality of this array type, or <code>0</code> if this
-	 * is not an array type binding.
-	 *
-	 * @return the number of dimension of this array type binding, or 
-	 *   <code>0</code> if this is not an array type
-	 */
-	public int getDimensions();
-	
-	/**
-	 * Returns whether this type binding represents a class type.
-	 * <p>
-	 * The set of class types is mutually exclusive with the sets of
-	 * primive types, array types, interface types, and the null type.
-	 * </p>
-	 *
-	 * @return <code>true</code> if this object represents a class,
-	 *    and <code>false</code> otherwise
-	 *
-	 * @see #isArray()
-	 * @see #isInterface()
-	 * @see #isPrimitive()
-	 */
-	public boolean isClass();
-	
-	/**
-	 * Returns whether this type binding represents an interface type.
-	 * <p>
-	 * The set of interface types is mutually exclusive with the sets of
-	 * primive types, array types, class types, and the null type.
-	 * </p>
-	 *
-	 * @return <code>true</code> if this object represents an interface,
-	 *    and <code>false</code> otherwise
-	 *
-	 * @see #isArray()
-	 * @see #isClass()
-	 * @see #isPrimitive()
-	 */
-	public boolean isInterface();
-	
-	/**
-	 * Returns the unqualified name of the type represented by this binding.
-	 * <p>
-	 * For named classes and interfaces, this is the simple name of the type. 
-	 * For primitive types, the name is the keyword for the primitive type. For array
-	 * types, the name is the unqualified name of the component type followed by "[]".
-	 * If this represents an anonymous class, it returns an empty string (note that
-	 * it is impossible to have an array type with an anonymous class as element type).
-	 * For the null type, it returns "null".
-	 * </p>
+	 * Returns a list of method bindings representing all the methods and 
+	 * constructors declared for this class or interface. These include public,
+	 * protected, default (package-private) access, and private methods. 
+	 * Synthetic methods and constructors may or may not be included. Returns
+	 * an empty list if the class or interface declares no methods or 
+	 * constructors, or if this type binding represents an array type or a
+	 * primitive type. The resulting bindings are in no particular order.
 	 * 
-	 * @return the unqualified name of the type represented by this binding, an
-	 *    empty string this is an anonymous type, or "null" for the null type
-	 * @see #getQualifiedName
+	 * @return the list of method bindings for the methods and constructors
+	 *   declared by this class or interface, or the empty list if this type does
+	 *   not declare any methods or constructors
 	 */
-	public String getName();
-			
+	public IMethodBinding[] getDeclaredMethods();
+	
 	/**
-	 * Returns the binding for the package in which this class or interface is 
-	 * declared.
-	 * 
-	 * @return the binding for the package in which this class or interface is
-	 *   declared, or <code>null</code> if this type binding represents a 
-	 *   primitive type, an array type, or the null type.
+	 * Returns the declared modifiers for this class or interface binding
+	 * as specified in the original source declaration of the class or 
+	 * interface. The result may not correspond to the modifiers in the compiled
+	 * binary, since the compiler may change them (in particular, for inner 
+	 * class emulation). The <code>getModifiers</code> method should be used if
+	 * the compiled modifiers are needed. Returns -1 if this type does not 
+	 * represent a class or interface.
+	 *
+	 * @return the bit-wise or of <code>Modifier</code> constants
+	 * @see #getModifiers
+	 * @see Modifier
 	 */
-	public IPackageBinding getPackage();
+	public int getDeclaredModifiers();
+
+	/**
+	 * Returns a list of type bindings representing all the classes
+	 * and interfaces declared as members of this class or interface type. 
+	 * These include public, protected, default (package-private) access,
+	 * and private classes and interfaces declared by the class, but excludes
+	 * inherited classes and interfaces. Returns an empty list if the
+	 * class declares no classes or interfaces as members, or if this type
+	 * binding represents an array type, a primitive type, or the null type.
+	 * The resulting bindings are in no particular order.
+	 * 
+	 * @return the list of type bindings for the member types of this type,
+	 *   or the empty list if this type does not have member types
+	 */
+	public ITypeBinding[] getDeclaredTypes();
 	
 	/**
 	 * Returns the type binding representing the class or interface
@@ -173,31 +121,23 @@
 	public ITypeBinding getDeclaringClass();
 	
 	/**
-	 * Returns the type binding for the superclass of the type represented
-	 * by this class binding.
-	 * <p>
-	 * If this type binding represents any class other than the class
-	 * <code>java.lang.Object</code>, then the type binding for the direct
-	 * superclass of this class is returned. If this type binding represents
-	 * the class <code>java.lang.Object</code>, then <code>null</code> is
-	 * returned.
-	 * <p>
-	 * Loops that ascend the class hierarchy need a suitable termination test.
-	 * Rather than test the superclass for <code>null</code>, it is more 
-	 * transparent to check whether the class is <code>Object</code>, by 
-	 * comparing whether the class binding is identical to 
-	 * <code>ast.resolveWellKnownType("java.lang.Object")</code>.
-	 * </p>
-	 * <p>
-	 * If this type binding represents an interface, an array type, a
-	 * primitive type, or the null type, then <code>null</code> is returned. 
-	 * </p>
+	 * Returns the dimensionality of this array type, or <code>0</code> if this
+	 * is not an array type binding.
 	 *
-	 * @return the superclass of the class represented by this type binding,
-	 *    or <code>null</code> if none
-	 * @see AST#resolveWellKnownType
+	 * @return the number of dimension of this array type binding, or 
+	 *   <code>0</code> if this is not an array type
 	 */
-	public ITypeBinding getSuperclass();
+	public int getDimensions();
+	
+	/**
+	 * Returns the binding representing the element type of this array type,
+	 * or <code>null</code> if this is not an array type binding. The element
+	 * type of an array is never itself an array type.
+	 *
+	 * @return the element type binding, or <code>null</code> if this is
+	 *   not an array type
+	 */
+	public ITypeBinding getElementType();
 	
 	/**
 	 * Returns a list of type bindings representing the direct superinterfaces
@@ -241,149 +181,31 @@
 	public int getModifiers();
 	
 	/**
-	 * Returns the declared modifiers for this class or interface binding
-	 * as specified in the original source declaration of the class or 
-	 * interface. The result may not correspond to the modifiers in the compiled
-	 * binary, since the compiler may change them (in particular, for inner 
-	 * class emulation). The <code>getModifiers</code> method should be used if
-	 * the compiled modifiers are needed. Returns -1 if this type does not 
-	 * represent a class or interface.
-	 *
-	 * @return the bit-wise or of <code>Modifier</code> constants
-	 * @see #getModifiers
-	 * @see Modifier
-	 */
-	public int getDeclaredModifiers();
-	
-	/**
-	 * Returns whether this type binding represents a top-level class or
-	 * interface.
+	 * Returns the unqualified name of the type represented by this binding.
 	 * <p>
-	 * A top-level type is any class or interface whose declaration does not
-	 * occur within the body of another class or interface. The set of top
-	 * level types is disjoint from the set of nested types.
+	 * For named classes and interfaces, this is the simple name of the type. 
+	 * For primitive types, the name is the keyword for the primitive type. For array
+	 * types, the name is the unqualified name of the component type followed by "[]".
+	 * If this represents an anonymous class, it returns an empty string (note that
+	 * it is impossible to have an array type with an anonymous class as element type).
+	 * For the null type, it returns "null".
 	 * </p>
-	 *
-	 * @return <code>true</code> if this type binding is for a top-level class
-	 *   or interface, and <code>false</code> otherwise
-	 */
-	public boolean isTopLevel();
-
-	/**
-	 * Returns whether this type binding represents a nested class or
-	 * interface.
-	 * <p>
-	 * A nested type is any class or interface whose declaration occurs within
-	 * the body of another class or interface. The set of nested types is 
-	 * disjoint from the set of top-level types. Nested types further subdivide
-	 * into member types, local types, and anonymous types.
-	 * </p>
-	 *
-	 * @return <code>true</code> if this type binding is for a nested class
-	 *   or interface, and <code>false</code> otherwise
-	 */
-	public boolean isNested();
-
-	/**
-	 * Returns whether this type binding represents a member class or
-	 * interface.
-	 * <p>
-	 * A member type is any class or interface declared as a member of
-	 * another class or interface. A member type is a subspecies of nested
-	 * type, and mutually exclusive with local types.
-	 * </p>
-	 *
-	 * @return <code>true</code> if this type binding is for a member class
-	 *   or interface, and <code>false</code> otherwise
-	 */
-	public boolean isMember();
-	
-	/**
-	 * Returns whether this type binding represents a local class or
-	 * interface.
-	 * <p>
-	 * A local type is any nested class or interface not declared as a member of
-	 * another class or interface. A local type is a subspecies of nested
-	 * type, and mutually exclusive with member types. Note that anonymous
-	 * classes are a subspecies of local types.
-	 * </p>
-	 *
-	 * @return <code>true</code> if this type binding is for a local class
-	 *   or interface, and <code>false</code> otherwise
-	 */
-	public boolean isLocal();
-	
-	/**
-	 * Returns whether this type binding represents an anonymous class.
-	 * <p>
-	 * An anonymous class is a subspecies of local class, and therefore mutually
-	 * exclusive with member types. Note that anonymous classes have no name 
-	 * (<code>getName</code> returns the empty string).
-	 * </p>
-	 *
-	 * @return <code>true</code> if this type binding is for an anonymous class,
-	 *   and <code>false</code> otherwise
-	 */
-	public boolean isAnonymous();
-
-	/**
-	 * Returns a list of type bindings representing all the classes
-	 * and interfaces declared as members of this class or interface type. 
-	 * These include public, protected, default (package-private) access,
-	 * and private classes and interfaces declared by the class, but excludes
-	 * inherited classes and interfaces. Returns an empty list if the
-	 * class declares no classes or interfaces as members, or if this type
-	 * binding represents an array type, a primitive type, or the null type.
-	 * The resulting bindings are in no particular order.
 	 * 
-	 * @return the list of type bindings for the member types of this type,
-	 *   or the empty list if this type does not have member types
+	 * @return the unqualified name of the type represented by this binding, an
+	 *    empty string this is an anonymous type, or "null" for the null type
+	 * @see #getQualifiedName
 	 */
-	public ITypeBinding[] getDeclaredTypes();
-	
+	public String getName();
+			
 	/**
-	 * Returns a list of bindings representing all the fields declared
-	 * as members of this class or interface. These include public, 
-	 * protected, default (package-private) access, and private fields declared
-	 * by the class, but excludes inherited fields. Synthetic fields may or
-	 * may not be included.
-	 * Returns an empty list if the class or interface declares no fields,
-	 * or if this type binding represents a primitive type or an array type 
-	 * (the implicit <code>length</code> field of array types is not considered
-	 * to be a declared field). The resulting bindings are in no particular 
-	 * order.
+	 * Returns the binding for the package in which this class or interface is 
+	 * declared.
 	 * 
-	 * @return the list of bindings for the field members of this type,
-	 *   or the empty list if this type does not have field members or is an
-	 *   array type, primitive type, or the null type
+	 * @return the binding for the package in which this class or interface is
+	 *   declared, or <code>null</code> if this type binding represents a 
+	 *   primitive type, an array type, or the null type.
 	 */
-	public IVariableBinding[] getDeclaredFields();
-	
-	/**
-	 * Returns a list of method bindings representing all the methods and 
-	 * constructors declared for this class or interface. These include public,
-	 * protected, default (package-private) access, and private methods. 
-	 * Synthetic methods and constructors may or may not be included. Returns
-	 * an empty list if the class or interface declares no methods or 
-	 * constructors, or if this type binding represents an array type or a
-	 * primitive type. The resulting bindings are in no particular order.
-	 * 
-	 * @return the list of method bindings for the methods and constructors
-	 *   declared by this class or interface, or the empty list if this type does
-	 *   not declare any methods or constructors
-	 */
-	public IMethodBinding[] getDeclaredMethods();
-	
-	/**
-	 * Returns whether this type binding originated in source code.
-	 * Returns <code>false</code> for primitive types, the null type, array types,
-	 * and classes and interfaces whose information came from a pre-compiled binary
-	 * class file.
-	 * 
-	 * @return <code>true</code> if the type is in source code,
-	 *    and <code>false</code> otherwise
-	 */
-	public boolean isFromSource();
+	public IPackageBinding getPackage();
 	
 	/**
 	 * Returns the fully qualified name of the type represented by this 
@@ -418,4 +240,198 @@
 	 * @since 2.1
 	 */
 	public String getQualifiedName();
+	
+	/**
+	 * Returns the type binding for the superclass of the type represented
+	 * by this class binding.
+	 * <p>
+	 * If this type binding represents any class other than the class
+	 * <code>java.lang.Object</code>, then the type binding for the direct
+	 * superclass of this class is returned. If this type binding represents
+	 * the class <code>java.lang.Object</code>, then <code>null</code> is
+	 * returned.
+	 * <p>
+	 * Loops that ascend the class hierarchy need a suitable termination test.
+	 * Rather than test the superclass for <code>null</code>, it is more 
+	 * transparent to check whether the class is <code>Object</code>, by 
+	 * comparing whether the class binding is identical to 
+	 * <code>ast.resolveWellKnownType("java.lang.Object")</code>.
+	 * </p>
+	 * <p>
+	 * If this type binding represents an interface, an array type, a
+	 * primitive type, or the null type, then <code>null</code> is returned. 
+	 * </p>
+	 *
+	 * @return the superclass of the class represented by this type binding,
+	 *    or <code>null</code> if none
+	 * @see AST#resolveWellKnownType
+	 */
+	public ITypeBinding getSuperclass();
+	
+	/**
+	 * Returns whether this type binding represents an anonymous class.
+	 * <p>
+	 * An anonymous class is a subspecies of local class, and therefore mutually
+	 * exclusive with member types. Note that anonymous classes have no name 
+	 * (<code>getName</code> returns the empty string).
+	 * </p>
+	 *
+	 * @return <code>true</code> if this type binding is for an anonymous class,
+	 *   and <code>false</code> otherwise
+	 */
+	public boolean isAnonymous();
+	
+	/**
+	 * Returns whether this type binding represents an array type.
+	 * <p>
+	 * The set of array types is mutually exclusive with the sets of
+	 * primitive types and with the sets of class and interface types.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this type binding is for an array type,
+	 *   and <code>false</code> otherwise
+	 * @see #isClass()
+	 * @see #isInterface()
+	 * @see #isPrimitive()
+	 */
+	public boolean isArray();
+	
+	/**
+	 * Returns whether this type binding represents a class type.
+	 * <p>
+	 * The set of class types is mutually exclusive with the sets of
+	 * primive types, array types, interface types, and the null type.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this object represents a class,
+	 *    and <code>false</code> otherwise
+	 *
+	 * @see #isArray()
+	 * @see #isInterface()
+	 * @see #isPrimitive()
+	 */
+	public boolean isClass();
+	
+	/**
+	 * Returns whether this type binding originated in source code.
+	 * Returns <code>false</code> for primitive types, the null type, array types,
+	 * and classes and interfaces whose information came from a pre-compiled binary
+	 * class file.
+	 * 
+	 * @return <code>true</code> if the type is in source code,
+	 *    and <code>false</code> otherwise
+	 */
+	public boolean isFromSource();
+	
+	/**
+	 * Returns whether this type binding represents an interface type.
+	 * <p>
+	 * The set of interface types is mutually exclusive with the sets of
+	 * primive types, array types, class types, and the null type.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this object represents an interface,
+	 *    and <code>false</code> otherwise
+	 *
+	 * @see #isArray()
+	 * @see #isClass()
+	 * @see #isPrimitive()
+	 */
+	public boolean isInterface();
+	
+	/**
+	 * Returns whether this type binding represents a local class or
+	 * interface.
+	 * <p>
+	 * A local type is any nested class or interface not declared as a member of
+	 * another class or interface. A local type is a subspecies of nested
+	 * type, and mutually exclusive with member types. Note that anonymous
+	 * classes are a subspecies of local types.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this type binding is for a local class
+	 *   or interface, and <code>false</code> otherwise
+	 */
+	public boolean isLocal();
+
+	/**
+	 * Returns whether this type binding represents a member class or
+	 * interface.
+	 * <p>
+	 * A member type is any class or interface declared as a member of
+	 * another class or interface. A member type is a subspecies of nested
+	 * type, and mutually exclusive with local types.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this type binding is for a member class
+	 *   or interface, and <code>false</code> otherwise
+	 */
+	public boolean isMember();
+
+	/**
+	 * Returns whether this type binding represents a nested class or
+	 * interface.
+	 * <p>
+	 * A nested type is any class or interface whose declaration occurs within
+	 * the body of another class or interface. The set of nested types is 
+	 * disjoint from the set of top-level types. Nested types further subdivide
+	 * into member types, local types, and anonymous types.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this type binding is for a nested class
+	 *   or interface, and <code>false</code> otherwise
+	 */
+	public boolean isNested();
+
+	/**
+	 * Returns whether this type binding represents the null type.
+	 * <p>
+	 * The null type is the type of a <code>NullLiteral</code> node.
+	 * </p>
+	 * <p>
+	 * The null type is mutually exclusive with the sets of
+	 * array types, with the sets of class and interface types, and 
+	 * with the set of primitive types .
+	 * </p>
+	 * 
+	 * @return <code>true</code> if this type binding is for the null type,
+	 *   and <code>false</code> otherwise
+	 */
+	public boolean isNullType();
+	
+	/**
+	 * Returns whether this type binding represents a primitive type.
+	 * <p>
+	 * There are nine predefined type bindings to represent the eight primitive
+	 * types and <code>void</code>. These have the same names as the primitive
+	 * types that they represent, namely boolean, byte, char, short, int,
+	 * long, float, and double, and void.
+	 * </p>
+	 * <p>
+	 * The set of primitive types is mutually exclusive with the sets of
+	 * array types, with the sets of class and interface types, and with the null type.
+	 * </p>
+	 * 
+	 * @return <code>true</code> if this type binding is for a primitive type,
+	 *   and <code>false</code> otherwise
+	 *
+	 * @see #isArray()
+	 * @see #isClass()
+	 * @see #isInterface()
+	 */
+	public boolean isPrimitive();
+	
+	/**
+	 * Returns whether this type binding represents a top-level class or
+	 * interface.
+	 * <p>
+	 * A top-level type is any class or interface whose declaration does not
+	 * occur within the body of another class or interface. The set of top
+	 * level types is disjoint from the set of nested types.
+	 * </p>
+	 *
+	 * @return <code>true</code> if this type binding is for a top-level class
+	 *   or interface, and <code>false</code> otherwise
+	 */
+	public boolean isTopLevel();
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java
index fd6c685..7aef182 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/IfStatement.java
@@ -150,6 +150,14 @@
 	
 	/**
 	 * Sets the "then" part of this if statement.
+	 * <p>
+	 * Special note: The Java language does not allow a local variable declaration
+	 * to appear as the "then" part of an if statement (they may only appear within a
+	 * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+	 * as the thenStatement of a <code>IfStatement</code>. To get something that will
+	 * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+	 * inside a <code>Block</code>.
+	 * </p>
 	 * 
 	 * @param statement the "then" statement node
 	 * @exception IllegalArgumentException if:
@@ -189,6 +197,14 @@
 	 * (as in <code>"if(true){}"</code>) and having an empty block (as in
 	 * "if(true){}else{}") or null statement (as in "if(true){}else;"). 
 	 * </p>
+	 * <p>
+	 * Special note: The Java language does not allow a local variable declaration
+	 * to appear as the "else" part of an if statement (they may only appear within a
+	 * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+	 * as the elseStatement of a <code>IfStatement</code>. To get something that will
+	 * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+	 * inside a <code>Block</code>.
+	 * </p>
 	 * 
 	 * @param statement the "else" statement node, or <code>null</code> if 
 	 *    there is none
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java
index 0ac56ce..515caeb 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Initializer.java
@@ -29,12 +29,6 @@
 	private static final int LEGAL_MODIFIERS = Modifier.STATIC;
 	
 	/**
-	 * The modifiers; bit-wise or of Modifier flags.
-	 * Defaults to none.
-	 */
-	private int modifiers = 0;
-
-	/**
 	 * The initializer body; lazily initialized; defaults to an empty block.
 	 */
 	private Block body = null;
@@ -68,7 +62,7 @@
 		result.setSourceRange(this.getStartPosition(), this.getLength());
 		result.setModifiers(getModifiers());
 		result.setJavadoc(
-			(Javadoc) ASTNode.copySubtree(target,(ASTNode) getJavadoc()));
+			(Javadoc) ASTNode.copySubtree(target, getJavadoc()));
 		result.setBody((Block) getBody().clone(target));
 		return result;
 	}
@@ -99,11 +93,11 @@
 	 * Note that static is the only meaningful modifier for an initializer.
 	 * </p>
 	 * 
-	 * @return the bit-wise or of <code>Modifier</code> constants
-	 * @see Modifier
+	 * @since 2.0
 	 */ 
 	public int getModifiers() {
-		return modifiers;
+		// method needed only for javadoc
+		return super.getModifiers();
 	}
 
 	/**
@@ -112,16 +106,13 @@
 	 * Note that static is the only meaningful modifier for an initializer.
 	 * </p>
 	 * 
-	 * @return the bit-wise or of <code>Modifier</code> constants
-	 * @see Modifier
-	 * @exception IllegalArgumentException if the modifiers are illegal
+	 * @since 2.0
 	 */ 
 	public void setModifiers(int modifiers) {
 		if ((modifiers & ~LEGAL_MODIFIERS) != 0) {
 			throw new IllegalArgumentException();
 		}
-		modifying();
-		this.modifiers = modifiers;
+		super.setModifiers(modifiers);
 	}
 
 	/**
@@ -162,7 +153,7 @@
 	 * Method declared on ASTNode.
 	 */
 	int memSize() {
-		return super.memSize() + 2 * 4;
+		return super.memSize() + 1 * 4;
 	}
 	
 	/* (omit javadoc for this method)
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java
index 5083b6d..80aebe4 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/LabeledStatement.java
@@ -140,6 +140,14 @@
 	
 	/**
 	 * Sets the body of this labeled statement.
+	 * <p>
+	 * Special note: The Java language does not allow a local variable declaration
+	 * to appear as the body of a labeled statement (they may only appear within a
+	 * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+	 * as the body of a <code>LabeledStatement</code>. To get something that will
+	 * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+	 * inside a <code>Block</code>.
+	 * </p>
 	 * 
 	 * @param statement the body statement node
 	 * @exception IllegalArgumentException if:
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java
index 6814e69..98b6979 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java
@@ -11,6 +11,8 @@
 
 package org.eclipse.jdt.core.dom;
 
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+
 /**
  * Internal implementation of method bindings.
  */
@@ -36,6 +38,17 @@
 	public boolean isConstructor() {
 		return this.binding.isConstructor();
 	}
+	
+	/*
+	 * @see IMethodBinding#isDefaultConstructor()
+	 * @since 3.0
+	 */
+	public boolean isDefaultConstructor() {
+		if (this.binding.declaringClass.isBinaryBinding()) {
+			return false;
+		}
+		return (this.binding.modifiers & CompilerModifiers.AccIsDefaultConstructor) != 0;
+	}	
 
 	/*
 	 * @see IBinding#getName()
@@ -142,15 +155,15 @@
 	 */
 	public String getKey() {
 		StringBuffer buffer = new StringBuffer();
-		ITypeBinding returnType = getReturnType();
-		if (returnType != null) {
-			buffer.append(returnType.getKey());
+		buffer.append(this.getDeclaringClass().getKey());
+		buffer.append('/');
+		ITypeBinding _returnType = getReturnType();
+		if (_returnType != null) {
+			buffer.append(_returnType.getKey());
 		}
 		if (!isConstructor()) {
 			buffer.append(this.getName());
-			buffer.append('/');
 		}
-		buffer.append(this.getDeclaringClass().getKey());
 		ITypeBinding[] parameters = getParameterTypes();
 		buffer.append('(');
 		for (int i = 0, max = parameters.length; i < max; i++) {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
index b767669..c651747 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
@@ -60,12 +60,6 @@
 	private boolean isConstructor = false;
 	
 	/**
-	 * The modifiers; bit-wise or of Modifier flags.
-	 * Defaults to none.
-	 */
-	private int modifiers = Modifier.NONE;
-	
-	/**
 	 * The method name; lazily initialized; defaults to an unspecified,
 	 * legal Java identifier.
 	 */
@@ -138,7 +132,7 @@
 		MethodDeclaration result = new MethodDeclaration(target);
 		result.setSourceRange(this.getStartPosition(), this.getLength());
 		result.setJavadoc(
-			(Javadoc) ASTNode.copySubtree(target,(ASTNode) getJavadoc()));
+			(Javadoc) ASTNode.copySubtree(target, getJavadoc()));
 		result.setModifiers(getModifiers());
 		result.setConstructor(isConstructor());
 		result.setReturnType(
@@ -204,14 +198,17 @@
 	/**
 	 * Returns the modifiers explicitly specified on this declaration.
 	 * <p>
+	 * The following modifiers are valid for methods: public, private, protected,
+	 * static, final, synchronized, native, abstract, and strictfp.
+	 * For constructors, only public, private, and protected are meaningful.
 	 * Note that deprecated is not included.
 	 * </p>
 	 * 
-	 * @return the bit-wise or of Modifier constants
-	 * @see Modifier
+	 * @since 2.0
 	 */ 
 	public int getModifiers() {
-		return modifiers;
+		// method needed only for javadoc
+		return super.getModifiers();
 	}
 	
 	/**
@@ -220,18 +217,16 @@
 	 * The following modifiers are valid for methods: public, private, protected,
 	 * static, final, synchronized, native, abstract, and strictfp.
 	 * For constructors, only public, private, and protected are meaningful.
+	 * Note that deprecated is not included.
 	 * </p>
 	 * 
-	 * @param modifiers the bit-wise or of Modifier constants
-	 * @see Modifier
-	 * @exception IllegalArgumentException if the modifiers are illegal
+	 * @since 2.0
 	 */ 
 	public void setModifiers(int modifiers) {
 		if ((modifiers & ~LEGAL_MODIFIERS) != 0) {
 			throw new IllegalArgumentException();
 		}
-		modifying();
-		this.modifiers = modifiers;
+		super.setModifiers(modifiers);
 	}
 
 //	public List<TypeParameter> typeParameters(); // JSR-014
@@ -338,7 +333,7 @@
 		if (type == null) {
 			throw new IllegalArgumentException();
 		}
-		replaceChild((ASTNode) this.returnType, (ASTNode) type, false);
+		replaceChild(this.returnType, type, false);
 		this.returnType = type;
 	}
 
@@ -467,7 +462,7 @@
 	 * Method declared on ASTNode.
 	 */
 	int memSize() {
-		return super.memSize() + 8 * 4;
+		return super.memSize() + 7 * 4;
 	}
 	
 	/* (omit javadoc for this method)
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java
index 7fe30a7..9f7ddb1 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Modifier.java
@@ -249,6 +249,7 @@
 	 * Block instantiation.
 	 */
 	private Modifier() {
+		// default implementation: do nothing
 	}
 	
 }
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NaiveASTFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NaiveASTFlattener.java
index 4a918ce..8760f85 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NaiveASTFlattener.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NaiveASTFlattener.java
@@ -39,12 +39,13 @@
 	 * The string buffer into which the serialized representation of the AST is
 	 * written.
 	 */
-	private StringBuffer buffer = new StringBuffer(6000);
+	private StringBuffer buffer;
 	
 	/**
 	 * Creates a new AST printer.
 	 */
 	NaiveASTFlattener() {
+		this.buffer = new StringBuffer();
 	}
 	
 	/**
@@ -53,8 +54,7 @@
 	 * @return the serialized 
 	 */
 	public String getResult() {
-		// convert to a string, but lose any extra space in the string buffer by copying
-		return new String(buffer.toString());
+		return buffer.toString();
 	}
 	
 	/**
@@ -766,11 +766,11 @@
 	 */
 	public boolean visit(SwitchCase node) {
 		if (node.isDefault()) {
-			buffer.append("default : ");//$NON-NLS-1$
+			buffer.append("default :");//$NON-NLS-1$
 		} else {
 			buffer.append("case ");//$NON-NLS-1$
 			node.getExpression().accept(this);
-			buffer.append(": ");//$NON-NLS-1$
+			buffer.append(":");//$NON-NLS-1$
 		}
 		return false;
 	}
@@ -836,6 +836,7 @@
 			cc.accept(this);
 		}
 		if (node.getFinally() != null) {
+			buffer.append("finally ");//$NON-NLS-1$
 			node.getFinally().accept(this);
 		}
 		return false;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Name.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Name.java
index 3f5fb1a..aed1b2a 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Name.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Name.java
@@ -31,6 +31,12 @@
 public abstract class Name extends Expression {
 	
 	/**
+	 * Approximate base size of an expression node instance in bytes, 
+	 * including object header and instance fields.
+	 */
+	static final int BASE_NAME_NODE_SIZE = BASE_NODE_SIZE + 1 * 4;
+	
+	/**
 	 * This index reprensents the position inside a qualified name.
 	 */
 	int index;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeSearcher.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeSearcher.java
new file mode 100644
index 0000000..9bf67aa
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NodeSearcher.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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 Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+
+class NodeSearcher extends ASTVisitor {
+	public org.eclipse.jdt.internal.compiler.ast.ASTNode found;
+	public TypeDeclaration enclosingType;
+	public int position;
+	
+	NodeSearcher(int position) {
+		this.position = position;
+	}
+
+	public boolean visit(
+		ConstructorDeclaration constructorDeclaration,
+		ClassScope scope) {
+
+		if (constructorDeclaration.declarationSourceStart <= position
+			&& position <= constructorDeclaration.declarationSourceEnd) {
+				found = constructorDeclaration;
+				return false;
+		}
+		return true;
+	}
+
+	public boolean visit(
+		FieldDeclaration fieldDeclaration,
+		MethodScope scope) {
+			if (fieldDeclaration.declarationSourceStart <= position
+				&& position <= fieldDeclaration.declarationSourceEnd) {
+					found = fieldDeclaration;
+					return false;
+			}
+			return true;
+	}
+
+	public boolean visit(Initializer initializer, MethodScope scope) {
+		if (initializer.declarationSourceStart <= position
+			&& position <= initializer.declarationSourceEnd) {
+				found = initializer;
+				return false;
+		}
+		return true;
+	}
+
+	public boolean visit(
+		TypeDeclaration memberTypeDeclaration,
+		ClassScope scope) {
+			if (memberTypeDeclaration.declarationSourceStart <= position
+				&& position <= memberTypeDeclaration.declarationSourceEnd) {
+					enclosingType = memberTypeDeclaration;
+					return true;
+
+			}
+			return false;		
+	}
+
+	public boolean visit(
+		MethodDeclaration methodDeclaration,
+		ClassScope scope) {
+
+		if (methodDeclaration.declarationSourceStart <= position
+			&& position <= methodDeclaration.declarationSourceEnd) {
+				found = methodDeclaration;
+				return false;
+		}
+		return true;
+	}
+
+	public boolean visit(
+		TypeDeclaration typeDeclaration,
+		CompilationUnitScope scope) {
+			if (typeDeclaration.declarationSourceStart <= position
+				&& position <= typeDeclaration.declarationSourceEnd) {
+					enclosingType = typeDeclaration;
+					return true;
+			}
+			return false;		
+	}
+
+}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java
index bd2166d..1efcc50 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/NumberLiteral.java
@@ -13,6 +13,7 @@
 
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 
 /**
  * Number literal nodes.
@@ -102,18 +103,18 @@
 		try {
 			int tokenType = scanner.getNextToken();
 			switch(tokenType) {
-				case Scanner.TokenNameDoubleLiteral:
-				case Scanner.TokenNameIntegerLiteral:
-				case Scanner.TokenNameFloatingPointLiteral:
-				case Scanner.TokenNameLongLiteral:
+				case TerminalTokens.TokenNameDoubleLiteral:
+				case TerminalTokens.TokenNameIntegerLiteral:
+				case TerminalTokens.TokenNameFloatingPointLiteral:
+				case TerminalTokens.TokenNameLongLiteral:
 					break;
-				case Scanner.TokenNameMINUS :
+				case TerminalTokens.TokenNameMINUS :
 					tokenType = scanner.getNextToken();
 					switch(tokenType) {
-						case Scanner.TokenNameDoubleLiteral:
-						case Scanner.TokenNameIntegerLiteral:
-						case Scanner.TokenNameFloatingPointLiteral:
-						case Scanner.TokenNameLongLiteral:
+						case TerminalTokens.TokenNameDoubleLiteral:
+						case TerminalTokens.TokenNameIntegerLiteral:
+						case TerminalTokens.TokenNameFloatingPointLiteral:
+						case TerminalTokens.TokenNameLongLiteral:
 							break;
 						default:
 							throw new IllegalArgumentException();
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java
index d748421..34ae61b 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageBinding.java
@@ -23,13 +23,11 @@
 	private static final char PACKAGE_NAME_SEPARATOR = '.';
 	
 	private org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding;
-	private BindingResolver resolver;
 	private String name;
 	private String[] components;
 		
-	PackageBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding) {
+	PackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding) {
 		this.binding = binding;
-		this.resolver = resolver;
 	}
 	
 	/*
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java
index 92ab854..5c62bb7 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/QualifiedName.java
@@ -125,7 +125,7 @@
 			throw new IllegalArgumentException();
 		}
 		// a QualifiedName may occur inside a QualifiedName - must check cycles
-		replaceChild((ASTNode) this.qualifier, (ASTNode) qualifier, true);
+		replaceChild(this.qualifier, qualifier, true);
 		this.qualifier = qualifier;
 	}
 	
@@ -166,7 +166,7 @@
 	 * Method declared on ASTNode.
 	 */
 	int memSize() {
-		return BASE_NODE_SIZE + 3 * 4;
+		return BASE_NAME_NODE_SIZE + 2 * 4;
 	}
 	
 	/* (omit javadoc for this method)
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java
index 3f1db4d..3348ba8 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleName.java
@@ -13,6 +13,7 @@
 
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 
 /**
  * AST node for a simple name. A simple name is an identifier other than
@@ -118,7 +119,7 @@
 		try {
 			int tokenType = scanner.getNextToken();
 			switch(tokenType) {
-				case Scanner.TokenNameIdentifier:
+				case TerminalTokens.TokenNameIdentifier:
 					break;
 				default:
 					throw new IllegalArgumentException();
@@ -182,9 +183,12 @@
 	 * Method declared on ASTNode.
 	 */
 	int memSize() {
-		int size = BASE_NODE_SIZE + 1 * 4;
+		int size = BASE_NAME_NODE_SIZE + 1 * 4;
 		if (identifier != null) {
-			size += HEADERS + 3 * 4 + HEADERS + 2 * identifier.length();
+			// Strings usually have 4 instance fields, one of which is a char[]
+			size += HEADERS + 4 * 4;
+			// char[] has 2 bytes per character
+			size += HEADERS + 2 * identifier.length();
 		}
 		return size;
 	}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java
index 16a126d..2bf402c 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SimpleType.java
@@ -53,7 +53,7 @@
 	ASTNode clone(AST target) {
 		SimpleType result = new SimpleType(target);
 		result.setSourceRange(this.getStartPosition(), this.getLength());
-		result.setName((Name) ((ASTNode) getName()).clone(target));
+		result.setName((Name) (getName()).clone(target));
 		return result;
 	}
 
@@ -105,7 +105,7 @@
 		if (typeName == null) {
 			throw new IllegalArgumentException();
 		}
-		replaceChild((ASTNode) this.typeName, (ASTNode) typeName, false);
+		replaceChild(this.typeName, typeName, false);
 		this.typeName = typeName;
 	}
 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java
index 1e2c1b2..459ab65 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/StringLiteral.java
@@ -13,6 +13,7 @@
 
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 
 /**
  * String literal nodes.
@@ -103,7 +104,7 @@
 	 */ 
 	public void setEscapedValue(String token) {
 		if (token == null) {
-			throw new IllegalArgumentException();
+			throw new IllegalArgumentException("Token cannot be null"); //$NON-NLS-1$
 		}
 		Scanner scanner = getAST().scanner;
 		char[] source = token.toCharArray();
@@ -112,13 +113,13 @@
 		try {
 			int tokenType = scanner.getNextToken();
 			switch(tokenType) {
-				case Scanner.TokenNameStringLiteral:
+				case TerminalTokens.TokenNameStringLiteral:
 					break;
 				default:
-					throw new IllegalArgumentException();
+					throw new IllegalArgumentException("Invalid string literal : >" + token + "<"); //$NON-NLS-1$//$NON-NLS-2$
 			}
 		} catch(InvalidInputException e) {
-			throw new IllegalArgumentException();
+			throw new IllegalArgumentException("Invalid string literal : >" + token + "<");//$NON-NLS-1$//$NON-NLS-2$
 		}
 		modifying();
 		this.escapedValue = token;
@@ -158,7 +159,7 @@
 		try {
 			int tokenType = scanner.getNextToken();
 			switch(tokenType) {
-				case Scanner.TokenNameStringLiteral:
+				case TerminalTokens.TokenNameStringLiteral:
 					return new String(scanner.getCurrentTokenSourceString());
 				default:
 					throw new IllegalArgumentException();
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java
index 1959a48..4d5ecea 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperFieldAccess.java
@@ -135,6 +135,22 @@
 		}
 		return fieldName;
 	}
+
+	/**
+	 * Resolves and returns the binding for the field accessed by this
+	 * expression.
+	 * <p>
+	 * Note that bindings are generally unavailable unless requested when the
+	 * AST is being built.
+	 * </p>
+	 *
+	 * @return the variable binding, or <code>null</code> if the binding cannot
+	 * be resolved
+	 * @since 3.0
+	 */
+	public IVariableBinding resolveFieldBinding() {
+		return getAST().getBindingResolver().resolveField(this);
+	}
 		
 	/**
 	 * Sets the name of the field accessed in this "super" field access 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
index 38a9066..772d2ea 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
@@ -12,6 +12,10 @@
 package org.eclipse.jdt.core.dom;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
 import org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
@@ -31,6 +35,7 @@
 	
 	private org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding;
 	private BindingResolver resolver;
+	private String key;
 	
 	public TypeBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding) {
 		this.binding = binding;
@@ -296,6 +301,20 @@
 			return NO_DECLARED_TYPES;
 		}
 	}
+	
+	/*
+	 * @see ITypeBinding#getBinaryName()
+	 * @since 3.0
+	 */
+	public String getBinaryName() {
+		char[] constantPoolName = this.binding.constantPoolName();
+		if (constantPoolName == null) return null;
+		int length = constantPoolName.length;
+		char[] dotSeparated = new char[length];
+		System.arraycopy(constantPoolName, 0, dotSeparated, 0, length);
+		CharOperation.replace(dotSeparated, '/', '.');
+		return new String(dotSeparated);
+	}
 
 	/*
 	 * @see ITypeBinding#getDeclaredFields()
@@ -384,21 +403,70 @@
 	 * @see IBinding#getKey()
 	 */
 	public String getKey() {
-		if (isLocal()) {
-			return null;
+		if (this.key == null) {
+			if (isLocal()) {
+				StringBuffer buffer = new StringBuffer();
+				
+				// declaring method or type
+				SourceTypeBinding sourceBinding = (SourceTypeBinding) this.binding; // per construction, a local type can only be defined in source
+				ClassScope scope = sourceBinding.scope;
+				ReferenceContext referenceContext;
+				if (isAnonymous()) {
+					ClassScope classScope = scope.enclosingClassScope();
+					referenceContext = classScope.referenceContext;
+				} else {
+					MethodScope methodScope = scope.enclosingMethodScope();
+					referenceContext = methodScope.referenceContext;
+				}
+				if (referenceContext instanceof AbstractMethodDeclaration) {
+					org.eclipse.jdt.internal.compiler.lookup.MethodBinding internalBinding = ((AbstractMethodDeclaration) referenceContext).binding;
+					IMethodBinding methodBinding = this.resolver.getMethodBinding(internalBinding);
+					if (methodBinding != null) {
+						buffer.append(methodBinding.getKey());
+					}
+				} else if (referenceContext instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
+					org.eclipse.jdt.internal.compiler.lookup.TypeBinding internalBinding = ((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) referenceContext).binding;
+					ITypeBinding typeBinding = this.resolver.getTypeBinding(internalBinding);
+					if (typeBinding != null) {
+						buffer.append(typeBinding.getKey());
+					}
+				}
+	
+				if (isAnonymous()) {
+					buffer.append('$');
+					CompilationUnitScope compilationUnitScope = scope.compilationUnitScope();
+					CompilationUnitDeclaration compilationUnitDeclaration = compilationUnitScope.referenceContext;
+					LocalTypeBinding[] localTypeBindings = compilationUnitDeclaration.localTypes;
+					for (int i = 0, max = compilationUnitDeclaration.localTypeCount; i < max; i++) {
+						if (localTypeBindings[i] == sourceBinding) {
+							buffer.append(i+1);
+							break;
+						}
+					}
+				} else {
+					// type name
+					buffer.append('/');
+					buffer.append(getName());
+				}
+				
+				this.key = buffer.toString();
+			} else {
+				if (this.binding.isClass() || this.binding.isInterface()) {
+					StringBuffer buffer = new StringBuffer();
+					buffer
+						.append(getPackage().getName())
+						.append('/')
+						.append(getName());
+					this.key = buffer.toString();
+				} else if (this.binding.isArrayType()) {
+					this.key = this.getElementType().getKey() + this.getDimensions();
+				} else {
+					// this is a primitive type
+					this.key = this.getName();
+				}
+			}
 		}
-		if (this.binding.isClass() || this.binding.isInterface()) {
-			StringBuffer buffer = new StringBuffer();
-			buffer
-				.append(getPackage().getName())
-				.append('.')
-				.append(getName());
-			return buffer.toString();
-		} else if (this.binding.isArrayType()) {
-			return this.getElementType().getKey() + this.getDimensions();
-		}
-		// this is a primitive type
-		return this.getName();
+		return this.key;
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java
index 1eb603c..e213e7a 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeDeclaration.java
@@ -29,7 +29,7 @@
  *			<b>{</b> { ClassBodyDeclaration | <b>;</b> } <b>}</b>
  * InterfaceDeclaration:
  *      [ Javadoc ] { Modifier } <b>interface</b> Identifier
- *			[ <b>extends</b> Type]
+ *			[ <b>extends</b> Type { <b>,</b> Type } ]
  * 			<b>{</b> { InterfaceBodyDeclaration | <b>;</b> } <b>}</b>
  * </pre>
  * <p>
@@ -62,12 +62,6 @@
 	private boolean isInterface = false;
 	
 	/**
-	 * The modifiers; bit-wise or of Modifier flags.
-	 * Defaults to none.
-	 */
-	private int modifiers = Modifier.NONE;
-	
-	/**
 	 * The type name; lazily initialized; defaults to a unspecified,
 	 * legal Java class identifier.
 	 */
@@ -127,11 +121,11 @@
 		result.setSourceRange(this.getStartPosition(), this.getLength());
 		result.setModifiers(getModifiers());
 		result.setJavadoc(
-			(Javadoc) ASTNode.copySubtree(target,(ASTNode) getJavadoc()));
+			(Javadoc) ASTNode.copySubtree(target, getJavadoc()));
 		result.setInterface(isInterface());
 		result.setName((SimpleName) getName().clone(target));
 		result.setSuperclass(
-			(Name) ASTNode.copySubtree(target,(ASTNode) getSuperclass()));
+			(Name) ASTNode.copySubtree(target, getSuperclass()));
 		result.superInterfaces().addAll(
 			ASTNode.copySubtrees(target, superInterfaces()));
 		result.bodyDeclarations().addAll(
@@ -190,37 +184,31 @@
 	/**
 	 * Returns the modifiers explicitly specified on this declaration.
 	 * <p>
-	 * Note that deprecated is not included.
+	 * The following modifiers are valid for types: public, private, protected,
+	 * static, final, abstract, and strictfp. Note that deprecated is not included.
 	 * </p>
 	 * 
-	 * @return the bit-wise or of Modifier constants
-	 * @see Modifier
+	 * @since 2.0
 	 */ 
 	public int getModifiers() {
-		return modifiers;
+		// method needed only for javadoc
+		return super.getModifiers();
 	}
 	
 	/**
 	 * Sets the modifiers explicitly specified on this declaration.
 	 * <p>
 	 * The following modifiers are valid for types: public, private, protected,
-	 * static, final, abstract, and strictfp.
-	 * </p>
-	 * <p>
-	 * Only a subset of modifiers are legal in any given situation.
-	 * Note that deprecated is not included.
+	 * static, final, abstract, and strictfp. Note that deprecated is not included.
 	 * </p>
 	 * 
-	 * @param modifiers the bit-wise or of Modifier constants
-	 * @see Modifier
-	 * @exception IllegalArgumentException if the modifiers are illegal
+	 * @since 2.0
 	 */ 
 	public void setModifiers(int modifiers) {
 		if ((modifiers & ~LEGAL_MODIFIERS) != 0) {
 			throw new IllegalArgumentException();
 		}
-		modifying();
-		this.modifiers = modifiers;
+		super.setModifiers(modifiers);
 	}
 
 	/**
@@ -295,8 +283,8 @@
 	 */ 
 	public void setSuperclass(Name superclassName) {
 		replaceChild(
-			(ASTNode) this.optionalSuperclassName,
-			(ASTNode) superclassName, false);
+			this.optionalSuperclassName,
+			superclassName, false);
 		this.optionalSuperclassName = superclassName;
 	}
 
@@ -506,7 +494,7 @@
 	 * Method declared on ASTNode.
 	 */
 	int memSize() {
-		return super.memSize() + 6 * 4;
+		return super.memSize() + 5 * 4;
 	}
 	
 	/* (omit javadoc for this method)
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java
index 3cf6395..d10af06 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeLiteral.java
@@ -107,7 +107,7 @@
 		if (type == null) {
 			throw new IllegalArgumentException();
 		}
-		replaceChild((ASTNode) this.type, (ASTNode) type, false);
+		replaceChild(this.type, type, false);
 		this.type = type;
 	}
 
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java
index fe87e31..e600bd9 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/VariableBinding.java
@@ -12,7 +12,13 @@
 package org.eclipse.jdt.core.dom;
 
 import org.eclipse.jdt.core.util.IModifierConstants;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
 
 /**
  * Internal implementation of variable bindings.
@@ -24,6 +30,7 @@
 	private String name;
 	private ITypeBinding declaringClass;
 	private ITypeBinding type;
+	private String key;
 
 	VariableBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.VariableBinding binding) {
 		this.resolver = resolver;
@@ -52,8 +59,8 @@
 	 */
 	public ITypeBinding getDeclaringClass() {
 		if (isField()) {
-			FieldBinding fieldBinding = (FieldBinding) this.binding;
 			if (this.declaringClass == null) {
+				FieldBinding fieldBinding = (FieldBinding) this.binding;
 				this.declaringClass = this.resolver.getTypeBinding(fieldBinding.declaringClass);
 			}
 			return this.declaringClass;
@@ -61,7 +68,7 @@
 			return null;
 		}
 	}
-
+	
 	/*
 	 * @see IVariableBinding#getType()
 	 */
@@ -116,15 +123,57 @@
 	 * @see IBinding#getKey()
 	 */
 	public String getKey() {
-		if (isField()) {
-			StringBuffer buffer = new StringBuffer();
-			if (this.getDeclaringClass() != null) {
-				buffer.append(this.getDeclaringClass().getKey());
+		if (this.key == null) {
+			if (isField()) {
+				StringBuffer buffer = new StringBuffer();
+				if (this.getDeclaringClass() != null) {
+					buffer.append(this.getDeclaringClass().getKey());
+					buffer.append('/');
+				}
+				buffer.append(this.getName());
+				this.key = buffer.toString();
+			} else {
+				StringBuffer buffer = new StringBuffer();
+				
+				// declaring method or type
+				LocalVariableBinding localVarBinding = (LocalVariableBinding) this.binding;
+				BlockScope scope = localVarBinding.declaringScope;
+				MethodScope methodScope = scope instanceof MethodScope ? (MethodScope) scope : scope.enclosingMethodScope();
+				ReferenceContext referenceContext = methodScope.referenceContext;
+				if (referenceContext instanceof AbstractMethodDeclaration) {
+					org.eclipse.jdt.internal.compiler.lookup.MethodBinding internalBinding = ((AbstractMethodDeclaration) referenceContext).binding;
+					IMethodBinding methodBinding = this.resolver.getMethodBinding(internalBinding);
+					if (methodBinding != null) {
+						buffer.append(methodBinding.getKey());
+					}
+				} else if (referenceContext instanceof TypeDeclaration) {
+					org.eclipse.jdt.internal.compiler.lookup.TypeBinding internalBinding = ((TypeDeclaration) referenceContext).binding;
+					ITypeBinding typeBinding = this.resolver.getTypeBinding(internalBinding);
+					if (typeBinding != null) {
+						buffer.append(typeBinding.getKey());
+					}
+				}
+	
+				// scope index
+				getKey(scope, buffer);
+	
+				// variable name
+				buffer.append('/');
+				buffer.append(getName());
+				
+				this.key = buffer.toString();
 			}
-			buffer.append(this.getName());
-			return buffer.toString();
-		}			
-		return null;
+		}
+		return this.key;
+	}
+	
+	private void getKey(BlockScope scope, StringBuffer buffer) {
+		int scopeIndex = scope.scopeIndex();
+		if (scopeIndex != -1) {
+			getKey((BlockScope)scope.parent, buffer);
+			buffer.append('/');
+			buffer.append(scopeIndex);
+		}
 	}
 	
 	/*
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java
index c6ecb02..38338bf 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/WhileStatement.java
@@ -141,6 +141,14 @@
 	
 	/**
 	 * Sets the body of this while statement.
+	 * <p>
+	 * Special note: The Java language does not allow a local variable declaration
+	 * to appear as the body of a while statement (they may only appear within a
+	 * block). However, the AST will allow a <code>VariableDeclarationStatement</code>
+	 * as the body of a <code>WhileStatement</code>. To get something that will
+	 * compile, be sure to embed the <code>VariableDeclarationStatement</code>
+	 * inside a <code>Block</code>.
+	 * </p>
 	 * 
 	 * @param statement the body statement node
 	 * @exception IllegalArgumentException if:
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java
index e8b8113..ff5fbd2 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
@@ -20,6 +21,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 
 public class CodeSnippetAllocationExpression extends AllocationExpression implements ProblemReasons, EvaluationConstants {
 	EvaluationContext evaluationContext;
@@ -36,15 +38,15 @@
 	boolean valueRequired) {
 
 	int pc = codeStream.position;
-	ReferenceBinding allocatedType = binding.declaringClass;
+	ReferenceBinding allocatedType = this.binding.declaringClass;
 
-	if (binding.canBeSeenBy(allocatedType, this, currentScope)) {
+	if (this.binding.canBeSeenBy(allocatedType, this, currentScope)) {
 		codeStream.new_(allocatedType);
 		if (valueRequired) {
 			codeStream.dup();
 		}
 		// better highlight for allocation: display the type individually
-		codeStream.recordPositionsFrom(pc, type.sourceStart);
+		codeStream.recordPositionsFrom(pc, this.type.sourceStart);
 
 		// handling innerclass instance allocation - enclosing instance arguments
 		if (allocatedType.isNestedType()) {
@@ -55,9 +57,9 @@
 				this);
 		}
 		// generate the arguments for constructor
-		if (arguments != null) {
-			for (int i = 0, count = arguments.length; i < count; i++) {
-				arguments[i].generateCode(currentScope, codeStream, true);
+		if (this.arguments != null) {
+			for (int i = 0, count = this.arguments.length; i < count; i++) {
+				this.arguments[i].generateCode(currentScope, codeStream, true);
 			}
 		}
 		// handling innerclass instance allocation - outer local arguments
@@ -68,22 +70,22 @@
 				this);
 		}
 		// invoke constructor
-		codeStream.invokespecial(binding);
+		codeStream.invokespecial(this.binding);
 	} else {
 		// private emulation using reflect
-		((CodeSnippetCodeStream) codeStream).generateEmulationForConstructor(currentScope, binding);
+		((CodeSnippetCodeStream) codeStream).generateEmulationForConstructor(currentScope, this.binding);
 		// generate arguments
-		if (arguments != null) {
-			int argsLength = arguments.length;
+		if (this.arguments != null) {
+			int argsLength = this.arguments.length;
 			codeStream.generateInlinedValue(argsLength);
-			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeBinding.JAVA_LANG_OBJECT), 1));
+			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT), 1));
 			codeStream.dup();
 			for (int i = 0; i < argsLength; i++) {
 				codeStream.generateInlinedValue(i);
-				arguments[i].generateCode(currentScope, codeStream, true);
-				TypeBinding parameterBinding = binding.parameters[i];
+				this.arguments[i].generateCode(currentScope, codeStream, true);
+				TypeBinding parameterBinding = this.binding.parameters[i];
 				if (parameterBinding.isBaseType() && parameterBinding != NullBinding) {
-					((CodeSnippetCodeStream)codeStream).generateObjectWrapperForType(binding.parameters[i]);
+					((CodeSnippetCodeStream)codeStream).generateObjectWrapperForType(this.binding.parameters[i]);
 				}
 				codeStream.aastore();
 				if (i < argsLength - 1) {
@@ -92,7 +94,7 @@
 			}
 		} else {
 			codeStream.generateInlinedValue(0);
-			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeBinding.JAVA_LANG_OBJECT), 1));			
+			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT), 1));			
 		}
 		((CodeSnippetCodeStream) codeStream).invokeJavaLangReflectConstructorNewInstance();
 		codeStream.checkcast(allocatedType);
@@ -106,76 +108,86 @@
  * types, since by the time we reach them, we might not yet know their
  * exact need.
  */
-public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
+public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 	// not supported yet
 }
-public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
+public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+	// do nothing
 }
 public TypeBinding resolveType(BlockScope scope) {
 	// Propagate the type checking to the arguments, and check if the constructor is defined.
-	constant = NotAConstant;
-	this.resolvedType = type.resolveType(scope); // will check for null after args are resolved
+	this.constant = NotAConstant;
+	this.resolvedType = this.type.resolveType(scope); // will check for null after args are resolved
 
 	// buffering the arguments' types
 	TypeBinding[] argumentTypes = NoParameters;
-	if (arguments != null) {
+	if (this.arguments != null) {
 		boolean argHasError = false;
-		int length = arguments.length;
+		int length = this.arguments.length;
 		argumentTypes = new TypeBinding[length];
-		for (int i = 0; i < length; i++)
-			if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
+		for (int i = 0; i < length; i++) {
+			if ((argumentTypes[i] = this.arguments[i].resolveType(scope)) == null) {
 				argHasError = true;
-		if (argHasError)
-			return this.resolvedType;
-	}
-	if (this.resolvedType == null)
-		return null;
-
-	if (!this.resolvedType.canBeInstantiated()) {
-		scope.problemReporter().cannotInstantiate(type, this.resolvedType);
-		return this.resolvedType;
-	}
-	ReferenceBinding allocatedType = (ReferenceBinding) this.resolvedType;
-	if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this)).isValidBinding()) {
-		if (binding instanceof ProblemMethodBinding
-			&& ((ProblemMethodBinding) binding).problemId() == NotVisible) {
-			if (this.evaluationContext.declaringTypeName != null) {
-				delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
-				if (delegateThis == null) {
-					if (binding.declaringClass == null)
-						binding.declaringClass = allocatedType;
-					scope.problemReporter().invalidConstructor(this, binding);
-					return this.resolvedType;
-				}
-			} else {
-				if (binding.declaringClass == null)
-					binding.declaringClass = allocatedType;
-				scope.problemReporter().invalidConstructor(this, binding);
-				return this.resolvedType;
 			}
-			CodeSnippetScope localScope = new CodeSnippetScope(scope);			
-			MethodBinding privateBinding = localScope.getConstructor((ReferenceBinding)delegateThis.type, argumentTypes, this);
-			if (!privateBinding.isValidBinding()) {
-				if (binding.declaringClass == null)
-					binding.declaringClass = allocatedType;
-				scope.problemReporter().invalidConstructor(this, binding);
-				return this.resolvedType;
-			} else {
-				binding = privateBinding;
-			}				
-		} else {
-			if (binding.declaringClass == null)
-				binding.declaringClass = allocatedType;
-			scope.problemReporter().invalidConstructor(this, binding);
+		}
+		if (argHasError) {
 			return this.resolvedType;
 		}
 	}
-	if (isMethodUseDeprecated(binding, scope))
-		scope.problemReporter().deprecatedMethod(binding, this);
-
-	if (arguments != null)
-		for (int i = 0; i < arguments.length; i++)
-			arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
+	if (this.resolvedType == null) {
+		return null;
+	}
+	if (!this.resolvedType.canBeInstantiated()) {
+		scope.problemReporter().cannotInstantiate(this.type, this.resolvedType);
+		return this.resolvedType;
+	}
+	ReferenceBinding allocatedType = (ReferenceBinding) this.resolvedType;
+	if (!(this.binding = scope.getConstructor(allocatedType, argumentTypes, this)).isValidBinding()) {
+		if (this.binding instanceof ProblemMethodBinding
+			&& ((ProblemMethodBinding) this.binding).problemId() == NotVisible) {
+			if (this.evaluationContext.declaringTypeName != null) {
+				this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
+				if (this.delegateThis == null) {
+					if (this.binding.declaringClass == null) {
+						this.binding.declaringClass = allocatedType;
+					}
+					scope.problemReporter().invalidConstructor(this, this.binding);
+					return this.resolvedType;
+				}
+			} else {
+				if (this.binding.declaringClass == null) {
+					this.binding.declaringClass = allocatedType;
+				}
+				scope.problemReporter().invalidConstructor(this, this.binding);
+				return this.resolvedType;
+			}
+			CodeSnippetScope localScope = new CodeSnippetScope(scope);			
+			MethodBinding privateBinding = localScope.getConstructor((ReferenceBinding)this.delegateThis.type, argumentTypes, this);
+			if (!privateBinding.isValidBinding()) {
+				if (this.binding.declaringClass == null) {
+					this.binding.declaringClass = allocatedType;
+				}
+				scope.problemReporter().invalidConstructor(this, this.binding);
+				return this.resolvedType;
+			} else {
+				this.binding = privateBinding;
+			}				
+		} else {
+			if (this.binding.declaringClass == null) {
+				this.binding.declaringClass = allocatedType;
+			}
+			scope.problemReporter().invalidConstructor(this, this.binding);
+			return this.resolvedType;
+		}
+	}
+	if (isMethodUseDeprecated(this.binding, scope)) {
+		scope.problemReporter().deprecatedMethod(this.binding, this);
+	}
+	if (this.arguments != null) {
+		for (int i = 0; i < this.arguments.length; i++) {
+			this.arguments[i].implicitWidening(this.binding.parameters[i], argumentTypes[i]);
+		}
+	}
 	return allocatedType;
 }
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
index 1c4b316..6dd1ecd 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
@@ -16,7 +16,7 @@
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldReference;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -41,31 +41,30 @@
 	 * @param enclosingClassFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
 	 * @param creatingProblemType <CODE>boolean</CODE>
 	 */
-	referenceBinding = aType;
-	header = new byte[INITIAL_HEADER_SIZE];
+	this.referenceBinding = aType;
+	this.header = new byte[INITIAL_HEADER_SIZE];
 	// generate the magic numbers inside the header
-	header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
-	header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
-	header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
-	header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
-	if (((SourceTypeBinding) referenceBinding).scope.environment().options.targetJDK >= CompilerOptions.JDK1_2) {
-		// Compatible with JDK 1.2
-		header[headerOffset++] = 0;
-		// minorVersion = 0 means we just need to offset the current offset by 2
-		header[headerOffset++] = 0;
-		header[headerOffset++] = 0;
-		header[headerOffset++] = 46;
-	} else {
-		// Compatible with JDK 1.1
-		header[headerOffset++] = 0;
-		header[headerOffset++] = 3;
-		header[headerOffset++] = 0;
-		header[headerOffset++] = 45;
+	this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 24);
+	this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 16);
+	this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 8);
+	this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 0);
+
+	long targetJDK = this.referenceBinding.scope.environment().options.targetJDK;
+	// TODO[1.5]  until a 1.5 VM is released (accepting 49.0 files), will instead generate 1.4 (48.0) classfiles
+	if (targetJDK == ClassFileConstants.JDK1_5) targetJDK = ClassFileConstants.JDK1_4;
+	this.header[this.headerOffset++] = (byte) (targetJDK >> 8); // minor high
+	this.header[this.headerOffset++] = (byte) (targetJDK >> 0); // minor low
+	this.header[this.headerOffset++] = (byte) (targetJDK >> 24); // major high
+	this.header[this.headerOffset++] = (byte) (targetJDK >> 16); // major low
+
+	this.constantPoolOffset = this.headerOffset;
+	this.headerOffset += 2;
+	this.constantPool = new CodeSnippetConstantPool(this);
+	int accessFlags = aType.getAccessFlags();
+	
+	if (aType.isClass()) {
+		accessFlags |= AccSuper;
 	}
-	constantPoolOffset = headerOffset;
-	headerOffset += 2;
-	constantPool = new CodeSnippetConstantPool(this);
-	int accessFlags = aType.getAccessFlags() | AccSuper;
 	if (aType.isNestedType()) {
 		if (aType.isStatic()) {
 			// clear Acc_Static
@@ -85,50 +84,45 @@
 	accessFlags &= ~AccStrictfp;
 
 	this.enclosingClassFile = enclosingClassFile;
-	contents = new byte[INITIAL_CONTENTS_SIZE];
+	this.contents = new byte[INITIAL_CONTENTS_SIZE];
 	// now we continue to generate the bytes inside the contents array
-	contents[contentsOffset++] = (byte) (accessFlags >> 8);
-	contents[contentsOffset++] = (byte) accessFlags;
-	int classNameIndex = constantPool.literalIndex(aType);
-	contents[contentsOffset++] = (byte) (classNameIndex >> 8);
-	contents[contentsOffset++] = (byte) classNameIndex;
+	this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8);
+	this.contents[this.contentsOffset++] = (byte) accessFlags;
+	int classNameIndex = this.constantPool.literalIndex(aType);
+	this.contents[this.contentsOffset++] = (byte) (classNameIndex >> 8);
+	this.contents[this.contentsOffset++] = (byte) classNameIndex;
 	int superclassNameIndex;
 	if (aType.isInterface()) {
-		superclassNameIndex = constantPool.literalIndexForJavaLangObject();
+		superclassNameIndex = this.constantPool.literalIndexForJavaLangObject();
 	} else {
 		superclassNameIndex =
-			(aType.superclass == null ? 0 : constantPool.literalIndex(aType.superclass));
+			(aType.superclass == null ? 0 : this.constantPool.literalIndex(aType.superclass));
 	}
-	contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
-	contents[contentsOffset++] = (byte) superclassNameIndex;
+	this.contents[this.contentsOffset++] = (byte) (superclassNameIndex >> 8);
+	this.contents[this.contentsOffset++] = (byte) superclassNameIndex;
 	ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
 	int interfacesCount = superInterfacesBinding.length;
-	contents[contentsOffset++] = (byte) (interfacesCount >> 8);
-	contents[contentsOffset++] = (byte) interfacesCount;
+	this.contents[this.contentsOffset++] = (byte) (interfacesCount >> 8);
+	this.contents[this.contentsOffset++] = (byte) interfacesCount;
 	if (superInterfacesBinding != null) {
 		for (int i = 0; i < interfacesCount; i++) {
-			int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
-			contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
-			contents[contentsOffset++] = (byte) interfaceIndex;
+			int interfaceIndex = this.constantPool.literalIndex(superInterfacesBinding[i]);
+			this.contents[this.contentsOffset++] = (byte) (interfaceIndex >> 8);
+			this.contents[this.contentsOffset++] = (byte) interfaceIndex;
 		}
 	}
-	produceDebugAttributes =
-		((SourceTypeBinding) referenceBinding)
-			.scope
-			.environment()
-			.options
-			.produceDebugAttributes;
-	innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
+	this.produceDebugAttributes = this.referenceBinding.scope.environment().options.produceDebugAttributes;
+	this.innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
 	this.creatingProblemType = creatingProblemType;
-	codeStream = new CodeSnippetCodeStream(this);
+	this.codeStream = new CodeSnippetCodeStream(this);
 
 	// retrieve the enclosing one guaranteed to be the one matching the propagated flow info
 	// 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
 	ClassFile outermostClassFile = this.outerMostEnclosingClassFile();
 	if (this == outermostClassFile) {
-		codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
+		this.codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
 	} else {
-		codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
+		this.codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
 	}
 }
 /**
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCodeStream.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCodeStream.java
index c96723f..4b4b28f 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCodeStream.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCodeStream.java
@@ -19,6 +19,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 
 public class CodeSnippetCodeStream extends CodeStream {
 	static InvocationSite NO_INVOCATION_SITE = 
@@ -37,46 +38,46 @@
 	super(classFile);
 }
 protected void checkcast(int baseId) {
-	countLabels = 0;
+	this.countLabels = 0;
 	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_checkcast;
+		this.position++;
+		this.bCodeStream[this.classFileOffset++] = OPC_checkcast;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_checkcast);
 	}
 	switch (baseId) {
 		case T_byte :
-			writeUnsignedShort(constantPool.literalIndexForJavaLangByte());
+			writeUnsignedShort(this.constantPool.literalIndexForJavaLangByte());
 			break;
 		case T_short :
-			writeUnsignedShort(constantPool.literalIndexForJavaLangShort());
+			writeUnsignedShort(this.constantPool.literalIndexForJavaLangShort());
 			break;
 		case T_char :
-			writeUnsignedShort(constantPool.literalIndexForJavaLangCharacter());
+			writeUnsignedShort(this.constantPool.literalIndexForJavaLangCharacter());
 			break;
 		case T_int :
-			writeUnsignedShort(constantPool.literalIndexForJavaLangInteger());
+			writeUnsignedShort(this.constantPool.literalIndexForJavaLangInteger());
 			break;
 		case T_long :
-			writeUnsignedShort(constantPool.literalIndexForJavaLangLong());
+			writeUnsignedShort(this.constantPool.literalIndexForJavaLangLong());
 			break;
 		case T_float :
-			writeUnsignedShort(constantPool.literalIndexForJavaLangFloat());
+			writeUnsignedShort(this.constantPool.literalIndexForJavaLangFloat());
 			break;
 		case T_double :
-			writeUnsignedShort(constantPool.literalIndexForJavaLangDouble());
+			writeUnsignedShort(this.constantPool.literalIndexForJavaLangDouble());
 			break;
 		case T_boolean :
-			writeUnsignedShort(constantPool.literalIndexForJavaLangBoolean());
+			writeUnsignedShort(this.constantPool.literalIndexForJavaLangBoolean());
 	}
 }
 public void generateEmulatedAccessForMethod(Scope scope, MethodBinding methodBinding) {
-	CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this;
+	CodeSnippetCodeStream localCodeStream = this;
 	localCodeStream.generateEmulationForMethod(scope, methodBinding);
 	localCodeStream.invokeJavaLangReflectMethodInvoke();
 }
 public void generateEmulatedReadAccessForField(FieldBinding fieldBinding) {
-	CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this;
+	CodeSnippetCodeStream localCodeStream = this;
 	localCodeStream.generateEmulationForField(fieldBinding);
 	// swap  the field with the receiver
 	this.swap();
@@ -86,17 +87,17 @@
 	}
 }
 public void generateEmulatedWriteAccessForField(FieldBinding fieldBinding) {
-	CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this;
+	CodeSnippetCodeStream localCodeStream = this;
 	localCodeStream.invokeJavaLangReflectFieldSetter(fieldBinding.type.id);
 }
 public void generateEmulationForConstructor(Scope scope, MethodBinding methodBinding) {
 	// leave a java.lang.reflect.Field object on the stack
-	CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this;
+	CodeSnippetCodeStream localCodeStream = this;
 	this.ldc(String.valueOf(methodBinding.declaringClass.constantPoolName()).replace('/', '.'));
 	this.invokeClassForName();
 	int paramLength = methodBinding.parameters.length;
 	this.generateInlinedValue(paramLength);
-	this.newArray(scope, new ArrayBinding(scope.getType(TypeBinding.JAVA_LANG_CLASS), 1));
+	this.newArray(scope, new ArrayBinding(scope.getType(TypeConstants.JAVA_LANG_CLASS), 1));
 	if (paramLength > 0) {
 		this.dup();
 		for (int i = 0; i < paramLength; i++) {
@@ -135,7 +136,7 @@
 }
 public void generateEmulationForField(FieldBinding fieldBinding) {
 	// leave a java.lang.reflect.Field object on the stack
-	CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this;
+	CodeSnippetCodeStream localCodeStream = this;
 	this.ldc(String.valueOf(fieldBinding.declaringClass.constantPoolName()).replace('/', '.'));
 	this.invokeClassForName();
 	this.ldc(String.valueOf(fieldBinding.name));
@@ -146,13 +147,13 @@
 }
 public void generateEmulationForMethod(Scope scope, MethodBinding methodBinding) {
 	// leave a java.lang.reflect.Field object on the stack
-	CodeSnippetCodeStream localCodeStream = (CodeSnippetCodeStream) this;
+	CodeSnippetCodeStream localCodeStream = this;
 	this.ldc(String.valueOf(methodBinding.declaringClass.constantPoolName()).replace('/', '.'));
 	this.invokeClassForName();
 	this.ldc(String.valueOf(methodBinding.selector));
 	int paramLength = methodBinding.parameters.length;
 	this.generateInlinedValue(paramLength);
-	this.newArray(scope, new ArrayBinding(scope.getType(TypeBinding.JAVA_LANG_CLASS), 1));
+	this.newArray(scope, new ArrayBinding(scope.getType(TypeConstants.JAVA_LANG_CLASS), 1));
 	if (paramLength > 0) {
 		this.dup();
 		for (int i = 0; i < paramLength; i++) {
@@ -221,7 +222,7 @@
 			wrapperTypeCompoundName = new char[][] {"java".toCharArray(), "lang".toCharArray(), "Long".toCharArray()}; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
 			break;
 	}
-	TypeBinding wrapperType = methodDeclaration.scope.getType(wrapperTypeCompoundName);
+	TypeBinding wrapperType = this.methodDeclaration.scope.getType(wrapperTypeCompoundName);
 	new_(wrapperType);
 	if (valueType.id == T_long || valueType.id == T_double) {
 		dup_x2();
@@ -231,7 +232,7 @@
 		dup_x1();
 		swap();
 	}
-	MethodBinding methodBinding = methodDeclaration.scope.getMethod(
+	MethodBinding methodBinding = this.methodDeclaration.scope.getMethod(
 				wrapperType, 
 				QualifiedNamesConstants.Init, 
 				new TypeBinding[] {valueType}, 
@@ -239,127 +240,127 @@
 	invokespecial(methodBinding);
 }
 public void getBaseTypeValue(int baseTypeID) {
-	countLabels = 0;
+	this.countLabels = 0;
 	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_invokevirtual;
+		this.position++;
+		this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_invokevirtual);
 	}
 	switch (baseTypeID) {
 		case T_byte :
 			// invokevirtual: byteValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangByteByteValue());
+			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangByteByteValue());
 			break;
 		case T_short :
 			// invokevirtual: shortValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangShortShortValue());
+			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangShortShortValue());
 			break;
 		case T_char :
 			// invokevirtual: charValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangCharacterCharValue());
+			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangCharacterCharValue());
 			break;
 		case T_int :
 			// invokevirtual: intValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangIntegerIntValue());
+			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangIntegerIntValue());
 			break;
 		case T_long :
 			// invokevirtual: longValue()
-			stackDepth++;
-			if (stackDepth > stackMax)
-				stackMax = stackDepth;
-			writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangLongLongValue());
+			this.stackDepth++;
+			if (this.stackDepth > this.stackMax)
+				this.stackMax = this.stackDepth;
+			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangLongLongValue());
 			break;
 		case T_float :
 			// invokevirtual: floatValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangFloatFloatValue());
+			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangFloatFloatValue());
 			break;
 		case T_double :
 			// invokevirtual: doubleValue()
-			stackDepth++;
-			if (stackDepth > stackMax)
-				stackMax = stackDepth;
-			writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangDoubleDoubleValue());
+			this.stackDepth++;
+			if (this.stackDepth > this.stackMax)
+				this.stackMax = this.stackDepth;
+			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangDoubleDoubleValue());
 			break;
 		case T_boolean :
 			// invokevirtual: booleanValue()
-			writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangBooleanBooleanValue());
+			writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangBooleanBooleanValue());
 	}
 }
 protected void invokeAccessibleObjectSetAccessible() {
 	// invokevirtual: java.lang.reflect.AccessibleObject.setAccessible(Z)V;
-	countLabels = 0;
+	this.countLabels = 0;
 	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_invokevirtual;
+		this.position++;
+		this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_invokevirtual);
 	}
-	writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangReflectAccessibleObjectSetAccessible());
-	stackDepth-=2;
+	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangReflectAccessibleObjectSetAccessible());
+	this.stackDepth-=2;
 }
 protected void invokeArrayNewInstance() {
 	// invokestatic: java.lang.reflect.Array.newInstance(Ljava.lang.Class;int[])Ljava.lang.reflect.Array;
-	countLabels = 0;
+	this.countLabels = 0;
 	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_invokestatic;
+		this.position++;
+		this.bCodeStream[this.classFileOffset++] = OPC_invokestatic;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_invokestatic);
 	}
-	writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangReflectArrayNewInstance());
-	stackDepth--;
+	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangReflectArrayNewInstance());
+	this.stackDepth--;
 }
 protected void invokeClassGetDeclaredConstructor() {
 	// invokevirtual: java.lang.Class getDeclaredConstructor([Ljava.lang.Class)Ljava.lang.reflect.Constructor;
-	countLabels = 0;
+	this.countLabels = 0;
 	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_invokevirtual;
+		this.position++;
+		this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_invokevirtual);
 	}
-	writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangClassGetDeclaredConstructor());
-	stackDepth--;
+	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangClassGetDeclaredConstructor());
+	this.stackDepth--;
 }
 protected void invokeClassGetDeclaredField() {
 	// invokevirtual: java.lang.Class.getDeclaredField(Ljava.lang.String)Ljava.lang.reflect.Field;
-	countLabels = 0;
+	this.countLabels = 0;
 	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_invokevirtual;
+		this.position++;
+		this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_invokevirtual);
 	}
-	writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangClassGetDeclaredField());
-	stackDepth--;
+	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangClassGetDeclaredField());
+	this.stackDepth--;
 }
 protected void invokeClassGetDeclaredMethod() {
 	// invokevirtual: java.lang.Class getDeclaredMethod(Ljava.lang.String, [Ljava.lang.Class)Ljava.lang.reflect.Method;
-	countLabels = 0;
+	this.countLabels = 0;
 	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_invokevirtual;
+		this.position++;
+		this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_invokevirtual);
 	}
-	writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangClassGetDeclaredMethod());
-	stackDepth-=2;
+	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangClassGetDeclaredMethod());
+	this.stackDepth-=2;
 }
 protected void invokeJavaLangReflectConstructorNewInstance() {
 	// invokevirtual: java.lang.reflect.Constructor.newInstance([Ljava.lang.Object;)Ljava.lang.Object;
-	countLabels = 0;
+	this.countLabels = 0;
 	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_invokevirtual;
+		this.position++;
+		this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_invokevirtual);
 	}
-	writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangReflectConstructorNewInstance());
-	stackDepth--;
+	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangReflectConstructorNewInstance());
+	this.stackDepth--;
 }
 protected void invokeJavaLangReflectFieldGetter(int typeID) {
-	countLabels = 0;
+	this.countLabels = 0;
 	int usedTypeID;
 	if (typeID == T_null)
 		usedTypeID = T_Object;
@@ -367,18 +368,18 @@
 		usedTypeID = typeID;
 	// invokevirtual
 	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_invokevirtual;
+		this.position++;
+		this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_invokevirtual);
 	}
-	writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexJavaLangReflectFieldGetter(typeID));
+	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexJavaLangReflectFieldGetter(typeID));
 	if ((usedTypeID != T_long) && (usedTypeID != T_double)) {
-		stackDepth--;
+		this.stackDepth--;
 	}
 }
 protected void invokeJavaLangReflectFieldSetter(int typeID) {
-	countLabels = 0;
+	this.countLabels = 0;
 	int usedTypeID;
 	if (typeID == T_null)
 		usedTypeID = T_Object;
@@ -386,28 +387,28 @@
 		usedTypeID = typeID;
 	// invokevirtual
 	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_invokevirtual;
+		this.position++;
+		this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_invokevirtual);
 	}
-	writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexJavaLangReflectFieldSetter(typeID));
+	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexJavaLangReflectFieldSetter(typeID));
 	if ((usedTypeID != T_long) && (usedTypeID != T_double)) {
-		stackDepth-=3;
+		this.stackDepth-=3;
 	} else {
-		stackDepth-=4;
+		this.stackDepth-=4;
 	}
 }
 protected void invokeJavaLangReflectMethodInvoke() {
 	// invokevirtual: java.lang.reflect.Method.invoke(Ljava.lang.Object;[Ljava.lang.Object;)Ljava.lang.Object;
-	countLabels = 0;
+	this.countLabels = 0;
 	try {
-		position++;
-		bCodeStream[classFileOffset++] = OPC_invokevirtual;
+		this.position++;
+		this.bCodeStream[this.classFileOffset++] = OPC_invokevirtual;
 	} catch (IndexOutOfBoundsException e) {
 		resizeByteArray(OPC_invokevirtual);
 	}
-	writeUnsignedShort(((CodeSnippetConstantPool) constantPool).literalIndexForJavaLangReflectMethodInvoke());
-	stackDepth-=2;
+	writeUnsignedShort(((CodeSnippetConstantPool) this.constantPool).literalIndexForJavaLangReflectMethodInvoke());
+	this.stackDepth-=2;
 }
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCompiler.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCompiler.java
index 72cafcc..61b124e 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCompiler.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetCompiler.java
@@ -17,12 +17,16 @@
 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 
 /**
  * A compiler that compiles code snippets. 
  */
 public class CodeSnippetCompiler extends Compiler {
+	
+	EvaluationContext evaluationContext;
+	int codeSnippetStart;
+	int codeSnippetEnd;
+	
 	/**
 	 * Creates a new code snippet compiler initialized with a code snippet parser.
 	 */
@@ -38,13 +42,25 @@
 		super(environment, policy, settings, requestor, problemFactory);
 		this.parser =
 			new CodeSnippetParser(
-				problemReporter,
+				this.problemReporter,
 				evaluationContext,
 				this.options.parseLiteralExpressionsAsConstants,
-				this.options.sourceLevel >= CompilerOptions.JDK1_4,
 				codeSnippetStart,
 				codeSnippetEnd);
 		this.parseThreshold = 1;
 		// fully parse only the code snippet compilation unit
 	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.Compiler#initializeParser()
+	 */
+	public void initializeParser() {
+		this.parser =
+			new CodeSnippetParser(
+				this.problemReporter,
+				this.evaluationContext,
+				this.options.parseLiteralExpressionsAsConstants,
+				this.codeSnippetStart,
+				this.codeSnippetEnd);
+		}
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetConstantPool.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetConstantPool.java
index eda210c..c1e40ee 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetConstantPool.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetConstantPool.java
@@ -25,154 +25,154 @@
 public class CodeSnippetConstantPool extends ConstantPool implements TypeConstants {
 
 	// predefined type constant names
-	final static char[][] JAVA_LANG_REFLECT_FIELD = new char[][] {JAVA, LANG, REFLECT, "Field".toCharArray()}; //$NON-NLS-1$
-	final static char[][] JAVA_LANG_REFLECT_ACCESSIBLEOBJECT = new char[][] {JAVA, LANG, REFLECT, "AccessibleObject".toCharArray()}; //$NON-NLS-1$
-	final static char[][] JAVA_LANG_REFLECT_METHOD = new char[][] {JAVA, LANG, REFLECT, "Method".toCharArray()}; //$NON-NLS-1$
-	final static char[][] JAVA_LANG_REFLECT_ARRAY = new char[][] {JAVA, LANG, REFLECT, "Array".toCharArray()}; //$NON-NLS-1$
+	static final char[][] JAVA_LANG_REFLECT_FIELD = new char[][] {JAVA, LANG, REFLECT, "Field".toCharArray()}; //$NON-NLS-1$
+	static final char[][] JAVA_LANG_REFLECT_ACCESSIBLEOBJECT = new char[][] {JAVA, LANG, REFLECT, "AccessibleObject".toCharArray()}; //$NON-NLS-1$
+	static final char[][] JAVA_LANG_REFLECT_METHOD = new char[][] {JAVA, LANG, REFLECT, "Method".toCharArray()}; //$NON-NLS-1$
+	static final char[][] JAVA_LANG_REFLECT_ARRAY = new char[][] {JAVA, LANG, REFLECT, "Array".toCharArray()}; //$NON-NLS-1$
 
 	// predefined methods constant names
-	final static char[] GETDECLAREDFIELD_NAME = "getDeclaredField".toCharArray(); //$NON-NLS-1$
-	final static char[] GETDECLAREDFIELD_SIGNATURE = "(Ljava/lang/String;)Ljava/lang/reflect/Field;".toCharArray(); //$NON-NLS-1$
-	final static char[] SETACCESSIBLE_NAME = "setAccessible".toCharArray(); //$NON-NLS-1$
-	final static char[] SETACCESSIBLE_SIGNATURE = "(Z)V".toCharArray(); //$NON-NLS-1$
-	final static char[] JAVALANGREFLECTFIELD_CONSTANTPOOLNAME = "java/lang/reflect/Field".toCharArray(); //$NON-NLS-1$
-	final static char[] JAVALANGREFLECTACCESSIBLEOBJECT_CONSTANTPOOLNAME = "java/lang/reflect/AccessibleObject".toCharArray(); //$NON-NLS-1$
-	final static char[] JAVALANGREFLECTARRAY_CONSTANTPOOLNAME = "java/lang/reflect/Array".toCharArray(); //$NON-NLS-1$
-	final static char[] JAVALANGREFLECTMETHOD_CONSTANTPOOLNAME = "java/lang/reflect/Method".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_INT_METHOD_NAME = "getInt".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_LONG_METHOD_NAME = "getLong".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_DOUBLE_METHOD_NAME = "getDouble".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_FLOAT_METHOD_NAME = "getFloat".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_BYTE_METHOD_NAME = "getByte".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_CHAR_METHOD_NAME = "getChar".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_BOOLEAN_METHOD_NAME = "getBoolean".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_OBJECT_METHOD_NAME = "get".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_SHORT_METHOD_NAME = "getShort".toCharArray(); //$NON-NLS-1$
-	final static char[] ARRAY_NEWINSTANCE_NAME = "newInstance".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;)I".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;)J".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;)D".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;)F".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;)B".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;)C".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;)Z".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
-	final static char[] GET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;)S".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_INT_METHOD_NAME = "setInt".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_LONG_METHOD_NAME = "setLong".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_DOUBLE_METHOD_NAME = "setDouble".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_FLOAT_METHOD_NAME = "setFloat".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_BYTE_METHOD_NAME = "setByte".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_CHAR_METHOD_NAME = "setChar".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_BOOLEAN_METHOD_NAME = "setBoolean".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_OBJECT_METHOD_NAME = "set".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_SHORT_METHOD_NAME = "setShort".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;I)V".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;J)V".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;D)V".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;F)V".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;B)V".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;C)V".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;Z)V".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;Ljava/lang/Object;)V".toCharArray(); //$NON-NLS-1$
-	final static char[] SET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;S)V".toCharArray(); //$NON-NLS-1$
-	final static char[] GETDECLAREDMETHOD_NAME = "getDeclaredMethod".toCharArray(); //$NON-NLS-1$
-	final static char[] GETDECLAREDMETHOD_SIGNATURE = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;".toCharArray(); //$NON-NLS-1$
-	final static char[] ARRAY_NEWINSTANCE_SIGNATURE = "(Ljava/lang/Class;[I)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
-	final static char[] INVOKE_METHOD_METHOD_NAME = "invoke".toCharArray(); //$NON-NLS-1$
-	final static char[] INVOKE_METHOD_METHOD_SIGNATURE = "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
-	final static char[] BYTEVALUE_BYTE_METHOD_NAME = "byteValue".toCharArray(); //$NON-NLS-1$
-	final static char[] BYTEVALUE_BYTE_METHOD_SIGNATURE = "()B".toCharArray(); //$NON-NLS-1$
-	final static char[] SHORTVALUE_SHORT_METHOD_NAME = "shortValue".toCharArray(); //$NON-NLS-1$
-	final static char[] DOUBLEVALUE_DOUBLE_METHOD_NAME = "doubleValue".toCharArray(); //$NON-NLS-1$
-	final static char[] FLOATVALUE_FLOAT_METHOD_NAME = "floatValue".toCharArray(); //$NON-NLS-1$
-	final static char[] INTVALUE_INTEGER_METHOD_NAME = "intValue".toCharArray(); //$NON-NLS-1$
-	final static char[] CHARVALUE_CHARACTER_METHOD_NAME = "charValue".toCharArray(); //$NON-NLS-1$
-	final static char[] BOOLEANVALUE_BOOLEAN_METHOD_NAME = "booleanValue".toCharArray(); //$NON-NLS-1$
-	final static char[] LONGVALUE_LONG_METHOD_NAME = "longValue".toCharArray(); //$NON-NLS-1$
-	final static char[] SHORTVALUE_SHORT_METHOD_SIGNATURE = "()S".toCharArray(); //$NON-NLS-1$
-	final static char[] DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE = "()D".toCharArray(); //$NON-NLS-1$
-	final static char[] FLOATVALUE_FLOAT_METHOD_SIGNATURE = "()F".toCharArray(); //$NON-NLS-1$
-	final static char[] INTVALUE_INTEGER_METHOD_SIGNATURE = "()I".toCharArray(); //$NON-NLS-1$
-	final static char[] CHARVALUE_CHARACTER_METHOD_SIGNATURE = "()C".toCharArray(); //$NON-NLS-1$
-	final static char[] BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE = "()Z".toCharArray(); //$NON-NLS-1$
-	final static char[] LONGVALUE_LONG_METHOD_SIGNATURE = "()J".toCharArray(); //$NON-NLS-1$
-	final static char[] GETDECLAREDCONSTRUCTOR_NAME = "getDeclaredConstructor".toCharArray(); //$NON-NLS-1$
-	final static char[] GETDECLAREDCONSTRUCTOR_SIGNATURE = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;".toCharArray(); //$NON-NLS-1$
+	static final char[] GETDECLAREDFIELD_NAME = "getDeclaredField".toCharArray(); //$NON-NLS-1$
+	static final char[] GETDECLAREDFIELD_SIGNATURE = "(Ljava/lang/String;)Ljava/lang/reflect/Field;".toCharArray(); //$NON-NLS-1$
+	static final char[] SETACCESSIBLE_NAME = "setAccessible".toCharArray(); //$NON-NLS-1$
+	static final char[] SETACCESSIBLE_SIGNATURE = "(Z)V".toCharArray(); //$NON-NLS-1$
+	static final char[] JAVALANGREFLECTFIELD_CONSTANTPOOLNAME = "java/lang/reflect/Field".toCharArray(); //$NON-NLS-1$
+	static final char[] JAVALANGREFLECTACCESSIBLEOBJECT_CONSTANTPOOLNAME = "java/lang/reflect/AccessibleObject".toCharArray(); //$NON-NLS-1$
+	static final char[] JAVALANGREFLECTARRAY_CONSTANTPOOLNAME = "java/lang/reflect/Array".toCharArray(); //$NON-NLS-1$
+	static final char[] JAVALANGREFLECTMETHOD_CONSTANTPOOLNAME = "java/lang/reflect/Method".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_INT_METHOD_NAME = "getInt".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_LONG_METHOD_NAME = "getLong".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_DOUBLE_METHOD_NAME = "getDouble".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_FLOAT_METHOD_NAME = "getFloat".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_BYTE_METHOD_NAME = "getByte".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_CHAR_METHOD_NAME = "getChar".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_BOOLEAN_METHOD_NAME = "getBoolean".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_OBJECT_METHOD_NAME = "get".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_SHORT_METHOD_NAME = "getShort".toCharArray(); //$NON-NLS-1$
+	static final char[] ARRAY_NEWINSTANCE_NAME = "newInstance".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;)I".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;)J".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;)D".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;)F".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;)B".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;)C".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;)Z".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+	static final char[] GET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;)S".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_INT_METHOD_NAME = "setInt".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_LONG_METHOD_NAME = "setLong".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_DOUBLE_METHOD_NAME = "setDouble".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_FLOAT_METHOD_NAME = "setFloat".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_BYTE_METHOD_NAME = "setByte".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_CHAR_METHOD_NAME = "setChar".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_BOOLEAN_METHOD_NAME = "setBoolean".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_OBJECT_METHOD_NAME = "set".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_SHORT_METHOD_NAME = "setShort".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_INT_METHOD_SIGNATURE = "(Ljava/lang/Object;I)V".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_LONG_METHOD_SIGNATURE = "(Ljava/lang/Object;J)V".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_DOUBLE_METHOD_SIGNATURE = "(Ljava/lang/Object;D)V".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_FLOAT_METHOD_SIGNATURE = "(Ljava/lang/Object;F)V".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_BYTE_METHOD_SIGNATURE = "(Ljava/lang/Object;B)V".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_CHAR_METHOD_SIGNATURE = "(Ljava/lang/Object;C)V".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_BOOLEAN_METHOD_SIGNATURE = "(Ljava/lang/Object;Z)V".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_OBJECT_METHOD_SIGNATURE = "(Ljava/lang/Object;Ljava/lang/Object;)V".toCharArray(); //$NON-NLS-1$
+	static final char[] SET_SHORT_METHOD_SIGNATURE = "(Ljava/lang/Object;S)V".toCharArray(); //$NON-NLS-1$
+	static final char[] GETDECLAREDMETHOD_NAME = "getDeclaredMethod".toCharArray(); //$NON-NLS-1$
+	static final char[] GETDECLAREDMETHOD_SIGNATURE = "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;".toCharArray(); //$NON-NLS-1$
+	static final char[] ARRAY_NEWINSTANCE_SIGNATURE = "(Ljava/lang/Class;[I)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+	static final char[] INVOKE_METHOD_METHOD_NAME = "invoke".toCharArray(); //$NON-NLS-1$
+	static final char[] INVOKE_METHOD_METHOD_SIGNATURE = "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;".toCharArray(); //$NON-NLS-1$
+	static final char[] BYTEVALUE_BYTE_METHOD_NAME = "byteValue".toCharArray(); //$NON-NLS-1$
+	static final char[] BYTEVALUE_BYTE_METHOD_SIGNATURE = "()B".toCharArray(); //$NON-NLS-1$
+	static final char[] SHORTVALUE_SHORT_METHOD_NAME = "shortValue".toCharArray(); //$NON-NLS-1$
+	static final char[] DOUBLEVALUE_DOUBLE_METHOD_NAME = "doubleValue".toCharArray(); //$NON-NLS-1$
+	static final char[] FLOATVALUE_FLOAT_METHOD_NAME = "floatValue".toCharArray(); //$NON-NLS-1$
+	static final char[] INTVALUE_INTEGER_METHOD_NAME = "intValue".toCharArray(); //$NON-NLS-1$
+	static final char[] CHARVALUE_CHARACTER_METHOD_NAME = "charValue".toCharArray(); //$NON-NLS-1$
+	static final char[] BOOLEANVALUE_BOOLEAN_METHOD_NAME = "booleanValue".toCharArray(); //$NON-NLS-1$
+	static final char[] LONGVALUE_LONG_METHOD_NAME = "longValue".toCharArray(); //$NON-NLS-1$
+	static final char[] SHORTVALUE_SHORT_METHOD_SIGNATURE = "()S".toCharArray(); //$NON-NLS-1$
+	static final char[] DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE = "()D".toCharArray(); //$NON-NLS-1$
+	static final char[] FLOATVALUE_FLOAT_METHOD_SIGNATURE = "()F".toCharArray(); //$NON-NLS-1$
+	static final char[] INTVALUE_INTEGER_METHOD_SIGNATURE = "()I".toCharArray(); //$NON-NLS-1$
+	static final char[] CHARVALUE_CHARACTER_METHOD_SIGNATURE = "()C".toCharArray(); //$NON-NLS-1$
+	static final char[] BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE = "()Z".toCharArray(); //$NON-NLS-1$
+	static final char[] LONGVALUE_LONG_METHOD_SIGNATURE = "()J".toCharArray(); //$NON-NLS-1$
+	static final char[] GETDECLAREDCONSTRUCTOR_NAME = "getDeclaredConstructor".toCharArray(); //$NON-NLS-1$
+	static final char[] GETDECLAREDCONSTRUCTOR_SIGNATURE = "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;".toCharArray(); //$NON-NLS-1$
 	
 	// predefined constant index for well known types
-	final static int JAVA_LANG_REFLECT_FIELD_TYPE = 0;
-	final static int JAVA_LANG_REFLECT_METHOD_TYPE = 1;
-	final static int JAVA_LANG_REFLECT_ACCESSIBLEOBJECT_TYPE = 2;
-	final static int JAVA_LANG_REFLECT_ARRAY_TYPE = 3;
+	static final int JAVA_LANG_REFLECT_FIELD_TYPE = 0;
+	static final int JAVA_LANG_REFLECT_METHOD_TYPE = 1;
+	static final int JAVA_LANG_REFLECT_ACCESSIBLEOBJECT_TYPE = 2;
+	static final int JAVA_LANG_REFLECT_ARRAY_TYPE = 3;
 
 	// predefined constant index for well known methods
-	final static int GETDECLAREDFIELD_CLASS_METHOD = 0;
-	final static int SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD = 1;
-	final static int GET_INT_METHOD = 2;
-	final static int GET_LONG_METHOD = 3;
-	final static int GET_DOUBLE_METHOD = 4;
-	final static int GET_FLOAT_METHOD = 5;
-	final static int GET_BYTE_METHOD = 6;
-	final static int GET_CHAR_METHOD = 7;
-	final static int GET_BOOLEAN_METHOD = 8;
-	final static int GET_OBJECT_METHOD = 9;
-	final static int GET_SHORT_METHOD = 10;
-	final static int SET_INT_METHOD = 11;
-	final static int SET_LONG_METHOD = 12;
-	final static int SET_DOUBLE_METHOD = 13;
-	final static int SET_FLOAT_METHOD = 14;
-	final static int SET_BYTE_METHOD = 15;
-	final static int SET_CHAR_METHOD = 16;
-	final static int SET_BOOLEAN_METHOD = 17;
-	final static int SET_OBJECT_METHOD = 18;
-	final static int SET_SHORT_METHOD = 19;
-	final static int GETDECLAREDMETHOD_CLASS_METHOD = 20;
-	final static int NEWINSTANCE_ARRAY_METHOD = 21;
-	final static int INVOKE_METHOD_METHOD = 22;
-	final static int BYTEVALUE_BYTE_METHOD = 23;
-	final static int SHORTVALUE_SHORT_METHOD = 24;
-	final static int DOUBLEVALUE_DOUBLE_METHOD = 25;
-	final static int FLOATVALUE_FLOAT_METHOD = 26;
-	final static int INTVALUE_INTEGER_METHOD = 27;
-	final static int CHARVALUE_CHARACTER_METHOD = 28;
-	final static int BOOLEANVALUE_BOOLEAN_METHOD = 29;
-	final static int LONGVALUE_LONG_METHOD = 30;
-	final static int GETDECLAREDCONSTRUCTOR_CLASS_METHOD = 31;
+	static final int GETDECLAREDFIELD_CLASS_METHOD = 0;
+	static final int SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD = 1;
+	static final int GET_INT_METHOD = 2;
+	static final int GET_LONG_METHOD = 3;
+	static final int GET_DOUBLE_METHOD = 4;
+	static final int GET_FLOAT_METHOD = 5;
+	static final int GET_BYTE_METHOD = 6;
+	static final int GET_CHAR_METHOD = 7;
+	static final int GET_BOOLEAN_METHOD = 8;
+	static final int GET_OBJECT_METHOD = 9;
+	static final int GET_SHORT_METHOD = 10;
+	static final int SET_INT_METHOD = 11;
+	static final int SET_LONG_METHOD = 12;
+	static final int SET_DOUBLE_METHOD = 13;
+	static final int SET_FLOAT_METHOD = 14;
+	static final int SET_BYTE_METHOD = 15;
+	static final int SET_CHAR_METHOD = 16;
+	static final int SET_BOOLEAN_METHOD = 17;
+	static final int SET_OBJECT_METHOD = 18;
+	static final int SET_SHORT_METHOD = 19;
+	static final int GETDECLAREDMETHOD_CLASS_METHOD = 20;
+	static final int NEWINSTANCE_ARRAY_METHOD = 21;
+	static final int INVOKE_METHOD_METHOD = 22;
+	static final int BYTEVALUE_BYTE_METHOD = 23;
+	static final int SHORTVALUE_SHORT_METHOD = 24;
+	static final int DOUBLEVALUE_DOUBLE_METHOD = 25;
+	static final int FLOATVALUE_FLOAT_METHOD = 26;
+	static final int INTVALUE_INTEGER_METHOD = 27;
+	static final int CHARVALUE_CHARACTER_METHOD = 28;
+	static final int BOOLEANVALUE_BOOLEAN_METHOD = 29;
+	static final int LONGVALUE_LONG_METHOD = 30;
+	static final int GETDECLAREDCONSTRUCTOR_CLASS_METHOD = 31;
 	
 	// predefined constant index for well known name and type for methods
-	final static int GETDECLAREDFIELD_CLASS_METHOD_NAME_AND_TYPE = 0;
-	final static int SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD_NAME_AND_TYPE = 1;
-	final static int GET_INT_METHOD_NAME_AND_TYPE = 2;
-	final static int GET_LONG_METHOD_NAME_AND_TYPE = 3;
-	final static int GET_DOUBLE_METHOD_NAME_AND_TYPE = 4;
-	final static int GET_FLOAT_METHOD_NAME_AND_TYPE = 5;
-	final static int GET_BYTE_METHOD_NAME_AND_TYPE = 6;
-	final static int GET_CHAR_METHOD_NAME_AND_TYPE = 7;
-	final static int GET_BOOLEAN_METHOD_NAME_AND_TYPE = 8;
-	final static int GET_OBJECT_METHOD_NAME_AND_TYPE = 9;
-	final static int GET_SHORT_METHOD_NAME_AND_TYPE = 10;
-	final static int SET_INT_METHOD_NAME_AND_TYPE = 11;
-	final static int SET_LONG_METHOD_NAME_AND_TYPE = 12;
-	final static int SET_DOUBLE_METHOD_NAME_AND_TYPE = 13;
-	final static int SET_FLOAT_METHOD_NAME_AND_TYPE = 14;
-	final static int SET_BYTE_METHOD_NAME_AND_TYPE = 15;
-	final static int SET_CHAR_METHOD_NAME_AND_TYPE = 16;
-	final static int SET_BOOLEAN_METHOD_NAME_AND_TYPE = 17;
-	final static int SET_OBJECT_METHOD_NAME_AND_TYPE = 18;
-	final static int SET_SHORT_METHOD_NAME_AND_TYPE = 19;
-	final static int GETDECLAREDMETHOD_CLASS_METHOD_NAME_AND_TYPE = 20;
-	final static int ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE = 21;
-	final static int INVOKE_METHOD_METHOD_NAME_AND_TYPE = 22;
-	final static int BYTEVALUE_BYTE_METHOD_NAME_AND_TYPE = 23;
-	final static int SHORTVALUE_SHORT_METHOD_NAME_AND_TYPE = 24;
-	final static int DOUBLEVALUE_DOUBLE_METHOD_NAME_AND_TYPE = 25;
-	final static int FLOATVALUE_FLOAT_METHOD_NAME_AND_TYPE = 26;
-	final static int INTVALUE_INTEGER_METHOD_NAME_AND_TYPE = 27;
-	final static int CHARVALUE_CHARACTER_METHOD_NAME_AND_TYPE = 28;
-	final static int BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE = 29;
-	final static int LONGVALUE_LONG_METHOD_NAME_AND_TYPE = 30;
-	final static int GETDECLAREDCONSTRUCTOR_CLASS_METHOD_NAME_AND_TYPE = 31;
+	static final int GETDECLAREDFIELD_CLASS_METHOD_NAME_AND_TYPE = 0;
+	static final int SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD_NAME_AND_TYPE = 1;
+	static final int GET_INT_METHOD_NAME_AND_TYPE = 2;
+	static final int GET_LONG_METHOD_NAME_AND_TYPE = 3;
+	static final int GET_DOUBLE_METHOD_NAME_AND_TYPE = 4;
+	static final int GET_FLOAT_METHOD_NAME_AND_TYPE = 5;
+	static final int GET_BYTE_METHOD_NAME_AND_TYPE = 6;
+	static final int GET_CHAR_METHOD_NAME_AND_TYPE = 7;
+	static final int GET_BOOLEAN_METHOD_NAME_AND_TYPE = 8;
+	static final int GET_OBJECT_METHOD_NAME_AND_TYPE = 9;
+	static final int GET_SHORT_METHOD_NAME_AND_TYPE = 10;
+	static final int SET_INT_METHOD_NAME_AND_TYPE = 11;
+	static final int SET_LONG_METHOD_NAME_AND_TYPE = 12;
+	static final int SET_DOUBLE_METHOD_NAME_AND_TYPE = 13;
+	static final int SET_FLOAT_METHOD_NAME_AND_TYPE = 14;
+	static final int SET_BYTE_METHOD_NAME_AND_TYPE = 15;
+	static final int SET_CHAR_METHOD_NAME_AND_TYPE = 16;
+	static final int SET_BOOLEAN_METHOD_NAME_AND_TYPE = 17;
+	static final int SET_OBJECT_METHOD_NAME_AND_TYPE = 18;
+	static final int SET_SHORT_METHOD_NAME_AND_TYPE = 19;
+	static final int GETDECLAREDMETHOD_CLASS_METHOD_NAME_AND_TYPE = 20;
+	static final int ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE = 21;
+	static final int INVOKE_METHOD_METHOD_NAME_AND_TYPE = 22;
+	static final int BYTEVALUE_BYTE_METHOD_NAME_AND_TYPE = 23;
+	static final int SHORTVALUE_SHORT_METHOD_NAME_AND_TYPE = 24;
+	static final int DOUBLEVALUE_DOUBLE_METHOD_NAME_AND_TYPE = 25;
+	static final int FLOATVALUE_FLOAT_METHOD_NAME_AND_TYPE = 26;
+	static final int INTVALUE_INTEGER_METHOD_NAME_AND_TYPE = 27;
+	static final int CHARVALUE_CHARACTER_METHOD_NAME_AND_TYPE = 28;
+	static final int BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE = 29;
+	static final int LONGVALUE_LONG_METHOD_NAME_AND_TYPE = 30;
+	static final int GETDECLAREDCONSTRUCTOR_CLASS_METHOD_NAME_AND_TYPE = 31;
 	
 	int[] wellKnownTypes = new int[4];
 	int[] wellKnownMethods = new int[32];
@@ -695,14 +695,14 @@
 		if ((indexWellKnownMethod = indexOfWellKnownMethods(aMethodBinding)) == -1) {
 			if (aMethodBinding.declaringClass.isInterface()) {
 				// Lookinf into the interface method ref table
-				if ((index = interfaceMethodCache.get(aMethodBinding)) < 0) {
+				if ((index = this.interfaceMethodCache.get(aMethodBinding)) < 0) {
 					classIndex = literalIndex(aMethodBinding.declaringClass);
 					nameAndTypeIndex =
 						literalIndexForMethods(
 							literalIndex(aMethodBinding.constantPoolName()),
 							literalIndex(aMethodBinding.signature()),
 							aMethodBinding);
-					index = interfaceMethodCache.put(aMethodBinding, currentIndex++);
+					index = this.interfaceMethodCache.put(aMethodBinding, this.currentIndex++);
 					// Write the interface method ref constant into the constant pool
 					// First add the tag
 					writeU1(InterfaceMethodRefTag);
@@ -713,14 +713,14 @@
 				}
 			} else {
 				// Lookinf into the method ref table
-				if ((index = methodCache.get(aMethodBinding)) < 0) {
+				if ((index = this.methodCache.get(aMethodBinding)) < 0) {
 					classIndex = literalIndex(aMethodBinding.declaringClass);
 					nameAndTypeIndex =
 						literalIndexForMethods(
 							literalIndex(aMethodBinding.constantPoolName()),
 							literalIndex(aMethodBinding.signature()),
 							aMethodBinding);
-					index = methodCache.put(aMethodBinding, currentIndex++);
+					index = this.methodCache.put(aMethodBinding, this.currentIndex++);
 					// Write the method ref constant into the constant pool
 					// First add the tag
 					writeU1(MethodRefTag);
@@ -732,7 +732,7 @@
 			}
 		} else {
 			// This is a well known method
-			if ((index = wellKnownMethods[indexWellKnownMethod]) == 0) {
+			if ((index = this.wellKnownMethods[indexWellKnownMethod]) == 0) {
 				// this methods was not inserted yet
 				if (aMethodBinding.declaringClass.isInterface()) {
 					// Lookinf into the interface method ref table
@@ -742,7 +742,7 @@
 							literalIndex(aMethodBinding.constantPoolName()),
 							literalIndex(aMethodBinding.signature()),
 							aMethodBinding);
-					index = wellKnownMethods[indexWellKnownMethod] = currentIndex++;
+					index = this.wellKnownMethods[indexWellKnownMethod] = this.currentIndex++;
 					// Write the interface method ref constant into the constant pool
 					// First add the tag
 					writeU1(InterfaceMethodRefTag);
@@ -758,7 +758,7 @@
 							literalIndex(aMethodBinding.constantPoolName()),
 							literalIndex(aMethodBinding.signature()),
 							aMethodBinding);
-					index = wellKnownMethods[indexWellKnownMethod] = currentIndex++;
+					index = this.wellKnownMethods[indexWellKnownMethod] = this.currentIndex++;
 					// Write the method ref constant into the constant pool
 					// First add the tag
 					writeU1(MethodRefTag);
@@ -786,19 +786,19 @@
 	int indexWellKnownType;
 	if ((indexWellKnownType = super.indexOfWellKnownTypes(aTypeBinding)) == -1) {
 		if ((indexWellKnownType = indexOfWellKnownTypes(aTypeBinding)) == -1) {
-			if ((index = classCache.get(aTypeBinding)) < 0) {
+			if ((index = this.classCache.get(aTypeBinding)) < 0) {
 				// The entry doesn't exit yet
 				nameIndex = literalIndex(aTypeBinding.constantPoolName());
-				index = classCache.put(aTypeBinding, currentIndex++);
+				index = this.classCache.put(aTypeBinding, this.currentIndex++);
 				writeU1(ClassTag);
 				// Then add the 8 bytes representing the long
 				writeU2(nameIndex);
 			}
 		} else {
-			if ((index = wellKnownTypes[indexWellKnownType]) == 0) {
+			if ((index = this.wellKnownTypes[indexWellKnownType]) == 0) {
 				// Need to insert that binding
 				nameIndex = literalIndex(aTypeBinding.constantPoolName());
-				index = wellKnownTypes[indexWellKnownType] = currentIndex++;
+				index = this.wellKnownTypes[indexWellKnownType] = this.currentIndex++;
 				writeU1(ClassTag);
 				// Then add the 8 bytes representing the long
 				writeU2(nameIndex);
@@ -821,17 +821,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[BOOLEANVALUE_BOOLEAN_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[BOOLEANVALUE_BOOLEAN_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangBoolean();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(BOOLEANVALUE_BOOLEAN_METHOD_NAME);
 			int typeIndex = literalIndex(BOOLEANVALUE_BOOLEAN_METHOD_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE] = currentIndex++;
+		index = this.wellKnownMethods[BOOLEANVALUE_BOOLEAN_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -854,17 +854,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[BYTEVALUE_BYTE_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[BYTEVALUE_BYTE_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangByte();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[BYTEVALUE_BYTE_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[BYTEVALUE_BYTE_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(BYTEVALUE_BYTE_METHOD_NAME);
 			int typeIndex = literalIndex(BYTEVALUE_BYTE_METHOD_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[BYTEVALUE_BYTE_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[BYTEVALUE_BYTE_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[BYTEVALUE_BYTE_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[BYTEVALUE_BYTE_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -887,17 +887,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[CHARVALUE_CHARACTER_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[CHARVALUE_CHARACTER_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangCharacter();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CHARVALUE_CHARACTER_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[CHARVALUE_CHARACTER_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(CHARVALUE_CHARACTER_METHOD_NAME);
 			int typeIndex = literalIndex(CHARVALUE_CHARACTER_METHOD_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[CHARVALUE_CHARACTER_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[CHARVALUE_CHARACTER_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[CHARVALUE_CHARACTER_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[CHARVALUE_CHARACTER_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -920,17 +920,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[GETDECLAREDCONSTRUCTOR_CLASS_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[GETDECLAREDCONSTRUCTOR_CLASS_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangClass();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETDECLAREDCONSTRUCTOR_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDCONSTRUCTOR_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(GETDECLAREDCONSTRUCTOR_NAME);
 			int typeIndex = literalIndex(GETDECLAREDCONSTRUCTOR_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[GETDECLAREDCONSTRUCTOR_CLASS_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDCONSTRUCTOR_CLASS_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[GETDECLAREDCONSTRUCTOR_CLASS_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[GETDECLAREDCONSTRUCTOR_CLASS_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -953,17 +953,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[GETDECLAREDFIELD_CLASS_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[GETDECLAREDFIELD_CLASS_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangClass();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETDECLAREDFIELD_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDFIELD_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(GETDECLAREDFIELD_NAME);
 			int typeIndex = literalIndex(GETDECLAREDFIELD_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[GETDECLAREDFIELD_CLASS_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDFIELD_CLASS_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[GETDECLAREDFIELD_CLASS_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[GETDECLAREDFIELD_CLASS_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -986,17 +986,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[GETDECLAREDMETHOD_CLASS_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[GETDECLAREDMETHOD_CLASS_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangClass();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETDECLAREDMETHOD_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDMETHOD_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(GETDECLAREDMETHOD_NAME);
 			int typeIndex = literalIndex(GETDECLAREDMETHOD_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[GETDECLAREDMETHOD_CLASS_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[GETDECLAREDMETHOD_CLASS_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[GETDECLAREDMETHOD_CLASS_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[GETDECLAREDMETHOD_CLASS_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -1019,17 +1019,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[DOUBLEVALUE_DOUBLE_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[DOUBLEVALUE_DOUBLE_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangDouble();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[DOUBLEVALUE_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[DOUBLEVALUE_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(DOUBLEVALUE_DOUBLE_METHOD_NAME);
 			int typeIndex = literalIndex(DOUBLEVALUE_DOUBLE_METHOD_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[DOUBLEVALUE_DOUBLE_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[DOUBLEVALUE_DOUBLE_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[DOUBLEVALUE_DOUBLE_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[DOUBLEVALUE_DOUBLE_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -1052,17 +1052,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[FLOATVALUE_FLOAT_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[FLOATVALUE_FLOAT_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangFloat();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[FLOATVALUE_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[FLOATVALUE_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(FLOATVALUE_FLOAT_METHOD_NAME);
 			int typeIndex = literalIndex(FLOATVALUE_FLOAT_METHOD_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[FLOATVALUE_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[FLOATVALUE_FLOAT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[FLOATVALUE_FLOAT_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[FLOATVALUE_FLOAT_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -1085,17 +1085,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[INTVALUE_INTEGER_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[INTVALUE_INTEGER_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangInteger();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[INTVALUE_INTEGER_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[INTVALUE_INTEGER_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(INTVALUE_INTEGER_METHOD_NAME);
 			int typeIndex = literalIndex(INTVALUE_INTEGER_METHOD_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[INTVALUE_INTEGER_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[INTVALUE_INTEGER_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[INTVALUE_INTEGER_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[INTVALUE_INTEGER_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -1118,17 +1118,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[LONGVALUE_LONG_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[LONGVALUE_LONG_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangLong();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[LONGVALUE_LONG_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[LONGVALUE_LONG_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(LONGVALUE_LONG_METHOD_NAME);
 			int typeIndex = literalIndex(LONGVALUE_LONG_METHOD_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[LONGVALUE_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[LONGVALUE_LONG_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[LONGVALUE_LONG_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[LONGVALUE_LONG_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -1148,11 +1148,11 @@
  */
 public int literalIndexForJavaLangReflectAccessibleObject() {
 	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_REFLECT_ACCESSIBLEOBJECT_TYPE]) == 0) {
+	if ((index = this.wellKnownTypes[JAVA_LANG_REFLECT_ACCESSIBLEOBJECT_TYPE]) == 0) {
 		int nameIndex;
 		// The entry doesn't exit yet
 		nameIndex = literalIndex(JAVALANGREFLECTACCESSIBLEOBJECT_CONSTANTPOOLNAME);
-		index = wellKnownTypes[JAVA_LANG_REFLECT_ACCESSIBLEOBJECT_TYPE] = currentIndex++;
+		index = this.wellKnownTypes[JAVA_LANG_REFLECT_ACCESSIBLEOBJECT_TYPE] = this.currentIndex++;
 		writeU1(ClassTag);
 		// Then add the 8 bytes representing the long
 		writeU2(nameIndex);
@@ -1171,17 +1171,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangReflectAccessibleObject();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(SETACCESSIBLE_NAME);
 			int typeIndex = literalIndex(SETACCESSIBLE_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[SETACCESSIBLE_ACCESSIBLEOBJECT_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -1201,11 +1201,11 @@
  */
 public int literalIndexForJavaLangReflectArray() {
 	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_REFLECT_ARRAY_TYPE]) == 0) {
+	if ((index = this.wellKnownTypes[JAVA_LANG_REFLECT_ARRAY_TYPE]) == 0) {
 		int nameIndex;
 		// The entry doesn't exit yet
 		nameIndex = literalIndex(JAVALANGREFLECTARRAY_CONSTANTPOOLNAME);
-		index = wellKnownTypes[JAVA_LANG_REFLECT_ARRAY_TYPE] = currentIndex++;
+		index = this.wellKnownTypes[JAVA_LANG_REFLECT_ARRAY_TYPE] = this.currentIndex++;
 		writeU1(ClassTag);
 		// Then add the 8 bytes representing the long
 		writeU2(nameIndex);
@@ -1224,17 +1224,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[NEWINSTANCE_ARRAY_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangReflectArray();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(ARRAY_NEWINSTANCE_NAME);
 			int typeIndex = literalIndex(ARRAY_NEWINSTANCE_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[ARRAY_NEWINSTANCE_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[NEWINSTANCE_ARRAY_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[NEWINSTANCE_ARRAY_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -1254,11 +1254,11 @@
  */
 public int literalIndexForJavaLangReflectField() {
 	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_REFLECT_FIELD_TYPE]) == 0) {
+	if ((index = this.wellKnownTypes[JAVA_LANG_REFLECT_FIELD_TYPE]) == 0) {
 		int nameIndex;
 		// The entry doesn't exit yet
 		nameIndex = literalIndex(JAVALANGREFLECTFIELD_CONSTANTPOOLNAME);
-		index = wellKnownTypes[JAVA_LANG_REFLECT_FIELD_TYPE] = currentIndex++;
+		index = this.wellKnownTypes[JAVA_LANG_REFLECT_FIELD_TYPE] = this.currentIndex++;
 		writeU1(ClassTag);
 		// Then add the 8 bytes representing the long
 		writeU2(nameIndex);
@@ -1274,11 +1274,11 @@
  */
 public int literalIndexForJavaLangReflectMethod() {
 	int index;
-	if ((index = wellKnownTypes[JAVA_LANG_REFLECT_METHOD_TYPE]) == 0) {
+	if ((index = this.wellKnownTypes[JAVA_LANG_REFLECT_METHOD_TYPE]) == 0) {
 		int nameIndex;
 		// The entry doesn't exit yet
 		nameIndex = literalIndex(JAVALANGREFLECTMETHOD_CONSTANTPOOLNAME);
-		index = wellKnownTypes[JAVA_LANG_REFLECT_METHOD_TYPE] = currentIndex++;
+		index = this.wellKnownTypes[JAVA_LANG_REFLECT_METHOD_TYPE] = this.currentIndex++;
 		writeU1(ClassTag);
 		// Then add the 8 bytes representing the long
 		writeU2(nameIndex);
@@ -1297,17 +1297,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[INVOKE_METHOD_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[INVOKE_METHOD_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangReflectMethod();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[INVOKE_METHOD_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[INVOKE_METHOD_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(INVOKE_METHOD_METHOD_NAME);
 			int typeIndex = literalIndex(INVOKE_METHOD_METHOD_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[INVOKE_METHOD_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[INVOKE_METHOD_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[INVOKE_METHOD_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[INVOKE_METHOD_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -1330,17 +1330,17 @@
 	int nameAndTypeIndex;
 	int classIndex;
 	// Looking into the method ref table
-	if ((index = wellKnownMethods[SHORTVALUE_SHORT_METHOD]) == 0) {
+	if ((index = this.wellKnownMethods[SHORTVALUE_SHORT_METHOD]) == 0) {
 		classIndex = literalIndexForJavaLangShort();
-		if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[SHORTVALUE_SHORT_METHOD_NAME_AND_TYPE]) == 0) {
+		if ((nameAndTypeIndex = this.wellKnownMethodNameAndTypes[SHORTVALUE_SHORT_METHOD_NAME_AND_TYPE]) == 0) {
 			int nameIndex = literalIndex(SHORTVALUE_SHORT_METHOD_NAME);
 			int typeIndex = literalIndex(SHORTVALUE_SHORT_METHOD_SIGNATURE);
-			nameAndTypeIndex = wellKnownMethodNameAndTypes[SHORTVALUE_SHORT_METHOD_NAME_AND_TYPE] = currentIndex++;
+			nameAndTypeIndex = this.wellKnownMethodNameAndTypes[SHORTVALUE_SHORT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 			writeU1(NameAndTypeTag);
 			writeU2(nameIndex);
 			writeU2(typeIndex);
 		}
-		index = wellKnownMethods[SHORTVALUE_SHORT_METHOD] = currentIndex++;
+		index = this.wellKnownMethods[SHORTVALUE_SHORT_METHOD] = this.currentIndex++;
 		// Write the method ref constant into the constant pool
 		// First add the tag
 		writeU1(MethodRefTag);
@@ -1366,16 +1366,16 @@
 	if ((indexOfWellKnownMethodNameAndType = super.indexOfWellKnownMethodNameAndType(key)) == -1) {
 		if ((indexOfWellKnownMethodNameAndType = indexOfWellKnownMethodNameAndType(key)) == -1) {
 			// check if the entry exists
-			if ((index = nameAndTypeCacheForMethods.get(key)) == -1) {
+			if ((index = this.nameAndTypeCacheForMethods.get(key)) == -1) {
 				// The entry doesn't exit yet
-				index = nameAndTypeCacheForMethods.put(key, currentIndex++);
+				index = this.nameAndTypeCacheForMethods.put(key, this.currentIndex++);
 				writeU1(NameAndTypeTag);
 				writeU2(nameIndex);
 				writeU2(typeIndex);
 			}
 		} else {
-			if ((index = wellKnownMethodNameAndTypes[indexOfWellKnownMethodNameAndType]) == 0) {
-				index = wellKnownMethodNameAndTypes[indexOfWellKnownMethodNameAndType] = currentIndex++;
+			if ((index = this.wellKnownMethodNameAndTypes[indexOfWellKnownMethodNameAndType]) == 0) {
+				index = this.wellKnownMethodNameAndTypes[indexOfWellKnownMethodNameAndType] = this.currentIndex++;
 				writeU1(NameAndTypeTag);
 				writeU2(nameIndex);
 				writeU2(typeIndex);
@@ -1399,20 +1399,20 @@
 	int classIndex = 0;
 	switch (typeID) {
 		case T_int :
-			if ((index = wellKnownMethods[GET_INT_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[GET_INT_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[GET_INT_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[GET_INT_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(GET_INT_METHOD_NAME);
 					int typeIndex = literalIndex(GET_INT_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[GET_INT_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[GET_INT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[GET_INT_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[GET_INT_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1423,20 +1423,20 @@
 			}
 			break;
 		case T_byte :
-			if ((index = wellKnownMethods[GET_BYTE_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[GET_BYTE_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[GET_BYTE_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[GET_BYTE_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(GET_BYTE_METHOD_NAME);
 					int typeIndex = literalIndex(GET_BYTE_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[GET_BYTE_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[GET_BYTE_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[GET_BYTE_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[GET_BYTE_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1447,20 +1447,20 @@
 			}
 			break;
 		case T_short :
-			if ((index = wellKnownMethods[GET_SHORT_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[GET_SHORT_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[GET_SHORT_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[GET_SHORT_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(GET_SHORT_METHOD_NAME);
 					int typeIndex = literalIndex(GET_SHORT_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[GET_SHORT_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[GET_SHORT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[GET_SHORT_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[GET_SHORT_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1471,20 +1471,20 @@
 			}
 			break;
 		case T_long :
-			if ((index = wellKnownMethods[GET_LONG_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[GET_LONG_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[GET_LONG_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[GET_LONG_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(GET_LONG_METHOD_NAME);
 					int typeIndex = literalIndex(GET_LONG_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[GET_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[GET_LONG_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[GET_LONG_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[GET_LONG_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1495,20 +1495,20 @@
 			}
 			break;
 		case T_float :
-			if ((index = wellKnownMethods[GET_FLOAT_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[GET_FLOAT_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[GET_FLOAT_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[GET_FLOAT_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(GET_FLOAT_METHOD_NAME);
 					int typeIndex = literalIndex(GET_FLOAT_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[GET_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[GET_FLOAT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[GET_FLOAT_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[GET_FLOAT_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1519,21 +1519,21 @@
 			}
 			break;
 		case T_double :
-			if ((index = wellKnownMethods[GET_DOUBLE_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[GET_DOUBLE_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[GET_DOUBLE_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[GET_DOUBLE_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(GET_DOUBLE_METHOD_NAME);
 					int typeIndex = literalIndex(GET_DOUBLE_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[GET_DOUBLE_METHOD_NAME_AND_TYPE] =
-							currentIndex++;
+						this.wellKnownMethodNameAndTypes[GET_DOUBLE_METHOD_NAME_AND_TYPE] =
+							this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[GET_DOUBLE_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[GET_DOUBLE_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1544,20 +1544,20 @@
 			}
 			break;
 		case T_char :
-			if ((index = wellKnownMethods[GET_CHAR_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[GET_CHAR_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[GET_CHAR_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[GET_CHAR_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(GET_CHAR_METHOD_NAME);
 					int typeIndex = literalIndex(GET_CHAR_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[GET_CHAR_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[GET_CHAR_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[GET_CHAR_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[GET_CHAR_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1568,21 +1568,21 @@
 			}
 			break;
 		case T_boolean :
-			if ((index = wellKnownMethods[GET_BOOLEAN_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[GET_BOOLEAN_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[GET_BOOLEAN_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[GET_BOOLEAN_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(GET_BOOLEAN_METHOD_NAME);
 					int typeIndex = literalIndex(GET_BOOLEAN_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[GET_BOOLEAN_METHOD_NAME_AND_TYPE] =
-							currentIndex++;
+						this.wellKnownMethodNameAndTypes[GET_BOOLEAN_METHOD_NAME_AND_TYPE] =
+							this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[GET_BOOLEAN_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[GET_BOOLEAN_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1593,21 +1593,21 @@
 			}
 			break;
 		default :
-			if ((index = wellKnownMethods[GET_OBJECT_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[GET_OBJECT_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[GET_OBJECT_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[GET_OBJECT_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(GET_OBJECT_METHOD_NAME);
 					int typeIndex = literalIndex(GET_OBJECT_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[GET_OBJECT_METHOD_NAME_AND_TYPE] =
-							currentIndex++;
+						this.wellKnownMethodNameAndTypes[GET_OBJECT_METHOD_NAME_AND_TYPE] =
+							this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[GET_OBJECT_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[GET_OBJECT_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1632,20 +1632,20 @@
 	int classIndex = 0;
 	switch (typeID) {
 		case T_int :
-			if ((index = wellKnownMethods[SET_INT_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[SET_INT_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[SET_INT_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[SET_INT_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(SET_INT_METHOD_NAME);
 					int typeIndex = literalIndex(SET_INT_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[SET_INT_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[SET_INT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[SET_INT_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[SET_INT_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1656,20 +1656,20 @@
 			}
 			break;
 		case T_byte :
-			if ((index = wellKnownMethods[SET_BYTE_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[SET_BYTE_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[SET_BYTE_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[SET_BYTE_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(SET_BYTE_METHOD_NAME);
 					int typeIndex = literalIndex(SET_BYTE_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[SET_BYTE_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[SET_BYTE_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[SET_BYTE_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[SET_BYTE_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1680,20 +1680,20 @@
 			}
 			break;
 		case T_short :
-			if ((index = wellKnownMethods[SET_SHORT_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[SET_SHORT_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[SET_SHORT_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[SET_SHORT_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(SET_SHORT_METHOD_NAME);
 					int typeIndex = literalIndex(SET_SHORT_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[SET_SHORT_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[SET_SHORT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[SET_SHORT_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[SET_SHORT_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1704,20 +1704,20 @@
 			}
 			break;
 		case T_long :
-			if ((index = wellKnownMethods[SET_LONG_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[SET_LONG_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[SET_LONG_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[SET_LONG_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(SET_LONG_METHOD_NAME);
 					int typeIndex = literalIndex(SET_LONG_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[SET_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[SET_LONG_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[SET_LONG_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[SET_LONG_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1728,20 +1728,20 @@
 			}
 			break;
 		case T_float :
-			if ((index = wellKnownMethods[SET_FLOAT_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[SET_FLOAT_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[SET_FLOAT_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[SET_FLOAT_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(SET_FLOAT_METHOD_NAME);
 					int typeIndex = literalIndex(SET_FLOAT_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[SET_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[SET_FLOAT_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[SET_FLOAT_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[SET_FLOAT_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1752,21 +1752,21 @@
 			}
 			break;
 		case T_double :
-			if ((index = wellKnownMethods[SET_DOUBLE_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[SET_DOUBLE_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[SET_DOUBLE_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[SET_DOUBLE_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(SET_DOUBLE_METHOD_NAME);
 					int typeIndex = literalIndex(SET_DOUBLE_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[SET_DOUBLE_METHOD_NAME_AND_TYPE] =
-							currentIndex++;
+						this.wellKnownMethodNameAndTypes[SET_DOUBLE_METHOD_NAME_AND_TYPE] =
+							this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[SET_DOUBLE_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[SET_DOUBLE_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1777,20 +1777,20 @@
 			}
 			break;
 		case T_char :
-			if ((index = wellKnownMethods[SET_CHAR_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[SET_CHAR_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[SET_CHAR_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[SET_CHAR_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(SET_CHAR_METHOD_NAME);
 					int typeIndex = literalIndex(SET_CHAR_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[SET_CHAR_METHOD_NAME_AND_TYPE] = currentIndex++;
+						this.wellKnownMethodNameAndTypes[SET_CHAR_METHOD_NAME_AND_TYPE] = this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[SET_CHAR_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[SET_CHAR_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1801,21 +1801,21 @@
 			}
 			break;
 		case T_boolean :
-			if ((index = wellKnownMethods[SET_BOOLEAN_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[SET_BOOLEAN_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[SET_BOOLEAN_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[SET_BOOLEAN_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(SET_BOOLEAN_METHOD_NAME);
 					int typeIndex = literalIndex(SET_BOOLEAN_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[SET_BOOLEAN_METHOD_NAME_AND_TYPE] =
-							currentIndex++;
+						this.wellKnownMethodNameAndTypes[SET_BOOLEAN_METHOD_NAME_AND_TYPE] =
+							this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[SET_BOOLEAN_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[SET_BOOLEAN_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
@@ -1826,21 +1826,21 @@
 			}
 			break;
 		default :
-			if ((index = wellKnownMethods[SET_OBJECT_METHOD]) == 0) {
+			if ((index = this.wellKnownMethods[SET_OBJECT_METHOD]) == 0) {
 				classIndex = literalIndexForJavaLangReflectField();
 				if ((nameAndTypeIndex =
-					wellKnownMethodNameAndTypes[SET_OBJECT_METHOD_NAME_AND_TYPE])
+					this.wellKnownMethodNameAndTypes[SET_OBJECT_METHOD_NAME_AND_TYPE])
 					== 0) {
 					int nameIndex = literalIndex(SET_OBJECT_METHOD_NAME);
 					int typeIndex = literalIndex(SET_OBJECT_METHOD_SIGNATURE);
 					nameAndTypeIndex =
-						wellKnownMethodNameAndTypes[SET_OBJECT_METHOD_NAME_AND_TYPE] =
-							currentIndex++;
+						this.wellKnownMethodNameAndTypes[SET_OBJECT_METHOD_NAME_AND_TYPE] =
+							this.currentIndex++;
 					writeU1(NameAndTypeTag);
 					writeU2(nameIndex);
 					writeU2(typeIndex);
 				}
-				index = wellKnownMethods[SET_OBJECT_METHOD] = currentIndex++;
+				index = this.wellKnownMethods[SET_OBJECT_METHOD] = this.currentIndex++;
 				// Write the method ref constant into the constant pool
 				// First add the tag
 				writeU1(MethodRefTag);
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEvaluator.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEvaluator.java
index 2050d71..4ec7eaa 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEvaluator.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetEvaluator.java
@@ -33,7 +33,7 @@
 	 * Whether the code snippet support classes should be found in the provided name environment
 	 * or on disk.
 	 */
-	final static boolean DEVELOPMENT_MODE = false;
+	static final boolean DEVELOPMENT_MODE = false;
 
 	/**
 	 * The code snippet to evaluate.
@@ -55,9 +55,9 @@
  * @see org.eclipse.jdt.internal.eval.Evaluator
  */
 protected void addEvaluationResultForCompilationProblem(Map resultsByIDs, IProblem problem, char[] cuSource) {
-	CodeSnippetToCuMapper mapper = getMapper();
+	CodeSnippetToCuMapper sourceMapper = getMapper();
 	int pbLineNumber = problem.getSourceLineNumber();
-	int evaluationType = mapper.getEvaluationType(pbLineNumber);
+	int evaluationType = sourceMapper.getEvaluationType(pbLineNumber);
 
 	char[] evaluationID = null;
 	switch(evaluationType) {
@@ -71,7 +71,7 @@
 			break;
 			
 		case EvaluationResult.T_IMPORT:
-			evaluationID = mapper.getImport(pbLineNumber);
+			evaluationID = sourceMapper.getImport(pbLineNumber);
 
 			// shift line number, source start and source end
 			problem.setSourceLineNumber(1);
@@ -109,7 +109,7 @@
 /**
  * @see Evaluator.
  */
-Compiler getCompiler(ICompilerRequestor requestor) {
+Compiler getCompiler(ICompilerRequestor compilerRequestor) {
 	Compiler compiler = null;
 	if (!DEVELOPMENT_MODE) {
 		// If we are not developping the code snippet support classes,
@@ -121,11 +121,11 @@
 				this.environment, 
 				DefaultErrorHandlingPolicies.exitAfterAllProblems(), 
 				this.options, 
-				requestor, 
+				compilerRequestor, 
 				this.problemFactory,
 				this.context,
 				getMapper().startPosOffset,
-				getMapper().startPosOffset + codeSnippet.length - 1);
+				getMapper().startPosOffset + this.codeSnippet.length - 1);
 		// Initialize the compiler's lookup environment with the already compiled super classes
 		IBinaryType binary = this.context.getRootCodeSnippetBinary();
 		if (binary != null) {
@@ -153,7 +153,7 @@
 			getWrapperEnvironment(), 
 			DefaultErrorHandlingPolicies.exitAfterAllProblems(), 
 			this.options, 
-			requestor, 
+			compilerRequestor, 
 			this.problemFactory);
 	}
 	return compiler;
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java
index bf9179e..bbac4e3 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java
@@ -15,8 +15,9 @@
 import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.FieldReference;
 import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding;
@@ -39,13 +40,13 @@
 }
 public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
 
-	if (this.codegenBinding.canBeSeenBy(receiverType, this, currentScope)) {
-		receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic());
+	if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
+		this.receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic());
 		assignment.expression.generateCode(currentScope, codeStream, true);
 		fieldStore(codeStream, this.codegenBinding, null, valueRequired);
 	} else {
 		((CodeSnippetCodeStream) codeStream).generateEmulationForField(this.codegenBinding);
-		receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic());
+		this.receiver.generateCode(currentScope, codeStream, !this.codegenBinding.isStatic());
 		if (this.codegenBinding.isStatic()) { // need a receiver?
 			codeStream.aconst_null();
 		}
@@ -73,19 +74,19 @@
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 
 	int pc = codeStream.position;
-	if (constant != NotAConstant) {
+	if (this.constant != NotAConstant) {
 		if (valueRequired) {
-			codeStream.generateConstant(constant, implicitConversion);
+			codeStream.generateConstant(this.constant, this.implicitConversion);
 		}
 	} else {
 		boolean isStatic = this.codegenBinding.isStatic();
-		receiver.generateCode(currentScope, codeStream, !isStatic);
+		this.receiver.generateCode(currentScope, codeStream, !isStatic);
 		if (valueRequired) {
 			if (this.codegenBinding.constant == NotAConstant) {
 				if (this.codegenBinding.declaringClass == null) { // array length
 					codeStream.arraylength();
 				} else {
-					if (this.codegenBinding.canBeSeenBy(receiverType, this, currentScope)) {
+					if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
 						if (isStatic) {
 							codeStream.getstatic(this.codegenBinding);
 						} else {
@@ -99,13 +100,13 @@
 						((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.codegenBinding);
 					}
 				}
-				codeStream.generateImplicitConversion(implicitConversion);
+				codeStream.generateImplicitConversion(this.implicitConversion);
 			} else {
 				if (!isStatic) {
 					codeStream.invokeObjectGetClass(); // perform null check
 					codeStream.pop();
 				}
-				codeStream.generateConstant(this.codegenBinding.constant, implicitConversion);
+				codeStream.generateConstant(this.codegenBinding.constant, this.implicitConversion);
 			}
 		} else {
 			if (!isStatic){
@@ -120,8 +121,8 @@
 public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
 	
 	boolean isStatic;
-	if (this.codegenBinding.canBeSeenBy(receiverType, this, currentScope)) {
-		receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
+	if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
+		this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
 		if (isStatic) {
 			codeStream.getstatic(this.codegenBinding);
 		} else {
@@ -129,14 +130,14 @@
 			codeStream.getfield(this.codegenBinding);
 		}
 		int operationTypeID;
-		if ((operationTypeID = implicitConversion >> 4) == T_String) {
+		if ((operationTypeID = this.implicitConversion >> 4) == T_String) {
 			codeStream.generateStringAppend(currentScope, null, expression);
 		} else {
 			// promote the array reference to the suitable operation type
-			codeStream.generateImplicitConversion(implicitConversion);
+			codeStream.generateImplicitConversion(this.implicitConversion);
 			// generate the increment value (will by itself  be promoted to the operation value)
 			if (expression == IntLiteral.One){ // prefix operation
-				codeStream.generateConstant(expression.constant, implicitConversion);			
+				codeStream.generateConstant(expression.constant, this.implicitConversion);			
 			} else {
 				expression.generateCode(currentScope, codeStream, true);
 			}		
@@ -147,7 +148,7 @@
 		}
 		fieldStore(codeStream, this.codegenBinding, null, valueRequired);
 	} else {
-		receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
+		this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
 		if (isStatic) {
 			// used to store the value
 			((CodeSnippetCodeStream) codeStream).generateEmulationForField(this.codegenBinding);
@@ -158,8 +159,8 @@
 			((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.codegenBinding);
 		} else {
 			// used to store the value
-			((CodeSnippetCodeStream) codeStream).generateEmulationForField(binding);
-			receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
+			((CodeSnippetCodeStream) codeStream).generateEmulationForField(this.binding);
+			this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
 
 			// used to retrieve the actual value
 			codeStream.dup();
@@ -167,14 +168,14 @@
 							
 		}
 		int operationTypeID;
-		if ((operationTypeID = implicitConversion >> 4) == T_String) {
+		if ((operationTypeID = this.implicitConversion >> 4) == T_String) {
 			codeStream.generateStringAppend(currentScope, null, expression);
 		} else {
 			// promote the array reference to the suitable operation type
-			codeStream.generateImplicitConversion(implicitConversion);
+			codeStream.generateImplicitConversion(this.implicitConversion);
 			// generate the increment value (will by itself  be promoted to the operation value)
 			if (expression == IntLiteral.One){ // prefix operation
-				codeStream.generateConstant(expression.constant, implicitConversion);			
+				codeStream.generateConstant(expression.constant, this.implicitConversion);			
 			} else {
 				expression.generateCode(currentScope, codeStream, true);
 			}		
@@ -199,8 +200,8 @@
 }
 public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
 	boolean isStatic;
-	if (this.codegenBinding.canBeSeenBy(receiverType, this, currentScope)) {
-		receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
+	if (this.codegenBinding.canBeSeenBy(this.receiverType, this, currentScope)) {
+		this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
 		if (isStatic) {
 			codeStream.getstatic(this.codegenBinding);
 		} else {
@@ -222,12 +223,12 @@
 				}
 			}
 		}
-		codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
+		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
 		codeStream.sendOperator(postIncrement.operator, this.codegenBinding.type.id);
 		codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
 		fieldStore(codeStream, this.codegenBinding, null, false);
 	} else {
-		receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
+		this.receiver.generateCode(currentScope, codeStream, !(isStatic = this.codegenBinding.isStatic()));
 		if (this.codegenBinding.isStatic()) {
 			codeStream.aconst_null();
 		}
@@ -270,7 +271,7 @@
 		}
 		codeStream.pop2();
 
-		codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
+		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
 		codeStream.sendOperator(postIncrement.operator, this.codegenBinding.type.id);
 		codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
 		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(this.codegenBinding);
@@ -279,39 +280,63 @@
 /*
  * No need to emulate access to protected fields since not implicitly accessed
  */
-public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope){
+public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){
 	// The private access will be managed through the code generation
 
+	if (!flowInfo.isReachable()) return;
+	
 	// if the binding declaring class is not visible, need special action
 	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
 	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-	if (binding.declaringClass != this.receiverType
+	if (this.delegateThis != null) {
+		if (this.binding.declaringClass != this.delegateThis.type
+			&& this.binding.declaringClass != null
+			&& this.binding.constant == NotAConstant
+			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
+					&& !this.binding.isStatic()
+					&& this.binding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
+				|| !this.binding.declaringClass.canBeSeenBy(currentScope))){
+			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(this.binding, (ReferenceBinding)this.delegateThis.type);
+		}
+	} else if (this.binding.declaringClass != this.receiverType
 		&& !this.receiverType.isArrayType()
-		&& binding.declaringClass != null // array.length
-		&& binding.constant == NotAConstant
-		&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
-				&& binding.declaringClass.id != T_Object) //no change for Object fields (in case there was)
-			|| !binding.declaringClass.canBeSeenBy(currentScope))){
-			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(binding, (ReferenceBinding) this.receiverType);
+		&& this.binding.declaringClass != null // array.length
+		&& this.binding.constant == NotAConstant
+		&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
+				&& this.binding.declaringClass.id != T_Object) //no change for Object fields (in case there was)
+			|| !this.binding.declaringClass.canBeSeenBy(currentScope))){
+			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(this.binding, (ReferenceBinding) this.receiverType);
 	}
 }
 /*
  * No need to emulate access to protected fields since not implicitly accessed
  */
-public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope){
+public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){
 	// The private access will be managed through the code generation
 
+	if (!flowInfo.isReachable()) return;
+	
 	// if the binding declaring class is not visible, need special action
 	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
 	// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-	if (binding.declaringClass != this.receiverType
+	if (this.delegateThis != null) {
+		if (this.binding.declaringClass != this.delegateThis.type
+			&& this.binding.declaringClass != null
+			&& this.binding.constant == NotAConstant
+			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
+					&& !this.binding.isStatic()
+					&& this.binding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
+				|| !this.binding.declaringClass.canBeSeenBy(currentScope))){
+			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(this.binding, (ReferenceBinding)this.delegateThis.type);
+		}
+	} else if (this.binding.declaringClass != this.receiverType
 		&& !this.receiverType.isArrayType()
-		&& binding.declaringClass != null // array.length
-		&& binding.constant == NotAConstant
-		&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
-				&& binding.declaringClass.id != T_Object) //no change for Object fields (in case there was)
-			|| !binding.declaringClass.canBeSeenBy(currentScope))){
-			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(binding, (ReferenceBinding) this.receiverType);
+		&& this.binding.declaringClass != null // array.length
+		&& this.binding.constant == NotAConstant
+		&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
+				&& this.binding.declaringClass.id != T_Object) //no change for Object fields (in case there was)
+			|| !this.binding.declaringClass.canBeSeenBy(currentScope))){
+			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(this.binding, (ReferenceBinding) this.receiverType);
 	}
 }
 public TypeBinding resolveType(BlockScope scope) {
@@ -320,53 +345,53 @@
 	// and initialized with a (compile time) constant 
 
 	// regular receiver reference 
-	receiverType = receiver.resolveType(scope);
-	if (receiverType == null){
-		constant = NotAConstant;
+	this.receiverType = this.receiver.resolveType(scope);
+	if (this.receiverType == null){
+		this.constant = NotAConstant;
 		return null;
 	}
 	// the case receiverType.isArrayType and token = 'length' is handled by the scope API
-	this.codegenBinding = this.binding = scope.getField(receiverType, token, this);
-	FieldBinding firstAttempt = binding;
+	this.codegenBinding = this.binding = scope.getField(this.receiverType, this.token, this);
+	FieldBinding firstAttempt = this.binding;
 	boolean isNotVisible = false;
-	if (!binding.isValidBinding()) {
-		if (binding instanceof ProblemFieldBinding
-			&& ((ProblemFieldBinding) binding).problemId() == NotVisible) {
+	if (!this.binding.isValidBinding()) {
+		if (this.binding instanceof ProblemFieldBinding
+			&& ((ProblemFieldBinding) this.binding).problemId() == NotVisible) {
 				isNotVisible = true;
 				if (this.evaluationContext.declaringTypeName != null) {
-					delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
-					if (delegateThis == null){ ; // if not found then internal error, field should have been found
-						constant = NotAConstant;
-						scope.problemReporter().invalidField(this, receiverType);
+					this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
+					if (this.delegateThis == null){  // if not found then internal error, field should have been found
+						this.constant = NotAConstant;
+						scope.problemReporter().invalidField(this, this.receiverType);
 						return null;
 					}
 				} else {
-					constant = NotAConstant;
-					scope.problemReporter().invalidField(this, receiverType);
+					this.constant = NotAConstant;
+					scope.problemReporter().invalidField(this, this.receiverType);
 					return null;
 				}
 			CodeSnippetScope localScope = new CodeSnippetScope(scope);
-			this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(delegateThis.type, token, this);
+			this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this);
 		}
 	}
 
-	if (!binding.isValidBinding()) {
-		constant = NotAConstant;
+	if (!this.binding.isValidBinding()) {
+		this.constant = NotAConstant;
 		if (isNotVisible) {
 			this.codegenBinding = this.binding = firstAttempt;
 		}
-		scope.problemReporter().invalidField(this, receiverType);
+		scope.problemReporter().invalidField(this, this.receiverType);
 		return null;
 	}
 
-	if (isFieldUseDeprecated(binding, scope))
-		scope.problemReporter().deprecatedField(binding, this);
-
+	if (isFieldUseDeprecated(this.binding, scope, (this.bits & IsStrictlyAssignedMASK) !=0)) {
+		scope.problemReporter().deprecatedField(this.binding, this);
+	}
 	// check for this.x in static is done in the resolution of the receiver
-	constant = FieldReference.getConstantFor(binding, this, receiver.isImplicitThis(), scope);
-	if (!receiver.isThis())
-		constant = NotAConstant;
-
-	return this.resolvedType = binding.type;
+	this.constant = FieldReference.getConstantFor(this.binding, this, this.receiver.isImplicitThis(), scope);
+	if (!this.receiver.isThis()) {
+		this.constant = NotAConstant;
+	}
+	return this.resolvedType = this.binding.type;
 }
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java
index c4cf367..641b0a1 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java
@@ -12,8 +12,9 @@
 
 import org.eclipse.jdt.internal.compiler.ast.MessageSend;
 import org.eclipse.jdt.internal.compiler.ast.NameReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
 import org.eclipse.jdt.internal.compiler.lookup.BindingIds;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -23,6 +24,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 
 public class CodeSnippetMessageSend extends MessageSend implements ProblemReasons, EvaluationConstants {
 	EvaluationContext evaluationContext;
@@ -47,13 +49,13 @@
 
 	int pc = codeStream.position;
 
-	if (binding.canBeSeenBy(receiverType, this, currentScope)) {
+	if (this.binding.canBeSeenBy(this.receiverType, this, currentScope)) {
 		// generate receiver/enclosing instance access
-		boolean isStatic = binding.isStatic();
+		boolean isStatic = this.binding.isStatic();
 		// outer access ?
-		if (!isStatic && ((bits & DepthMASK) != 0)) {
+		if (!isStatic && ((this.bits & DepthMASK) != 0)) {
 			// outer method can be reached through emulation
-			ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+			ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
 			Object[] path = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
 			if (path == null) {
 				// emulation was not possible (should not happen per construction)
@@ -62,55 +64,55 @@
 				codeStream.generateOuterAccess(path, this, targetType, currentScope);
 			}
 		} else {
-			receiver.generateCode(currentScope, codeStream, !isStatic);
+			this.receiver.generateCode(currentScope, codeStream, !isStatic);
 		}
 		// generate arguments
-		if (arguments != null) {
-			for (int i = 0, max = arguments.length; i < max; i++) {
-				arguments[i].generateCode(currentScope, codeStream, true);
+		if (this.arguments != null) {
+			for (int i = 0, max = this.arguments.length; i < max; i++) {
+				this.arguments[i].generateCode(currentScope, codeStream, true);
 			}
 		}
 		// actual message invocation
 		if (isStatic) {
-			codeStream.invokestatic(binding);
+			codeStream.invokestatic(this.binding);
 		} else {
-			if (receiver.isSuper()) {
-				codeStream.invokespecial(binding);
+			if (this.receiver.isSuper()) {
+				codeStream.invokespecial(this.binding);
 			} else {
-				if (binding.declaringClass.isInterface()) {
-					codeStream.invokeinterface(binding);
+				if (this.binding.declaringClass.isInterface()) {
+					codeStream.invokeinterface(this.binding);
 				} else {
-					codeStream.invokevirtual(binding);
+					codeStream.invokevirtual(this.binding);
 				}
 			}
 		}
 	} else {
-		((CodeSnippetCodeStream) codeStream).generateEmulationForMethod(currentScope, binding);
+		((CodeSnippetCodeStream) codeStream).generateEmulationForMethod(currentScope, this.binding);
 		// generate receiver/enclosing instance access
-		boolean isStatic = binding.isStatic();
+		boolean isStatic = this.binding.isStatic();
 		// outer access ?
-		if (!isStatic && ((bits & DepthMASK) != 0)) {
+		if (!isStatic && ((this.bits & DepthMASK) != 0)) {
 			// not supported yet
 			currentScope.problemReporter().needImplementation();
 		} else {
-			receiver.generateCode(currentScope, codeStream, !isStatic);
+			this.receiver.generateCode(currentScope, codeStream, !isStatic);
 		}
 		if (isStatic) {
 			// we need an object on the stack which is ignored for the method invocation
 			codeStream.aconst_null();
 		}
 		// generate arguments
-		if (arguments != null) {
-			int argsLength = arguments.length;
+		if (this.arguments != null) {
+			int argsLength = this.arguments.length;
 			codeStream.generateInlinedValue(argsLength);
-			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeBinding.JAVA_LANG_OBJECT), 1));
+			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT), 1));
 			codeStream.dup();
 			for (int i = 0; i < argsLength; i++) {
 				codeStream.generateInlinedValue(i);
-				arguments[i].generateCode(currentScope, codeStream, true);
-				TypeBinding parameterBinding = binding.parameters[i];
+				this.arguments[i].generateCode(currentScope, codeStream, true);
+				TypeBinding parameterBinding = this.binding.parameters[i];
 				if (parameterBinding.isBaseType() && parameterBinding != NullBinding) {
-					((CodeSnippetCodeStream)codeStream).generateObjectWrapperForType(binding.parameters[i]);
+					((CodeSnippetCodeStream)codeStream).generateObjectWrapperForType(this.binding.parameters[i]);
 				}
 				codeStream.aastore();
 				if (i < argsLength - 1) {
@@ -119,13 +121,13 @@
 			}
 		} else {
 			codeStream.generateInlinedValue(0);
-			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeBinding.JAVA_LANG_OBJECT), 1));			
+			codeStream.newArray(currentScope, new ArrayBinding(currentScope.getType(TypeConstants.JAVA_LANG_OBJECT), 1));			
 		}
 		((CodeSnippetCodeStream) codeStream).invokeJavaLangReflectMethodInvoke();
 
 		// convert the return value to the appropriate type for primitive types
-		if (binding.returnType.isBaseType()) {
-			int typeID = binding.returnType.id;
+		if (this.binding.returnType.isBaseType()) {
+			int typeID = this.binding.returnType.id;
 			if (typeID == T_void) {
 				// remove the null from the stack
 				codeStream.pop();
@@ -133,16 +135,16 @@
 			((CodeSnippetCodeStream) codeStream).checkcast(typeID);
 			((CodeSnippetCodeStream) codeStream).getBaseTypeValue(typeID);
 		} else {
-			codeStream.checkcast(binding.returnType);
+			codeStream.checkcast(this.binding.returnType);
 		}
 	}
 	// operation on the returned value
 	if (valueRequired) {
 		// implicit conversion if necessary
-		codeStream.generateImplicitConversion(implicitConversion);
+		codeStream.generateImplicitConversion(this.implicitConversion);
 	} else {
 		// pop return value if any
-		switch (binding.returnType.id) {
+		switch (this.binding.returnType.id) {
 			case T_long :
 			case T_double :
 				codeStream.pop2();
@@ -155,125 +157,125 @@
 	}
 	codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
-public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
-}
-public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
+public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
 
+	if (!flowInfo.isReachable()) return;
+	
 	// if the binding declaring class is not visible, need special action
 	// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
 	// NOTE: from target 1.2 on, method's declaring class is touched if any different from receiver type
 	// and not from Object or implicit static method call.	
-	if (binding.declaringClass != this.qualifyingType
+	if (this.binding.declaringClass != this.qualifyingType
 		&& !this.qualifyingType.isArrayType()
-		&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
-				&& (!receiver.isImplicitThis() || !binding.isStatic())
-				&& binding.declaringClass.id != T_Object) // no change for Object methods
-			|| !binding.declaringClass.canBeSeenBy(currentScope))) {
-		codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(binding, (ReferenceBinding) this.qualifyingType);
+		&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
+				&& (!this.receiver.isImplicitThis() || !this.binding.isStatic())
+				&& this.binding.declaringClass.id != T_Object) // no change for Object methods
+			|| !this.binding.declaringClass.canBeSeenBy(currentScope))) {
+		this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(this.binding, (ReferenceBinding) this.qualifyingType);
 	}	
 }
 public TypeBinding resolveType(BlockScope scope) {
 	// Answer the signature return type
 	// Base type promotion
 
-	constant = NotAConstant;
-	this.qualifyingType = this.receiverType = receiver.resolveType(scope); 
+	this.constant = NotAConstant;
+	this.qualifyingType = this.receiverType = this.receiver.resolveType(scope); 
 	// will check for null after args are resolved
 	TypeBinding[] argumentTypes = NoParameters;
-	if (arguments != null) {
+	if (this.arguments != null) {
 		boolean argHasError = false; // typeChecks all arguments 
-		int length = arguments.length;
+		int length = this.arguments.length;
 		argumentTypes = new TypeBinding[length];
 		for (int i = 0; i < length; i++)
-			if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
+			if ((argumentTypes[i] = this.arguments[i].resolveType(scope)) == null)
 				argHasError = true;
 		if (argHasError)
 			return null;
 	}
-	if (receiverType == null) 
+	if (this.receiverType == null) 
 		return null;
 
 	// base type cannot receive any message
-	if (receiverType.isBaseType()) {
-		scope.problemReporter().errorNoMethodFor(this, receiverType, argumentTypes);
+	if (this.receiverType.isBaseType()) {
+		scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
 		return null;
 	}
 
-	binding = 
-		receiver.isImplicitThis()
-			? scope.getImplicitMethod(selector, argumentTypes, this)
-			: scope.getMethod(receiverType, selector, argumentTypes, this); 
-	if (!binding.isValidBinding()) {
-		if (binding instanceof ProblemMethodBinding
-			&& ((ProblemMethodBinding) binding).problemId() == NotVisible) {
+	this.binding = 
+		this.receiver.isImplicitThis()
+			? scope.getImplicitMethod(this.selector, argumentTypes, this)
+			: scope.getMethod(this.receiverType, this.selector, argumentTypes, this); 
+	if (!this.binding.isValidBinding()) {
+		if (this.binding instanceof ProblemMethodBinding
+			&& ((ProblemMethodBinding) this.binding).problemId() == NotVisible) {
 			if (this.evaluationContext.declaringTypeName != null) {
-				delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
-				if (delegateThis == null){ ; // if not found then internal error, field should have been found
-					constant = NotAConstant;
-					scope.problemReporter().invalidMethod(this, binding);
+				this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
+				if (this.delegateThis == null){ // if not found then internal error, field should have been found
+					this.constant = NotAConstant;
+					scope.problemReporter().invalidMethod(this, this.binding);
 					return null;
 				}
 			} else {
-				constant = NotAConstant;
-				scope.problemReporter().invalidMethod(this, binding);
+				this.constant = NotAConstant;
+				scope.problemReporter().invalidMethod(this, this.binding);
 				return null;
 			}
 			CodeSnippetScope localScope = new CodeSnippetScope(scope);			
 			MethodBinding privateBinding = 
-				receiver instanceof CodeSnippetThisReference && ((CodeSnippetThisReference) receiver).isImplicit
-					? localScope.getImplicitMethod((ReferenceBinding)delegateThis.type, selector, argumentTypes, this)
-					: localScope.getMethod(delegateThis.type, selector, argumentTypes, this); 
+				this.receiver instanceof CodeSnippetThisReference && ((CodeSnippetThisReference) this.receiver).isImplicit
+					? localScope.getImplicitMethod((ReferenceBinding)this.delegateThis.type, this.selector, argumentTypes, this)
+					: localScope.getMethod(this.delegateThis.type, this.selector, argumentTypes, this); 
 			if (!privateBinding.isValidBinding()) {
-				if (binding.declaringClass == null) {
-					if (receiverType instanceof ReferenceBinding) {
-						binding.declaringClass = (ReferenceBinding) receiverType;
+				if (this.binding.declaringClass == null) {
+					if (this.receiverType instanceof ReferenceBinding) {
+						this.binding.declaringClass = (ReferenceBinding) this.receiverType;
 					} else { // really bad error ....
-						scope.problemReporter().errorNoMethodFor(this, receiverType, argumentTypes);
+						scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
 						return null;
 					}
 				}
-				scope.problemReporter().invalidMethod(this, binding);
+				scope.problemReporter().invalidMethod(this, this.binding);
 				return null;
 			} else {
-				binding = privateBinding;
+				this.binding = privateBinding;
 			}
 		} else {
-			if (binding.declaringClass == null) {
-				if (receiverType instanceof ReferenceBinding) {
-					binding.declaringClass = (ReferenceBinding) receiverType;
+			if (this.binding.declaringClass == null) {
+				if (this.receiverType instanceof ReferenceBinding) {
+					this.binding.declaringClass = (ReferenceBinding) this.receiverType;
 				} else { // really bad error ....
-					scope.problemReporter().errorNoMethodFor(this, receiverType, argumentTypes);
+					scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
 					return null;
 				}
 			}
-			scope.problemReporter().invalidMethod(this, binding);
+			scope.problemReporter().invalidMethod(this, this.binding);
 			return null;
 		}
 	}
-	if (!binding.isStatic()) {
+	if (!this.binding.isStatic()) {
 		// the "receiver" must not be a type, in other words, a NameReference that the TC has bound to a Type
-		if (receiver instanceof NameReference) {
-			if ((((NameReference) receiver).bits & BindingIds.TYPE) != 0) {
-				scope.problemReporter().mustUseAStaticMethod(this, binding);
+		if (this.receiver instanceof NameReference) {
+			if ((((NameReference) this.receiver).bits & BindingIds.TYPE) != 0) {
+				scope.problemReporter().mustUseAStaticMethod(this, this.binding);
 				return null;
 			}
 		}
 	}
-	if (arguments != null)
-		for (int i = 0; i < arguments.length; i++)
-			arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
+	if (this.arguments != null)
+		for (int i = 0; i < this.arguments.length; i++)
+			this.arguments[i].implicitWidening(this.binding.parameters[i], argumentTypes[i]);
 
 	//-------message send that are known to fail at compile time-----------
-	if (binding.isAbstract()) {
-		if (receiver.isSuper()) {
-			scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, binding);
+	if (this.binding.isAbstract()) {
+		if (this.receiver.isSuper()) {
+			scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, this.binding);
 			return null;
 		}
 		// abstract private methods cannot occur nor abstract static............
 	}
-	if (isMethodUseDeprecated(binding, scope))
-		scope.problemReporter().deprecatedMethod(binding, this);
+	if (isMethodUseDeprecated(this.binding, scope))
+		scope.problemReporter().deprecatedMethod(this.binding, this);
 
-	return this.resolvedType = binding.returnType;
+	return this.resolvedType = this.binding.returnType;
 }
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java
index 373a4e8..0570d44 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java
@@ -31,11 +31,13 @@
 /**
  * Creates a new code snippet parser.
  */
-public CodeSnippetParser(ProblemReporter problemReporter, EvaluationContext evaluationContext, boolean optimizeStringLiterals, boolean assertMode, int codeSnippetStart, int codeSnippetEnd) {
-	super(problemReporter, optimizeStringLiterals, assertMode);
+public CodeSnippetParser(ProblemReporter problemReporter, EvaluationContext evaluationContext, boolean optimizeStringLiterals, int codeSnippetStart, int codeSnippetEnd) {
+	super(problemReporter, optimizeStringLiterals);
 	this.codeSnippetStart = codeSnippetStart;
 	this.codeSnippetEnd = codeSnippetEnd;
 	this.evaluationContext = evaluationContext;
+	this.reportOnlyOneSyntaxError = true;
+	this.javadocParser.checkJavadoc = false;
 }
 protected void classInstanceCreation(boolean alwaysQualified) {
 	// ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
@@ -45,22 +47,22 @@
 
 	AllocationExpression alloc;
 	int length;
-	if (((length = astLengthStack[astLengthPtr--]) == 1)
-		&& (astStack[astPtr] == null)) {
+	if (((length = this.astLengthStack[this.astLengthPtr--]) == 1)
+		&& (this.astStack[this.astPtr] == null)) {
 		//NO ClassBody
-		astPtr--;
+		this.astPtr--;
 		if (alwaysQualified) {
 			alloc = new QualifiedAllocationExpression();
 		} else {
-			alloc = new CodeSnippetAllocationExpression(evaluationContext);
+			alloc = new CodeSnippetAllocationExpression(this.evaluationContext);
 		}
-		alloc.sourceEnd = endPosition; //the position has been stored explicitly
+		alloc.sourceEnd = this.endPosition; //the position has been stored explicitly
 
-		if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
-			expressionPtr -= length;
+		if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+			this.expressionPtr -= length;
 			System.arraycopy(
-				expressionStack, 
-				expressionPtr + 1, 
+				this.expressionStack, 
+				this.expressionPtr + 1, 
 				alloc.arguments = new Expression[length], 
 				0, 
 				length); 
@@ -68,17 +70,17 @@
 		alloc.type = getTypeReference(0);
 		//the default constructor with the correct number of argument
 		//will be created and added by the TC (see createsInternalConstructorWithBinding)
-		alloc.sourceStart = intStack[intPtr--];
+		alloc.sourceStart = this.intStack[this.intPtr--];
 		pushOnExpressionStack(alloc);
 	} else {
 		dispatchDeclarationInto(length);
-		AnonymousLocalTypeDeclaration anonymousTypeDeclaration = (AnonymousLocalTypeDeclaration) astStack[astPtr];
-		anonymousTypeDeclaration.declarationSourceEnd = endStatementPosition;
+		TypeDeclaration anonymousTypeDeclaration = (TypeDeclaration) this.astStack[this.astPtr];
+		anonymousTypeDeclaration.declarationSourceEnd = this.endStatementPosition;
 		if (anonymousTypeDeclaration.allocation != null) {
-			anonymousTypeDeclaration.allocation.sourceEnd = endStatementPosition;
+			anonymousTypeDeclaration.allocation.sourceEnd = this.endStatementPosition;
 		}		
-		astPtr--;
-		astLengthPtr--;
+		this.astPtr--;
+		this.astLengthPtr--;
 
 		// mark initializers with local type mark if needed
 		markInitializersWithLocalType(anonymousTypeDeclaration);
@@ -92,45 +94,50 @@
 protected void consumeClassHeaderName() {
 	// ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
 	TypeDeclaration typeDecl;
-	if (nestedMethod[nestedType] == 0) {
-		if (nestedType != 0) {
-			typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
+	if (this.nestedMethod[this.nestedType] == 0) {
+		if (this.nestedType != 0) {
+			typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+			typeDecl.bits |= ASTNode.IsMemberTypeMASK;
 		} else {
 			typeDecl = new CodeSnippetTypeDeclaration(this.compilationUnit.compilationResult);
 		}
 	} else {
 		// Record that the block has a declaration for local types
-		typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+		typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+		typeDecl.bits |= ASTNode.IsLocalTypeMASK;
 		markEnclosingMemberWithLocalType();
 		blockReal();
 	}
 
 	//highlight the name of the type
-	long pos = identifierPositionStack[identifierPtr];
+	long pos = this.identifierPositionStack[this.identifierPtr];
 	typeDecl.sourceEnd = (int) pos;
 	typeDecl.sourceStart = (int) (pos >>> 32);
-	typeDecl.name = identifierStack[identifierPtr--];
-	identifierLengthPtr--;
+	typeDecl.name = this.identifierStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
 
 	//compute the declaration source too
-	typeDecl.declarationSourceStart = intStack[intPtr--]; 
-	intPtr--;
+	typeDecl.declarationSourceStart = this.intStack[this.intPtr--]; 
+	this.intPtr--;
 	// 'class' and 'interface' push an int position
-	typeDecl.modifiersSourceStart = intStack[intPtr--];
-	typeDecl.modifiers = intStack[intPtr--];
+	typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
+	typeDecl.modifiers = this.intStack[this.intPtr--];
 	if (typeDecl.modifiersSourceStart >= 0) {
 		typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
 	}
 	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
 	pushOnAstStack(typeDecl);
 
-	listLength = 0; // will be updated when reading super-interfaces
+	this.listLength = 0; // will be updated when reading super-interfaces
 	// recovery
-	if (currentElement != null){ 
-		lastCheckPoint = typeDecl.bodyStart;
-		currentElement = currentElement.add(typeDecl, 0);
-		lastIgnoredToken = -1;
+	if (this.currentElement != null){ 
+		this.lastCheckPoint = typeDecl.bodyStart;
+		this.currentElement = this.currentElement.add(typeDecl, 0);
+		this.lastIgnoredToken = -1;
 	}
+	// javadoc
+	typeDecl.javadoc = this.javadoc;
+	this.javadoc = null;
 }
 protected void consumeEmptyStatement() {
 	super.consumeEmptyStatement();
@@ -148,66 +155,71 @@
 
 	FieldReference fr =
 		new CodeSnippetFieldReference(
-			identifierStack[identifierPtr],
-			identifierPositionStack[identifierPtr--],
-			evaluationContext);
-	identifierLengthPtr--;
+			this.identifierStack[this.identifierPtr],
+			this.identifierPositionStack[this.identifierPtr--],
+			this.evaluationContext);
+	this.identifierLengthPtr--;
 	if (isSuperAccess) {
 		//considerates the fieldReference beginning at the 'super' ....	
-		fr.sourceStart = intStack[intPtr--];
+		fr.sourceStart = this.intStack[this.intPtr--];
 		problemReporter().codeSnippetMissingClass(null,0, 0);
-		fr.receiver = new CodeSnippetSuperReference(fr.sourceStart, endPosition, evaluationContext);
+		fr.receiver = new CodeSnippetSuperReference(fr.sourceStart, this.endPosition, this.evaluationContext);
 		pushOnExpressionStack(fr);
 	} else {
 		//optimize push/pop
-		if ((fr.receiver = expressionStack[expressionPtr]).isThis()) {
+		if ((fr.receiver = this.expressionStack[this.expressionPtr]).isThis()) {
 			//fieldreference begins at the this
 			fr.sourceStart = fr.receiver.sourceStart;
 		}
-		expressionStack[expressionPtr] = fr;
+		this.expressionStack[this.expressionPtr] = fr;
 	}
 }
 protected void consumeInterfaceHeaderName() {
 	// InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
 	TypeDeclaration typeDecl;
-	if (nestedMethod[nestedType] == 0) {
-		if (nestedType != 0) {
-			typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
+	if (this.nestedMethod[this.nestedType] == 0) {
+		if (this.nestedType != 0) {
+			typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+			typeDecl.bits |= ASTNode.IsMemberTypeMASK;
 		} else {
 			typeDecl = new CodeSnippetTypeDeclaration(this.compilationUnit.compilationResult);
 		}
 	} else {
 		// Record that the block has a declaration for local types
-		typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+		typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+		typeDecl.bits |= ASTNode.IsLocalTypeMASK;
 		markEnclosingMemberWithLocalType(); 
 		blockReal();
 	}
 
 	//highlight the name of the type
-	long pos = identifierPositionStack[identifierPtr];
+	long pos = this.identifierPositionStack[this.identifierPtr];
 	typeDecl.sourceEnd = (int) pos;
 	typeDecl.sourceStart = (int) (pos >>> 32);
-	typeDecl.name = identifierStack[identifierPtr--];
-	identifierLengthPtr--;
+	typeDecl.name = this.identifierStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
 
 	//compute the declaration source too
-	typeDecl.declarationSourceStart = intStack[intPtr--];
-	intPtr--;
+	typeDecl.declarationSourceStart = this.intStack[this.intPtr--];
+	this.intPtr--;
 	// 'class' and 'interface' push an int position
-	typeDecl.modifiersSourceStart = intStack[intPtr--];
-	typeDecl.modifiers = intStack[intPtr--];
+	typeDecl.modifiersSourceStart = this.intStack[this.intPtr--];
+	typeDecl.modifiers = this.intStack[this.intPtr--];
 	if (typeDecl.modifiersSourceStart >= 0) {
 		typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
 	}
 	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
 	pushOnAstStack(typeDecl);
-	listLength = 0; // will be updated when reading super-interfaces
+	this.listLength = 0; // will be updated when reading super-interfaces
 	// recovery
-	if (currentElement != null){ // is recovering
-		lastCheckPoint = typeDecl.bodyStart;
-		currentElement = currentElement.add(typeDecl, 0);
-		lastIgnoredToken = -1;		
+	if (this.currentElement != null){ // is recovering
+		this.lastCheckPoint = typeDecl.bodyStart;
+		this.currentElement = this.currentElement.add(typeDecl, 0);
+		this.lastIgnoredToken = -1;		
 	}
+	// javadoc
+	typeDecl.javadoc = this.javadoc;
+	this.javadoc = null;
 }
 protected void consumeLocalVariableDeclarationStatement() {
 	super.consumeLocalVariableDeclarationStatement();
@@ -227,7 +239,7 @@
 	super.consumeMethodDeclaration(isNotAbstract);
 	
 	// now we know that we have a method declaration at the top of the ast stack
-	MethodDeclaration methodDecl = (MethodDeclaration) astStack[astPtr];
+	MethodDeclaration methodDecl = (MethodDeclaration) this.astStack[this.astPtr];
 
 	// automatically wrap the last statement inside a return statement, if it is an expression
 	// support have to be defined at toplevel only
@@ -238,8 +250,7 @@
 			methodDecl.statements[last] = new CodeSnippetReturnStatement(
 											lastExpression, 
 											lastExpression.sourceStart, 
-											lastExpression.sourceEnd,
-											evaluationContext);
+											lastExpression.sourceEnd);
 		}
 	}
 	
@@ -255,10 +266,13 @@
 		for (int i = 0; i < varCount; i++){
 			char[] trimmedTypeName = this.evaluationContext.localVariableTypeNames[i];
 			int nameEnd = CharOperation.indexOf('[', trimmedTypeName);
-			if (nameEnd >= 0) trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd);
+			if (nameEnd >= 0) {
+				trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd);
+			}
 			nameEnd = CharOperation.indexOf(' ', trimmedTypeName);
-			if (nameEnd >= 0) trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd);
-			
+			if (nameEnd >= 0) {
+				trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd);
+			}
 			TypeReference typeReference = new QualifiedTypeReference(
 				CharOperation.splitOn('.', trimmedTypeName),
 				positions);
@@ -268,7 +282,8 @@
 			}
 			NameReference init = new SingleNameReference(
 									CharOperation.concat(LOCAL_VAR_PREFIX, this.evaluationContext.localVariableNames[i]), position);
-			LocalDeclaration declaration = new LocalDeclaration(init, this.evaluationContext.localVariableNames[i], start, end);
+			LocalDeclaration declaration = new LocalDeclaration(this.evaluationContext.localVariableNames[i], start, end);
+			declaration.initialization = init;
 			declaration.type = typeReference;
 			declaration.modifiers = this.evaluationContext.localVariableModifiers[i];
 			newStatements[i] = declaration;
@@ -303,22 +318,22 @@
 protected void consumeMethodInvocationName() {
 	// MethodInvocation ::= Name '(' ArgumentListopt ')'
 
-	if (scanner.startPosition >= this.codeSnippetStart
-		&& scanner.startPosition <= this.codeSnippetEnd + 1 + Util.LINE_SEPARATOR_CHARS.length // 14838
+	if (this.scanner.startPosition >= this.codeSnippetStart
+		&& this.scanner.startPosition <= this.codeSnippetEnd + 1 + Util.LINE_SEPARATOR_CHARS.length // 14838
 		&& isTopLevelType()) {
 			
 		// when the name is only an identifier...we have a message send to "this" (implicit)
 
 		MessageSend m = newMessageSend();
-		m.sourceEnd = rParenPos;
+		m.sourceEnd = this.rParenPos;
 		m.sourceStart = 
-			(int) ((m.nameSourcePosition = identifierPositionStack[identifierPtr]) >>> 32); 
-		m.selector = identifierStack[identifierPtr--];
-		if (identifierLengthStack[identifierLengthPtr] == 1) {
-			m.receiver = new CodeSnippetThisReference(0,0,evaluationContext, true);
-			identifierLengthPtr--;
+			(int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32); 
+		m.selector = this.identifierStack[this.identifierPtr--];
+		if (this.identifierLengthStack[this.identifierLengthPtr] == 1) {
+			m.receiver = new CodeSnippetThisReference(0,0,this.evaluationContext, true);
+			this.identifierLengthPtr--;
 		} else {
-			identifierLengthStack[identifierLengthPtr]--;
+			this.identifierLengthStack[this.identifierLengthPtr]--;
 			m.receiver = getUnspecifiedReference();
 			m.sourceStart = m.receiver.sourceStart;		
 		}
@@ -332,23 +347,23 @@
 	// MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
 
 	MessageSend m = newMessageSend();
-	m.sourceStart = intStack[intPtr--];
-	m.sourceEnd = rParenPos;
-	m.nameSourcePosition = identifierPositionStack[identifierPtr];
-	m.selector = identifierStack[identifierPtr--];
-	identifierLengthPtr--;
-	m.receiver = new CodeSnippetSuperReference(m.sourceStart, endPosition, this.evaluationContext);
+	m.sourceStart = this.intStack[this.intPtr--];
+	m.sourceEnd = this.rParenPos;
+	m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr];
+	m.selector = this.identifierStack[this.identifierPtr--];
+	this.identifierLengthPtr--;
+	m.receiver = new CodeSnippetSuperReference(m.sourceStart, this.endPosition, this.evaluationContext);
 	pushOnExpressionStack(m);
 }
 
 protected void consumePrimaryNoNewArrayThis() {
 	// PrimaryNoNewArray ::= 'this'
 
-	if (scanner.startPosition >= this.codeSnippetStart
-		&& scanner.startPosition <= this.codeSnippetEnd + 1 + Util.LINE_SEPARATOR_CHARS.length // 14838
+	if (this.scanner.startPosition >= this.codeSnippetStart
+		&& this.scanner.startPosition <= this.codeSnippetEnd + 1 + Util.LINE_SEPARATOR_CHARS.length // 14838
 		&& isTopLevelType()) {
 		pushOnExpressionStack(
-			new CodeSnippetThisReference(intStack[intPtr--], endPosition, this.evaluationContext, false));
+			new CodeSnippetThisReference(this.intStack[this.intPtr--], this.endPosition, this.evaluationContext, false));
 	} else {
 		super.consumePrimaryNoNewArrayThis();
 	}
@@ -409,7 +424,7 @@
 	// returned value intercepted by code snippet 
 	// support have to be defined at toplevel only
 	if ((this.hasRecoveredOnExpression
-			|| (scanner.startPosition >= codeSnippetStart && scanner.startPosition <= codeSnippetEnd+1+Util.LINE_SEPARATOR_CHARS.length /* 14838*/))
+			|| (this.scanner.startPosition >= this.codeSnippetStart && this.scanner.startPosition <= this.codeSnippetEnd+1+Util.LINE_SEPARATOR_CHARS.length /* 14838*/))
 		&& this.expressionLengthStack[this.expressionLengthPtr] != 0
 		&& isTopLevelType()) {
 		this.expressionLengthPtr--;
@@ -418,8 +433,7 @@
 			new CodeSnippetReturnStatement(
 				expression, 
 				expression.sourceStart, 
-				expression.sourceEnd,
-				evaluationContext));
+				expression.sourceEnd));
 	} else {
 		super.consumeStatementReturn();
 	}
@@ -532,29 +546,31 @@
 protected NameReference getUnspecifiedReference() {
 	/* build a (unspecified) NameReference which may be qualified*/
 
-	if (scanner.startPosition >= codeSnippetStart 
-		&& scanner.startPosition <= codeSnippetEnd+1+Util.LINE_SEPARATOR_CHARS.length /*14838*/){
+	if (this.scanner.startPosition >= this.codeSnippetStart 
+		&& this.scanner.startPosition <= this.codeSnippetEnd+1+Util.LINE_SEPARATOR_CHARS.length /*14838*/){
 		int length;
 		NameReference ref;
-		if ((length = identifierLengthStack[identifierLengthPtr--]) == 1)
+		if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
 			// single variable reference
 			ref = 
 				new CodeSnippetSingleNameReference(
-					identifierStack[identifierPtr], 
-					identifierPositionStack[identifierPtr--],
+					this.identifierStack[this.identifierPtr], 
+					this.identifierPositionStack[this.identifierPtr--],
 					this.evaluationContext); 
-		else
+		} else {
 			//Qualified variable reference
-			{
 			char[][] tokens = new char[length][];
-			identifierPtr -= length;
-			System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+			this.identifierPtr -= length;
+			System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+			long[] positions = new long[length];
+			System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
 			ref = 
-				new CodeSnippetQualifiedNameReference(tokens, 
-					(int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
-					(int) identifierPositionStack[identifierPtr + length],
-					evaluationContext); // sourceEnd
-		};
+				new CodeSnippetQualifiedNameReference(tokens,
+					positions, 
+					(int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
+					(int) this.identifierPositionStack[this.identifierPtr + length],
+					this.evaluationContext); // sourceEnd
+		}
 		return ref;
 	} else {
 		return super.getUnspecifiedReference();
@@ -568,18 +584,18 @@
 	that when a NameReference is build, the type checker should always
 	look for that it is not a type reference */
 
-	if (scanner.startPosition >= codeSnippetStart 
-		&& scanner.startPosition <= codeSnippetEnd+1+Util.LINE_SEPARATOR_CHARS.length /*14838*/){
+	if (this.scanner.startPosition >= this.codeSnippetStart 
+		&& this.scanner.startPosition <= this.codeSnippetEnd+1+Util.LINE_SEPARATOR_CHARS.length /*14838*/){
 		int length;
 		NameReference ref;
-		if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+		if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
 			// single variable reference
 			ref = 
 				new CodeSnippetSingleNameReference(
-					identifierStack[identifierPtr], 
-					identifierPositionStack[identifierPtr--],
+					this.identifierStack[this.identifierPtr], 
+					this.identifierPositionStack[this.identifierPtr--],
 					this.evaluationContext); 
-			ref.bits &= ~AstNode.RestrictiveFlagMASK;
+			ref.bits &= ~ASTNode.RestrictiveFlagMASK;
 			ref.bits |= LOCAL | FIELD;
 			return ref;
 		}
@@ -591,14 +607,17 @@
 		//or else..........This optimisation is not really relevant so just leave as it is
 
 		char[][] tokens = new char[length][];
-		identifierPtr -= length;
-		System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+		this.identifierPtr -= length;
+		System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+		long[] positions = new long[length];
+		System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
 		ref = new CodeSnippetQualifiedNameReference(
-				tokens, 
-				(int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
-				(int) identifierPositionStack[identifierPtr + length],
-				evaluationContext); // sourceEnd
-		ref.bits &= ~AstNode.RestrictiveFlagMASK;
+				tokens,
+				positions, 
+				(int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
+				(int) this.identifierPositionStack[this.identifierPtr + length],
+				this.evaluationContext); // sourceEnd
+		ref.bits &= ~ASTNode.RestrictiveFlagMASK;
 		ref.bits |= LOCAL | FIELD;
 		return ref;
 	} else {
@@ -620,17 +639,17 @@
 	// '(' ArgumentListopt ')'
 	// the arguments are on the expression stack
 
-	CodeSnippetMessageSend m = new CodeSnippetMessageSend(evaluationContext);
+	CodeSnippetMessageSend m = new CodeSnippetMessageSend(this.evaluationContext);
 	int length;
-	if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
-		expressionPtr -= length;
+	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+		this.expressionPtr -= length;
 		System.arraycopy(
-			expressionStack, 
-			expressionPtr + 1, 
+			this.expressionStack, 
+			this.expressionPtr + 1, 
 			m.arguments = new Expression[length], 
 			0, 
 			length); 
-	};
+	}
 	return m;
 }
 /**
@@ -641,20 +660,22 @@
 		this.lastStatement = this.scanner.startPosition;
 	}
 }
-protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
-	if (!this.diet) {
-		this.scanner.initialPosition = this.codeSnippetStart; // for correct bracket match diagnosis
+protected void reportSyntaxErrors(boolean isDietParse, int oldFirstToken) {
+	if (!isDietParse) {
+		this.scanner.initialPosition = this.lastStatement;
 		this.scanner.eofPosition = this.codeSnippetEnd + 1; // stop after expression 
+		oldFirstToken = TokenNameTWIDDLE;//TokenNameREMAINDER; // first token of th expression parse
 	}
-	super.reportSyntaxError(act, currentKind, stateStackTop);
+	super.reportSyntaxErrors(isDietParse, oldFirstToken);
 }
+
 /*
  * A syntax error was detected. If a method is being parsed, records the number of errors and
  * attempts to restart from the last statement by going for an expression.
  */
 protected boolean resumeOnSyntaxError() {
 	if (this.diet || this.hasRecoveredOnExpression) { // no reentering inside expression recovery
-		return super.resumeOnSyntaxError();
+		return false;
 	}
 	
 	// record previous error, in case more accurate than potential one in expression recovery
@@ -676,10 +697,11 @@
 	this.identifierPtr = -1;
 	this.identifierLengthPtr = -1;
 
-	// go for the exprssion
+	// go for the expression
 	goForExpression();
 	this.hasRecoveredOnExpression = true;
 	this.hasReportedError = false;
+	this.hasError = false;
 	return true;
 }
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java
index f632b71..699151a 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java
@@ -16,8 +16,9 @@
 import org.eclipse.jdt.internal.compiler.ast.FieldReference;
 import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
@@ -42,8 +43,8 @@
  * @param sourceStart int
  * @param sourceEnd int
  */
-public CodeSnippetQualifiedNameReference(char[][] sources, int sourceStart, int sourceEnd, EvaluationContext evaluationContext) {
-	super(sources, sourceStart, sourceEnd);
+public CodeSnippetQualifiedNameReference(char[][] sources, long[] positions, int sourceStart, int sourceEnd, EvaluationContext evaluationContext) {
+	super(sources, positions, sourceStart, sourceEnd);
 	this.evaluationContext = evaluationContext;	
 }
 /**
@@ -51,29 +52,29 @@
  */
 public TypeBinding checkFieldAccess(BlockScope scope) {
 	// check for forward references
-	bits &= ~RestrictiveFlagMASK; // clear bits
-	bits |= FIELD;
+	this.bits &= ~RestrictiveFlagMASK; // clear bits
+	this.bits |= FIELD;
 	return getOtherFieldBindings(scope);
 }
 public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
 
 	generateReadSequence(currentScope, codeStream);
-	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+	if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
 		// the last field access is a write access
 		assignment.expression.generateCode(currentScope, codeStream, true);
-		fieldStore(codeStream, lastFieldBinding, null, valueRequired);
+		fieldStore(codeStream, this.lastFieldBinding, null, valueRequired);
 	} else {
-		((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
+		((CodeSnippetCodeStream) codeStream).generateEmulationForField(this.lastFieldBinding);
 		codeStream.swap();
 		assignment.expression.generateCode(currentScope, codeStream, true);
 		if (valueRequired) {
-			if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
+			if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
 				codeStream.dup2_x2();
 			} else {
 				codeStream.dup_x2();
 			}
 		}
-		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(lastFieldBinding);	
+		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(this.lastFieldBinding);	
 	}
 	if (valueRequired) {
 		codeStream.generateImplicitConversion(assignment.implicitConversion);
@@ -81,39 +82,39 @@
 }
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 	int pc = codeStream.position;
-	if (constant != NotAConstant) {
+	if (this.constant != NotAConstant) {
 		if (valueRequired) {
-			codeStream.generateConstant(constant, implicitConversion);
+			codeStream.generateConstant(this.constant, this.implicitConversion);
 		}
 	} else {
 		generateReadSequence(currentScope, codeStream); 
 		if (valueRequired) {
-			if (lastFieldBinding.declaringClass == null) { // array length
+			if (this.lastFieldBinding.declaringClass == null) { // array length
 				codeStream.arraylength();
-				codeStream.generateImplicitConversion(implicitConversion);
+				codeStream.generateImplicitConversion(this.implicitConversion);
 			} else {
-				if (lastFieldBinding.constant != NotAConstant) {
-					if (!lastFieldBinding.isStatic()){
+				if (this.lastFieldBinding.constant != NotAConstant) {
+					if (!this.lastFieldBinding.isStatic()){
 						codeStream.invokeObjectGetClass();
 						codeStream.pop();
 					}
 					// inline the last field constant
-					codeStream.generateConstant(lastFieldBinding.constant, implicitConversion);
+					codeStream.generateConstant(this.lastFieldBinding.constant, this.implicitConversion);
 				} else {	
-					if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-						if (lastFieldBinding.isStatic()) {
-							codeStream.getstatic(lastFieldBinding);
+					if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+						if (this.lastFieldBinding.isStatic()) {
+							codeStream.getstatic(this.lastFieldBinding);
 						} else {
-							codeStream.getfield(lastFieldBinding);
+							codeStream.getfield(this.lastFieldBinding);
 						}
 					} else {
-						((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
+						((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.lastFieldBinding);
 					}	
-					codeStream.generateImplicitConversion(implicitConversion);
+					codeStream.generateImplicitConversion(this.implicitConversion);
 				}
 			}
 		} else {
-			if (lastFieldBinding != null && !lastFieldBinding.isStatic()){
+			if (this.lastFieldBinding != null && !this.lastFieldBinding.isStatic()){
 				codeStream.invokeObjectGetClass(); // perform null check
 				codeStream.pop();
 			}
@@ -124,24 +125,24 @@
 public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
 	
 	generateReadSequence(currentScope, codeStream);
-	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-		if (lastFieldBinding.isStatic()){
-			codeStream.getstatic(lastFieldBinding);
+	if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+		if (this.lastFieldBinding.isStatic()){
+			codeStream.getstatic(this.lastFieldBinding);
 		} else {
 			codeStream.dup();
-			codeStream.getfield(lastFieldBinding);
+			codeStream.getfield(this.lastFieldBinding);
 		}
 		// the last field access is a write access
 		// perform the actual compound operation
 		int operationTypeID;
-		if ((operationTypeID = implicitConversion >> 4) == T_String) {
+		if ((operationTypeID = this.implicitConversion >> 4) == T_String) {
 			codeStream.generateStringAppend(currentScope, null, expression);
 		} else {
 			// promote the array reference to the suitable operation type
-			codeStream.generateImplicitConversion(implicitConversion);
+			codeStream.generateImplicitConversion(this.implicitConversion);
 			// generate the increment value (will by itself  be promoted to the operation value)
 			if (expression == IntLiteral.One){ // prefix operation
-				codeStream.generateConstant(expression.constant, implicitConversion);			
+				codeStream.generateConstant(expression.constant, this.implicitConversion);			
 			} else {
 				expression.generateCode(currentScope, codeStream, true);
 			}
@@ -151,33 +152,33 @@
 			codeStream.generateImplicitConversion(assignmentImplicitConversion);
 		}
 		// actual assignment
-		fieldStore(codeStream, lastFieldBinding, null, valueRequired);
+		fieldStore(codeStream, this.lastFieldBinding, null, valueRequired);
 	} else {
-		if (lastFieldBinding.isStatic()){
-			((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
+		if (this.lastFieldBinding.isStatic()){
+			((CodeSnippetCodeStream) codeStream).generateEmulationForField(this.lastFieldBinding);
 			codeStream.swap();
 			codeStream.aconst_null();
 			codeStream.swap();
 
-			((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
+			((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.lastFieldBinding);
 		} else {
-			((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
+			((CodeSnippetCodeStream) codeStream).generateEmulationForField(this.lastFieldBinding);
 			codeStream.swap();
 			codeStream.dup();
 
-			((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
+			((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.lastFieldBinding);
 		}
 		// the last field access is a write access
 		// perform the actual compound operation
 		int operationTypeID;
-		if ((operationTypeID = implicitConversion >> 4) == T_String) {
+		if ((operationTypeID = this.implicitConversion >> 4) == T_String) {
 			codeStream.generateStringAppend(currentScope, null, expression);
 		} else {
 			// promote the array reference to the suitable operation type
-			codeStream.generateImplicitConversion(implicitConversion);
+			codeStream.generateImplicitConversion(this.implicitConversion);
 			// generate the increment value (will by itself  be promoted to the operation value)
 			if (expression == IntLiteral.One){ // prefix operation
-				codeStream.generateConstant(expression.constant, implicitConversion);			
+				codeStream.generateConstant(expression.constant, this.implicitConversion);			
 			} else {
 				expression.generateCode(currentScope, codeStream, true);
 			}
@@ -191,7 +192,7 @@
 		// current stack is:
 		// field receiver value
 		if (valueRequired) {
-			if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
+			if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
 				codeStream.dup2_x2();
 			} else {
 				codeStream.dup_x2();
@@ -199,54 +200,54 @@
 		}
 		// current stack is:
 		// value field receiver value				
-		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(lastFieldBinding);
+		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(this.lastFieldBinding);
 	}
 }
 public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
 	generateReadSequence(currentScope, codeStream);
 
-	if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-		if (lastFieldBinding.isStatic()){
-			codeStream.getstatic(lastFieldBinding);
+	if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+		if (this.lastFieldBinding.isStatic()){
+			codeStream.getstatic(this.lastFieldBinding);
 		} else {
 			codeStream.dup();
-			codeStream.getfield(lastFieldBinding);
+			codeStream.getfield(this.lastFieldBinding);
 		}	
 		// duplicate the old field value
 		if (valueRequired) {
-			if (lastFieldBinding.isStatic()) {
-				if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
+			if (this.lastFieldBinding.isStatic()) {
+				if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
 					codeStream.dup2();
 				} else {
 					codeStream.dup();
 				}
 			} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
-				if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
+				if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
 					codeStream.dup2_x1();
 				} else {
 					codeStream.dup_x1();
 				}
 			}
 		}
-		codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
-		codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
+		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
+		codeStream.sendOperator(postIncrement.operator, this.lastFieldBinding.type.id);
 		codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
 		
-		fieldStore(codeStream, lastFieldBinding, null, false);
+		fieldStore(codeStream, this.lastFieldBinding, null, false);
 	} else {
-		((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
+		((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.lastFieldBinding);
 		if (valueRequired) {
-			if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
+			if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
 				codeStream.dup2();
 			} else {
 				codeStream.dup();
 			}
 		}
-		((CodeSnippetCodeStream) codeStream).generateEmulationForField(lastFieldBinding);
-		if ((lastFieldBinding.type == LongBinding) || (lastFieldBinding.type == DoubleBinding)) {
+		((CodeSnippetCodeStream) codeStream).generateEmulationForField(this.lastFieldBinding);
+		if ((this.lastFieldBinding.type == LongBinding) || (this.lastFieldBinding.type == DoubleBinding)) {
 			codeStream.dup_x2();
 			codeStream.pop();
-			if (lastFieldBinding.isStatic()) {
+			if (this.lastFieldBinding.isStatic()) {
 				codeStream.aconst_null();
 			} else {
 				generateReadSequence(currentScope, codeStream);
@@ -256,7 +257,7 @@
 		} else {
 			codeStream.dup_x1();
 			codeStream.pop();
-			if (lastFieldBinding.isStatic()) {
+			if (this.lastFieldBinding.isStatic()) {
 				codeStream.aconst_null();
 			} else {
 				generateReadSequence(currentScope, codeStream);
@@ -264,10 +265,10 @@
 			codeStream.dup_x1();
 			codeStream.pop();					
 		}
-		codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
-		codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
+		codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
+		codeStream.sendOperator(postIncrement.operator, this.lastFieldBinding.type.id);
 		codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
-		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(lastFieldBinding);
+		((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(this.lastFieldBinding);
 	}
 }
 /*
@@ -276,21 +277,21 @@
  */
 public void generateReadSequence(BlockScope currentScope, CodeStream codeStream) {
 	// determine the rank until which we now we do not need any actual value for the field access
-	int otherBindingsCount = this.otherCodegenBindings == null ? 0 : otherCodegenBindings.length;
+	int otherBindingsCount = this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length;
 
 	boolean needValue = otherBindingsCount == 0 || !this.otherBindings[0].isStatic();
-	switch (bits & RestrictiveFlagMASK) {
+	switch (this.bits & RestrictiveFlagMASK) {
 		case FIELD :
-			lastFieldBinding = (FieldBinding) this.codegenBinding;
+			this.lastFieldBinding = (FieldBinding) this.codegenBinding;
 			// if first field is actually constant, we can inline it
-			if (lastFieldBinding.constant != NotAConstant) {
+			if (this.lastFieldBinding.constant != NotAConstant) {
 				break;
 			}
 			if (needValue) {
-				if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-					if (!lastFieldBinding.isStatic()) {
-						if ((bits & DepthMASK) != 0) {
-							ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+				if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+					if (!this.lastFieldBinding.isStatic()) {
+						if ((this.bits & DepthMASK) != 0) {
+							ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
 							Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
 							if (emulationPath == null) {
 								// internal error, per construction we should have found it
@@ -303,8 +304,8 @@
 						}
 					}
 				} else {
-					if (!lastFieldBinding.isStatic()) {
-						if ((bits & DepthMASK) != 0) {
+					if (!this.lastFieldBinding.isStatic()) {
+						if ((this.bits & DepthMASK) != 0) {
 							// internal error, per construction we should have found it
 							// not yet supported
 							currentScope.problemReporter().needImplementation();
@@ -319,7 +320,7 @@
 			break;
 		case LOCAL : // reading the first local variable
 			if (!needValue) break; // no value needed
-			lastFieldBinding = null;
+			this.lastFieldBinding = null;
 			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 			// regular local variable read
 			if (localBinding.constant != NotAConstant) {
@@ -327,7 +328,7 @@
 				// no implicit conversion
 			} else {
 				// outer local?
-				if ((bits & DepthMASK) != 0) {
+				if ((this.bits & DepthMASK) != 0) {
 					// outer local can be reached either through a synthetic arg or a synthetic field
 					VariableBinding[] path = currentScope.getEmulationPath(localBinding);
 					if (path == null) {
@@ -347,23 +348,23 @@
 	if (this.otherCodegenBindings != null) {
 		for (int i = 0; i < otherBindingsCount; i++) {
 			FieldBinding nextField = this.otherCodegenBindings[i];
-			if (lastFieldBinding != null) {
+			if (this.lastFieldBinding != null) {
 				needValue = !nextField.isStatic();
 				if (needValue) {
-					if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-						if (lastFieldBinding.constant != NotAConstant) {
+					if (this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+						if (this.lastFieldBinding.constant != NotAConstant) {
 							if (this.lastFieldBinding != this.codegenBinding && !this.lastFieldBinding.isStatic()) {
 								codeStream.invokeObjectGetClass(); // perform null check
 								codeStream.pop();
 							}
-							codeStream.generateConstant(lastFieldBinding.constant, 0);
-						} else if (lastFieldBinding.isStatic()) {
-							codeStream.getstatic(lastFieldBinding);
+							codeStream.generateConstant(this.lastFieldBinding.constant, 0);
+						} else if (this.lastFieldBinding.isStatic()) {
+							codeStream.getstatic(this.lastFieldBinding);
 						} else {
-							codeStream.getfield(lastFieldBinding);
+							codeStream.getfield(this.lastFieldBinding);
 						}
 					} else {
-						((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(lastFieldBinding);
+						((CodeSnippetCodeStream) codeStream).generateEmulatedReadAccessForField(this.lastFieldBinding);
 					}
 				} else {
 					if (this.codegenBinding != this.lastFieldBinding && !this.lastFieldBinding.isStatic()){
@@ -373,8 +374,8 @@
 				}
 			}
 			this.lastFieldBinding = nextField;
-			if (lastFieldBinding != null && !lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-				if (lastFieldBinding.isStatic()) {
+			if (this.lastFieldBinding != null && !this.lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+				if (this.lastFieldBinding.isStatic()) {
 					codeStream.aconst_null();
 				}
 			}
@@ -384,33 +385,37 @@
 
 public void generateReceiver(CodeStream codeStream) {
 	codeStream.aload_0();
-	if (delegateThis != null) codeStream.getfield(delegateThis); // delegated field access
+	if (this.delegateThis != null) {
+		codeStream.getfield(this.delegateThis); // delegated field access
+	}
 }
 public TypeBinding getOtherFieldBindings(BlockScope scope) {
 	// At this point restrictiveFlag may ONLY have two potential value : FIELD LOCAL (i.e cast <<(VariableBinding) binding>> is valid)
 
-	if ((bits & FIELD) != 0) {
-		if (!((FieldBinding) binding).isStatic()) { //must check for the static status....
-			if (indexOfFirstFieldBinding == 1) {
+	int length = this.tokens.length;
+	if ((this.bits & FIELD) != 0) {
+		if (!((FieldBinding) this.binding).isStatic()) { //must check for the static status....
+			if (this.indexOfFirstFieldBinding == 1) {
 				//the field is the first token of the qualified reference....
 				if (scope.methodScope().isStatic) {
-					scope.problemReporter().staticFieldAccessToNonStaticVariable(this, (FieldBinding) binding);
+					scope.problemReporter().staticFieldAccessToNonStaticVariable(this, (FieldBinding) this.binding);
 					return null;
 				}
 			} else { //accessing to a field using a type as "receiver" is allowed only with static field	
-				scope.problemReporter().staticFieldAccessToNonStaticVariable(this, (FieldBinding) binding);
+				scope.problemReporter().staticFieldAccessToNonStaticVariable(this, (FieldBinding) this.binding);
 				return null;
 			}
 		}
-		if (isFieldUseDeprecated((FieldBinding) binding, scope))
-			scope.problemReporter().deprecatedField((FieldBinding) binding, this);
+		// only last field is actually a write access if any
+		if (isFieldUseDeprecated((FieldBinding) this.binding, scope, (this.bits & IsStrictlyAssignedMASK) !=0 && this.indexOfFirstFieldBinding == length)) {
+			scope.problemReporter().deprecatedField((FieldBinding) this.binding, this);
+		}
 	}
 
-	TypeBinding type = ((VariableBinding) binding).type;
-	int index = indexOfFirstFieldBinding;
-	int length = tokens.length;
+	TypeBinding type = ((VariableBinding) this.binding).type;
+	int index = this.indexOfFirstFieldBinding;
 	if (index == length) { //	restrictiveFlag == FIELD
-		constant = FieldReference.getConstantFor((FieldBinding) binding, this, false, scope);
+		this.constant = FieldReference.getConstantFor((FieldBinding) this.binding, this, false, scope);
 		return type;
 	}
 
@@ -419,64 +424,66 @@
 	this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength];
 	
 	// fill the first constant (the one of the binding)
-	constant =
-		((bits & FIELD) != 0)
-			? FieldReference.getConstantFor((FieldBinding) binding, this, false, scope)
-			: ((VariableBinding) binding).constant;
+	this.constant =
+		((this.bits & FIELD) != 0)
+			? FieldReference.getConstantFor((FieldBinding) this.binding, this, false, scope)
+			: ((VariableBinding) this.binding).constant;
 
 	// iteration on each field	
 	while (index < length) {
-		char[] token = tokens[index];
+		char[] token = this.tokens[index];
 		if (type == null) return null; // could not resolve type prior to this point
 		FieldBinding field = scope.getField(type, token, this);
-		int place = index - indexOfFirstFieldBinding;
-		otherBindings[place] = field;
+		int place = index - this.indexOfFirstFieldBinding;
+		this.otherBindings[place] = field;
 		if (!field.isValidBinding()) {
 			// try to retrieve the field as private field
 			CodeSnippetScope localScope = new CodeSnippetScope(scope);
-			if (delegateThis == null) {
+			if (this.delegateThis == null) {
 				if (this.evaluationContext.declaringTypeName != null) {
-					delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
-					if (delegateThis == null){ ; // if not found then internal error, field should have been found
+					this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
+					if (this.delegateThis == null){  // if not found then internal error, field should have been found
 						return super.reportError(scope);
 					}
 				} else {
-					constant = NotAConstant; //don't fill other constants slots...
+					this.constant = NotAConstant; //don't fill other constants slots...
 					scope.problemReporter().invalidField(this, field, index, type);
 					return null;
 				}
 			}
-			field = localScope.getFieldForCodeSnippet(delegateThis.type, token, this);
-			otherBindings[place] = field;
+			field = localScope.getFieldForCodeSnippet(this.delegateThis.type, token, this);
+			this.otherBindings[place] = field;
 		}
 		if (field.isValidBinding()) {
-			if (isFieldUseDeprecated(field, scope))
+			// only last field is actually a write access if any
+			if (isFieldUseDeprecated(field, scope, (this.bits & IsStrictlyAssignedMASK) !=0 && index+1 == length)) {
 				scope.problemReporter().deprecatedField(field, this);
+			}
 			Constant someConstant = FieldReference.getConstantFor(field, this, false, scope);
 			// constant propagation can only be performed as long as the previous one is a constant too.
-			if (constant != NotAConstant){
-				constant = someConstant;
+			if (this.constant != NotAConstant){
+				this.constant = someConstant;
 			}
 			type = field.type;
 			index++;
 		} else {
-			constant = NotAConstant; //don't fill other constants slots...
+			this.constant = NotAConstant; //don't fill other constants slots...
 			scope.problemReporter().invalidField(this, field, index, type);
 			return null;
 		}
 	}
-	return (otherBindings[otherBindingsLength - 1]).type;
+	return (this.otherBindings[otherBindingsLength - 1]).type;
 }
 /**
  * Check and/or redirect the field access to the delegate receiver if any
  */
 public TypeBinding getReceiverType(BlockScope currentScope) {
-	if (receiverType != null) return receiverType;
+	if (this.receiverType != null) return this.receiverType;
 	Scope scope = currentScope.parent;
 	while (true) {
 			switch (scope.kind) {
 				case Scope.CLASS_SCOPE :
-					return receiverType = ((ClassScope) scope).referenceContext.binding;
+					return this.receiverType = ((ClassScope) scope).referenceContext.binding;
 				default:
 					scope = scope.parent;
 			}
@@ -487,20 +494,25 @@
 		BlockScope currentScope,
 		FieldBinding fieldBinding,
 		TypeBinding lastReceiverType,
-		int index) {
+		int index,
+		FlowInfo flowInfo) {
+
+		if (!flowInfo.isReachable()) return;
+	
 
 		// if the binding declaring class is not visible, need special action
 		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
 		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
 		boolean useDelegate = index == 0 && this.delegateThis != null;
-		if (useDelegate) lastReceiverType = this.delegateThis.type;
-
+		if (useDelegate) {
+			lastReceiverType = this.delegateThis.type;
+		}
 		if (fieldBinding.declaringClass != lastReceiverType
 			&& !lastReceiverType.isArrayType()			
 			&& fieldBinding.declaringClass != null
 			&& fieldBinding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
-					&& (index > 0 || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
+			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
+					&& (index > 0 || this.indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
 					&& fieldBinding.declaringClass.id != T_Object)
 				|| !(useDelegate
 						? new CodeSnippetScope(currentScope).canBeSeenByForCodeSnippet(fieldBinding.declaringClass, (ReferenceBinding) this.delegateThis.type)
@@ -522,25 +534,29 @@
 	public void manageSyntheticWriteAccessIfNecessary(
 		BlockScope currentScope,
 		FieldBinding fieldBinding,
-		TypeBinding lastReceiverType) {
+		TypeBinding lastReceiverType,
+		FlowInfo flowInfo) {
 
+		if (!flowInfo.isReachable()) return;
+	
 		// if the binding declaring class is not visible, need special action
 		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
 		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
-		boolean useDelegate = fieldBinding == binding && this.delegateThis != null;
-		if (useDelegate) lastReceiverType = this.delegateThis.type;
-
+		boolean useDelegate = fieldBinding == this.binding && this.delegateThis != null;
+		if (useDelegate) {
+			lastReceiverType = this.delegateThis.type;
+		}
 		if (fieldBinding.declaringClass != lastReceiverType
 			&& !lastReceiverType.isArrayType()			
 			&& fieldBinding.declaringClass != null
 			&& fieldBinding.constant == NotAConstant
-			&& ((currentScope.environment().options.targetJDK >= CompilerOptions.JDK1_2
-					&& (fieldBinding != binding || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
+			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
+					&& (fieldBinding != this.binding || this.indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
 					&& fieldBinding.declaringClass.id != T_Object)
 				|| !(useDelegate
 						? new CodeSnippetScope(currentScope).canBeSeenByForCodeSnippet(fieldBinding.declaringClass, (ReferenceBinding) this.delegateThis.type)
 						: fieldBinding.declaringClass.canBeSeenBy(currentScope)))){
-			if (fieldBinding == binding){
+			if (fieldBinding == this.binding){
 				this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
 			} else {
 				if (this.otherCodegenBindings == this.otherBindings){
@@ -558,24 +574,24 @@
 public TypeBinding reportError(BlockScope scope) {
 
 	if (this.evaluationContext.declaringTypeName != null) {
-		delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
-		if (delegateThis == null){ ; // if not found then internal error, field should have been found
+		this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
+		if (this.delegateThis == null){  // if not found then internal error, field should have been found
 			return super.reportError(scope);
 		}
 	} else {
 		return super.reportError(scope);
 	}
 
-	if ((binding instanceof ProblemFieldBinding && ((ProblemFieldBinding) binding).problemId() == NotFound)
-		|| (binding instanceof ProblemBinding && ((ProblemBinding) binding).problemId() == NotFound)){
+	if ((this.binding instanceof ProblemFieldBinding && ((ProblemFieldBinding) this.binding).problemId() == NotFound)
+		|| (this.binding instanceof ProblemBinding && ((ProblemBinding) this.binding).problemId() == NotFound)){
 		// will not support innerclass emulation inside delegate
-		FieldBinding fieldBinding = scope.getField(delegateThis.type, this.tokens[0], this);
+		FieldBinding fieldBinding = scope.getField(this.delegateThis.type, this.tokens[0], this);
 		if (!fieldBinding.isValidBinding()) {
 			if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) {
 				// manage the access to a private field of the enclosing type
 				CodeSnippetScope localScope = new CodeSnippetScope(scope);
-				this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(delegateThis.type, this.tokens[0], this);
-				if (binding.isValidBinding()) {
+				this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.tokens[0], this);
+				if (this.binding.isValidBinding()) {
 					return checkFieldAccess(scope);						
 				} else {
 					return super.reportError(scope);
@@ -584,16 +600,17 @@
 				return super.reportError(scope);
 			}
 		}
-		this.codegenBinding = binding = fieldBinding;
+		this.codegenBinding = this.binding = fieldBinding;
 		return checkFieldAccess(scope);
 	}
 
 	TypeBinding result;
-	if (binding instanceof ProblemFieldBinding
-		&& ((ProblemFieldBinding) binding).problemId() == NotVisible) {
+	if (this.binding instanceof ProblemFieldBinding
+		&& ((ProblemFieldBinding) this.binding).problemId() == NotVisible) {
 		result = resolveTypeVisibility(scope);
-		if (result == null)
+		if (result == null) {
 			return super.reportError(scope);
+		}
 		if (result.isValidBinding()) {
 			return result;
 		}
@@ -608,9 +625,9 @@
 	// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField 
 
 	CodeSnippetScope localScope = new CodeSnippetScope(scope);
-	if ((this.codegenBinding = binding = localScope.getBinding(tokens, bits & RestrictiveFlagMASK, this, (ReferenceBinding) delegateThis.type)).isValidBinding()) {
-		bits &= ~RestrictiveFlagMASK; // clear bits
-		bits |= FIELD;
+	if ((this.codegenBinding = this.binding = localScope.getBinding(this.tokens, this.bits & RestrictiveFlagMASK, this, (ReferenceBinding) this.delegateThis.type)).isValidBinding()) {
+		this.bits &= ~RestrictiveFlagMASK; // clear bits
+		this.bits |= FIELD;
 		return getOtherFieldBindings(scope);
 	}
 	//========error cases===============
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java
index ec9d7fb..0e15f76 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java
@@ -29,7 +29,7 @@
  */
 public class CodeSnippetReturnStatement extends ReturnStatement implements InvocationSite, EvaluationConstants {
 	MethodBinding setResultMethod;
-public CodeSnippetReturnStatement(Expression expr, int s, int e, EvaluationContext evaluationContext) {
+public CodeSnippetReturnStatement(Expression expr, int s, int e) {
 	super(expr, s, e);
 }
 
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java
index e2bcb4b..85ed2a4 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetScope.java
@@ -272,7 +272,7 @@
 			return new ProblemFieldBinding((ReferenceBinding)leafType, fieldName, ReceiverTypeNotVisible);
 		}
 		if (CharOperation.equals(fieldName, LENGTH))
-			return ArrayBinding.LengthField;
+			return ArrayBinding.ArrayLength;
 		return null;
 	}
 
@@ -280,7 +280,7 @@
 	if (!currentType.canBeSeenBy(this))
 		return new ProblemFieldBinding(currentType, fieldName, ReceiverTypeNotVisible);
 
-	FieldBinding field = currentType.getField(fieldName);
+	FieldBinding field = currentType.getField(fieldName, true /*resolve*/);
 	if (field != null) {
 		if (canBeSeenByForCodeSnippet(field, currentType, invocationSite, this))
 			return field;
@@ -306,7 +306,7 @@
 		if ((currentType = currentType.superclass()) == null)
 			break;
 
-		if ((field = currentType.getField(fieldName)) != null) {
+		if ((field = currentType.getField(fieldName, true /*resolve*/)) != null) {
 			keepLooking = false;
 			if (canBeSeenByForCodeSnippet(field, receiverType, invocationSite, this)) {
 				if (visibleField == null)
@@ -328,7 +328,7 @@
 				ReferenceBinding anInterface = interfaces[j];
 				if ((anInterface.tagBits & InterfaceVisited) == 0) { // if interface as not already been visited
 					anInterface.tagBits |= InterfaceVisited;
-					if ((field = anInterface.getField(fieldName)) != null) {
+					if ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) {
 						if (visibleField == null) {
 							visibleField = field;
 						} else {
@@ -538,7 +538,7 @@
 */
 
 public Binding getBinding(char[][] compoundName, int mask, InvocationSite invocationSite, ReferenceBinding receiverType) {
-	Binding binding = getBinding(compoundName[0], mask | TYPE | PACKAGE, invocationSite);
+	Binding binding = getBinding(compoundName[0], mask | TYPE | PACKAGE, invocationSite, true /*resolve*/);
 	invocationSite.setFieldIndex(1);
 	if (!binding.isValidBinding() || binding instanceof VariableBinding)
 		return binding;
@@ -561,7 +561,7 @@
 	 			if (!binding.isValidBinding())
 					return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), binding.problemId());
 	 			if (!this.canBeSeenByForCodeSnippet((ReferenceBinding) binding, receiverType))
-					return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), binding, NotVisible);
+					return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, currentIndex), (ReferenceBinding) binding, NotVisible);
 	 			break foundType;
  			}
  			packageBinding = (PackageBinding) binding;
@@ -612,14 +612,15 @@
 
 public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
 	MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
-	if (methodBinding != null)
-		if (canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this))
+	if (methodBinding != null) {
+		if (canBeSeenByForCodeSnippet(methodBinding, receiverType, invocationSite, this)) {
 			return methodBinding;
-
+		}
+	}
 	MethodBinding[] methods = receiverType.getMethods(ConstructorDeclaration.ConstantPoolName);
-	if (methods == NoMethods)
+	if (methods == NoMethods) {
 		return new ProblemMethodBinding(ConstructorDeclaration.ConstantPoolName, argumentTypes, NotFound);
-
+	}
 	MethodBinding[] compatible = new MethodBinding[methods.length];
 	int compatibleIndex = 0;
 	for (int i = 0, length = methods.length; i < length; i++)
@@ -632,13 +633,16 @@
 	int visibleIndex = 0;
 	for (int i = 0; i < compatibleIndex; i++) {
 		MethodBinding method = compatible[i];
-		if (canBeSeenByForCodeSnippet(method, receiverType, invocationSite, this))
+		if (canBeSeenByForCodeSnippet(method, receiverType, invocationSite, this)) {
 			visible[visibleIndex++] = method;
+		}
 	}
-	if (visibleIndex == 1)
+	if (visibleIndex == 1) {
 		return visible[0];
-	if (visibleIndex == 0)
+	}
+	if (visibleIndex == 0) {
 		return new ProblemMethodBinding(ConstructorDeclaration.ConstantPoolName, compatible[0].parameters, NotVisible);
+	}
 	return mostSpecificClassMethodBinding(visible, visibleIndex);
 }
 /* API
@@ -716,7 +720,6 @@
 					fuzzyProblem = new ProblemMethodBinding(selector, argumentTypes, methodBinding.declaringClass, NotVisible);
 				}
 			}
-			//TODO: (philippe) should set closest match
 			if (fuzzyProblem == null && !methodBinding.isStatic()) {
 				if (insideConstructorCall) {
 					insideProblem = new ProblemMethodBinding(methodBinding.selector, methodBinding.parameters, NonStaticReferenceInConstructorInvocation);
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
index aa89b5c..6fcc67f 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
@@ -17,6 +17,7 @@
 import org.eclipse.jdt.internal.compiler.ast.FieldReference;
 import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
 import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
@@ -50,11 +51,11 @@
 }
 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
 
-	switch (bits & RestrictiveFlagMASK) {
+	switch (this.bits & RestrictiveFlagMASK) {
 		case FIELD : // reading a field
 			// check if reading a final blank field
 			FieldBinding fieldBinding;
-			if ((fieldBinding = (FieldBinding) binding).isBlankFinal() 
+			if ((fieldBinding = (FieldBinding) this.binding).isBlankFinal() 
 					&& currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
 				if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
 					currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
@@ -63,7 +64,7 @@
 			break;
 		case LOCAL : // reading a local variable
 			LocalVariableBinding localBinding;
-			if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
+			if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) this.binding)) {
 				currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
 			}
 			if (flowInfo.isReachable()) {
@@ -79,25 +80,27 @@
  */
 public TypeBinding checkFieldAccess(BlockScope scope) {
 
-	if (delegateThis == null) return super.checkFieldAccess(scope);
-	
-	FieldBinding fieldBinding = (FieldBinding) binding;
-	bits &= ~RestrictiveFlagMASK; // clear bits
-	bits |= FIELD;
+	if (this.delegateThis == null) {
+		return super.checkFieldAccess(scope);
+	}
+	FieldBinding fieldBinding = (FieldBinding) this.binding;
+	this.bits &= ~RestrictiveFlagMASK; // clear bits
+	this.bits |= FIELD;
 	if (!fieldBinding.isStatic()) {
 		// must check for the static status....
 		if (this.evaluationContext.isStatic) {
 			scope.problemReporter().staticFieldAccessToNonStaticVariable(
 				this,
 				fieldBinding);
-			constant = NotAConstant;
+			this.constant = NotAConstant;
 			return null;
 		}
 	}
-	constant = FieldReference.getConstantFor(fieldBinding, this, true, scope);
-	if (isFieldUseDeprecated(fieldBinding, scope))
-		scope.problemReporter().deprecatedField(fieldBinding, this);
+	this.constant = FieldReference.getConstantFor(fieldBinding, this, true, scope);
 
+	if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssignedMASK) !=0)) {
+		scope.problemReporter().deprecatedField(fieldBinding, this);
+	}
 	return fieldBinding.type;
 
 }
@@ -107,30 +110,30 @@
 	if (assignment.expression.isCompactableOperation()) {
 		BinaryExpression operation = (BinaryExpression) assignment.expression;
 		SingleNameReference variableReference;
-		if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == binding)) {
+		if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == this.binding)) {
 			// i = i + value, then use the variable on the right hand side, since it has the correct implicit conversion
-			variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.right, (operation.bits & OperatorMASK) >> OperatorSHIFT, operation.left.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
+			variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], operation.right, (operation.bits & OperatorMASK) >> OperatorSHIFT, operation.left.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
 			return;
 		}
 		int operator = (operation.bits & OperatorMASK) >> OperatorSHIFT;
 		if ((operation.right instanceof SingleNameReference)
 			&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
-			&& ((variableReference = (SingleNameReference) operation.right).binding == binding)
+			&& ((variableReference = (SingleNameReference) operation.right).binding == this.binding)
 			&& (operation.left.constant != NotAConstant) // exclude non constant expressions, since could have side-effect
 			&& ((operation.left.implicitConversion >> 4) != T_String) // exclude string concatenation which would occur backwards
 			&& ((operation.right.implicitConversion >> 4) != T_String)) { // exclude string concatenation which would occur backwards
 			// i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
-			variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.left, operator, operation.right.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
+			variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[WRITE], operation.left, operator, operation.right.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
 			return;
 		}
 	}
-	switch (bits & RestrictiveFlagMASK) {
+	switch (this.bits & RestrictiveFlagMASK) {
 		case FIELD : // assigning to a field
 			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
 			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
 				if (!fieldBinding.isStatic()) { // need a receiver?
-					if ((bits & DepthMASK) != 0) {
-						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+					if ((this.bits & DepthMASK) != 0) {
+						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
 						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
 						codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
 					} else {
@@ -145,7 +148,7 @@
 			} else {
 				((CodeSnippetCodeStream) codeStream).generateEmulationForField(fieldBinding);
 				if (!fieldBinding.isStatic()) { // need a receiver?
-					if ((bits & DepthMASK) != 0) {
+					if ((this.bits & DepthMASK) != 0) {
 						// internal error, per construction we should have found it
 						// not yet supported
 						currentScope.problemReporter().needImplementation();
@@ -197,7 +200,7 @@
 			}
 			// normal local assignment (since cannot store in outer local which are final locations)
 			codeStream.store(localBinding, valueRequired);
-			if ((bits & FirstAssignmentToLocalMASK) != 0) { // for local variable debug attributes
+			if ((this.bits & FirstAssignmentToLocalMASK) != 0) { // for local variable debug attributes
 				localBinding.recordInitializationStartPC(codeStream.position);
 			}
 			// implicit conversion
@@ -208,12 +211,12 @@
 }
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 	int pc = codeStream.position;
-	if (constant != NotAConstant) {
+	if (this.constant != NotAConstant) {
 		if (valueRequired) {
-			codeStream.generateConstant(constant, implicitConversion);
+			codeStream.generateConstant(this.constant, this.implicitConversion);
 		}
 	} else {
-		switch (bits & RestrictiveFlagMASK) {
+		switch (this.bits & RestrictiveFlagMASK) {
 			case FIELD : // reading a field
 				FieldBinding fieldBinding;
 				if (valueRequired) {
@@ -222,8 +225,8 @@
 							 // directly use inlined value for constant fields
 							boolean isStatic;
 							if (!(isStatic = fieldBinding.isStatic())) {
-								if ((bits & DepthMASK) != 0) {
-									ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+								if ((this.bits & DepthMASK) != 0) {
+									ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
 									Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
 									codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
 								} else {
@@ -239,7 +242,7 @@
 						} else {
 							// managing private access
 							if (!fieldBinding.isStatic()) {
-								if ((bits & DepthMASK) != 0) {
+								if ((this.bits & DepthMASK) != 0) {
 									// internal error, per construction we should have found it
 									// not yet supported
 									currentScope.problemReporter().needImplementation();
@@ -251,9 +254,9 @@
 							}
 							((CodeSnippetCodeStream)codeStream).generateEmulatedReadAccessForField(fieldBinding);
 						}
-						codeStream.generateImplicitConversion(implicitConversion);
+						codeStream.generateImplicitConversion(this.implicitConversion);
 					} else { // directly use the inlined value
-						codeStream.generateConstant(fieldBinding.constant, implicitConversion);
+						codeStream.generateConstant(fieldBinding.constant, this.implicitConversion);
 					}
 				}
 				break;
@@ -261,7 +264,7 @@
 				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 				if (valueRequired) {
 					// outer local?
-					if ((bits & DepthMASK) != 0) {
+					if ((this.bits & DepthMASK) != 0) {
 						// outer local can be reached either through a synthetic arg or a synthetic field
 						VariableBinding[] path = currentScope.getEmulationPath(localBinding);
 						codeStream.generateOuterAccess(path, this, localBinding, currentScope);
@@ -269,7 +272,7 @@
 						// regular local variable read
 						codeStream.load(localBinding);
 					}
-					codeStream.generateImplicitConversion(implicitConversion);
+					codeStream.generateImplicitConversion(this.implicitConversion);
 				}
 		}
 	}
@@ -280,7 +283,7 @@
  * are optimized in one access: e.g "a = a + 1" optimized into "a++".
  */
 public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
-	switch (bits & RestrictiveFlagMASK) {
+	switch (this.bits & RestrictiveFlagMASK) {
 		case FIELD : // assigning to a field
 			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
 			if (fieldBinding.isStatic()) {
@@ -297,8 +300,8 @@
 				}
 			} else {
 				if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-					if ((bits & DepthMASK) != 0) {
-						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+					if ((this.bits & DepthMASK) != 0) {
+						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
 						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
 						codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
 					} else {
@@ -307,7 +310,7 @@
 					codeStream.dup();
 					codeStream.getfield(fieldBinding);
 				} else {
-					if ((bits & DepthMASK) != 0) {
+					if ((this.bits & DepthMASK) != 0) {
 						// internal error, per construction we should have found it
 						// not yet supported
 						currentScope.problemReporter().needImplementation();
@@ -361,14 +364,14 @@
 	}
 	// perform the actual compound operation
 	int operationTypeID;
-	if ((operationTypeID = implicitConversion >> 4) == T_String || operationTypeID == T_Object) {
+	if ((operationTypeID = this.implicitConversion >> 4) == T_String || operationTypeID == T_Object) {
 		codeStream.generateStringAppend(currentScope, null, expression);
 	} else {
 		// promote the array reference to the suitable operation type
-		codeStream.generateImplicitConversion(implicitConversion);
+		codeStream.generateImplicitConversion(this.implicitConversion);
 		// generate the increment value (will by itself  be promoted to the operation value)
 		if (expression == IntLiteral.One){ // prefix operation
-			codeStream.generateConstant(expression.constant, implicitConversion);			
+			codeStream.generateConstant(expression.constant, this.implicitConversion);			
 		} else {
 			expression.generateCode(currentScope, codeStream, true);
 		}		
@@ -378,7 +381,7 @@
 		codeStream.generateImplicitConversion(assignmentImplicitConversion);
 	}
 	// store the result back into the variable
-	switch (bits & RestrictiveFlagMASK) {
+	switch (this.bits & RestrictiveFlagMASK) {
 		case FIELD : // assigning to a field
 			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
 			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
@@ -411,15 +414,15 @@
 	}
 }
 public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
-	switch (bits & RestrictiveFlagMASK) {
+	switch (this.bits & RestrictiveFlagMASK) {
 		case FIELD : // assigning to a field
 			FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
 			if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
 				if (fieldBinding.isStatic()) {
 					codeStream.getstatic(fieldBinding);
 				} else {
-					if ((bits & DepthMASK) != 0) {
-						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+					if ((this.bits & DepthMASK) != 0) {
+						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
 						Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
 						codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
 					} else {
@@ -443,7 +446,7 @@
 						}
 					}
 				}
-				codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
+				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
 				codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
 				codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
 				fieldStore(codeStream, fieldBinding, null, false);
@@ -451,7 +454,7 @@
 				if (fieldBinding.isStatic()) {
 					codeStream.aconst_null();
 				} else {
-					if ((bits & DepthMASK) != 0) {
+					if ((this.bits & DepthMASK) != 0) {
 						// internal error, per construction we should have found it
 						// not yet supported
 						currentScope.problemReporter().needImplementation();
@@ -489,7 +492,7 @@
 					codeStream.dup_x1();
 					codeStream.pop();					
 				}
-				codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
+				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
 				codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
 				codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
 				((CodeSnippetCodeStream) codeStream).generateEmulatedWriteAccessForField(fieldBinding);
@@ -516,7 +519,7 @@
 						codeStream.dup();
 					}
 				}
-				codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
+				codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
 				codeStream.sendOperator(postIncrement.operator, localBinding.type.id);
 				codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
 
@@ -526,57 +529,144 @@
 }
 public void generateReceiver(CodeStream codeStream) {
 	codeStream.aload_0();
-	if (delegateThis != null) codeStream.getfield(delegateThis); // delegated field access
+	if (this.delegateThis != null) {
+		codeStream.getfield(this.delegateThis); // delegated field access
+	}
 }
 /**
  * Check and/or redirect the field access to the delegate receiver if any
  */
 public TypeBinding getReceiverType(BlockScope currentScope) {
-	if (receiverType != null) return receiverType;
+	if (this.receiverType != null) {
+		return this.receiverType;
+	}
 	Scope scope = currentScope.parent;
 	while (true) {
 			switch (scope.kind) {
 				case Scope.CLASS_SCOPE :
-					return receiverType = ((ClassScope) scope).referenceContext.binding;
+					return this.receiverType = ((ClassScope) scope).referenceContext.binding;
 				default:
 					scope = scope.parent;
 			}
 	}
 }
+public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+
+	if (this.delegateThis == null) {
+		super.manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+		return;
+	}
+	
+	if (!flowInfo.isReachable()) return;
+	//If inlinable field, forget the access emulation, the code gen will directly target it
+	if (this.constant != NotAConstant)
+		return;
+	if ((this.bits & FIELD) != 0) {
+		FieldBinding fieldBinding = (FieldBinding) this.binding;
+//			if (((this.bits & DepthMASK) != 0)
+//				&& (fieldBinding.isPrivate() // private access
+//					|| (fieldBinding.isProtected() // implicit protected access
+//							&& fieldBinding.declaringClass.getPackage() 
+//								!= this.delegateThis.type.getPackage()))) {
+//				if (this.syntheticAccessors == null)
+//					this.syntheticAccessors = new MethodBinding[2];
+//				this.syntheticAccessors[READ] = 
+//					((SourceTypeBinding)currentScope.enclosingSourceType().
+//						enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT)).
+//							addSyntheticMethod(fieldBinding, true);
+//				currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
+//				return;
+//			}
+		// if the binding declaring class is not visible, need special action
+		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
+		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
+		// and not from Object or implicit static field access.	
+		if (fieldBinding.declaringClass != this.delegateThis.type
+			&& fieldBinding.declaringClass != null
+			&& fieldBinding.constant == NotAConstant
+			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
+					&& !fieldBinding.isStatic()
+					&& fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
+				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
+			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.delegateThis.type);
+		}
+	}
+}
+public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+
+	if (this.delegateThis == null) {
+		super.manageSyntheticWriteAccessIfNecessary(currentScope, flowInfo);
+		return;
+	}
+
+	if (!flowInfo.isReachable()) return;
+	if ((this.bits & FIELD) != 0) {
+		FieldBinding fieldBinding = (FieldBinding) this.binding;
+//		if (((this.bits & DepthMASK) != 0) 
+//			&& (fieldBinding.isPrivate() // private access
+//				|| (fieldBinding.isProtected() // implicit protected access
+//						&& fieldBinding.declaringClass.getPackage() 
+//							!= currentScope.enclosingSourceType().getPackage()))) {
+//			if (this.syntheticAccessors == null)
+//				this.syntheticAccessors = new MethodBinding[2];
+//			this.syntheticAccessors[WRITE] = 
+//				((SourceTypeBinding)currentScope.enclosingSourceType().
+//					enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT)).
+//						addSyntheticMethod(fieldBinding, false);
+//			currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
+//			return;
+//		}
+		// if the binding declaring class is not visible, need special action
+		// for runtime compatibility on 1.2 VMs : change the declaring class of the binding
+		// NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
+		// and not from Object or implicit static field access.	
+		if (fieldBinding.declaringClass != this.delegateThis.type
+			&& fieldBinding.declaringClass != null
+			&& fieldBinding.constant == NotAConstant
+			&& ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
+					&& !fieldBinding.isStatic()
+					&& fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
+				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
+			this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.delegateThis.type);
+		}
+	}
+}
 /**
  * Normal field binding did not work, try to bind to a field of the delegate receiver.
  */
 public TypeBinding reportError(BlockScope scope) {
 
-	constant = Constant.NotAConstant;
-	if (binding instanceof ProblemFieldBinding && ((ProblemFieldBinding) binding).problemId() == NotFound){
+	this.constant = Constant.NotAConstant;
+	if (this.binding instanceof ProblemFieldBinding && ((ProblemFieldBinding) this.binding).problemId() == NotFound){
 		if (this.evaluationContext.declaringTypeName != null) {
-			delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
-			if (delegateThis != null){ ; // if not found then internal error, field should have been found
+			this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
+			if (this.delegateThis != null){  // if not found then internal error, field should have been found
 				// will not support innerclass emulation inside delegate
-				this.codegenBinding = binding = scope.getField(delegateThis.type, this.token, this);
-				if (!binding.isValidBinding()) return super.reportError(scope);
+				this.codegenBinding = this.binding = scope.getField(this.delegateThis.type, this.token, this);
+				if (!this.binding.isValidBinding()) {
+					return super.reportError(scope);
+				}
 				return checkFieldAccess(scope);
 			}
 		}
 	}
-	if (binding instanceof ProblemBinding && ((ProblemBinding) binding).problemId() == NotFound){
+	if (this.binding instanceof ProblemBinding && ((ProblemBinding) this.binding).problemId() == NotFound){
 		if (this.evaluationContext.declaringTypeName != null) {
-			delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
-			if (delegateThis != null){ ; // if not found then internal error, field should have been found
+			this.delegateThis = scope.getField(scope.enclosingSourceType(), DELEGATE_THIS, this);
+			if (this.delegateThis != null){  // if not found then internal error, field should have been found
 				// will not support innerclass emulation inside delegate
-				FieldBinding fieldBinding = scope.getField(delegateThis.type, this.token, this);
+				FieldBinding fieldBinding = scope.getField(this.delegateThis.type, this.token, this);
 				if (!fieldBinding.isValidBinding()) {
 					if (((ProblemFieldBinding) fieldBinding).problemId() == NotVisible) {
 						// manage the access to a private field of the enclosing type
 						CodeSnippetScope localScope = new CodeSnippetScope(scope);
-						this.codegenBinding = binding = localScope.getFieldForCodeSnippet(delegateThis.type, this.token, this);
+						this.codegenBinding = this.binding = localScope.getFieldForCodeSnippet(this.delegateThis.type, this.token, this);
 						return checkFieldAccess(scope);						
 					} else {
 						return super.reportError(scope);
 					}
 				}
-				this.codegenBinding = binding = fieldBinding;
+				this.codegenBinding = this.binding = fieldBinding;
 				return checkFieldAccess(scope);
 			}
 		}
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
index b671d76..d33c533 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetSkeleton.java
@@ -16,6 +16,7 @@
 import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 
 /**
  * The skeleton of the class 'org.eclipse.jdt.internal.eval.target.CodeSnippet'
@@ -103,7 +104,7 @@
 	return null;
 }
 public char[] getFileName() {
-	return CharOperation.concat(CODE_SNIPPET_NAME, ".java".toCharArray()); //$NON-NLS-1$
+	return CharOperation.concat(CODE_SNIPPET_NAME, SuffixConstants.SUFFIX_java); //$NON-NLS-1$
 }
 public char[][] getInterfaceNames() {
 	return null;
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java
index 8c38f25..4c9b451 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java
@@ -24,74 +24,81 @@
  * receiver object (that is, the receiver of the context in the stack frame)
  */
 public class CodeSnippetThisReference extends ThisReference implements EvaluationConstants, InvocationSite {
+	
 	EvaluationContext evaluationContext;
 	FieldBinding delegateThis;
 	boolean isImplicit;
-/**
- * CodeSnippetThisReference constructor comment.
- * @param s int
- * @param sourceEnd int
- */
-public CodeSnippetThisReference(int s, int sourceEnd, EvaluationContext evaluationContext, boolean isImplicit) {
-	super(s, sourceEnd);
-	this.evaluationContext = evaluationContext;
-	this.isImplicit = isImplicit;
-}
-public boolean checkAccess(MethodScope methodScope) {
-	// this/super cannot be used in constructor call
-	if (evaluationContext.isConstructorCall) {
-		methodScope.problemReporter().fieldsOrThisBeforeConstructorInvocation(this);
-		return false;
-	}
-
-	// static may not refer to this/super
-	if (this.evaluationContext.declaringTypeName == null || evaluationContext.isStatic) {
-		methodScope.problemReporter().errorThisSuperInStatic(this);
-		return false;
-	}
-	return true;
-}
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
-	int pc = codeStream.position;
-	if (valueRequired) {
-		codeStream.aload_0();
-		codeStream.getfield(delegateThis);
-	}
-	codeStream.recordPositionsFrom(pc, this.sourceStart);
-}
-public boolean isSuperAccess(){
-	return false;
-}
-public boolean isTypeAccess(){
-	return false;
-}
-public TypeBinding resolveType(BlockScope scope) {
-
-	// implicit this
-	constant = NotAConstant;
-	TypeBinding snippetType = null;
-	if (this.isImplicit || checkAccess(scope.methodScope())){
-		snippetType = scope.enclosingSourceType();
-	}
-	if (snippetType == null) return null;
 	
-	delegateThis = scope.getField(snippetType, DELEGATE_THIS, this);
-	if (delegateThis == null) return null; // internal error, field should have been found
-	if (delegateThis.isValidBinding()) return this.resolvedType = delegateThis.type;
-	return this.resolvedType = snippetType;
-}
-public void setActualReceiverType(ReferenceBinding receiverType) {
-	// ignored
-}
-public void setDepth(int depth){
-	// ignored
-}
-public void setFieldIndex(int index){
-	// ignored
-}
-
-public String toStringExpression(){
-	char[] declaringType = this.evaluationContext.declaringTypeName;
-	return "(" + (declaringType == null ? "<NO DECLARING TYPE>" : new String(declaringType)) + ")this"; //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
-}
+	/**
+	 * CodeSnippetThisReference constructor comment.
+	 * @param s int
+	 * @param sourceEnd int
+	 */
+	public CodeSnippetThisReference(int s, int sourceEnd, EvaluationContext evaluationContext, boolean isImplicit) {
+		super(s, sourceEnd);
+		this.evaluationContext = evaluationContext;
+		this.isImplicit = isImplicit;
+	}
+	public boolean checkAccess(MethodScope methodScope) {
+		// this/super cannot be used in constructor call
+		if (this.evaluationContext.isConstructorCall) {
+			methodScope.problemReporter().fieldsOrThisBeforeConstructorInvocation(this);
+			return false;
+		}
+	
+		// static may not refer to this/super
+		if (this.evaluationContext.declaringTypeName == null || this.evaluationContext.isStatic) {
+			methodScope.problemReporter().errorThisSuperInStatic(this);
+			return false;
+		}
+		return true;
+	}
+	public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+		int pc = codeStream.position;
+		if (valueRequired) {
+			codeStream.aload_0();
+			codeStream.getfield(this.delegateThis);
+		}
+		codeStream.recordPositionsFrom(pc, this.sourceStart);
+	}
+	public boolean isSuperAccess(){
+		return false;
+	}
+	public boolean isTypeAccess(){
+		return false;
+	}
+	public StringBuffer printExpression(int indent, StringBuffer output){
+		
+		char[] declaringType = this.evaluationContext.declaringTypeName;
+		output.append('(');
+		if (declaringType == null) 
+			output.append("<NO DECLARING TYPE>"); //$NON-NLS-1$
+		else 
+			output.append(declaringType);
+		return output.append(")this"); //$NON-NLS-1$
+	}
+	public TypeBinding resolveType(BlockScope scope) {
+	
+		// implicit this
+		this.constant = NotAConstant;
+		TypeBinding snippetType = null;
+		if (this.isImplicit || checkAccess(scope.methodScope())){
+			snippetType = scope.enclosingSourceType();
+		}
+		if (snippetType == null) return null;
+		
+		this.delegateThis = scope.getField(snippetType, DELEGATE_THIS, this);
+		if (this.delegateThis == null) return null; // internal error, field should have been found
+		if (this.delegateThis.isValidBinding()) return this.resolvedType = this.delegateThis.type;
+		return this.resolvedType = snippetType;
+	}
+	public void setActualReceiverType(ReferenceBinding receiverType) {
+		// ignored
+	}
+	public void setDepth(int depth){
+		// ignored
+	}
+	public void setFieldIndex(int index){
+		// ignored
+	}
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java
index f7d2ed0..6fde68f 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetToCuMapper.java
@@ -42,45 +42,45 @@
 
 	// Internal fields
 	char[] codeSnippet;
-	char[] packageName;
-	char[][] imports;
-	char[] className; 
-	char[] varClassName;
+	char[] snippetPackageName;
+	char[][] snippetImports;
+	char[] snippetClassName; 
+	char[] snippetVarClassName;
+	char[] snippetDeclaringTypeName;
 
 	// Mapping of external local variables
 	char[][] localVarNames;
 	char[][] localVarTypeNames;
 	int[] localVarModifiers;
-	char[] declaringTypeName;
-
+	
 /**
  * Rebuild source in presence of external local variables
  */
  public CodeSnippetToCuMapper(char[] codeSnippet, char[] packageName, char[][] imports, char[] className, char[] varClassName, char[][] localVarNames, char[][] localVarTypeNames, int[] localVarModifiers, char[] declaringTypeName) {
 	this.codeSnippet = codeSnippet;
-	this.packageName = packageName;
-	this.imports = imports;
-	this.className = className;
-	this.varClassName = varClassName;
+	this.snippetPackageName = packageName;
+	this.snippetImports = imports;
+	this.snippetClassName = className;
+	this.snippetVarClassName = varClassName;
 	this.localVarNames = localVarNames;
 	this.localVarTypeNames = localVarTypeNames;
 	this.localVarModifiers = localVarModifiers;
-	this.declaringTypeName = declaringTypeName;
+	this.snippetDeclaringTypeName = declaringTypeName;
 	this.buildCUSource();
 }
 private void buildCUSource() {
 	StringBuffer buffer = new StringBuffer();
 
 	// package declaration
-	if (this.packageName != null && this.packageName.length != 0) {
+	if (this.snippetPackageName != null && this.snippetPackageName.length != 0) {
 		buffer.append("package "); //$NON-NLS-1$
-		buffer.append(this.packageName);
+		buffer.append(this.snippetPackageName);
 		buffer.append(";").append(Util.LINE_SEPARATOR); //$NON-NLS-1$
 		this.lineNumberOffset++;
 	}
 
 	// import declarations
-	char[][] imports = this.imports;
+	char[][] imports = this.snippetImports;
 	for (int i = 0; i < imports.length; i++) {
 		buffer.append("import "); //$NON-NLS-1$
 		buffer.append(imports[i]);
@@ -90,12 +90,12 @@
 
 	// class declaration
 	buffer.append("public class "); //$NON-NLS-1$
-	buffer.append(this.className);
+	buffer.append(this.snippetClassName);
 
 	// super class is either a global variable class or the CodeSnippet class
-	if (this.varClassName != null) {
+	if (this.snippetVarClassName != null) {
 		buffer.append(" extends "); //$NON-NLS-1$
-		buffer.append(this.varClassName);
+		buffer.append(this.snippetVarClassName);
 	} else {
 		buffer.append(" extends "); //$NON-NLS-1$
 		buffer.append(PACKAGE_NAME);
@@ -105,22 +105,22 @@
 	buffer.append(" {").append(Util.LINE_SEPARATOR); //$NON-NLS-1$
 	this.lineNumberOffset++;
 
-	if (this.declaringTypeName != null){
+	if (this.snippetDeclaringTypeName != null){
 		buffer.append("  "); //$NON-NLS-1$
-		buffer.append(this.declaringTypeName);
+		buffer.append(this.snippetDeclaringTypeName);
 		buffer.append(" "); //$NON-NLS-1$
 		buffer.append(DELEGATE_THIS); // val$this
 		buffer.append(';').append(Util.LINE_SEPARATOR);
 		this.lineNumberOffset++;
 	}
 	// add some storage location for local variable persisted state
-	if (localVarNames != null) {
-		for (int i = 0, max = localVarNames.length; i < max; i++) {
+	if (this.localVarNames != null) {
+		for (int i = 0, max = this.localVarNames.length; i < max; i++) {
 			buffer.append("    "); //$NON-NLS-1$
-			buffer.append(localVarTypeNames[i]);
+			buffer.append(this.localVarTypeNames[i]);
 			buffer.append(" "); //$NON-NLS-1$
 			buffer.append(LOCAL_VAR_PREFIX); // val$...
-			buffer.append(localVarNames[i]);
+			buffer.append(this.localVarNames[i]);
 			buffer.append(';').append(Util.LINE_SEPARATOR);
 			this.lineNumberOffset++;
 		}
@@ -128,8 +128,8 @@
 	// run() method declaration
 	buffer.append("public void run() throws Throwable {").append(Util.LINE_SEPARATOR); //$NON-NLS-1$
 	this.lineNumberOffset++;
-	startPosOffset = buffer.length();
-	buffer.append(codeSnippet);
+	this.startPosOffset = buffer.length();
+	buffer.append(this.codeSnippet);
 	// a line separator is required after the code snippet source code
 	// in case the code snippet source code ends with a line comment
 	// http://dev.eclipse.org/bugs/show_bug.cgi?id=14838
@@ -148,68 +148,66 @@
  * according to the start offset and line number offset of the code snippet in the generated compilation unit. 
  */
 public ICompletionRequestor getCompletionRequestor(final ICompletionRequestor originalRequestor) {
-	final int startPosOffset = this.startPosOffset;
-	final int lineNumberOffset = this.lineNumberOffset;
 	return new ICompletionRequestor() {
 		public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
-			originalRequestor.acceptAnonymousType(superTypePackageName, superTypeName, parameterPackageNames, parameterTypeNames, parameterNames, completionName, modifiers, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			originalRequestor.acceptAnonymousType(superTypePackageName, superTypeName, parameterPackageNames, parameterTypeNames, parameterNames, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		
 		public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
 			// Remove completion on generated class name or generated global variable class name
-			if (CharOperation.equals(packageName, CodeSnippetToCuMapper.this.packageName) 
-					&& (CharOperation.equals(className, CodeSnippetToCuMapper.this.className)
-						|| CharOperation.equals(className, CodeSnippetToCuMapper.this.varClassName))) return;
-			originalRequestor.acceptClass(packageName, className, completionName, modifiers, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			if (CharOperation.equals(packageName, CodeSnippetToCuMapper.this.snippetPackageName) 
+					&& (CharOperation.equals(className, CodeSnippetToCuMapper.this.snippetClassName)
+						|| CharOperation.equals(className, CodeSnippetToCuMapper.this.snippetVarClassName))) return;
+			originalRequestor.acceptClass(packageName, className, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		public void acceptError(IProblem error) {
 
-			error.setSourceStart(error.getSourceStart() - startPosOffset);
-			error.setSourceEnd(error.getSourceEnd() - startPosOffset);
-			error.setSourceLineNumber(error.getSourceLineNumber() - lineNumberOffset);
+			error.setSourceStart(error.getSourceStart() - CodeSnippetToCuMapper.this.startPosOffset);
+			error.setSourceEnd(error.getSourceEnd() - CodeSnippetToCuMapper.this.startPosOffset);
+			error.setSourceLineNumber(error.getSourceLineNumber() -  CodeSnippetToCuMapper.this.lineNumberOffset);
 			originalRequestor.acceptError(error);
 		}
 		public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			originalRequestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		public void acceptInterface(char[] packageName, char[] interfaceName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			originalRequestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		public void acceptKeyword(char[] keywordName, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptKeyword(keywordName, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			originalRequestor.acceptKeyword(keywordName, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		public void acceptLabel(char[] labelName, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptLabel(labelName, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			originalRequestor.acceptLabel(labelName, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		public void acceptLocalVariable(char[] name, char[] typePackageName, char[] typeName, int modifiers, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptLocalVariable(name, typePackageName, typeName, modifiers, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			originalRequestor.acceptLocalVariable(name, typePackageName, typeName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, char[][] parameterNames, char[] returnTypePackageName, char[] returnTypeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
 			// Remove completion on generated method
-			if (CharOperation.equals(declaringTypePackageName, CodeSnippetToCuMapper.this.packageName) 
-					&& CharOperation.equals(declaringTypeName, CodeSnippetToCuMapper.this.className)
+			if (CharOperation.equals(declaringTypePackageName, CodeSnippetToCuMapper.this.snippetPackageName) 
+					&& CharOperation.equals(declaringTypeName, CodeSnippetToCuMapper.this.snippetClassName)
 					&& CharOperation.equals(selector, "run".toCharArray())) return; //$NON-NLS-1$
-			originalRequestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, parameterNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			originalRequestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, parameterNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		public void acceptMethodDeclaration(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, char[][] parameterNames, char[] returnTypePackageName, char[] returnTypeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
 			// Remove completion on generated method
-			if (CharOperation.equals(declaringTypePackageName, CodeSnippetToCuMapper.this.packageName) 
-					&& CharOperation.equals(declaringTypeName, CodeSnippetToCuMapper.this.className)
+			if (CharOperation.equals(declaringTypePackageName, CodeSnippetToCuMapper.this.snippetPackageName) 
+					&& CharOperation.equals(declaringTypeName, CodeSnippetToCuMapper.this.snippetClassName)
 					&& CharOperation.equals(selector, "run".toCharArray())) return;//$NON-NLS-1$
-			originalRequestor.acceptMethodDeclaration(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, parameterNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			originalRequestor.acceptMethodDeclaration(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, parameterNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		public void acceptModifier(char[] modifierName, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptModifier(modifierName, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			originalRequestor.acceptModifier(modifierName, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		public void acceptPackage(char[] packageName, char[] completionName, int completionStart, int completionEnd, int relevance) {
-			originalRequestor.acceptPackage(packageName, completionName, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			originalRequestor.acceptPackage(packageName, completionName, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		public void acceptType(char[] packageName, char[] typeName, char[] completionName, int completionStart, int completionEnd, int relevance) {
 			// Remove completion on generated class name or generated global variable class name
-			if (CharOperation.equals(packageName, CodeSnippetToCuMapper.this.packageName) 
-					&& (CharOperation.equals(className, CodeSnippetToCuMapper.this.className)
-						|| CharOperation.equals(className, CodeSnippetToCuMapper.this.varClassName))) return;
-			originalRequestor.acceptType(packageName, typeName, completionName, completionStart - startPosOffset, completionEnd - startPosOffset, relevance);
+			if (CharOperation.equals(packageName, CodeSnippetToCuMapper.this.snippetPackageName) 
+					&& (CharOperation.equals( CodeSnippetToCuMapper.this.snippetClassName, CodeSnippetToCuMapper.this.snippetClassName)
+						|| CharOperation.equals( CodeSnippetToCuMapper.this.snippetClassName, CodeSnippetToCuMapper.this.snippetVarClassName))) return;
+			originalRequestor.acceptType(packageName, typeName, completionName, completionStart - CodeSnippetToCuMapper.this.startPosOffset, completionEnd - CodeSnippetToCuMapper.this.startPosOffset, relevance);
 		}
 		public void acceptVariableName(char[] typePackageName, char[] typeName, char[] name, char[] completionName, int completionStart, int completionEnd, int relevance){
 			originalRequestor.acceptVariableName(typePackageName, typeName, name, completionName, completionStart, completionEnd, relevance);
@@ -229,7 +227,7 @@
 	int currentLine = 1;
 
 	// check package declaration	
-	if (this.packageName != null && this.packageName.length != 0) {
+	if (this.snippetPackageName != null && this.snippetPackageName.length != 0) {
 		if (lineNumber == 1) {
 			return EvaluationResult.T_PACKAGE;
 		}
@@ -237,7 +235,7 @@
 	}
 
 	// check imports
-	char[][] imports = this.imports;
+	char[][] imports = this.snippetImports;
 	if ((currentLine <= lineNumber) && (lineNumber < (currentLine + imports.length))) {
 		return EvaluationResult.T_IMPORT;
 	}
@@ -245,7 +243,7 @@
 
 	// check generated fields
 	currentLine +=
-		(this.declaringTypeName == null ? 0 : 1) 
+		(this.snippetDeclaringTypeName == null ? 0 : 1) 
 		+ (this.localVarNames == null ? 0 : this.localVarNames.length);
 	if (currentLine > lineNumber) {
 		return EvaluationResult.T_INTERNAL;
@@ -264,24 +262,22 @@
  * Returns the import defined at the given line number. 
  */
 public char[] getImport(int lineNumber) {
-	int importStartLine = this.lineNumberOffset - 1 - this.imports.length;
-	return this.imports[lineNumber - importStartLine];
+	int importStartLine = this.lineNumberOffset - 1 - this.snippetImports.length;
+	return this.snippetImports[lineNumber - importStartLine];
 }
 /**
  * Returns a selection requestor that wraps the given requestor and shift the problems
  * according to the start offset and line number offset of the code snippet in the generated compilation unit. 
  */
 public ISelectionRequestor getSelectionRequestor(final ISelectionRequestor originalRequestor) {
-	final int startPosOffset = this.startPosOffset;
-	final int lineNumberOffset = this.lineNumberOffset;
 	return new ISelectionRequestor() {
 		public void acceptClass(char[] packageName, char[] className, boolean needQualification) {
 			originalRequestor.acceptClass(packageName, className, needQualification);
 		}
 		public void acceptError(IProblem error) {
-			error.setSourceLineNumber(error.getSourceLineNumber() - lineNumberOffset);
-			error.setSourceStart(error.getSourceStart() - startPosOffset);
-			error.setSourceEnd(error.getSourceEnd() - startPosOffset);
+			error.setSourceLineNumber(error.getSourceLineNumber() -  CodeSnippetToCuMapper.this.lineNumberOffset);
+			error.setSourceStart(error.getSourceStart() - CodeSnippetToCuMapper.this.startPosOffset);
+			error.setSourceEnd(error.getSourceEnd() - CodeSnippetToCuMapper.this.startPosOffset);
 			originalRequestor.acceptError(error);
 		}
 		public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name) {
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java
index 2722fa9..25414a1 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java
@@ -25,59 +25,59 @@
  * Generic bytecode generation for type
  */
 public void generateCode(ClassFile enclosingClassFile) {
-	if (hasBeenGenerated) return;
-	hasBeenGenerated = true;
+	if (this.hasBeenGenerated) return;
+	this.hasBeenGenerated = true;
 	
-	if (ignoreFurtherInvestigation) {
-		if (binding == null)
+	if (this.ignoreFurtherInvestigation) {
+		if (this.binding == null)
 			return;
-		CodeSnippetClassFile.createProblemType(this, scope.referenceCompilationUnit().compilationResult);
+		CodeSnippetClassFile.createProblemType(this, this.scope.referenceCompilationUnit().compilationResult);
 		return;
 	}
 	try {
 		// create the result for a compiled type
-		ClassFile classFile = new CodeSnippetClassFile(binding, enclosingClassFile, false);
+		ClassFile classFile = new CodeSnippetClassFile(this.binding, enclosingClassFile, false);
 		// generate all fiels
 		classFile.addFieldInfos();
 
 		// record the inner type inside its own .class file to be able
 		// to generate inner classes attributes
-		if (binding.isMemberType())
-			classFile.recordEnclosingTypeAttributes(binding);
-		if (binding.isLocalType()) {
-			enclosingClassFile.recordNestedLocalAttribute(binding);
-			classFile.recordNestedLocalAttribute(binding);
+		if (this.binding.isMemberType())
+			classFile.recordEnclosingTypeAttributes(this.binding);
+		if (this.binding.isLocalType()) {
+			enclosingClassFile.recordNestedLocalAttribute(this.binding);
+			classFile.recordNestedLocalAttribute(this.binding);
 		}
-		if (memberTypes != null) {
-			for (int i = 0, max = memberTypes.length; i < max; i++) {
+		if (this.memberTypes != null) {
+			for (int i = 0, max = this.memberTypes.length; i < max; i++) {
 				// record the inner type inside its own .class file to be able
 				// to generate inner classes attributes
-				classFile.recordNestedMemberAttribute(memberTypes[i].binding);
-				memberTypes[i].generateCode(scope, classFile);
+				classFile.recordNestedMemberAttribute(this.memberTypes[i].binding);
+				this.memberTypes[i].generateCode(this.scope, classFile);
 			}
 		}
 		// generate all methods
 		classFile.setForMethodInfos();
-		if (methods != null) {
-			for (int i = 0, max = methods.length; i < max; i++) {
-				methods[i].generateCode(scope, classFile);
+		if (this.methods != null) {
+			for (int i = 0, max = this.methods.length; i < max; i++) {
+				this.methods[i].generateCode(this.scope, classFile);
 			}
 		}
 		
 		// generate all methods
 		classFile.addSpecialMethods();
 
-		if (ignoreFurtherInvestigation){ // trigger problem type generation for code gen errors
-			throw new AbortType(scope.referenceCompilationUnit().compilationResult);
+		if (this.ignoreFurtherInvestigation){ // trigger problem type generation for code gen errors
+			throw new AbortType(this.scope.referenceCompilationUnit().compilationResult);
 		}
 
 		// finalize the compiled type result
 		classFile.addAttributes();
-		scope.referenceCompilationUnit().compilationResult.record(binding.constantPoolName(), classFile);
+		this.scope.referenceCompilationUnit().compilationResult.record(this.binding.constantPoolName(), classFile);
 	} catch (AbortType e) {
-		if (binding == null)
+		if (this.binding == null)
 			return;
-		CodeSnippetClassFile.createProblemType(this, scope.referenceCompilationUnit().compilationResult);
+		CodeSnippetClassFile.createProblemType(this, this.scope.referenceCompilationUnit().compilationResult);
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationConstants.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationConstants.java
index 316fb85..3d973c4 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationConstants.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationConstants.java
@@ -25,7 +25,7 @@
 	public static final String RUN_METHOD = "run"; //$NON-NLS-1$
 	public static final String RESULT_VALUE_FIELD = "resultValue"; //$NON-NLS-1$
 	public static final String RESULT_TYPE_FIELD = "resultType"; //$NON-NLS-1$
-	public final static char[] LOCAL_VAR_PREFIX = "val$".toCharArray(); //$NON-NLS-1$
-	public final static char[] DELEGATE_THIS = "val$this".toCharArray(); //$NON-NLS-1$
+	public static final char[] LOCAL_VAR_PREFIX = "val$".toCharArray(); //$NON-NLS-1$
+	public static final char[] DELEGATE_THIS = "val$this".toCharArray(); //$NON-NLS-1$
 	
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java
index 4c68d1e..b51700c 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/EvaluationContext.java
@@ -12,7 +12,6 @@
 
 import java.util.Map;
 
-import org.eclipse.jdt.core.ICompletionRequestor;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.compiler.IProblem;
@@ -26,11 +25,13 @@
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.CompletionRequestorWrapper;
 
 /**
  * @see org.eclipse.jdt.core.eval.IEvaluationContext
  */
-public class EvaluationContext implements EvaluationConstants {
+public class EvaluationContext implements EvaluationConstants, SuffixConstants {
 	/**
 	 * Whether timing information should be output to the stdout
 	 */
@@ -42,11 +43,11 @@
 	static int VAR_CLASS_COUNTER = 0;
 	static int CODE_SNIPPET_COUNTER = 0;
 
-	GlobalVariable[] variables = new GlobalVariable[5];
-	int variableCount = 0;
-	char[][] imports = CharOperation.NO_CHAR_CHAR;
-	char[] packageName = CharOperation.NO_CHAR;
-	boolean varsChanged = true;
+	GlobalVariable[] variables;
+	int variableCount;
+	char[][] imports;
+	char[] packageName;
+	boolean varsChanged;
 	VariablesInfo installedVars;
 	IBinaryType codeSnippetBinary;
 
@@ -57,12 +58,19 @@
 	char[][] localVariableNames;
 	
 	/* can 'this' be used in this context */
-	boolean isStatic = true;
-	boolean isConstructorCall = false;
+	boolean isStatic;
+	boolean isConstructorCall;
 /**
  * Creates a new evaluation context.
  */
 public EvaluationContext() {
+	this.variables = new GlobalVariable[5];
+	this.variableCount = 0;
+	this.imports = CharOperation.NO_CHAR_CHAR;
+	this.packageName = CharOperation.NO_CHAR;
+	this.varsChanged = true;
+	this.isStatic = true;
+	this.isConstructorCall = false;
 }
 /**
  * Returns the global variables of this evaluation context in the order they were created in.
@@ -87,7 +95,7 @@
  *  @param options
  *		set of options used to configure the code assist engine.
  */
-public void complete(char[] codeSnippet, int completionPosition, ISearchableNameEnvironment environment, ICompletionRequestor requestor, Map options, IJavaProject project) {
+public void complete(char[] codeSnippet, int completionPosition, ISearchableNameEnvironment environment, CompletionRequestorWrapper requestor, Map options, IJavaProject project) {
 	final char[] className = "CodeSnippetCompletion".toCharArray(); //$NON-NLS-1$
 	final CodeSnippetToCuMapper mapper = new CodeSnippetToCuMapper(
 		codeSnippet, 
@@ -102,7 +110,7 @@
 	);
 	ICompilationUnit sourceUnit = new ICompilationUnit() {
 		public char[] getFileName() {
-			return CharOperation.concat(className, "java".toCharArray(), '.'); //$NON-NLS-1$
+			return CharOperation.concat(className, SUFFIX_java);
 		}
 		public char[] getContents() {
 			return mapper.getCUSource();
@@ -115,6 +123,7 @@
 		}
 	};
 	CompletionEngine engine = new CompletionEngine(environment, mapper.getCompletionRequestor(requestor), options, project);
+	requestor.completionEngine = engine;
 	engine.complete(sourceUnit, mapper.startPosOffset + completionPosition, 0);
 }
 /**
@@ -164,24 +173,24 @@
  */
 public void evaluate(
 	char[] codeSnippet, 
-	char[][] localVariableTypeNames,
-	char[][] localVariableNames, 
-	int[] localVariableModifiers,
-	char[] declaringTypeName,
-	boolean isStatic,
-	boolean isConstructorCall,
+	char[][] contextLocalVariableTypeNames,
+	char[][] contextLocalVariableNames, 
+	int[] contextLocalVariableModifiers,
+	char[] contextDeclaringTypeName,
+	boolean contextIsStatic,
+	boolean contextIsConstructorCall,
 	INameEnvironment environment, 
 	Map options, 
 	final IRequestor requestor, 
 	IProblemFactory problemFactory) throws InstallException {
 
 	// Initialialize context
-	this.localVariableTypeNames = localVariableTypeNames;
-	this.localVariableNames = localVariableNames;
-	this.localVariableModifiers = localVariableModifiers;
-	this.declaringTypeName = declaringTypeName;
-	this.isStatic = isStatic;
-	this.isConstructorCall = isConstructorCall;
+	this.localVariableTypeNames = contextLocalVariableTypeNames;
+	this.localVariableNames = contextLocalVariableNames;
+	this.localVariableModifiers = contextLocalVariableModifiers;
+	this.declaringTypeName = contextDeclaringTypeName;
+	this.isStatic = contextIsStatic;
+	this.isConstructorCall = contextIsConstructorCall;
 
 	this.deployCodeSnippetClassIfNeeded(requestor);
 
@@ -195,10 +204,10 @@
 			public void acceptProblem(IProblem problem, char[] fragmentSource, int fragmentKind) {
 				requestor.acceptProblem(problem, fragmentSource, fragmentKind);
 				if (problem.isError()) {
-					hasErrors = true;
+					this.hasErrors = true;
 				}
 			}
-		};
+		}
 		ForwardingRequestor forwardingRequestor = new ForwardingRequestor();
 		if (this.varsChanged) {
 			evaluateVariables(environment, options, forwardingRequestor, problemFactory);
@@ -225,11 +234,11 @@
 			// Send code snippet on target
 			if (classes != null && classes.length > 0) {
 				char[] simpleClassName = evaluator.getClassName();
-				char[] packageName = this.getPackageName();
+				char[] pkgName = this.getPackageName();
 				char[] qualifiedClassName =
-					packageName.length == 0 ?
+					pkgName.length == 0 ?
 						simpleClassName :
-						CharOperation.concat(packageName, simpleClassName, '.');
+						CharOperation.concat(pkgName, simpleClassName, '.');
 				CODE_SNIPPET_COUNTER++;
 				requestor.acceptClassFiles(classes, qualifiedClassName);
 			}
@@ -272,8 +281,8 @@
 		char[][] splitDeclaration = CharOperation.splitOn('.', importDeclaration);
 		int splitLength = splitDeclaration.length;
 		if (splitLength > 0) {
-			char[] packageName = splitDeclaration[splitLength - 1];
-			if (packageName.length == 1 && packageName[0] == '*') {
+			char[] pkgName = splitDeclaration[splitLength - 1];
+			if (pkgName.length == 1 && pkgName[0] == '*') {
 				char[][] parentName;
 				switch (splitLength) {
 					case 1:
@@ -281,13 +290,13 @@
 						break;
 					case 2:
 						parentName = null;
-						packageName = splitDeclaration[splitLength - 2];
+						pkgName = splitDeclaration[splitLength - 2];
 						break;
 					default:
 						parentName = CharOperation.subarray(splitDeclaration, 0, splitLength - 2);
-						packageName = splitDeclaration[splitLength - 2];
+						pkgName = splitDeclaration[splitLength - 2];
 				}
-				if (!environment.isPackage(parentName, packageName)) {
+				if (!environment.isPackage(parentName, pkgName)) {
 					String[] arguments = new String[] {new String(importDeclaration)};
 					problems[0] = problemFactory.createProblem(importDeclaration, IProblem.ImportNotFound, arguments, arguments, ProblemSeverities.Warning, 0, importDeclaration.length - 1, i);
 				}
@@ -330,10 +339,10 @@
 			}
 
 			// Remember that the variables have been installed
-			int variableCount = this.variableCount;
-			GlobalVariable[] variablesCopy = new GlobalVariable[variableCount];
-			System.arraycopy(this.variables, 0, variablesCopy, 0, variableCount); 
-			this.installedVars = new VariablesInfo(evaluator.getPackageName(), evaluator.getClassName(), classes, variablesCopy, variableCount);
+			int count = this.variableCount;
+			GlobalVariable[] variablesCopy = new GlobalVariable[count];
+			System.arraycopy(this.variables, 0, variablesCopy, 0, count); 
+			this.installedVars = new VariablesInfo(evaluator.getPackageName(), evaluator.getClassName(), classes, variablesCopy, count);
 			VAR_CLASS_COUNTER++;
 		}
 		this.varsChanged = false;
@@ -417,9 +426,9 @@
 		"/**\n" + //$NON-NLS-1$
 		" * Stores the result type and value of the code snippet evaluation.\n" + //$NON-NLS-1$
 		" */\n" + //$NON-NLS-1$
-		"public void setResult(Object resultValue, Class resultType) {\n" + //$NON-NLS-1$
-		"	this.resultValue = resultValue;\n" + //$NON-NLS-1$
-		"	this.resultType = resultType;\n" + //$NON-NLS-1$
+		"public void setResult(Object someResultValue, Class someResultType) {\n" + //$NON-NLS-1$
+		"	this.resultValue = someResultValue;\n" + //$NON-NLS-1$
+		"	this.resultType = someResultType;\n" + //$NON-NLS-1$
 		"}\n" + //$NON-NLS-1$
 		"}\n"; //$NON-NLS-1$
 }
@@ -443,7 +452,7 @@
  * Return the binary for the root code snippet class (ie. org.eclipse.jdt.internal.eval.target.CodeSnippet).
  */
 IBinaryType getRootCodeSnippetBinary() {
-	if (codeSnippetBinary == null) {
+	if (this.codeSnippetBinary == null) {
 		this.codeSnippetBinary = new CodeSnippetSkeleton();
 	}
 	return this.codeSnippetBinary;
@@ -513,7 +522,7 @@
 	);
 	ICompilationUnit sourceUnit = new ICompilationUnit() {
 		public char[] getFileName() {
-			return CharOperation.concat(className, "java".toCharArray(), '.'); //$NON-NLS-1$
+			return CharOperation.concat(className, SUFFIX_java);
 		}
 		public char[] getContents() {
 			return mapper.getCUSource();
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java
index c5357b6..48abd65 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/Evaluator.java
@@ -25,6 +25,7 @@
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 
 /**
  * A evaluator builds a compilation unit and compiles it into class files.
@@ -53,7 +54,7 @@
  * are computed so that they correspond to the given problem. If it is found to be an internal problem,
  * then the evaluation id of the result is the given compilation unit source.
  */
-abstract protected void addEvaluationResultForCompilationProblem(Map resultsByIDs,IProblem problem, char[] cuSource);
+protected abstract void addEvaluationResultForCompilationProblem(Map resultsByIDs,IProblem problem, char[] cuSource);
 /**
  * Returns the evaluation results that converts the given compilation result that has problems.
  * If the compilation result has more than one problem, then the problems are broken down so that
@@ -100,7 +101,7 @@
 				}
 			}
 			if (result.hasErrors()) {
-				hasErrors = true;
+				this.hasErrors = true;
 			} else {
 				ClassFile[] classFiles = result.getClassFiles();
 				for (int i = 0; i < classFiles.length; i++) {
@@ -129,7 +130,7 @@
 	compiler.compile(new ICompilationUnit[] {new ICompilationUnit() {
 		public char[] getFileName() {
 			 // Name of class is name of CU
-			return CharOperation.concat(Evaluator.this.getClassName(), ".java".toCharArray()); //$NON-NLS-1$
+			return CharOperation.concat(Evaluator.this.getClassName(), SuffixConstants.SUFFIX_java); //$NON-NLS-1$
 		}
 		public char[] getContents() {
 			return source;
@@ -153,20 +154,20 @@
  * Returns the name of the current class. This is the simple name of the class.
  * This doesn't include the extension ".java" nor the name of the package.
  */
-abstract protected char[] getClassName();
+protected abstract char[] getClassName();
 /**
  * Creates and returns a compiler for this evaluator.
  */
-Compiler getCompiler(ICompilerRequestor requestor) {
+Compiler getCompiler(ICompilerRequestor compilerRequestor) {
 	return new Compiler(
 		this.environment, 
 		DefaultErrorHandlingPolicies.exitAfterAllProblems(), 
 		this.options, 
-		requestor, 
+		compilerRequestor, 
 		this.problemFactory);
 }
 /**
  * Builds and returns the source for the current compilation unit.
  */
-abstract protected char[] getSource();
+protected abstract char[] getSource();
 }
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesEvaluator.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesEvaluator.java
index 6489a0e..f23fbfd 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesEvaluator.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesEvaluator.java
@@ -140,13 +140,13 @@
  * @see org.eclipse.jdt.internal.eval.Evaluator
  */
 protected char[] getClassName() {
-	return CharOperation.concat(EvaluationContext.GLOBAL_VARS_CLASS_NAME_PREFIX, Integer.toString(EvaluationContext.VAR_CLASS_COUNTER + 1).toCharArray());
+	return CharOperation.concat(EvaluationConstants.GLOBAL_VARS_CLASS_NAME_PREFIX, Integer.toString(EvaluationContext.VAR_CLASS_COUNTER + 1).toCharArray());
 }
 /**
  * Creates and returns a compiler for this evaluator.
  */
-Compiler getCompiler(ICompilerRequestor requestor) {
-	Compiler compiler = super.getCompiler(requestor);
+Compiler getCompiler(ICompilerRequestor compilerRequestor) {
+	Compiler compiler = super.getCompiler(compilerRequestor);
 	
 	// Initialize the compiler's lookup environment with the already compiled super class
 	IBinaryType binaryType = this.context.getRootCodeSnippetBinary();
@@ -212,7 +212,7 @@
 	buffer.append(ROOT_CLASS_NAME);
 	buffer.append(" {").append(Util.LINE_SEPARATOR); //$NON-NLS-1$
 	lineNumberOffset++;
-	startPosOffset = buffer.length();
+	this.startPosOffset = buffer.length();
 
 	// field declarations
 	GlobalVariable[] vars = this.context.variables;
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesInfo.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesInfo.java
index c973607..99adde9 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesInfo.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/VariablesInfo.java
@@ -43,9 +43,10 @@
  */
 int indexOf(GlobalVariable var) {
 	for (int i = 0; i < this.variableCount; i++) {
-		if (var.equals(this.variables[i]))
+		if (var.equals(this.variables[i])) {
 			return i;
-	};
+		}
+	}
 	return -1;
 }
 /**
@@ -56,9 +57,10 @@
 	GlobalVariable[] vars = this.variables;
 	for (int i = 0; i < this.variableCount; i++) {
 		GlobalVariable var = vars[i];
-		if (CharOperation.equals(name, var.name))
+		if (CharOperation.equals(name, var.name)) {
 			return var;
-	};
+		}
+	}
 	return null;
 }
 }
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java
new file mode 100644
index 0000000..e41a598
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/CodeFormatter.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.core.formatter;
+
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ * Specification for a generic source code formatter. This is still subject to change.
+ * 
+ * @since 3.0
+ */
+public abstract class CodeFormatter {
+
+	/**
+	 * Unknown kind
+	 */
+	public static final int K_UNKNOWN = 0x00;
+
+	/**
+	 * Kind used to format an expression
+	 */
+	public static final int K_EXPRESSION = 0x01;
+	
+	/**
+	 * Kind used to format a set of statements
+	 */
+	public static final int K_STATEMENTS = 0x02;
+	
+	/**
+	 * Kind used to format a set of class body declarations
+	 */
+	public static final int K_CLASS_BODY_DECLARATIONS = 0x04;
+	
+	/**
+	 * Kind used to format a compilation unit
+	 */
+	public static final int K_COMPILATION_UNIT = 0x08;
+
+	/** 
+	 * Format <code>source</code>,
+	 * and returns a text edit that correspond to the difference between the given string and the formatted string.
+	 * It returns null if the given string cannot be formatted.
+	 * 
+	 * If the offset position is matching a whitespace, the result can include whitespaces. It would be up to the
+	 * caller to get rid of preceeding whitespaces.
+	 * 
+	 * @param kind Use to specify the kind of the code snippet to format. It can be any of these:
+	 * 		  K_EXPRESSION, K_STATEMENTS, K_CLASS_BODY_DECLARATIONS, K_COMPILATION_UNIT, K_UNKNOWN
+	 * @param source the source to format
+	 * @param offset the given offset to start recording the edits (inclusive).
+	 * @param length the given length to stop recording the edits (exclusive).
+	 * @param indentationLevel the initial indentation level, used 
+	 *      to shift left/right the entire source fragment. An initial indentation
+	 *      level of zero or below has no effect.
+	 * @param lineSeparator the line separator to use in formatted source,
+	 *     if set to <code>null</code>, then the platform default one will be used.
+	 * @return the text edit
+	 * @throws IllegalArgumentException if offset is lower than 0, length is lower than 0 or
+	 * length is greater than source length.
+	 */
+	public abstract TextEdit format(int kind, String source, int offset, int length, int indentationLevel, String lineSeparator);
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
new file mode 100644
index 0000000..439eb05
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java
@@ -0,0 +1,250 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.core.formatter;
+
+import java.util.Map;
+
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions;
+
+/**
+ * This is still subject to changes before 3.0.
+ * @since 3.0
+ */
+public class DefaultCodeFormatterConstants {
+
+	public static final String END_OF_LINE = "end_of_line";						//$NON-NLS-1$
+	public static final String FALSE = "false"; 										//$NON-NLS-1$
+	/**
+	 * if bit set, then alignment will be non-optional (default is optional)
+	 */
+	public static final String FORMATTER_ALIGNMENT_FORCE = "1";//$NON-NLS-1$
+	public static final String FORMATTER_ALLOCATION_EXPRESSION_ARGUMENTS_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.allocation_expression_arguments_alignment";	//$NON-NLS-1$
+	public static final String FORMATTER_ANONYMOUS_TYPE_DECLARATION_BRACE_POSITION = JavaCore.PLUGIN_ID + ".formatter.anonymous_type_declaration_brace_position";	//$NON-NLS-1$
+	public static final String FORMATTER_ARRAY_INITIALIZER_BRACE_POSITION = JavaCore.PLUGIN_ID + ".formatter.array_initializer_brace_position";	//$NON-NLS-1$
+	public static final String FORMATTER_ARRAY_INITIALIZER_CONTINUATION_INDENTATION = JavaCore.PLUGIN_ID + ".formatter.array_initializer_continuation_indentation";	//$NON-NLS-1$
+	public static final String FORMATTER_ARRAY_INITIALIZER_EXPRESSIONS_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.array_initializer_expressions_alignment";	//$NON-NLS-1$
+	public static final String FORMATTER_BINARY_EXPRESSION_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.binary_expression_alignment";	//$NON-NLS-1$
+	public static final String FORMATTER_BLANK_LINES_AFTER_IMPORTS = JavaCore.PLUGIN_ID + ".formatter.blank_lines_after_imports";	//$NON-NLS-1$
+	public static final String FORMATTER_BLANK_LINES_AFTER_PACKAGE = JavaCore.PLUGIN_ID + ".formatter.blank_lines_after_package";	//$NON-NLS-1$
+	public static final String FORMATTER_BLANK_LINES_BEFORE_FIELD = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_field";	//$NON-NLS-1$
+	public static final String FORMATTER_BLANK_LINES_BEFORE_FIRST_CLASS_BODY_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_first_class_body_declaration";	//$NON-NLS-1$
+	public static final String FORMATTER_BLANK_LINES_BEFORE_IMPORTS = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_imports";	//$NON-NLS-1$
+	public static final String FORMATTER_BLANK_LINES_BEFORE_MEMBER_TYPE = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_member_type";	//$NON-NLS-1$
+	public static final String FORMATTER_BLANK_LINES_BEFORE_METHOD = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_method";	//$NON-NLS-1$
+	public static final String FORMATTER_BLANK_LINES_BEFORE_NEW_CHUNK = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_new_chunk";	//$NON-NLS-1$
+	public static final String FORMATTER_BLANK_LINES_BEFORE_PACKAGE = JavaCore.PLUGIN_ID + ".formatter.blank_lines_before_package";	//$NON-NLS-1$
+	public static final String FORMATTER_BLOCK_BRACE_POSITION = JavaCore.PLUGIN_ID + ".formatter.block_brace_position";	//$NON-NLS-1$
+	public static final String FORMATTER_COMPACT_ELSE_IF = JavaCore.PLUGIN_ID + ".formatter.compact_else_if";	//$NON-NLS-1$
+	/** foobar(<ul>
+	 * <li>    #fragment1, #fragment2,  </li>
+	 * <li>     #fragment5, #fragment4, </li>
+	 * </ul>
+	 */
+	public static final String FORMATTER_COMPACT_FIRST_BREAK_SPLIT = "32";//$NON-NLS-1$
+	public static final String FORMATTER_COMPACT_IF_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.compact_if_alignment";	//$NON-NLS-1$
+	/** foobar(#fragment1, #fragment2, <ul>
+	 *  <li>    #fragment3, #fragment4 </li>
+	 * </ul>
+	 */
+	public static final String FORMATTER_COMPACT_SPLIT = "16";//$NON-NLS-1$
+	public static final String FORMATTER_CONDITIONAL_EXPRESSION_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.conditional_expression_alignment";	//$NON-NLS-1$
+	public static final String FORMATTER_CONTINUATION_INDENTATION = JavaCore.PLUGIN_ID + ".formatter.continuation_indentation";	//$NON-NLS-1$
+	public static final String FORMATTER_EXPLICIT_CONSTRUCTOR_ARGUMENTS_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.explicit_constructor_arguments_alignment";	//$NON-NLS-1$
+	public static final String FORMATTER_FILLING_SPACE = JavaCore.PLUGIN_ID + ".formatter.filling_space";	//$NON-NLS-1$
+	public static final String FORMATTER_FORMAT_GUARDIAN_CLAUSE_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.format_guardian_clause_on_one_line";	//$NON-NLS-1$
+	public static final String FORMATTER_INDENT_BLOCK_STATEMENTS = JavaCore.PLUGIN_ID + ".formatter.indent_block_statements"; //$NON-NLS-1$
+	public static final String FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_TYPE_HEADER = JavaCore.PLUGIN_ID + ".formatter.indent_body_declarations_compare_to_type_header";	//$NON-NLS-1$
+	public static final String FORMATTER_INDENT_BREAKS_COMPARE_TO_CASES = JavaCore.PLUGIN_ID + ".formatter.indent_breaks_compare_to_cases";	//$NON-NLS-1$
+	/**
+	 * if bit set, broken fragments will be indented one level below current (not using continuation indentation)
+	 */
+	public static final String FORMATTER_INDENT_BY_ONE = "4";//$NON-NLS-1$
+	/**
+	 * if bit set, broken fragments will be aligned on current location column (default is to break at current indentation level)
+	 */
+	public static final String FORMATTER_INDENT_ON_COLUMN = "2";//$NON-NLS-1$
+	public static final String FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES = JavaCore.PLUGIN_ID + ".formatter.indent_switchstatements_compare_to_cases";	//$NON-NLS-1$
+	public static final String FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH = JavaCore.PLUGIN_ID + ".formatter.indent_switchstatements_compare_to_switch";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_NEW_LINE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_before_closing_brace_in_array_initializer";//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_NEW_LINE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_after_opening_brace_in_array_initializer";//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_NEW_LINE_IN_CONTROL_STATEMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_control_statements";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANONYMOUS_TYPE_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_anonymous_type_declaration";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_block";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_method_body";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION = JavaCore.PLUGIN_ID + ".formatter.insert_new_line_in_empty_type_declaration";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATORS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_assignment_operators";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_binary_operator";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_BLOCK_CLOSE_BRACE = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_block_close_brace";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_CLOSING_PAREN_IN_CAST = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_closing_paren_in_cast";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COLON_IN_ASSERT = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_colon_in_assert";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COLON_IN_CONDITIONAL = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_colon_in_conditional";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COLON_IN_LABELED_STATEMENT = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_colon_in_labeled_statement";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ALLOCATION_EXPRESSION = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_allocation_expression";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_array_initializer";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_constructor_arguments";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_THROWS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_constructor_throws";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_EXPLICITCONSTRUCTORCALL_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_explicitconstructorcall_arguments";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_FOR_INCREMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_for_increments";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_FOR_INITS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_for_inits";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MESSAGESEND_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_messagesend_arguments";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_METHOD_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_method_arguments";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_METHOD_THROWS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_method_throws";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_multiple_field_declarations";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma_in_multiple_local_declarations";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_SUPERINTERFACES = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_comma__in_superinterfaces";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_OPEN_PAREN_IN_PARENTHESIZED_EXPRESSION = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_open_paren_in_parenthesized_expression"; //$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CAST = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_opening_paren_in_cast";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_POSTFIX_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_postfix_operator";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_PREFIX_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_prefix_operator";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_QUESTION_IN_CONDITIONAL = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_question_in_conditional";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_SEMICOLON_IN_FOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_semicolon_in_for";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_AFTER_UNARY_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_after_unary_operator";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_ANONYMOUS_TYPE_OPEN_BRACE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_anonymous_type_open_brace"; 	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATORS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_assignment_operators";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_binary_operator";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_BLOCK_OPEN_BRACE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_block_open_brace";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_BRACKET_IN_ARRAY_REFERENCE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_bracket_in_array_reference";//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_BRACKET_IN_ARRAY_TYPE_REFERENCE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_bracket_in_array_type_reference";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_CATCH_EXPRESSION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_catch_expression";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_closing_brace_in_array_initializer";		//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CAST = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_cast";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_PARENTHESIZED_EXPRESSION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_closing_paren_in_parenthesized_expression"; //$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_ASSERT = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_assert";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_CASE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_case";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_CONDITIONAL = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_conditional";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_DEFAULT = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_default";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_LABELED_STATEMENT = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_colon_in_labeled_statement";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ALLOCATION_EXPRESSION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_allocation_expression";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_array_initializer";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_constructor_arguments";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_THROWS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_constructor_throws";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_EXPLICITCONSTRUCTORCALL_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_explicitconstructorcall_arguments";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INCREMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_for_increments";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INITS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_for_inits";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MESSAGESEND_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_messagesend_arguments";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_method_arguments";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_THROWS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_method_throws";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_multiple_field_declarations";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma_in_multiple_local_declarations";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_SUPERINTERFACES = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_comma__in_superinterfaces";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_FIRST_ARGUMENT = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_first_argument";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_FIRST_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_first_initializer";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_FOR_PAREN = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_for_paren";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_IF_CONDITION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_if_condition";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_MESSAGE_SEND = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_message_send";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_METHOD_DECLARATION_OPEN_PAREN = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_method_declaration_open_paren";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_METHOD_OPEN_BRACE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_method_open_brace";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPEN_PAREN_IN_PARENTHESIZED_EXPRESSION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_open_paren_in_parenthesized_expression"; //$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_opening_brace_in_array_initializer"; //$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_POSTFIX_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_postfix_operator";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_PREFIX_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_prefix_operator";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_QUESTION_IN_CONDITIONAL = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_question_in_conditional";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_SEMICOLON = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_semicolon";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_SWITCH_CONDITION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_switch_condition";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_SWITCH_OPEN_BRACE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_switch_open_brace";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_SYNCHRONIZED_CONDITION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_synchronized_condition";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_TYPE_OPEN_BRACE = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_type_open_brace";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_UNARY_OPERATOR = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_unary_operator";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BEFORE_WHILE_CONDITION = JavaCore.PLUGIN_ID + ".formatter.insert_space_before_while_condition";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_REFERENCE = JavaCore.PLUGIN_ID + ".formatter.insert_space_between_brackets_in_array_reference";//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_TYPE_REFERENCE = JavaCore.PLUGIN_ID + ".formatter.insert_space_between_brackets_in_array_type_reference";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_ARGUMENTS = JavaCore.PLUGIN_ID + ".formatter.inset_space_between_empty_arguments";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_ARRAY_INITIALIZER = JavaCore.PLUGIN_ID + ".formatter.insert_space_between_empty_array_initializer";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_IN_CATCH_EXPRESSION = JavaCore.PLUGIN_ID + ".formatter.insert_space_in_catch_expression";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_IN_FOR_PARENS = JavaCore.PLUGIN_ID + ".formatter.insert_space_in_for_parens";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_IN_IF_CONDITION = JavaCore.PLUGIN_ID + ".formatter.insert_space_in_if_condition";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_IN_SWITCH_CONDITION = JavaCore.PLUGIN_ID + ".formatter.insert_space_in_switch_condition";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_IN_SYNCHRONIZED_CONDITION = JavaCore.PLUGIN_ID + ".formatter.insert_space_in_synchronized_condition";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_IN_WHILE_CONDITION = JavaCore.PLUGIN_ID + ".formatter.insert_space_in_while_condition";	//$NON-NLS-1$
+	public static final String FORMATTER_INSERT_SPACE_WITHIN_MESSAGE_SEND = JavaCore.PLUGIN_ID + ".formatter.insert_space_within_message_send";	//$NON-NLS-1$
+	public static final String FORMATTER_KEEP_ELSE_STATEMENT_ON_SAME_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_else_statement_on_same_line"; //$NON-NLS-1$
+	public static final String FORMATTER_KEEP_SIMPLE_IF_ON_ONE_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_imple_if_on_one_line"; //$NON-NLS-1$
+	public static final String FORMATTER_KEEP_THEN_STATEMENT_ON_SAME_LINE = JavaCore.PLUGIN_ID + ".formatter.keep_then_statement_on_same_line";//$NON-NLS-1$
+	public static final String FORMATTER_LINE_SPLIT = JavaCore.PLUGIN_ID + ".formatter.lineSplit"; //$NON-NLS-1$
+	public static final String FORMATTER_MESSAGE_SEND_ARGUMENTS_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.message_send_arguments_alignment";	//$NON-NLS-1$
+	public static final String FORMATTER_MESSAGE_SEND_SELECTOR_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.message_send_selector_alignment";	//$NON-NLS-1$
+	public static final String FORMATTER_METHOD_DECLARATION_ARGUMENTS_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.method_declaration_arguments_alignment";	//$NON-NLS-1$
+	public static final String FORMATTER_METHOD_DECLARATION_BRACE_POSITION = JavaCore.PLUGIN_ID + ".formatter.method_declaration_brace_position";	//$NON-NLS-1$
+	public static final String FORMATTER_METHOD_THROWS_CLAUSE_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.method_throws_clause_alignment";	//$NON-NLS-1$
+	/** 
+	 * <table BORDER COLS=4 WIDTH="100%" >
+	 * <tr><td>#fragment1A</td>            <td>#fragment2A</td>       <td>#fragment3A</td>  <td>#very-long-fragment4A</td></tr>
+	 * <tr><td>#fragment1B</td>            <td>#long-fragment2B</td>  <td>#fragment3B</td>  <td>#fragment4B</td></tr>
+	 * <tr><td>#very-long-fragment1C</td>  <td>#fragment2C</td>       <td>#fragment3C</td>  <td>#fragment4C</td></tr>
+	 * </table>
+	 */
+	public static final String FORMATTER_MULTICOLUMN = "256"; //$NON-NLS-1$
+	public static final String FORMATTER_MULTIPLE_FIELDS_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.multiple_fields_alignment";//$NON-NLS-1$
+	/** foobar(#fragment1, <ul>
+	 * <li>      #fragment2,  </li>
+	 * <li>      #fragment3 </li>
+	 * <li>      #fragment4,  </li>
+	 * </ul>
+	 */
+	public static final String FORMATTER_NEXT_PER_LINE_SPLIT = "80"; //$NON-NLS-1$
+	/** 
+	 * foobar(<ul>
+	 * <li>     #fragment1,  </li>
+	 * <li>        #fragment2,  </li>
+	 * <li>        #fragment3 </li>
+	 * <li>        #fragment4,  </li>
+	 * </ul>
+	 */ 
+	public static final String FORMATTER_NEXT_SHIFTED_SPLIT = "64";//$NON-NLS-1$
+
+	public static final String FORMATTER_NO_ALIGNMENT = "0";//$NON-NLS-1$
+	public static final String FORMATTER_NUMBER_OF_BLANK_LINES_TO_INSERT_AT_BEGINNING_OF_METHOD_BODY = JavaCore.PLUGIN_ID + ".formatter.number_of_blank_lines_to_insert_at_beginning_of_method_body"; //$NON-NLS-1$
+	public static final String FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE = JavaCore.PLUGIN_ID + ".formatter.number_of_empty_lines_to_preserve";	//$NON-NLS-1$
+	/** foobar(<ul>
+	 * <li>     #fragment1,  </li>
+	 * <li>     #fragment2,  </li>
+	 * <li>     #fragment3 </li>
+	 * <li>     #fragment4,  </li>
+	 * </ul>
+	 */
+	public static final String FORMATTER_ONE_PER_LINE_SPLIT = "48";//$NON-NLS-1$
+	public static final String FORMATTER_PRESERVE_USER_LINEBREAKS = JavaCore.PLUGIN_ID + ".formatter.preserve_user_linebreaks";//$NON-NLS-1$
+	public static final String FORMATTER_PUT_EMPTY_STATEMENT_ON_NEW_LINE = JavaCore.PLUGIN_ID + ".formatter.put_empty_statement_on_new_line";	//$NON-NLS-1$
+	public static final String FORMATTER_QUALIFIED_ALLOCATION_EXPRESSION_ARGUMENTS_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.qualified_allocation_expression_arguments_alignment";	//$NON-NLS-1$
+	public static final String FORMATTER_SWITCH_BRACE_POSITION = JavaCore.PLUGIN_ID + ".formatter.switch_brace_position";	//$NON-NLS-1$
+	public static final String FORMATTER_TAB_CHAR = JavaCore.PLUGIN_ID + ".formatter.tabulation.char"; //$NON-NLS-1$
+	public static final String FORMATTER_TAB_SIZE = JavaCore.PLUGIN_ID + ".formatter.tabulation.size"; //$NON-NLS-1$
+	public static final String FORMATTER_TYPE_DECLARATION_BRACE_POSITION = JavaCore.PLUGIN_ID + ".formatter.type_declaration_brace_position";	//$NON-NLS-1$
+	public static final String FORMATTER_TYPE_DECLARATION_SUPERCLASS_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.type_declaration_superclass_alignment";	//$NON-NLS-1$
+	public static final String FORMATTER_TYPE_DECLARATION_SUPERINTERFACES_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.type_declaration_superinterfaces_alignment";	//$NON-NLS-1$
+	public static final String FORMATTER_TYPE_MEMBER_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.type_member_alignment";	//$NON-NLS-1$
+
+	public static final String NEXT_LINE = "next_line"; //$NON-NLS-1$
+	public static final String NEXT_LINE_SHIFTED = "next_line_shifted";	//$NON-NLS-1$
+	public static final String TRUE = "true"; 											//$NON-NLS-1$
+
+	/**
+	 * <p>Returns the default settings.</p>
+	 * 
+	 * <p>This is subject to change before 3.0.</p>
+	 * @since 3.0
+	 */
+	public static Map getDefaultSettings() {
+		return DefaultCodeFormatterOptions.getDefaultSettings().getMap();
+	}
+
+	/**
+	 * <p>Returns the settings according to the Java conventions.</p>
+	 * 
+	 * <p>This is subject to change before 3.0.</p>
+	 * @since 3.0
+	 */
+	public static Map getJavaConventionsSettings() {
+		return DefaultCodeFormatterOptions.getJavaConventionsSettings().getMap();
+	}
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/AbortFormatting.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/AbortFormatting.java
new file mode 100644
index 0000000..987b905
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/AbortFormatting.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2003 International Business Machines 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 API and implementation
+ ******************************************************************************/
+package org.eclipse.jdt.internal.formatter;
+
+/**
+ * Unchecked exception wrapping invalid input checked exception which may occur
+ * when scanning original formatted source. 
+ * 
+ * @since 2.1
+ */
+public class AbortFormatting extends RuntimeException {
+
+	Throwable nestedException;
+	
+	public AbortFormatting(String message) {
+		super(message);
+	}
+	public AbortFormatting(Throwable nestedException) {
+		super(nestedException.getMessage());
+		this.nestedException = nestedException;
+	}
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/BinaryExpressionFragmentBuilder.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/BinaryExpressionFragmentBuilder.java
new file mode 100644
index 0000000..2aa7f88
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/BinaryExpressionFragmentBuilder.java
@@ -0,0 +1,423 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2003 International Business Machines 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 API and implementation
+ ******************************************************************************/
+package org.eclipse.jdt.internal.formatter;
+
+import java.util.ArrayList;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
+import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
+import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
+import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.Assignment;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
+import org.eclipse.jdt.internal.compiler.ast.CastExpression;
+import org.eclipse.jdt.internal.compiler.ast.CharLiteral;
+import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
+import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
+import org.eclipse.jdt.internal.compiler.ast.DoubleLiteral;
+import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.ExtendedStringLiteral;
+import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.FloatLiteral;
+import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
+import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
+import org.eclipse.jdt.internal.compiler.ast.LongLiteral;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression;
+import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.PostfixExpression;
+import org.eclipse.jdt.internal.compiler.ast.PrefixExpression;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.jdt.internal.compiler.ast.SuperReference;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
+import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+class BinaryExpressionFragmentBuilder
+	extends ASTVisitor {
+		
+	ArrayList fragmentsList;
+	ArrayList operatorsList;
+	private int realFragmentsSize;
+
+	BinaryExpressionFragmentBuilder() {
+		this.fragmentsList = new ArrayList();
+		this.operatorsList = new ArrayList();
+		this.realFragmentsSize = 0;
+	}
+
+	private final void addRealFragment(ASTNode node) {
+		this.fragmentsList.add(node);
+		this.realFragmentsSize++;
+	}
+	
+	private final void addSmallFragment(ASTNode node) {
+		this.fragmentsList.add(node);
+	}
+
+	private boolean buildFragments(Expression expression) {
+		if (((expression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) {
+			addRealFragment(expression);
+			return false;
+		} else {
+			return true;
+		}
+	}
+
+	public ASTNode[] fragments() {
+		ASTNode[] fragments = new ASTNode[this.fragmentsList.size()];
+		this.fragmentsList.toArray(fragments);
+		return fragments;
+	}
+	
+	public int[] operators() {
+		int length = operatorsList.size();
+		int[] tab = new int[length];
+		for (int i = 0; i < length; i++) {
+			tab[i] = ((Integer)operatorsList.get(i)).intValue();
+		}
+		return tab;
+	}
+
+	public int realFragmentsSize() {
+		return this.realFragmentsSize;
+	}
+	
+	public boolean visit(
+		AllocationExpression allocationExpression,
+		BlockScope scope) {
+			this.addRealFragment(allocationExpression);
+			return false;
+	}
+
+	public boolean visit(
+		AND_AND_Expression and_and_Expression,
+		BlockScope scope) {
+			if (buildFragments(and_and_Expression)) {
+				this.operatorsList.add(new Integer(TerminalTokens.TokenNameAND_AND));
+				return true;
+			} else {
+				return false;
+			}
+	}
+
+	public boolean visit(
+		ArrayAllocationExpression arrayAllocationExpression,
+		BlockScope scope) {
+			this.addRealFragment(arrayAllocationExpression);
+			return false;
+	}
+
+	public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) {
+		this.addRealFragment(arrayInitializer);
+		return false;
+	}
+	
+	public boolean visit(
+		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+		BlockScope scope) {
+			this.addRealFragment(arrayQualifiedTypeReference);
+			return false;
+	}
+
+	public boolean visit(
+		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+		ClassScope scope) {
+			this.addRealFragment(arrayQualifiedTypeReference);
+			return false;
+	}
+
+	public boolean visit(ArrayReference arrayReference, BlockScope scope) {
+		this.addRealFragment(arrayReference);
+		return false;
+	}
+
+	public boolean visit(
+		ArrayTypeReference arrayTypeReference,
+		BlockScope scope) {
+			this.addRealFragment(arrayTypeReference);
+			return false;
+	}
+
+	public boolean visit(
+		ArrayTypeReference arrayTypeReference,
+		ClassScope scope) {
+			this.addRealFragment(arrayTypeReference);
+			return false;
+	}
+
+	public boolean visit(Assignment assignment, BlockScope scope) {
+		this.addRealFragment(assignment);
+		return false;
+	}
+
+	public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
+		final int numberOfParens = (binaryExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			this.addRealFragment(binaryExpression);
+		} else {
+			switch((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) {
+				case OperatorIds.PLUS :
+					if (buildFragments(binaryExpression)) {
+						binaryExpression.left.traverse(this, scope);
+						this.operatorsList.add(new Integer(TerminalTokens.TokenNamePLUS));
+						binaryExpression.right.traverse(this, scope);
+					}
+					return false;
+				case OperatorIds.MINUS :
+					if (buildFragments(binaryExpression)) {
+						binaryExpression.left.traverse(this, scope);
+						this.operatorsList.add(new Integer(TerminalTokens.TokenNameMINUS));
+						binaryExpression.right.traverse(this, scope);
+					}
+					return false;
+				case OperatorIds.MULTIPLY :
+					if (buildFragments(binaryExpression)) {
+						binaryExpression.left.traverse(this, scope);
+						this.operatorsList.add(new Integer(TerminalTokens.TokenNameMULTIPLY));
+						binaryExpression.right.traverse(this, scope);
+					}
+					return false;
+				case OperatorIds.REMAINDER :
+					if (buildFragments(binaryExpression)) {
+						binaryExpression.left.traverse(this, scope);
+						this.operatorsList.add(new Integer(TerminalTokens.TokenNameREMAINDER));
+						binaryExpression.right.traverse(this, scope);
+					}
+					return false;
+				case OperatorIds.XOR :
+					if (buildFragments(binaryExpression)) {
+						binaryExpression.left.traverse(this, scope);
+						this.operatorsList.add(new Integer(TerminalTokens.TokenNameXOR));
+						binaryExpression.right.traverse(this, scope);
+					}
+					return false;
+				case OperatorIds.DIVIDE :
+					if (buildFragments(binaryExpression)) {
+						binaryExpression.left.traverse(this, scope);
+						this.operatorsList.add(new Integer(TerminalTokens.TokenNameDIVIDE));
+						binaryExpression.right.traverse(this, scope);
+					}
+					return false;
+				case OperatorIds.OR :
+					if (buildFragments(binaryExpression)) {
+						binaryExpression.left.traverse(this, scope);
+						this.operatorsList.add(new Integer(TerminalTokens.TokenNameOR));
+						binaryExpression.right.traverse(this, scope);
+					}
+					return false;
+				case OperatorIds.AND :
+					if (buildFragments(binaryExpression)) {
+						binaryExpression.left.traverse(this, scope);
+						this.operatorsList.add(new Integer(TerminalTokens.TokenNameAND));
+						binaryExpression.right.traverse(this, scope);
+					}
+					return false;
+				default:
+					this.addRealFragment(binaryExpression);
+			}
+		}
+		return false;
+	}
+
+	public boolean visit(CastExpression castExpression, BlockScope scope) {
+		this.addRealFragment(castExpression);
+		return false;
+	}
+
+	public boolean visit(CharLiteral charLiteral, BlockScope scope) {
+		this.addSmallFragment(charLiteral);
+		return false;
+	}
+
+	public boolean visit(
+		CompoundAssignment compoundAssignment,
+		BlockScope scope) {
+			this.addRealFragment(compoundAssignment);
+			return false;
+	}
+
+	public boolean visit(
+		ConditionalExpression conditionalExpression,
+		BlockScope scope) {
+			this.addRealFragment(conditionalExpression);
+			return false;
+	}
+
+	public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {
+		this.addSmallFragment(doubleLiteral);
+		return false;
+	}
+
+	public boolean visit(EqualExpression equalExpression, BlockScope scope) {
+		this.addRealFragment(equalExpression);
+		return false;
+	}
+
+	public boolean visit(
+		ExtendedStringLiteral extendedStringLiteral,
+		BlockScope scope) {
+			this.addRealFragment(extendedStringLiteral);
+			return false;
+	}
+
+	public boolean visit(FalseLiteral falseLiteral, BlockScope scope) {
+		this.addSmallFragment(falseLiteral);
+		return false;
+	}
+
+	public boolean visit(FieldReference fieldReference, BlockScope scope) {
+		this.addRealFragment(fieldReference);
+		return false;
+	}
+
+	public boolean visit(FloatLiteral floatLiteral, BlockScope scope) {
+		this.addSmallFragment(floatLiteral);
+		return false;
+	}
+
+	public boolean visit(
+		InstanceOfExpression instanceOfExpression,
+		BlockScope scope) {
+			this.addRealFragment(instanceOfExpression);
+			return false;
+	}
+
+	public boolean visit(IntLiteral intLiteral, BlockScope scope) {
+		this.addSmallFragment(intLiteral);
+		return false;
+	}
+
+	public boolean visit(LongLiteral longLiteral, BlockScope scope) {
+		this.addSmallFragment(longLiteral);
+		return false;
+	}
+
+	public boolean visit(MessageSend messageSend, BlockScope scope) {
+		this.addRealFragment(messageSend);
+		return false;
+	}
+
+	public boolean visit(NullLiteral nullLiteral, BlockScope scope) {
+		this.addRealFragment(nullLiteral);
+		return false;
+	}
+
+	public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+		if (buildFragments(or_or_Expression)) {
+			this.operatorsList.add(new Integer(TerminalTokens.TokenNameOR_OR));
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	public boolean visit(
+		PostfixExpression postfixExpression,
+		BlockScope scope) {
+			this.addRealFragment(postfixExpression);
+			return false;
+	}
+
+	public boolean visit(PrefixExpression prefixExpression, BlockScope scope) {
+		this.addRealFragment(prefixExpression);
+		return false;
+	}
+
+	public boolean visit(
+		QualifiedAllocationExpression qualifiedAllocationExpression,
+		BlockScope scope) {
+			this.addRealFragment(qualifiedAllocationExpression);
+			return false;
+	}
+	public boolean visit(
+		QualifiedNameReference qualifiedNameReference,
+		BlockScope scope) {
+			this.addRealFragment(qualifiedNameReference);
+			return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+			QualifiedSuperReference qualifiedSuperReference,
+			BlockScope scope) {
+		this.addRealFragment(qualifiedSuperReference);
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+			QualifiedThisReference qualifiedThisReference,
+			BlockScope scope) {
+		this.addRealFragment(qualifiedThisReference);
+		return false;
+	}
+
+	public boolean visit(
+		SingleNameReference singleNameReference,
+		BlockScope scope) {
+			this.addRealFragment(singleNameReference);
+			return false;
+	}
+
+	public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
+		this.addRealFragment(stringLiteral);
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SuperReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(SuperReference superReference, BlockScope scope) {
+		this.addRealFragment(superReference);
+		return false;
+	}
+
+	public boolean visit(ThisReference thisReference, BlockScope scope) {
+		this.addRealFragment(thisReference);
+		return false;
+	}
+
+	public boolean visit(TrueLiteral trueLiteral, BlockScope scope) {
+		this.addSmallFragment(trueLiteral);
+		return false;
+	}
+
+	public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
+		this.addRealFragment(unaryExpression);
+		return false;
+	}
+
+	public int size() {
+		return this.fragmentsList.size();
+	}
+
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CascadingMethodInvocationFragmentBuilder.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CascadingMethodInvocationFragmentBuilder.java
new file mode 100644
index 0000000..7b967c6
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CascadingMethodInvocationFragmentBuilder.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2003 International Business Machines 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 API and implementation
+ ******************************************************************************/
+package org.eclipse.jdt.internal.formatter;
+
+import java.util.ArrayList;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+
+class CascadingMethodInvocationFragmentBuilder
+	extends ASTVisitor {
+		
+	ArrayList fragmentsList;
+
+	CascadingMethodInvocationFragmentBuilder() {
+		this.fragmentsList = new ArrayList();
+	}
+
+	public MessageSend[] fragments() {
+		MessageSend[] fragments = new MessageSend[this.fragmentsList.size()];
+		this.fragmentsList.toArray(fragments);
+		return fragments;
+	}
+
+	public int size() {
+		return this.fragmentsList.size();
+	}
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.MessageSend, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(MessageSend messageSend, BlockScope scope) {
+		if ((messageSend.receiver.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT == 0) {
+			if (messageSend.receiver instanceof MessageSend) {
+				this.fragmentsList.add(0, messageSend);
+				messageSend.receiver.traverse(this, scope);
+				return false;
+			}
+			this.fragmentsList.add(0, messageSend);
+			this.fragmentsList.add(1, messageSend);
+		} else {
+			this.fragmentsList.add(0, messageSend);
+			this.fragmentsList.add(1, messageSend);
+		}
+		return false;
+	}
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatter.java
index a7c310f..1fde62e 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatter.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatter.java
@@ -17,10 +17,11 @@
 import java.util.Locale;
 import java.util.Map;
 
-import org.eclipse.jdt.core.ICodeFormatter;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.ConfigurableOption;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 import org.eclipse.jdt.internal.formatter.impl.FormatterOptions;
@@ -31,6 +32,7 @@
  * <li>Use the method <code>void format(aString)</code>
  * on this instance to format <code>aString</code>.
  * It will return the formatted string.</ul>
+ * @deprecated 
 */
 public class CodeFormatter implements TerminalTokens, ICodeFormatter {
 
@@ -144,12 +146,12 @@
 	 */
 	public CodeFormatter(Map settings) {
 		// initialize primary and secondary scanners
-		scanner = new Scanner(true /*comment*/, true /*whitespace*/, false /*nls*/, false /*assert*/, null /*taskTags*/, null/*taskPriorities*/); // regular scanner for forming lines
+		scanner = new Scanner(true /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/); // regular scanner for forming lines
 		// to record positions of the beginning of lines.
 		scanner.recordLineSeparator = true;
 
 		// secondary scanner to split long lines formed by primary scanning
-		splitScanner = new Scanner(true /*comment*/, true /*whitespace*/, false /*nls*/, false /*assert*/, null /*taskTags*/, null/*taskPriorities*/);
+		splitScanner = new Scanner(true /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/);
 
 		this.options = new FormatterOptions(settings);
 	}
@@ -367,7 +369,7 @@
 					}
 					token = 0;
 				}
-				if (token == Scanner.TokenNameEOF)
+				if (token == TerminalTokens.TokenNameEOF)
 					break;
 
 				/* ## MODIFYING the indentation level before generating new lines
@@ -376,7 +378,7 @@
 
 				// Removes all the indentations made by statements not followed by a block
 				// except if the current token is ELSE, CATCH or if we are in a switch/case
-				if (clearNonBlockIndents && (token != Scanner.TokenNameWHITESPACE)) {
+				if (clearNonBlockIndents && (token != TerminalTokens.TokenNameWHITESPACE)) {
 					switch (token) {
 						case TokenNameelse :
 							if (constructionsCount > 0
@@ -410,10 +412,10 @@
 				if (token == TokenNamecase || token == TokenNamedefault) {
 					indentationLevel += pop(TokenNamecase);
 				}
-				if (token == Scanner.TokenNamethrows) {
+				if (token == TerminalTokens.TokenNamethrows) {
 					inThrowsClause = true;
 				}
-				if ((token == Scanner.TokenNameclass || token == Scanner.TokenNameinterface) && previousToken != Scanner.TokenNameDOT) {
+				if ((token == TerminalTokens.TokenNameclass || token == TerminalTokens.TokenNameinterface) && previousToken != TerminalTokens.TokenNameDOT) {
 					inClassOrInterfaceHeader = true;
 				}
 
@@ -438,7 +440,7 @@
 				pendingNewlineAfterParen =
 					pendingNewlineAfterParen
 						|| (previousCompilableToken == TokenNameRPAREN && token == TokenNameLBRACE);
-				if (pendingNewlineAfterParen && token != Scanner.TokenNameWHITESPACE) {
+				if (pendingNewlineAfterParen && token != TerminalTokens.TokenNameWHITESPACE) {
 					pendingNewlineAfterParen = false;
 
 					// Do to add a newline & indent sequence if the current token is an
@@ -506,7 +508,7 @@
 				if (((pendingNewLines > 0 && (!isComment(token)))
 					|| (newLinesInWhitespace > 0 && (openParenthesisCount <= 1 && isComment(token)))
 					|| (previousCompilableToken == TokenNameLBRACE && token == TokenNameRBRACE))
-					&& token != Scanner.TokenNameWHITESPACE) {
+					&& token != TerminalTokens.TokenNameWHITESPACE) {
 
 					// Do not add newline & indent between an adjoining close brace and
 					// close paren.  Anonymous inner classes may use this form.
@@ -530,7 +532,7 @@
 
 					// Do not add a new line & indent between a multiline comment and a opening brace
 					boolean commentAndOpenBrace =
-						previousToken == Scanner.TokenNameCOMMENT_BLOCK && token == TokenNameLBRACE;
+						previousToken == TerminalTokens.TokenNameCOMMENT_BLOCK && token == TokenNameLBRACE;
 
 					// Do not add a newline & indent between a close brace and a colon (in array assignments, for example).
 					boolean commaAndCloseBrace =
@@ -577,8 +579,8 @@
 							}
 						} else {
 							// see PR 1FKKC3U: LFCOM:WINNT - Format problem with a comment before the ';'
-							if (!((previousToken == Scanner.TokenNameCOMMENT_BLOCK
-								|| previousToken == Scanner.TokenNameCOMMENT_JAVADOC)
+							if (!((previousToken == TerminalTokens.TokenNameCOMMENT_BLOCK
+								|| previousToken == TerminalTokens.TokenNameCOMMENT_JAVADOC)
 								&& token == TokenNameSEMICOLON)) {
 								newLine(pendingNewLines);
 							}
@@ -591,7 +593,7 @@
 							indentationOffset = -1;
 							indentationLevel += popExclusiveUntilBlock();
 						}
-						if (previousToken == Scanner.TokenNameCOMMENT_LINE && inAssignment) {
+						if (previousToken == TerminalTokens.TokenNameCOMMENT_LINE && inAssignment) {
 							// PR 1FI5IPO
 							currentLineIndentationLevel++;
 						} else {
@@ -839,18 +841,18 @@
 					case TokenNameEQUAL :
 						inAssignment = true;
 						break;
-					case Scanner.TokenNameCOMMENT_LINE :
+					case TerminalTokens.TokenNameCOMMENT_LINE :
 						pendingNewLines = 1;
 						if (inAssignment) {
 							currentLineIndentationLevel++;
 						}
 						break; // a line is always inserted after a one-line comment
-					case Scanner.TokenNameCOMMENT_JAVADOC :
-					case Scanner.TokenNameCOMMENT_BLOCK :
+					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+					case TerminalTokens.TokenNameCOMMENT_BLOCK :
 						currentCommentOffset = getCurrentCommentOffset();
 						pendingNewLines = 1;
 						break;
-					case Scanner.TokenNameWHITESPACE :
+					case TerminalTokens.TokenNameWHITESPACE :
 
 						// Count the number of line terminators in the whitespace so
 						// line spacing can be preserved near comments.
@@ -894,7 +896,7 @@
 						break;
 				}
 				// Do not output whitespace tokens.
-				if (token != Scanner.TokenNameWHITESPACE) {
+				if (token != TerminalTokens.TokenNameWHITESPACE) {
 
 					/* Add pending space to the formatted source string.
 					Do not output a space under the following circumstances:
@@ -915,7 +917,7 @@
 						&& insertSpaceAfter(previousToken)
 						&& !(inAssignment
 							&& (previousToken == TokenNameLBRACE || token == TokenNameRBRACE))
-						&& previousToken != Scanner.TokenNameCOMMENT_LINE) {
+						&& previousToken != TerminalTokens.TokenNameCOMMENT_LINE) {
 						if ((!(options.compactAssignmentMode && token == TokenNameEQUAL))
 							&& !openAndCloseBrace) {
 								if (previousCompilableToken == TokenNameRPAREN) {
@@ -952,7 +954,7 @@
 					}
 					// Add the next token to the formatted source string.
 					outputCurrentToken(token);
-					if (token == Scanner.TokenNameCOMMENT_LINE && openParenthesisCount > 1) {
+					if (token == TerminalTokens.TokenNameCOMMENT_LINE && openParenthesisCount > 1) {
 						pendingNewLines = 0;
 						currentLineBuffer.append(options.lineSeparatorSequence);
 						increaseLineDelta(options.lineSeparatorSequence.length);
@@ -960,11 +962,11 @@
 					pendingSpace = true;
 				}
 				// Whitespace tokens do not need to be remembered.
-				if (token != Scanner.TokenNameWHITESPACE) {
+				if (token != TerminalTokens.TokenNameWHITESPACE) {
 					previousToken = token;
-					if (token != Scanner.TokenNameCOMMENT_BLOCK
-						&& token != Scanner.TokenNameCOMMENT_LINE
-						&& token != Scanner.TokenNameCOMMENT_JAVADOC) {
+					if (token != TerminalTokens.TokenNameCOMMENT_BLOCK
+						&& token != TerminalTokens.TokenNameCOMMENT_LINE
+						&& token != TerminalTokens.TokenNameCOMMENT_JAVADOC) {
 						previousCompilableToken = token;
 					}
 				}
@@ -997,8 +999,8 @@
 	 * @param indentationLevel the initial indentation level
 	 * @return the formatted ouput.
 	 */
-	public String format(String string, int indentationLevel) {
-		return format(string, indentationLevel, (int[])null);
+	public String format(String string, int indentLevel) {
+		return format(string, indentLevel, (int[])null);
 	}	
 	
 	/** 
@@ -1010,23 +1012,22 @@
 	 * @param positions the array of positions to map
 	 * @return the formatted ouput.
 	 */
-	public String format(String string, int indentationLevel, int[] positions) {
-		return this.format(string, indentationLevel, positions, null);
+	public String format(String string, int indentLevel, int[] positions) {
+		return this.format(string, indentLevel, positions, null);
 	}
 	
-	public String format(String string, int indentationLevel, int[] positions, String lineSeparator) {
+	public String format(String string, int indentLevel, int[] positions, String lineSeparator) {
 		if (lineSeparator != null){
 			this.options.setLineSeparator(lineSeparator);
 		}
 		if (positions != null) {
 			this.setPositionsToMap(positions);
-			this.setInitialIndentationLevel(indentationLevel);
+			this.setInitialIndentationLevel(indentLevel);
 			String formattedString = this.formatSourceString(string);
-			int[] mappedPositions = this.getMappedPositions();
-			System.arraycopy(mappedPositions, 0, positions, 0, positions.length);
+			System.arraycopy(this.mappedPositions, 0, positions, 0, positions.length);
 			return formattedString;
 		} else {
-			this.setInitialIndentationLevel(indentationLevel);
+			this.setInitialIndentationLevel(indentLevel);
 			return this.formatSourceString(string);
 		}
 	}	
@@ -1232,7 +1233,7 @@
 			case TokenNameDOT :
 			case 0 : // no token
 			case TokenNameLBRACKET :
-			case Scanner.TokenNameCOMMENT_LINE :
+			case TerminalTokens.TokenNameCOMMENT_LINE :
 				return false;
 			default :
 				return true;
@@ -1256,9 +1257,9 @@
 
 	private static boolean isComment(int token) {
 		boolean result =
-			token == Scanner.TokenNameCOMMENT_BLOCK
-				|| token == Scanner.TokenNameCOMMENT_LINE
-				|| token == Scanner.TokenNameCOMMENT_JAVADOC;
+			token == TerminalTokens.TokenNameCOMMENT_BLOCK
+				|| token == TerminalTokens.TokenNameCOMMENT_LINE
+				|| token == TerminalTokens.TokenNameCOMMENT_JAVADOC;
 		return result;
 	}
 
@@ -1465,14 +1466,14 @@
 		int startPosition = scanner.startPosition;
 
 		switch (token) {
-			case Scanner.TokenNameCOMMENT_JAVADOC :
-			case Scanner.TokenNameCOMMENT_BLOCK :
-			case Scanner.TokenNameCOMMENT_LINE :
+			case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+			case TerminalTokens.TokenNameCOMMENT_BLOCK :
+			case TerminalTokens.TokenNameCOMMENT_LINE :
 				boolean endOfLine = false;
-				int currentCommentOffset = getCurrentCommentOffset();
+				int commentOffset = getCurrentCommentOffset();
 				int beginningOfLineSpaces = 0;
 				endOfLine = false;
-				currentCommentOffset = getCurrentCommentOffset();
+				commentOffset = getCurrentCommentOffset();
 				beginningOfLineSpaces = 0;
 				boolean pendingCarriageReturn = false;
 				for (int i = startPosition, max = scanner.currentPosition; i < max; i++) {
@@ -1505,7 +1506,7 @@
 							if (endOfLine) {
 								// we remove a maximum of currentCommentOffset characters (tabs are converted to space numbers).
 								beginningOfLineSpaces += options.tabSize;
-								if (beginningOfLineSpaces > currentCommentOffset) {
+								if (beginningOfLineSpaces > commentOffset) {
 									currentLineBuffer.append(currentCharacter);
 								} else {
 									increaseGlobalDelta(-1);
@@ -1525,7 +1526,7 @@
 							if (endOfLine) {
 								// we remove a maximum of currentCommentOffset characters (tabs are converted to space numbers).
 								beginningOfLineSpaces++;
-								if (beginningOfLineSpaces > currentCommentOffset) {
+								if (beginningOfLineSpaces > commentOffset) {
 									currentLineBuffer.append(currentCharacter);
 								} else {
 									increaseGlobalDelta(-1);
@@ -2036,7 +2037,7 @@
 			while (true) {
 				// takes the next token
 				try {
-					if (currentToken != Scanner.TokenNameWHITESPACE)
+					if (currentToken != TerminalTokens.TokenNameWHITESPACE)
 						previousToken = currentToken;
 					currentToken = splitScanner.getNextToken();
 				} catch (InvalidInputException e) {
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterParser.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterParser.java
new file mode 100644
index 0000000..df0c0df
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterParser.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 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 org.eclipse.jdt.internal.formatter;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+
+/**
+ * Subclass of the parser used to parse different code snippets
+ */
+public class CodeFormatterParser extends Parser {
+
+	public CodeFormatterParser(
+			ProblemReporter problemReporter,
+			boolean optimizeStringLiterals) {
+		super(problemReporter, optimizeStringLiterals);
+		this.javadocParser.checkJavadoc = false;
+	}
+
+	public Expression parseExpression(char[] source, CompilationUnitDeclaration unit) {
+	
+		initialize();
+		goForExpression();
+		nestedMethod[nestedType]++;
+	
+		referenceContext = unit;
+		compilationUnit = unit;
+	
+		scanner.setSource(source);
+		scanner.resetTo(0, source.length-1);
+		try {
+			parse();
+		} catch (AbortCompilation ex) {
+			lastAct = ERROR_ACTION;
+		} finally {
+			nestedMethod[nestedType]--;
+		}
+	
+		if (lastAct == ERROR_ACTION) {
+			return null;
+		}
+	
+		return expressionStack[expressionPtr];
+	}
+	
+	public ASTNode[] parseClassBodyDeclarations(char[] source, CompilationUnitDeclaration unit) {
+		/* automaton initialization */
+		initialize();
+		goForClassBodyDeclarations();
+		/* scanner initialization */
+		scanner.setSource(source);
+		scanner.resetTo(0, source.length - 1);
+
+		/* type declaration should be parsed as member type declaration */	
+		nestedType = 1;
+
+		/* unit creation */
+		referenceContext = unit;
+		compilationUnit = unit;
+
+		/* run automaton */
+		try {
+			parse();
+		} catch (AbortCompilation ex) {
+			lastAct = ERROR_ACTION;
+		}
+	
+		if (lastAct == ERROR_ACTION) {
+			return null;
+		}
+		int length;
+		if ((length = astLengthStack[astLengthPtr--]) != 0) {
+			ASTNode[] result = new ASTNode[length];
+			astPtr -= length;
+			System.arraycopy(astStack, astPtr + 1, result, 0, length);
+			return result;
+		} else {
+			return null;
+		}
+	}	
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
new file mode 100644
index 0000000..af04e62
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
@@ -0,0 +1,3962 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2003 International Business Machines 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 API and implementation
+ ******************************************************************************/
+package org.eclipse.jdt.internal.formatter;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
+import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
+import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.AssertStatement;
+import org.eclipse.jdt.internal.compiler.ast.Assignment;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
+import org.eclipse.jdt.internal.compiler.ast.Block;
+import org.eclipse.jdt.internal.compiler.ast.BreakStatement;
+import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
+import org.eclipse.jdt.internal.compiler.ast.CastExpression;
+import org.eclipse.jdt.internal.compiler.ast.CharLiteral;
+import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
+import org.eclipse.jdt.internal.compiler.ast.Clinit;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
+import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
+import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ContinueStatement;
+import org.eclipse.jdt.internal.compiler.ast.DoStatement;
+import org.eclipse.jdt.internal.compiler.ast.DoubleLiteral;
+import org.eclipse.jdt.internal.compiler.ast.EmptyStatement;
+import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.FloatLiteral;
+import org.eclipse.jdt.internal.compiler.ast.ForStatement;
+import org.eclipse.jdt.internal.compiler.ast.IfStatement;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
+import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
+import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
+import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.LongLiteral;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression;
+import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.PostfixExpression;
+import org.eclipse.jdt.internal.compiler.ast.PrefixExpression;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.jdt.internal.compiler.ast.SuperReference;
+import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
+import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
+import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
+import org.eclipse.jdt.internal.compiler.ast.TryStatement;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
+import org.eclipse.jdt.internal.compiler.ast.WhileStatement;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.formatter.align.Alignment;
+import org.eclipse.jdt.internal.formatter.align.AlignmentException;
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ * This class is responsible for formatting a valid java source code.
+ * @since 2.1
+ */
+/*
+   <extension
+         id="org.eclipse.jdt.core.newformatter.codeformatter"
+         name="org.eclipse.jdt.core.newformatter.codeformatter"
+         point="org.eclipse.jdt.core.codeFormatter">
+      <codeFormatter
+            class="org.eclipse.jdt.internal.formatter.CodeFormatterVisitor">
+      </codeFormatter>
+   </extension>
+*/
+public class CodeFormatterVisitor extends ASTVisitor {
+
+	public static class MultiFieldDeclaration extends FieldDeclaration {
+		
+		FieldDeclaration[] declarations;
+		
+		MultiFieldDeclaration(FieldDeclaration[] declarations){
+			this.declarations = declarations;
+			this.modifiers = declarations[0].modifiers; 
+		}
+	}
+	
+	public static boolean DEBUG = false;
+	private static final int NO_MODIFIERS = 0;
+	/*
+	 * Set of expected tokens type for a single type reference.
+	 * This array needs to be SORTED.
+	 */
+	private static final int[] SINGLETYPEREFERENCE_EXPECTEDTOKENS = new int[] {
+		TerminalTokens.TokenNameIdentifier,
+		TerminalTokens.TokenNameboolean,
+		TerminalTokens.TokenNamebyte,
+		TerminalTokens.TokenNamechar,
+		TerminalTokens.TokenNamedouble,
+		TerminalTokens.TokenNamefloat,
+		TerminalTokens.TokenNameint,
+		TerminalTokens.TokenNamelong,
+		TerminalTokens.TokenNameshort,
+		TerminalTokens.TokenNamevoid
+	};
+	private int chunkKind;
+	public int lastLocalDeclarationSourceStart;
+	private Scanner localScanner;
+	public DefaultCodeFormatterOptions preferences;
+	public Scribe scribe;
+	
+	/*
+	 * TODO See how to choose the formatter's options. The extension point is calling
+	 * this constructor, but then there is no way to initialize the option used by the formatter.
+	 */ 
+	public CodeFormatterVisitor() {
+		this(new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getJavaConventionsSettings()), JavaCore.getDefaultOptions(), 0, -1);
+	}
+
+	public CodeFormatterVisitor(DefaultCodeFormatterOptions preferences, Map settings, int offset, int length) {
+		if (settings != null) {
+			Object assertModeSetting = settings.get(JavaCore.COMPILER_SOURCE);
+			if (assertModeSetting == null) {
+				this.localScanner = new Scanner(true, false, false/*nls*/, JavaCore.VERSION_1_4.equals(assertModeSetting) ? ClassFileConstants.JDK1_4 : ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/);
+			} else {
+				this.localScanner = new Scanner(true, false, false/*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/);
+			}
+		} else {
+			this.localScanner = new Scanner(true, false, false/*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/);
+		}
+		
+		this.preferences = preferences;
+		this.scribe = new Scribe(this, settings, offset, length);
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#acceptProblem(org.eclipse.jdt.core.compiler.IProblem)
+	 */
+	public void acceptProblem(IProblem problem) {
+		super.acceptProblem(problem);
+	}
+
+	private BinaryExpressionFragmentBuilder buildFragments(BinaryExpression binaryExpression, BlockScope scope) {
+		BinaryExpressionFragmentBuilder builder = new BinaryExpressionFragmentBuilder();
+
+		switch((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) {
+			case OperatorIds.MULTIPLY :
+				binaryExpression.left.traverse(builder, scope);
+				builder.operatorsList.add(new Integer(TerminalTokens.TokenNameMULTIPLY));
+				binaryExpression.right.traverse(builder, scope);
+				break;
+			case OperatorIds.PLUS :
+				binaryExpression.left.traverse(builder, scope);
+				builder.operatorsList.add(new Integer(TerminalTokens.TokenNamePLUS));
+				binaryExpression.right.traverse(builder, scope);
+				break;
+			case OperatorIds.DIVIDE :
+				binaryExpression.left.traverse(builder, scope);
+				builder.operatorsList.add(new Integer(TerminalTokens.TokenNameDIVIDE));
+				binaryExpression.right.traverse(builder, scope);
+				break;
+			case OperatorIds.REMAINDER :
+				binaryExpression.left.traverse(builder, scope);
+				builder.operatorsList.add(new Integer(TerminalTokens.TokenNameREMAINDER));
+				binaryExpression.right.traverse(builder, scope);
+				break;
+			case OperatorIds.XOR :
+				binaryExpression.left.traverse(builder, scope);
+				builder.operatorsList.add(new Integer(TerminalTokens.TokenNameXOR));
+				binaryExpression.right.traverse(builder, scope);
+				break;
+			case OperatorIds.MINUS :
+				binaryExpression.left.traverse(builder, scope);
+				builder.operatorsList.add(new Integer(TerminalTokens.TokenNameMINUS));
+				binaryExpression.right.traverse(builder, scope);
+				break;
+			case OperatorIds.OR :
+				binaryExpression.left.traverse(builder, scope);
+				builder.operatorsList.add(new Integer(TerminalTokens.TokenNameOR));
+				binaryExpression.right.traverse(builder, scope);
+				break;
+			case OperatorIds.AND :
+				binaryExpression.left.traverse(builder, scope);
+				builder.operatorsList.add(new Integer(TerminalTokens.TokenNameAND));
+				binaryExpression.right.traverse(builder, scope);
+				break;
+			case OperatorIds.AND_AND :
+				binaryExpression.left.traverse(builder, scope);
+				builder.operatorsList.add(new Integer(TerminalTokens.TokenNameAND_AND));
+				binaryExpression.right.traverse(builder, scope);
+				break;
+			case OperatorIds.OR_OR :
+				binaryExpression.left.traverse(builder, scope);
+				builder.operatorsList.add(new Integer(TerminalTokens.TokenNameOR_OR));
+				binaryExpression.right.traverse(builder, scope);
+				break;
+		}
+
+		return builder;
+	}
+
+	private CascadingMethodInvocationFragmentBuilder buildFragments(MessageSend messageSend, BlockScope scope) {
+		CascadingMethodInvocationFragmentBuilder builder = new CascadingMethodInvocationFragmentBuilder();
+
+		messageSend.traverse(builder, scope);
+		return builder;
+	}	
+	public boolean checkChunkStart(int kind) {
+		if (this.chunkKind != kind) {
+			this.chunkKind = kind;
+			return true;
+		}
+		return false;
+	}
+	
+	private ASTNode[] computeMergedMemberDeclarations(TypeDeclaration typeDeclaration){
+		
+		int fieldIndex = 0, fieldCount = (typeDeclaration.fields == null) ? 0 : typeDeclaration.fields.length;
+		FieldDeclaration field = fieldCount == 0 ? null : typeDeclaration.fields[fieldIndex];
+		int fieldStart = field == null ? Integer.MAX_VALUE : field.declarationSourceStart;
+
+		int methodIndex = 0, methodCount = (typeDeclaration.methods == null) ? 0 : typeDeclaration.methods.length;
+		AbstractMethodDeclaration method = methodCount == 0 ? null : typeDeclaration.methods[methodIndex];
+		int methodStart = method == null ? Integer.MAX_VALUE : method.declarationSourceStart;
+
+		int typeIndex = 0, typeCount = (typeDeclaration.memberTypes == null) ? 0 : typeDeclaration.memberTypes.length;
+		TypeDeclaration type = typeCount == 0 ? null : typeDeclaration.memberTypes[typeIndex];
+		int typeStart = type == null ? Integer.MAX_VALUE : type.declarationSourceStart;
+	
+		final int memberLength = fieldCount+methodCount+typeCount;
+		ASTNode[] members = new ASTNode[memberLength];
+		if (memberLength != 0) {
+			int index = 0;
+			int previousFieldStart = -1;
+			do {
+				if (fieldStart < methodStart && fieldStart < typeStart) {
+					// next member is a field
+					if (fieldStart == previousFieldStart){ 
+						ASTNode previousMember = members[index - 1];
+						if (previousMember instanceof MultiFieldDeclaration) {
+							MultiFieldDeclaration multiField = (MultiFieldDeclaration) previousMember;
+							int length = multiField.declarations.length;
+							System.arraycopy(multiField.declarations, 0, multiField.declarations=new FieldDeclaration[length+1], 0, length);
+							multiField.declarations[length] = field;
+						} else {
+							members[index - 1] = new MultiFieldDeclaration(new FieldDeclaration[]{ (FieldDeclaration)previousMember, field});
+						}
+					} else {
+						members[index++] = field;					
+					}
+					previousFieldStart = fieldStart;
+					if (++fieldIndex < fieldCount) { // find next field if any
+						fieldStart = (field = typeDeclaration.fields[fieldIndex]).declarationSourceStart;
+					} else {
+						fieldStart = Integer.MAX_VALUE;
+					}
+				} else if (methodStart < fieldStart && methodStart < typeStart) {
+					// next member is a method
+					if (!method.isDefaultConstructor() && !method.isClinit()) {
+						members[index++] = method;					
+					}
+					if (++methodIndex < methodCount) { // find next method if any
+						methodStart = (method = typeDeclaration.methods[methodIndex]).declarationSourceStart;
+					} else {
+						methodStart = Integer.MAX_VALUE;
+					}
+				} else {
+					// next member is a type
+					members[index++] = type;
+					if (++typeIndex < typeCount) { // find next type if any
+						typeStart = (type = typeDeclaration.memberTypes[typeIndex]).declarationSourceStart;
+					} else {
+						typeStart = Integer.MAX_VALUE;
+					}
+				}
+			} while ((fieldIndex < fieldCount) || (typeIndex < typeCount) || (methodIndex < methodCount));
+			
+			if (members.length != index) {
+				System.arraycopy(members, 0, members=new ASTNode[index], 0, index);
+			}
+		}
+		return members;
+	}
+
+	private ASTNode[] computeMergedMemberDeclarations(ASTNode[] nodes){
+		ArrayList mergedNodes = new ArrayList();
+		for (int i = 0, max = nodes.length; i < max; i++) {
+			ASTNode currentNode = nodes[i];
+			if (currentNode instanceof FieldDeclaration) {
+				FieldDeclaration currentField = (FieldDeclaration) currentNode;
+				if (mergedNodes.size() == 0) {
+					// first node
+					mergedNodes.add(currentNode);
+				} else {
+					// we need to check if the previous merged node is a field declaration
+					ASTNode previousMergedNode = (ASTNode) mergedNodes.get(mergedNodes.size() - 1);
+					if (previousMergedNode instanceof MultiFieldDeclaration) {
+						// we merge the current node
+						MultiFieldDeclaration multiFieldDeclaration = (MultiFieldDeclaration) previousMergedNode;
+						int length = multiFieldDeclaration.declarations.length;
+						System.arraycopy(multiFieldDeclaration.declarations, 0, multiFieldDeclaration.declarations= new FieldDeclaration[length+1], 0, length);
+						multiFieldDeclaration.declarations[length] = currentField;
+					} else if (previousMergedNode instanceof FieldDeclaration) {
+						// need to check we need to create a multiple field declaration
+						if (currentField.declarationSourceStart == ((FieldDeclaration) previousMergedNode).declarationSourceStart) {
+							// we create a multi field declaration
+							mergedNodes.set(mergedNodes.size() - 1, new MultiFieldDeclaration(new FieldDeclaration[]{ (FieldDeclaration)previousMergedNode, currentField}));
+						}
+					} else {
+						mergedNodes.add(currentNode);
+					}
+				}
+			} else {
+				mergedNodes.add(currentNode);
+			}
+		}
+		if (mergedNodes.size() != nodes.length) {
+			ASTNode[] result = new ASTNode[mergedNodes.size()];
+			mergedNodes.toArray(result);
+			return result;
+		} else {
+			return nodes;
+		}
+	}
+	
+	private boolean dumpBinaryExpression(
+		BinaryExpression binaryExpression,
+		int operator,
+		BlockScope scope) {
+
+		final int numberOfParens = (binaryExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(binaryExpression, numberOfParens);
+		}	
+		BinaryExpressionFragmentBuilder builder = buildFragments(binaryExpression, scope);
+		final int fragmentsSize = builder.size();
+		
+		if ((builder.realFragmentsSize() > 1 || builder.size() > 4) && numberOfParens == 0) {
+			this.scribe.printComment();
+			Alignment binaryExpressionAlignment = this.scribe.createAlignment("binaryExpressionAlignment", this.preferences.binary_expression_alignment, Alignment.R_OUTERMOST, fragmentsSize, this.scribe.scanner.currentPosition); //$NON-NLS-1$
+			this.scribe.enterAlignment(binaryExpressionAlignment);
+			boolean ok = false;
+			ASTNode[] fragments = builder.fragments();
+			int[] operators = builder.operators();
+			do {
+				try {
+					for (int i = 0; i < fragmentsSize - 1; i++) {
+						ASTNode fragment = fragments[i];
+						fragment.traverse(this, scope);
+						this.scribe.alignFragment(binaryExpressionAlignment, i);
+						this.scribe.printNextToken(operators[i], this.preferences.insert_space_before_binary_operator);
+						if (operators[i] == TerminalTokens.TokenNameMINUS && isMinus()) {
+							// the next character is a minus (unary operator)
+							this.scribe.space();
+						}
+						if (this.preferences.insert_space_after_binary_operator) {
+							this.scribe.space();
+						}
+						this.scribe.printTrailingComment();
+					}
+					fragments[fragmentsSize - 1].traverse(this, scope);
+					ok = true;
+				} catch(AlignmentException e){
+					this.scribe.redoAlignment(e);
+				}
+			} while (!ok);		
+			this.scribe.exitAlignment(binaryExpressionAlignment, true);
+		} else {
+			binaryExpression.left.traverse(this, scope);
+			this.scribe.printNextToken(operator, this.preferences.insert_space_before_binary_operator);
+			if (operator == TerminalTokens.TokenNameMINUS && isMinus()) {
+				// the next character is a minus (unary operator)
+				this.scribe.space();
+			}
+			if (this.preferences.insert_space_after_binary_operator) {
+				this.scribe.space();
+			}
+			binaryExpression.right.traverse(this, scope);
+		}	
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(binaryExpression, numberOfParens);
+		}
+		return false;
+	}
+
+	private boolean dumpEqualityExpression(
+		BinaryExpression binaryExpression,
+		int operator,
+		BlockScope scope) {
+	
+		final int numberOfParens = (binaryExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+	
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(binaryExpression, numberOfParens);
+		}	
+		binaryExpression.left.traverse(this, scope);
+		this.scribe.printNextToken(operator, this.preferences.insert_space_before_binary_operator);
+		if (this.preferences.insert_space_after_binary_operator) {
+			this.scribe.space();
+		}
+		binaryExpression.right.traverse(this, scope);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(binaryExpression, numberOfParens);
+		}
+		return false;
+	}
+
+	private final TextEdit failedToFormat() {
+		if (DEBUG) {
+			System.out.println("COULD NOT FORMAT \n" + this.scribe.scanner); //$NON-NLS-1$
+			System.out.println(this.scribe);
+		}
+		return null;
+	}
+
+	private void format(
+		AbstractMethodDeclaration methodDeclaration,
+		ClassScope scope,
+		boolean isChunkStart,
+		boolean isFirstClassBodyDeclaration) {
+
+		if (isFirstClassBodyDeclaration) {
+			int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
+			if (newLinesBeforeFirstClassBodyDeclaration > 0) {
+				this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
+			}
+		} else {
+			final int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
+			if (newLineBeforeChunk > 0) {
+				this.scribe.printEmptyLines(newLineBeforeChunk);
+			}
+		}
+		final int newLinesBeforeMethod = this.preferences.blank_lines_before_method;
+		if (newLinesBeforeMethod > 0 && !isFirstClassBodyDeclaration) {
+			this.scribe.printEmptyLines(newLinesBeforeMethod);
+		} else if (this.scribe.line != 0 || this.scribe.column != 1) {
+			this.scribe.printNewLine();
+		}
+		methodDeclaration.traverse(this, scope);
+	}
+	
+	private void format(FieldDeclaration fieldDeclaration, ASTVisitor visitor, MethodScope scope, boolean isChunkStart, boolean isFirstClassBodyDeclaration) {
+		
+		if (isFirstClassBodyDeclaration) {
+			int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
+			if (newLinesBeforeFirstClassBodyDeclaration > 0) {
+				this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
+			}
+		} else {
+			int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
+			if (newLineBeforeChunk > 0) {
+				this.scribe.printEmptyLines(newLineBeforeChunk);
+			}
+			final int newLinesBeforeField = this.preferences.blank_lines_before_field;
+			if (newLinesBeforeField > 0) {
+				this.scribe.printEmptyLines(newLinesBeforeField);
+			}
+		}
+		Alignment memberAlignment = this.scribe.getMemberAlignment();	//$NON-NLS-1$
+	
+		this.scribe.printModifiers();
+		this.scribe.space();
+		/*
+		 * Field type
+		 */
+		fieldDeclaration.type.traverse(this, scope);
+		
+		/*
+		 * Field name
+		 */
+		this.scribe.alignFragment(memberAlignment, 0);
+	
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
+	
+		/*
+		 * Check for extra dimensions
+		 */
+		int extraDimensions = getExtraDimension();
+		if (extraDimensions != 0) {
+			 for (int i = 0; i < extraDimensions; i++) {
+			 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+			 	this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			 }
+		}
+	
+		/*
+		 * Field initialization
+		 */
+		final Expression initialization = fieldDeclaration.initialization;
+		if (initialization != null) {
+			this.scribe.alignFragment(memberAlignment, 1);
+			this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operators);
+			if (!(initialization instanceof ArrayInitializer) && this.preferences.insert_space_after_assignment_operators) {
+				this.scribe.space();
+			}
+			initialization.traverse(this, scope);
+		}
+		
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+
+		if (memberAlignment != null) {
+			this.scribe.alignFragment(memberAlignment, 2);
+			this.scribe.printTrailingComment();
+		} else {
+			this.scribe.space();
+			this.scribe.printTrailingComment();
+		}
+	}
+
+	private void format(
+		TypeDeclaration memberTypeDeclaration,
+		ClassScope scope,
+		boolean isChunkStart,
+		boolean isFirstClassBodyDeclaration) {
+
+		if (isFirstClassBodyDeclaration) {
+			int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
+			if (newLinesBeforeFirstClassBodyDeclaration > 0) {
+				this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
+			}
+		} else {
+			int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
+			if (newLineBeforeChunk > 0) {
+				this.scribe.printEmptyLines(newLineBeforeChunk);
+			}
+			final int newLinesBeforeMember = this.preferences.blank_lines_before_member_type;
+			if (newLinesBeforeMember > 0) {
+				this.scribe.printEmptyLines(newLinesBeforeMember);
+			}
+		}
+		memberTypeDeclaration.traverse(this, scope);
+	}
+	
+	private void format(MultiFieldDeclaration multiFieldDeclaration, ASTVisitor visitor, MethodScope scope, boolean isChunkStart, boolean isFirstClassBodyDeclaration) {
+	
+		if (isFirstClassBodyDeclaration) {
+			int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
+			if (newLinesBeforeFirstClassBodyDeclaration > 0) {
+				this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
+			}
+		} else {
+			int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
+			if (newLineBeforeChunk > 0) {
+				this.scribe.printEmptyLines(newLineBeforeChunk);
+			}
+			final int newLinesBeforeField = this.preferences.blank_lines_before_field;
+			if (newLinesBeforeField > 0) {
+				this.scribe.printEmptyLines(newLinesBeforeField);
+			}
+		}
+		Alignment fieldAlignment = this.scribe.getMemberAlignment();	//$NON-NLS-1$
+	
+		this.scribe.printModifiers();
+		this.scribe.space();
+	
+		multiFieldDeclaration.declarations[0].type.traverse(this, scope);
+	
+		final int multipleFieldDeclarationsLength = multiFieldDeclaration.declarations.length;
+
+		Alignment multiFieldDeclarationsAlignment =this.scribe.createAlignment(
+				"multiple_field",//$NON-NLS-1$
+				this.preferences.multiple_fields_alignment,
+				multipleFieldDeclarationsLength - 1,
+				this.scribe.scanner.currentPosition);
+		this.scribe.enterAlignment(multiFieldDeclarationsAlignment);
+	
+		boolean ok = false;
+		do {
+			try {
+				for (int i = 0, length = multipleFieldDeclarationsLength; i < length; i++) {
+					FieldDeclaration fieldDeclaration = multiFieldDeclaration.declarations[i];
+					/*
+					 * Field name
+					 */
+					if (i == 0) {
+						this.scribe.alignFragment(fieldAlignment, 0);
+						this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
+					} else {
+						this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false);
+					}
+			
+					/*
+					 * Check for extra dimensions
+					 */
+					int extraDimensions = getExtraDimension();
+					if (extraDimensions != 0) {
+						 for (int index = 0; index < extraDimensions; index++) {
+						 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+						 	this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+						 }
+					}
+				
+					/*
+					 * Field initialization
+					 */
+					final Expression initialization = fieldDeclaration.initialization;
+					if (initialization != null) {
+						if (i == 0) {
+							this.scribe.alignFragment(fieldAlignment, 1);
+						}
+						this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operators);
+						if (!(initialization instanceof ArrayInitializer) && this.preferences.insert_space_after_assignment_operators) {
+							this.scribe.space();
+						}
+						initialization.traverse(this, scope);
+					}
+					
+					if (i != length - 1) {
+						this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_multiple_field_declarations);
+
+						this.scribe.alignFragment(multiFieldDeclarationsAlignment, i);
+
+						if (this.preferences.insert_space_after_comma_in_multiple_field_declarations) {
+							this.scribe.space();
+						}
+					} else {
+						this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+						this.scribe.alignFragment(fieldAlignment, 2);
+						this.scribe.printTrailingComment();
+					}
+				}
+				ok = true;
+			} catch (AlignmentException e) {
+				this.scribe.redoAlignment(e);
+			}
+		} while (!ok);
+		this.scribe.exitAlignment(multiFieldDeclarationsAlignment, true);				
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.core.ICodeFormatter#format(java.lang.String, int, int, java.lang.String)
+	 */
+	public TextEdit format(String string, ASTNode[] nodes) {
+		// reset the scribe
+		this.scribe.reset();
+		
+		long startTime = System.currentTimeMillis();
+
+		final char[] compilationUnitSource = string.toCharArray();
+		
+		this.localScanner.setSource(compilationUnitSource);
+		this.scribe.initializeScanner(compilationUnitSource);
+
+		if (nodes == null) {
+			return null;
+		}
+
+		this.lastLocalDeclarationSourceStart = -1;
+		try {
+			formatClassBodyDeclarations(nodes);
+		} catch(AbortFormatting e){
+			return failedToFormat();
+		}
+		if (DEBUG){
+			System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime));  //$NON-NLS-1$
+		}
+		return this.scribe.getRootEdit();
+	}
+
+	/**
+	 * @see org.eclipse.jdt.core.ICodeFormatter#format(java.lang.String, int, int, java.lang.String)
+	 */
+	public TextEdit format(String string, CompilationUnitDeclaration compilationUnitDeclaration) {
+		// reset the scribe
+		this.scribe.reset();
+		
+		if (compilationUnitDeclaration == null || compilationUnitDeclaration.ignoreFurtherInvestigation) {
+			return failedToFormat();
+		}
+
+		long startTime = System.currentTimeMillis();
+
+		final char[] compilationUnitSource = string.toCharArray();
+		
+		this.localScanner.setSource(compilationUnitSource);
+		this.scribe.initializeScanner(compilationUnitSource);
+
+		this.lastLocalDeclarationSourceStart = -1;
+		try {
+			compilationUnitDeclaration.traverse(this, compilationUnitDeclaration.scope);
+		} catch(AbortFormatting e){
+			return failedToFormat();
+		}
+		if (DEBUG){
+			System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime));  //$NON-NLS-1$
+		}
+		return this.scribe.getRootEdit();
+	}
+
+	/**
+	 * @see org.eclipse.jdt.core.ICodeFormatter#format(java.lang.String, int, int, java.lang.String)
+	 */
+	public TextEdit format(String string, ConstructorDeclaration constructorDeclaration) {
+		// reset the scribe
+		this.scribe.reset();
+		
+		long startTime = System.currentTimeMillis();
+
+		final char[] compilationUnitSource = string.toCharArray();
+		
+		this.localScanner.setSource(compilationUnitSource);
+		this.scribe.initializeScanner(compilationUnitSource);
+
+		if (constructorDeclaration == null) {
+			return null;
+		}
+
+		this.lastLocalDeclarationSourceStart = -1;
+		try {
+			ExplicitConstructorCall explicitConstructorCall = constructorDeclaration.constructorCall;
+			if (explicitConstructorCall != null && !explicitConstructorCall.isImplicitSuper()) {
+				explicitConstructorCall.traverse(this, null);
+			}
+			Statement[] statements = constructorDeclaration.statements;
+			if (statements != null) {
+				formatStatements(null, statements, false);
+			}
+			if (hasComments()) {
+				this.scribe.printNewLine();
+			}
+			this.scribe.printComment();
+		} catch(AbortFormatting e){
+			return failedToFormat();
+		}
+		if (DEBUG){
+			System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime));  //$NON-NLS-1$
+		}
+		return this.scribe.getRootEdit();
+	}
+
+	/**
+	 * @see org.eclipse.jdt.core.ICodeFormatter#format(java.lang.String, int, int, java.lang.String)
+	 */
+	public TextEdit format(String string, Expression expression) {
+		// reset the scribe
+		this.scribe.reset();
+		
+		long startTime = System.currentTimeMillis();
+
+		final char[] compilationUnitSource = string.toCharArray();
+		
+		this.localScanner.setSource(compilationUnitSource);
+		this.scribe.initializeScanner(compilationUnitSource);
+
+		if (expression == null) {
+			return null;
+		}
+
+		this.lastLocalDeclarationSourceStart = -1;
+		try {
+			expression.traverse(this, null);
+			this.scribe.printComment();
+		} catch(AbortFormatting e){
+			return failedToFormat();
+		}
+		if (DEBUG){
+			System.out.println("Formatting time: " + (System.currentTimeMillis() - startTime));  //$NON-NLS-1$
+		}
+		return this.scribe.getRootEdit();
+	}
+	
+	private void format(TypeDeclaration typeDeclaration){
+
+		if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+			/*
+			 * Type body
+			 */
+			String anonymous_type_declaration_brace_position = this.preferences.anonymous_type_declaration_brace_position;
+			formatTypeOpeningBrace(anonymous_type_declaration_brace_position, this.preferences.insert_space_before_anonymous_type_open_brace, typeDeclaration);
+			
+			this.scribe.indent();
+	
+			formatTypeMembers(typeDeclaration);
+			
+			this.scribe.printComment();
+			this.scribe.unIndent();
+			if (this.preferences.insert_new_line_in_empty_anonymous_type_declaration) {
+				this.scribe.printNewLine();
+			}
+			this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
+			if (anonymous_type_declaration_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
+				this.scribe.unIndent();
+			}
+			return;
+		}
+		this.scribe.printModifiers();
+		/*
+		 * Type name
+		 */
+		if (typeDeclaration.isInterface()) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameinterface, true); 
+		} else {
+			this.scribe.printNextToken(TerminalTokens.TokenNameclass, true); 
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
+
+		/* 
+		 * Superclass 
+		 */
+		final TypeReference superclass = typeDeclaration.superclass;
+		if (superclass != null) {
+			Alignment superclassAlignment =this.scribe.createAlignment(
+					"superclass", //$NON-NLS-1$
+					this.preferences.type_declaration_superclass_alignment,
+					2,
+					this.scribe.scanner.currentPosition);
+			this.scribe.enterAlignment(superclassAlignment);
+			boolean ok = false;
+			do {
+				try {
+					this.scribe.alignFragment(superclassAlignment, 0);
+					this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
+					this.scribe.alignFragment(superclassAlignment, 1);
+					this.scribe.space();
+					superclass.traverse(this, typeDeclaration.scope);
+					ok = true;
+				} catch (AlignmentException e) {
+					this.scribe.redoAlignment(e);
+				}
+			} while (!ok);
+			this.scribe.exitAlignment(superclassAlignment, true); 
+		}
+
+		/* 
+		 * Super Interfaces 
+		 */
+		final TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+		if (superInterfaces != null) {
+			
+			int superInterfaceLength = superInterfaces.length;
+			Alignment interfaceAlignment =this.scribe.createAlignment(
+					"superInterfaces",//$NON-NLS-1$
+					this.preferences.type_declaration_superinterfaces_alignment,
+					superInterfaceLength+1,  // implements token is first fragment
+					this.scribe.scanner.currentPosition);
+			this.scribe.enterAlignment(interfaceAlignment);
+			boolean ok = false;
+			do {
+				try {
+					this.scribe.alignFragment(interfaceAlignment, 0);
+					if (typeDeclaration.isInterface()) {
+						this.scribe.printNextToken(TerminalTokens.TokenNameextends, true);
+					} else  {
+						this.scribe.printNextToken(TerminalTokens.TokenNameimplements, true);
+					}
+					for (int i = 0; i < superInterfaceLength; i++) {
+						if (i > 0) {
+							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_superinterfaces);
+							this.scribe.alignFragment(interfaceAlignment, i+1);
+							if (this.preferences.insert_space_after_comma_in_superinterfaces) {
+								this.scribe.space();
+							}
+							superInterfaces[i].traverse(this, typeDeclaration.scope);
+						} else {
+							this.scribe.alignFragment(interfaceAlignment, i+1);
+							this.scribe.space();
+							superInterfaces[i].traverse(this, typeDeclaration.scope);
+						}
+					}
+					ok = true;
+				} catch (AlignmentException e) {
+					this.scribe.redoAlignment(e);
+				}
+			} while (!ok);
+			this.scribe.exitAlignment(interfaceAlignment, true);
+		}
+
+		/*
+		 * Type body
+		 */
+		String class_declaration_brace = this.preferences.type_declaration_brace_position;
+
+		formatTypeOpeningBrace(class_declaration_brace, this.preferences.insert_space_before_type_open_brace, typeDeclaration);
+		
+		if (this.preferences.indent_body_declarations_compare_to_type_header) {
+			this.scribe.indent();
+		}
+
+		formatTypeMembers(typeDeclaration);
+
+		this.scribe.printComment();
+		
+		if (this.preferences.indent_body_declarations_compare_to_type_header) {
+			this.scribe.unIndent();
+		}
+		
+		if (this.preferences.insert_new_line_in_empty_type_declaration) {
+			this.scribe.printNewLine();
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
+		this.scribe.printTrailingComment();
+		if (class_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
+			this.scribe.unIndent();
+		}
+		if (hasComments()) {
+			this.scribe.printNewLine();
+		}
+	}
+
+	private void formatArrayInitializer(ArrayInitializer arrayInitializer, BlockScope scope, boolean insertSpaceBeforeOpeningBrace) {
+		final int numberOfParens = (arrayInitializer.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(arrayInitializer, numberOfParens);
+		}
+		
+		String array_initializer_brace_position = this.preferences.array_initializer_brace_position;
+		formatOpeningBrace(array_initializer_brace_position, insertSpaceBeforeOpeningBrace);
+		
+		if (this.preferences.insert_new_line_after_opening_brace_in_array_initializer) {
+			this.scribe.printNewLine();
+		}
+		final Expression[] expressions = arrayInitializer.expressions;
+		if (expressions != null) {
+			int expressionsLength = expressions.length;
+			if (expressionsLength > 1) {
+				Alignment arrayInitializerAlignment =this.scribe.createAlignment(
+						"array_initializer",//$NON-NLS-1$
+						this.preferences.array_initializer_expressions_alignment,
+						Alignment.R_OUTERMOST,
+						expressionsLength,
+						this.scribe.scanner.currentPosition,
+						this.preferences.array_initializer_continuation_indentation,
+						true);
+				
+				if (this.preferences.insert_new_line_after_opening_brace_in_array_initializer) {
+				    arrayInitializerAlignment.fragmentIndentations[0] = arrayInitializerAlignment.breakIndentationLevel;
+				}
+				
+				this.scribe.enterAlignment(arrayInitializerAlignment);
+				boolean ok = false;
+				do {
+					try {
+						this.scribe.alignFragment(arrayInitializerAlignment, 0);
+						if (this.preferences.insert_space_before_first_initializer) {
+							this.scribe.space();
+						}
+						expressions[0].traverse(this, scope);
+						for (int i = 1; i < expressionsLength; i++) {
+							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
+							this.scribe.alignFragment(arrayInitializerAlignment, i);
+							if (this.preferences.insert_space_after_comma_in_array_initializer) {
+								this.scribe.space();
+							}
+							expressions[i].traverse(this, scope);
+							if (i == expressionsLength - 1) {
+								if (isComma()) {
+									this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
+								}
+							}
+						}
+						ok = true;
+					} catch (AlignmentException e) {
+						this.scribe.redoAlignment(e);
+					}
+				} while (!ok);
+				this.scribe.exitAlignment(arrayInitializerAlignment, true);
+			} else {
+				// we don't need to use an alignment
+				if (this.preferences.insert_space_before_first_initializer) {
+					this.scribe.space();
+				}
+				expressions[0].traverse(this, scope);
+				if (expressionsLength == 1) {
+					if (isComma()) {
+						this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
+					}
+				} else {
+					for (int i = 1; i < expressionsLength; i++) {
+						this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
+						if (this.preferences.insert_space_after_comma_in_array_initializer) {
+							this.scribe.space();
+						}
+						expressions[i].traverse(this, scope);
+						if (i == expressionsLength - 1) {
+							if (isComma()) {
+								this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_array_initializer);
+							}
+						}
+					}
+				}
+			}
+		}
+		if (this.preferences.insert_new_line_before_closing_brace_in_array_initializer) {
+			this.scribe.printNewLine();
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, this.preferences.insert_space_before_closing_brace_in_array_initializer, true); 
+		if (array_initializer_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
+			this.scribe.unIndent();
+		}	
+	
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(arrayInitializer, numberOfParens);
+		}
+	}
+
+	private void formatCascadingMessageSends(CascadingMethodInvocationFragmentBuilder builder, BlockScope scope) {
+		int size = builder.size();
+		MessageSend[] fragments = builder.fragments();
+		Expression fragment = fragments[0].receiver;
+		int startingPositionInCascade = 1;
+		if (!fragment.isImplicitThis()) {
+			fragment.traverse(this, scope);
+		} else {
+			MessageSend currentMessageSend = fragments[1];
+			final int numberOfParens = (currentMessageSend.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+			if (numberOfParens > 0) {
+				manageOpeningParenthesizedExpression(currentMessageSend, numberOfParens);
+			}
+			ASTNode[] arguments = currentMessageSend.arguments;
+			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
+			this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_message_send);
+			if (arguments != null) {
+				int argumentLength = arguments.length;
+				Alignment argumentsAlignment = this.scribe.createAlignment(
+						"messageArguments", //$NON-NLS-1$
+						Alignment.M_COMPACT_SPLIT,
+						Alignment.R_OUTERMOST,
+						argumentLength,
+						this.scribe.scanner.currentPosition);
+				this.scribe.enterAlignment(argumentsAlignment);
+				boolean okForArguments = false;
+				do {
+					try {
+						if (this.preferences.insert_space_within_message_send) {
+							this.scribe.space();
+						}
+						for (int j = 0; j < argumentLength; j++) {
+							if (j > 0) {
+								this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_messagesend_arguments);
+							}
+							this.scribe.alignFragment(argumentsAlignment, j);
+							if (j > 0 && this.preferences.insert_space_after_comma_in_messagesend_arguments) {
+								this.scribe.space();
+							}
+							arguments[j].traverse(this, scope);
+						}
+						okForArguments = true;
+					} catch (AlignmentException e) {
+						this.scribe.redoAlignment(e);
+					}
+				} while (!okForArguments);
+				this.scribe.exitAlignment(argumentsAlignment, true);
+			}
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_within_message_send);
+			if (numberOfParens > 0) {
+				manageClosingParenthesizedExpression(currentMessageSend, numberOfParens);
+			}
+			startingPositionInCascade = 2;
+		}
+		Alignment cascadingMessageSendAlignment = this.scribe.createAlignment("cascadingMessageSendAlignment", Alignment.M_COMPACT_SPLIT, Alignment.R_INNERMOST, size, this.scribe.scanner.currentPosition); //$NON-NLS-1$
+		this.scribe.enterAlignment(cascadingMessageSendAlignment);
+		boolean ok = false;
+		do {
+			try {
+				this.scribe.alignFragment(cascadingMessageSendAlignment, 0);
+				this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+				for (int i = startingPositionInCascade; i < size; i++) {
+					MessageSend currentMessageSend = fragments[i];
+					final int numberOfParens = (currentMessageSend.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+					if (numberOfParens > 0) {
+						manageOpeningParenthesizedExpression(currentMessageSend, numberOfParens);
+					}
+					ASTNode[] arguments = currentMessageSend.arguments;
+					this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
+					this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_message_send);
+					if (arguments != null) {
+						int argumentLength = arguments.length;
+						Alignment argumentsAlignment = this.scribe.createAlignment(
+								"messageArguments", //$NON-NLS-1$
+								Alignment.M_COMPACT_SPLIT,
+								Alignment.R_OUTERMOST,
+								argumentLength,
+								this.scribe.scanner.currentPosition);
+						this.scribe.enterAlignment(argumentsAlignment);
+						boolean okForArguments = false;
+						do {
+							try {
+								if (this.preferences.insert_space_within_message_send) {
+									this.scribe.space();
+								}
+								for (int j = 0; j < argumentLength; j++) {
+									if (j > 0) {
+										this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_messagesend_arguments);
+									}
+									this.scribe.alignFragment(argumentsAlignment, j);
+									if (j > 0 && this.preferences.insert_space_after_comma_in_messagesend_arguments) {
+										this.scribe.space();
+									}
+									arguments[j].traverse(this, scope);
+								}
+								okForArguments = true;
+							} catch (AlignmentException e) {
+								this.scribe.redoAlignment(e);
+							}
+						} while (!okForArguments);
+						this.scribe.exitAlignment(argumentsAlignment, true);
+					}
+					this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_within_message_send);
+					if (numberOfParens > 0) {
+						manageClosingParenthesizedExpression(currentMessageSend, numberOfParens);
+					}
+					if (i < size - 1) {
+						this.scribe.alignFragment(cascadingMessageSendAlignment, i);
+						this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+					}
+				}
+				ok = true;
+			} catch(AlignmentException e){
+				this.scribe.redoAlignment(e);
+			}
+		} while (!ok);		
+		this.scribe.exitAlignment(cascadingMessageSendAlignment, true);
+	}
+	
+	/*
+	 * Merged traversal of member (types, fields, methods)
+	 */
+	private void formatClassBodyDeclarations(ASTNode[] nodes) {
+		final int FIELD = 1, METHOD = 2, TYPE = 3;
+		this.scribe.lastNumberOfNewLines = 1;
+		ASTNode[] mergedNodes = computeMergedMemberDeclarations(nodes);
+		Alignment memberAlignment = this.scribe.createMemberAlignment("typeMembers", this.preferences.type_member_alignment, 4, this.scribe.scanner.currentPosition); //$NON-NLS-1$
+		this.scribe.enterMemberAlignment(memberAlignment);
+		boolean isChunkStart = false;
+		boolean ok = false;
+		int startIndex = 0;
+		do {
+			try {
+				for (int i = startIndex, max = mergedNodes.length; i < max; i++) {
+					ASTNode member = mergedNodes[i];
+					if (member instanceof FieldDeclaration) {
+						isChunkStart = memberAlignment.checkChunkStart(FIELD, i, this.scribe.scanner.currentPosition);
+						if (member instanceof MultiFieldDeclaration){
+							MultiFieldDeclaration multiField = (MultiFieldDeclaration) member;
+							format(multiField, this, null, isChunkStart, i == 0);
+						} else if (member instanceof Initializer) {
+							int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
+							if (newLineBeforeChunk > 0 && i != 0) {
+								this.scribe.printEmptyLines(newLineBeforeChunk);
+							} else if (i == 0) {
+								int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
+								if (newLinesBeforeFirstClassBodyDeclaration > 0) {
+									this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
+								}
+							}
+							Initializer initializer = (Initializer) member;
+							initializer.traverse(this, null);
+						} else {
+							FieldDeclaration field = (FieldDeclaration) member;
+							format(field, this, null, isChunkStart, i == 0);
+						}
+					} else if (member instanceof AbstractMethodDeclaration) {
+						isChunkStart = memberAlignment.checkChunkStart(METHOD, i, this.scribe.scanner.currentPosition);
+						format((AbstractMethodDeclaration) member, null, isChunkStart, i == 0);
+					} else {
+						isChunkStart = memberAlignment.checkChunkStart(TYPE, i, this.scribe.scanner.currentPosition);
+						format((TypeDeclaration)member, null, isChunkStart, i == 0);
+					}
+					if (isSemiColon()) {
+						this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+						this.scribe.printTrailingComment();
+					}
+					if (i != max - 1) {
+						this.scribe.printNewLine();
+					}
+				}
+				ok = true;
+			} catch(AlignmentException e){
+				startIndex = memberAlignment.chunkStartIndex;
+				this.scribe.redoMemberAlignment(e);
+			}
+		} while (!ok);		
+		this.scribe.exitMemberAlignment(memberAlignment);
+		if (hasComments()) {
+			this.scribe.printNewLine();
+		}
+		this.scribe.printComment();
+	}
+	
+	private void formatEmptyStatement() {
+
+		if (this.preferences.put_empty_statement_on_new_line) {
+			this.scribe.printNewLine();
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		this.scribe.printTrailingComment();
+	}
+
+	private void formatGuardClauseBlock(Block block, BlockScope scope) {
+
+		this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, this.preferences.insert_space_before_block_open_brace);
+		this.scribe.space();
+
+		final Statement[] statements = block.statements;
+		statements[0].traverse(this, scope);
+		this.scribe.space();
+		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE, false, true);
+		this.scribe.printTrailingComment();
+	}	
+
+	private void formatLocalDeclaration(LocalDeclaration localDeclaration, BlockScope scope, boolean insertSpaceBeforeComma, boolean insertSpaceAfterComma) {
+
+		if (!isMultipleLocalDeclaration(localDeclaration)) {
+			if (localDeclaration.modifiers != NO_MODIFIERS) {
+				this.scribe.printModifiers();
+				this.scribe.space();
+			}
+	
+			/*
+			 * Argument type 
+			 */		
+			if (localDeclaration.type != null) {
+				localDeclaration.type.traverse(this, scope);
+			}
+			/*
+			 * Print the argument name
+		 	*/
+			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
+		} else {
+			/*
+			 * Print the argument name
+		 	*/
+			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, false); 
+		}
+		/*
+		 * Check for extra dimensions
+		 */
+		int extraDimensions = getExtraDimension();
+		if (extraDimensions != 0) {
+			 for (int index = 0; index < extraDimensions; index++) {
+			 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+			 	this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			 }
+		}
+	
+		final Expression initialization = localDeclaration.initialization;
+		if (initialization != null) {
+			/*
+			 * Print the method name
+			 */	
+			this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operators);
+			if (!(initialization instanceof ArrayInitializer) && this.preferences.insert_space_after_assignment_operators) {
+				this.scribe.space();
+			}
+			initialization.traverse(this, scope);
+		}
+
+		if (isPartOfMultipleLocalDeclaration()) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, insertSpaceBeforeComma); 
+			if (insertSpaceAfterComma) {
+				this.scribe.space();
+			}
+		}
+	}
+
+	private void formatMessageSend(
+		MessageSend messageSend,
+		BlockScope scope,
+		Alignment messageAlignment) {
+
+		if (messageAlignment != null) {
+			this.scribe.alignFragment(messageAlignment, 0);
+			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier); // selector
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_message_send);
+
+		final Expression[] arguments = messageSend.arguments;
+		if (arguments != null) {
+			int argumentsLength = arguments.length;
+			if (argumentsLength > 1) {
+				Alignment argumentsAlignment = this.scribe.createAlignment(
+						"messageArguments", //$NON-NLS-1$
+						this.preferences.message_send_arguments_alignment,
+						argumentsLength,
+						this.scribe.scanner.currentPosition);
+				this.scribe.enterAlignment(argumentsAlignment);
+				boolean ok = false;
+				do {
+					try {
+						if (this.preferences.insert_space_within_message_send) {
+							this.scribe.space();
+						}
+						for (int i = 0; i < argumentsLength; i++) {
+							if (i > 0) {
+								this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_messagesend_arguments);
+							}
+							this.scribe.alignFragment(argumentsAlignment, i);
+							if (i > 0 && this.preferences.insert_space_after_comma_in_messagesend_arguments) {
+								this.scribe.space();
+							}
+							arguments[i].traverse(this, scope);
+						}
+						ok = true;
+					} catch (AlignmentException e) {
+						this.scribe.redoAlignment(e);
+					}
+				} while (!ok);
+				this.scribe.exitAlignment(argumentsAlignment, true);
+			} else {
+				if (this.preferences.insert_space_within_message_send) {
+						this.scribe.space();
+				}
+				for (int i = 0; i < argumentsLength; i++) {
+					if (i > 0) {
+						this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_messagesend_arguments);
+					}
+					if (i > 0 && this.preferences.insert_space_after_comma_in_messagesend_arguments) {
+						this.scribe.space();
+					}
+					arguments[i].traverse(this, scope);
+				}
+			}
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_arguments);
+	}
+
+	private void formatMethodArguments(
+			AbstractMethodDeclaration methodDeclaration, 
+			boolean spaceBeforeOpenParen, 
+			boolean spaceBetweenEmptyArgument,
+			boolean spaceBeforeClosingParen, 
+			boolean spaceBeforeFirstArgument, 
+			boolean spaceBeforeComma, 
+			boolean spaceAfterComma) {
+				
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, spaceBeforeOpenParen); 
+		
+		final Argument[] arguments = methodDeclaration.arguments;
+		if (arguments != null) {
+			int argumentLength = arguments.length;
+			Alignment argumentsAlignment = this.scribe.createAlignment(
+					"methodArguments",//$NON-NLS-1$
+					this.preferences.method_declaration_arguments_alignment,
+					argumentLength,
+					this.scribe.scanner.currentPosition);
+			this.scribe.enterAlignment(argumentsAlignment);
+			boolean ok = false;
+			do {
+				try {
+					if (spaceBeforeFirstArgument) {
+						this.scribe.space();
+					}
+					for (int i = 0; i < argumentLength; i++) {
+						if (i > 0) {
+							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, spaceBeforeComma);
+						}
+						this.scribe.alignFragment(argumentsAlignment, i);
+						if (i > 0 && spaceAfterComma) {
+							this.scribe.space();
+						}
+						arguments[i].traverse(this, methodDeclaration.scope);
+					}
+					ok = true;
+				} catch (AlignmentException e) {
+					this.scribe.redoAlignment(e);
+				}
+			} while (!ok);
+			this.scribe.exitAlignment(argumentsAlignment, true);
+		
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBeforeClosingParen); 
+		} else {
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, spaceBetweenEmptyArgument); 
+		}	
+	}
+
+	private void formatOpeningBrace(String bracePosition, boolean insertSpaceBeforeBrace) {
+	
+		if (bracePosition.equals(DefaultCodeFormatterConstants.NEXT_LINE)) {
+			this.scribe.printNewLine();
+		} else if (bracePosition.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
+			this.scribe.printNewLine();
+			this.scribe.indent();
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameLBRACE, insertSpaceBeforeBrace);
+
+		this.scribe.printTrailingComment();
+	}
+
+	private void formatStatements(BlockScope scope, final Statement[] statements, boolean insertNewLineAfterLastStatement) {
+		int statementsLength = statements.length;
+		for (int i = 0; i < statementsLength; i++) {
+			final Statement statement = statements[i];
+			if (i > 0 && (statements[i - 1] instanceof EmptyStatement) && !(statement instanceof EmptyStatement)) {
+				this.scribe.printNewLine();
+			}
+			statement.traverse(this, scope);
+			if (statement instanceof Expression) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+				this.scribe.printTrailingComment();
+				if (i != statementsLength - 1 || (i == statementsLength - 1 && insertNewLineAfterLastStatement)) {
+					this.scribe.printNewLine();
+				}
+			} else if (statement instanceof LocalDeclaration) {
+				LocalDeclaration currentLocal = (LocalDeclaration) statement;
+				if (i < (statementsLength - 1)) {
+					/* 
+					 * We need to check that the next statement is a local declaration
+					 */
+					if (statements[i + 1] instanceof LocalDeclaration) {
+						LocalDeclaration nextLocal = (LocalDeclaration) statements[i + 1];
+						if (currentLocal.declarationSourceStart != nextLocal.declarationSourceStart) {
+							this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+							this.scribe.printTrailingComment();
+							if (i != statementsLength - 1 || (i == statementsLength - 1 && insertNewLineAfterLastStatement)) {
+								this.scribe.printNewLine();
+							}
+						}
+					} else {
+						this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+						this.scribe.printTrailingComment();
+						if (i != statementsLength - 1 || (i == statementsLength - 1 && insertNewLineAfterLastStatement)) {
+							this.scribe.printNewLine();
+						}
+					}
+				} else {
+					this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+					this.scribe.printTrailingComment();
+					if (i != statementsLength - 1 || (i == statementsLength - 1 && insertNewLineAfterLastStatement)) {
+						this.scribe.printNewLine();
+					}
+				}
+			} else if (i != statementsLength - 1) {
+				if (!(statement instanceof EmptyStatement) && !(statements[i + 1] instanceof EmptyStatement)) {
+					this.scribe.printNewLine();
+				}
+			} else if (i == statementsLength - 1 && insertNewLineAfterLastStatement) {
+				this.scribe.printNewLine();
+			}
+		}
+	}
+	
+	private void formatThrowsClause(
+		AbstractMethodDeclaration methodDeclaration,
+		boolean spaceBeforeComma,
+		boolean spaceAfterComma) {
+			
+		final TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
+		if (thrownExceptions != null) {
+			int thrownExceptionsLength = thrownExceptions.length;
+			Alignment throwsAlignment = this.scribe.createAlignment(
+					"throws",//$NON-NLS-1$
+					this.preferences.method_throws_clause_alignment,
+					thrownExceptionsLength, // throws is the first token
+					this.scribe.scanner.currentPosition);
+		
+			this.scribe.enterAlignment(throwsAlignment);
+			boolean ok = false;
+			do {
+				try {
+					this.scribe.alignFragment(throwsAlignment, 0);
+					this.scribe.printNextToken(TerminalTokens.TokenNamethrows, true); 
+		
+					for (int i = 0; i < thrownExceptionsLength; i++) {
+						if (i > 0) {
+							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, spaceBeforeComma);
+							this.scribe.alignFragment(throwsAlignment, i);
+							if (spaceAfterComma) {
+								this.scribe.space();
+							}
+						} else {
+							this.scribe.space();
+						}
+						thrownExceptions[i].traverse(this, methodDeclaration.scope);
+					}
+					ok = true;
+				} catch (AlignmentException e) {
+					this.scribe.redoAlignment(e);
+				}
+			} while (!ok);
+			this.scribe.exitAlignment(throwsAlignment, true);
+		}
+	}
+
+	/*
+	 * Merged traversal of member (types, fields, methods)
+	 */
+	private void formatTypeMembers(TypeDeclaration typeDeclaration) {
+		Alignment memberAlignment = this.scribe.createMemberAlignment("typeMembers", this.preferences.type_member_alignment, 3, this.scribe.scanner.currentPosition); //$NON-NLS-1$
+		this.scribe.enterMemberAlignment(memberAlignment);
+		ASTNode[] members = computeMergedMemberDeclarations(typeDeclaration);
+		boolean isChunkStart = false;
+		boolean ok = false;
+		int startIndex = 0;
+		do {
+			try {
+				for (int i = startIndex, max = members.length; i < max; i++) {
+					ASTNode member = members[i];
+					if (member instanceof FieldDeclaration) {
+						isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_FIELD, i, this.scribe.scanner.currentPosition);
+						if (member instanceof MultiFieldDeclaration){
+							MultiFieldDeclaration multiField = (MultiFieldDeclaration) member;
+							
+							if (multiField.isStatic()) {
+								format(multiField, this, typeDeclaration.staticInitializerScope, isChunkStart, i == 0);
+							} else {
+								format(multiField, this, typeDeclaration.initializerScope, isChunkStart, i == 0);
+							}					
+						} else if (member instanceof Initializer) {
+							int newLineBeforeChunk = isChunkStart ? this.preferences.blank_lines_before_new_chunk : 0;
+							if (newLineBeforeChunk > 0 && i != 0) {
+								this.scribe.printEmptyLines(newLineBeforeChunk);
+							} else if (i == 0) {
+								int newLinesBeforeFirstClassBodyDeclaration = this.preferences.blank_lines_before_first_class_body_declaration;
+								if (newLinesBeforeFirstClassBodyDeclaration > 0) {
+									this.scribe.printEmptyLines(newLinesBeforeFirstClassBodyDeclaration);
+								}
+							}
+							Initializer initializer = (Initializer) member;
+							if (initializer.isStatic()) {
+								initializer.traverse(this, typeDeclaration.staticInitializerScope);
+							} else {
+								initializer.traverse(this, typeDeclaration.initializerScope);
+							}					
+						} else {
+							FieldDeclaration field = (FieldDeclaration) member;
+							if (field.isStatic()) {
+								format(field, this, typeDeclaration.staticInitializerScope, isChunkStart, i == 0);
+							} else {
+								format(field, this, typeDeclaration.initializerScope, isChunkStart, i == 0);
+							}					
+						}
+					} else if (member instanceof AbstractMethodDeclaration) {
+						isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_METHOD, i, this.scribe.scanner.currentPosition);
+						format((AbstractMethodDeclaration) member, typeDeclaration.scope, isChunkStart, i == 0);
+					} else {
+						isChunkStart = memberAlignment.checkChunkStart(Alignment.CHUNK_TYPE, i, this.scribe.scanner.currentPosition);
+						format((TypeDeclaration)member, typeDeclaration.scope, isChunkStart, i == 0);
+					}
+					if (isSemiColon()) {
+						this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+						this.scribe.printTrailingComment();
+					}
+					this.scribe.printNewLine();
+					// realign to the proper value
+					if (this.scribe.memberAlignment != null) {
+						// select the last alignment
+						this.scribe.indentationLevel = this.scribe.memberAlignment.originalIndentationLevel;
+					}
+				}
+				ok = true;
+			} catch(AlignmentException e){
+				startIndex = memberAlignment.chunkStartIndex;
+				this.scribe.redoMemberAlignment(e);
+			}
+		} while (!ok);		
+		this.scribe.exitMemberAlignment(memberAlignment);
+	}
+
+	private void formatTypeOpeningBrace(String bracePosition, boolean insertSpaceBeforeBrace, TypeDeclaration typeDeclaration) {
+		int fieldCount = (typeDeclaration.fields == null) ? 0 : typeDeclaration.fields.length;
+		int methodCount = (typeDeclaration.methods == null) ? 0 : typeDeclaration.methods.length;
+		int typeCount = (typeDeclaration.memberTypes == null) ? 0 : typeDeclaration.memberTypes.length;
+	
+		if (methodCount == 1 && typeDeclaration.methods[0].isDefaultConstructor()) {
+			methodCount = 0;
+		}
+		final int memberLength = fieldCount+methodCount+typeCount;
+
+		boolean insertNewLine = memberLength > 0;
+		
+		if (!insertNewLine) {
+			if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+				insertNewLine = this.preferences.insert_new_line_in_empty_anonymous_type_declaration;
+			} else {
+				insertNewLine = this.preferences.insert_new_line_in_empty_type_declaration;
+			}
+		}
+	
+		formatOpeningBrace(bracePosition, insertSpaceBeforeBrace);
+		
+		if (insertNewLine) {
+			this.scribe.printNewLine();
+		}
+	}
+
+	private int getExtraDimension() {
+
+		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
+		int dimensions = 0;
+		try {
+			int token;
+			while ((token = this.localScanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameRBRACKET://166 
+						dimensions++;
+						break;
+					case TerminalTokens.TokenNameIdentifier ://90						
+					case TerminalTokens.TokenNameLBRACE ://90						
+					case TerminalTokens.TokenNameLPAREN :
+					case TerminalTokens.TokenNameCOMMA ://90
+					case TerminalTokens.TokenNameEQUAL ://167
+					case TerminalTokens.TokenNameSEMICOLON ://64
+					case TerminalTokens.TokenNameRPAREN : //86
+						return dimensions;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return dimensions;
+	}
+
+	private boolean isComma() {
+
+		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
+		try {
+			int token = this.localScanner.getNextToken();
+			loop: while(true) {
+				switch(token) {
+					case TerminalTokens.TokenNameCOMMENT_BLOCK :
+					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+					case TerminalTokens.TokenNameCOMMENT_LINE :
+						token = this.localScanner.getNextToken();
+						continue loop;
+					default:
+						break loop;
+				}
+			}
+			return  token == TerminalTokens.TokenNameCOMMA;
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return false;
+	}
+
+	private boolean isGuardClause(Block block) {
+		return block.statements != null 
+				&& block.statements.length == 1
+				&& (block.statements[0] instanceof ReturnStatement
+					|| block.statements[0] instanceof ThrowStatement);
+	}	
+
+	private boolean isMinus() {
+
+		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
+		try {
+			int token = this.localScanner.getNextToken();
+			loop: while(true) {
+				switch(token) {
+					case TerminalTokens.TokenNameCOMMENT_BLOCK :
+					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+					case TerminalTokens.TokenNameCOMMENT_LINE :
+						token = this.localScanner.getNextToken();
+						continue loop;
+					default:
+						break loop;
+				}
+			}
+			return  token == TerminalTokens.TokenNameMINUS;
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return false;
+	}
+
+	private boolean isMultipleLocalDeclaration(LocalDeclaration localDeclaration) {
+
+		if (localDeclaration.declarationSourceStart == this.lastLocalDeclarationSourceStart) return true;
+		this.lastLocalDeclarationSourceStart = localDeclaration.declarationSourceStart;
+		return false;
+	}
+
+	private boolean isPartOfMultipleLocalDeclaration() {
+		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
+		try {
+			int token;
+			while ((token = this.localScanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(token) {
+					case TerminalTokens.TokenNameCOMMA ://90
+						return true;
+					case TerminalTokens.TokenNameCOMMENT_BLOCK :
+					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+					case TerminalTokens.TokenNameCOMMENT_LINE :
+						break;
+					default:
+						return false;
+				}
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return false;
+	}
+
+	private boolean isSemiColon() {
+
+		this.localScanner.resetTo(this.scribe.scanner.currentPosition, this.scribe.scannerEndPosition - 1);
+		try {
+			int token = this.localScanner.getNextToken();
+			loop: while(true) {
+				switch(token) {
+					case TerminalTokens.TokenNameCOMMENT_BLOCK :
+					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+					case TerminalTokens.TokenNameCOMMENT_LINE :
+						token = this.localScanner.getNextToken();
+						continue loop;
+					default:
+						break loop;
+				}
+			}
+			return  token == TerminalTokens.TokenNameSEMICOLON;
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return false;
+	}
+
+	private boolean hasComments() {
+
+		this.localScanner.resetTo(this.scribe.scanner.startPosition, this.scribe.scannerEndPosition - 1);
+		try {
+			switch(this.localScanner.getNextToken()) {
+				case TerminalTokens.TokenNameCOMMENT_BLOCK :
+				case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+				case TerminalTokens.TokenNameCOMMENT_LINE :
+					return true;
+			}
+		} catch(InvalidInputException e) {
+			// ignore
+		}
+		return false;
+	}
+
+	private void manageClosingParenthesizedExpression(Expression expression, int numberOfParens) {
+		for (int i = 0; i < numberOfParens; i++) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_parenthesized_expression);
+		}
+	}
+
+	private void manageOpeningParenthesizedExpression(Expression expression, int numberOfParens) {
+		for (int i = 0; i < numberOfParens; i++) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_open_paren_in_parenthesized_expression);
+			if (this.preferences.insert_space_after_open_paren_in_parenthesized_expression) {
+				this.scribe.space();
+			}
+		}
+	}
+			
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.AllocationExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		AllocationExpression allocationExpression,
+		BlockScope scope) {
+		// 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
+
+		final int numberOfParens = (allocationExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(allocationExpression, numberOfParens);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNamenew);
+		this.scribe.space();
+		allocationExpression.type.traverse(this, scope);
+		
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_message_send);
+
+		final Expression[] arguments = allocationExpression.arguments;
+		if (arguments != null) {
+			int argumentLength = arguments.length;
+			Alignment argumentsAlignment =this.scribe.createAlignment(
+					"allocation",//$NON-NLS-1$
+					this.preferences.allocation_expression_arguments_alignment,
+					argumentLength,
+					this.scribe.scanner.currentPosition);
+			this.scribe.enterAlignment(argumentsAlignment);
+			boolean ok = false;
+			do {
+				try {
+					if (this.preferences.insert_space_within_message_send) {
+						this.scribe.space();
+					}
+					for (int i = 0; i < argumentLength; i++) {
+						if (i > 0) {
+							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_allocation_expression);
+						}
+						this.scribe.alignFragment(argumentsAlignment, i);
+						if (i > 0 && this.preferences.insert_space_after_comma_in_allocation_expression) {
+							this.scribe.space();
+						}
+						arguments[i].traverse(this, scope);
+					}
+					ok = true;
+				} catch (AlignmentException e) {
+					this.scribe.redoAlignment(e);
+				}
+			} while (!ok);
+			this.scribe.exitAlignment(argumentsAlignment, true);
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_within_message_send); 
+		} else {
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_arguments); 
+		}
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(allocationExpression, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		AND_AND_Expression and_and_Expression,
+		BlockScope scope) {
+			
+		return dumpBinaryExpression(and_and_Expression, TerminalTokens.TokenNameAND_AND, scope);
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Argument, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(Argument argument, BlockScope scope) {
+
+		if (argument.modifiers != NO_MODIFIERS) {
+			this.scribe.printModifiers();
+			this.scribe.space();
+		}
+
+		/*
+		 * Argument type 
+		 */		
+		if (argument.type != null) {
+			argument.type.traverse(this, scope);
+		}
+		
+		/*
+		 * Print the argument name
+		 */	
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
+
+
+		/*
+		 * Check for extra dimensions
+		 */
+		int extraDimensions = getExtraDimension();
+		if (extraDimensions != 0) {
+			 for (int i = 0; i < extraDimensions; i++) {
+			 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+			 	this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			 }
+		}
+		
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		ArrayAllocationExpression arrayAllocationExpression,
+		BlockScope scope) {
+
+			final int numberOfParens = (arrayAllocationExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+			if (numberOfParens > 0) {
+				manageOpeningParenthesizedExpression(arrayAllocationExpression, numberOfParens);
+			}
+			this.scribe.printNextToken(TerminalTokens.TokenNamenew);
+			this.scribe.space();
+			arrayAllocationExpression.type.traverse(this, scope);
+			
+			final Expression[] dimensions = arrayAllocationExpression.dimensions;
+			int dimensionsLength = dimensions.length;
+			for (int i = 0; i < dimensionsLength; i++) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+				if (dimensions[i] != null) {
+					dimensions[i].traverse(this, scope);
+				}
+				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			}
+			final ArrayInitializer initializer = arrayAllocationExpression.initializer;
+			if (initializer != null) {
+				formatArrayInitializer(initializer, scope, this.preferences.insert_space_before_opening_brace_in_array_initializer);
+			}
+
+			if (numberOfParens > 0) {
+				manageClosingParenthesizedExpression(arrayAllocationExpression, numberOfParens);
+			}
+			return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayInitializer, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) {
+		formatArrayInitializer(arrayInitializer, scope, this.preferences.insert_space_before_opening_brace_in_array_initializer || this.preferences.insert_space_after_assignment_operators);
+		return false;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+		BlockScope scope) {
+
+			final int numberOfParens = (arrayQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+			if (numberOfParens > 0) {
+				manageOpeningParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
+			}
+			this.scribe.printQualifiedReference(arrayQualifiedTypeReference.sourceEnd - 1);
+			int dimensions = getExtraDimension();
+			if (dimensions != 0) {
+				for (int i = 0; i < dimensions; i++) {
+					this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+					this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+				}
+			}
+			if (numberOfParens > 0) {
+				manageClosingParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
+			}
+			return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
+	 */
+	public boolean visit(
+		ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+		ClassScope scope) {
+
+			final int numberOfParens = (arrayQualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+			if (numberOfParens > 0) {
+				manageOpeningParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
+			}
+			this.scribe.printQualifiedReference(arrayQualifiedTypeReference.sourceEnd - 1);
+			int dimensions = getExtraDimension();
+			if (dimensions != 0) {
+				for (int i = 0; i < dimensions; i++) {
+					this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+					this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+				}
+			}
+			if (numberOfParens > 0) {
+				manageClosingParenthesizedExpression(arrayQualifiedTypeReference, numberOfParens);
+			}
+			return false;
+	}
+
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(ArrayReference arrayReference, BlockScope scope) {
+
+		final int numberOfParens = (arrayReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(arrayReference, numberOfParens);
+		}
+		arrayReference.receiver.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET, this.preferences.insert_space_before_bracket_in_array_reference);
+		if (this.preferences.insert_space_between_brackets_in_array_reference) {
+			this.scribe.space();
+		}
+		arrayReference.position.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET, this.preferences.insert_space_between_brackets_in_array_reference);
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(arrayReference, numberOfParens);
+		}
+		return false;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		ArrayTypeReference arrayTypeReference,
+		BlockScope scope) {
+
+		final int numberOfParens = (arrayTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(arrayTypeReference, numberOfParens);
+		}
+		this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS, false, true);
+		
+		int dimensions = getExtraDimension();
+		if (dimensions != 0) {
+			if (this.preferences.insert_space_before_bracket_in_array_type_reference) {
+				this.scribe.space();
+			}
+			for (int i = 0; i < dimensions; i++) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+				if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
+					this.scribe.space();
+				}
+				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			}
+		}
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(arrayTypeReference, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
+	 */
+	public boolean visit(
+		ArrayTypeReference arrayTypeReference,
+		ClassScope scope) {
+
+		final int numberOfParens = (arrayTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) { 
+			manageOpeningParenthesizedExpression(arrayTypeReference, numberOfParens);
+		}
+		this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS, false, true);
+		int dimensions = getExtraDimension();
+		if (dimensions != 0) {
+			if (this.preferences.insert_space_before_bracket_in_array_type_reference) {
+				this.scribe.space();
+			}
+			for (int i = 0; i < dimensions; i++) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+				if (this.preferences.insert_space_between_brackets_in_array_type_reference) {
+					this.scribe.space();
+				}
+				this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			}
+		}
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(arrayTypeReference, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.AssertStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(AssertStatement assertStatement, BlockScope scope) {
+		
+		this.scribe.printNextToken(TerminalTokens.TokenNameassert);
+		this.scribe.space();
+		assertStatement.assertExpression.traverse(this, scope);
+		
+		if (assertStatement.exceptionArgument != null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_assert);
+			if (this.preferences.insert_space_after_colon_in_assert) {
+				this.scribe.space();
+			}
+			assertStatement.exceptionArgument.traverse(this, scope);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);		
+		this.scribe.printTrailingComment();
+		return false;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Assignment, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(Assignment assignment, BlockScope scope) {
+
+		final int numberOfParens = (assignment.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(assignment, numberOfParens);
+		}
+		assignment.lhs.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameEQUAL, this.preferences.insert_space_before_assignment_operators);
+		if (!(assignment.expression instanceof ArrayInitializer) && this.preferences.insert_space_after_assignment_operators) {
+			this.scribe.space();
+		}
+		assignment.expression.traverse(this, scope);
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(assignment, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.BinaryExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
+
+		switch((binaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) {
+			case OperatorIds.AND :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameAND, scope);
+			case OperatorIds.DIVIDE :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameDIVIDE, scope);
+			case OperatorIds.GREATER :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameGREATER, scope);
+			case OperatorIds.GREATER_EQUAL :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameGREATER_EQUAL, scope);
+			case OperatorIds.LEFT_SHIFT :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameLEFT_SHIFT, scope);
+			case OperatorIds.LESS :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameLESS, scope);
+			case OperatorIds.LESS_EQUAL :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameLESS_EQUAL, scope);
+			case OperatorIds.MINUS :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameMINUS, scope);
+			case OperatorIds.MULTIPLY :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameMULTIPLY, scope);
+			case OperatorIds.OR :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameOR, scope);
+			case OperatorIds.PLUS :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNamePLUS, scope);
+			case OperatorIds.REMAINDER :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameREMAINDER, scope);
+			case OperatorIds.RIGHT_SHIFT :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameRIGHT_SHIFT, scope);
+			case OperatorIds.UNSIGNED_RIGHT_SHIFT :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT, scope);
+			case OperatorIds.XOR :
+				return dumpBinaryExpression(binaryExpression, TerminalTokens.TokenNameXOR, scope);
+			default:
+				throw new IllegalStateException();
+		}
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Block, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(Block block, BlockScope scope) {
+	
+		String block_brace_position = this.preferences.block_brace_position;
+		formatOpeningBrace(block_brace_position, this.preferences.insert_space_before_block_open_brace);
+		final Statement[] statements = block.statements;
+		if (statements != null) {
+			this.scribe.printNewLine();
+			if (this.preferences.indent_block_statements) {
+				this.scribe.indent();
+			}
+			formatStatements(scope, statements, true);
+			this.scribe.printComment();
+	
+			if (this.preferences.indent_block_statements) {
+				this.scribe.unIndent();
+			}
+		} else if (this.preferences.insert_new_line_in_empty_block) {
+			this.scribe.printNewLine();
+			if (this.preferences.indent_block_statements) {
+				this.scribe.indent();
+			}
+			this.scribe.printComment();
+	
+			if (this.preferences.indent_block_statements) {
+				this.scribe.unIndent();
+			}
+		} else {
+			if (this.preferences.indent_block_statements) {
+				this.scribe.indent();
+			}
+			this.scribe.printComment();
+	
+			if (this.preferences.indent_block_statements) {
+				this.scribe.unIndent();
+			}
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
+		this.scribe.printTrailingComment();
+		if (block_brace_position.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
+			this.scribe.unIndent();
+		}		
+		return false;	
+	}
+
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Break, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(BreakStatement breakStatement, BlockScope scope) {
+		
+		this.scribe.printNextToken(TerminalTokens.TokenNamebreak);
+		if (breakStatement.label != null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		this.scribe.printTrailingComment();
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Case, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(CaseStatement caseStatement, BlockScope scope) {		
+		if (caseStatement.constantExpression == null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNamedefault);
+			this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_default);
+		} else {
+			this.scribe.printNextToken(TerminalTokens.TokenNamecase);
+			this.scribe.space();
+			caseStatement.constantExpression.traverse(this, scope);
+			this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_case);
+		}
+		return false;
+	}
+
+
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.CastExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(CastExpression castExpression, BlockScope scope) {
+
+		final int numberOfParens = (castExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(castExpression, numberOfParens);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN);
+		if (this.preferences.insert_space_after_opening_paren_in_cast) {
+			this.scribe.space();
+		}
+		castExpression.type.traverse(this, scope);
+
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_before_closing_paren_in_cast);
+		if (this.preferences.insert_space_after_closing_paren_in_cast) {
+			this.scribe.space();
+		}
+		castExpression.expression.traverse(this, scope);
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(castExpression, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.CharLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(CharLiteral charLiteral, BlockScope scope) {
+
+		final int numberOfParens = (charLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(charLiteral, numberOfParens);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameCharacterLiteral);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(charLiteral, numberOfParens);
+		}
+		return false;
+	}
+
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(ClassLiteralAccess classLiteral, BlockScope scope) {
+
+		final int numberOfParens = (classLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(classLiteral, numberOfParens);
+		}
+		classLiteral.type.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+		this.scribe.printNextToken(TerminalTokens.TokenNameclass);
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(classLiteral, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Clinit, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
+	 */
+	public boolean visit(Clinit clinit, ClassScope scope) {
+
+		return false;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration, org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope)
+	 */
+	public boolean visit(
+		CompilationUnitDeclaration compilationUnitDeclaration,
+		CompilationUnitScope scope) {
+		
+		/* 
+		 * Package declaration
+		 */
+		if (compilationUnitDeclaration.currentPackage != null) {
+			// OPTION
+			// dump the package keyword
+			int blankLinesBeforePackage = this.preferences.blank_lines_before_package;
+			if (blankLinesBeforePackage > 0) {
+				this.scribe.printEmptyLines(blankLinesBeforePackage - 1);
+			}
+			this.scribe.printNextToken(TerminalTokens.TokenNamepackage);
+			this.scribe.space();
+			this.scribe.printQualifiedReference(compilationUnitDeclaration.currentPackage.sourceEnd);
+			this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+			this.scribe.printTrailingComment();
+			int blankLinesAfterPackage = this.preferences.blank_lines_after_package;
+			if (blankLinesAfterPackage > 0) {
+				this.scribe.printEmptyLines(blankLinesAfterPackage);
+			} else {
+				this.scribe.printNewLine();
+			}			
+		} else {
+			this.scribe.printComment();
+		}
+		
+		/*
+		 * Import statements
+		 */
+		final ImportReference[] imports = compilationUnitDeclaration.imports;
+		if (imports != null) {
+			int blankLinesBeforeImports = this.preferences.blank_lines_before_imports;
+			if (blankLinesBeforeImports > 0) {
+				this.scribe.printEmptyLines(blankLinesBeforeImports);
+			}
+			int importLength = imports.length;
+			for (int i = 0; i < importLength; i++) {
+				imports[i].traverse(this, scope);
+			}			
+			
+			int blankLinesAfterImports = this.preferences.blank_lines_after_imports;
+			if (blankLinesAfterImports > 0) {
+				this.scribe.printEmptyLines(blankLinesAfterImports);
+			}
+		}
+
+		/*
+		 * Type declarations
+		 */
+		final TypeDeclaration[] types = compilationUnitDeclaration.types;
+		if (types != null) {
+			int typesLength = types.length;
+			for (int i = 0; i < typesLength - 1; i++) {
+				types[i].traverse(this, scope);
+				this.scribe.printComment();
+				this.scribe.printNewLine();
+			}
+			format(types[typesLength - 1]);
+		}
+		this.scribe.printComment();
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.CompoundAssignment, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		CompoundAssignment compoundAssignment,
+		BlockScope scope) {
+			
+		final int numberOfParens = (compoundAssignment.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(compoundAssignment, numberOfParens);
+		}
+		compoundAssignment.lhs.traverse(this, scope);
+		
+		/*
+		 * Print the operator
+		 */
+		int operator;
+		switch(compoundAssignment.operator) {
+			case OperatorIds.PLUS :
+				operator = TerminalTokens.TokenNamePLUS_EQUAL;
+				break;
+			case OperatorIds.MINUS :
+				operator = TerminalTokens.TokenNameMINUS_EQUAL;
+				break;
+			case OperatorIds.MULTIPLY :
+				operator = TerminalTokens.TokenNameMULTIPLY_EQUAL;
+				break;
+			case OperatorIds.DIVIDE :
+				operator = TerminalTokens.TokenNameDIVIDE_EQUAL;
+				break;
+			case OperatorIds.AND :
+				operator = TerminalTokens.TokenNameAND_EQUAL;
+				break;
+			case OperatorIds.OR :
+				operator = TerminalTokens.TokenNameOR_EQUAL;
+				break;
+			case OperatorIds.XOR :
+				operator = TerminalTokens.TokenNameXOR_EQUAL;
+				break;
+			case OperatorIds.REMAINDER :
+				operator = TerminalTokens.TokenNameREMAINDER_EQUAL;
+				break;
+			case OperatorIds.LEFT_SHIFT :
+				operator = TerminalTokens.TokenNameLEFT_SHIFT_EQUAL;
+				break;
+			case OperatorIds.RIGHT_SHIFT :
+				operator = TerminalTokens.TokenNameRIGHT_SHIFT_EQUAL;
+				break;
+			default: // OperatorIds.UNSIGNED_RIGHT_SHIFT :
+				operator = TerminalTokens.TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL;
+		}
+		
+		this.scribe.printNextToken(operator, this.preferences.insert_space_before_assignment_operators);
+		if (this.preferences.insert_space_after_assignment_operators) {
+			this.scribe.space();
+		}
+		compoundAssignment.expression.traverse(this, scope);
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(compoundAssignment, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+     * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ConditionalExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+     */
+    public boolean visit(
+    	ConditionalExpression conditionalExpression,
+    	BlockScope scope) {
+    
+    	final int numberOfParens = (conditionalExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+    	if (numberOfParens > 0) {
+    		manageOpeningParenthesizedExpression(conditionalExpression, numberOfParens);
+    	}
+    	conditionalExpression.condition.traverse(this, scope);
+    
+    	Alignment conditionalExpressionAlignment =this.scribe.createAlignment(
+    			"conditionalExpression", //$NON-NLS-1$
+    			this.preferences.conditional_expression_alignment,
+    			2,
+    			this.scribe.scanner.currentPosition);
+    
+    	this.scribe.enterAlignment(conditionalExpressionAlignment);
+    	boolean ok = false;
+    	do {
+    		try {
+    			this.scribe.alignFragment(conditionalExpressionAlignment, 0);
+    			this.scribe.printNextToken(TerminalTokens.TokenNameQUESTION, this.preferences.insert_space_before_question_in_conditional);
+    
+    			if (this.preferences.insert_space_after_question_in_conditional) {
+    				this.scribe.space();
+    			}
+    			conditionalExpression.valueIfTrue.traverse(this, scope);
+    			this.scribe.printTrailingComment();
+    			this.scribe.alignFragment(conditionalExpressionAlignment, 1);
+    			this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_conditional);
+    
+    			if (this.preferences.insert_space_after_colon_in_conditional) {
+    				this.scribe.space();
+    			}
+    			conditionalExpression.valueIfFalse.traverse(this, scope);
+    
+    			ok = true;
+    		} catch (AlignmentException e) {
+    			this.scribe.redoAlignment(e);
+    		}
+    	} while (!ok);
+    	this.scribe.exitAlignment(conditionalExpressionAlignment, true);
+    		
+    	if (numberOfParens > 0) {
+    		manageClosingParenthesizedExpression(conditionalExpression, numberOfParens);
+    	}
+    	return false;	
+    }
+
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
+	 */
+	public boolean visit(
+		ConstructorDeclaration constructorDeclaration,
+		ClassScope scope) {
+			
+		if (constructorDeclaration.ignoreFurtherInvestigation) {
+			this.scribe.printComment();
+			this.scribe.scanner.resetTo(constructorDeclaration.declarationSourceEnd + 1, this.scribe.scannerEndPosition);
+			this.scribe.printTrailingComment();
+			return false;
+		}
+		this.scribe.printModifiers();
+		this.scribe.space();
+		/*
+		 * Print the method name
+		 */	
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
+
+		formatMethodArguments(
+			constructorDeclaration, 
+			this.preferences.insert_space_before_method_declaration_open_paren,
+			this.preferences.insert_space_between_empty_arguments,
+			this.preferences.insert_space_before_closing_paren,
+			this.preferences.insert_space_before_first_argument,
+			this.preferences.insert_space_before_comma_in_constructor_arguments,
+			this.preferences.insert_space_after_comma_in_constructor_arguments);
+
+		formatThrowsClause(
+				constructorDeclaration,
+				this.preferences.insert_space_before_comma_in_constructor_throws,
+				this.preferences.insert_space_after_comma_in_constructor_throws);
+
+		if (!constructorDeclaration.isNative() && !constructorDeclaration.isAbstract()) {
+			/*
+			 * Method body
+			 */
+			String method_declaration_brace = this.preferences.method_declaration_brace_position;
+			formatOpeningBrace(method_declaration_brace, this.preferences.insert_space_before_method_open_brace);
+			final int numberOfBlankLinesAtBeginningOfMethodBody = this.preferences.number_of_blank_lines_to_insert_at_beginning_of_method_body;
+			if (numberOfBlankLinesAtBeginningOfMethodBody > 0) {
+				this.scribe.printEmptyLines(numberOfBlankLinesAtBeginningOfMethodBody);
+			}
+			if (constructorDeclaration.constructorCall != null && !constructorDeclaration.constructorCall.isImplicitSuper()) {
+				this.scribe.printNewLine();
+				if (this.preferences.indent_block_statements) {
+					this.scribe.indent();
+				}
+				constructorDeclaration.constructorCall.traverse(this, constructorDeclaration.scope);
+				if (this.preferences.indent_block_statements) {
+					this.scribe.unIndent();
+				}
+			}
+			final Statement[] statements = constructorDeclaration.statements;
+			if (statements != null) {
+				this.scribe.printNewLine();
+				if (this.preferences.indent_block_statements) {
+					this.scribe.indent();
+				}
+				formatStatements(constructorDeclaration.scope, statements, true);
+				this.scribe.printComment();
+				if (this.preferences.indent_block_statements) {
+					this.scribe.unIndent();
+				}
+			} else if (this.preferences.insert_new_line_in_empty_method_body) {
+				this.scribe.printNewLine();
+				if (this.preferences.indent_block_statements) {
+					this.scribe.indent();
+				}
+				this.scribe.printComment();
+				if (this.preferences.indent_block_statements) {
+					this.scribe.unIndent();
+				}
+			}
+			this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
+			this.scribe.printTrailingComment();
+			if (method_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
+				this.scribe.unIndent();
+			}
+		} else {
+			// no method body
+			this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+			this.scribe.printTrailingComment();
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Continue, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(ContinueStatement continueStatement, BlockScope scope) {
+
+		this.scribe.printNextToken(TerminalTokens.TokenNamecontinue);
+		if (continueStatement.label != null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		this.scribe.printTrailingComment();
+		return false;
+	}
+
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.DoStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(DoStatement doStatement, BlockScope scope) {
+
+		this.scribe.printNextToken(TerminalTokens.TokenNamedo);
+		
+		final Statement action = doStatement.action;
+		if (action != null) {
+			if (action instanceof Block) {
+				action.traverse(this, scope);
+			} else {
+				this.scribe.printNewLine();
+				this.scribe.indent();
+				action.traverse(this, scope);
+				this.scribe.unIndent();
+				this.scribe.printNewLine();
+			}
+			if (action instanceof Expression) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+				this.scribe.printTrailingComment();
+				this.scribe.printNewLine();
+			}
+		} else {
+			this.scribe.indent();
+			/*
+			 * This is an empty statement
+			 */
+			formatEmptyStatement(); 
+			this.scribe.unIndent();
+		}
+		
+		if (this.preferences.insert_new_line_in_control_statements) {
+			this.scribe.printNewLine();
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNamewhile, this.preferences.insert_space_after_block_close_brace);
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_while_condition);
+		
+		if (this.preferences.insert_space_in_while_condition) {
+			this.scribe.space();
+		}
+		
+		doStatement.condition.traverse(this, scope);
+		
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_in_while_condition);
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		this.scribe.printTrailingComment();
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.DoubleLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {
+
+		final int numberOfParens = (doubleLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(doubleLiteral, numberOfParens);
+		}
+		Constant constant = doubleLiteral.constant;
+		if (constant != null && constant.doubleValue() < 0) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);			
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameDoubleLiteral);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(doubleLiteral, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.EmptyStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(EmptyStatement statement, BlockScope scope) {
+
+		formatEmptyStatement();
+		return false;	
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.EqualExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(EqualExpression equalExpression, BlockScope scope) {
+
+		if ((equalExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT == OperatorIds.EQUAL_EQUAL) {
+			return dumpEqualityExpression(equalExpression, TerminalTokens.TokenNameEQUAL_EQUAL, scope);
+		} else {
+			return dumpEqualityExpression(equalExpression, TerminalTokens.TokenNameNOT_EQUAL, scope);
+		}			
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		ExplicitConstructorCall explicitConstructor,
+		BlockScope scope) {
+
+		if (explicitConstructor.isImplicitSuper()) {
+			return false;
+		}
+		final Expression qualification = explicitConstructor.qualification;
+		if (qualification != null) {
+			qualification.traverse(this, scope);
+			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+		}
+
+		if (explicitConstructor.isSuperAccess()) {
+			this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
+		} else {
+			this.scribe.printNextToken(TerminalTokens.TokenNamethis);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_message_send);
+		
+		final Expression[] arguments = explicitConstructor.arguments;
+		if (arguments != null) {
+			int argumentLength = arguments.length;
+			Alignment argumentsAlignment =this.scribe.createAlignment(
+					"explicit_constructor_call",//$NON-NLS-1$
+					this.preferences.explicit_constructor_arguments_alignment,
+					argumentLength,
+					this.scribe.scanner.currentPosition);
+			this.scribe.enterAlignment(argumentsAlignment);
+			boolean ok = false;
+			do {
+				try {
+					if (this.preferences.insert_space_within_message_send) {
+						this.scribe.space();
+					}
+					for (int i = 0; i < argumentLength; i++) {
+						if (i > 0) {
+							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_explicitconstructorcall_arguments);
+						}
+						this.scribe.alignFragment(argumentsAlignment, i);
+						if (i > 0 && this.preferences.insert_space_after_comma_in_explicitconstructorcall_arguments) {
+							this.scribe.space();
+						}
+						arguments[i].traverse(this, scope);
+					}
+					ok = true;
+				} catch (AlignmentException e) {
+					this.scribe.redoAlignment(e);
+				}
+			} while (!ok);
+			this.scribe.exitAlignment(argumentsAlignment, true);
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_within_message_send); 
+		} else {
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_arguments); 
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		this.scribe.printTrailingComment();
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.FalseLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(FalseLiteral falseLiteral, BlockScope scope) {
+
+		final int numberOfParens = (falseLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(falseLiteral, numberOfParens);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNamefalse);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(falseLiteral, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.FieldReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(FieldReference fieldReference, BlockScope scope) {
+
+		final int numberOfParens = (fieldReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(fieldReference, numberOfParens);
+		}
+		fieldReference.receiver.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(fieldReference, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.FloatLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(FloatLiteral floatLiteral, BlockScope scope) {
+
+		final int numberOfParens = (floatLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(floatLiteral, numberOfParens);
+		}
+		Constant constant = floatLiteral.constant;
+		if (constant != null && floatLiteral.constant.floatValue() < 0) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);			
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameFloatingPointLiteral);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(floatLiteral, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ForStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(ForStatement forStatement, BlockScope scope) {
+	
+		this.scribe.printNextToken(TerminalTokens.TokenNamefor);
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_for_paren);
+		
+		if (this.preferences.insert_space_in_for_parens) {
+			this.scribe.space();
+		}
+		final Statement[] initializations = forStatement.initializations;
+		if (initializations != null) {
+			int length = initializations.length;
+			for (int i = 0; i < length; i++) {
+				if (initializations[i] instanceof LocalDeclaration) {
+					formatLocalDeclaration((LocalDeclaration) initializations[i], scope, this.preferences.insert_space_before_comma_in_for_inits, this.preferences.insert_space_after_comma_in_for_inits);
+				} else {
+					initializations[i].traverse(this, scope);
+					if (i >= 0 && (i < length - 1)) {
+						this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_for_inits);
+						if (this.preferences.insert_space_after_comma_in_for_inits) {
+							this.scribe.space();
+						}
+					}				
+				}
+			}
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		if (this.preferences.insert_space_after_semicolon_in_for) {
+			this.scribe.space();
+		}
+		final Expression condition = forStatement.condition;
+		if (condition != null) {
+			condition.traverse(this, scope);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		if (this.preferences.insert_space_after_semicolon_in_for) {
+			this.scribe.space();
+		}
+		final Statement[] increments = forStatement.increments;
+		if (increments != null) {
+			for (int i = 0, length = increments.length; i < length; i++) {
+				increments[i].traverse(this, scope);
+				if (i != length - 1) {
+					this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_for_increments);
+					if (this.preferences.insert_space_after_comma_in_for_increments) {
+						this.scribe.space();
+					}
+				}
+			}
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_in_for_parens);
+		
+		final Statement action = forStatement.action;
+		if (action != null) {
+			if (action instanceof Block) {
+				action.traverse(this, scope);
+			} else if (action instanceof EmptyStatement && !this.preferences.put_empty_statement_on_new_line) {
+				action.traverse(this, scope);
+			} else {
+				this.scribe.indent();
+				this.scribe.printNewLine();
+				action.traverse(this, scope);
+				this.scribe.unIndent();
+			}
+			if (action instanceof Expression) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+				this.scribe.printTrailingComment();
+			}
+		} else {
+			this.scribe.indent();
+			/*
+			 * This is an empty statement
+			 */
+			formatEmptyStatement(); 
+			this.scribe.unIndent();
+		}
+		return false;
+	}
+
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.IfStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(IfStatement ifStatement, BlockScope scope) {
+
+		this.scribe.printNextToken(TerminalTokens.TokenNameif);
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_if_condition);
+		if (this.preferences.insert_space_in_if_condition) {
+			this.scribe.space();
+		}
+		ifStatement.condition.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_in_if_condition);
+
+		final Statement thenStatement = ifStatement.thenStatement;
+		final Statement elseStatement = ifStatement.elseStatement;
+
+		if (thenStatement != null) {
+			if (thenStatement instanceof Block) {
+				if (isGuardClause((Block)thenStatement) && elseStatement == null && this.preferences.format_guardian_clause_on_one_line) {
+					/* 
+					 * Need a specific formatting for guard clauses
+					 * guard clauses are block with a single return or throw
+					 * statement
+					 */
+					 formatGuardClauseBlock((Block) thenStatement, scope);
+				} else {
+					if (thenStatement instanceof Block) {
+						thenStatement.traverse(this, scope);
+					} else {
+						this.scribe.printNewLine();
+						this.scribe.indent();
+						thenStatement.traverse(this, scope);
+						this.scribe.unIndent();
+					}
+					if (elseStatement != null && this.preferences.insert_new_line_in_control_statements) {
+						this.scribe.printNewLine();
+					}
+				}
+			} else if (elseStatement == null && this.preferences.keep_simple_if_on_one_line) {
+				Alignment compactIfAlignment = this.scribe.createAlignment(
+					"compactIf", //$NON-NLS-1$
+					this.preferences.compact_if_alignment,
+					Alignment.R_OUTERMOST,
+					1, 
+					this.scribe.scanner.currentPosition);
+				this.scribe.enterAlignment(compactIfAlignment);
+				boolean ok = false;
+				do {
+					try {
+						this.scribe.alignFragment(compactIfAlignment, 0);
+						this.scribe.space();
+						thenStatement.traverse(this, scope);
+						if (thenStatement instanceof Expression) {
+							this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+						}
+						ok = true;
+					} catch (AlignmentException e) {
+						this.scribe.redoAlignment(e);
+					}
+				} while (!ok);
+				this.scribe.exitAlignment(compactIfAlignment, true);				
+			} else if (this.preferences.keep_then_statement_on_same_line) {
+				this.scribe.space();
+				thenStatement.traverse(this, scope);
+				if (thenStatement instanceof Expression) {
+					this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+					this.scribe.printTrailingComment();
+				}
+				if (elseStatement != null) {
+					this.scribe.printNewLine();
+				}
+			} else {
+				this.scribe.printTrailingComment();
+				this.scribe.printNewLine();
+				this.scribe.indent();
+				thenStatement.traverse(this, scope);
+				if (thenStatement instanceof Expression) {
+					this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+					this.scribe.printTrailingComment();
+				}
+				if (elseStatement != null) {
+					this.scribe.printNewLine();
+				}
+				this.scribe.unIndent();
+			}
+		}
+		
+		if (elseStatement != null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameelse, true);
+			if (elseStatement instanceof Block) {
+				elseStatement.traverse(this, scope);
+			} else if (elseStatement instanceof IfStatement) {
+				if (!this.preferences.compact_else_if) {
+					this.scribe.printNewLine();
+					this.scribe.indent();
+				}
+				this.scribe.space();				
+				elseStatement.traverse(this, scope);
+				if (!this.preferences.compact_else_if) {
+					this.scribe.unIndent();
+				}
+			} else if (this.preferences.keep_else_statement_on_same_line) {
+				this.scribe.space();
+				elseStatement.traverse(this, scope);
+				if (elseStatement instanceof Expression) {
+					this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+					this.scribe.printTrailingComment();
+				}
+			} else {
+				this.scribe.printNewLine();
+				this.scribe.indent();
+				elseStatement.traverse(this, scope);
+				if (elseStatement instanceof Expression) {
+					this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+				}
+				this.scribe.unIndent();
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ImportReference, org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope)
+	 */
+	public boolean visit(
+		ImportReference importRef,
+		CompilationUnitScope scope) {
+		
+		this.scribe.printNextToken(TerminalTokens.TokenNameimport);
+		this.scribe.space();
+		if (importRef.onDemand) {
+			this.scribe.printQualifiedReference(importRef.sourceEnd);
+			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+			this.scribe.printNextToken(TerminalTokens.TokenNameMULTIPLY);			
+			this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		} else {
+			this.scribe.printQualifiedReference(importRef.sourceEnd);
+			this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		}
+		this.scribe.printTrailingComment();
+		this.scribe.printNewLine();
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.Initializer, org.eclipse.jdt.internal.compiler.lookup.MethodScope)
+	 */
+	public boolean visit(Initializer initializer, MethodScope scope) {
+
+		if (initializer.isStatic()) {
+			this.scribe.printNextToken(TerminalTokens.TokenNamestatic);
+		}
+		initializer.block.traverse(this, scope);
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		InstanceOfExpression instanceOfExpression,
+		BlockScope scope) {
+
+		final int numberOfParens = (instanceOfExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(instanceOfExpression, numberOfParens);
+		}
+		instanceOfExpression.expression.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameinstanceof, true);
+		this.scribe.space();
+		instanceOfExpression.type.traverse(this, scope);
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(instanceOfExpression, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter#visit(org.eclipse.jdt.internal.compiler.ast.IntLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(IntLiteral intLiteral, BlockScope scope) {
+
+		final int numberOfParens = (intLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(intLiteral, numberOfParens);
+		}
+		Constant constant = intLiteral.constant;
+		if (constant != null && constant.intValue() < 0) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);			
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameIntegerLiteral);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(intLiteral, numberOfParens);
+		}
+		return false;
+	}
+
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.LabeledStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {
+
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier);
+		this.scribe.printNextToken(TerminalTokens.TokenNameCOLON, this.preferences.insert_space_before_colon_in_labeled_statement);
+		if (this.preferences.insert_space_after_colon_in_labeled_statement) {
+			this.scribe.space();
+		}
+		labeledStatement.statement.traverse(this, scope);
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
+		formatLocalDeclaration(localDeclaration, scope, this.preferences.insert_space_before_comma_in_multiple_local_declarations, this.preferences.insert_space_after_comma_in_multiple_local_declarations);
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.LongLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(LongLiteral longLiteral, BlockScope scope) {
+
+		final int numberOfParens = (longLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(longLiteral, numberOfParens);
+		}
+		Constant constant = longLiteral.constant;
+		if (constant != null && constant.longValue() < 0) {
+			this.scribe.printNextToken(TerminalTokens.TokenNameMINUS);			
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameLongLiteral);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(longLiteral, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter#visit(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
+	 */
+	public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
+		format(memberTypeDeclaration);	
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.MessageSend, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(MessageSend messageSend, BlockScope scope) {
+
+		final int numberOfParens = (messageSend.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(messageSend, numberOfParens);
+		}
+		CascadingMethodInvocationFragmentBuilder builder = buildFragments(messageSend, scope);
+		
+		if (builder.size() >= 3 && numberOfParens == 0) {
+			formatCascadingMessageSends(builder, scope);
+		} else {
+			Alignment messageAlignment = null;
+			if (!messageSend.receiver.isImplicitThis()) {
+				messageSend.receiver.traverse(this, scope);
+				messageAlignment = this.scribe.createAlignment(
+						"messageAlignment", //$NON-NLS-1$
+						this.preferences.message_send_selector_alignment,
+						1,
+						this.scribe.scanner.currentPosition);
+				this.scribe.enterAlignment(messageAlignment);
+				boolean ok = false;
+				do {
+					try {
+						formatMessageSend(messageSend, scope, messageAlignment);
+						ok = true;
+					} catch (AlignmentException e) {
+						this.scribe.redoAlignment(e);
+					}
+				} while (!ok);
+				this.scribe.exitAlignment(messageAlignment, true);
+			} else {
+				formatMessageSend(messageSend, scope, null);			
+			}
+		}
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(messageSend, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.MethodDeclaration, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
+	 */
+	public boolean visit(
+		MethodDeclaration methodDeclaration,
+		ClassScope scope) {
+
+		if (methodDeclaration.ignoreFurtherInvestigation) {
+			this.scribe.printComment();
+			this.scribe.scanner.resetTo(methodDeclaration.declarationSourceEnd + 1, this.scribe.scannerEndPosition);
+			this.scribe.printTrailingComment();
+			return false;
+		}
+		this.scribe.printModifiers();
+		this.scribe.space();
+		
+		/*
+		 * Print the method return type
+		 */	
+		final TypeReference returnType = methodDeclaration.returnType;
+		final MethodScope methodDeclarationScope = methodDeclaration.scope;
+		
+		if (returnType != null) {
+			returnType.traverse(this, methodDeclarationScope);
+		}
+		/*
+		 * Print the method name
+		 */
+		this.scribe.printNextToken(TerminalTokens.TokenNameIdentifier, true); 
+
+		formatMethodArguments(
+			methodDeclaration, 
+			this.preferences.insert_space_before_method_declaration_open_paren,
+			this.preferences.insert_space_between_empty_arguments,
+			this.preferences.insert_space_before_closing_paren,
+			this.preferences.insert_space_before_first_argument,
+			this.preferences.insert_space_before_comma_in_method_arguments,
+			this.preferences.insert_space_after_comma_in_method_arguments);
+
+		/*
+		 * Check for extra dimensions
+		 */
+		int extraDimensions = getExtraDimension();
+		if (extraDimensions != 0) {
+			 for (int i = 0; i < extraDimensions; i++) {
+			 	this.scribe.printNextToken(TerminalTokens.TokenNameLBRACKET);
+			 	this.scribe.printNextToken(TerminalTokens.TokenNameRBRACKET);
+			 }
+		}
+				
+		formatThrowsClause(
+			methodDeclaration,
+			this.preferences.insert_space_before_comma_in_method_throws,
+			this.preferences.insert_space_after_comma_in_method_throws);
+
+		if (!methodDeclaration.isNative() && !methodDeclaration.isAbstract() && ((methodDeclaration.modifiers & CompilerModifiers.AccSemicolonBody) == 0)) {
+			/*
+			 * Method body
+			 */
+			String method_declaration_brace = this.preferences.method_declaration_brace_position;
+			formatOpeningBrace(method_declaration_brace, this.preferences.insert_space_before_method_open_brace);
+			final int numberOfBlankLinesAtBeginningOfMethodBody = this.preferences.number_of_blank_lines_to_insert_at_beginning_of_method_body;
+			if (numberOfBlankLinesAtBeginningOfMethodBody > 0) {
+				this.scribe.printEmptyLines(numberOfBlankLinesAtBeginningOfMethodBody);
+			}
+			final Statement[] statements = methodDeclaration.statements;
+			if (statements != null) {
+				this.scribe.printNewLine();
+				if (this.preferences.indent_block_statements) {
+					this.scribe.indent();
+				}
+				formatStatements(methodDeclarationScope, statements, true);
+				this.scribe.printComment();
+				if (this.preferences.indent_block_statements) {
+					this.scribe.unIndent();
+				}
+			} else if (this.preferences.insert_new_line_in_empty_method_body) {
+				this.scribe.printNewLine();
+				if (this.preferences.indent_block_statements) {
+					this.scribe.indent();
+				}
+				this.scribe.printComment();
+				if (this.preferences.indent_block_statements) {
+					this.scribe.unIndent();
+				}
+			}
+			this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
+			this.scribe.printTrailingComment();
+			if (method_declaration_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
+				this.scribe.unIndent();
+			}
+		} else {
+			// no method body
+			this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+			this.scribe.printTrailingComment();
+		}
+		return false;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.NullLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(NullLiteral nullLiteral, BlockScope scope) {
+
+		final int numberOfParens = (nullLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(nullLiteral, numberOfParens);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNamenull);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(nullLiteral, numberOfParens);
+		}
+		return false;
+	}
+
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+
+		return dumpBinaryExpression(or_or_Expression, TerminalTokens.TokenNameOR_OR, scope);
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.PostfixExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		PostfixExpression postfixExpression,
+		BlockScope scope) {
+
+		final int numberOfParens = (postfixExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(postfixExpression, numberOfParens);
+		}
+		postfixExpression.lhs.traverse(this, scope);
+		int operator = postfixExpression.operator == OperatorIds.PLUS 
+			? TerminalTokens.TokenNamePLUS_PLUS : TerminalTokens.TokenNameMINUS_MINUS;
+		this.scribe.printNextToken(operator, this.preferences.insert_space_before_postfix_operator);
+		if (this.preferences.insert_space_after_postfix_operator) {
+			this.scribe.space();
+		}
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(postfixExpression, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.PrefixExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(PrefixExpression prefixExpression, BlockScope scope) {
+
+		final int numberOfParens = (prefixExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(prefixExpression, numberOfParens);
+		}
+		int operator = prefixExpression.operator == OperatorIds.PLUS 
+			? TerminalTokens.TokenNamePLUS_PLUS : TerminalTokens.TokenNameMINUS_MINUS;
+		this.scribe.printNextToken(operator, this.preferences.insert_space_before_prefix_operator);
+		if (this.preferences.insert_space_after_prefix_operator) {
+			this.scribe.space();
+		}
+		prefixExpression.lhs.traverse(this, scope);
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(prefixExpression, numberOfParens);
+		}
+		return false;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		QualifiedAllocationExpression qualifiedAllocationExpression,
+		BlockScope scope) {
+			
+		final int numberOfParens = (qualifiedAllocationExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(qualifiedAllocationExpression, numberOfParens);
+		}
+		final Expression enclosingInstance = qualifiedAllocationExpression.enclosingInstance;
+		if (enclosingInstance != null) {
+			enclosingInstance.traverse(this, scope);
+			this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNamenew);
+		this.scribe.space();
+		qualifiedAllocationExpression.type.traverse(this, scope);
+		
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_message_send);
+
+		final Expression[] arguments = qualifiedAllocationExpression.arguments;
+		if (arguments != null) {
+			int argumentLength = arguments.length;
+			Alignment argumentsAlignment =this.scribe.createAlignment(
+					"allocation",//$NON-NLS-1$
+					this.preferences.qualified_allocation_expression_arguments_alignment,
+					argumentLength,
+					this.scribe.scanner.currentPosition);
+			this.scribe.enterAlignment(argumentsAlignment);
+			boolean ok = false;
+			do {
+				try {
+					if (this.preferences.insert_space_within_message_send) {
+						this.scribe.space();
+					}
+					for (int i = 0; i < argumentLength; i++) {
+						if (i > 0) {
+							this.scribe.printNextToken(TerminalTokens.TokenNameCOMMA, this.preferences.insert_space_before_comma_in_allocation_expression);
+						}
+						this.scribe.alignFragment(argumentsAlignment, i);
+						if (i > 0 && this.preferences.insert_space_after_comma_in_allocation_expression) {
+							this.scribe.space();
+						}
+						arguments[i].traverse(this, scope);
+					}
+					ok = true;
+				} catch (AlignmentException e) {
+					this.scribe.redoAlignment(e);
+				}
+			} while (!ok);
+			this.scribe.exitAlignment(argumentsAlignment, true);
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_within_message_send); 
+		} else {
+			this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_between_empty_arguments); 
+		}
+		final TypeDeclaration anonymousType = qualifiedAllocationExpression.anonymousType;
+		if (anonymousType != null) {
+			anonymousType.traverse(this, scope);
+		}
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(qualifiedAllocationExpression, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		QualifiedNameReference qualifiedNameReference,
+		BlockScope scope) {
+
+		final int numberOfParens = (qualifiedNameReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(qualifiedNameReference, numberOfParens);
+		}
+		this.scribe.printQualifiedReference(qualifiedNameReference.sourceEnd + 1);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(qualifiedNameReference, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		QualifiedSuperReference qualifiedSuperReference,
+		BlockScope scope) {
+
+		final int numberOfParens = (qualifiedSuperReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(qualifiedSuperReference, numberOfParens);
+		}
+		qualifiedSuperReference.qualification.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+		this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(qualifiedSuperReference, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		QualifiedThisReference qualifiedThisReference,
+		BlockScope scope) {
+
+		final int numberOfParens = (qualifiedThisReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(qualifiedThisReference, numberOfParens);
+		}
+		qualifiedThisReference.qualification.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameDOT);
+		this.scribe.printNextToken(TerminalTokens.TokenNamethis);
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(qualifiedThisReference, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		QualifiedTypeReference qualifiedTypeReference,
+		BlockScope scope) {
+
+		final int numberOfParens = (qualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(qualifiedTypeReference, numberOfParens);
+		}
+		this.scribe.printQualifiedReference(qualifiedTypeReference.sourceEnd + 1);
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(qualifiedTypeReference, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
+	 */
+	public boolean visit(
+		QualifiedTypeReference qualifiedTypeReference,
+		ClassScope scope) {
+
+			final int numberOfParens = (qualifiedTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+			if (numberOfParens > 0) {
+				manageOpeningParenthesizedExpression(qualifiedTypeReference, numberOfParens);
+			}
+			this.scribe.printQualifiedReference(qualifiedTypeReference.sourceEnd + 1);
+			
+			if (numberOfParens > 0) {
+				manageClosingParenthesizedExpression(qualifiedTypeReference, numberOfParens);
+			}
+			return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ReturnStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(ReturnStatement returnStatement, BlockScope scope) {
+		
+		this.scribe.printNextToken(TerminalTokens.TokenNamereturn);
+		final Expression expression = returnStatement.expression;
+		if (expression != null) {
+			this.scribe.space();
+			expression.traverse(this, scope);
+		}
+		/*
+		 * Print the semi-colon
+		 */	
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		this.scribe.printTrailingComment();
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter#visit(org.eclipse.jdt.internal.compiler.ast.SingleNameReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(SingleNameReference singleNameReference, BlockScope scope) {
+
+		final int numberOfParens = (singleNameReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(singleNameReference, numberOfParens);
+		}
+		this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS, false, true);
+		
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(singleNameReference, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SingleTypeReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		SingleTypeReference singleTypeReference,
+		BlockScope scope) {
+
+		final int numberOfParens = (singleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(singleTypeReference, numberOfParens);
+		}
+		this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS, false, true);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(singleTypeReference, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SingleTypeReference, org.eclipse.jdt.internal.compiler.lookup.ClassScope)
+	 */
+	public boolean visit(
+		SingleTypeReference singleTypeReference,
+		ClassScope scope) {
+
+		final int numberOfParens = (singleTypeReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(singleTypeReference, numberOfParens);
+		}
+		this.scribe.printNextToken(SINGLETYPEREFERENCE_EXPECTEDTOKENS, false, true);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(singleTypeReference, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.StringLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
+
+		final int numberOfParens = (stringLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(stringLiteral, numberOfParens);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNameStringLiteral);
+		this.scribe.printTrailingComment();
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(stringLiteral, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SuperReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(SuperReference superReference, BlockScope scope) {
+
+		final int numberOfParens = (superReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(superReference, numberOfParens);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNamesuper);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(superReference, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SwitchStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(SwitchStatement switchStatement, BlockScope scope) {
+		this.scribe.printNextToken(TerminalTokens.TokenNameswitch);
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_switch_condition);
+		
+		if (this.preferences.insert_space_in_switch_condition) {
+			this.scribe.space();
+		}
+		
+		switchStatement.expression.traverse(this, scope);
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_in_switch_condition);
+		/*
+		 * Type body
+		 */
+		String switch_brace = this.preferences.switch_brace_position;
+		formatOpeningBrace(switch_brace, this.preferences.insert_space_before_switch_open_brace);
+		this.scribe.printNewLine();
+
+		if (preferences.indent_switchstatements_compare_to_switch) {
+			this.scribe.indent();
+		}
+		final Statement[] statements = switchStatement.statements;
+		boolean wasACase = false;
+		boolean wasAStatement = false;
+		if (statements != null) {
+			int statementsLength = statements.length;
+			for (int i = 0; i < statementsLength; i++) {
+				final Statement statement = statements[i];
+				if (statement instanceof CaseStatement) {
+					if ((wasACase && this.preferences.indent_switchstatements_compare_to_cases) 
+						|| (wasAStatement && this.preferences.indent_switchstatements_compare_to_cases)) {
+						this.scribe.unIndent();
+					}
+					statement.traverse(this, scope);
+					wasACase = true;
+					wasAStatement = false;
+					if (this.preferences.indent_switchstatements_compare_to_cases) {
+						this.scribe.indent();
+					}
+				} else if (statement instanceof BreakStatement) {
+					if (this.preferences.indent_breaks_compare_to_cases) {
+						if (wasAStatement && !this.preferences.indent_switchstatements_compare_to_cases) {
+							this.scribe.indent();
+						}
+					} else {
+						if (wasAStatement) {
+							if (this.preferences.indent_switchstatements_compare_to_cases) {
+								this.scribe.unIndent();
+							}
+						}
+						if (wasACase && this.preferences.indent_switchstatements_compare_to_cases) {
+							this.scribe.unIndent();
+						}
+					}
+					statement.traverse(this, scope);
+					if (this.preferences.indent_breaks_compare_to_cases) {
+						this.scribe.unIndent();
+					}
+					wasACase = false;
+					wasAStatement = false;
+				} else {
+					statement.traverse(this, scope);
+					wasAStatement = true;
+					wasACase = false;
+				}
+				if (statement instanceof Expression) {
+					/*
+					 * Print the semi-colon
+					 */	
+					this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+					this.scribe.printTrailingComment();
+				} else if (statement instanceof LocalDeclaration) {
+					LocalDeclaration currentLocal = (LocalDeclaration) statement;
+					if (i < (statementsLength - 1)) {
+						/* 
+						 * We need to check that the next statement is a local declaration
+						 */
+						if (statements[i + 1] instanceof LocalDeclaration) {
+							LocalDeclaration nextLocal = (LocalDeclaration) statements[i + 1];
+							if (currentLocal.declarationSourceStart != nextLocal.declarationSourceStart) {
+								/*
+								 * Print the semi-colon
+								 */	
+								this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+								this.scribe.printTrailingComment();
+							}
+						} else {
+							/*
+							 * Print the semi-colon
+							 */	
+							this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+							this.scribe.printTrailingComment();
+						}
+					} else {
+						/*
+						 * Print the semi-colon
+						 */	
+						this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+						this.scribe.printTrailingComment();
+					}
+				}
+				this.scribe.printNewLine();
+			}
+		}		
+		
+		if ((wasACase || wasAStatement) && this.preferences.indent_switchstatements_compare_to_cases) {
+			this.scribe.unIndent();
+		}
+		if (preferences.indent_switchstatements_compare_to_switch) {
+			this.scribe.unIndent();
+		}
+		this.scribe.printNewLine();
+		this.scribe.printNextToken(TerminalTokens.TokenNameRBRACE);
+		this.scribe.printTrailingComment();
+		if (switch_brace.equals(DefaultCodeFormatterConstants.NEXT_LINE_SHIFTED)) {
+			this.scribe.unIndent();
+		}		
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		SynchronizedStatement synchronizedStatement,
+		BlockScope scope) {
+		
+		this.scribe.printNextToken(TerminalTokens.TokenNamesynchronized);
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_synchronized_condition);
+		
+		if (this.preferences.insert_space_in_synchronized_condition) {
+			this.scribe.space();
+		}
+		synchronizedStatement.expression.traverse(this, scope);
+	
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_in_synchronized_condition);
+		
+		synchronizedStatement.block.traverse(this, scope);
+		return false;
+	}
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ThisReference, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(ThisReference thisReference, BlockScope scope) {
+		
+		if (!thisReference.isImplicitThis()) {
+			final int numberOfParens = (thisReference.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+			if (numberOfParens > 0) {
+				manageOpeningParenthesizedExpression(thisReference, numberOfParens);
+			}
+			this.scribe.printNextToken(TerminalTokens.TokenNamethis);
+			
+			if (numberOfParens > 0) {
+				manageClosingParenthesizedExpression(thisReference, numberOfParens);
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.ThrowStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(ThrowStatement throwStatement, BlockScope scope) {
+
+		this.scribe.printNextToken(TerminalTokens.TokenNamethrow);
+		this.scribe.space();
+		throwStatement.exception.traverse(this, scope);
+		/*
+		 * Print the semi-colon
+		 */	
+		this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+		this.scribe.printTrailingComment();
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TrueLiteral, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(TrueLiteral trueLiteral, BlockScope scope) {
+
+		final int numberOfParens = (trueLiteral.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(trueLiteral, numberOfParens);
+		}
+		this.scribe.printNextToken(TerminalTokens.TokenNametrue);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(trueLiteral, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TryStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(TryStatement tryStatement, BlockScope scope) {
+
+		this.scribe.printNextToken(TerminalTokens.TokenNametry);
+		tryStatement.tryBlock.traverse(this, scope);
+		if (this.preferences.insert_new_line_in_control_statements) {
+			this.scribe.printNewLine();
+		}	
+		if (tryStatement.catchArguments != null) {
+			for (int i = 0, max = tryStatement.catchBlocks.length; i < max; i++) {
+				this.scribe.printNextToken(TerminalTokens.TokenNamecatch, this.preferences.insert_space_after_block_close_brace);
+				this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_catch_expression);
+				
+				if (this.preferences.insert_space_in_catch_expression) {
+					this.scribe.space();
+				}
+				
+				tryStatement.catchArguments[i].traverse(this, scope);
+			
+				this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_in_catch_expression);
+				
+				tryStatement.catchBlocks[i].traverse(this, scope);
+				if (this.preferences.insert_new_line_in_control_statements) {
+					this.scribe.printNewLine();
+				}	
+			}
+		}
+		if (tryStatement.finallyBlock != null) {
+			this.scribe.printNextToken(TerminalTokens.TokenNamefinally, this.preferences.insert_space_after_block_close_brace);
+			tryStatement.finallyBlock.traverse(this, scope);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(
+		TypeDeclaration localTypeDeclaration,
+		BlockScope scope) {
+
+			format(localTypeDeclaration);
+			return false;
+	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration, org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope)
+	 */
+	public boolean visit(
+		TypeDeclaration typeDeclaration,
+		CompilationUnitScope scope) {
+
+		format(typeDeclaration);
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.UnaryExpression, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
+
+		final int numberOfParens = (unaryExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
+		if (numberOfParens > 0) {
+			manageOpeningParenthesizedExpression(unaryExpression, numberOfParens);
+		}
+
+		/*
+		 * Print the operator
+		 */
+		int operator;
+		switch((unaryExpression.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) {
+			case OperatorIds.PLUS:
+				operator = TerminalTokens.TokenNamePLUS;
+				break;
+			case OperatorIds.MINUS:
+				operator = TerminalTokens.TokenNameMINUS;
+				break;
+			case OperatorIds.TWIDDLE:
+				operator = TerminalTokens.TokenNameTWIDDLE;
+				break;
+			default:
+				operator = TerminalTokens.TokenNameNOT;
+		}
+
+		this.scribe.printNextToken(operator, this.preferences.insert_space_before_unary_operator);
+		if (this.preferences.insert_space_after_unary_operator) {
+			this.scribe.space();
+		}
+		unaryExpression.expression.traverse(this, scope);
+
+		if (numberOfParens > 0) {
+			manageClosingParenthesizedExpression(unaryExpression, numberOfParens);
+		}
+		return false;
+	}
+
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ASTVisitor#visit(org.eclipse.jdt.internal.compiler.ast.WhileStatement, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+	 */
+	public boolean visit(WhileStatement whileStatement, BlockScope scope) {
+
+		this.scribe.printNextToken(TerminalTokens.TokenNamewhile);
+		this.scribe.printNextToken(TerminalTokens.TokenNameLPAREN, this.preferences.insert_space_before_while_condition);
+		
+		if (this.preferences.insert_space_in_while_condition) {
+			this.scribe.space();
+		}
+		whileStatement.condition.traverse(this, scope);
+		
+		this.scribe.printNextToken(TerminalTokens.TokenNameRPAREN, this.preferences.insert_space_in_while_condition);
+		
+		final Statement action = whileStatement.action;
+		if (action != null) {
+			if (action instanceof Block) {
+				action.traverse(this, scope);
+			} else {
+				this.scribe.printNewLine();
+				this.scribe.indent();
+				action.traverse(this, scope);
+				this.scribe.unIndent();
+			}
+			if (action instanceof Expression) {
+				this.scribe.printNextToken(TerminalTokens.TokenNameSEMICOLON, this.preferences.insert_space_before_semicolon);
+				this.scribe.printTrailingComment();
+			}
+		} else {
+			this.scribe.indent();
+			/*
+			 * This is an empty statement
+			 */
+			formatEmptyStatement(); 
+			this.scribe.unIndent();
+		}
+		return false;
+	}
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
new file mode 100644
index 0000000..d272a13
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatter.java
@@ -0,0 +1,325 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2003 International Business Machines 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 API and implementation
+ ******************************************************************************/
+package org.eclipse.jdt.internal.formatter;
+
+import java.util.Locale;
+import java.util.Map;
+
+import org.eclipse.jdt.core.formatter.CodeFormatter;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.text.edits.TextEdit;
+
+public class DefaultCodeFormatter extends CodeFormatter {
+
+	public static final boolean DEBUG = false;
+
+	private static ASTNode[] parseClassBodyDeclarations(char[] source, Map settings) {
+		
+		if (source == null) {
+			throw new IllegalArgumentException();
+		}
+		CompilerOptions compilerOptions = new CompilerOptions(settings);
+		final ProblemReporter problemReporter = new ProblemReporter(
+					DefaultErrorHandlingPolicies.proceedWithAllProblems(), 
+					compilerOptions, 
+					new DefaultProblemFactory(Locale.getDefault()));
+					
+		CodeFormatterParser parser =
+			new CodeFormatterParser(problemReporter, false);
+
+		ICompilationUnit sourceUnit = 
+			new CompilationUnit(
+				source, 
+				"", //$NON-NLS-1$
+				compilerOptions.defaultEncoding);
+
+		return parser.parseClassBodyDeclarations(source, new CompilationUnitDeclaration(problemReporter, new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit), source.length));
+	}
+
+	private static CompilationUnitDeclaration parseCompilationUnit(char[] source, Map settings) {
+		
+		if (source == null) {
+			throw new IllegalArgumentException();
+		}
+		CompilerOptions compilerOptions = new CompilerOptions(settings);
+		CodeFormatterParser parser =
+			new CodeFormatterParser(
+				new ProblemReporter(
+					DefaultErrorHandlingPolicies.proceedWithAllProblems(), 
+					compilerOptions, 
+					new DefaultProblemFactory(Locale.getDefault())),
+			false);
+		ICompilationUnit sourceUnit = 
+			new CompilationUnit(
+				source, 
+				"", //$NON-NLS-1$
+				compilerOptions.defaultEncoding);
+		CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit));
+		
+		if (compilationUnitDeclaration.ignoreMethodBodies) {
+			compilationUnitDeclaration.ignoreFurtherInvestigation = true;
+			// if initial diet parse did not work, no need to dig into method bodies.
+			return compilationUnitDeclaration; 
+		}
+		
+		//fill the methods bodies in order for the code to be generated
+		//real parse of the method....
+		parser.scanner.setSource(source);
+		org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
+		if (types != null) {
+			for (int i = types.length; --i >= 0;) {
+				types[i].parseMethod(parser, compilationUnitDeclaration);
+			}
+		}
+		return compilationUnitDeclaration;
+	}
+
+	private static Expression parseExpression(char[] source, Map settings) {
+		
+		if (source == null) {
+			throw new IllegalArgumentException();
+		}
+		CompilerOptions compilerOptions = new CompilerOptions(settings);
+		final ProblemReporter problemReporter = new ProblemReporter(
+					DefaultErrorHandlingPolicies.proceedWithAllProblems(), 
+					compilerOptions, 
+					new DefaultProblemFactory(Locale.getDefault()));
+					
+		CodeFormatterParser parser =
+			new CodeFormatterParser(problemReporter, false);
+
+		ICompilationUnit sourceUnit = 
+			new CompilationUnit(
+				source, 
+				"", //$NON-NLS-1$
+				compilerOptions.defaultEncoding);
+
+		return parser.parseExpression(source, new CompilationUnitDeclaration(problemReporter, new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit), source.length));
+	}
+
+	private static ConstructorDeclaration parseStatements(char[] source, Map settings) {
+		
+		if (source == null) {
+			throw new IllegalArgumentException();
+		}
+		CompilerOptions compilerOptions = new CompilerOptions(settings);
+		final ProblemReporter problemReporter = new ProblemReporter(
+					DefaultErrorHandlingPolicies.proceedWithAllProblems(), 
+					compilerOptions, 
+					new DefaultProblemFactory(Locale.getDefault()));
+		CodeFormatterParser parser = new CodeFormatterParser(problemReporter, false);
+		ICompilationUnit sourceUnit = 
+			new CompilationUnit(
+				source, 
+				"", //$NON-NLS-1$
+				compilerOptions.defaultEncoding);
+
+		final CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
+		CompilationUnitDeclaration compilationUnitDeclaration = new CompilationUnitDeclaration(problemReporter, compilationResult, source.length);		
+
+		ConstructorDeclaration constructorDeclaration = new ConstructorDeclaration(compilationResult);
+		constructorDeclaration.sourceEnd  = -1;
+		constructorDeclaration.declarationSourceEnd = source.length - 1;
+		constructorDeclaration.bodyStart = 0;
+		constructorDeclaration.bodyEnd = source.length - 1;
+		
+		parser.scanner.setSource(source);
+		parser.parse(constructorDeclaration, compilationUnitDeclaration);
+		
+		return constructorDeclaration;
+	}
+	
+	private CodeFormatterVisitor newCodeFormatter;
+	private Map options;
+	
+	private DefaultCodeFormatterOptions preferences;
+	
+	public DefaultCodeFormatter() {
+		this(new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getDefaultSettings()), null);
+	}
+	
+	public DefaultCodeFormatter(DefaultCodeFormatterOptions preferences) {
+		this(preferences, null);
+	}
+
+	public DefaultCodeFormatter(DefaultCodeFormatterOptions preferences, Map options) {
+		if (options == null) {
+			options = JavaCore.getOptions();
+		}
+		this.options = options;
+		if (options != null) {
+			this.preferences = new DefaultCodeFormatterOptions(options);
+			if (preferences != null) {
+				this.preferences.set(preferences.getMap());
+			}
+		} else {
+			this.preferences = new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getDefaultSettings());
+			if (preferences != null) {
+				this.preferences.set(preferences.getMap());
+			}
+		}
+	}
+
+	public DefaultCodeFormatter(Map options) {
+		this(null, options);
+	}
+
+	/**
+	 * @see CodeFormatter#format(int, String, int, int[], String, Map)
+	 */
+	public TextEdit format(
+			int kind,
+			String source,
+			int offset,
+			int length,
+			int indentationLevel,
+			String lineSeparator) {
+
+		if (offset < 0 || length < 0 || length > source.length()) {
+			throw new IllegalArgumentException();
+		}
+		switch(kind) {
+			case K_CLASS_BODY_DECLARATIONS :
+				return formatClassBodyDeclarations(source, indentationLevel, lineSeparator, offset, length);
+			case K_COMPILATION_UNIT :
+				return formatCompilationUnit(source, indentationLevel, lineSeparator, offset, length);
+			case K_EXPRESSION :
+				return formatExpression(source, indentationLevel, lineSeparator, offset, length);
+			case K_STATEMENTS :
+				return formatStatements(source, indentationLevel, lineSeparator, offset, length);
+			case K_UNKNOWN :
+				return probeFormatting(source, indentationLevel, lineSeparator, offset, length);
+		}
+		return null;
+	}
+	
+	private TextEdit formatClassBodyDeclarations(String source, int indentationLevel, String lineSeparator, int offset, int length) {
+		ASTNode[] bodyDeclarations = parseClassBodyDeclarations(source.toCharArray(), this.options);
+		
+		if (bodyDeclarations == null) {
+			// a problem occured while parsing the source
+			return null;
+		}
+		return internalFormatClassBodyDeclarations(source, indentationLevel, lineSeparator, bodyDeclarations, offset, length);
+	}
+
+	private TextEdit formatCompilationUnit(String source, int indentationLevel, String lineSeparator, int offset, int length) {
+		CompilationUnitDeclaration compilationUnitDeclaration = parseCompilationUnit(source.toCharArray(), this.options);
+		
+		if (lineSeparator != null) {
+			this.preferences.line_separator = lineSeparator;
+		} else {
+			this.preferences.line_separator = System.getProperty("line.separator"); //$NON-NLS-1$
+		}
+		this.preferences.initial_indentation_level = indentationLevel;
+
+		this.newCodeFormatter = new CodeFormatterVisitor(this.preferences, options, offset, length);
+		
+		return this.newCodeFormatter.format(source, compilationUnitDeclaration);
+	}
+
+	private TextEdit formatExpression(String source, int indentationLevel, String lineSeparator, int offset, int length) {
+		Expression expression = parseExpression(source.toCharArray(), this.options);
+		
+		if (expression == null) {
+			// a problem occured while parsing the source
+			return null;
+		}
+		return internalFormatExpression(source, indentationLevel, lineSeparator, expression, offset, length);
+	}
+
+	private TextEdit formatStatements(String source, int indentationLevel, String lineSeparator, int offset, int length) {
+		ConstructorDeclaration constructorDeclaration = parseStatements(source.toCharArray(), this.options);
+		
+		if (constructorDeclaration.statements == null) {
+			// a problem occured while parsing the source
+			return null;
+		}
+		return internalFormatStatements(source, indentationLevel, lineSeparator, constructorDeclaration, offset, length);
+	}
+
+	public String getDebugOutput() {
+		return this.newCodeFormatter.scribe.toString();
+	}
+
+	private TextEdit internalFormatClassBodyDeclarations(String source, int indentationLevel, String lineSeparator, ASTNode[] bodyDeclarations, int offset, int length) {
+		if (lineSeparator != null) {
+			this.preferences.line_separator = lineSeparator;
+		} else {
+			this.preferences.line_separator = System.getProperty("line.separator"); //$NON-NLS-1$
+		}
+		this.preferences.initial_indentation_level = indentationLevel;
+
+		this.newCodeFormatter = new CodeFormatterVisitor(this.preferences, options, offset, length);
+		
+		return this.newCodeFormatter.format(source, bodyDeclarations);
+	}
+
+	private TextEdit internalFormatExpression(String source, int indentationLevel, String lineSeparator, Expression expression, int offset, int length) {
+		if (lineSeparator != null) {
+			this.preferences.line_separator = lineSeparator;
+		} else {
+			this.preferences.line_separator = System.getProperty("line.separator"); //$NON-NLS-1$
+		}
+		this.preferences.initial_indentation_level = indentationLevel;
+
+		this.newCodeFormatter = new CodeFormatterVisitor(this.preferences, options, offset, length);
+		
+		return this.newCodeFormatter.format(source, expression);
+	}
+	
+	private TextEdit internalFormatStatements(String source, int indentationLevel, String lineSeparator, ConstructorDeclaration constructorDeclaration, int offset, int length) {
+		if (lineSeparator != null) {
+			this.preferences.line_separator = lineSeparator;
+		} else {
+			this.preferences.line_separator = System.getProperty("line.separator"); //$NON-NLS-1$
+		}
+		this.preferences.initial_indentation_level = indentationLevel;
+
+		this.newCodeFormatter = new CodeFormatterVisitor(this.preferences, options, offset, length);
+		
+		return  this.newCodeFormatter.format(source, constructorDeclaration);
+	}
+
+	private TextEdit probeFormatting(String source, int indentationLevel, String lineSeparator, int offset, int length) {
+		Expression expression = parseExpression(source.toCharArray(), this.options);
+		
+		if (expression != null) {
+			return internalFormatExpression(source, indentationLevel, lineSeparator, expression, offset, length);
+		}
+
+		ConstructorDeclaration constructorDeclaration = parseStatements(source.toCharArray(), this.options);
+		
+		if (constructorDeclaration.statements != null) {
+			return internalFormatStatements(source, indentationLevel, lineSeparator, constructorDeclaration, offset, length);
+		}
+		
+		ASTNode[] bodyDeclarations = parseClassBodyDeclarations(source.toCharArray(), this.options);
+		
+		if (bodyDeclarations != null) {
+			return internalFormatClassBodyDeclarations(source, indentationLevel, lineSeparator, bodyDeclarations, offset, length);
+		}
+
+		return formatCompilationUnit(source, indentationLevel, lineSeparator, offset, length);
+	}
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
new file mode 100644
index 0000000..8d5e1a5
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java
@@ -0,0 +1,1366 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.formatter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.internal.formatter.align.Alignment;
+
+/**
+ * This is still subject to changes before 3.0.
+ * @since 3.0
+ */
+
+public class DefaultCodeFormatterOptions {
+	public static final char DASH = ' ';//183
+	public static final int DEFAULT_ALLOCATION_EXPRESSION_ARGUMENTS_ALIGNMENT = Alignment.M_COMPACT_SPLIT;
+	public static final String DEFAULT_ANONYMOUS_TYPE_DECLARATION_BRACE_POSITION = DefaultCodeFormatterConstants.END_OF_LINE;
+	public static final int DEFAULT_ARRAY_INITIALIZER_EXPRESSIONS_ALIGNMENT = Alignment.M_COMPACT_SPLIT;
+	public static final String DEFAULT_ARRAY_INITIALIZER_BRACE_POSITION = DefaultCodeFormatterConstants.END_OF_LINE;
+	public static final int DEFAULT_ARRAY_INITIALIZER_CONTINUATION_INDENTATION = 2; // 2 indentations
+	public static final int DEFAULT_BINARY_EXPRESSION_ALIGNMENT = Alignment.M_COMPACT_SPLIT;
+	public static final int DEFAULT_BLANK_LINES_AFTER_IMPORTS = 0;
+	public static final int DEFAULT_BLANK_LINES_AFTER_PACKAGE = 0;
+	public static final int DEFAULT_BLANK_LINES_BEFORE_FIELD = 0;
+	public static final int DEFAULT_BLANK_LINES_BEFORE_FIRST_CLASS_BODY_DECLARATION = 0;
+	public static final int DEFAULT_BLANK_LINES_BEFORE_IMPORTS = 0;
+	public static final int DEFAULT_BLANK_LINES_BEFORE_MEMBER_TYPE = 0;
+	public static final int DEFAULT_BLANK_LINES_BEFORE_METHOD = 0;
+	public static final int DEFAULT_BLANK_LINES_BEFORE_NEW_CHUNK = 0;
+	public static final int DEFAULT_BLANK_LINES_BEFORE_PACKAGE = 0;
+	public static final String DEFAULT_BLOCK_BRACE_POSITION = DefaultCodeFormatterConstants.END_OF_LINE;
+	public static final boolean DEFAULT_COMPACT_ELSE_IF = true;
+	public static final int DEFAULT_COMPACT_IF_ALIGNMENT = Alignment.M_ONE_PER_LINE_SPLIT | Alignment.M_INDENT_BY_ONE;
+	public static final int DEFAULT_CONDITIONAL_EXPRESSION_ALIGNMENT = Alignment.M_ONE_PER_LINE_SPLIT;
+	public static final int DEFAULT_CONTINUATION_INDENTATION = 2; // 2 indentations
+	// TODO remove before 3.0
+	/**
+	 * @deprecated
+	 */
+	public static final boolean DEFAULT_CONVERT_OLD_TO_NEW = true;
+	public static final int DEFAULT_EXPLICIT_CONSTRUCTOR_ARGUMENTS_ALIGNMENT = Alignment.M_COMPACT_SPLIT;
+	public static final char DEFAULT_FILLING_SPACE = DASH;
+	public static final boolean DEFAULT_FORMAT_GUARDIAN_CLAUSE_ON_ONE_LINE = false;
+	public static final boolean DEFAULT_INDENT_BLOCK_STATEMENTS = true;
+	public static final boolean DEFAULT_INDENT_BODY_DECLARATIONS_COMPARE_TO_TYPE_HEADER = true;
+	public static final boolean DEFAULT_INDENT_BREAKS_COMPARE_TO_CASES = true;
+	public static final boolean DEFAULT_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES = true;
+	public static final boolean DEFAULT_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH = true;
+	public static final boolean DEFAULT_INSERT_NEW_LINE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER = false;
+	public static final boolean DEFAULT_INSERT_NEW_LINE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER = false;
+	public static final boolean DEFAULT_INSERT_NEW_LINE_IN_CONTROL_STATEMENTS = false;
+	public static final boolean DEFAULT_INSERT_NEW_LINE_IN_EMPTY_ANONYMOUS_TYPE_DECLARATION = true;
+	public static final boolean DEFAULT_INSERT_NEW_LINE_IN_EMPTY_BLOCK = true;
+	public static final boolean DEFAULT_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY = true;
+	public static final boolean DEFAULT_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATORS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_BINARY_OPERATOR = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_BLOCK_CLOSE_BRACE = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_CLOSING_PAREN_IN_CAST = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COLON_IN_ASSERT = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COLON_IN_CONDITIONAL = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COLON_IN_LABELED_STATEMENT = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_ALLOCATION_EXPRESSION = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_ARRAY_INITIALIZER = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_ARGUMENTS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_THROWS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_EXPLICITCONSTRUCTORCALL_ARGUMENTS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_FOR_INCREMENTS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_FOR_INITS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_MESSAGESEND_ARGUMENTS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_METHOD_ARGUMENTS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_METHOD_THROWS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_SUPERINTERFACES = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_OPEN_PAREN_IN_PARENTHESIZED_EXPRESSION = false;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CAST = false;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_POSTFIX_OPERATOR = false;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_PREFIX_OPERATOR = false;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_QUESTION_IN_CONDITIONAL = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_SEMICOLON_IN_FOR = true;
+	public static final boolean DEFAULT_INSERT_SPACE_AFTER_UNARY_OPERATOR = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_ANONYMOUS_TYPE_OPEN_BRACE = true; 
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATORS = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_BINARY_OPERATOR = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_BLOCK_OPEN_BRACE = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_BRACKET_IN_ARRAY_REFERENCE = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_BRACKET_IN_ARRAY_TYPE_REFERENCE = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_CATCH_EXPRESSION = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_CLOSING_PAREN = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CAST = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_PARENTHESIZED_EXPRESSION = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COLON_IN_ASSERT = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COLON_IN_CASE = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COLON_IN_CONDITIONAL = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COLON_IN_DEFAULT = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COLON_IN_LABELED_STATEMENT = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_ALLOCATION_EXPRESSION = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_ARRAY_INITIALIZER = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_ARGUMENTS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_THROWS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_EXPLICITCONSTRUCTORCALL_ARGUMENTS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INCREMENTS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INITS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_MESSAGESEND_ARGUMENTS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_ARGUMENTS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_THROWS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_SUPERINTERFACES = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_FIRST_ARGUMENT = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_FIRST_INITIALIZER = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_FOR_PAREN = true;	
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_IF_CONDITION = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_MESSAGE_SEND = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_METHOD_DECLARATION_OPEN_PAREN = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_METHOD_OPEN_BRACE = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_OPEN_PAREN_IN_PARENTHESIZED_EXPRESSION = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ARRAY_INITIALIZER = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_POSTFIX_OPERATOR = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_PREFIX_OPERATOR = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_QUESTION_IN_CONDITIONAL = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_SEMICOLON = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_SWITCH_CONDITION = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_SWITCH_OPEN_BRACE = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_SYNCHRONIZED_CONDITION = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_TYPE_OPEN_BRACE = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_UNARY_OPERATOR = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BEFORE_WHILE_CONDITION = true;
+	public static final boolean DEFAULT_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_REFERENCE = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_TYPE_REFERENCE = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BETWEEN_EMPTY_ARGUMENTS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_BETWEEN_EMPTY_ARRAY_INITIALIZER = false;	
+	public static final boolean DEFAULT_INSERT_SPACE_IN_CATCH_EXPRESSION = false;
+	public static final boolean DEFAULT_INSERT_SPACE_IN_FOR_PARENS = false;
+	public static final boolean DEFAULT_INSERT_SPACE_IN_IF_CONDITION = false;
+	public static final boolean DEFAULT_INSERT_SPACE_IN_SWITCH_CONDITION = false;
+	public static final boolean DEFAULT_INSERT_SPACE_IN_SYNCHRONIZED_CONDITION = false;
+	public static final boolean DEFAULT_INSERT_SPACE_IN_WHILE_CONDITION = false;
+	public static final boolean DEFAULT_INSERT_SPACE_WITHIN_MESSAGE_SEND = false;
+	public static final boolean DEFAULT_KEEP_ELSE_STATEMENT_ON_SAME_LINE = false;
+	public static final boolean DEFAULT_KEEP_SIMPLE_IF_ON_ONE_LINE = false; 
+	public static final boolean DEFAULT_KEEP_THEN_STATEMENT_ON_SAME_LINE = false;
+	public static final int DEFAULT_MESSAGE_SEND_ARGUMENTS_ALIGNMENT = Alignment.M_COMPACT_SPLIT;
+	public static final int DEFAULT_MESSAGE_SEND_SELECTOR_ALIGNMENT = Alignment.M_COMPACT_SPLIT;
+	public static final int DEFAULT_METHOD_DECLARATION_ARGUMENTS_ALIGNMENT = Alignment.M_COMPACT_SPLIT;
+	public static final String DEFAULT_METHOD_DECLARATION_BRACE_POSITION = DefaultCodeFormatterConstants.END_OF_LINE;
+	public static final int DEFAULT_METHOD_THROWS_CLAUSE_ALIGNMENT = Alignment.M_COMPACT_SPLIT;
+	public static final int DEFAULT_MULTIPLE_FIELDS_ALIGNMENT = Alignment.M_COMPACT_SPLIT;//$NON-NLS-1$
+	public static final int DEFAULT_NUMBER_OF_BLANK_LINES_TO_INSERT_AT_BEGINNING_OF_METHOD_BODY = 0;
+	public static final int DEFAULT_NUMBER_OF_EMPTY_LINES_TO_PRESERVE = 0;
+	
+	public static final int DEFAULT_PAGE_WIDTH = 80;
+	public static final boolean DEFAULT_PRESERVE_USER_LINEBREAKS = false;
+	public static final boolean DEFAULT_PUT_EMPTY_STATEMENT_ON_NEW_LINE = false;
+	public static final int DEFAULT_QUALIFIED_ALLOCATION_EXPRESSION_ARGUMENTS_ALIGNMENT = Alignment.M_COMPACT_SPLIT;
+	public static final String DEFAULT_SWITCH_BRACE_POSITION = DefaultCodeFormatterConstants.END_OF_LINE;
+	public static final int DEFAULT_TAB_SIZE = 4;
+	public static final String DEFAULT_TYPE_DECLARATION_BRACE_POSITION = DefaultCodeFormatterConstants.END_OF_LINE;
+	public static final int DEFAULT_TYPE_DECLARATION_SUPERCLASS_ALIGNMENT = Alignment.M_NEXT_SHIFTED_SPLIT;
+	public static final int DEFAULT_TYPE_DECLARATION_SUPERINTERFACES_ALIGNMENT = Alignment.M_NEXT_SHIFTED_SPLIT;
+	public static final int DEFAULT_TYPE_MEMBER_ALIGNMENT = Alignment.M_NO_ALIGNMENT;
+	public static final boolean DEFAULT_USE_TAB = true; // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=49081
+
+	public static DefaultCodeFormatterOptions getDefaultSettings() {
+		DefaultCodeFormatterOptions options = new DefaultCodeFormatterOptions();
+		options.setDefaultSettings();
+		return options;
+	}
+	
+	public static DefaultCodeFormatterOptions getJavaConventionsSettings() {
+		DefaultCodeFormatterOptions options = new DefaultCodeFormatterOptions();
+		options.setJavaConventionsSettings();
+		return options;
+	}
+
+	public int allocation_expression_arguments_alignment;
+	public String anonymous_type_declaration_brace_position;
+	public String array_initializer_brace_position;
+	public int array_initializer_continuation_indentation;
+	public int array_initializer_expressions_alignment;
+	public int binary_expression_alignment;
+	public int blank_lines_after_imports;
+	public int blank_lines_after_package;
+	public int blank_lines_before_field;
+	public int blank_lines_before_first_class_body_declaration;
+	public int blank_lines_before_imports;
+	public int blank_lines_before_member_type;
+	public int blank_lines_before_method;
+	public int blank_lines_before_new_chunk;
+	public int blank_lines_before_package;
+	public String block_brace_position;
+	public boolean compact_else_if;
+	public int compact_if_alignment;
+	public int conditional_expression_alignment;
+	public int continuation_indentation;
+	public int explicit_constructor_arguments_alignment;
+	public char filling_space; 	// TODO remove when testing is over
+	public boolean format_guardian_clause_on_one_line;
+	public boolean indent_block_statements;
+	public boolean indent_body_declarations_compare_to_type_header;
+	public boolean indent_breaks_compare_to_cases;
+	public boolean indent_switchstatements_compare_to_cases;
+	public boolean indent_switchstatements_compare_to_switch;
+	public int initial_indentation_level;
+	public boolean insert_new_line_after_opening_brace_in_array_initializer;
+	public boolean insert_new_line_before_closing_brace_in_array_initializer;
+	public boolean insert_new_line_in_control_statements;
+	public boolean insert_new_line_in_empty_anonymous_type_declaration;
+	public boolean insert_new_line_in_empty_block;
+	public boolean insert_new_line_in_empty_method_body;
+	public boolean insert_new_line_in_empty_type_declaration;
+	public boolean insert_space_after_assignment_operators;
+	public boolean insert_space_after_binary_operator;
+	public boolean insert_space_after_block_close_brace;
+	public boolean insert_space_after_closing_paren_in_cast;
+	public boolean insert_space_after_colon_in_assert;
+	public boolean insert_space_after_colon_in_conditional;
+	public boolean insert_space_after_colon_in_labeled_statement;
+	public boolean insert_space_after_comma_in_allocation_expression;
+	public boolean insert_space_after_comma_in_array_initializer;
+	public boolean insert_space_after_comma_in_constructor_arguments;
+	public boolean insert_space_after_comma_in_constructor_throws;
+	public boolean insert_space_after_comma_in_explicitconstructorcall_arguments;
+	public boolean insert_space_after_comma_in_for_increments;
+	public boolean insert_space_after_comma_in_for_inits;
+	public boolean insert_space_after_comma_in_messagesend_arguments;
+	public boolean insert_space_after_comma_in_method_arguments;
+	public boolean insert_space_after_comma_in_method_throws;
+	public boolean insert_space_after_comma_in_multiple_field_declarations;
+	public boolean insert_space_after_comma_in_multiple_local_declarations;
+	public boolean insert_space_after_comma_in_superinterfaces;
+	public boolean insert_space_after_open_paren_in_parenthesized_expression;
+	public boolean insert_space_after_opening_paren_in_cast;
+	public boolean insert_space_after_postfix_operator;
+	public boolean insert_space_after_prefix_operator;
+	public boolean insert_space_after_question_in_conditional;
+	public boolean insert_space_after_semicolon_in_for;
+	public boolean insert_space_after_unary_operator;
+	public boolean insert_space_before_anonymous_type_open_brace;
+	public boolean insert_space_before_assignment_operators;
+	public boolean insert_space_before_binary_operator;
+	public boolean insert_space_before_block_open_brace;
+	public boolean insert_space_before_bracket_in_array_reference;
+	public boolean insert_space_before_bracket_in_array_type_reference;
+	public boolean insert_space_before_catch_expression;
+	public boolean insert_space_before_closing_brace_in_array_initializer;
+	public boolean insert_space_before_closing_paren;
+	public boolean insert_space_before_closing_paren_in_cast;
+	public boolean insert_space_before_closing_paren_in_parenthesized_expression;
+	public boolean insert_space_before_colon_in_assert;
+	public boolean insert_space_before_colon_in_case;
+	public boolean insert_space_before_colon_in_conditional;
+	public boolean insert_space_before_colon_in_default;
+	public boolean insert_space_before_colon_in_labeled_statement;
+	public boolean insert_space_before_comma_in_allocation_expression;
+	public boolean insert_space_before_comma_in_array_initializer;
+	public boolean insert_space_before_comma_in_constructor_arguments;
+	public boolean insert_space_before_comma_in_constructor_throws;
+	public boolean insert_space_before_comma_in_explicitconstructorcall_arguments;
+	public boolean insert_space_before_comma_in_for_increments;
+	public boolean insert_space_before_comma_in_for_inits;
+	public boolean insert_space_before_comma_in_messagesend_arguments;
+	public boolean insert_space_before_comma_in_method_arguments;
+	public boolean insert_space_before_comma_in_method_throws;
+	public boolean insert_space_before_comma_in_multiple_field_declarations;
+	public boolean insert_space_before_comma_in_multiple_local_declarations;
+	public boolean insert_space_before_comma_in_superinterfaces;
+	public boolean insert_space_before_first_argument;
+	public boolean insert_space_before_first_initializer;
+	public boolean insert_space_before_for_paren;
+	public boolean insert_space_before_if_condition;
+	public boolean insert_space_before_message_send;
+	public boolean insert_space_before_method_declaration_open_paren;
+	public boolean insert_space_before_method_open_brace;
+	public boolean insert_space_before_open_paren_in_parenthesized_expression;
+	public boolean insert_space_before_opening_brace_in_array_initializer;
+	public boolean insert_space_before_postfix_operator;
+	public boolean insert_space_before_prefix_operator;
+	public boolean insert_space_before_question_in_conditional;
+	public boolean insert_space_before_semicolon;
+	public boolean insert_space_before_switch_condition;
+	public boolean insert_space_before_switch_open_brace;
+	public boolean insert_space_before_synchronized_condition;
+	public boolean insert_space_before_type_open_brace;
+	public boolean insert_space_before_unary_operator;
+	public boolean insert_space_before_while_condition;
+	public boolean insert_space_between_brackets_in_array_reference;
+	public boolean insert_space_between_brackets_in_array_type_reference;
+	public boolean insert_space_between_empty_arguments;
+	public boolean insert_space_between_empty_array_initializer;
+	public boolean insert_space_in_catch_expression;
+	public boolean insert_space_in_for_parens;
+	public boolean insert_space_in_if_condition;
+	public boolean insert_space_in_switch_condition;
+	public boolean insert_space_in_synchronized_condition;
+	public boolean insert_space_in_while_condition;
+	public boolean insert_space_within_message_send;
+	public boolean keep_else_statement_on_same_line;
+	public boolean keep_simple_if_on_one_line;
+	public boolean keep_then_statement_on_same_line;
+	public String line_separator;
+	public int message_send_arguments_alignment;
+	public int message_send_selector_alignment;
+	public int method_declaration_arguments_alignment;
+	public String method_declaration_brace_position;
+	public int method_throws_clause_alignment;
+	public int multiple_fields_alignment;
+	public int number_of_blank_lines_to_insert_at_beginning_of_method_body;
+	public int number_of_empty_lines_to_preserve;
+	public int page_width;
+	public boolean preserve_user_linebreaks;
+	public boolean put_empty_statement_on_new_line; 
+	public int qualified_allocation_expression_arguments_alignment;
+	public String switch_brace_position;
+	public int tab_size;
+	public String type_declaration_brace_position;
+	public int type_declaration_superclass_alignment;
+	public int type_declaration_superinterfaces_alignment;
+	public int type_member_alignment;
+	public boolean use_tab;
+	
+	private DefaultCodeFormatterOptions() {
+		// cannot be instantiated
+	}
+
+	public DefaultCodeFormatterOptions(Map settings) {
+		setDefaultSettings();
+		if (settings == null) return;
+		set(settings);
+	}
+
+	private String getAlignment(int alignment) {
+		return Integer.toString(alignment);
+	}
+
+	public Map getMap() {
+		Map options = new HashMap();
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ALLOCATION_EXPRESSION_ARGUMENTS_ALIGNMENT, getAlignment(this.allocation_expression_arguments_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ANONYMOUS_TYPE_DECLARATION_BRACE_POSITION, this.anonymous_type_declaration_brace_position);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ARRAY_INITIALIZER_BRACE_POSITION, this.array_initializer_brace_position);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ARRAY_INITIALIZER_CONTINUATION_INDENTATION, Integer.toString(this.array_initializer_continuation_indentation));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_ARRAY_INITIALIZER_EXPRESSIONS_ALIGNMENT, getAlignment(this.array_initializer_expressions_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BINARY_EXPRESSION_ALIGNMENT, getAlignment(this.binary_expression_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_AFTER_IMPORTS, Integer.toString(this.blank_lines_after_imports));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_AFTER_PACKAGE, Integer.toString(this.blank_lines_after_package));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_FIELD, Integer.toString(this.blank_lines_before_field));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_FIRST_CLASS_BODY_DECLARATION, Integer.toString(this.blank_lines_before_first_class_body_declaration));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_IMPORTS, Integer.toString(this.blank_lines_before_imports));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_MEMBER_TYPE, Integer.toString(this.blank_lines_before_member_type));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_METHOD, Integer.toString(this.blank_lines_before_method));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_NEW_CHUNK, Integer.toString(this.blank_lines_before_new_chunk));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_PACKAGE, Integer.toString(this.blank_lines_before_package));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_BLOCK_BRACE_POSITION, this.block_brace_position);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_COMPACT_ELSE_IF, this.compact_else_if ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_COMPACT_IF_ALIGNMENT, getAlignment(this.compact_if_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_CONDITIONAL_EXPRESSION_ALIGNMENT, getAlignment(this.conditional_expression_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION, Integer.toString(this.continuation_indentation));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_EXPLICIT_CONSTRUCTOR_ARGUMENTS_ALIGNMENT, getAlignment(this.explicit_constructor_arguments_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_FILLING_SPACE, String.valueOf(this.filling_space));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_FORMAT_GUARDIAN_CLAUSE_ON_ONE_LINE, this.format_guardian_clause_on_one_line ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_BLOCK_STATEMENTS, this.indent_block_statements ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_TYPE_HEADER, this.indent_body_declarations_compare_to_type_header ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_BREAKS_COMPARE_TO_CASES, this.indent_breaks_compare_to_cases ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES, this.indent_switchstatements_compare_to_cases ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH, this.indent_switchstatements_compare_to_switch ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER, this.insert_new_line_after_opening_brace_in_array_initializer ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER, this.insert_new_line_before_closing_brace_in_array_initializer ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_CONTROL_STATEMENTS, this.insert_new_line_in_control_statements ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANONYMOUS_TYPE_DECLARATION, this.insert_new_line_in_empty_anonymous_type_declaration ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK, this.insert_new_line_in_empty_block ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY, this.insert_new_line_in_empty_method_body ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION, this.insert_new_line_in_empty_type_declaration ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATORS, this.insert_space_after_assignment_operators ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR, this.insert_space_after_binary_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BLOCK_CLOSE_BRACE, this.insert_space_after_block_close_brace ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_PAREN_IN_CAST, this.insert_space_after_closing_paren_in_cast ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_ASSERT, this.insert_space_after_colon_in_assert ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_CONDITIONAL, this.insert_space_after_colon_in_conditional ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_LABELED_STATEMENT, this.insert_space_after_colon_in_labeled_statement ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ALLOCATION_EXPRESSION, this.insert_space_after_comma_in_allocation_expression ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ARRAY_INITIALIZER, this.insert_space_after_comma_in_array_initializer ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_ARGUMENTS, this.insert_space_after_comma_in_constructor_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_THROWS, this.insert_space_after_comma_in_constructor_throws ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_EXPLICITCONSTRUCTORCALL_ARGUMENTS, this.insert_space_after_comma_in_explicitconstructorcall_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_FOR_INCREMENTS, this.insert_space_after_comma_in_for_increments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_FOR_INITS, this.insert_space_after_comma_in_for_inits ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MESSAGESEND_ARGUMENTS, this.insert_space_after_comma_in_messagesend_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_METHOD_ARGUMENTS, this.insert_space_after_comma_in_method_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_METHOD_THROWS, this.insert_space_after_comma_in_method_throws ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS, this.insert_space_after_comma_in_multiple_field_declarations ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS, this.insert_space_after_comma_in_multiple_local_declarations ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_SUPERINTERFACES, this.insert_space_after_comma_in_superinterfaces ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPEN_PAREN_IN_PARENTHESIZED_EXPRESSION, this.insert_space_after_open_paren_in_parenthesized_expression ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CAST, this.insert_space_after_opening_paren_in_cast ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_POSTFIX_OPERATOR, this.insert_space_after_postfix_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_PREFIX_OPERATOR, this.insert_space_after_prefix_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_QUESTION_IN_CONDITIONAL, this.insert_space_after_question_in_conditional ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_SEMICOLON_IN_FOR, this.insert_space_after_semicolon_in_for ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_UNARY_OPERATOR, this.insert_space_after_unary_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ANONYMOUS_TYPE_OPEN_BRACE, this.insert_space_before_anonymous_type_open_brace ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATORS, this.insert_space_before_assignment_operators ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, this.insert_space_before_binary_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BLOCK_OPEN_BRACE, this.insert_space_before_block_open_brace ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BRACKET_IN_ARRAY_REFERENCE, this.insert_space_before_bracket_in_array_reference ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BRACKET_IN_ARRAY_TYPE_REFERENCE, this.insert_space_before_bracket_in_array_type_reference ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CATCH_EXPRESSION, this.insert_space_before_catch_expression ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER, this.insert_space_before_closing_brace_in_array_initializer ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN, this.insert_space_before_closing_paren ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CAST, this.insert_space_before_closing_paren_in_cast ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_PARENTHESIZED_EXPRESSION, this.insert_space_before_closing_paren_in_parenthesized_expression ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_ASSERT, this.insert_space_before_colon_in_assert ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_CASE, this.insert_space_before_colon_in_case ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_CONDITIONAL, this.insert_space_before_colon_in_conditional ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_DEFAULT, this.insert_space_before_colon_in_default ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_LABELED_STATEMENT, this.insert_space_before_colon_in_labeled_statement ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ALLOCATION_EXPRESSION, this.insert_space_before_comma_in_allocation_expression ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ARRAY_INITIALIZER, this.insert_space_before_comma_in_array_initializer ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_ARGUMENTS, this.insert_space_before_comma_in_constructor_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_THROWS, this.insert_space_before_comma_in_constructor_throws ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_EXPLICITCONSTRUCTORCALL_ARGUMENTS, this.insert_space_before_comma_in_explicitconstructorcall_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INCREMENTS, this.insert_space_before_comma_in_for_increments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INITS, this.insert_space_before_comma_in_for_inits ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MESSAGESEND_ARGUMENTS, this.insert_space_before_comma_in_messagesend_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_ARGUMENTS, this.insert_space_before_comma_in_method_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_THROWS, this.insert_space_before_comma_in_method_throws ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS, this.insert_space_before_comma_in_multiple_field_declarations ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS, this.insert_space_before_comma_in_multiple_local_declarations ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_SUPERINTERFACES, this.insert_space_before_comma_in_superinterfaces ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_FIRST_ARGUMENT, this.insert_space_before_first_argument ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_FIRST_INITIALIZER, this.insert_space_before_first_initializer ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_FOR_PAREN, this.insert_space_before_for_paren ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_IF_CONDITION, this.insert_space_before_if_condition ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_MESSAGE_SEND, this.insert_space_before_message_send ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_METHOD_DECLARATION_OPEN_PAREN, this.insert_space_before_method_declaration_open_paren ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_METHOD_OPEN_BRACE, this.insert_space_before_method_open_brace ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPEN_PAREN_IN_PARENTHESIZED_EXPRESSION, this.insert_space_before_open_paren_in_parenthesized_expression ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ARRAY_INITIALIZER, this.insert_space_before_opening_brace_in_array_initializer ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_POSTFIX_OPERATOR, this.insert_space_before_postfix_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_PREFIX_OPERATOR, this.insert_space_before_prefix_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_QUESTION_IN_CONDITIONAL, this.insert_space_before_question_in_conditional ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SEMICOLON, this.insert_space_before_semicolon ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SWITCH_CONDITION, this.insert_space_before_switch_condition ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SWITCH_OPEN_BRACE, this.insert_space_before_switch_open_brace ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SYNCHRONIZED_CONDITION, this.insert_space_before_synchronized_condition ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_TYPE_OPEN_BRACE, this.insert_space_before_type_open_brace ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_UNARY_OPERATOR, this.insert_space_before_unary_operator ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_WHILE_CONDITION, this.insert_space_before_while_condition ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_REFERENCE, this.insert_space_between_brackets_in_array_reference ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_TYPE_REFERENCE, this.insert_space_between_brackets_in_array_type_reference ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_ARGUMENTS, this.insert_space_between_empty_arguments ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_ARRAY_INITIALIZER, this.insert_space_between_empty_array_initializer ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_CATCH_EXPRESSION, this.insert_space_in_catch_expression ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_FOR_PARENS, this.insert_space_in_for_parens ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_IF_CONDITION, this.insert_space_in_if_condition ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_SWITCH_CONDITION, this.insert_space_in_switch_condition ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_SYNCHRONIZED_CONDITION, this.insert_space_in_synchronized_condition ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_WHILE_CONDITION, this.insert_space_in_while_condition ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_WITHIN_MESSAGE_SEND, this.insert_space_within_message_send ? JavaCore.INSERT : JavaCore.DO_NOT_INSERT);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_ELSE_STATEMENT_ON_SAME_LINE, this.keep_else_statement_on_same_line ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_SIMPLE_IF_ON_ONE_LINE, this.keep_simple_if_on_one_line ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_KEEP_THEN_STATEMENT_ON_SAME_LINE, this.keep_then_statement_on_same_line ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_LINE_SPLIT, Integer.toString(this.page_width));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_MESSAGE_SEND_ARGUMENTS_ALIGNMENT, getAlignment(this.message_send_arguments_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_MESSAGE_SEND_SELECTOR_ALIGNMENT, getAlignment(this.message_send_selector_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_METHOD_DECLARATION_ARGUMENTS_ALIGNMENT, getAlignment(this.method_declaration_arguments_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_METHOD_DECLARATION_BRACE_POSITION, this.method_declaration_brace_position);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_METHOD_THROWS_CLAUSE_ALIGNMENT, getAlignment(this.method_throws_clause_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_MULTIPLE_FIELDS_ALIGNMENT, getAlignment(this.multiple_fields_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_NUMBER_OF_BLANK_LINES_TO_INSERT_AT_BEGINNING_OF_METHOD_BODY, Integer.toString(number_of_blank_lines_to_insert_at_beginning_of_method_body));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE, Integer.toString(this.number_of_empty_lines_to_preserve));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_PRESERVE_USER_LINEBREAKS, this.preserve_user_linebreaks ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_PUT_EMPTY_STATEMENT_ON_NEW_LINE, this.put_empty_statement_on_new_line ? DefaultCodeFormatterConstants.TRUE : DefaultCodeFormatterConstants.FALSE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_QUALIFIED_ALLOCATION_EXPRESSION_ARGUMENTS_ALIGNMENT, getAlignment(this.qualified_allocation_expression_arguments_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_SWITCH_BRACE_POSITION, this.switch_brace_position);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, this.use_tab ? JavaCore.TAB: JavaCore.SPACE);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE, Integer.toString(this.tab_size));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_TYPE_DECLARATION_BRACE_POSITION, this.type_declaration_brace_position);
+		options.put(DefaultCodeFormatterConstants.FORMATTER_TYPE_DECLARATION_SUPERCLASS_ALIGNMENT, getAlignment(this.type_declaration_superclass_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_TYPE_DECLARATION_SUPERINTERFACES_ALIGNMENT, getAlignment(this.type_declaration_superinterfaces_alignment));
+		options.put(DefaultCodeFormatterConstants.FORMATTER_TYPE_MEMBER_ALIGNMENT, getAlignment(this.type_member_alignment));
+		return options;
+	}
+
+	public void set(Map settings) {
+		final Object allocationExpressionArgumentsAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ALLOCATION_EXPRESSION_ARGUMENTS_ALIGNMENT);
+		if (allocationExpressionArgumentsAlignmentOption != null) {
+			this.allocation_expression_arguments_alignment = Integer.parseInt((String) allocationExpressionArgumentsAlignmentOption);
+		}
+		final Object anonymousTypeDeclarationBracePositionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ANONYMOUS_TYPE_DECLARATION_BRACE_POSITION);
+		if (anonymousTypeDeclarationBracePositionOption != null) {
+			this.anonymous_type_declaration_brace_position = (String) anonymousTypeDeclarationBracePositionOption;
+		}
+		final Object arrayInitializerBracePositionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ARRAY_INITIALIZER_BRACE_POSITION);
+		if (arrayInitializerBracePositionOption != null) {
+			this.array_initializer_brace_position = (String) arrayInitializerBracePositionOption;
+		}
+		final Object arrayInitializerContinuationIndentationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ARRAY_INITIALIZER_CONTINUATION_INDENTATION);
+		if (arrayInitializerContinuationIndentationOption != null) {
+			this.array_initializer_continuation_indentation = Integer.parseInt((String) arrayInitializerContinuationIndentationOption);
+		}
+		final Object arrayInitializerExpressionsAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_ARRAY_INITIALIZER_EXPRESSIONS_ALIGNMENT);
+		if (arrayInitializerExpressionsAlignmentOption != null) {
+			this.array_initializer_expressions_alignment = Integer.parseInt((String) arrayInitializerExpressionsAlignmentOption);
+		}
+		final Object binaryExpressionAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BINARY_EXPRESSION_ALIGNMENT);
+		if (binaryExpressionAlignmentOption != null) {
+			this.binary_expression_alignment = Integer.parseInt((String) binaryExpressionAlignmentOption);
+		}
+		final Object blankLinesAfterImportsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_AFTER_IMPORTS);
+		if (blankLinesAfterImportsOption != null) {
+			this.blank_lines_after_imports = Integer.parseInt((String) blankLinesAfterImportsOption);
+		}
+		final Object blankLinesAfterPackageOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_AFTER_PACKAGE);
+		if (blankLinesAfterPackageOption != null) {
+			this.blank_lines_after_package = Integer.parseInt((String) blankLinesAfterPackageOption);
+		}
+		final Object blankLinesBeforeFieldOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_FIELD);
+		if (blankLinesBeforeFieldOption != null) {
+			this.blank_lines_before_field = Integer.parseInt((String) blankLinesBeforeFieldOption);
+		}
+		final Object blankLinesBeforeFirstClassBodyDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_FIRST_CLASS_BODY_DECLARATION);
+		if (blankLinesBeforeFirstClassBodyDeclarationOption != null) {
+			this.blank_lines_before_first_class_body_declaration = Integer.parseInt((String) blankLinesBeforeFirstClassBodyDeclarationOption);
+		}
+		final Object blankLinesBeforeImportsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_IMPORTS);
+		if (blankLinesBeforeImportsOption != null) {
+			this.blank_lines_before_imports = Integer.parseInt((String) blankLinesBeforeImportsOption);
+		}
+		final Object blankLinesBeforeMemberTypeOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_MEMBER_TYPE);
+		if (blankLinesBeforeMemberTypeOption != null) {
+			this.blank_lines_before_member_type = Integer.parseInt((String) blankLinesBeforeMemberTypeOption);
+		}
+		final Object blankLinesBeforeMethodOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_METHOD);
+		if (blankLinesBeforeMethodOption != null) {
+			this.blank_lines_before_method = Integer.parseInt((String) blankLinesBeforeMethodOption);
+		}
+		final Object blankLinesBeforeNewChunkOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_NEW_CHUNK);
+		if (blankLinesBeforeNewChunkOption != null) {
+			this.blank_lines_before_new_chunk = Integer.parseInt((String) blankLinesBeforeNewChunkOption);
+		}
+		final Object blankLinesBeforePackageOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BEFORE_PACKAGE);
+		if (blankLinesBeforePackageOption != null) {
+			this.blank_lines_before_package = Integer.parseInt((String) blankLinesBeforePackageOption);
+		}
+		final Object blockBracePositionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_BLOCK_BRACE_POSITION);
+		if (blockBracePositionOption != null) {
+			this.block_brace_position = (String) blockBracePositionOption;
+		}
+		final Object compactElseIfOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMPACT_ELSE_IF);
+		if (compactElseIfOption != null) {
+			this.compact_else_if = DefaultCodeFormatterConstants.TRUE.equals(compactElseIfOption);
+		}
+		final Object compactIfAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_COMPACT_IF_ALIGNMENT);
+		if (compactIfAlignmentOption != null) {
+			this.compact_if_alignment = Integer.parseInt((String) compactIfAlignmentOption);
+		}
+		final Object conditionalExpressionAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_CONDITIONAL_EXPRESSION_ALIGNMENT);
+		if (conditionalExpressionAlignmentOption != null) {
+			this.conditional_expression_alignment = Integer.parseInt((String) conditionalExpressionAlignmentOption);
+		}
+		final Object continuationIndentationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_CONTINUATION_INDENTATION);
+		if (continuationIndentationOption != null) {
+			this.continuation_indentation = Integer.parseInt((String) continuationIndentationOption);
+		}
+		final Object explicitConstructorArgumentsAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_EXPLICIT_CONSTRUCTOR_ARGUMENTS_ALIGNMENT);
+		if (explicitConstructorArgumentsAlignmentOption != null) {
+			this.explicit_constructor_arguments_alignment = Integer.parseInt((String) explicitConstructorArgumentsAlignmentOption);
+		}
+		final Object fillingSpaceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_FILLING_SPACE);
+		if (fillingSpaceOption != null) {
+			String fillingSpaceOptionValue = (String) fillingSpaceOption;
+			if (fillingSpaceOptionValue.length() >= 1) {
+				this.filling_space = fillingSpaceOptionValue.charAt(0);
+			}
+		}
+		final Object formatGuardianClauseOnOneLineOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_FORMAT_GUARDIAN_CLAUSE_ON_ONE_LINE);
+		if (formatGuardianClauseOnOneLineOption != null) {
+			this.format_guardian_clause_on_one_line = DefaultCodeFormatterConstants.TRUE.equals(formatGuardianClauseOnOneLineOption);
+		}
+		final Object indentBlockStatementsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INDENT_BLOCK_STATEMENTS);
+		if (indentBlockStatementsOption != null) {
+			this.indent_block_statements = DefaultCodeFormatterConstants.TRUE.equals(indentBlockStatementsOption);
+		}
+		final Object indentBodyDeclarationsCompareToTypeHeaderOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INDENT_BODY_DECLARATIONS_COMPARE_TO_TYPE_HEADER);
+		if (indentBodyDeclarationsCompareToTypeHeaderOption != null) {
+			this.indent_body_declarations_compare_to_type_header = DefaultCodeFormatterConstants.TRUE.equals(indentBodyDeclarationsCompareToTypeHeaderOption);
+		}
+		final Object indentBreaksCompareToCasesOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INDENT_BREAKS_COMPARE_TO_CASES);
+		if (indentBreaksCompareToCasesOption != null) {
+			this.indent_breaks_compare_to_cases = DefaultCodeFormatterConstants.TRUE.equals(indentBreaksCompareToCasesOption);
+		}
+		final Object indentSwitchstatementsCompareToCasesOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES);
+		if (indentSwitchstatementsCompareToCasesOption != null) {
+			this.indent_switchstatements_compare_to_cases = DefaultCodeFormatterConstants.TRUE.equals(indentSwitchstatementsCompareToCasesOption);
+		}
+		final Object indentSwitchstatementsCompareToSwitchOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH);
+		if (indentSwitchstatementsCompareToSwitchOption != null) {
+			this.indent_switchstatements_compare_to_switch = DefaultCodeFormatterConstants.TRUE.equals(indentSwitchstatementsCompareToSwitchOption);
+		}
+		final Object insertNewLineAfterOpeningBraceInArrayInitializerOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER);
+		if (insertNewLineAfterOpeningBraceInArrayInitializerOption != null) {
+			this.insert_new_line_after_opening_brace_in_array_initializer = JavaCore.INSERT.equals(insertNewLineAfterOpeningBraceInArrayInitializerOption);
+		}
+		final Object insertNewLineBeforeClosingBraceInArrayInitializerOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER);
+		if (insertNewLineBeforeClosingBraceInArrayInitializerOption != null) {
+			this.insert_new_line_before_closing_brace_in_array_initializer = JavaCore.INSERT.equals(insertNewLineBeforeClosingBraceInArrayInitializerOption);
+		}
+		final Object insertNewLineInControlStatementsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_CONTROL_STATEMENTS);
+		if (insertNewLineInControlStatementsOption != null) {
+			this.insert_new_line_in_control_statements = JavaCore.INSERT.equals(insertNewLineInControlStatementsOption);
+		}
+		final Object insertNewLineInEmptyAnonymousTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_ANONYMOUS_TYPE_DECLARATION);
+		if (insertNewLineInEmptyAnonymousTypeDeclarationOption != null) {
+			this.insert_new_line_in_empty_anonymous_type_declaration = JavaCore.INSERT.equals(insertNewLineInEmptyAnonymousTypeDeclarationOption);
+		}
+		final Object insertNewLineInEmptyBlockOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_BLOCK);
+		if (insertNewLineInEmptyBlockOption != null) {
+			this.insert_new_line_in_empty_block = JavaCore.INSERT.equals(insertNewLineInEmptyBlockOption);
+		}
+		final Object insertNewLineInEmptyMethodBodyOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY);
+		if (insertNewLineInEmptyMethodBodyOption != null) {
+			this.insert_new_line_in_empty_method_body = JavaCore.INSERT.equals(insertNewLineInEmptyMethodBodyOption);
+		}
+		final Object insertNewLineInEmptyTypeDeclarationOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION);
+		if (insertNewLineInEmptyTypeDeclarationOption != null) {
+			this.insert_new_line_in_empty_type_declaration = JavaCore.INSERT.equals(insertNewLineInEmptyTypeDeclarationOption);
+		}
+		final Object insertSpaceAfterAssignmentOperatorsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATORS);
+		if (insertSpaceAfterAssignmentOperatorsOption != null) {
+			this.insert_space_after_assignment_operators = JavaCore.INSERT.equals(insertSpaceAfterAssignmentOperatorsOption);
+		}
+		final Object insertSpaceAfterBinaryOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BINARY_OPERATOR);
+		if (insertSpaceAfterBinaryOperatorOption != null) {
+			this.insert_space_after_binary_operator = JavaCore.INSERT.equals(insertSpaceAfterBinaryOperatorOption);
+		}
+		final Object insertSpaceAfterBlockCloseBraceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_BLOCK_CLOSE_BRACE);
+		if (insertSpaceAfterBlockCloseBraceOption != null) {
+			this.insert_space_after_block_close_brace = JavaCore.INSERT.equals(insertSpaceAfterBlockCloseBraceOption);
+		}
+		final Object insertSpaceAfterClosingParenInCastOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_PAREN_IN_CAST);
+		if (insertSpaceAfterClosingParenInCastOption != null) {
+			this.insert_space_after_closing_paren_in_cast = JavaCore.INSERT.equals(insertSpaceAfterClosingParenInCastOption);
+		}
+		final Object insertSpaceAfterColonInAssertOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_ASSERT);
+		if (insertSpaceAfterColonInAssertOption != null) {
+			this.insert_space_after_colon_in_assert = JavaCore.INSERT.equals(insertSpaceAfterColonInAssertOption);
+		}
+		final Object insertSpaceAfterColonInConditionalOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_CONDITIONAL);
+		if (insertSpaceAfterColonInConditionalOption != null) {
+			this.insert_space_after_colon_in_conditional = JavaCore.INSERT.equals(insertSpaceAfterColonInConditionalOption);
+		}
+		final Object insertSpaceAfterColonInLabeledStatementOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COLON_IN_LABELED_STATEMENT);
+		if (insertSpaceAfterColonInLabeledStatementOption != null) {
+			this.insert_space_after_colon_in_labeled_statement = JavaCore.INSERT.equals(insertSpaceAfterColonInLabeledStatementOption);
+		}
+		final Object insertSpaceAfterCommaInAllocationExpressionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ALLOCATION_EXPRESSION);
+		if (insertSpaceAfterCommaInAllocationExpressionOption != null) {
+			this.insert_space_after_comma_in_allocation_expression = JavaCore.INSERT.equals(insertSpaceAfterCommaInAllocationExpressionOption);
+		}
+		final Object insertSpaceAfterCommaInArrayInitializerOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_ARRAY_INITIALIZER);
+		if (insertSpaceAfterCommaInArrayInitializerOption != null) {
+			this.insert_space_after_comma_in_array_initializer = JavaCore.INSERT.equals(insertSpaceAfterCommaInArrayInitializerOption);
+		}
+		final Object insertSpaceAfterCommaInConstructorArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_ARGUMENTS);
+		if (insertSpaceAfterCommaInConstructorArgumentsOption != null) {
+			this.insert_space_after_comma_in_constructor_arguments = JavaCore.INSERT.equals(insertSpaceAfterCommaInConstructorArgumentsOption);
+		}
+		final Object insertSpaceAfterCommaInConstructorThrowsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_THROWS);
+		if (insertSpaceAfterCommaInConstructorThrowsOption != null) {
+			this.insert_space_after_comma_in_constructor_throws = JavaCore.INSERT.equals(insertSpaceAfterCommaInConstructorThrowsOption);
+		}
+		final Object insertSpaceAfterCommaInExplicitconstructorcallArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_EXPLICITCONSTRUCTORCALL_ARGUMENTS);
+		if (insertSpaceAfterCommaInExplicitconstructorcallArgumentsOption != null) {
+			this.insert_space_after_comma_in_explicitconstructorcall_arguments = JavaCore.INSERT.equals(insertSpaceAfterCommaInExplicitconstructorcallArgumentsOption);
+		}
+		final Object insertSpaceAfterCommaInForIncrementsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_FOR_INCREMENTS);
+		if (insertSpaceAfterCommaInForIncrementsOption != null) {
+			this.insert_space_after_comma_in_for_increments = JavaCore.INSERT.equals(insertSpaceAfterCommaInForIncrementsOption);
+		}
+		final Object insertSpaceAfterCommaInForInitsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_FOR_INITS);
+		if (insertSpaceAfterCommaInForInitsOption != null) {
+			this.insert_space_after_comma_in_for_inits = JavaCore.INSERT.equals(insertSpaceAfterCommaInForInitsOption);
+		}
+		final Object insertSpaceAfterCommaInMessagesendArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MESSAGESEND_ARGUMENTS);
+		if (insertSpaceAfterCommaInMessagesendArgumentsOption != null) {
+			this.insert_space_after_comma_in_messagesend_arguments = JavaCore.INSERT.equals(insertSpaceAfterCommaInMessagesendArgumentsOption);
+		}
+		final Object insertSpaceAfterCommaInMethodArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_METHOD_ARGUMENTS);
+		if (insertSpaceAfterCommaInMethodArgumentsOption != null) {
+			this.insert_space_after_comma_in_method_arguments = JavaCore.INSERT.equals(insertSpaceAfterCommaInMethodArgumentsOption);
+		}
+		final Object insertSpaceAfterCommaInMethodThrowsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_METHOD_THROWS);
+		if (insertSpaceAfterCommaInMethodThrowsOption != null) {
+			this.insert_space_after_comma_in_method_throws = JavaCore.INSERT.equals(insertSpaceAfterCommaInMethodThrowsOption);
+		}
+		final Object insertSpaceAfterCommaInMultipleFieldDeclarationsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS);
+		if (insertSpaceAfterCommaInMultipleFieldDeclarationsOption != null) {
+			this.insert_space_after_comma_in_multiple_field_declarations = JavaCore.INSERT.equals(insertSpaceAfterCommaInMultipleFieldDeclarationsOption);
+		}
+		final Object insertSpaceAfterCommaInMultipleLocalDeclarationsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS);
+		if (insertSpaceAfterCommaInMultipleLocalDeclarationsOption != null) {
+			this.insert_space_after_comma_in_multiple_local_declarations = JavaCore.INSERT.equals(insertSpaceAfterCommaInMultipleLocalDeclarationsOption);
+		}
+		final Object insertSpaceAfterCommaInSuperinterfacesOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_COMMA_IN_SUPERINTERFACES);
+		if (insertSpaceAfterCommaInSuperinterfacesOption != null) {
+			this.insert_space_after_comma_in_superinterfaces = JavaCore.INSERT.equals(insertSpaceAfterCommaInSuperinterfacesOption);
+		}
+		final Object insertSpaceAfterOpenParenInParenthesizedExpressionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPEN_PAREN_IN_PARENTHESIZED_EXPRESSION);
+		if (insertSpaceAfterOpenParenInParenthesizedExpressionOption != null) {
+			this.insert_space_after_open_paren_in_parenthesized_expression = JavaCore.INSERT.equals(insertSpaceAfterOpenParenInParenthesizedExpressionOption);
+		}
+		final Object insertSpaceAfterOpeningParenInCastOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CAST);
+		if (insertSpaceAfterOpeningParenInCastOption != null) {
+			this.insert_space_after_opening_paren_in_cast = JavaCore.INSERT.equals(insertSpaceAfterOpeningParenInCastOption);
+		}
+		final Object insertSpaceAfterPostfixOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_POSTFIX_OPERATOR);
+		if (insertSpaceAfterPostfixOperatorOption != null) {
+			this.insert_space_after_postfix_operator = JavaCore.INSERT.equals(insertSpaceAfterPostfixOperatorOption);
+		}
+		final Object insertSpaceAfterPrefixOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_PREFIX_OPERATOR);
+		if (insertSpaceAfterPrefixOperatorOption != null) {
+			this.insert_space_after_prefix_operator = JavaCore.INSERT.equals(insertSpaceAfterPrefixOperatorOption);
+		}
+		final Object insertSpaceAfterQuestionInConditionalOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_QUESTION_IN_CONDITIONAL);
+		if (insertSpaceAfterQuestionInConditionalOption != null) {
+			this.insert_space_after_question_in_conditional = JavaCore.INSERT.equals(insertSpaceAfterQuestionInConditionalOption);
+		}
+		final Object insertSpaceAfterSemicolonInForOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_SEMICOLON_IN_FOR);
+		if (insertSpaceAfterSemicolonInForOption != null) {
+			this.insert_space_after_semicolon_in_for = JavaCore.INSERT.equals(insertSpaceAfterSemicolonInForOption);
+		}
+		final Object insertSpaceAfterUnaryOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_UNARY_OPERATOR);
+		if (insertSpaceAfterUnaryOperatorOption != null) {
+			this.insert_space_after_unary_operator = JavaCore.INSERT.equals(insertSpaceAfterUnaryOperatorOption);
+		}
+		final Object insertSpaceBeforeAnonymousTypeOpenBraceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ANONYMOUS_TYPE_OPEN_BRACE);
+		if (insertSpaceBeforeAnonymousTypeOpenBraceOption != null) {
+			this.insert_space_before_anonymous_type_open_brace = JavaCore.INSERT.equals(insertSpaceBeforeAnonymousTypeOpenBraceOption);
+		}
+		final Object insertSpaceBeforeAssignmentOperatorsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATORS);
+		if (insertSpaceBeforeAssignmentOperatorsOption != null) {
+			this.insert_space_before_assignment_operators = JavaCore.INSERT.equals(insertSpaceBeforeAssignmentOperatorsOption);
+		}
+		final Object insertSpaceBeforeBinaryOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR);
+		if (insertSpaceBeforeBinaryOperatorOption != null) {
+			this.insert_space_before_binary_operator = JavaCore.INSERT.equals(insertSpaceBeforeBinaryOperatorOption);
+		}
+		final Object insertSpaceBeforeBlockOpenBraceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BLOCK_OPEN_BRACE);
+		if (insertSpaceBeforeBlockOpenBraceOption != null) {
+			this.insert_space_before_block_open_brace = JavaCore.INSERT.equals(insertSpaceBeforeBlockOpenBraceOption);
+		}
+		final Object insertSpaceBeforeBracketInArrayReferenceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BRACKET_IN_ARRAY_REFERENCE);
+		if (insertSpaceBeforeBracketInArrayReferenceOption != null) {
+			this.insert_space_before_bracket_in_array_reference = JavaCore.INSERT.equals(insertSpaceBeforeBracketInArrayReferenceOption);
+		}
+		final Object insertSpaceBeforeBracketInArrayTypeReferenceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BRACKET_IN_ARRAY_TYPE_REFERENCE);
+		if (insertSpaceBeforeBracketInArrayTypeReferenceOption != null) {
+			this.insert_space_before_bracket_in_array_type_reference = JavaCore.INSERT.equals(insertSpaceBeforeBracketInArrayTypeReferenceOption);
+		}
+		final Object insertSpaceBeforeCatchExpressionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CATCH_EXPRESSION);
+		if (insertSpaceBeforeCatchExpressionOption != null) {
+			this.insert_space_before_catch_expression = JavaCore.INSERT.equals(insertSpaceBeforeCatchExpressionOption);
+		}
+		final Object insertSpaceBeforeClosingBraceInArrayInitializerOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER);
+		if (insertSpaceBeforeClosingBraceInArrayInitializerOption != null) {
+			this.insert_space_before_closing_brace_in_array_initializer = JavaCore.INSERT.equals(insertSpaceBeforeClosingBraceInArrayInitializerOption);
+		}
+		final Object insertSpaceBeforeClosingParenOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN);
+		if (insertSpaceBeforeClosingParenOption != null) {
+			this.insert_space_before_closing_paren = JavaCore.INSERT.equals(insertSpaceBeforeClosingParenOption);
+		}
+		final Object insertSpaceBeforeClosingParenInCastOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CAST);
+		if (insertSpaceBeforeClosingParenInCastOption != null) {
+			this.insert_space_before_closing_paren_in_cast = JavaCore.INSERT.equals(insertSpaceBeforeClosingParenInCastOption);
+		}
+		final Object insertSpaceBeforeClosingParenInParenthesizedExpressionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_PARENTHESIZED_EXPRESSION);
+		if (insertSpaceBeforeClosingParenInParenthesizedExpressionOption != null) {
+			this.insert_space_before_closing_paren_in_parenthesized_expression = JavaCore.INSERT.equals(insertSpaceBeforeClosingParenInParenthesizedExpressionOption);
+		}
+		final Object insertSpaceBeforeColonInAssertOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_ASSERT);
+		if (insertSpaceBeforeColonInAssertOption != null) {
+			this.insert_space_before_colon_in_assert = JavaCore.INSERT.equals(insertSpaceBeforeColonInAssertOption);
+		}
+		final Object insertSpaceBeforeColonInCaseOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_CASE);
+		if (insertSpaceBeforeColonInCaseOption != null) {
+			this.insert_space_before_colon_in_case = JavaCore.INSERT.equals(insertSpaceBeforeColonInCaseOption);
+		}
+		final Object insertSpaceBeforeColonInConditionalOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_CONDITIONAL);
+		if (insertSpaceBeforeColonInConditionalOption != null) {
+			this.insert_space_before_colon_in_conditional = JavaCore.INSERT.equals(insertSpaceBeforeColonInConditionalOption);
+		}
+		final Object insertSpaceBeforeColonInDefaultOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_DEFAULT);
+		if (insertSpaceBeforeColonInDefaultOption != null) {
+			this.insert_space_before_colon_in_default = JavaCore.INSERT.equals(insertSpaceBeforeColonInDefaultOption);
+		}
+		final Object insertSpaceBeforeColonInLabeledStatementOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COLON_IN_LABELED_STATEMENT);
+		if (insertSpaceBeforeColonInLabeledStatementOption != null) {
+			this.insert_space_before_colon_in_labeled_statement = JavaCore.INSERT.equals(insertSpaceBeforeColonInLabeledStatementOption);
+		}
+		final Object insertSpaceBeforeCommaInAllocationExpressionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ALLOCATION_EXPRESSION);
+		if (insertSpaceBeforeCommaInAllocationExpressionOption != null) {
+			this.insert_space_before_comma_in_allocation_expression = JavaCore.INSERT.equals(insertSpaceBeforeCommaInAllocationExpressionOption);
+		}
+		final Object insertSpaceBeforeCommaInArrayInitializerOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_ARRAY_INITIALIZER);
+		if (insertSpaceBeforeCommaInArrayInitializerOption != null) {
+			this.insert_space_before_comma_in_array_initializer = JavaCore.INSERT.equals(insertSpaceBeforeCommaInArrayInitializerOption);
+		}
+		final Object insertSpaceBeforeCommaInConstructorArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_ARGUMENTS);
+		if (insertSpaceBeforeCommaInConstructorArgumentsOption != null) {
+			this.insert_space_before_comma_in_constructor_arguments = JavaCore.INSERT.equals(insertSpaceBeforeCommaInConstructorArgumentsOption);
+		}
+		final Object insertSpaceBeforeCommaInConstructorThrowsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_THROWS);
+		if (insertSpaceBeforeCommaInConstructorThrowsOption != null) {
+			this.insert_space_before_comma_in_constructor_throws = JavaCore.INSERT.equals(insertSpaceBeforeCommaInConstructorThrowsOption);
+		}
+		final Object insertSpaceBeforeCommaInExplicitconstructorcallArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_EXPLICITCONSTRUCTORCALL_ARGUMENTS);
+		if (insertSpaceBeforeCommaInExplicitconstructorcallArgumentsOption != null) {
+			this.insert_space_before_comma_in_explicitconstructorcall_arguments = JavaCore.INSERT.equals(insertSpaceBeforeCommaInExplicitconstructorcallArgumentsOption);
+		}
+		final Object insertSpaceBeforeCommaInForIncrementsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INCREMENTS);
+		if (insertSpaceBeforeCommaInForIncrementsOption != null) {
+			this.insert_space_before_comma_in_for_increments = JavaCore.INSERT.equals(insertSpaceBeforeCommaInForIncrementsOption);
+		}
+		final Object insertSpaceBeforeCommaInForInitsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INITS);
+		if (insertSpaceBeforeCommaInForInitsOption != null) {
+			this.insert_space_before_comma_in_for_inits = JavaCore.INSERT.equals(insertSpaceBeforeCommaInForInitsOption);
+		}
+		final Object insertSpaceBeforeCommaInMessagesendArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MESSAGESEND_ARGUMENTS);
+		if (insertSpaceBeforeCommaInMessagesendArgumentsOption != null) {
+			this.insert_space_before_comma_in_messagesend_arguments = JavaCore.INSERT.equals(insertSpaceBeforeCommaInMessagesendArgumentsOption);
+		}
+		final Object insertSpaceBeforeCommaInMethodArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_ARGUMENTS);
+		if (insertSpaceBeforeCommaInMethodArgumentsOption != null) {
+			this.insert_space_before_comma_in_method_arguments = JavaCore.INSERT.equals(insertSpaceBeforeCommaInMethodArgumentsOption);
+		}
+		final Object insertSpaceBeforeCommaInMethodThrowsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_THROWS);
+		if (insertSpaceBeforeCommaInMethodThrowsOption != null) {
+			this.insert_space_before_comma_in_method_throws = JavaCore.INSERT.equals(insertSpaceBeforeCommaInMethodThrowsOption);
+		}
+		final Object insertSpaceBeforeCommaInMultipleFieldDeclarationsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS);
+		if (insertSpaceBeforeCommaInMultipleFieldDeclarationsOption != null) {
+			this.insert_space_before_comma_in_multiple_field_declarations = JavaCore.INSERT.equals(insertSpaceBeforeCommaInMultipleFieldDeclarationsOption);
+		}
+		final Object insertSpaceBeforeCommaInMultipleLocalDeclarationsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS);
+		if (insertSpaceBeforeCommaInMultipleLocalDeclarationsOption != null) {
+			this.insert_space_before_comma_in_multiple_local_declarations = JavaCore.INSERT.equals(insertSpaceBeforeCommaInMultipleLocalDeclarationsOption);
+		}
+		final Object insertSpaceBeforeCommaInSuperinterfacesOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_COMMA_IN_SUPERINTERFACES);
+		if (insertSpaceBeforeCommaInSuperinterfacesOption != null) {
+			this.insert_space_before_comma_in_superinterfaces = JavaCore.INSERT.equals(insertSpaceBeforeCommaInSuperinterfacesOption);
+		}
+		final Object insertSpaceBeforeFirstArgumentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_FIRST_ARGUMENT);
+		if (insertSpaceBeforeFirstArgumentOption != null) {
+			this.insert_space_before_first_argument = JavaCore.INSERT.equals(insertSpaceBeforeFirstArgumentOption);
+		}
+		final Object insertSpaceBeforeFirstInitializerOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_FIRST_INITIALIZER);
+		if (insertSpaceBeforeFirstInitializerOption != null) {
+			this.insert_space_before_first_initializer = JavaCore.INSERT.equals(insertSpaceBeforeFirstInitializerOption);
+		}
+		final Object insertSpaceBeforeForParenOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_FOR_PAREN);
+		if (insertSpaceBeforeForParenOption != null) {
+			this.insert_space_before_for_paren = JavaCore.INSERT.equals(insertSpaceBeforeForParenOption);
+		}
+		final Object insertSpaceBeforeIfConditionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_IF_CONDITION);
+		if (insertSpaceBeforeIfConditionOption != null) {
+			this.insert_space_before_if_condition = JavaCore.INSERT.equals(insertSpaceBeforeIfConditionOption);
+		}
+		final Object insertSpaceBeforeMessageSendOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_MESSAGE_SEND);
+		if (insertSpaceBeforeMessageSendOption != null) {
+			this.insert_space_before_message_send = JavaCore.INSERT.equals(insertSpaceBeforeMessageSendOption);
+		}
+		final Object insertSpaceBeforeMethodDeclarationOpenParenOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_METHOD_DECLARATION_OPEN_PAREN);
+		if (insertSpaceBeforeMethodDeclarationOpenParenOption != null) {
+			this.insert_space_before_method_declaration_open_paren = JavaCore.INSERT.equals(insertSpaceBeforeMethodDeclarationOpenParenOption);
+		}
+		final Object insertSpaceBeforeMethodOpenBraceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_METHOD_OPEN_BRACE);
+		if (insertSpaceBeforeMethodOpenBraceOption != null) {
+			this.insert_space_before_method_open_brace = JavaCore.INSERT.equals(insertSpaceBeforeMethodOpenBraceOption);
+		}
+		final Object insertSpaceBeforeOpenParenInParenthesizedExpressionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPEN_PAREN_IN_PARENTHESIZED_EXPRESSION);
+		if (insertSpaceBeforeOpenParenInParenthesizedExpressionOption != null) {
+			this.insert_space_before_open_paren_in_parenthesized_expression = JavaCore.INSERT.equals(insertSpaceBeforeOpenParenInParenthesizedExpressionOption);
+		}
+		final Object insertSpaceBeforeOpeningBraceInArrayInitializerOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ARRAY_INITIALIZER);
+		if (insertSpaceBeforeOpeningBraceInArrayInitializerOption != null) {
+			this.insert_space_before_opening_brace_in_array_initializer = JavaCore.INSERT.equals(insertSpaceBeforeOpeningBraceInArrayInitializerOption);
+		}
+		final Object insertSpaceBeforePostfixOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_POSTFIX_OPERATOR);
+		if (insertSpaceBeforePostfixOperatorOption != null) {
+			this.insert_space_before_postfix_operator = JavaCore.INSERT.equals(insertSpaceBeforePostfixOperatorOption);
+		}
+		final Object insertSpaceBeforePrefixOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_PREFIX_OPERATOR);
+		if (insertSpaceBeforePrefixOperatorOption != null) {
+			this.insert_space_before_prefix_operator = JavaCore.INSERT.equals(insertSpaceBeforePrefixOperatorOption);
+		}
+		final Object insertSpaceBeforeQuestionInConditionalOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_QUESTION_IN_CONDITIONAL);
+		if (insertSpaceBeforeQuestionInConditionalOption != null) {
+			this.insert_space_before_question_in_conditional = JavaCore.INSERT.equals(insertSpaceBeforeQuestionInConditionalOption);
+		}
+		final Object insertSpaceBeforeSemicolonOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SEMICOLON);
+		if (insertSpaceBeforeSemicolonOption != null) {
+			this.insert_space_before_semicolon = JavaCore.INSERT.equals(insertSpaceBeforeSemicolonOption);
+		}
+		final Object insertSpaceBeforeSwitchConditionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SWITCH_CONDITION);
+		if (insertSpaceBeforeSwitchConditionOption != null) {
+			this.insert_space_before_switch_condition = JavaCore.INSERT.equals(insertSpaceBeforeSwitchConditionOption);
+		}
+		final Object insertSpaceBeforeSwitchOpenBraceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SWITCH_OPEN_BRACE);
+		if (insertSpaceBeforeSwitchOpenBraceOption != null) {
+			this.insert_space_before_switch_open_brace = JavaCore.INSERT.equals(insertSpaceBeforeSwitchOpenBraceOption);
+		}
+		final Object insertSpaceBeforeSynchronizedConditionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_SYNCHRONIZED_CONDITION);
+		if (insertSpaceBeforeSynchronizedConditionOption != null) {
+			this.insert_space_before_synchronized_condition = JavaCore.INSERT.equals(insertSpaceBeforeSynchronizedConditionOption);
+		}
+		final Object insertSpaceBeforeTypeOpenBraceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_TYPE_OPEN_BRACE);
+		if (insertSpaceBeforeTypeOpenBraceOption != null) {
+			this.insert_space_before_type_open_brace = JavaCore.INSERT.equals(insertSpaceBeforeTypeOpenBraceOption);
+		}
+		final Object insertSpaceBeforeUnaryOperatorOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_UNARY_OPERATOR);
+		if (insertSpaceBeforeUnaryOperatorOption != null) {
+			this.insert_space_before_unary_operator = JavaCore.INSERT.equals(insertSpaceBeforeUnaryOperatorOption);
+		}
+		final Object insertSpaceBeforeWhileConditionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_WHILE_CONDITION);
+		if (insertSpaceBeforeWhileConditionOption != null) {
+			this.insert_space_before_while_condition = JavaCore.INSERT.equals(insertSpaceBeforeWhileConditionOption);
+		}
+		final Object insertSpaceBetweenBracketsInArrayReferenceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_REFERENCE);
+		if (insertSpaceBetweenBracketsInArrayReferenceOption != null) {
+			this.insert_space_between_brackets_in_array_reference = JavaCore.INSERT.equals(insertSpaceBetweenBracketsInArrayReferenceOption);
+		}
+		final Object insertSpaceBetweenBracketsInArrayTypeReferenceOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_TYPE_REFERENCE);
+		if (insertSpaceBetweenBracketsInArrayTypeReferenceOption != null) {
+			this.insert_space_between_brackets_in_array_type_reference = JavaCore.INSERT.equals(insertSpaceBetweenBracketsInArrayTypeReferenceOption);
+		}
+		final Object insertSpaceBetweenEmptyArgumentsOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_ARGUMENTS);
+		if (insertSpaceBetweenEmptyArgumentsOption != null) {
+			this.insert_space_between_empty_arguments = JavaCore.INSERT.equals(insertSpaceBetweenEmptyArgumentsOption);
+		}
+		final Object insertSpaceBetweenEmptyArrayInitializerOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BETWEEN_EMPTY_ARRAY_INITIALIZER);
+		if (insertSpaceBetweenEmptyArrayInitializerOption != null) {
+			this.insert_space_between_empty_array_initializer = JavaCore.INSERT.equals(insertSpaceBetweenEmptyArrayInitializerOption);
+		}
+		final Object insertSpaceInCatchExpressionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_CATCH_EXPRESSION);
+		if (insertSpaceInCatchExpressionOption != null) {
+			this.insert_space_in_catch_expression = JavaCore.INSERT.equals(insertSpaceInCatchExpressionOption);
+		}
+		final Object insertSpaceInForParensOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_FOR_PARENS);
+		if (insertSpaceInForParensOption != null) {
+			this.insert_space_in_for_parens = JavaCore.INSERT.equals(insertSpaceInForParensOption);
+		}
+		final Object insertSpaceInIfConditionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_IF_CONDITION);
+		if (insertSpaceInIfConditionOption != null) {
+			this.insert_space_in_if_condition = JavaCore.INSERT.equals(insertSpaceInIfConditionOption);
+		}
+		final Object insertSpaceInSwitchConditionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_SWITCH_CONDITION);
+		if (insertSpaceInSwitchConditionOption != null) {
+			this.insert_space_in_switch_condition = JavaCore.INSERT.equals(insertSpaceInSwitchConditionOption);
+		}
+		final Object insertSpaceInSynchronizedConditionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_SYNCHRONIZED_CONDITION);
+		if (insertSpaceInSynchronizedConditionOption != null) {
+			this.insert_space_in_synchronized_condition = JavaCore.INSERT.equals(insertSpaceInSynchronizedConditionOption);
+		}
+		final Object insertSpaceInWhileConditionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_IN_WHILE_CONDITION);
+		if (insertSpaceInWhileConditionOption != null) {
+			this.insert_space_in_while_condition = JavaCore.INSERT.equals(insertSpaceInWhileConditionOption);
+		}
+		final Object insertSpaceWithinMessageSendOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_WITHIN_MESSAGE_SEND);
+		if (insertSpaceWithinMessageSendOption != null) {
+			this.insert_space_within_message_send = JavaCore.INSERT.equals(insertSpaceWithinMessageSendOption);
+		}
+		final Object keepElseStatementOnSameLineOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_ELSE_STATEMENT_ON_SAME_LINE);
+		if (keepElseStatementOnSameLineOption != null) {
+			this.keep_else_statement_on_same_line = DefaultCodeFormatterConstants.TRUE.equals(keepElseStatementOnSameLineOption);
+		}
+		final Object keepSimpleIfOnOneLineOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_SIMPLE_IF_ON_ONE_LINE);
+		if (keepSimpleIfOnOneLineOption != null) {
+			this.keep_simple_if_on_one_line = DefaultCodeFormatterConstants.TRUE.equals(keepSimpleIfOnOneLineOption);
+		}
+		final Object keepThenStatementOnSameLineOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_KEEP_THEN_STATEMENT_ON_SAME_LINE);
+		if (keepThenStatementOnSameLineOption != null) {
+			this.keep_then_statement_on_same_line = DefaultCodeFormatterConstants.TRUE.equals(keepThenStatementOnSameLineOption);
+		}
+		final Object messageSendArgumentsAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_MESSAGE_SEND_ARGUMENTS_ALIGNMENT);
+		if (messageSendArgumentsAlignmentOption != null) {
+			this.message_send_arguments_alignment = Integer.parseInt((String) messageSendArgumentsAlignmentOption);
+		}
+		final Object messageSendSelectorAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_MESSAGE_SEND_SELECTOR_ALIGNMENT);
+		if (messageSendSelectorAlignmentOption != null) {
+			this.message_send_selector_alignment = Integer.parseInt((String) messageSendSelectorAlignmentOption);
+		}
+		final Object methodDeclarationArgumentsAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_METHOD_DECLARATION_ARGUMENTS_ALIGNMENT);
+		if (methodDeclarationArgumentsAlignmentOption != null) {
+			this.method_declaration_arguments_alignment = Integer.parseInt((String) methodDeclarationArgumentsAlignmentOption);
+		}
+		final Object methodDeclarationBracePositionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_METHOD_DECLARATION_BRACE_POSITION);
+		if (methodDeclarationBracePositionOption != null) {
+			this.method_declaration_brace_position = (String) methodDeclarationBracePositionOption;
+		}
+		final Object methodThrowsClauseAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_METHOD_THROWS_CLAUSE_ALIGNMENT);
+		if (methodThrowsClauseAlignmentOption != null) {
+			this.method_throws_clause_alignment = Integer.parseInt((String) methodThrowsClauseAlignmentOption);
+		}
+		final Object multipleFieldsAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_MULTIPLE_FIELDS_ALIGNMENT);
+		if (multipleFieldsAlignmentOption != null) {
+			this.multiple_fields_alignment = Integer.parseInt((String) multipleFieldsAlignmentOption);
+		}
+		final Object numberOfBlankLinesToInsertAtBeginningOfMethodBodyOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_NUMBER_OF_BLANK_LINES_TO_INSERT_AT_BEGINNING_OF_METHOD_BODY);
+		if (numberOfBlankLinesToInsertAtBeginningOfMethodBodyOption != null) {
+			this.number_of_blank_lines_to_insert_at_beginning_of_method_body = Integer.parseInt((String) numberOfBlankLinesToInsertAtBeginningOfMethodBodyOption);
+		}
+		final Object numberOfEmptyLinesToPreserveOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_NUMBER_OF_EMPTY_LINES_TO_PRESERVE);
+		if (numberOfEmptyLinesToPreserveOption != null) {
+			this.number_of_empty_lines_to_preserve = Integer.parseInt((String) numberOfEmptyLinesToPreserveOption);
+		}
+		final Object pageWidthOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_LINE_SPLIT);
+		if (pageWidthOption != null) {
+			this.page_width = Integer.parseInt((String) pageWidthOption);
+		}
+		final Object preserveUserLinebreaksOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_PRESERVE_USER_LINEBREAKS);
+		if (preserveUserLinebreaksOption != null) {
+			this.preserve_user_linebreaks = DefaultCodeFormatterConstants.TRUE.equals(preserveUserLinebreaksOption);
+		}
+		final Object putEmptyStatementOnNewLineOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_PUT_EMPTY_STATEMENT_ON_NEW_LINE);
+		if (putEmptyStatementOnNewLineOption != null) {
+			this.put_empty_statement_on_new_line = DefaultCodeFormatterConstants.TRUE.equals(putEmptyStatementOnNewLineOption);
+		}
+		final Object qualifiedAllocationExpressionArgumentsAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_QUALIFIED_ALLOCATION_EXPRESSION_ARGUMENTS_ALIGNMENT);
+		if (qualifiedAllocationExpressionArgumentsAlignmentOption != null) {
+			this.qualified_allocation_expression_arguments_alignment = Integer.parseInt((String) qualifiedAllocationExpressionArgumentsAlignmentOption);
+		}
+		final Object switchBracePositionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_SWITCH_BRACE_POSITION);
+		if (switchBracePositionOption != null) {
+			this.switch_brace_position = (String) switchBracePositionOption;
+		}
+		final Object tabSizeOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE);
+		if (tabSizeOption != null) {
+			this.tab_size = Integer.parseInt((String) tabSizeOption);
+		}
+		final Object typeDeclarationBracePositionOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_TYPE_DECLARATION_BRACE_POSITION);
+		if (typeDeclarationBracePositionOption != null) {
+			this.type_declaration_brace_position = (String) typeDeclarationBracePositionOption;
+		}
+		final Object typeDeclarationSuperclassAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_TYPE_DECLARATION_SUPERCLASS_ALIGNMENT);
+		if (typeDeclarationSuperclassAlignmentOption != null) {
+			this.type_declaration_superclass_alignment = Integer.parseInt((String) typeDeclarationSuperclassAlignmentOption);
+		}
+		final Object typeDeclarationSuperinterfacesAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_TYPE_DECLARATION_SUPERINTERFACES_ALIGNMENT);
+		if (typeDeclarationSuperinterfacesAlignmentOption != null) {
+			this.type_declaration_superinterfaces_alignment = Integer.parseInt((String) typeDeclarationSuperinterfacesAlignmentOption);
+		}
+		final Object typeMemberAlignmentOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_TYPE_MEMBER_ALIGNMENT);
+		if (typeMemberAlignmentOption != null) {
+			this.type_member_alignment = Integer.parseInt((String) typeMemberAlignmentOption);
+		}
+		final Object useTabOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR);
+		if (useTabOption != null) {
+			this.use_tab = JavaCore.TAB.equals(useTabOption);
+		}
+	}
+
+	
+	public void setDefaultSettings() {
+		this.allocation_expression_arguments_alignment = DEFAULT_ALLOCATION_EXPRESSION_ARGUMENTS_ALIGNMENT;
+		this.anonymous_type_declaration_brace_position = DEFAULT_ANONYMOUS_TYPE_DECLARATION_BRACE_POSITION;
+		this.array_initializer_brace_position = DEFAULT_ARRAY_INITIALIZER_BRACE_POSITION;
+		this.array_initializer_continuation_indentation = DEFAULT_ARRAY_INITIALIZER_CONTINUATION_INDENTATION;
+		this.array_initializer_expressions_alignment = DEFAULT_ARRAY_INITIALIZER_EXPRESSIONS_ALIGNMENT;
+		this.binary_expression_alignment = DEFAULT_BINARY_EXPRESSION_ALIGNMENT;
+		this.blank_lines_after_imports = DEFAULT_BLANK_LINES_AFTER_IMPORTS;
+		this.blank_lines_after_package = DEFAULT_BLANK_LINES_AFTER_PACKAGE;
+		this.blank_lines_before_field = DEFAULT_BLANK_LINES_BEFORE_FIELD;
+		this.blank_lines_before_first_class_body_declaration = DEFAULT_BLANK_LINES_BEFORE_FIRST_CLASS_BODY_DECLARATION;
+		this.blank_lines_before_imports = DEFAULT_BLANK_LINES_BEFORE_IMPORTS;
+		this.blank_lines_before_member_type = DEFAULT_BLANK_LINES_BEFORE_MEMBER_TYPE;
+		this.blank_lines_before_method = DEFAULT_BLANK_LINES_BEFORE_METHOD;
+		this.blank_lines_before_new_chunk = DEFAULT_BLANK_LINES_BEFORE_NEW_CHUNK;
+		this.blank_lines_before_package = DEFAULT_BLANK_LINES_BEFORE_PACKAGE;
+		this.block_brace_position = DEFAULT_BLOCK_BRACE_POSITION;
+		this.compact_else_if = DEFAULT_COMPACT_ELSE_IF;
+		this.compact_if_alignment = DEFAULT_COMPACT_IF_ALIGNMENT;
+		this.conditional_expression_alignment = DEFAULT_CONDITIONAL_EXPRESSION_ALIGNMENT;
+		this.continuation_indentation = DEFAULT_CONTINUATION_INDENTATION;
+		this.explicit_constructor_arguments_alignment = DEFAULT_EXPLICIT_CONSTRUCTOR_ARGUMENTS_ALIGNMENT;
+		this.filling_space = DEFAULT_FILLING_SPACE;
+		this.format_guardian_clause_on_one_line = DEFAULT_FORMAT_GUARDIAN_CLAUSE_ON_ONE_LINE;
+		this.indent_block_statements = DEFAULT_INDENT_BLOCK_STATEMENTS;
+		this.indent_body_declarations_compare_to_type_header = DEFAULT_INDENT_BODY_DECLARATIONS_COMPARE_TO_TYPE_HEADER;
+		this.indent_breaks_compare_to_cases = DEFAULT_INDENT_BREAKS_COMPARE_TO_CASES;
+		this.indent_switchstatements_compare_to_cases = DEFAULT_INDENT_SWITCHSTATEMENTS_COMPARE_TO_CASES;
+		this.indent_switchstatements_compare_to_switch = DEFAULT_INDENT_SWITCHSTATEMENTS_COMPARE_TO_SWITCH;
+		this.insert_new_line_after_opening_brace_in_array_initializer = DEFAULT_INSERT_NEW_LINE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER;
+		this.insert_new_line_before_closing_brace_in_array_initializer = DEFAULT_INSERT_NEW_LINE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER;
+		this.insert_new_line_in_control_statements = DEFAULT_INSERT_NEW_LINE_IN_CONTROL_STATEMENTS;
+		this.insert_new_line_in_empty_anonymous_type_declaration = DEFAULT_INSERT_NEW_LINE_IN_EMPTY_ANONYMOUS_TYPE_DECLARATION;
+		this.insert_new_line_in_empty_block = DEFAULT_INSERT_NEW_LINE_IN_EMPTY_BLOCK;
+		this.insert_new_line_in_empty_method_body = DEFAULT_INSERT_NEW_LINE_IN_EMPTY_METHOD_BODY;
+		this.insert_new_line_in_empty_type_declaration = DEFAULT_INSERT_NEW_LINE_IN_EMPTY_TYPE_DECLARATION;
+		this.insert_space_after_assignment_operators = DEFAULT_INSERT_SPACE_AFTER_ASSIGNMENT_OPERATORS;
+		this.insert_space_after_binary_operator = DEFAULT_INSERT_SPACE_AFTER_BINARY_OPERATOR;
+		this.insert_space_after_block_close_brace = DEFAULT_INSERT_SPACE_AFTER_BLOCK_CLOSE_BRACE;
+		this.insert_space_after_closing_paren_in_cast = DEFAULT_INSERT_SPACE_AFTER_CLOSING_PAREN_IN_CAST;
+		this.insert_space_after_colon_in_assert = DEFAULT_INSERT_SPACE_AFTER_COLON_IN_ASSERT;
+		this.insert_space_after_colon_in_conditional = DEFAULT_INSERT_SPACE_AFTER_COLON_IN_CONDITIONAL;
+		this.insert_space_after_colon_in_labeled_statement = DEFAULT_INSERT_SPACE_AFTER_COLON_IN_LABELED_STATEMENT;
+		this.insert_space_after_comma_in_allocation_expression = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_ALLOCATION_EXPRESSION;
+		this.insert_space_after_comma_in_array_initializer = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_ARRAY_INITIALIZER;
+		this.insert_space_after_comma_in_constructor_arguments = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_ARGUMENTS;
+		this.insert_space_after_comma_in_constructor_throws = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_CONSTRUCTOR_THROWS;
+		this.insert_space_after_comma_in_explicitconstructorcall_arguments = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_EXPLICITCONSTRUCTORCALL_ARGUMENTS;
+		this.insert_space_after_comma_in_for_increments = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_FOR_INCREMENTS;
+		this.insert_space_after_comma_in_for_inits = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_FOR_INITS;
+		this.insert_space_after_comma_in_messagesend_arguments = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_MESSAGESEND_ARGUMENTS;
+		this.insert_space_after_comma_in_method_arguments = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_METHOD_ARGUMENTS;
+		this.insert_space_after_comma_in_method_throws = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_METHOD_THROWS;
+		this.insert_space_after_comma_in_multiple_field_declarations = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS;
+		this.insert_space_after_comma_in_multiple_local_declarations = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS;
+		this.insert_space_after_comma_in_superinterfaces = DEFAULT_INSERT_SPACE_AFTER_COMMA_IN_SUPERINTERFACES;
+		this.insert_space_after_open_paren_in_parenthesized_expression = DEFAULT_INSERT_SPACE_AFTER_OPEN_PAREN_IN_PARENTHESIZED_EXPRESSION;
+		this.insert_space_after_opening_paren_in_cast = DEFAULT_INSERT_SPACE_AFTER_OPENING_PAREN_IN_CAST;
+		this.insert_space_after_postfix_operator = DEFAULT_INSERT_SPACE_AFTER_POSTFIX_OPERATOR;
+		this.insert_space_after_prefix_operator = DEFAULT_INSERT_SPACE_AFTER_PREFIX_OPERATOR;
+		this.insert_space_after_question_in_conditional = DEFAULT_INSERT_SPACE_AFTER_QUESTION_IN_CONDITIONAL;
+		this.insert_space_after_semicolon_in_for = DEFAULT_INSERT_SPACE_AFTER_SEMICOLON_IN_FOR;
+		this.insert_space_after_unary_operator = DEFAULT_INSERT_SPACE_AFTER_UNARY_OPERATOR;
+		this.insert_space_before_anonymous_type_open_brace = DEFAULT_INSERT_SPACE_BEFORE_ANONYMOUS_TYPE_OPEN_BRACE;
+		this.insert_space_before_assignment_operators = DEFAULT_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATORS;
+		this.insert_space_before_binary_operator = DEFAULT_INSERT_SPACE_BEFORE_BINARY_OPERATOR;
+		this.insert_space_before_block_open_brace = DEFAULT_INSERT_SPACE_BEFORE_BLOCK_OPEN_BRACE;
+		this.insert_space_before_bracket_in_array_reference = DEFAULT_INSERT_SPACE_BEFORE_BRACKET_IN_ARRAY_REFERENCE;
+		this.insert_space_before_bracket_in_array_type_reference = DEFAULT_INSERT_SPACE_BEFORE_BRACKET_IN_ARRAY_TYPE_REFERENCE;
+		this.insert_space_before_catch_expression = DEFAULT_INSERT_SPACE_BEFORE_CATCH_EXPRESSION;
+		this.insert_space_before_closing_brace_in_array_initializer = DEFAULT_INSERT_SPACE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER;
+		this.insert_space_before_closing_paren = DEFAULT_INSERT_SPACE_BEFORE_CLOSING_PAREN;
+		this.insert_space_before_closing_paren_in_cast = DEFAULT_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_CAST;
+		this.insert_space_before_closing_paren_in_parenthesized_expression = DEFAULT_INSERT_SPACE_BEFORE_CLOSING_PAREN_IN_PARENTHESIZED_EXPRESSION;
+		this.insert_space_before_colon_in_assert = DEFAULT_INSERT_SPACE_BEFORE_COLON_IN_ASSERT;
+		this.insert_space_before_colon_in_case = DEFAULT_INSERT_SPACE_BEFORE_COLON_IN_CASE;
+		this.insert_space_before_colon_in_conditional = DEFAULT_INSERT_SPACE_BEFORE_COLON_IN_CONDITIONAL;
+		this.insert_space_before_colon_in_default = DEFAULT_INSERT_SPACE_BEFORE_COLON_IN_DEFAULT;
+		this.insert_space_before_colon_in_labeled_statement = DEFAULT_INSERT_SPACE_BEFORE_COLON_IN_LABELED_STATEMENT;
+		this.insert_space_before_comma_in_allocation_expression = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_ALLOCATION_EXPRESSION;
+		this.insert_space_before_comma_in_array_initializer = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_ARRAY_INITIALIZER;
+		this.insert_space_before_comma_in_constructor_arguments = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_ARGUMENTS;
+		this.insert_space_before_comma_in_constructor_throws = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_CONSTRUCTOR_THROWS;
+		this.insert_space_before_comma_in_explicitconstructorcall_arguments = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_EXPLICITCONSTRUCTORCALL_ARGUMENTS;
+		this.insert_space_before_comma_in_for_increments = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INCREMENTS;
+		this.insert_space_before_comma_in_for_inits = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_FOR_INITS;
+		this.insert_space_before_comma_in_messagesend_arguments = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_MESSAGESEND_ARGUMENTS;
+		this.insert_space_before_comma_in_method_arguments = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_ARGUMENTS;
+		this.insert_space_before_comma_in_method_throws = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_METHOD_THROWS;
+		this.insert_space_before_comma_in_multiple_field_declarations = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_FIELD_DECLARATIONS;
+		this.insert_space_before_comma_in_multiple_local_declarations = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_MULTIPLE_LOCAL_DECLARATIONS;
+		this.insert_space_before_comma_in_superinterfaces = DEFAULT_INSERT_SPACE_BEFORE_COMMA_IN_SUPERINTERFACES;
+		this.insert_space_before_first_argument = DEFAULT_INSERT_SPACE_BEFORE_FIRST_ARGUMENT;
+		this.insert_space_before_first_initializer = DEFAULT_INSERT_SPACE_BEFORE_FIRST_INITIALIZER;
+		this.insert_space_before_for_paren = DEFAULT_INSERT_SPACE_BEFORE_FOR_PAREN;
+		this.insert_space_before_if_condition = DEFAULT_INSERT_SPACE_BEFORE_IF_CONDITION;
+		this.insert_space_before_message_send = DEFAULT_INSERT_SPACE_BEFORE_MESSAGE_SEND;
+		this.insert_space_before_method_declaration_open_paren = DEFAULT_INSERT_SPACE_BEFORE_METHOD_DECLARATION_OPEN_PAREN;
+		this.insert_space_before_method_open_brace = DEFAULT_INSERT_SPACE_BEFORE_METHOD_OPEN_BRACE;
+		this.insert_space_before_open_paren_in_parenthesized_expression = DEFAULT_INSERT_SPACE_BEFORE_OPEN_PAREN_IN_PARENTHESIZED_EXPRESSION;
+		this.insert_space_before_opening_brace_in_array_initializer = DEFAULT_INSERT_SPACE_BEFORE_OPENING_BRACE_IN_ARRAY_INITIALIZER;
+		this.insert_space_before_postfix_operator = DEFAULT_INSERT_SPACE_BEFORE_POSTFIX_OPERATOR;
+		this.insert_space_before_prefix_operator = DEFAULT_INSERT_SPACE_BEFORE_PREFIX_OPERATOR;
+		this.insert_space_before_question_in_conditional = DEFAULT_INSERT_SPACE_BEFORE_QUESTION_IN_CONDITIONAL;
+		this.insert_space_before_semicolon = DEFAULT_INSERT_SPACE_BEFORE_SEMICOLON;
+		this.insert_space_before_switch_condition = DEFAULT_INSERT_SPACE_BEFORE_SWITCH_CONDITION;
+		this.insert_space_before_switch_open_brace = DEFAULT_INSERT_SPACE_BEFORE_SWITCH_OPEN_BRACE;
+		this.insert_space_before_synchronized_condition = DEFAULT_INSERT_SPACE_BEFORE_SYNCHRONIZED_CONDITION;
+		this.insert_space_before_type_open_brace = DEFAULT_INSERT_SPACE_BEFORE_TYPE_OPEN_BRACE;
+		this.insert_space_before_unary_operator = DEFAULT_INSERT_SPACE_BEFORE_UNARY_OPERATOR;
+		this.insert_space_before_while_condition = DEFAULT_INSERT_SPACE_BEFORE_WHILE_CONDITION;
+		this.insert_space_between_brackets_in_array_reference = DEFAULT_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_REFERENCE;
+		this.insert_space_between_brackets_in_array_type_reference = DEFAULT_INSERT_SPACE_BETWEEN_BRACKETS_IN_ARRAY_TYPE_REFERENCE;
+		this.insert_space_between_empty_arguments = DEFAULT_INSERT_SPACE_BETWEEN_EMPTY_ARGUMENTS;
+		this.insert_space_between_empty_array_initializer = DEFAULT_INSERT_SPACE_BETWEEN_EMPTY_ARRAY_INITIALIZER;
+		this.insert_space_in_catch_expression = DEFAULT_INSERT_SPACE_IN_CATCH_EXPRESSION;
+		this.insert_space_in_for_parens = DEFAULT_INSERT_SPACE_IN_FOR_PARENS;
+		this.insert_space_in_if_condition = DEFAULT_INSERT_SPACE_IN_IF_CONDITION;
+		this.insert_space_in_switch_condition = DEFAULT_INSERT_SPACE_IN_SWITCH_CONDITION;
+		this.insert_space_in_synchronized_condition = DEFAULT_INSERT_SPACE_IN_SYNCHRONIZED_CONDITION;
+		this.insert_space_in_while_condition = DEFAULT_INSERT_SPACE_IN_WHILE_CONDITION;
+		this.insert_space_within_message_send = DEFAULT_INSERT_SPACE_WITHIN_MESSAGE_SEND;
+		this.keep_else_statement_on_same_line = DEFAULT_KEEP_ELSE_STATEMENT_ON_SAME_LINE;
+		this.keep_simple_if_on_one_line = DEFAULT_KEEP_SIMPLE_IF_ON_ONE_LINE;
+		this.keep_then_statement_on_same_line = DEFAULT_KEEP_THEN_STATEMENT_ON_SAME_LINE;
+		this.message_send_arguments_alignment = DEFAULT_MESSAGE_SEND_ARGUMENTS_ALIGNMENT;
+		this.message_send_selector_alignment = DEFAULT_MESSAGE_SEND_SELECTOR_ALIGNMENT;
+		this.method_declaration_arguments_alignment = DEFAULT_METHOD_DECLARATION_ARGUMENTS_ALIGNMENT;
+		this.method_declaration_brace_position = DEFAULT_METHOD_DECLARATION_BRACE_POSITION;
+		this.method_throws_clause_alignment = DEFAULT_METHOD_THROWS_CLAUSE_ALIGNMENT;
+		this.multiple_fields_alignment = DEFAULT_MULTIPLE_FIELDS_ALIGNMENT;
+		this.number_of_blank_lines_to_insert_at_beginning_of_method_body = DEFAULT_NUMBER_OF_BLANK_LINES_TO_INSERT_AT_BEGINNING_OF_METHOD_BODY;
+		this.number_of_empty_lines_to_preserve = DEFAULT_NUMBER_OF_EMPTY_LINES_TO_PRESERVE;
+		this.page_width = DEFAULT_PAGE_WIDTH;
+		this.preserve_user_linebreaks = DEFAULT_PRESERVE_USER_LINEBREAKS;
+		this.put_empty_statement_on_new_line = DEFAULT_PUT_EMPTY_STATEMENT_ON_NEW_LINE;
+		this.qualified_allocation_expression_arguments_alignment = DEFAULT_QUALIFIED_ALLOCATION_EXPRESSION_ARGUMENTS_ALIGNMENT;
+		this.switch_brace_position = DEFAULT_SWITCH_BRACE_POSITION;
+		this.tab_size = DEFAULT_TAB_SIZE;
+		this.type_declaration_brace_position = DEFAULT_TYPE_DECLARATION_BRACE_POSITION;
+		this.type_declaration_superclass_alignment = DEFAULT_TYPE_DECLARATION_SUPERCLASS_ALIGNMENT;
+		this.type_declaration_superinterfaces_alignment = DEFAULT_TYPE_DECLARATION_SUPERINTERFACES_ALIGNMENT;
+		this.type_member_alignment = DEFAULT_TYPE_MEMBER_ALIGNMENT;
+		this.use_tab = DEFAULT_USE_TAB;
+	}
+	public void setJavaConventionsSettings() {
+		this.allocation_expression_arguments_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.anonymous_type_declaration_brace_position = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.array_initializer_brace_position = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.array_initializer_continuation_indentation = 2;
+		this.array_initializer_expressions_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.binary_expression_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.blank_lines_after_imports = 1;
+		this.blank_lines_after_package = 1;
+		this.blank_lines_before_field = 1;
+		this.blank_lines_before_first_class_body_declaration = 0;
+		this.blank_lines_before_imports= 1;
+		this.blank_lines_before_member_type = 1;
+		this.blank_lines_before_method = 1;
+		this.blank_lines_before_new_chunk = 1;
+		this.blank_lines_before_package = 0;
+		this.block_brace_position = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.compact_else_if = true;
+		this.compact_if_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.conditional_expression_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_NEXT_PER_LINE_SPLIT);
+		this.continuation_indentation = 2;
+		this.explicit_constructor_arguments_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.filling_space = ' ';
+		this.format_guardian_clause_on_one_line = true;
+		this.indent_block_statements = true;
+		this.indent_body_declarations_compare_to_type_header = true;
+		this.indent_breaks_compare_to_cases = true;
+		this.indent_switchstatements_compare_to_cases = true;
+		this.indent_switchstatements_compare_to_switch = false;
+		this.insert_new_line_after_opening_brace_in_array_initializer = false;
+		this.insert_new_line_before_closing_brace_in_array_initializer = false;
+		this.insert_new_line_in_control_statements = false;
+		this.insert_new_line_in_empty_anonymous_type_declaration = true;
+		this.insert_new_line_in_empty_block = true;
+		this.insert_new_line_in_empty_method_body = true;
+		this.insert_new_line_in_empty_type_declaration = true;
+		this.insert_space_after_assignment_operators = true;
+		this.insert_space_after_binary_operator = true;
+		this.insert_space_after_block_close_brace = true;
+		this.insert_space_after_closing_paren_in_cast = true;
+		this.insert_space_after_colon_in_assert = true;
+		this.insert_space_after_colon_in_conditional = true;
+		this.insert_space_after_colon_in_labeled_statement = true;
+		this.insert_space_after_comma_in_allocation_expression = true;
+		this.insert_space_after_comma_in_array_initializer = true;
+		this.insert_space_after_comma_in_constructor_arguments = true;
+		this.insert_space_after_comma_in_constructor_throws = true;
+		this.insert_space_after_comma_in_explicitconstructorcall_arguments = true;
+		this.insert_space_after_comma_in_for_increments = true;
+		this.insert_space_after_comma_in_for_inits = true;
+		this.insert_space_after_comma_in_messagesend_arguments = true;
+		this.insert_space_after_comma_in_method_arguments = true;
+		this.insert_space_after_comma_in_method_throws = true;
+		this.insert_space_after_comma_in_multiple_field_declarations = true;
+		this.insert_space_after_comma_in_multiple_local_declarations = true;
+		this.insert_space_after_comma_in_superinterfaces = true;
+		this.insert_space_after_open_paren_in_parenthesized_expression = false;
+		this.insert_space_after_opening_paren_in_cast = false;
+		this.insert_space_after_postfix_operator = false;
+		this.insert_space_after_prefix_operator = false;
+		this.insert_space_after_question_in_conditional = true;
+		this.insert_space_after_semicolon_in_for = true;
+		this.insert_space_after_unary_operator = false;
+		this.insert_space_before_anonymous_type_open_brace = true;
+		this.insert_space_before_assignment_operators = true;
+		this.insert_space_before_binary_operator = true;
+		this.insert_space_before_block_open_brace = true;
+		this.insert_space_before_bracket_in_array_reference = false;
+		this.insert_space_before_bracket_in_array_type_reference = false;
+		this.insert_space_before_catch_expression = true;
+		this.insert_space_before_closing_brace_in_array_initializer = false;
+		this.insert_space_before_closing_paren = false;
+		this.insert_space_before_closing_paren_in_cast = false;
+		this.insert_space_before_closing_paren_in_parenthesized_expression = false;
+		this.insert_space_before_colon_in_assert = true;
+		this.insert_space_before_colon_in_case = false;
+		this.insert_space_before_colon_in_conditional = true;
+		this.insert_space_before_colon_in_default = false;
+		this.insert_space_before_colon_in_labeled_statement = false;
+		this.insert_space_before_comma_in_allocation_expression = false;
+		this.insert_space_before_comma_in_array_initializer = false;
+		this.insert_space_before_comma_in_constructor_arguments = false;
+		this.insert_space_before_comma_in_constructor_throws = false;
+		this.insert_space_before_comma_in_explicitconstructorcall_arguments = false;
+		this.insert_space_before_comma_in_for_increments = false;
+		this.insert_space_before_comma_in_for_inits = false;
+		this.insert_space_before_comma_in_messagesend_arguments = false;
+		this.insert_space_before_comma_in_method_arguments = false;
+		this.insert_space_before_comma_in_method_throws = false;
+		this.insert_space_before_comma_in_multiple_field_declarations = false;
+		this.insert_space_before_comma_in_multiple_local_declarations = false;
+		this.insert_space_before_comma_in_superinterfaces = false;
+		this.insert_space_before_first_argument = false;
+		this.insert_space_before_first_initializer = false;
+		this.insert_space_before_for_paren = true;
+		this.insert_space_before_if_condition = true;
+		this.insert_space_before_message_send = false;
+		this.insert_space_before_method_declaration_open_paren = false;
+		this.insert_space_before_method_open_brace = true;
+		this.insert_space_before_open_paren_in_parenthesized_expression = false;
+		this.insert_space_before_opening_brace_in_array_initializer = false;
+		this.insert_space_before_postfix_operator = false;
+		this.insert_space_before_prefix_operator = false;
+		this.insert_space_before_question_in_conditional = true;
+		this.insert_space_before_semicolon = false;
+		this.insert_space_before_switch_condition = true;
+		this.insert_space_before_switch_open_brace = true;
+		this.insert_space_before_synchronized_condition = true;
+		this.insert_space_before_type_open_brace = true;
+		this.insert_space_before_unary_operator = false;
+		this.insert_space_before_while_condition = true;
+		this.insert_space_between_brackets_in_array_reference = false;
+		this.insert_space_between_brackets_in_array_type_reference = false;
+		this.insert_space_between_empty_arguments = false;
+		this.insert_space_between_empty_array_initializer = false;
+		this.insert_space_in_catch_expression = false;
+		this.insert_space_in_for_parens = false;
+		this.insert_space_in_if_condition = false;
+		this.insert_space_in_switch_condition = false;
+		this.insert_space_in_synchronized_condition = false;
+		this.insert_space_in_while_condition = false;
+		this.insert_space_within_message_send = false;
+		this.keep_else_statement_on_same_line = false;
+		this.keep_simple_if_on_one_line = true;
+		this.keep_then_statement_on_same_line = true;
+		this.message_send_arguments_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.message_send_selector_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.method_declaration_arguments_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.method_declaration_brace_position = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.method_throws_clause_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.multiple_fields_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.number_of_blank_lines_to_insert_at_beginning_of_method_body = 0;
+		this.number_of_empty_lines_to_preserve = 1;
+		this.page_width = 80;
+		this.preserve_user_linebreaks = false;
+		this.put_empty_statement_on_new_line = true;
+		this.qualified_allocation_expression_arguments_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.switch_brace_position = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.tab_size = 4;
+		this.type_declaration_brace_position = DefaultCodeFormatterConstants.END_OF_LINE;
+		this.type_declaration_superclass_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.type_declaration_superinterfaces_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_COMPACT_SPLIT);
+		this.type_member_alignment = Integer.parseInt(DefaultCodeFormatterConstants.FORMATTER_NO_ALIGNMENT);
+		this.use_tab = false;
+	}
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Location.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Location.java
new file mode 100644
index 0000000..67dc56a
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Location.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2003 International Business Machines 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 API and implementation
+ ******************************************************************************/
+package org.eclipse.jdt.internal.formatter;
+
+/**
+ * A location maintains positional information both in original source and in the output source.
+ * It remembers source offsets, line/column and indentation level.
+ * @since 2.1
+ */
+public class Location {
+
+	public int inputOffset;
+	public int outputLine;
+	public int outputColumn;
+	public int outputIndentationLevel;
+	public boolean needSpace;
+
+	// chunk management
+	public int lastNumberOfNewLines;	
+	
+	// edits management
+	int editsIndex;
+	OptimizedReplaceEdit textEdit;
+	
+	public Location(Scribe scribe, int sourceRestart){
+		update(scribe, sourceRestart);
+	}
+	
+	public void update(Scribe scribe, int sourceRestart){
+		this.outputColumn = scribe.column;
+		this.outputLine = scribe.line;
+		this.inputOffset = sourceRestart;
+		this.outputIndentationLevel = scribe.indentationLevel;
+		this.lastNumberOfNewLines = scribe.lastNumberOfNewLines;
+		this.needSpace = scribe.needSpace;
+		this.editsIndex = scribe.editsIndex;
+		textEdit = scribe.getLastEdit();
+	}
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/OptimizedReplaceEdit.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/OptimizedReplaceEdit.java
new file mode 100644
index 0000000..fc18a14
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/OptimizedReplaceEdit.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2003 International Business Machines 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 API and implementation
+ ******************************************************************************/
+package org.eclipse.jdt.internal.formatter;
+
+class OptimizedReplaceEdit {
+	
+	int offset;
+	int length;
+	String replacement;
+	
+	OptimizedReplaceEdit(int offset, int length, String replacement) {
+		this.offset = offset;
+		this.length = length;
+		this.replacement = replacement;
+	}
+	
+	public String toString() {
+		return "(" + this.offset + ", length " + this.length + " :>" + this.replacement + "<"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java
new file mode 100644
index 0000000..05d872a
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java
@@ -0,0 +1,1130 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2003 International Business Machines 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 API and implementation
+ ******************************************************************************/
+package org.eclipse.jdt.internal.formatter;
+
+import java.util.Arrays;
+import java.util.Map;
+
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.formatter.align.*;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+
+/**
+ * This class is responsible for dumping formatted source
+ * @since 2.1
+ */
+public class Scribe {
+
+	private static final int INITIAL_SIZE = 100;
+	
+	private boolean checkLineWrapping;
+	public int column;
+		
+	// Most specific alignment. 
+	public Alignment currentAlignment;
+	public int currentToken;
+	
+	// edits management
+	public int editsIndex;
+	private OptimizedReplaceEdit[] edits;
+	
+	// TODO to remove when the testing is done
+	private char fillingSpace;
+	public CodeFormatterVisitor formatter;
+	public int indentationLevel;	
+	public int lastNumberOfNewLines;
+	public int line;
+	private String lineSeparator;
+	public Alignment memberAlignment;
+	public boolean needSpace = false;
+	public int pageWidth;
+
+	public Scanner scanner;
+	public int scannerEndPosition;
+	public int tabSize;	
+	private int textRegionEnd;
+	private int textRegionStart;
+	public boolean useTab;
+
+	Scribe(CodeFormatterVisitor formatter, Map settings, int offset, int length) {
+		if (settings != null) {
+			Object assertModeSetting = settings.get(JavaCore.COMPILER_SOURCE);
+			if (assertModeSetting == null) {
+				this.scanner = new Scanner(true, true, false/*nls*/, JavaCore.VERSION_1_4.equals(assertModeSetting) ? ClassFileConstants.JDK1_4 : ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/);
+			} else {
+				this.scanner = new Scanner(true, true, false/*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/);
+			}
+		} else {
+			this.scanner = new Scanner(true, true, false/*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/);
+		}
+		this.formatter = formatter;
+		this.pageWidth = formatter.preferences.page_width;
+		this.tabSize = formatter.preferences.tab_size;
+		this.useTab = formatter.preferences.use_tab;
+		this.fillingSpace = formatter.preferences.filling_space;
+		setLineSeparatorAndIdentationLevel(formatter.preferences);
+		this.textRegionStart = offset;
+		this.textRegionEnd = offset + length - 1; 
+		reset();
+	}
+	
+	private final void addDeleteEdit(int start, int end) {
+		if (this.textRegionStart <= start && end <= this.textRegionEnd) {
+			if (this.edits.length == this.editsIndex) {
+				// resize
+				resize();
+			}
+			addOptimizedReplaceEdit(start, end - start + 1, ""); //$NON-NLS-1$
+		}
+	}
+	
+	private final void addInsertEdit(int insertPosition, String insertedString) {
+		if (this.textRegionStart <= insertPosition && insertPosition <= this.textRegionEnd) {
+			if (this.edits.length == this.editsIndex) {
+				// resize
+				resize();
+			}
+			addOptimizedReplaceEdit(insertPosition, 0, insertedString);
+		}
+	}
+
+	private final void addOptimizedReplaceEdit(int offset, int length, String replacement) {
+		if (this.editsIndex > 0) {
+			// try to merge last two edits
+			final OptimizedReplaceEdit previous = this.edits[this.editsIndex-1];
+			final int previousOffset = previous.offset;
+			final int previousLength = previous.length;
+			final int endOffsetOfPreviousEdit = previousOffset + previousLength;
+			final int replacementLength = replacement.length();
+			final String previousReplacement = previous.replacement;
+			final int previousReplacementLength = previousReplacement.length();
+			if (previousOffset == offset && previousLength == length && (replacementLength == 0 || previousReplacementLength == 0)) {
+				if (this.currentAlignment != null) {
+					final Location location = this.currentAlignment.location;
+					if (location.editsIndex == this.editsIndex) {
+						location.editsIndex--;
+						location.textEdit = previous;
+					}
+				}
+				this.editsIndex--;
+				return;
+			}
+			if (endOffsetOfPreviousEdit == offset) {
+				if (length != 0) {
+					if (replacementLength != 0) {
+						this.edits[this.editsIndex - 1] = new OptimizedReplaceEdit(previousOffset, previousLength + length, previousReplacement + replacement);
+					} else if (previousLength + length == previousReplacementLength) {
+						// check the characters. If they are identical, we can get rid of the previous edit
+						boolean canBeRemoved = true;
+						loop: for (int i = previousOffset; i < previousOffset + previousReplacementLength; i++) {
+							if (scanner.source[i] != previousReplacement.charAt(i - previousOffset)) {
+								this.edits[this.editsIndex - 1] = new OptimizedReplaceEdit(previousOffset, previousReplacementLength, previousReplacement);
+								canBeRemoved = false;
+								break loop;
+							}
+						}
+						if (canBeRemoved) {
+							if (this.currentAlignment != null) {
+								final Location location = this.currentAlignment.location;
+								if (location.editsIndex == this.editsIndex) {
+									location.editsIndex--;
+									location.textEdit = previous;
+								}
+							}
+							this.editsIndex--;
+						}
+					} else {
+						this.edits[this.editsIndex - 1] = new OptimizedReplaceEdit(previousOffset, previousLength + length, previousReplacement);
+					}
+				} else {
+					if (replacementLength != 0) {
+						this.edits[this.editsIndex - 1] = new OptimizedReplaceEdit(previousOffset, previousLength, previousReplacement + replacement);
+					}
+				}
+			} else {
+				this.edits[this.editsIndex++] = new OptimizedReplaceEdit(offset, length, replacement);
+			}
+		} else {
+			this.edits[this.editsIndex++] = new OptimizedReplaceEdit(offset, length, replacement);
+		}
+	}
+	
+	private final void addReplaceEdit(int start, int end, String replacement) {
+		if (this.textRegionStart <= start && end <= this.textRegionEnd) {
+			if (this.edits.length == this.editsIndex) {
+				// resize
+				resize();
+			}
+			addOptimizedReplaceEdit(start,  end - start + 1, replacement);
+		}
+	}
+
+	public void alignFragment(Alignment alignment, int fragmentIndex){
+		alignment.fragmentIndex = fragmentIndex;
+		alignment.checkColumn();
+		alignment.performFragmentEffect();
+	}
+	
+	public Alignment createAlignment(String name, int mode, int count, int sourceRestart){
+		return createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart);
+	}
+
+	public Alignment createAlignment(String name, int mode, int count, int sourceRestart, boolean adjust){
+		return createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart, adjust);
+	}
+
+	public Alignment createAlignment(String name, int mode, int count, int sourceRestart, int continuationIndent, boolean adjust){
+		return createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart, continuationIndent, adjust);
+	}
+	
+	public Alignment createAlignment(String name, int mode, int tieBreakRule, int count, int sourceRestart){
+		return createAlignment(name, mode, tieBreakRule, count, sourceRestart, this.formatter.preferences.continuation_indentation, false);
+	}
+
+	public Alignment createAlignment(String name, int mode, int tieBreakRule, int count, int sourceRestart, int continuationIndent, boolean adjust){
+		Alignment alignment = new Alignment(name, mode, tieBreakRule, this, count, sourceRestart, continuationIndent);
+		// adjust break indentation
+		if (adjust && this.memberAlignment != null) {
+			Alignment current = this.memberAlignment;
+			while (current.enclosing != null) {
+				current = current.enclosing;
+			}
+			if (current.mode != Alignment.M_NO_ALIGNMENT) {
+				final int indentSize = this.useTab ? 1 : this.tabSize;
+				switch(current.chunkKind) {
+					case Alignment.CHUNK_METHOD :
+					case Alignment.CHUNK_TYPE :
+						if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
+							alignment.breakIndentationLevel = this.indentationLevel + indentSize;
+						} else {
+							alignment.breakIndentationLevel = this.indentationLevel + continuationIndent * indentSize;
+						}
+						alignment.update();
+						break;
+					case Alignment.CHUNK_FIELD :
+						if ((mode & Alignment.M_INDENT_BY_ONE) != 0) {
+							alignment.breakIndentationLevel = current.originalIndentationLevel + indentSize;
+						} else {
+							alignment.breakIndentationLevel = current.originalIndentationLevel + continuationIndent * indentSize;
+						}
+						alignment.update();
+						break;
+				}
+			}
+		}
+		return alignment; 
+	}
+
+	public Alignment createMemberAlignment(String name, int mode, int count, int sourceRestart) {
+		Alignment mAlignment = createAlignment(name, mode, Alignment.R_INNERMOST, count, sourceRestart);
+		mAlignment.breakIndentationLevel = this.indentationLevel;
+		return mAlignment;
+	}
+	
+	public void enterAlignment(Alignment alignment){
+		alignment.enclosing = this.currentAlignment;
+		this.currentAlignment = alignment;
+	}
+
+	public void enterMemberAlignment(Alignment alignment) {
+		alignment.enclosing = this.memberAlignment;
+		this.memberAlignment = alignment;
+	}
+
+	public void exitAlignment(Alignment alignment, boolean discardAlignment){
+		Alignment current = this.currentAlignment;
+		while (current != null){
+			if (current == alignment) break;
+			current = current.enclosing;
+		}
+		if (current == null) {
+			throw new AbortFormatting("could not find matching alignment: "+alignment); //$NON-NLS-1$
+		}
+		this.indentationLevel = alignment.location.outputIndentationLevel;
+			
+		if (discardAlignment){ 
+			this.currentAlignment = alignment.enclosing;
+		}
+	}
+	
+	public void exitMemberAlignment(Alignment alignment){
+		Alignment current = this.memberAlignment;
+		while (current != null){
+			if (current == alignment) break;
+			current = current.enclosing;
+		}
+		if (current == null) {
+			throw new AbortFormatting("could not find matching alignment: "+alignment); //$NON-NLS-1$
+		}
+		this.indentationLevel = current.location.outputIndentationLevel;
+		this.memberAlignment = current.enclosing;
+	}
+	
+	public Alignment getAlignment(String name){
+		if (this.currentAlignment != null) {
+			return this.currentAlignment.getAlignment(name);
+		}
+		return null;
+	}
+	
+	/** 
+	 * Answer actual indentation level based on true column position
+	 * @return int
+	 */
+	public int getColumnIndentationLevel() {
+		if (this.useTab) {
+			return (this.column - 1)/ this.tabSize; 
+		} else {
+			return this.column - 1;
+		}
+	}	
+
+	/** 
+	 * Answer indentation level based on column estimated position
+	 * (if column is not indented, then use indentationLevel)
+	 */
+	public int getIndentationLevel(int someColumn) {
+		if (someColumn == 1) return this.indentationLevel;
+		if (this.useTab) {
+			return (someColumn - 1) / this.tabSize;
+		} else {
+			return someColumn - 1;
+		}
+	}	
+
+	public OptimizedReplaceEdit getLastEdit() {
+		if (this.editsIndex > 0) {
+			return this.edits[this.editsIndex - 1];
+		}
+		return null;
+	}
+	
+	Alignment getMemberAlignment() {
+		return this.memberAlignment;
+	}
+
+	/** 
+	 * Answer next indentation level based on column estimated position
+	 * (if column is not indented, then use indentationLevel)
+	 */
+	public int getNextIndentationLevel(int someColumn) {
+		if (someColumn == 1) return this.indentationLevel;
+		if (this.useTab) {
+			int rem = (someColumn - 1)% this.tabSize; // round to superior
+			return rem == 0 ? (someColumn - 1)/ this.tabSize : ((someColumn - 1)/ this.tabSize)+1;
+		} else {
+			return someColumn - 1;
+		}
+	}	
+
+	public TextEdit getRootEdit() {
+		MultiTextEdit edit = null;
+		if (this.textRegionStart < 0) {
+			edit = new MultiTextEdit(0, this.textRegionEnd + 1);
+		} else {
+			edit = new MultiTextEdit(this.textRegionStart, this.textRegionEnd - this.textRegionStart + 1);
+		}
+		for (int i= 0, max = this.editsIndex; i < max; i++) {
+			OptimizedReplaceEdit currentEdit = edits[i];
+			if (isValidEdit(currentEdit)) {
+				edit.addChild(new ReplaceEdit(currentEdit.offset, currentEdit.length, currentEdit.replacement));
+			}
+		}
+		this.edits = null;
+		return edit;
+	}
+	
+	public void handleLineTooLong() {
+		
+		// search for closest breakable alignment, using tiebreak rules
+		
+		// look for outermost breakable one
+		int relativeDepth = 0, outerMostDepth = -1;
+		Alignment targetAlignment = this.currentAlignment;
+		while (targetAlignment != null){
+			if (targetAlignment.tieBreakRule == Alignment.R_OUTERMOST && targetAlignment.couldBreak()){
+				outerMostDepth = relativeDepth;
+			}
+			targetAlignment = targetAlignment.enclosing;
+			relativeDepth++;
+		}
+		if (outerMostDepth >= 0) {
+			throw new AlignmentException(AlignmentException.LINE_TOO_LONG, outerMostDepth);
+		}
+		// look for innermost breakable one
+		relativeDepth = 0;
+		targetAlignment = this.currentAlignment;
+		while (targetAlignment != null){
+			if (targetAlignment.couldBreak()){
+				throw new AlignmentException(AlignmentException.LINE_TOO_LONG, relativeDepth);
+			}
+			targetAlignment = targetAlignment.enclosing;
+			relativeDepth++;
+		}
+		// did not find any breakable location - proceed
+	}
+	
+	public void indent() {
+		if (this.useTab) {
+			this.indentationLevel++; 
+		} else {
+			this.indentationLevel += tabSize; 
+		}
+	}	
+
+	/**
+	 * @param compilationUnitSource
+	 */
+	public void initializeScanner(char[] compilationUnitSource) {
+		this.scanner.setSource(compilationUnitSource);
+		this.scannerEndPosition = compilationUnitSource.length;
+		this.scanner.resetTo(0, this.scannerEndPosition);
+		if (this.textRegionEnd == -1) {
+			this.textRegionEnd = this.scannerEndPosition;
+		}
+		this.edits = new OptimizedReplaceEdit[INITIAL_SIZE];
+	}	
+	
+	private boolean isValidEdit(OptimizedReplaceEdit edit) {
+		final int editLength= edit.length;
+		final int editReplacementLength= edit.replacement.length();
+		final int editOffset= edit.offset;
+		if (editLength != 0 && editReplacementLength != 0 && editLength == editReplacementLength) {
+			for (int i = editOffset, max = editOffset + editLength; i < max; i++) {
+				if (scanner.source[i] != edit.replacement.charAt(i - editOffset)) {
+					return true;
+				}
+			}
+			return false;
+		} else {
+			return true;
+		}
+	}
+
+	private void preserveEmptyLines(int count, int insertPosition) {
+		if (count > 0) {
+			if (this.formatter.preferences.preserve_user_linebreaks) {
+				this.printEmptyLines(count, insertPosition);
+			} else if (this.formatter.preferences.number_of_empty_lines_to_preserve != 0) {
+				int linesToPreserve = Math.min(count, this.formatter.preferences.number_of_empty_lines_to_preserve);
+				this.printEmptyLines(linesToPreserve, insertPosition);
+			} else {
+				printNewLine(insertPosition);
+			}
+		}
+	}
+		
+	private void print(char[] s, boolean considerSpaceIfAny) {
+		if (checkLineWrapping && s.length + column > this.pageWidth) {
+			handleLineTooLong();
+		}
+		this.lastNumberOfNewLines = 0;
+		printIndentationIfNecessary();
+		if (considerSpaceIfAny) {
+			this.space(this.scanner.getCurrentTokenStartPosition());
+		}
+		column += s.length;
+		needSpace = true;
+	}
+	private void printBlockComment(char[] s, boolean isJavadoc) {
+		int currentTokenStartPosition = this.scanner.getCurrentTokenStartPosition();
+		int currentTokenEndPosition = this.scanner.getCurrentTokenEndPosition() + 1;
+		
+		this.scanner.resetTo(currentTokenStartPosition, currentTokenEndPosition - 1);
+		int currentCharacter;
+		boolean isNewLine = false;
+		int start = currentTokenStartPosition;
+		int nextCharacterStart = currentTokenStartPosition;
+		printIndentationIfNecessary();
+		int previousStart = currentTokenStartPosition;
+
+		while (nextCharacterStart <= currentTokenEndPosition && (currentCharacter = this.scanner.getNextChar()) != -1) {
+			nextCharacterStart = this.scanner.currentPosition;
+
+			switch(currentCharacter) {
+				case '\r' :
+					start = previousStart;
+					isNewLine = true;
+					if (this.scanner.getNextChar('\n')) {
+						currentCharacter = '\n';
+						nextCharacterStart = this.scanner.currentPosition;
+					}
+					break;
+				case '\n' :
+					start = previousStart;
+					isNewLine = true;
+					break;
+				default:
+					if (isNewLine) {
+						if (Character.isWhitespace((char) currentCharacter)) {
+							int previousStartPosition = this.scanner.currentPosition;
+							while(currentCharacter != -1 && currentCharacter != '\r' && currentCharacter != '\n' && Character.isWhitespace((char) currentCharacter)) {
+								previousStart = nextCharacterStart;
+								previousStartPosition = this.scanner.currentPosition;
+								currentCharacter = this.scanner.getNextChar();
+								nextCharacterStart = this.scanner.currentPosition;
+							}
+							if (currentCharacter == '\r' || currentCharacter == '\n') {
+								nextCharacterStart = previousStartPosition;
+							}
+						}
+						this.column = 1;
+						this.line++;
+
+						StringBuffer buffer = new StringBuffer();
+						buffer.append(this.lineSeparator);
+						printIndentationIfNecessary(buffer);
+						buffer.append(this.fillingSpace);
+				
+						addReplaceEdit(start, previousStart - 1, String.valueOf(buffer));
+					} else {
+						this.column += (nextCharacterStart - previousStart);
+					}
+					isNewLine = false;
+			}
+			previousStart = nextCharacterStart;
+			this.scanner.currentPosition = nextCharacterStart;
+		}
+		this.lastNumberOfNewLines = 0;
+		needSpace = false;
+		this.scanner.resetTo(currentTokenEndPosition, this.scannerEndPosition - 1);
+		if (isJavadoc) {
+			printNewLine();
+		}
+	}
+	public void printComment() {
+		try {
+			// if we have a space between two tokens we ensure it will be dumped in the formatted string
+			int currentTokenStartPosition = this.scanner.currentPosition;
+			boolean hasComment = false;
+			boolean hasLineComment = false;
+			boolean hasWhitespace = false;
+			int count = 0;
+			while ((this.currentToken = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(this.currentToken) {
+					case TerminalTokens.TokenNameWHITESPACE :
+						char[] whiteSpaces = this.scanner.getCurrentTokenSource();
+						count = 0;
+						for (int i = 0, max = whiteSpaces.length; i < max; i++) {
+							switch(whiteSpaces[i]) {
+								case '\r' :
+									if ((i + 1) < max) {
+										if (whiteSpaces[i + 1] == '\n') {
+											i++;
+										}
+									}
+									count++;
+									break;
+								case '\n' :
+									count++;
+							}
+						}
+						if (count == 0) {
+							hasWhitespace = true;
+							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+						} else if (hasComment) {
+							if (count == 1) {
+								this.printNewLine(this.scanner.getCurrentTokenStartPosition());
+							} else {
+								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
+							}
+							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+						} else if (hasLineComment) {
+							this.preserveEmptyLines(count, this.scanner.getCurrentTokenStartPosition());
+							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+						} else if (this.formatter.preferences.preserve_user_linebreaks) {
+							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+							if (count == 1) {
+								this.printNewLine(this.scanner.getCurrentTokenEndPosition() + 1);
+							}
+						} else if (count != 0 && this.formatter.preferences.number_of_empty_lines_to_preserve != 0) {
+							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+							preserveEmptyLines(count - 1, this.scanner.getCurrentTokenEndPosition() + 1);
+						} else {
+							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+						}
+						currentTokenStartPosition = this.scanner.currentPosition;						
+						break;
+					case TerminalTokens.TokenNameCOMMENT_LINE :
+						if (count >= 1) {
+							if (count > 1) {
+								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
+							} else if (count == 1 || this.formatter.preferences.preserve_user_linebreaks) {
+								printNewLine(this.scanner.getCurrentTokenStartPosition());
+							}
+						} else if (hasWhitespace) {
+							space(this.scanner.getCurrentTokenStartPosition());
+						} 
+						hasWhitespace = false;
+						this.printCommentLine(this.scanner.getRawTokenSource());
+						currentTokenStartPosition = this.scanner.currentPosition;
+						hasLineComment = true;		
+						count = 0;
+						break;
+					case TerminalTokens.TokenNameCOMMENT_BLOCK :
+						if (count >= 1) {
+							if (count > 1) {
+								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
+							} else if (count == 1 && this.formatter.preferences.preserve_user_linebreaks) {
+								printNewLine(this.scanner.getCurrentTokenStartPosition());
+							}
+						} else if (hasWhitespace) {
+							space(this.scanner.getCurrentTokenStartPosition());
+						} 
+						hasWhitespace = false;
+						this.printBlockComment(this.scanner.getRawTokenSource(), false);
+						currentTokenStartPosition = this.scanner.currentPosition;
+						hasLineComment = false;
+						hasComment = true;
+						count = 0;
+						break;
+					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+						if (count >= 1) {
+							if (count > 1) {
+								preserveEmptyLines(count - 1, this.scanner.getCurrentTokenStartPosition());
+							} else if (count == 1 && this.formatter.preferences.preserve_user_linebreaks) {
+								printNewLine(this.scanner.getCurrentTokenStartPosition());
+							}
+						} else if (hasWhitespace) {
+							space(this.scanner.getCurrentTokenStartPosition());
+						} 
+						hasWhitespace = false;
+						this.printBlockComment(this.scanner.getRawTokenSource(), true);
+						currentTokenStartPosition = this.scanner.currentPosition;
+						hasLineComment = false;
+						hasComment = true;
+						count = 0;
+						break;
+					default :
+						// step back one token
+						this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
+						return;
+				}
+			}
+		} catch (InvalidInputException e) {
+			throw new AbortFormatting(e);
+		}
+	}
+	
+	private void printCommentLine(char[] s) {
+		int currentTokenStartPosition = this.scanner.getCurrentTokenStartPosition();
+		int currentTokenEndPosition = this.scanner.getCurrentTokenEndPosition() + 1;
+
+		this.scanner.resetTo(currentTokenStartPosition, currentTokenEndPosition - 1);
+		int currentCharacter;
+		int start = currentTokenStartPosition;
+		int nextCharacterStart = currentTokenStartPosition;
+		printIndentationIfNecessary();
+		int previousStart = currentTokenStartPosition;
+
+		loop: while (nextCharacterStart <= currentTokenEndPosition && (currentCharacter = this.scanner.getNextChar()) != -1) {
+			nextCharacterStart = this.scanner.currentPosition;
+
+			switch(currentCharacter) {
+				case '\r' :
+					start = previousStart;
+					break loop;
+				case '\n' :
+					start = previousStart;
+					break loop;
+			}
+			previousStart = nextCharacterStart;
+		}
+		if (start != currentTokenStartPosition) {
+			addReplaceEdit(start, currentTokenEndPosition - 1, lineSeparator);
+		}
+		line++; 
+		column = 1;
+		needSpace = false;
+		lastNumberOfNewLines = 1;
+		// realign to the proper value
+		if (this.currentAlignment != null) {
+			if (this.memberAlignment != null) {
+				// select the last alignment
+				if (this.currentAlignment.location.inputOffset > this.memberAlignment.location.inputOffset) {
+					this.indentationLevel = Math.max(this.indentationLevel, this.currentAlignment.breakIndentationLevel);
+				} else {
+					this.indentationLevel = Math.max(this.indentationLevel, this.memberAlignment.breakIndentationLevel);
+				}
+			} else {
+				this.indentationLevel = Math.max(this.indentationLevel, this.currentAlignment.breakIndentationLevel);
+			}
+		}
+		this.scanner.resetTo(currentTokenEndPosition, this.scannerEndPosition - 1);
+	}
+	public void printEmptyLines(int linesNumber) {
+		this.printEmptyLines(linesNumber, this.scanner.getCurrentTokenEndPosition() + 1);
+	}
+
+	public void printEmptyLines(int linesNumber, int insertPosition) {
+		StringBuffer buffer = new StringBuffer();
+		if (lastNumberOfNewLines == 0) {
+			linesNumber++; // add an extra line breaks
+			for (int i = 0; i < linesNumber; i++) {
+				buffer.append(this.lineSeparator);
+			}
+			lastNumberOfNewLines += linesNumber;
+			line += linesNumber;
+			column = 1;
+			needSpace = false;
+		} else if (lastNumberOfNewLines == 1) {
+			for (int i = 0; i < linesNumber; i++) {
+				buffer.append(this.lineSeparator);
+			}
+			lastNumberOfNewLines += linesNumber;
+			line += linesNumber;
+			column = 1;
+			needSpace = false;
+		} else {
+			if ((lastNumberOfNewLines - 1) >= linesNumber) {
+				// there is no need to add new lines
+				return;
+			}
+			final int realNewLineNumber = linesNumber - lastNumberOfNewLines + 1;
+			for (int i = 0; i < realNewLineNumber; i++) {
+				buffer.append(this.lineSeparator);
+			}
+			lastNumberOfNewLines += realNewLineNumber;
+			line += realNewLineNumber;
+			column = 1;
+			needSpace = false;
+		}
+		addInsertEdit(insertPosition, buffer.toString());
+	}
+
+	private void printIndentationIfNecessary() {
+		int indentationColumn = (this.useTab ? this.indentationLevel * this.tabSize : this.indentationLevel)+1;
+		if (this.column < indentationColumn) {
+			StringBuffer buffer = new StringBuffer();
+			for (int i = getColumnIndentationLevel(), max = this.indentationLevel; i < max; i++) { 
+				if (this.useTab) {
+					this.tab(buffer);
+				} else {
+					this.column++;
+					buffer.append(this.fillingSpace);
+					this.needSpace = false;
+				}
+			}
+			addInsertEdit(this.scanner.getCurrentTokenStartPosition(), buffer.toString());
+		}
+	}
+
+
+	private void printIndentationIfNecessary(StringBuffer buffer) {
+		int indentationColumn = (this.useTab ? this.indentationLevel * this.tabSize : this.indentationLevel)+1;
+		if (this.column < indentationColumn) {
+			for (int i = getColumnIndentationLevel(), max = this.indentationLevel; i < max; i++) { 
+				if (this.useTab) {
+					this.tab(buffer);
+				} else {
+					this.column++;
+					buffer.append(this.fillingSpace);
+					this.needSpace = false;
+				}
+			}
+		}
+	}
+
+	public void printModifiers() {
+		this.printComment();
+		try {
+			boolean isFirstModifier = true;
+			int currentTokenStartPosition = this.scanner.currentPosition;
+			boolean hasComment = false;
+			while ((this.currentToken = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(this.currentToken) {
+					case TerminalTokens.TokenNamepublic :
+					case TerminalTokens.TokenNameprotected :
+					case TerminalTokens.TokenNameprivate :
+					case TerminalTokens.TokenNamestatic :
+					case TerminalTokens.TokenNameabstract :
+					case TerminalTokens.TokenNamefinal :
+					case TerminalTokens.TokenNamenative :
+					case TerminalTokens.TokenNamesynchronized :
+					case TerminalTokens.TokenNametransient :
+					case TerminalTokens.TokenNamevolatile :
+						this.print(this.scanner.getRawTokenSource(), !isFirstModifier);
+						isFirstModifier = false;
+						currentTokenStartPosition = this.scanner.getCurrentTokenStartPosition();
+						break;
+					case TerminalTokens.TokenNameCOMMENT_BLOCK :
+						this.printBlockComment(this.scanner.getRawTokenSource(), false);
+						currentTokenStartPosition = this.scanner.currentPosition;
+						hasComment = true;
+						break;
+					case TerminalTokens.TokenNameCOMMENT_JAVADOC :
+						this.printBlockComment(this.scanner.getRawTokenSource(), true);
+						currentTokenStartPosition = this.scanner.currentPosition;
+						hasComment = true;
+						break;
+					case TerminalTokens.TokenNameCOMMENT_LINE :
+						this.printCommentLine(this.scanner.getRawTokenSource());
+						currentTokenStartPosition = this.scanner.currentPosition;
+						break;
+					case TerminalTokens.TokenNameWHITESPACE :
+						addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+						int count = 0;
+						char[] whiteSpaces = this.scanner.getCurrentTokenSource();
+						for (int i = 0, max = whiteSpaces.length; i < max; i++) {
+							switch(whiteSpaces[i]) {
+								case '\r' :
+									if ((i + 1) < max) {
+										if (whiteSpaces[i + 1] == '\n') {
+											i++;
+										}
+									}
+									count++;
+									break;
+								case '\n' :
+									count++;
+							}
+						}
+						if (count >= 1 && hasComment) {
+							printNewLine();
+						}
+						currentTokenStartPosition = this.scanner.currentPosition;
+						hasComment = false;
+						break;
+					default:
+						// step back one token
+						this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
+						return;					
+				}
+			}
+		} catch (InvalidInputException e) {
+			throw new AbortFormatting(e);
+		}
+	}
+	
+	public void printNewLine() {
+		if (lastNumberOfNewLines >= 1) {
+			column = 1; // ensure that the scribe is at the beginning of a new line
+			return;
+		}
+		addInsertEdit(this.scanner.getCurrentTokenEndPosition() + 1, this.lineSeparator);
+		line++;
+		lastNumberOfNewLines = 1;
+		column = 1;
+		needSpace = false;
+	}
+
+	public void printNewLine(int inserPosition) {
+		if (lastNumberOfNewLines >= 1) {
+			column = 1; // ensure that the scribe is at the beginning of a new line
+			return;
+		}
+		addInsertEdit(inserPosition, this.lineSeparator);
+		line++;
+		lastNumberOfNewLines = 1;
+		column = 1;
+		needSpace = false;
+	}
+
+	public void printNextToken(int expectedTokenType){
+		printNextToken(expectedTokenType, false);
+	}
+
+	public void printNextToken(int expectedTokenType, boolean considerSpaceIfAny){
+		printComment();
+		try {
+			this.currentToken = this.scanner.getNextToken();
+			char[] currentTokenSource = this.scanner.getRawTokenSource();
+			if (expectedTokenType != this.currentToken) {
+				throw new AbortFormatting("unexpected token type, expecting:"+expectedTokenType+", actual:"+this.currentToken);//$NON-NLS-1$//$NON-NLS-2$
+			}
+			this.print(currentTokenSource, considerSpaceIfAny);
+		} catch (InvalidInputException e) {
+			throw new AbortFormatting(e);
+		}
+	}
+		
+	public void printNextToken(int expectedTokenType, boolean considerSpaceIfAny, boolean considerNewLineAfterComment){
+		printComment();
+		try {
+			this.currentToken = this.scanner.getNextToken();
+			char[] currentTokenSource = this.scanner.getRawTokenSource();
+			if (expectedTokenType != this.currentToken) {
+				throw new AbortFormatting("unexpected token type, expecting:"+expectedTokenType+", actual:"+this.currentToken);//$NON-NLS-1$//$NON-NLS-2$
+			}
+			this.print(currentTokenSource, considerSpaceIfAny);
+		} catch (InvalidInputException e) {
+			throw new AbortFormatting(e);
+		}
+	}
+
+	public void printNextToken(int[] expectedTokenTypes){
+		printComment();
+		try {
+			this.currentToken = this.scanner.getNextToken();
+			char[] currentTokenSource = this.scanner.getRawTokenSource();
+			if (Arrays.binarySearch(expectedTokenTypes, this.currentToken) < 0) {
+				StringBuffer expectations = new StringBuffer(5);
+				for (int i = 0; i < expectedTokenTypes.length; i++){
+					if (i > 0) {
+						expectations.append(',');
+					}
+					expectations.append(expectedTokenTypes[i]);
+				}				
+				throw new AbortFormatting("unexpected token type, expecting:["+expectations.toString()+"], actual:"+this.currentToken);//$NON-NLS-1$//$NON-NLS-2$
+			}
+			this.print(currentTokenSource, false);
+		} catch (InvalidInputException e) {
+			throw new AbortFormatting(e);
+		}
+	}
+	
+	public void printNextToken(int[] expectedTokenTypes, boolean considerSpaceIfAny, boolean considerNewLineAfterComment){
+		printComment();
+		try {
+			this.currentToken = this.scanner.getNextToken();
+			char[] currentTokenSource = this.scanner.getRawTokenSource();
+			if (Arrays.binarySearch(expectedTokenTypes, this.currentToken) < 0) {
+				StringBuffer expectations = new StringBuffer(5);
+				for (int i = 0; i < expectedTokenTypes.length; i++){
+					if (i > 0) {
+						expectations.append(',');
+					}
+					expectations.append(expectedTokenTypes[i]);
+				}				
+				throw new AbortFormatting("unexpected token type, expecting:["+expectations.toString()+"], actual:"+this.currentToken);//$NON-NLS-1$//$NON-NLS-2$
+			}
+			this.print(currentTokenSource, considerSpaceIfAny);
+		} catch (InvalidInputException e) {
+			throw new AbortFormatting(e);
+		}
+	}
+
+	public void printQualifiedReference(int sourceEnd) {
+		try {
+			do {
+				this.printComment();
+				switch(this.currentToken = this.scanner.getNextToken()) {
+					case TerminalTokens.TokenNameEOF :
+						return;
+					case TerminalTokens.TokenNameWHITESPACE :
+						addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+						break;
+					default: 
+						this.print(this.scanner.getRawTokenSource(), false);
+						break;
+				}
+			} while (this.scanner.currentPosition < sourceEnd);
+		} catch(InvalidInputException e) {
+			throw new AbortFormatting(e);
+		}
+	}
+
+	private void printRule(StringBuffer stringBuffer) {
+		for (int i = 0; i < this.pageWidth; i++){
+			if ((i % this.tabSize) == 0) { 
+				stringBuffer.append('+');
+			} else {
+				stringBuffer.append('-');
+			}
+		}
+		stringBuffer.append(this.lineSeparator);
+		
+		for (int i = 0; i < (pageWidth / tabSize); i++) {
+			stringBuffer.append(i);
+			stringBuffer.append('\t');
+		}			
+	}
+
+	public void printTrailingComment() {
+		try {
+			// if we have a space between two tokens we ensure it will be dumped in the formatted string
+			int currentTokenStartPosition = this.scanner.currentPosition;
+			boolean hasWhitespaces = false;
+			boolean hasComment = false;
+			boolean hasLineComment = false;
+			while ((this.currentToken = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+				switch(this.currentToken) {
+					case TerminalTokens.TokenNameWHITESPACE :
+						int count = 0;
+						char[] whiteSpaces = this.scanner.getCurrentTokenSource();
+						for (int i = 0, max = whiteSpaces.length; i < max; i++) {
+							switch(whiteSpaces[i]) {
+								case '\r' :
+									if ((i + 1) < max) {
+										if (whiteSpaces[i + 1] == '\n') {
+											i++;
+										}
+									}
+									count++;
+									break;
+								case '\n' :
+									count++;
+							}
+						}
+						if (hasLineComment) {
+							if (count >= 1) {
+								currentTokenStartPosition = this.scanner.getCurrentTokenStartPosition();
+								this.preserveEmptyLines(count, currentTokenStartPosition);
+								addDeleteEdit(currentTokenStartPosition, this.scanner.getCurrentTokenEndPosition());
+								this.scanner.resetTo(this.scanner.currentPosition, this.scannerEndPosition - 1);
+								return;
+							} else {
+								this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
+								return;
+							}
+						} else if (count >= 1) {
+							if (hasComment) {
+								this.printNewLine(this.scanner.getCurrentTokenStartPosition());
+							}
+							this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
+							return;
+						} else {
+							hasWhitespaces = true;
+							currentTokenStartPosition = this.scanner.currentPosition;						
+							addDeleteEdit(this.scanner.getCurrentTokenStartPosition(), this.scanner.getCurrentTokenEndPosition());
+						}
+						break;
+					case TerminalTokens.TokenNameCOMMENT_LINE :
+						if (hasWhitespaces) {
+							space(this.scanner.getCurrentTokenStartPosition());
+						}
+						this.printCommentLine(this.scanner.getRawTokenSource());
+						currentTokenStartPosition = this.scanner.currentPosition;
+						hasLineComment = true;
+						break;
+					case TerminalTokens.TokenNameCOMMENT_BLOCK :
+						if (hasWhitespaces) {
+							space(this.scanner.getCurrentTokenStartPosition());
+						}
+						this.printBlockComment(this.scanner.getRawTokenSource(), false);
+						currentTokenStartPosition = this.scanner.currentPosition;
+						hasComment = true;
+						break;
+					default :
+						// step back one token
+						this.scanner.resetTo(currentTokenStartPosition, this.scannerEndPosition - 1);
+						return;
+				}
+			}
+		} catch (InvalidInputException e) {
+			throw new AbortFormatting(e);
+		}
+	}
+
+	void redoAlignment(AlignmentException e){
+		if (e.relativeDepth > 0) { // if exception targets a distinct context
+			e.relativeDepth--; // record fact that current context got traversed
+			this.currentAlignment = this.currentAlignment.enclosing; // pop currentLocation
+			throw e; // rethrow
+		} 
+		// reset scribe/scanner to restart at this given location
+		this.resetAt(this.currentAlignment.location);
+		this.scanner.resetTo(this.currentAlignment.location.inputOffset, this.scanner.eofPosition);
+		// clean alignment chunkKind so it will think it is a new chunk again
+		this.currentAlignment.chunkKind = 0;
+		this.formatter.lastLocalDeclarationSourceStart = -1;
+	}
+
+	void redoMemberAlignment(AlignmentException e){
+		// reset scribe/scanner to restart at this given location
+		this.resetAt(this.memberAlignment.location);
+		this.scanner.resetTo(this.memberAlignment.location.inputOffset, this.scanner.eofPosition);
+		// clean alignment chunkKind so it will think it is a new chunk again
+		this.memberAlignment.chunkKind = 0;
+		this.formatter.lastLocalDeclarationSourceStart = -1;
+	}
+
+	public void reset() {
+		this.checkLineWrapping = true;
+		this.line = 0;
+		this.column = 1;
+		this.editsIndex = 0;
+	}
+		
+	private void resetAt(Location location) {
+		this.line = location.outputLine;
+		this.column = location.outputColumn;
+		this.indentationLevel = location.outputIndentationLevel;
+		this.lastNumberOfNewLines = location.lastNumberOfNewLines;
+		this.needSpace = location.needSpace;
+		this.editsIndex = location.editsIndex;
+		if (this.editsIndex > 0) {
+			this.edits[this.editsIndex - 1] = location.textEdit;
+		}
+	}
+
+	private void resize() {
+		System.arraycopy(this.edits, 0, (this.edits = new OptimizedReplaceEdit[this.editsIndex * 2]), 0, this.editsIndex);
+	}
+
+	public void setLineSeparatorAndIdentationLevel(DefaultCodeFormatterOptions preferences) {
+		this.lineSeparator = preferences.line_separator;
+		if (this.useTab) {
+			this.indentationLevel = preferences.initial_indentation_level;
+		} else {
+			this.indentationLevel = preferences.initial_indentation_level * this.tabSize;
+		}
+	}
+	
+	public void space() {
+		if (!this.needSpace) return;
+		this.lastNumberOfNewLines = 0;
+		addInsertEdit(this.scanner.getCurrentTokenEndPosition() + 1, " ");  //$NON-NLS-1$
+		this.column++;
+		this.needSpace = false;		
+	}
+
+	private void space(int insertPosition) {
+		if (!this.needSpace) return;
+		this.lastNumberOfNewLines = 0;
+		addInsertEdit(insertPosition, " ");  //$NON-NLS-1$
+		this.column++;
+		this.needSpace = false;		
+	}
+
+	private void tab(StringBuffer buffer) {
+		this.lastNumberOfNewLines = 0;
+		int complement = this.tabSize - ((this.column - 1)% this.tabSize); // amount of space
+		if (this.useTab) {
+			buffer.append('\t');
+		} else {
+			for (int i = 0; i < complement; i++) {
+				buffer.append(this.fillingSpace);
+			}
+		}
+		this.column += complement;
+		this.needSpace = false;
+	}
+	
+	public String toString() {
+		StringBuffer stringBuffer = new StringBuffer();
+		stringBuffer
+			.append("(page witdh = " + this.pageWidth + ") - (useTab = " + this.useTab + ") - (tabSize = " + this.tabSize + ")")	//$NON-NLS-1$	//$NON-NLS-2$	//$NON-NLS-3$	//$NON-NLS-4$
+			.append(this.lineSeparator)
+			.append("(line = " + this.line + ") - (column = " + this.column + ") - (identationLevel = " + this.indentationLevel + ")")	//$NON-NLS-1$	//$NON-NLS-2$	//$NON-NLS-3$	//$NON-NLS-4$
+			.append(this.lineSeparator)
+			.append("(needSpace = " + this.needSpace + ") - (lastNumberOfNewLines = " + this.lastNumberOfNewLines + ") - (checkLineWrapping = " + this.checkLineWrapping + ")")	//$NON-NLS-1$	//$NON-NLS-2$	//$NON-NLS-3$	//$NON-NLS-4$
+			.append(this.lineSeparator)
+			.append("==================================================================================")	//$NON-NLS-1$
+			.append(this.lineSeparator);
+		printRule(stringBuffer);
+		return stringBuffer.toString();
+	}
+	
+	public void unIndent() {
+		if (this.useTab) {
+			this.indentationLevel--;
+		} else {
+			this.indentationLevel -= tabSize;
+		}
+	}
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/Alignment.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/Alignment.java
new file mode 100644
index 0000000..cc79fa4
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/Alignment.java
@@ -0,0 +1,409 @@
+/*******************************************************************************
+ * Copyright (c) 2002, 2003 International Business Machines 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 API and implementation
+ ******************************************************************************/
+package org.eclipse.jdt.internal.formatter.align;
+
+import org.eclipse.jdt.internal.formatter.Location;
+import org.eclipse.jdt.internal.formatter.Scribe;
+
+/**
+ * Alignment management
+ * 
+ * @since 2.1
+ */
+public class Alignment {
+
+	// name of alignment
+	public String name;
+	
+	// link to enclosing alignment
+	public Alignment enclosing;
+	 
+	// start location of this alignment
+	public Location location;
+	
+	// indentation management
+	public int fragmentIndex;
+	public int fragmentCount;
+	public int[] fragmentIndentations;
+	public boolean needRedoColumnAlignment;
+
+	// chunk management
+	public int chunkStartIndex;
+	public int chunkKind;
+
+	// break management	
+	public int originalIndentationLevel;
+	public int breakIndentationLevel;
+	public int shiftBreakIndentationLevel;
+	public int[] fragmentBreaks;
+	public boolean wasSplit;
+
+	public Scribe scribe;
+	
+	/* 
+	 * Alignment modes
+	 */
+	public static final int M_FORCE = 1; // if bit set, then alignment will be non-optional (default is optional)
+	public static final int M_INDENT_ON_COLUMN = 2; // if bit set, broken fragments will be aligned on current location column (default is to break at current indentation level)
+	public static final int	M_INDENT_BY_ONE = 4; // if bit set, broken fragments will be indented one level below current (not using continuation indentation)
+
+	// split modes can be combined either with M_FORCE or M_INDENT_ON_COLUMN
+	
+	/** foobar(#fragment1, #fragment2, <ul>
+	 *  <li>    #fragment3, #fragment4 </li>
+	 * </ul>
+	 */
+	public static final int M_COMPACT_SPLIT = 16; // fill each line with all possible fragments
+
+	/** foobar(<ul>
+	 * <li>    #fragment1, #fragment2,  </li>
+	 * <li>     #fragment5, #fragment4, </li>
+	 * </ul>
+	 */
+	public static final int M_COMPACT_FIRST_BREAK_SPLIT = 32; //  compact mode, but will first try to break before first fragment
+
+	/** foobar(<ul>
+	 * <li>     #fragment1,  </li>
+	 * <li>     #fragment2,  </li>
+	 * <li>     #fragment3 </li>
+	 * <li>     #fragment4,  </li>
+	 * </ul>
+	 */
+	public static final int M_ONE_PER_LINE_SPLIT = 32+16; // one fragment per line
+
+	/** 
+	 * foobar(<ul>
+	 * <li>     #fragment1,  </li>
+	 * <li>        #fragment2,  </li>
+	 * <li>        #fragment3 </li>
+	 * <li>        #fragment4,  </li>
+	 * </ul>
+	 */ 
+	public static final int M_NEXT_SHIFTED_SPLIT = 64; // one fragment per line, subsequent are indented further
+
+	/** foobar(#fragment1, <ul>
+	 * <li>      #fragment2,  </li>
+	 * <li>      #fragment3 </li>
+	 * <li>      #fragment4,  </li>
+	 * </ul>
+	 */
+	public static final int M_NEXT_PER_LINE_SPLIT = 64+16; // one per line, except first fragment (if possible)
+
+	//64+32
+	//64+32+16
+	
+	// mode controlling column alignments
+	/** 
+	 * <table BORDER COLS=4 WIDTH="100%" >
+	 * <tr><td>#fragment1A</td>            <td>#fragment2A</td>       <td>#fragment3A</td>  <td>#very-long-fragment4A</td></tr>
+	 * <tr><td>#fragment1B</td>            <td>#long-fragment2B</td>  <td>#fragment3B</td>  <td>#fragment4B</td></tr>
+	 * <tr><td>#very-long-fragment1C</td>  <td>#fragment2C</td>       <td>#fragment3C</td>  <td>#fragment4C</td></tr>
+	 * </table>
+	 */
+	public static final int M_MULTICOLUMN = 256; // fragments are on same line, but multiple line of fragments will be aligned vertically
+	
+	public static final int M_NO_ALIGNMENT = 0;
+	
+	public int mode;
+	
+	public static final int SPLIT_MASK = M_ONE_PER_LINE_SPLIT | M_NEXT_SHIFTED_SPLIT | M_COMPACT_SPLIT | M_COMPACT_FIRST_BREAK_SPLIT | M_NEXT_PER_LINE_SPLIT;
+
+	// alignment tie-break rules - when split is needed, will decide whether innermost/outermost alignment is to be chosen
+	public static final int R_OUTERMOST = 1;
+	public static final int R_INNERMOST = 2;
+	public int tieBreakRule;
+	
+	// alignment effects on a per fragment basis
+	public static int NONE = 0;
+	public static int BREAK = 1;
+	
+	// chunk kind
+	public static final int CHUNK_FIELD = 1;
+	public static final int CHUNK_METHOD = 2;
+	public static final int CHUNK_TYPE = 3;
+
+
+	// location to align and break on.
+	public Alignment(String name, int mode, int tieBreakRule, Scribe scribe, int fragmentCount, int sourceRestart, int continuationIndent){
+		
+		this.name = name;
+		this.location = new Location(scribe, sourceRestart);
+		this.mode = mode;
+		this.tieBreakRule = tieBreakRule;
+		this.fragmentCount = fragmentCount;
+		this.scribe = scribe;
+		this.originalIndentationLevel = this.scribe.indentationLevel;
+		this.wasSplit = false;
+		
+		// initialize the break indentation level, using modes and continuationIndentationLevel preference
+		final int indentSize = this.scribe.useTab ? 1 : this.scribe.tabSize;
+		int currentColumn = this.location.outputColumn;
+		if (currentColumn == 1) {
+		    currentColumn = this.location.outputIndentationLevel * indentSize + 1;
+		}
+		
+		if ((mode & M_INDENT_ON_COLUMN) != 0) {
+			// indent broken fragments at next indentation level, based on current column
+			this.breakIndentationLevel = this.scribe.getNextIndentationLevel(currentColumn);
+			if (this.breakIndentationLevel == this.location.outputIndentationLevel) {
+				this.breakIndentationLevel += (continuationIndent * indentSize);
+			}
+		} else if ((mode & M_INDENT_BY_ONE) != 0) {
+			// indent broken fragments exactly one level deeper than current indentation
+			this.breakIndentationLevel = this.location.outputIndentationLevel + indentSize;
+		} else {
+			// indent broken fragments by one continuation indentation deeper than current indentation
+			this.breakIndentationLevel = this.location.outputIndentationLevel + continuationIndent * indentSize;
+		}
+		this.shiftBreakIndentationLevel = this.breakIndentationLevel + indentSize;
+
+		this.fragmentIndentations = new int[this.fragmentCount];
+		this.fragmentBreaks = new int[this.fragmentCount];
+
+		// check for forced alignments
+		if ((this.mode & M_FORCE) != 0) {
+			couldBreak();
+		}					
+	}
+	
+	public boolean checkChunkStart(int kind, int startIndex, int sourceRestart) {
+		if (this.chunkKind != kind) {
+			this.chunkKind = kind;
+			
+			// when redoing same chunk alignment, must not reset
+			if (startIndex != this.chunkStartIndex) {
+				this.chunkStartIndex = startIndex;
+				this.location.update(this.scribe, sourceRestart);
+				reset();
+			}
+			return true;
+		}
+		return false;
+	}
+
+	public void checkColumn() {
+		
+		if ((this.mode & M_NO_ALIGNMENT) != 0) {
+			return;
+		}
+	
+		if ((this.mode & M_MULTICOLUMN) != 0) {
+			int currentIndentation = this.scribe.getNextIndentationLevel(this.scribe.column+(this.scribe.needSpace ? 1 : 0));
+			int fragmentIndentation = this.fragmentIndentations[this.fragmentIndex];
+			if (currentIndentation > fragmentIndentation) {
+				this.fragmentIndentations[this.fragmentIndex] =  currentIndentation;
+				if (fragmentIndentation != 0) {
+					for (int i = this.fragmentIndex+1; i < this.fragmentCount; i++) {
+						this.fragmentIndentations[i] = 0;
+					}
+					this.needRedoColumnAlignment = true;
+				}
+			}
+			// backtrack only once all fragments got checked
+			if (this.needRedoColumnAlignment && this.fragmentIndex == this.fragmentCount-1) { // alignment too small
+
+//				if (CodeFormatterVisitor.DEBUG){
+//					System.out.println("ALIGNMENT TOO SMALL");
+//					System.out.println(this);
+//				}
+				this.needRedoColumnAlignment = false;
+				int relativeDepth = 0;
+				Alignment targetAlignment = this.scribe.memberAlignment;
+				while (targetAlignment != null){
+					if (targetAlignment == this){
+						throw new AlignmentException(AlignmentException.ALIGN_TOO_SMALL, relativeDepth);
+					}
+					targetAlignment = targetAlignment.enclosing;
+					relativeDepth++;
+				}
+			}
+		}
+	}
+		
+	public boolean couldBreak(){
+
+		if ((this.mode & M_NO_ALIGNMENT) != 0) {
+			return false;
+		}
+		int i;
+		switch(mode & SPLIT_MASK){
+
+			/*  # aligned fragment
+			 *  foo(
+			 *     #AAAAA, #BBBBB,
+			 *     #CCCC);
+			 */
+			case M_COMPACT_FIRST_BREAK_SPLIT : 
+				if (this.fragmentBreaks[0] == NONE) {
+					this.fragmentBreaks[0] = BREAK;
+					this.fragmentIndentations[0] = this.breakIndentationLevel;
+					return wasSplit = true;
+				}
+				i = this.fragmentIndex;
+				do {
+					if (this.fragmentBreaks[i] == NONE) {
+						this.fragmentBreaks[i] = BREAK;
+						this.fragmentIndentations[i] = this.breakIndentationLevel;
+						return wasSplit = true;
+					}
+				} while (--i >= 0);
+				break;
+			/*  # aligned fragment
+			 *  foo(#AAAAA, #BBBBB,
+			 *     #CCCC);
+			 */
+			case M_COMPACT_SPLIT : 
+				i = this.fragmentIndex;
+				do {
+					if (this.fragmentBreaks[i] == NONE) {
+						this.fragmentBreaks[i] = BREAK;
+						this.fragmentIndentations[i] = this.breakIndentationLevel;						
+						return wasSplit = true;
+					}
+				} while (--i >= 0);
+				break;
+
+			/*  # aligned fragment
+			 *  foo(
+			 *      #AAAAA,
+			 *          #BBBBB,
+			 *          #CCCC);
+			 */
+			case M_NEXT_SHIFTED_SPLIT :
+				if (this.fragmentBreaks[0] == NONE) {
+					this.fragmentBreaks[0] = BREAK;					
+					this.fragmentIndentations[0] = this.breakIndentationLevel;
+					for (i = 1; i < this.fragmentCount; i++){
+						this.fragmentBreaks[i] = BREAK;
+						this.fragmentIndentations[i] = this.shiftBreakIndentationLevel;
+					}
+					return wasSplit = true;
+				}
+				break;
+				
+			/*  # aligned fragment
+			 *  foo(
+			 *      #AAAAA,
+			 *      #BBBBB,
+			 *      #CCCC);
+			 */
+			case M_ONE_PER_LINE_SPLIT :
+				if (this.fragmentBreaks[0] == NONE) {
+					for (i = 0; i < this.fragmentCount; i++){
+						this.fragmentBreaks[i] = BREAK;
+						this.fragmentIndentations[i] = this.breakIndentationLevel;
+					}
+					return wasSplit = true;
+				}
+			/*  # aligned fragment
+			 *  foo(#AAAAA,
+			 *      #BBBBB,
+			 *      #CCCC);
+			 */
+			case M_NEXT_PER_LINE_SPLIT : 
+				if (this.fragmentBreaks[0] == NONE) {
+					if (this.fragmentCount > 1
+							&& this.fragmentBreaks[1] == NONE) {
+						if ((this.mode & M_INDENT_ON_COLUMN) != 0) {
+							this.fragmentIndentations[0] = this.breakIndentationLevel;
+						}
+						for (i = 1; i < this.fragmentCount; i++) {
+							this.fragmentBreaks[i] = BREAK;
+							this.fragmentIndentations[i] = this.breakIndentationLevel;
+						}
+						return wasSplit = true;
+					}
+				}
+				break;
+		}		
+		return false; // cannot split better
+	}
+	
+	public Alignment getAlignment(String targetName) {
+
+		if (targetName.equals(this.name)) return this;
+		if (this.enclosing == null) return null;
+		
+		return this.enclosing.getAlignment(targetName);
+	}
+		
+	// perform alignment effect for current fragment
+	public void performFragmentEffect(){
+		if ((this.mode & M_NO_ALIGNMENT) != 0) {
+			return;
+		}
+		
+		if (this.fragmentBreaks[this.fragmentIndex] == BREAK) {
+			this.scribe.printNewLine();
+		}
+		if (this.fragmentIndentations[this.fragmentIndex] > 0) {
+			this.scribe.indentationLevel = this.fragmentIndentations[this.fragmentIndex];
+		}
+	}					
+
+	// reset fragment indentation/break status	
+	public void reset() {
+
+		if (fragmentCount > 0){
+			this.fragmentIndentations = new int[this.fragmentCount];
+			this.fragmentBreaks = new int[this.fragmentCount];
+		}
+
+		// check for forced alignments
+		if ((mode & M_FORCE) != 0) {
+			couldBreak();
+		}		
+	}		
+
+	public void toFragmentsString(StringBuffer buffer){
+		// default implementation
+	}
+	
+	public String toString() {
+		StringBuffer buffer = new StringBuffer(10);
+		buffer
+			.append(getClass().getName())
+			.append(':')
+			.append("<name: ")	//$NON-NLS-1$
+			.append(this.name)
+			.append(">");	//$NON-NLS-1$
+		if (this.enclosing != null) {
+			buffer
+				.append("<enclosingName: ")	//$NON-NLS-1$
+				.append(this.enclosing.name)
+				.append('>');
+		}
+		buffer.append('\n');	
+
+		for (int i = 0; i < this.fragmentCount; i++){
+			buffer
+				.append(" - fragment ")	//$NON-NLS-1$
+				.append(i)
+				.append(": ")	//$NON-NLS-1$
+				.append("<break: ")	//$NON-NLS-1$
+				.append(this.fragmentBreaks[i] > 0 ? "YES" : "NO")	//$NON-NLS-1$	//$NON-NLS-2$
+				.append(">")	//$NON-NLS-1$
+				.append("<indent: ")	//$NON-NLS-1$
+				.append(this.fragmentIndentations[i])
+				.append(">\n");	//$NON-NLS-1$
+		}
+		buffer.append('\n');	
+		return buffer.toString();
+	}
+	
+	public void update() {
+		for (int i = 1; i < this.fragmentCount; i++){
+		    if (this.fragmentBreaks[i] == BREAK) {
+		        this.fragmentIndentations[i] = this.breakIndentationLevel;
+		    }
+		}
+	}
+}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/AlignmentException.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/AlignmentException.java
new file mode 100644
index 0000000..1b5969f
--- /dev/null
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/align/AlignmentException.java
Binary files differ
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/impl/FormatterOptions.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/impl/FormatterOptions.java
index 4ab9b65..c4ed89d 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/impl/FormatterOptions.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/impl/FormatterOptions.java
@@ -67,6 +67,7 @@
  * Initializing the formatter options with default settings
  */
 public FormatterOptions(){
+	// empty constructor
 }
 /** 
  * Initializing the formatter options with external settings
@@ -147,6 +148,7 @@
 				int val = Integer.parseInt(optionValue);
 				if (val >= 0) this.maxLineLength = val;
 			} catch(NumberFormatException e){
+				// should not happen
 			}
 		}
 		if(optionID.equals(OPTION_CompactAssignment)){
@@ -170,6 +172,7 @@
 				int val = Integer.parseInt(optionValue);
 				if (val > 0) this.tabSize = val;
 			} catch(NumberFormatException e){
+				// should not happen
 			}
 		}
 		if(optionID.equals(OPTION_InsertSpaceAfterCast)){
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/impl/SplitLine.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/impl/SplitLine.java
index e718611..821a051 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/impl/SplitLine.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/impl/SplitLine.java
@@ -12,8 +12,9 @@
 
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 
-/** Represents a split line: contains an operator and all substrings
-*/
+/**
+ * Represents a split line: contains an operator and all substrings
+ */
 public class SplitLine implements TerminalTokens{
 	public int[] operators; // the operator on which the string was split.
 	public String[] substrings;
@@ -39,7 +40,6 @@
  */
 public String toString() {
 	StringBuffer result=new StringBuffer();
-	String operatorString = new String();
 		
 	for (int i=0,max=substrings.length;i<max;i++){
 		int currentOperator = operators[i];
@@ -47,156 +47,157 @@
 		boolean placeOperatorAhead = currentOperator != TerminalTokens.TokenNameCOMMA && currentOperator != TerminalTokens.TokenNameSEMICOLON;
 		boolean placeOperatorBehind = currentOperator == TerminalTokens.TokenNameCOMMA || currentOperator == TerminalTokens.TokenNameSEMICOLON;
 		
-
-
-	switch (currentOperator){
-		case TokenNameextends:
-			operatorString="extends"; //$NON-NLS-1$
-			break;
-		case TokenNameimplements:
-			operatorString="implements"; //$NON-NLS-1$
-			break;
-		case TokenNamethrows:
-			operatorString="throws"; //$NON-NLS-1$
-			break;
-		case TokenNameSEMICOLON : // ;
-			operatorString=";"; //$NON-NLS-1$
-			break;
-		case TokenNameCOMMA : // ,
-			operatorString=","; //$NON-NLS-1$
-			break;
-		case TokenNameEQUAL : // =
-			operatorString="="; //$NON-NLS-1$
-			break;
-		case TokenNameAND_AND : // && (15.22)
-			operatorString="&&"; //$NON-NLS-1$
-			break;
-		case TokenNameOR_OR : // || (15.23)
-			operatorString="||"; //$NON-NLS-1$
-			break;
-		case TokenNameQUESTION : // ? (15.24)
-			operatorString="?"; //$NON-NLS-1$
-			break;
-
-		case TokenNameCOLON : // : (15.24)
-			operatorString=":"; //$NON-NLS-1$
-			break;
-		case TokenNameEQUAL_EQUAL : // == (15.20, 15.20.1, 15.20.2, 15.20.3)
-			operatorString="=="; //$NON-NLS-1$
-			break;
-
-		case TokenNameNOT_EQUAL : // != (15.20, 15.20.1, 15.20.2, 15.20.3)
-			operatorString="!="; //$NON-NLS-1$
-			break;
-
-		case TokenNameLESS : // < (15.19.1)
-			operatorString="<"; //$NON-NLS-1$
-			break;
-
-		case TokenNameLESS_EQUAL : // <= (15.19.1)
-			operatorString="<="; //$NON-NLS-1$
-			break;
-
-		case TokenNameGREATER : // > (15.19.1)
-			operatorString=">"; //$NON-NLS-1$
-			break;
-
-		case TokenNameGREATER_EQUAL : // >= (15.19.1)
-			operatorString=">="; //$NON-NLS-1$
-			break;
-
-		case TokenNameinstanceof : // instanceof
-			operatorString="instanceof"; //$NON-NLS-1$
-			break;
-		case TokenNamePLUS : // + (15.17, 15.17.2)
-			operatorString="+"; //$NON-NLS-1$
-			break;
-
-		case TokenNameMINUS : // - (15.17.2)
-			operatorString="-"; //$NON-NLS-1$
-			break;
-		case TokenNameMULTIPLY : // * (15.16.1)
-			operatorString="*"; //$NON-NLS-1$
-			break;
-
-		case TokenNameDIVIDE : // / (15.16.2)
-			operatorString="/"; //$NON-NLS-1$
-			break;
-
-		case TokenNameREMAINDER : // % (15.16.3)
-			operatorString="%"; //$NON-NLS-1$
-			break;
-		case TokenNameLEFT_SHIFT : // << (15.18)
-			operatorString="<<"; //$NON-NLS-1$
-			break;
-
-		case TokenNameRIGHT_SHIFT : // >> (15.18)
-			operatorString=">>"; //$NON-NLS-1$
-			break;
-
-		case TokenNameUNSIGNED_RIGHT_SHIFT : // >>> (15.18)
-			operatorString=">>>"; //$NON-NLS-1$
-			break;
-		case TokenNameAND : // & (15.21, 15.21.1, 15.21.2)
-			operatorString="&"; //$NON-NLS-1$
-			break;
-
-		case TokenNameOR : // | (15.21, 15.21.1, 15.21.2)
-			operatorString="|"; //$NON-NLS-1$
-			break;
-
-		case TokenNameXOR : // ^ (15.21, 15.21.1, 15.21.2)
-			operatorString="^"; //$NON-NLS-1$
-			break;
-		case TokenNameMULTIPLY_EQUAL : // *= (15.25.2)
-			operatorString="*="; //$NON-NLS-1$
-			break;
-
-		case TokenNameDIVIDE_EQUAL : // /= (15.25.2)
-			operatorString="/="; //$NON-NLS-1$
-			break;
-		case TokenNameREMAINDER_EQUAL : // %= (15.25.2)
-			operatorString="%="; //$NON-NLS-1$
-			break;
-
-		case TokenNamePLUS_EQUAL : // += (15.25.2)
-			operatorString="+="; //$NON-NLS-1$
-			break;
-
-		case TokenNameMINUS_EQUAL : // -= (15.25.2)
-			operatorString="-="; //$NON-NLS-1$
-			break;
-
-		case TokenNameLEFT_SHIFT_EQUAL : // <<= (15.25.2)
-			operatorString="<<="; //$NON-NLS-1$
-			break;
-
-		case TokenNameRIGHT_SHIFT_EQUAL : // >>= (15.25.2)
-			operatorString=">>="; //$NON-NLS-1$
-			break;
-
-		case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL : // >>>= (15.25.2)
-			operatorString=">>>="; //$NON-NLS-1$
-			break;
-
-		case TokenNameAND_EQUAL : // &= (15.25.2)
-			operatorString="&="; //$NON-NLS-1$
-			break;
-
-		case TokenNameXOR_EQUAL : // ^= (15.25.2)
-			operatorString="^="; //$NON-NLS-1$
-			break;
-
-		case TokenNameOR_EQUAL : // |= (15.25.2)
-			operatorString="|="; //$NON-NLS-1$
-			break;
-		case TokenNameDOT : // .
-			operatorString="."; //$NON-NLS-1$
-			break;
-
-		default:
-			operatorString=""; //$NON-NLS-1$
-	}
+		
+		
+		String operatorString = null;
+		switch (currentOperator){
+			case TokenNameextends:
+				operatorString="extends"; //$NON-NLS-1$
+				break;
+			case TokenNameimplements:
+				operatorString="implements"; //$NON-NLS-1$
+				break;
+			case TokenNamethrows:
+				operatorString="throws"; //$NON-NLS-1$
+				break;
+			case TokenNameSEMICOLON : // ;
+				operatorString=";"; //$NON-NLS-1$
+				break;
+			case TokenNameCOMMA : // ,
+				operatorString=","; //$NON-NLS-1$
+				break;
+			case TokenNameEQUAL : // =
+				operatorString="="; //$NON-NLS-1$
+				break;
+			case TokenNameAND_AND : // && (15.22)
+				operatorString="&&"; //$NON-NLS-1$
+				break;
+			case TokenNameOR_OR : // || (15.23)
+				operatorString="||"; //$NON-NLS-1$
+				break;
+			case TokenNameQUESTION : // ? (15.24)
+				operatorString="?"; //$NON-NLS-1$
+				break;
+				
+			case TokenNameCOLON : // : (15.24)
+				operatorString=":"; //$NON-NLS-1$
+				break;
+			case TokenNameEQUAL_EQUAL : // == (15.20, 15.20.1, 15.20.2, 15.20.3)
+				operatorString="=="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameNOT_EQUAL : // != (15.20, 15.20.1, 15.20.2, 15.20.3)
+				operatorString="!="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameLESS : // < (15.19.1)
+				operatorString="<"; //$NON-NLS-1$
+				break;
+				
+			case TokenNameLESS_EQUAL : // <= (15.19.1)
+				operatorString="<="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameGREATER : // > (15.19.1)
+				operatorString=">"; //$NON-NLS-1$
+				break;
+				
+			case TokenNameGREATER_EQUAL : // >= (15.19.1)
+				operatorString=">="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameinstanceof : // instanceof
+				operatorString="instanceof"; //$NON-NLS-1$
+				break;
+			case TokenNamePLUS : // + (15.17, 15.17.2)
+				operatorString="+"; //$NON-NLS-1$
+				break;
+				
+			case TokenNameMINUS : // - (15.17.2)
+				operatorString="-"; //$NON-NLS-1$
+				break;
+			case TokenNameMULTIPLY : // * (15.16.1)
+				operatorString="*"; //$NON-NLS-1$
+				break;
+				
+			case TokenNameDIVIDE : // / (15.16.2)
+				operatorString="/"; //$NON-NLS-1$
+				break;
+				
+			case TokenNameREMAINDER : // % (15.16.3)
+				operatorString="%"; //$NON-NLS-1$
+				break;
+			case TokenNameLEFT_SHIFT : // << (15.18)
+				operatorString="<<"; //$NON-NLS-1$
+				break;
+				
+			case TokenNameRIGHT_SHIFT : // >> (15.18)
+				operatorString=">>"; //$NON-NLS-1$
+				break;
+				
+			case TokenNameUNSIGNED_RIGHT_SHIFT : // >>> (15.18)
+				operatorString=">>>"; //$NON-NLS-1$
+				break;
+			case TokenNameAND : // & (15.21, 15.21.1, 15.21.2)
+				operatorString="&"; //$NON-NLS-1$
+				break;
+				
+			case TokenNameOR : // | (15.21, 15.21.1, 15.21.2)
+				operatorString="|"; //$NON-NLS-1$
+				break;
+				
+			case TokenNameXOR : // ^ (15.21, 15.21.1, 15.21.2)
+				operatorString="^"; //$NON-NLS-1$
+				break;
+			case TokenNameMULTIPLY_EQUAL : // *= (15.25.2)
+				operatorString="*="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameDIVIDE_EQUAL : // /= (15.25.2)
+				operatorString="/="; //$NON-NLS-1$
+				break;
+			case TokenNameREMAINDER_EQUAL : // %= (15.25.2)
+				operatorString="%="; //$NON-NLS-1$
+				break;
+				
+			case TokenNamePLUS_EQUAL : // += (15.25.2)
+				operatorString="+="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameMINUS_EQUAL : // -= (15.25.2)
+				operatorString="-="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameLEFT_SHIFT_EQUAL : // <<= (15.25.2)
+				operatorString="<<="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameRIGHT_SHIFT_EQUAL : // >>= (15.25.2)
+				operatorString=">>="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL : // >>>= (15.25.2)
+				operatorString=">>>="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameAND_EQUAL : // &= (15.25.2)
+				operatorString="&="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameXOR_EQUAL : // ^= (15.25.2)
+				operatorString="^="; //$NON-NLS-1$
+				break;
+				
+			case TokenNameOR_EQUAL : // |= (15.25.2)
+				operatorString="|="; //$NON-NLS-1$
+				break;
+			case TokenNameDOT : // .
+				operatorString="."; //$NON-NLS-1$
+				break;
+				
+			default:
+				operatorString=""; //$NON-NLS-1$
+		}
 		if (placeOperatorAhead){
 			result.append(operatorString);
 		}
diff --git a/org.eclipse.jdt.core/grammar/java_1_4.g b/org.eclipse.jdt.core/grammar/java_1_4.g
index 20ec4e6..0d5bd8a 100644
--- a/org.eclipse.jdt.core/grammar/java_1_4.g
+++ b/org.eclipse.jdt.core/grammar/java_1_4.g
@@ -1,7 +1,7 @@
 --main options

 %options ACTION, AN=JavaAction.java, GP=java, 

 %options FILE-PREFIX=java, ESCAPE=$, PREFIX=TokenName, OUTPUT-SIZE=125 ,

-%options NOGOTO-DEFAULT, SINGLE-PRODUCTIONS, LALR=1 , TABLE=TIME , 

+%options NOGOTO-DEFAULT, SINGLE-PRODUCTIONS, LALR=1 , TABLE, 

 

 --error recovering options.....

 %options ERROR_MAPS 

@@ -11,10 +11,14 @@
 %options TRACE=FULL ,

 %options VERBOSE

 

+%options DEFERRED

+%options NAMES=MAX

+%options SCOPES

+

 --Usefull macros helping reading/writing semantic actions

 $Define 

 $putCase 

-/.    case $rule_number : // System.out.println("$rule_text");  

+/.    case $rule_number : // System.out.println("$rule_text");  //$NON-NLS-1$

 		   ./

 

 $break

@@ -22,6 +26,9 @@
 			break ;

 ./

 

+$readableName 

+/.$rule_number=./

+

 -- here it starts really ------------------------------------------

 $Terminals

 

@@ -155,14 +162,12 @@
 

 Goal ::= '++' CompilationUnit

 Goal ::= '--' MethodBody

-Goal ::= '==' ConstructorBody

 -- Initializer

 Goal ::= '>>' StaticInitializer

 Goal ::= '>>' Initializer

 -- error recovery

 Goal ::= '>>>' Headers

 Goal ::= '*' BlockStatements

-Goal ::= '*' MethodPushModifiersHeader

 Goal ::= '*' CatchHeader

 -- JDOM

 Goal ::= '&&' FieldDeclaration

@@ -170,12 +175,12 @@
 Goal ::= '?' PackageDeclaration

 Goal ::= '+' TypeDeclaration

 Goal ::= '/' GenericMethodDeclaration

-Goal ::= '&' ClassBodyDeclaration

+Goal ::= '&' ClassBodyDeclarations

 -- code snippet

 Goal ::= '%' Expression

 -- completion parser

-Goal ::= '!' ConstructorBlockStatementsopt

 Goal ::= '~' BlockStatementsopt

+/:$readableName Goal:/

 

 Literal -> IntegerLiteral

 Literal -> LongLiteral

@@ -185,8 +190,10 @@
 Literal -> StringLiteral

 Literal -> null

 Literal -> BooleanLiteral

+/:$readableName Literal:/

 BooleanLiteral -> true

 BooleanLiteral -> false

+/:$readableName BooleanLiteral:/

 

 -------------------------------------------------------------

 -------------------------------------------------------------

@@ -195,10 +202,13 @@
 Type ::= PrimitiveType

  /.$putCase consumePrimitiveType(); $break ./

 Type -> ReferenceType

+/:$readableName Type:/

 

 PrimitiveType -> NumericType

+/:$readableName PrimitiveType:/

 NumericType -> IntegralType

 NumericType -> FloatingPointType

+/:$readableName NumericType:/

 

 PrimitiveType -> 'boolean'

 PrimitiveType -> 'void'

@@ -207,14 +217,17 @@
 IntegralType -> 'int'

 IntegralType -> 'long'

 IntegralType -> 'char'

+/:$readableName IntegralType:/

 FloatingPointType -> 'float'

 FloatingPointType -> 'double'

+/:$readableName FloatingPointType:/

 

 ReferenceType ::= ClassOrInterfaceType

 /.$putCase consumeReferenceType();  $break ./

 ReferenceType -> ArrayType -- here a push of dimensions is done, that explains the two previous push 0

-

+/:$readableName ReferenceType:/

 ClassOrInterfaceType -> Name

+/:$readableName Type:/

 

 --

 -- These rules have been rewritten to avoid some conflicts introduced

@@ -227,29 +240,36 @@
 

 ArrayType ::= PrimitiveType Dims

 ArrayType ::= Name Dims

+/:$readableName ArrayType:/

 

 ClassType -> ClassOrInterfaceType

-

+/:$readableName ClassType:/

 

 --------------------------------------------------------------

 --------------------------------------------------------------

 

 Name -> SimpleName

 Name -> QualifiedName

+/:$readableName Name:/

 

 SimpleName -> 'Identifier'

+/:$readableName SimpleName:/

 

 QualifiedName ::= Name '.' SimpleName 

 /.$putCase consumeQualifiedName(); $break ./

+/:$readableName QualifiedName:/

 

 CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt TypeDeclarationsopt

 /.$putCase consumeCompilationUnit(); $break ./

+/:$readableName CompilationUnit:/

 

 EnterCompilationUnit ::= $empty

 /.$putCase consumeEnterCompilationUnit(); $break ./

+/:$readableName EnterCompilationUnit:/

 

 Headers -> Header

 Headers ::= Headers Header

+/:$readableName Headers:/

 

 Header -> ImportDeclaration

 Header -> PackageDeclaration

@@ -260,38 +280,50 @@
 Header -> ConstructorHeader

 Header -> FieldDeclaration

 Header -> AllocationHeader

+Header -> ArrayCreationHeader 

+/:$readableName Header:/

 

 CatchHeader ::= 'catch' '(' FormalParameter ')' '{'

 /.$putCase consumeCatchHeader(); $break ./

+/:$readableName CatchHeader:/

 

 ImportDeclarations -> ImportDeclaration

 ImportDeclarations ::= ImportDeclarations ImportDeclaration 

 /.$putCase consumeImportDeclarations(); $break ./

+/:$readableName ImportDeclarations:/

 

 TypeDeclarations -> TypeDeclaration

 TypeDeclarations ::= TypeDeclarations TypeDeclaration

 /.$putCase consumeTypeDeclarations(); $break ./

+/:$readableName TypeDeclarations:/

 

 PackageDeclaration ::= PackageDeclarationName ';'

 /.$putCase  consumePackageDeclaration(); $break ./

+/:$readableName PackageDeclaration:/

 

 PackageDeclarationName ::= 'package' Name

 /.$putCase  consumePackageDeclarationName(); $break ./

+/:$readableName PackageDeclarationName:/

 

 ImportDeclaration -> SingleTypeImportDeclaration

 ImportDeclaration -> TypeImportOnDemandDeclaration

+/:$readableName ImportDeclaration:/

 

 SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'

 /.$putCase consumeSingleTypeImportDeclaration(); $break ./

+/:$readableName SingleTypeImportDeclaration:/

 			  

 SingleTypeImportDeclarationName ::= 'import' Name

 /.$putCase consumeSingleTypeImportDeclarationName(); $break ./

+/:$readableName SingleTypeImportDeclarationName:/

 			  

 TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName ';'

 /.$putCase consumeTypeImportOnDemandDeclaration(); $break ./

+/:$readableName TypeImportOnDemandDeclaration:/

 

 TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'

 /.$putCase consumeTypeImportOnDemandDeclarationName(); $break ./

+/:$readableName TypeImportOnDemandDeclarationName:/

 

 TypeDeclaration -> ClassDeclaration

 TypeDeclaration -> InterfaceDeclaration

@@ -300,11 +332,13 @@
 -- thus we decrement the number while it will be incremend.....

 TypeDeclaration ::= ';' 

 /. $putCase consumeEmptyTypeDeclaration(); $break ./

+/:$readableName TypeDeclaration:/

 

 --18.7 Only in the LALR(1) Grammar

 

 Modifiers ::= Modifier

 Modifiers ::= Modifiers Modifier

+/:$readableName Modifiers:/

 

 Modifier -> 'public' 

 Modifier -> 'protected'

@@ -317,6 +351,7 @@
 Modifier -> 'transient'

 Modifier -> 'volatile'

 Modifier -> 'strictfp'

+/:$readableName Modifier:/

 

 --18.8 Productions from 8: Class Declarations

 --ClassModifier ::=

@@ -327,31 +362,40 @@
 

 ClassDeclaration ::= ClassHeader ClassBody

 /.$putCase consumeClassDeclaration(); $break ./

+/:$readableName ClassDeclaration:/

 

 ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt

 /.$putCase consumeClassHeader(); $break ./

+/:$readableName ClassHeader:/

 

 ClassHeaderName ::= Modifiersopt 'class' 'Identifier'

 /.$putCase consumeClassHeaderName(); $break ./

+/:$readableName ClassHeaderName:/

 

 ClassHeaderExtends ::= 'extends' ClassType

 /.$putCase consumeClassHeaderExtends(); $break ./

+/:$readableName ClassHeaderExtends:/

 

 ClassHeaderImplements ::= 'implements' InterfaceTypeList

 /.$putCase consumeClassHeaderImplements(); $break ./

+/:$readableName ClassHeaderImplements:/

 

 InterfaceTypeList -> InterfaceType

 InterfaceTypeList ::= InterfaceTypeList ',' InterfaceType

 /.$putCase consumeInterfaceTypeList(); $break ./

+/:$readableName InterfaceTypeList:/

 

 InterfaceType ::= ClassOrInterfaceType

 /.$putCase consumeInterfaceType(); $break ./

+/:$readableName InterfaceType:/

 

 ClassBody ::= '{' ClassBodyDeclarationsopt '}'

+/:$readableName ClassBody:/

 

 ClassBodyDeclarations ::= ClassBodyDeclaration

 ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration

 /.$putCase consumeClassBodyDeclarations(); $break ./

+/:$readableName ClassBodyDeclarations:/

 

 ClassBodyDeclaration -> ClassMemberDeclaration

 ClassBodyDeclaration -> StaticInitializer

@@ -359,11 +403,14 @@
 --1.1 feature

 ClassBodyDeclaration ::= Diet NestedMethod Block

 /.$putCase consumeClassBodyDeclaration(); $break ./

+/:$readableName ClassBodyDeclaration:/

 Diet ::= $empty

 /.$putCase consumeDiet(); $break./

+/:$readableName Diet:/

 

 Initializer ::= Diet NestedMethod Block

 /.$putCase consumeClassBodyDeclaration(); $break ./

+/:$readableName Initializer:/

 

 ClassMemberDeclaration -> FieldDeclaration

 ClassMemberDeclaration -> MethodDeclaration

@@ -371,6 +418,7 @@
 ClassMemberDeclaration -> ClassDeclaration

 --1.1 feature

 ClassMemberDeclaration -> InterfaceDeclaration

+/:$readableName ClassMemberDeclaration:/

 

 -- Empty declarations are not valid Java ClassMemberDeclarations.

 -- However, since the current (2/14/97) Java compiler accepts them 

@@ -379,6 +427,7 @@
 

 GenericMethodDeclaration -> MethodDeclaration

 GenericMethodDeclaration -> ConstructorDeclaration

+/:$readableName GenericMethodDeclaration:/

 

 ClassMemberDeclaration ::= ';'

 /.$putCase consumeEmptyClassMemberDeclaration(); $break./

@@ -395,33 +444,43 @@
 

 FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'

 /.$putCase consumeFieldDeclaration(); $break ./

+/:$readableName FieldDeclaration:/

 

 VariableDeclarators -> VariableDeclarator 

 VariableDeclarators ::= VariableDeclarators ',' VariableDeclarator

 /.$putCase consumeVariableDeclarators(); $break ./

+/:$readableName VariableDeclarators:/

 

 VariableDeclarator ::= VariableDeclaratorId EnterVariable ExitVariableWithoutInitialization

 

 VariableDeclarator ::= VariableDeclaratorId EnterVariable '=' ForceNoDiet VariableInitializer RestoreDiet ExitVariableWithInitialization

+/:$readableName VariableDeclarator:/

 

 EnterVariable ::= $empty

 /.$putCase consumeEnterVariable(); $break ./

+/:$readableName EnterVariable:/

 

 ExitVariableWithInitialization ::= $empty

 /.$putCase consumeExitVariableWithInitialization(); $break ./

+/:$readableName ExitVariableWithInitialization:/

 

 ExitVariableWithoutInitialization ::= $empty

 /.$putCase consumeExitVariableWithoutInitialization(); $break ./

+/:$readableName ExitVariableWithoutInitialization:/

 

 ForceNoDiet ::= $empty

 /.$putCase consumeForceNoDiet(); $break ./

+/:$readableName ForceNoDiet:/

 RestoreDiet ::= $empty

 /.$putCase consumeRestoreDiet(); $break ./

+/:$readableName RestoreDiet:/

 

 VariableDeclaratorId ::= 'Identifier' Dimsopt

+/:$readableName VariableDeclaratorId:/

 

 VariableInitializer -> Expression

 VariableInitializer -> ArrayInitializer

+/:$readableName VariableInitializer:/

 

 --18.8.3 Productions from 8.4: Method Declarations

 --MethodModifier ::=

@@ -439,71 +498,78 @@
 MethodDeclaration ::= MethodHeader MethodBody 

 /.$putCase // set to true to consume a method with a body

   consumeMethodDeclaration(true);  $break ./

+/:$readableName MethodDeclaration:/

 

 AbstractMethodDeclaration ::= MethodHeader ';'

 /.$putCase // set to false to consume a method without body

   consumeMethodDeclaration(false); $break ./

+/:$readableName AbstractMethodDeclaration:/

 

 MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims MethodHeaderThrowsClauseopt

 /.$putCase consumeMethodHeader(); $break ./

-

-MethodPushModifiersHeader ::= MethodPushModifiersHeaderName MethodHeaderParameters MethodHeaderExtendedDims MethodHeaderThrowsClauseopt

-/.$putCase consumeMethodHeader(); $break ./

-

-MethodPushModifiersHeaderName ::= Modifiers Type PushModifiers 'Identifier' '(' 

-/.$putCase consumeMethodPushModifiersHeaderName(); $break ./

-

-MethodPushModifiersHeaderName ::= Type PushModifiers 'Identifier' '(' 

-/.$putCase consumeMethodPushModifiersHeaderName(); $break ./

+/:$readableName MethodHeader:/

 

 MethodHeaderName ::= Modifiersopt Type 'Identifier' '('

 /.$putCase consumeMethodHeaderName(); $break ./

+/:$readableName MethodHeaderName:/

 

 MethodHeaderParameters ::= FormalParameterListopt ')'

 /.$putCase consumeMethodHeaderParameters(); $break ./

+/:$readableName MethodHeaderParameters:/

 

 MethodHeaderExtendedDims ::= Dimsopt

 /.$putCase consumeMethodHeaderExtendedDims(); $break ./

+/:$readableName MethodHeaderExtendedDims:/

 

 MethodHeaderThrowsClause ::= 'throws' ClassTypeList

 /.$putCase consumeMethodHeaderThrowsClause(); $break ./

+/:$readableName MethodHeaderThrowsClause:/

 

 ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt

 /.$putCase consumeConstructorHeader(); $break ./

+/:$readableName ConstructorHeader:/

 

 ConstructorHeaderName ::=  Modifiersopt 'Identifier' '('

 /.$putCase consumeConstructorHeaderName(); $break ./

+/:$readableName ConstructorHeaderName:/

 

 FormalParameterList -> FormalParameter

 FormalParameterList ::= FormalParameterList ',' FormalParameter

 /.$putCase consumeFormalParameterList(); $break ./

+/:$readableName FormalParameterList:/

 

 --1.1 feature

 FormalParameter ::= Modifiersopt Type VariableDeclaratorId

 /.$putCase // the boolean is used to know if the modifiers should be reset

  	consumeFormalParameter(); $break ./

+/:$readableName FormalParameter:/

 

 ClassTypeList -> ClassTypeElt

 ClassTypeList ::= ClassTypeList ',' ClassTypeElt

 /.$putCase consumeClassTypeList(); $break ./

+/:$readableName ClassTypeList:/

 

 ClassTypeElt ::= ClassType

 /.$putCase consumeClassTypeElt(); $break ./

-

+/:$readableName ClassType:/

 

 MethodBody ::= NestedMethod '{' BlockStatementsopt '}' 

 /.$putCase consumeMethodBody(); $break ./

+/:$readableName MethodBody:/

 

 NestedMethod ::= $empty

 /.$putCase consumeNestedMethod(); $break ./

+/:$readableName NestedMethod:/

 

 --18.8.4 Productions from 8.5: Static Initializers

 

 StaticInitializer ::=  StaticOnly Block

 /.$putCase consumeStaticInitializer(); $break./

+/:$readableName StaticInitializer:/

 

 StaticOnly ::= 'static'

 /.$putCase consumeStaticOnly(); $break ./

+/:$readableName StaticOnly:/

 

 --18.8.5 Productions from 8.6: Constructor Declarations

 --ConstructorModifier ::=

@@ -512,27 +578,16 @@
 --    | 'private'

 --

 --

-ConstructorDeclaration ::= ConstructorHeader ConstructorBody

+ConstructorDeclaration ::= ConstructorHeader MethodBody

 /.$putCase consumeConstructorDeclaration() ; $break ./ 

 

 -- These rules are added to be able to parse constructors with no body

 ConstructorDeclaration ::= ConstructorHeader ';'

 /.$putCase consumeInvalidConstructorDeclaration() ; $break ./ 

+/:$readableName ConstructorDeclaration:/

 

 -- the rules ExplicitConstructorInvocationopt has been expanded

 -- in the rule below in order to make the grammar lalr(1).

--- ConstructorBody ::= '{' ExplicitConstructorInvocationopt BlockStatementsopt '}'

--- Other inlining has occured into the next rule too....

-

-ConstructorBody ::= NestedMethod  '{' ConstructorBlockStatementsopt '}'

-/.$putCase consumeConstructorBody(); $break ./

-

-ConstructorBlockStatementsopt -> BlockStatementsopt

-

-ConstructorBlockStatementsopt -> ExplicitConstructorInvocation

-

-ConstructorBlockStatementsopt ::= ExplicitConstructorInvocation BlockStatements

-/.$putCase  consumeConstructorBlockStatements(); $break ./

 

 ExplicitConstructorInvocation ::= 'this' '(' ArgumentListopt ')' ';'

 /.$putCase consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.This); $break ./

@@ -555,6 +610,7 @@
 --1.1 feature

 ExplicitConstructorInvocation ::= Name '.' 'this' '(' ArgumentListopt ')' ';'

 /.$putCase consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.This); $break ./

+/:$readableName ExplicitConstructorInvocation:/

 

 --18.9 Productions from 9: Interface Declarations

 

@@ -565,52 +621,66 @@
 --

 InterfaceDeclaration ::= InterfaceHeader InterfaceBody

 /.$putCase consumeInterfaceDeclaration(); $break ./

+/:$readableName InterfaceDeclaration:/

 

 InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt

 /.$putCase consumeInterfaceHeader(); $break ./

+/:$readableName InterfaceHeader:/

 

 InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'

 /.$putCase consumeInterfaceHeaderName(); $break ./

+/:$readableName InterfaceHeaderName:/

 

 -- This rule will be used to accept inner local interface and then report a relevant error message

 InvalidInterfaceDeclaration -> InterfaceHeader InterfaceBody

+/:$readableName InvalidInterfaceDeclaration:/

 

 InterfaceHeaderExtends ::= 'extends' InterfaceTypeList

 /.$putCase consumeInterfaceHeaderExtends(); $break ./

+/:$readableName InterfaceHeaderExtends:/

 

 InterfaceBody ::= '{' InterfaceMemberDeclarationsopt '}' 

+/:$readableName InterfaceBody:/

 

 InterfaceMemberDeclarations -> InterfaceMemberDeclaration

 InterfaceMemberDeclarations ::= InterfaceMemberDeclarations InterfaceMemberDeclaration

 /.$putCase consumeInterfaceMemberDeclarations(); $break ./

+/:$readableName InterfaceMemberDeclarations:/

 

 --same as for class members

 InterfaceMemberDeclaration ::= ';'

 /.$putCase consumeEmptyInterfaceMemberDeclaration(); $break ./

+/:$readableName InterfaceMemberDeclaration:/

 

 -- This rule is added to be able to parse non abstract method inside interface and then report a relevent error message

 InvalidMethodDeclaration -> MethodHeader MethodBody

+/:$readableName InvalidMethodDeclaration:/

 

 InterfaceMemberDeclaration -> ConstantDeclaration

 InterfaceMemberDeclaration ::= InvalidMethodDeclaration

 /.$putCase ignoreMethodBody(); $break ./

+/:$readableName InterfaceMemberDeclaration:/

 

 -- These rules are added to be able to parse constructors inside interface and then report a relevent error message

-InvalidConstructorDeclaration ::= ConstructorHeader ConstructorBody

+InvalidConstructorDeclaration ::= ConstructorHeader MethodBody

 /.$putCase ignoreInvalidConstructorDeclaration(true);  $break ./

 

 InvalidConstructorDeclaration ::= ConstructorHeader ';'

 /.$putCase ignoreInvalidConstructorDeclaration(false);  $break ./

+/:$readableName InvalidConstructorDeclaration:/

 

 InterfaceMemberDeclaration -> AbstractMethodDeclaration

 InterfaceMemberDeclaration -> InvalidConstructorDeclaration

- 

+/:$readableName InterfaceMemberDeclaration:/

+

 --1.1 feature

 InterfaceMemberDeclaration -> ClassDeclaration

 --1.1 feature

 InterfaceMemberDeclaration -> InterfaceDeclaration

+/:$readableName InterfaceMemberDeclaration:/

 

 ConstantDeclaration -> FieldDeclaration

+/:$readableName ConstantDeclaration:/

 

 ArrayInitializer ::= '{' ,opt '}'

 /.$putCase consumeEmptyArrayInitializer(); $break ./

@@ -618,19 +688,25 @@
 /.$putCase consumeArrayInitializer(); $break ./

 ArrayInitializer ::= '{' VariableInitializers , '}'

 /.$putCase consumeArrayInitializer(); $break ./

+/:$readableName ArrayInitializer:/

 

 VariableInitializers ::= VariableInitializer

 VariableInitializers ::= VariableInitializers ',' VariableInitializer

 /.$putCase consumeVariableInitializers(); $break ./

+/:$readableName VariableInitializers:/

 

 Block ::= OpenBlock '{' BlockStatementsopt '}'

 /.$putCase consumeBlock(); $break ./

+/:$readableName Block:/

+

 OpenBlock ::= $empty

 /.$putCase consumeOpenBlock() ; $break ./

+/:$readableName OpenBlock:/

 

 BlockStatements -> BlockStatement

 BlockStatements ::= BlockStatements BlockStatement

 /.$putCase consumeBlockStatements() ; $break ./

+/:$readableName BlockStatements:/

 

 BlockStatement -> LocalVariableDeclarationStatement

 BlockStatement -> Statement

@@ -638,9 +714,11 @@
 BlockStatement -> ClassDeclaration

 BlockStatement ::= InvalidInterfaceDeclaration

 /.$putCase ignoreInterfaceDeclaration(); $break ./

+/:$readableName BlockStatement:/

 

 LocalVariableDeclarationStatement ::= LocalVariableDeclaration ';'

 /.$putCase consumeLocalVariableDeclarationStatement(); $break ./

+/:$readableName LocalVariableDeclarationStatement:/

 

 LocalVariableDeclaration ::= Type PushModifiers VariableDeclarators

 /.$putCase consumeLocalVariableDeclaration(); $break ./

@@ -652,9 +730,11 @@
 

 LocalVariableDeclaration ::= Modifiers Type PushModifiers VariableDeclarators

 /.$putCase consumeLocalVariableDeclaration(); $break ./

+/:$readableName LocalVariableDeclaration:/

 

 PushModifiers ::= $empty

 /.$putCase consumePushModifiers(); $break ./

+/:$readableName PushModifiers:/

 

 Statement -> StatementWithoutTrailingSubstatement

 Statement -> LabeledStatement

@@ -662,12 +742,14 @@
 Statement -> IfThenElseStatement

 Statement -> WhileStatement

 Statement -> ForStatement

+/:$readableName Statement:/

 

 StatementNoShortIf -> StatementWithoutTrailingSubstatement

 StatementNoShortIf -> LabeledStatementNoShortIf

 StatementNoShortIf -> IfThenElseStatementNoShortIf

 StatementNoShortIf -> WhileStatementNoShortIf

 StatementNoShortIf -> ForStatementNoShortIf

+/:$readableName Statement:/

 

 StatementWithoutTrailingSubstatement -> AssertStatement

 StatementWithoutTrailingSubstatement -> Block

@@ -681,18 +763,24 @@
 StatementWithoutTrailingSubstatement -> SynchronizedStatement

 StatementWithoutTrailingSubstatement -> ThrowStatement

 StatementWithoutTrailingSubstatement -> TryStatement

+/:$readableName Statement:/

 

 EmptyStatement ::= ';'

 /.$putCase consumeEmptyStatement(); $break ./

+/:$readableName EmptyStatement:/

 

 LabeledStatement ::= 'Identifier' ':' Statement

 /.$putCase consumeStatementLabel() ; $break ./

+/:$readableName LabeledStatement:/

 

 LabeledStatementNoShortIf ::= 'Identifier' ':' StatementNoShortIf

 /.$putCase consumeStatementLabel() ; $break ./

+/:$readableName LabeledStatement:/

 

 ExpressionStatement ::= StatementExpression ';'

 /. $putCase consumeExpressionStatement(); $break ./

+ExpressionStatement ::= ExplicitConstructorInvocation

+/:$readableName Statement:/

 

 StatementExpression ::= Assignment

 StatementExpression ::= PreIncrementExpression

@@ -701,18 +789,23 @@
 StatementExpression ::= PostDecrementExpression

 StatementExpression ::= MethodInvocation

 StatementExpression ::= ClassInstanceCreationExpression

+/:$readableName Expression:/

 

 IfThenStatement ::=  'if' '(' Expression ')' Statement

 /.$putCase consumeStatementIfNoElse(); $break ./

+/:$readableName IfStatement:/

 

 IfThenElseStatement ::=  'if' '(' Expression ')' StatementNoShortIf 'else' Statement

 /.$putCase consumeStatementIfWithElse(); $break ./

+/:$readableName IfStatement:/

 

 IfThenElseStatementNoShortIf ::=  'if' '(' Expression ')' StatementNoShortIf 'else' StatementNoShortIf

 /.$putCase consumeStatementIfWithElse(); $break ./

+/:$readableName IfStatement:/

 

-SwitchStatement ::= 'switch' OpenBlock '(' Expression ')' SwitchBlock

+SwitchStatement ::= 'switch' '(' Expression ')' OpenBlock SwitchBlock

 /.$putCase consumeStatementSwitch() ; $break ./

+/:$readableName SwitchStatement:/

 

 SwitchBlock ::= '{' '}'

 /.$putCase consumeEmptySwitchBlock() ; $break ./

@@ -721,48 +814,63 @@
 SwitchBlock ::= '{' SwitchLabels '}'

 SwitchBlock ::= '{' SwitchBlockStatements SwitchLabels '}'

 /.$putCase consumeSwitchBlock() ; $break ./

+/:$readableName SwitchBlock:/

 

 SwitchBlockStatements -> SwitchBlockStatement

 SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement

 /.$putCase consumeSwitchBlockStatements() ; $break ./

+/:$readableName SwitchBlockStatements:/

 

 SwitchBlockStatement ::= SwitchLabels BlockStatements

 /.$putCase consumeSwitchBlockStatement() ; $break ./

+/:$readableName SwitchBlockStatement:/

+

 

 SwitchLabels -> SwitchLabel

 SwitchLabels ::= SwitchLabels SwitchLabel

 /.$putCase consumeSwitchLabels() ; $break ./

+/:$readableName SwitchLabels:/

 

 SwitchLabel ::= 'case' ConstantExpression ':'

 /. $putCase consumeCaseLabel(); $break ./

 

 SwitchLabel ::= 'default' ':'

 /. $putCase consumeDefaultLabel(); $break ./

+/:$readableName SwitchLabel:/

 

 WhileStatement ::= 'while' '(' Expression ')' Statement

 /.$putCase consumeStatementWhile() ; $break ./

+/:$readableName WhileStatement:/

 

 WhileStatementNoShortIf ::= 'while' '(' Expression ')' StatementNoShortIf

 /.$putCase consumeStatementWhile() ; $break ./

+/:$readableName WhileStatement:/

 

 DoStatement ::= 'do' Statement 'while' '(' Expression ')' ';'

 /.$putCase consumeStatementDo() ; $break ./

+/:$readableName DoStatement:/

 

 ForStatement ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' Statement

 /.$putCase consumeStatementFor() ; $break ./

+/:$readableName ForStatement:/

+

 ForStatementNoShortIf ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' StatementNoShortIf

 /.$putCase consumeStatementFor() ; $break ./

+/:$readableName ForStatement:/

 

 --the minus one allows to avoid a stack-to-stack transfer

 ForInit ::= StatementExpressionList

 /.$putCase consumeForInit() ; $break ./

 ForInit -> LocalVariableDeclaration

+/:$readableName ForInit:/

 

 ForUpdate -> StatementExpressionList

+/:$readableName ForUpdate:/

 

 StatementExpressionList -> StatementExpression

 StatementExpressionList ::= StatementExpressionList ',' StatementExpression

 /.$putCase consumeStatementExpressionList() ; $break ./

+/:$readableName StatementExpressionList:/

 

 -- 1.4 feature

 AssertStatement ::= 'assert' Expression ';'

@@ -770,57 +878,78 @@
 

 AssertStatement ::= 'assert' Expression ':' Expression ';'

 /.$putCase consumeAssertStatement() ; $break ./

-          

+/:$readableName AssertStatement:/

+

 BreakStatement ::= 'break' ';'

 /.$putCase consumeStatementBreak() ; $break ./

 

 BreakStatement ::= 'break' Identifier ';'

 /.$putCase consumeStatementBreakWithLabel() ; $break ./

+/:$readableName BreakStatement:/

 

 ContinueStatement ::= 'continue' ';'

 /.$putCase consumeStatementContinue() ; $break ./

 

 ContinueStatement ::= 'continue' Identifier ';'

 /.$putCase consumeStatementContinueWithLabel() ; $break ./

+/:$readableName ContinueStatement:/

 

 ReturnStatement ::= 'return' Expressionopt ';'

 /.$putCase consumeStatementReturn() ; $break ./

+/:$readableName ReturnStatement:/

 

 ThrowStatement ::= 'throw' Expression ';'

 /.$putCase consumeStatementThrow();

 $break ./

+/:$readableName ThrowStatement:/

 

 SynchronizedStatement ::= OnlySynchronized '(' Expression ')'    Block

 /.$putCase consumeStatementSynchronized(); $break ./

+/:$readableName SynchronizedStatement:/

+

 OnlySynchronized ::= 'synchronized'

 /.$putCase consumeOnlySynchronized(); $break ./

+/:$readableName OnlySynchronized:/

 

-

-TryStatement ::= 'try'    Block Catches

+TryStatement ::= 'try' TryBlock Catches

 /.$putCase consumeStatementTry(false); $break ./

-TryStatement ::= 'try'    Block Catchesopt Finally

+TryStatement ::= 'try' TryBlock Catchesopt Finally

 /.$putCase consumeStatementTry(true); $break ./

+/:$readableName TryStatement:/

+

+TryBlock ::= Block ExitTryBlock

+/:$readableName Block:/

+

+ExitTryBlock ::= $empty

+/.$putCase consumeExitTryBlock(); $break ./

+/:$readableName ExitTryBlock:/

 

 Catches -> CatchClause

 Catches ::= Catches CatchClause

 /.$putCase consumeCatches(); $break ./

+/:$readableName Catches:/

 

 CatchClause ::= 'catch' '(' FormalParameter ')'    Block

 /.$putCase consumeStatementCatch() ; $break ./

+/:$readableName CatchClause:/

 

 Finally ::= 'finally'    Block

+/:$readableName Finally:/

 

 --18.12 Productions from 14: Expressions

 

 --for source positionning purpose

 PushLPAREN ::= '('

 /.$putCase consumeLeftParen(); $break ./

+/:$readableName (:/

 PushRPAREN ::= ')'

 /.$putCase consumeRightParen(); $break ./

+/:$readableName ):/

 

 Primary -> PrimaryNoNewArray

 Primary -> ArrayCreationWithArrayInitializer

 Primary -> ArrayCreationWithoutArrayInitializer

+/:$readableName Expression:/

 

 PrimaryNoNewArray -> Literal

 PrimaryNoNewArray ::= 'this'

@@ -852,7 +981,7 @@
 

 PrimaryNoNewArray -> MethodInvocation

 PrimaryNoNewArray -> ArrayAccess

-

+/:$readableName Expression:/

 --1.1 feature

 --

 -- In Java 1.0 a ClassBody could not appear at all in a

@@ -861,6 +990,7 @@
 

 AllocationHeader ::= 'new' ClassType '(' ArgumentListopt ')'

 /.$putCase consumeAllocationHeader(); $break ./

+/:$readableName AllocationHeader:/

 

 ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt

 /.$putCase consumeClassInstanceCreationExpression(); $break ./

@@ -872,26 +1002,40 @@
 --1.1 feature

 ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt

 /.$putCase consumeClassInstanceCreationExpressionQualified() ; $break ./

+/:$readableName ClassInstanceCreationExpression:/

 

 ClassInstanceCreationExpressionName ::= Name '.'

 /.$putCase consumeClassInstanceCreationExpressionName() ; $break ./

+/:$readableName ClassInstanceCreationExpressionName:/

 

 ClassBodyopt ::= $empty --test made using null as contents

 /.$putCase consumeClassBodyopt(); $break ./

 ClassBodyopt ::= EnterAnonymousClassBody ClassBody

+/:$readableName ClassBody:/

 

 EnterAnonymousClassBody ::= $empty

 /.$putCase consumeEnterAnonymousClassBody(); $break ./

+/:$readableName EnterAnonymousClassBody:/

 

 ArgumentList ::= Expression

 ArgumentList ::= ArgumentList ',' Expression

 /.$putCase consumeArgumentList(); $break ./

+/:$readableName ArgumentList:/

+

+ArrayCreationHeader ::= 'new' PrimitiveType DimWithOrWithOutExprs

+/.$putCase consumeArrayCreationHeader(); $break ./

+

+ArrayCreationHeader ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs

+/.$putCase consumeArrayCreationHeader(); $break ./

+/:$readableName ArrayCreationHeader:/

 

 ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs

 /.$putCase consumeArrayCreationExpressionWithoutInitializer(); $break ./

+/:$readableName ArrayCreationWithoutArrayInitializer:/

 

 ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer

 /.$putCase consumeArrayCreationExpressionWithInitializer(); $break ./

+/:$readableName ArrayCreationWithArrayInitializer:/

 

 ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs

 /.$putCase consumeArrayCreationExpressionWithoutInitializer(); $break ./

@@ -902,24 +1046,30 @@
 DimWithOrWithOutExprs ::= DimWithOrWithOutExpr

 DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr

 /.$putCase consumeDimWithOrWithOutExprs(); $break ./

+/:$readableName Dimensions:/

 

 DimWithOrWithOutExpr ::= '[' Expression ']'

 DimWithOrWithOutExpr ::= '[' ']'

 /. $putCase consumeDimWithOrWithOutExpr(); $break ./

+/:$readableName Dimension:/

 -- -----------------------------------------------

 

 Dims ::= DimsLoop

 /. $putCase consumeDims(); $break ./

+/:$readableName Dimensions:/

 DimsLoop -> OneDimLoop

 DimsLoop ::= DimsLoop OneDimLoop

+/:$readableName Dimensions:/

 OneDimLoop ::= '[' ']'

 /. $putCase consumeOneDimLoop(); $break ./

+/:$readableName Dimension:/

 

 FieldAccess ::= Primary '.' 'Identifier'

 /.$putCase consumeFieldAccess(false); $break ./

 

 FieldAccess ::= 'super' '.' 'Identifier'

 /.$putCase consumeFieldAccess(true); $break ./

+/:$readableName FieldAccess:/

 

 MethodInvocation ::= Name '(' ArgumentListopt ')'

 /.$putCase consumeMethodInvocationName(); $break ./

@@ -929,6 +1079,7 @@
 

 MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'

 /.$putCase consumeMethodInvocationSuper(); $break ./

+/:$readableName MethodInvocation:/

 

 ArrayAccess ::= Name '[' Expression ']'

 /.$putCase consumeArrayAccess(true); $break ./

@@ -936,43 +1087,52 @@
 /.$putCase consumeArrayAccess(false); $break ./

 ArrayAccess ::= ArrayCreationWithArrayInitializer '[' Expression ']'

 /.$putCase consumeArrayAccess(false); $break ./

+/:$readableName ArrayAccess:/

 

 PostfixExpression -> Primary

 PostfixExpression ::= Name

 /.$putCase consumePostfixExpression(); $break ./

 PostfixExpression -> PostIncrementExpression

 PostfixExpression -> PostDecrementExpression

+/:$readableName Expression:/

 

 PostIncrementExpression ::= PostfixExpression '++'

-/.$putCase consumeUnaryExpression(OperatorExpression.PLUS,true); $break ./

+/.$putCase consumeUnaryExpression(OperatorIds.PLUS,true); $break ./

+/:$readableName PostIncrementExpression:/

 

 PostDecrementExpression ::= PostfixExpression '--'

-/.$putCase consumeUnaryExpression(OperatorExpression.MINUS,true); $break ./

+/.$putCase consumeUnaryExpression(OperatorIds.MINUS,true); $break ./

+/:$readableName PostDecrementExpression:/

 

 --for source managment purpose

 PushPosition ::= $empty

  /.$putCase consumePushPosition(); $break ./

+/:$readableName PushPosition:/

 

 UnaryExpression -> PreIncrementExpression

 UnaryExpression -> PreDecrementExpression

 UnaryExpression ::= '+' PushPosition UnaryExpression

-/.$putCase consumeUnaryExpression(OperatorExpression.PLUS); $break ./

+/.$putCase consumeUnaryExpression(OperatorIds.PLUS); $break ./

 UnaryExpression ::= '-' PushPosition UnaryExpression

-/.$putCase consumeUnaryExpression(OperatorExpression.MINUS); $break ./

+/.$putCase consumeUnaryExpression(OperatorIds.MINUS); $break ./

 UnaryExpression -> UnaryExpressionNotPlusMinus

+/:$readableName Expression:/

 

 PreIncrementExpression ::= '++' PushPosition UnaryExpression

-/.$putCase consumeUnaryExpression(OperatorExpression.PLUS,false); $break ./

+/.$putCase consumeUnaryExpression(OperatorIds.PLUS,false); $break ./

+/:$readableName PreIncrementExpression:/

 

 PreDecrementExpression ::= '--' PushPosition UnaryExpression

-/.$putCase consumeUnaryExpression(OperatorExpression.MINUS,false); $break ./

+/.$putCase consumeUnaryExpression(OperatorIds.MINUS,false); $break ./

+/:$readableName PreDecrementExpression:/

 

 UnaryExpressionNotPlusMinus -> PostfixExpression

 UnaryExpressionNotPlusMinus ::= '~' PushPosition UnaryExpression

-/.$putCase consumeUnaryExpression(OperatorExpression.TWIDDLE); $break ./

+/.$putCase consumeUnaryExpression(OperatorIds.TWIDDLE); $break ./

 UnaryExpressionNotPlusMinus ::= '!' PushPosition UnaryExpression

-/.$putCase consumeUnaryExpression(OperatorExpression.NOT); $break ./

+/.$putCase consumeUnaryExpression(OperatorIds.NOT); $break ./

 UnaryExpressionNotPlusMinus -> CastExpression

+/:$readableName Expression:/

 

 CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN InsideCastExpression UnaryExpression

 /.$putCase consumeCastExpression(); $break ./

@@ -981,84 +1141,101 @@
 -- Expression is here only in order to make the grammar LL1

 CastExpression ::= PushLPAREN Expression PushRPAREN InsideCastExpressionLL1 UnaryExpressionNotPlusMinus

 /.$putCase consumeCastExpressionLL1(); $break ./

+/:$readableName CastExpression:/

 

 InsideCastExpression ::= $empty

 /.$putCase consumeInsideCastExpression(); $break ./

+/:$readableName InsideCastExpression:/

 InsideCastExpressionLL1 ::= $empty

 /.$putCase consumeInsideCastExpressionLL1(); $break ./

+/:$readableName InsideCastExpression:/

 

 MultiplicativeExpression -> UnaryExpression

 MultiplicativeExpression ::= MultiplicativeExpression '*' UnaryExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.MULTIPLY); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.MULTIPLY); $break ./

 MultiplicativeExpression ::= MultiplicativeExpression '/' UnaryExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.DIVIDE); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.DIVIDE); $break ./

 MultiplicativeExpression ::= MultiplicativeExpression '%' UnaryExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.REMAINDER); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.REMAINDER); $break ./

+/:$readableName Expression:/

 

 AdditiveExpression -> MultiplicativeExpression

 AdditiveExpression ::= AdditiveExpression '+' MultiplicativeExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.PLUS); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.PLUS); $break ./

 AdditiveExpression ::= AdditiveExpression '-' MultiplicativeExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.MINUS); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.MINUS); $break ./

+/:$readableName Expression:/

 

 ShiftExpression -> AdditiveExpression

 ShiftExpression ::= ShiftExpression '<<'  AdditiveExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.LEFT_SHIFT); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.LEFT_SHIFT); $break ./

 ShiftExpression ::= ShiftExpression '>>'  AdditiveExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.RIGHT_SHIFT); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.RIGHT_SHIFT); $break ./

 ShiftExpression ::= ShiftExpression '>>>' AdditiveExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.UNSIGNED_RIGHT_SHIFT); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT); $break ./

+/:$readableName Expression:/

 

 RelationalExpression -> ShiftExpression

 RelationalExpression ::= RelationalExpression '<'  ShiftExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.LESS); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.LESS); $break ./

 RelationalExpression ::= RelationalExpression '>'  ShiftExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.GREATER); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.GREATER); $break ./

 RelationalExpression ::= RelationalExpression '<=' ShiftExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.LESS_EQUAL); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.LESS_EQUAL); $break ./

 RelationalExpression ::= RelationalExpression '>=' ShiftExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.GREATER_EQUAL); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.GREATER_EQUAL); $break ./

 RelationalExpression ::= RelationalExpression 'instanceof' ReferenceType

-/.$putCase consumeInstanceOfExpression(OperatorExpression.INSTANCEOF); $break ./

+/.$putCase consumeInstanceOfExpression(OperatorIds.INSTANCEOF); $break ./

+/:$readableName Expression:/

 

 EqualityExpression -> RelationalExpression

 EqualityExpression ::= EqualityExpression '==' RelationalExpression

-/.$putCase consumeEqualityExpression(OperatorExpression.EQUAL_EQUAL); $break ./

+/.$putCase consumeEqualityExpression(OperatorIds.EQUAL_EQUAL); $break ./

 EqualityExpression ::= EqualityExpression '!=' RelationalExpression

-/.$putCase consumeEqualityExpression(OperatorExpression.NOT_EQUAL); $break ./

+/.$putCase consumeEqualityExpression(OperatorIds.NOT_EQUAL); $break ./

+/:$readableName Expression:/

 

 AndExpression -> EqualityExpression

 AndExpression ::= AndExpression '&' EqualityExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.AND); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.AND); $break ./

+/:$readableName Expression:/

 

 ExclusiveOrExpression -> AndExpression

 ExclusiveOrExpression ::= ExclusiveOrExpression '^' AndExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.XOR); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.XOR); $break ./

+/:$readableName Expression:/

 

 InclusiveOrExpression -> ExclusiveOrExpression

 InclusiveOrExpression ::= InclusiveOrExpression '|' ExclusiveOrExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.OR); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.OR); $break ./

+/:$readableName Expression:/

 

 ConditionalAndExpression -> InclusiveOrExpression

 ConditionalAndExpression ::= ConditionalAndExpression '&&' InclusiveOrExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.AND_AND); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.AND_AND); $break ./

+/:$readableName Expression:/

 

 ConditionalOrExpression -> ConditionalAndExpression

 ConditionalOrExpression ::= ConditionalOrExpression '||' ConditionalAndExpression

-/.$putCase consumeBinaryExpression(OperatorExpression.OR_OR); $break ./

+/.$putCase consumeBinaryExpression(OperatorIds.OR_OR); $break ./

+/:$readableName Expression:/

 

 ConditionalExpression -> ConditionalOrExpression

 ConditionalExpression ::= ConditionalOrExpression '?' Expression ':' ConditionalExpression

-/.$putCase consumeConditionalExpression(OperatorExpression.QUESTIONCOLON) ; $break ./

+/.$putCase consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ; $break ./

+/:$readableName Expression:/

 

 AssignmentExpression -> ConditionalExpression

 AssignmentExpression -> Assignment

+/:$readableName Expression:/

 

 Assignment ::= PostfixExpression AssignmentOperator AssignmentExpression

 /.$putCase consumeAssignment(); $break ./

+/:$readableName Assignment:/

 

 -- this rule is added to parse an array initializer in a assigment and then report a syntax error knowing the exact senario

 InvalidArrayInitializerAssignement ::= PostfixExpression AssignmentOperator ArrayInitializer

+/:$readableName ArrayInitializerAssignement:/

 Assignment ::= InvalidArrayInitializerAssignement

 /.$putcase ignoreExpressionAssignment();$break ./

 

@@ -1086,23 +1263,29 @@
 /.$putCase consumeAssignmentOperator(XOR); $break ./

 AssignmentOperator ::= '|='

 /.$putCase consumeAssignmentOperator(OR); $break ./

+/:$readableName AssignmentOperator:/

 

 Expression -> AssignmentExpression

+/:$readableName Expression:/

 

 ConstantExpression -> Expression

+/:$readableName ConstantExpression:/

 

 -- The following rules are for optional nonterminals.

 --

 

 PackageDeclarationopt -> $empty 

 PackageDeclarationopt -> PackageDeclaration

+/:$readableName PackageDeclaration:/

 

 ClassHeaderExtendsopt ::= $empty

 ClassHeaderExtendsopt -> ClassHeaderExtends

+/:$readableName ClassHeaderExtends:/

 

 Expressionopt ::= $empty

 /.$putCase consumeEmptyExpression(); $break ./

 Expressionopt -> Expression

+/:$readableName Expression:/

 

 

 ---------------------------------------------------------------------------------------

@@ -1119,72 +1302,88 @@
 

 ,opt -> $empty

 ,opt -> ,

+/:$readableName ,:/

 

 ImportDeclarationsopt ::= $empty

 /.$putCase consumeEmptyImportDeclarationsopt(); $break ./

 ImportDeclarationsopt ::= ImportDeclarations

 /.$putCase consumeImportDeclarationsopt(); $break ./

-

+/:$readableName ImportDeclarations:/

 

 TypeDeclarationsopt ::= $empty

 /.$putCase consumeEmptyTypeDeclarationsopt(); $break ./

 TypeDeclarationsopt ::= TypeDeclarations

 /.$putCase consumeTypeDeclarationsopt(); $break ./

+/:$readableName TypeDeclarations:/

 

 ClassBodyDeclarationsopt ::= $empty

 /.$putCase consumeEmptyClassBodyDeclarationsopt(); $break ./

 ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations

 /.$putCase consumeClassBodyDeclarationsopt(); $break ./

+/:$readableName ClassBodyDeclarations:/

 

 Modifiersopt ::= $empty 

 /. $putCase consumeDefaultModifiers(); $break ./

 Modifiersopt ::= Modifiers 

 /.$putCase consumeModifiers(); $break ./ 

+/:$readableName Modifiers:/

 

 BlockStatementsopt ::= $empty

 /.$putCase consumeEmptyBlockStatementsopt(); $break ./

 BlockStatementsopt -> BlockStatements

+/:$readableName BlockStatements:/

 

 Dimsopt ::= $empty

 /. $putCase consumeEmptyDimsopt(); $break ./

 Dimsopt -> Dims

+/:$readableName Dimensions:/

 

 ArgumentListopt ::= $empty

 /. $putCase consumeEmptyArgumentListopt(); $break ./

 ArgumentListopt -> ArgumentList

+/:$readableName ArgumentList:/

 

 MethodHeaderThrowsClauseopt ::= $empty

 MethodHeaderThrowsClauseopt -> MethodHeaderThrowsClause

-   

+/:$readableName MethodHeaderThrowsClause:/

+

 FormalParameterListopt ::= $empty

 /.$putcase consumeFormalParameterListopt(); $break ./

 FormalParameterListopt -> FormalParameterList

+/:$readableName FormalParameterList:/

 

 ClassHeaderImplementsopt ::= $empty

 ClassHeaderImplementsopt -> ClassHeaderImplements

+/:$readableName ClassHeaderImplements:/

 

 InterfaceMemberDeclarationsopt ::= $empty

 /. $putCase consumeEmptyInterfaceMemberDeclarationsopt(); $break ./

 InterfaceMemberDeclarationsopt ::= NestedType InterfaceMemberDeclarations

 /. $putCase consumeInterfaceMemberDeclarationsopt(); $break ./

+/:$readableName InterfaceMemberDeclarations:/

 

 NestedType ::= $empty 

 /.$putCase consumeNestedType(); $break./

+/:$readableName NestedType:/

 

 ForInitopt ::= $empty

 /. $putCase consumeEmptyForInitopt(); $break ./

 ForInitopt -> ForInit

+/:$readableName ForInit:/

 

 ForUpdateopt ::= $empty

 /. $putCase consumeEmptyForUpdateopt(); $break ./

- ForUpdateopt -> ForUpdate

+ForUpdateopt -> ForUpdate

+/:$readableName ForUpdate:/

 

 InterfaceHeaderExtendsopt ::= $empty

 InterfaceHeaderExtendsopt -> InterfaceHeaderExtends

+/:$readableName InterfaceHeaderExtends:/

 

 Catchesopt ::= $empty

 /. $putCase consumeEmptyCatchesopt(); $break ./

 Catchesopt -> Catches

+/:$readableName Catches:/

 

 /.	}

 } ./

diff --git a/org.eclipse.jdt.core/grammar/java_1_5.g b/org.eclipse.jdt.core/grammar/java_1_5.g
index 5d2967b..caaff7f 100644
--- a/org.eclipse.jdt.core/grammar/java_1_5.g
+++ b/org.eclipse.jdt.core/grammar/java_1_5.g
Binary files differ
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java
index e11692d..95b06a0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/BufferChangedEvent.java
@@ -80,7 +80,7 @@
  * @return the buffer affected by the change
  */
 public IBuffer getBuffer() {
-	return (IBuffer) source;
+	return (IBuffer) this.source;
 }
 /**
  * Returns the length of text removed or replaced in the buffer, or
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathContainerInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathContainerInitializer.java
index 8e98051..795ddc8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathContainerInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathContainerInitializer.java
@@ -48,6 +48,7 @@
      * Creates a new classpath container initializer.
      */
     public ClasspathContainerInitializer() {
+    	// a classpath container initializer must have a public 0-argument constructor
     }
 
     /**
@@ -59,16 +60,30 @@
      * the second segment can be used as an additional hint when performing the resolution.
      * <p>
      * The initializer is invoked if a container path needs to be resolved for a given project, and no
-     * value for it was recorded so far. The implementation of the initializer can set the corresponding 
-     * container using <code>JavaCore#setClasspathContainer</code>.
+     * value for it was recorded so far. The implementation of the initializer would typically set the 
+     * corresponding container using <code>JavaCore#setClasspathContainer</code>.
+     * <p>
+     * A container initialization can be indirectly performed while attempting to resolve a project
+     * classpath using <code>IJavaProject#getResolvedClasspath(</code>; or directly when using
+     * <code>JavaCore#getClasspathContainer</code>. During the initialization process, any attempt
+     * to further obtain the same container will simply return <code>null</code> so as to avoid an
+     * infinite regression of initializations.
+     * <p>
+     * A container initialization may also occur indirectly when setting a project classpath, as the operation
+     * needs to resolve the classpath for validation purpose. While the operation is in progress, a referenced 
+     * container initializer may be invoked. If the initializer further tries to access the referring project classpath, 
+     * it will not see the new assigned classpath until the operation has completed. Note that once the Java 
+     * change notification occurs (at the end of the operation), the model has been updated, and the project 
+     * classpath can be queried normally.
      * <p>
      * @param containerPath a two-segment path (ID/hint) identifying the container that needs 
      * 	to be resolved
      * @param project the Java project in which context the container is to be resolved.
      *    This allows generic containers to be bound with project specific values.
+     * @throws CoreException if an exception occurs during the initialization
      * 
      * @see JavaCore#getClasspathContainer(IPath, IJavaProject)
-     * @see JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)
+     * @see JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], org.eclipse.core.runtime.IProgressMonitor)
      * @see IClasspathContainer
      */
     public abstract void initialize(IPath containerPath, IJavaProject project) throws CoreException;
@@ -107,7 +122,7 @@
      * @param project the project for which the container is to be updated
 	 * @param containerSuggestion a suggestion to update the corresponding container definition
 	 * @throws CoreException when <code>JavaCore#setClasspathContainer</code> would throw any.
-	 * @see JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], IProgressMonitor)
+	 * @see JavaCore#setClasspathContainer(IPath, IJavaProject[], IClasspathContainer[], org.eclipse.core.runtime.IProgressMonitor)
 	 * @see ClasspathContainerInitializer#canUpdateClasspathContainer(IPath, IJavaProject)
 	 * @since 2.1
 	 */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathVariableInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathVariableInitializer.java
index 3bc1d04..4f1f200 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathVariableInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ClasspathVariableInitializer.java
@@ -29,6 +29,7 @@
      * Creates a new classpath variable initializer.
      */
     public ClasspathVariableInitializer() {
+    	// a classpath variable initializer must have a public 0-argument constructor
     }
 
     /**
@@ -44,8 +45,8 @@
      *    that requires a binding
      * 
      * @see JavaCore#getClasspathVariable(String)
-     * @see JavaCore#setClasspathVariable(String, IPath, IProgressMonitor)
-     * @see JavaCore#setClasspathVariables(String[], IPath[], IProgressMonitor)
+     * @see JavaCore#setClasspathVariable(String, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IProgressMonitor)
+     * @see JavaCore#setClasspathVariables(String[], org.eclipse.core.runtime.IPath[], org.eclipse.core.runtime.IProgressMonitor)
      */
     public abstract void initialize(String variable);
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java
index db43e7f..f2d7f31 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CompletionRequestorAdapter.java
@@ -37,6 +37,7 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
@@ -50,12 +51,14 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
 	 * @see ICompletionRequestor#acceptError(IProblem)
 	 */
 	public void acceptError(IProblem error) {
+		// default behavior is to ignore
 	}
 
 	/*
@@ -72,6 +75,7 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
@@ -85,6 +89,7 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
@@ -95,6 +100,7 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
@@ -105,6 +111,7 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
@@ -118,6 +125,7 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
@@ -137,6 +145,7 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
@@ -156,6 +165,7 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
@@ -166,6 +176,7 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
@@ -177,6 +188,7 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
@@ -189,6 +201,7 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 
 	/*
@@ -202,5 +215,6 @@
 		int completionStart,
 		int completionEnd,
 		int relevance) {
+			// default behavior is to ignore
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
index 3a84f32..91a34a5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/CorrectionEngine.java
@@ -18,7 +18,7 @@
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
 import org.eclipse.jdt.internal.compiler.parser.*;
-import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This class is the entry point for source corrections.
@@ -44,11 +44,11 @@
 	/**
 	 * This field is not intended to be used by client.
 	 */
-	protected ICompilationUnit unit;
+	protected ICompilationUnit compilationUnit;
 	/**
 	 * This field is not intended to be used by client.
 	 */
-	protected ICorrectionRequestor requestor;
+	protected ICorrectionRequestor correctionRequestor;
 	/**
 	 * This field is not intended to be used by client.
 	 */
@@ -86,7 +86,7 @@
 	 * 		CURRENTLY THERE IS NO CORRECTION SPECIFIC SETTINGS.
 	 */
 	public CorrectionEngine(Map setting) {
-		
+		// settings ignored for now
 	}
 	
 	/**
@@ -97,13 +97,12 @@
 	 * 
 	 * @param marker
 	 * 		the marker which describe the problem to correct.
-	 * 
 	 * @param targetUnit
 	 * 		replace the compilation unit given by the marker. Ignored if null.
-	 * 
 	 * @param positionOffset
 	 * 		the offset of position given by the marker.
-	 *
+	 * @param requestor
+	 * 		the given correction requestor
 	 * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code>
 	 * @exception JavaModelException currently this exception is never thrown, but the opportunity to thrown an exception
 	 * 	when the correction failed is kept for later. 
@@ -134,10 +133,10 @@
 	 * 
 	 * @param problem
 	 * 		the problem which describe the problem to correct.
-	 * 
 	 * @param targetUnit
 	 * 		denote the compilation unit in which correction occurs. Cannot be null.
-	 * 
+	 * @param requestor
+	 * 		the given correction requestor
 	 * @exception IllegalArgumentException if <code>targetUnit</code> or <code>requestor</code> is <code>null</code>
 	 * @exception JavaModelException currently this exception is never thrown, but the opportunity to thrown an exception
 	 * 	when the correction failed is kept for later.
@@ -155,7 +154,7 @@
 			requestor);
 	}
 
-	/**
+	/*
 	 * Ask the engine to compute a correction for the specified problem
 	 * of the given compilation unit.
 	 * Correction results are answered through a requestor.
@@ -180,7 +179,7 @@
 	 * 	when the correction failed is kept for later.
 	 * @since 2.0
 	 */
-	private void computeCorrections(ICompilationUnit unit, int id, int start, int end, String[] arguments, ICorrectionRequestor requestor) throws JavaModelException{
+	private void computeCorrections(ICompilationUnit unit, int id, int start, int end, String[] arguments, ICorrectionRequestor requestor) {
 
 		if(id == -1 || arguments == null || start == -1 || end == -1)
 			return;		
@@ -188,10 +187,10 @@
 			throw new IllegalArgumentException(Util.bind("correction.nullRequestor")); //$NON-NLS-1$
 		}
 		
-		this.requestor = requestor;
+		this.correctionRequestor = requestor;
 		this.correctionStart = start;
 		this.correctionEnd = end;
-		this.unit = unit;
+		this.compilationUnit = unit;
 		
 		String argument = null;
 		try {
@@ -199,47 +198,47 @@
 				// Type correction
 				case IProblem.FieldTypeNotFound :
 				case IProblem.ArgumentTypeNotFound :
-					filter = CLASSES | INTERFACES;
+					this.filter = CLASSES | INTERFACES;
 					argument = arguments[2];
 					break;
 				case IProblem.SuperclassNotFound :
-					filter = CLASSES;
+					this.filter = CLASSES;
 					argument = arguments[0];
 					break;
 				case IProblem.InterfaceNotFound :
-					filter = INTERFACES;
+					this.filter = INTERFACES;
 					argument = arguments[0];
 					break;
 				case IProblem.ExceptionTypeNotFound :
-					filter = CLASSES;
+					this.filter = CLASSES;
 					argument = arguments[1];
 					break;
 				case IProblem.ReturnTypeNotFound :
-					filter = CLASSES | INTERFACES;
+					this.filter = CLASSES | INTERFACES;
 					argument = arguments[1];
 					break;
 				case IProblem.ImportNotFound :
-					filter = IMPORT;
+					this.filter = IMPORT;
 					argument = arguments[0];
 					break;
 				case IProblem.UndefinedType :
-					filter = CLASSES | INTERFACES;
+					this.filter = CLASSES | INTERFACES;
 					argument = arguments[0];
 					break;
 					
 				// Method correction
 				case IProblem.UndefinedMethod :
-					filter = METHOD;
+					this.filter = METHOD;
 					argument = arguments[1];
 					break;
 					
 				// Field and local variable correction
 				case IProblem.UndefinedField :
-					filter = FIELD;
+					this.filter = FIELD;
 					argument = arguments[0];
 					break;
 				case IProblem.UndefinedName :
-					filter = FIELD | LOCAL;
+					this.filter = FIELD | LOCAL;
 					argument = arguments[0];
 					break;
 			}
@@ -251,13 +250,13 @@
 		}
 	}
 
-	private void correct(char[] argument) throws JavaModelException {
+	private void correct(char[] argument) {
 		try {
-			String source = unit.getSource();
+			String source = this.compilationUnit.getSource();
 			Scanner scanner = new Scanner();
 			scanner.setSource(source.toCharArray());
 			
-			scanner.resetTo(correctionStart, correctionEnd);
+			scanner.resetTo(this.correctionStart, this.correctionEnd);
 			int token = 0;
 			char[] argumentSource = CharOperation.NO_CHAR;
 			
@@ -273,17 +272,17 @@
 					return;
 				
 				if(CharOperation.equals(argument, argumentSource)) {
-					correctionStart = scanner.startPosition;
-					correctionEnd = scanner.currentPosition;
-					prefixLength = CharOperation.lastIndexOf('.', argument) + 1;
+					this.correctionStart = scanner.startPosition;
+					this.correctionEnd = scanner.currentPosition;
+					this.prefixLength = CharOperation.lastIndexOf('.', argument) + 1;
 					break;
 				}
 				
 			}
 		
 			// search completion position
-			int completionPosition = correctionStart;
-			scanner.resetTo(completionPosition, correctionEnd);
+			int completionPosition = this.correctionStart;
+			scanner.resetTo(completionPosition, this.correctionEnd);
 			int position = completionPosition;
 			
 			for (int i = 0; i < 4; i++) {
@@ -295,9 +294,9 @@
 				}
 			}
 			
-			unit.codeComplete(
+			this.compilationUnit.codeComplete(
 				completionPosition,
-				completionRequestor
+				this.completionRequestor
 			);
 		} catch (JavaModelException e) {
 			return;
@@ -312,29 +311,29 @@
 	protected ICompletionRequestor completionRequestor = new ICompletionRequestor() {
 		public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {}
 		public void acceptClass(char[] packageName,char[] className,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
-			if((filter & (CLASSES | INTERFACES)) != 0) {
-				requestor.acceptClass(
+			if((CorrectionEngine.this.filter & (CLASSES | INTERFACES)) != 0) {
+				CorrectionEngine.this.correctionRequestor.acceptClass(
 					packageName,
 					className,
-					CharOperation.subarray(completionName, prefixLength, completionName.length),
+					CharOperation.subarray(completionName, CorrectionEngine.this.prefixLength, completionName.length),
 					modifiers,
-					correctionStart,
-					correctionEnd);
-			} else if((filter & IMPORT) != 0) {
+					CorrectionEngine.this.correctionStart,
+					CorrectionEngine.this.correctionEnd);
+			} else if((CorrectionEngine.this.filter & IMPORT) != 0) {
 				char[] fullName = CharOperation.concat(packageName, className, '.');
-				requestor.acceptClass(
+				CorrectionEngine.this.correctionRequestor.acceptClass(
 					packageName,
 					className,
-					CharOperation.subarray(fullName, prefixLength, fullName.length),
+					CharOperation.subarray(fullName, CorrectionEngine.this.prefixLength, fullName.length),
 					modifiers,
-					correctionStart,
-					correctionEnd);
+					CorrectionEngine.this.correctionStart,
+					CorrectionEngine.this.correctionEnd);
 			}
 		}
 		public void acceptError(IProblem error) {}
 		public void acceptField(char[] declaringTypePackageName,char[] declaringTypeName,char[] name,char[] typePackageName,char[] typeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
-			if((filter & FIELD) != 0) {
-				requestor.acceptField(
+			if((CorrectionEngine.this.filter & FIELD) != 0) {
+				CorrectionEngine.this.correctionRequestor.acceptField(
 					declaringTypePackageName,
 					declaringTypeName,
 					name,
@@ -342,46 +341,46 @@
 					typeName,
 					name,
 					modifiers,
-					correctionStart,
-					correctionEnd);
+					CorrectionEngine.this.correctionStart,
+					CorrectionEngine.this.correctionEnd);
 			}
 		}
 		public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
-			if((filter & (CLASSES | INTERFACES)) != 0) {
-				requestor.acceptInterface(
+			if((CorrectionEngine.this.filter & (CLASSES | INTERFACES)) != 0) {
+				CorrectionEngine.this.correctionRequestor.acceptInterface(
 					packageName,
 					interfaceName,
-					CharOperation.subarray(completionName, prefixLength, completionName.length),
+					CharOperation.subarray(completionName, CorrectionEngine.this.prefixLength, completionName.length),
 					modifiers,
-					correctionStart,
-					correctionEnd);
-			} else if((filter & IMPORT) != 0) {
+					CorrectionEngine.this.correctionStart,
+					CorrectionEngine.this.correctionEnd);
+			} else if((CorrectionEngine.this.filter & IMPORT) != 0) {
 				char[] fullName = CharOperation.concat(packageName, interfaceName, '.');
-				requestor.acceptInterface(
+				CorrectionEngine.this.correctionRequestor.acceptInterface(
 					packageName,
 					interfaceName,
-					CharOperation.subarray(fullName, prefixLength, fullName.length),
+					CharOperation.subarray(fullName, CorrectionEngine.this.prefixLength, fullName.length),
 					modifiers,
-					correctionStart,
-					correctionEnd);
+					CorrectionEngine.this.correctionStart,
+					CorrectionEngine.this.correctionEnd);
 			}
 		}
 		public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance) {}
 		public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance) {}
 		public void acceptLocalVariable(char[] name,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance) {
-			if((filter & LOCAL) != 0) {
-				requestor.acceptLocalVariable(
+			if((CorrectionEngine.this.filter & LOCAL) != 0) {
+				CorrectionEngine.this.correctionRequestor.acceptLocalVariable(
 					name,
 					typePackageName,
 					typeName,
 					modifiers,
-					correctionStart,
-					correctionEnd);
+					CorrectionEngine.this.correctionStart,
+					CorrectionEngine.this.correctionEnd);
 			}
 		}
 		public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
-			if((filter & METHOD) != 0) {
-				requestor.acceptMethod(
+			if((CorrectionEngine.this.filter & METHOD) != 0) {
+				CorrectionEngine.this.correctionRequestor.acceptMethod(
 					declaringTypePackageName,
 					declaringTypeName,
 					selector,
@@ -392,19 +391,19 @@
 					returnTypeName,
 					selector,
 					modifiers,
-					correctionStart,
-					correctionEnd);
+					CorrectionEngine.this.correctionStart,
+					CorrectionEngine.this.correctionEnd);
 			}
 		}
 		public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {}
 		public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance) {}
 		public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance) {
-			if((filter & (CLASSES | INTERFACES | IMPORT)) != 0) {
-				requestor.acceptPackage(
+			if((CorrectionEngine.this.filter & (CLASSES | INTERFACES | IMPORT)) != 0) {
+				CorrectionEngine.this.correctionRequestor.acceptPackage(
 					packageName,
-					CharOperation.subarray(packageName, prefixLength, packageName.length),
-					correctionStart,
-					correctionEnd);
+					CharOperation.subarray(packageName, CorrectionEngine.this.prefixLength, packageName.length),
+					CorrectionEngine.this.correctionStart,
+					CorrectionEngine.this.correctionEnd);
 			}
 		}
 		public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance) {}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java
index eec8444..bf37c97 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ElementChangedEvent.java
@@ -61,6 +61,7 @@
 	 * @see org.eclipse.core.resources.IResourceChangeEvent
 	 * @see #getDelta()
 	 * @since 2.0
+	 * @deprecated - no longer used, such deltas are now notified during POST_CHANGE
 	 */
 	public static final int PRE_AUTO_BUILD = 2;
 
@@ -92,6 +93,7 @@
 	 * Creates an new element changed event (based on a <code>IJavaElementDelta</code>).
 	 *
 	 * @param delta the Java element delta.
+	 * @param type the type of delta (ADDED, REMOVED, CHANGED) this event contains
 	 */
 	public ElementChangedEvent(IJavaElementDelta delta, int type) {
 		super(delta);
@@ -103,7 +105,7 @@
 	 * @return the delta describing the change
 	 */
 	public IJavaElementDelta getDelta() {
-		return (IJavaElementDelta) source;
+		return (IJavaElementDelta) this.source;
 	}
 	
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java
index ca9a3e4..147ba33 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Flags.java
@@ -7,6 +7,7 @@
  * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     IBM Corporation - added constant AccDefault
  *******************************************************************************/
 package org.eclipse.jdt.core;
 
@@ -25,11 +26,16 @@
  * the <code>org.eclipse.jdt.core.dom</code> package.
  * </p>
  *
- * @see IMember#getFlags
+ * @see IMember#getFlags()
  */
 public final class Flags {
 
 	/**
+	 * Constant representing the absence of any flag
+	 * @since 3.0
+	 */
+	public static final int AccDefault = 0;
+	/**
 	 * Public access flag. See The Java Virtual Machine Specification for more details.
 	 * @since 2.0
 	 */
@@ -109,6 +115,7 @@
 	 * Not instantiable.
 	 */
 	private Flags() {
+		// Not instantiable
 	}
 	/**
 	 * Returns whether the given integer includes the <code>abstract</code> modifier.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBuffer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBuffer.java
index 92e1837..fc5de22 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBuffer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBuffer.java
@@ -47,9 +47,7 @@
  * Any client can append to the contents of the buffer, not just the owner of the buffer.
  * Reports a buffer changed event.
  * <p>
- * Has no effect if this buffer is read-only.
- * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * Has no effect if this buffer is read-only or if the buffer is closed.
  *
  * @param text the given character array to append to contents of the buffer
  */
@@ -60,9 +58,7 @@
  * Any client can append to the contents of the buffer, not just the owner of the buffer.
  * Reports a buffer changed event.
  * <p>
- * Has no effect if this buffer is read-only.
- * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * Has no effect if this buffer is read-only or if the buffer is closed.
  *
  * @param text the <code>String</code> to append to the contents of the buffer
  */
@@ -79,7 +75,7 @@
 /**
  * Returns the character at the given position in this buffer.
  * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * The returned value is undefined if the buffer is closed.
  *
  * @param position a zero-based source offset in this buffer
  * @return the character at the given position in this buffer
@@ -94,9 +90,8 @@
  * wishes to change this array, they should make a copy. Likewise, if the
  * client wishes to hang on to the array in its current state, they should
  * make a copy.
- * </p>
- * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * </p><p>
+ * The returned value is undefined if the buffer is closed.
  *
  * @return the characters contained in this buffer
  */
@@ -106,7 +101,7 @@
  * the result is an immutable value object., It can also answer <code>null</code> if
  * the buffer has not been initialized.
  * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * The returned value is undefined if the buffer is closed.
  *
  * @return the contents of this buffer as a <code>String</code>
  */
@@ -114,7 +109,7 @@
 /**
  * Returns number of characters stored in this buffer.
  * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * The returned value is undefined if the buffer is closed.
  *
  * @return the number of characters in this buffer
  */
@@ -128,7 +123,7 @@
 /**
  * Returns the given range of text in this buffer.
  * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * The returned value is undefined if the buffer is closed.
  *
  * @param offset the  zero-based starting offset
  * @param length the number of characters to retrieve
@@ -148,7 +143,11 @@
  * was opened or since it was last saved.
  * If a buffer does not have an underlying resource, this method always
  * returns <code>true</code>.
- *
+ * <p>
+ * NOTE: when a buffer does not have unsaved changes, the model may decide to close it 
+ * to claim some memory back. If the associated element needs to be reopened later on, its
+ * buffer factory will be requested to create a new buffer.
+ * </p>
  * @return a <code>boolean</code> indicating presence of unsaved changes (in
  *   the absence of any underlying resource, it will always return <code>true</code>).
  */
@@ -177,7 +176,7 @@
  * <code>position</code> and <code>position + length</code> must be in the range [0, getLength()].
  * <code>length</code> must not be negative.
  * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * Has no effect if this buffer is read-only or if the buffer is closed.
  *
  * @param position the zero-based starting position of the affected text range in this buffer
  * @param length the length of the affected text range in this buffer
@@ -189,7 +188,7 @@
  * <code>position</code> and <code>position + length</code> must be in the range [0, getLength()].
  * <code>length</code> must not be negative.
  * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * Has no effect if this buffer is read-only or if the buffer is closed.
  *
  * @param position the zero-based starting position of the affected text range in this buffer
  * @param length the length of the affected text range in this buffer
@@ -216,7 +215,7 @@
  * In either case, if this method succeeds, the resource will be marked 
  * as being local (even if it wasn't before).
  * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * Has no effect if this buffer is read-only or if the buffer is closed.
  *
  * @param progress the progress monitor to notify
  * @param force a <code> boolean </code> flag indicating how to deal with resource
@@ -235,11 +234,8 @@
  * Reports a buffer changed event.
  * <p>
  * Equivalent to <code>replace(0,getLength(),contents)</code>.
- * </p>
- * <p>
- * Has no effect if this buffer is read-only.
- * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * </p><p>
+ * Has no effect if this buffer is read-only or if the buffer is closed.
  *
  * @param contents the new contents of this buffer as a character array
  */
@@ -251,11 +247,8 @@
  * Reports a buffer changed event.
  * <p>
  * Equivalent to <code>replace(0,getLength(),contents)</code>.
- * </p>
- * <p>
- * Has no effect if this buffer is read-only.
- * <p>
- * A <code>RuntimeException</code> might be thrown if the buffer is closed.
+ * </p><p>
+ * Has no effect if this buffer is read-only or if the buffer is closed.
  *
  * @param contents the new contents of this buffer as a <code>String</code>
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferFactory.java
index 4816919..81e293a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IBufferFactory.java
@@ -16,6 +16,7 @@
  * This interface may be implemented by clients.
  * </p>
  * @since 2.0
+ * @deprecated Use <code>WorkingCopyOwner</code> instead
  */
 public interface IBufferFactory {
 
@@ -26,6 +27,7 @@
 	 * its content is <code>null</code>).
 	 * 
 	 * @param owner the owner of the buffer
+	 * @return the newly created buffer
 	 * @see IBuffer
 	 */
 	IBuffer createBuffer(IOpenable owner);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java
index 6110e53..835629d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClassFile.java
@@ -29,7 +29,7 @@
  * This interface is not intended to be implemented by clients.
  * </p>
  *
- * @see IPackageFragmentRoot#attachSource
+ * @see IPackageFragmentRoot#attachSource(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, IProgressMonitor)
  */
  
 public interface IClassFile extends IJavaElement, IParent, IOpenable, ISourceReference, ICodeAssist {
@@ -59,6 +59,29 @@
 IType getType() throws JavaModelException;
 /**
  * Returns a working copy on the source associated with this class file using the given 
+ * owner to create the buffer, or <code>null</code> if there is no source associated
+ * with the class file.
+ * <p>
+ * The buffer will be automatically initialized with the source of the class file
+ * upon creation.
+ * <p>
+ * The only valid operations on this working copy are <code>getBuffer()</code> or <code>getPrimary()</code>.
+ *
+ * @param owner the owner that creates a buffer that is used to get the content of the working copy
+ *                 or <code>null</code> if the primary owner should be used
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ *                 or <code>null</code> if no progress should be reported 
+ * @return a  a working copy on the source associated with this class file
+ * @exception JavaModelException if the source of this class file can
+ *   not be determined. Reasons include:
+ * <ul>
+ * <li> This class file does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ * @since 3.0
+ */
+ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Returns a working copy on the source associated with this class file using the given 
  * factory to create the buffer, or <code>null</code> if there is no source associated
  * with the class file.
  * <p>
@@ -71,15 +94,16 @@
  *                 or <code>null</code> if no progress should be reported 
  * @param factory the factory that creates a buffer that is used to get the content of the working copy
  *                 or <code>null</code> if the internal factory should be used
+ * @return a  a working copy on the source associated with this class file
  * @exception JavaModelException if the source of this class file can
  *   not be determined. Reasons include:
  * <ul>
  * <li> This class file does not exist (ELEMENT_DOES_NOT_EXIST)</li>
  * </ul>
  * @since 2.0
+ * @deprecated Use getWorkingCopy(WorkingCopyOwner, IProgressMonitor) instead
  */
-IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory) throws JavaModelException;
-/**
+IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory) throws JavaModelException;/**
  * Returns whether this type represents a class. This is not guaranteed to be
  * instantaneous, as it may require parsing the underlying file.
  *
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathContainer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathContainer.java
index 2a77df8..fd085ad 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathContainer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathContainer.java
@@ -84,6 +84,7 @@
 	 * 	implicitly contributed by the runtime).</li>
 	 * </ul>
 	 * Typically, system containers should be placed first on a build path.
+	 * @return the kind of this container
 	 */	
     int getKind();
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
index 78ef639..138123d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IClasspathEntry.java
@@ -103,11 +103,11 @@
  * Classpath entries can be created via methods on <code>JavaCore</code>.
  * </p>
  *
- * @see JavaCore#newLibraryEntry
- * @see JavaCore#newProjectEntry
- * @see JavaCore#newSourceEntry
- * @see JavaCore#newVariableEntry
- * @see JavaCore#newContainerEntry
+ * @see JavaCore#newLibraryEntry(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath)
+ * @see JavaCore#newProjectEntry(org.eclipse.core.runtime.IPath)
+ * @see JavaCore#newSourceEntry(org.eclipse.core.runtime.IPath)
+ * @see JavaCore#newVariableEntry(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath)
+ * @see JavaCore#newContainerEntry(org.eclipse.core.runtime.IPath)
  * @see ClasspathVariableInitializer
  * @see ClasspathContainerInitializer
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java
index ee96da0..23bdd29 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeAssist.java
@@ -25,44 +25,6 @@
 	 * is the 0-based index of the character, after which code assist is desired.
 	 * An <code>offset</code> of -1 indicates to code assist at the beginning of this
 	 * compilation unit.
-	 *
-	 * @param offset the given offset position
-	 * @param requestor the given completion requestor
-	 * @exception JavaModelException if code assist could not be performed. Reasons include:<ul>
-	 *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
-	 *  <li> The position specified is < -1 or is greater than this compilation unit's
-	 *      source length (INDEX_OUT_OF_BOUNDS)
-	 * </ul>
-	 *
-	 * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code>
-	 * @since 2.0
-	 * 	 */
-	void codeComplete(int offset, ICompletionRequestor requestor)
-		throws JavaModelException;
-	/**
-	 * Performs code selection on the given selected text in this compilation unit,
-	 * reporting results to the given selection requestor. The <code>offset</code>
-	 * is the 0-based index of the first selected character. The <code>length</code> 
-	 * is the number of selected characters.
-	 * 
-	 * @param offset the given offset position
-	 * @param length the number of selected characters
-	 *
-	 * @exception JavaModelException if code resolve could not be performed. Reasons include:
-	 *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
-	 *  <li> The range specified is not within this element's
-	 *      source range (INDEX_OUT_OF_BOUNDS)
-	 * </ul>
-	 *
-	 */
-	IJavaElement[] codeSelect(int offset, int length) throws JavaModelException;
-
-	/**
-	 * Performs code completion at the given offset position in this compilation unit,
-	 * reporting results to the given completion requestor. The <code>offset</code>
-	 * is the 0-based index of the character, after which code assist is desired.
-	 * An <code>offset</code> of -1 indicates to code assist at the beginning of this
-	 * compilation unit.
 	 * 
 	 * @param offset the given offset position
 	 * @param requestor the given completion requestor
@@ -75,7 +37,98 @@
 	 *
 	 * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code>
 	 * @deprecated - use codeComplete(int, ICompletionRequestor) instead
+	 * TODO remove before 3.0
 	 */
 	void codeComplete(int offset, ICodeCompletionRequestor requestor)
 		throws JavaModelException;
+	/**
+	 * Performs code completion at the given offset position in this compilation unit,
+	 * reporting results to the given completion requestor. The <code>offset</code>
+	 * is the 0-based index of the character, after which code assist is desired.
+	 * An <code>offset</code> of -1 indicates to code assist at the beginning of this
+	 * compilation unit.
+	 *
+	 * @param offset the given offset position
+	 * @param requestor the given completion requestor
+	 * @exception JavaModelException if code assist could not be performed. Reasons include:<ul>
+	 *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+	 *  <li> The position specified is < -1 or is greater than this compilation unit's
+	 *      source length (INDEX_OUT_OF_BOUNDS)
+	 * </ul>
+	 *
+	 * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code>
+	 * @since 2.0
+ 	 */
+	void codeComplete(int offset, ICompletionRequestor requestor)
+		throws JavaModelException;
+	/**
+	 * Performs code completion at the given offset position in this compilation unit,
+	 * reporting results to the given completion requestor. The <code>offset</code>
+	 * is the 0-based index of the character, after which code assist is desired.
+	 * An <code>offset</code> of -1 indicates to code assist at the beginning of this
+	 * compilation unit.
+	 * It considers types in the working copies with the given owner first. In other words, 
+	 * the owner's working copies will take precedence over their original compilation units
+	 * in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * </p>
+	 *
+	 * @param offset the given offset position
+	 * @param requestor the given completion requestor
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * @exception JavaModelException if code assist could not be performed. Reasons include:<ul>
+	 *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+	 *  <li> The position specified is < -1 or is greater than this compilation unit's
+	 *      source length (INDEX_OUT_OF_BOUNDS)
+	 * </ul>
+	 *
+	 * @exception IllegalArgumentException if <code>requestor</code> is <code>null</code>
+	 * @since 3.0
+	 */
+	void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner)
+		throws JavaModelException;
+	/**
+	 * Returns the Java elements correspondiing to the given selected text in this compilation unit. 
+	 * The <code>offset</code> is the 0-based index of the first selected character. 
+	 * The <code>length</code> is the number of selected characters.
+	 * 
+	 * @param offset the given offset position
+	 * @param length the number of selected characters
+	 * @return the Java elements correspondiing to the given selected text
+	 *
+	 * @exception JavaModelException if code resolve could not be performed. Reasons include:
+	 *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+	 *  <li> The range specified is not within this element's
+	 *      source range (INDEX_OUT_OF_BOUNDS)
+	 * </ul>
+	 *
+	 */
+	IJavaElement[] codeSelect(int offset, int length) throws JavaModelException;
+	/**
+	 * Returns the Java elements correspondiing to the given selected text in this compilation unit. 
+	 * The <code>offset</code> is the 0-based index of the first selected character. 
+	 * The <code>length</code> is the number of selected characters.
+	 * It considers types in the working copies with the given owner first. In other words, 
+	 * the owner's working copies will take precedence over their original compilation units
+	 * in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * </p>
+	 * 
+	 * @param offset the given offset position
+	 * @param length the number of selected characters
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * @return the Java elements correspondiing to the given selected text
+	 *
+	 * @exception JavaModelException if code resolve could not be performed. Reasons include:
+	 *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+	 *  <li> The range specified is not within this element's
+	 *      source range (INDEX_OUT_OF_BOUNDS)
+	 * </ul>
+	 * @since 3.0
+	 */
+	IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner owner) throws JavaModelException;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeCompletionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeCompletionRequestor.java
index edd9ed7..f04a139 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeCompletionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeCompletionRequestor.java
@@ -26,8 +26,6 @@
 /**
  * Code assist notification of a class completion.
  * 
- * @return void - Nothing is answered back to code assist engine
- *
  * @param packageName Declaring package name of the class.
  * @param className Name of the class.
  * @param completionName The completion for the class.
@@ -50,7 +48,7 @@
 	int completionEnd);
 /**
  * Code assist notification of a compilation error detected during completion.
- *  @param error Only problems which are categorized as errors are notified to the requestor,
+ *  @param marker Only problems which are categorized as errors are notified to the requestor,
  *		warnings are silently ignored.
  *		In case an error got signaled, no other completions might be available,
  *		therefore the problem message should be presented to the user.
@@ -102,7 +100,7 @@
  * Code assist notification of an interface completion.
  *
  * @param packageName Declaring package name of the interface.
- * @param className Name of the interface.
+ * @param interfaceName Name of the interface.
  * @param completionName The completion for the interface.
  *   Can include ';' for imported interfaces.
  * @param modifiers The modifiers of the interface.
@@ -132,12 +130,8 @@
 /**
  * Code assist notification of a label completion.
  *
- * @return void - Nothing is answered back to code assist engine
- *
  * @param labelName The label source.
- * 
  * @param completionStart The start position of insertion of the name of this label.
- * 
  * @param completionEnd The end position of insertion of the name of this label.
  */
 void acceptLabel(char[] labelName, int completionStart, int completionEnd);
@@ -222,8 +216,6 @@
 /**
  * Code assist notification of a modifier completion.
  *
- * @return void - Nothing is answered back to code assist engine
- *
  * @param modifierName The new modifier.
  * @param completionStart The start position of insertion of the name of this new modifier.
  * @param completionEnd The end position of insertion of the name of this new modifier.
@@ -232,8 +224,6 @@
 /**
  * Code assist notification of a package completion.
  *
- * @return void - Nothing is answered back to code assist engine
- *
  * @param packageName The package name.
  * @param completionName The completion for the package.
  *   Can include '.*;' for imports.
@@ -252,8 +242,6 @@
 /**
  * Code assist notification of a type completion.
  * 
- * @return void - Nothing is answered back to code assist engine
- *
  * @param packageName Declaring package name of the type.
  * @param typeName Name of the type.
  * @param completionName The completion for the type.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeFormatter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeFormatter.java
index 39f1eba..33f0ec4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeFormatter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICodeFormatter.java
@@ -16,8 +16,9 @@
  * In case none is found, a default formatter can be provided through the ToolFactory.
  * 
  * @see ToolFactory#createCodeFormatter()
- * @see ToolFactory#createDefaultCodeFormatter(Map options)
+ * @see ToolFactory#createDefaultCodeFormatter(java.util.Map options)
  * @since 2.0
+ * @deprecated - should use org.eclipse.jdt.core.formatter.CodeFormatter instead (note: options have changed)
  */
 public interface ICodeFormatter {
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
index 849a51e..83fe310 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
@@ -27,6 +27,65 @@
  */
 public interface ICompilationUnit extends IJavaElement, ISourceReference, IParent, IOpenable, IWorkingCopy, ISourceManipulation, ICodeAssist {
 /**
+ * Changes this compilation unit handle into a working copy. A new <code>IBuffer</code> is
+ * created using this compilation unit handle's owner. Uses the primary owner is none was
+ * specified when this compilation unit handle was created.
+ * <p>
+ * When switching to working copy mode, problems are reported to given 
+ * <code>IProblemRequestor</code>.
+ * </p>
+ * <p>
+ * Once in working copy mode, changes to this compilation unit or its children are done in memory.
+ * Only the new buffer is affected. Using <code>commitWorkingCopy(boolean, IProgressMonitor)</code>
+ * will bring the underlying resource in sync with this compilation unit.
+ * </p>
+ * <p>
+ * If this compilation unit was already in working copy mode, an internal counter is incremented and no
+ * other action is taken on this compilation unit. To bring this compilation unit back into the original mode 
+ * (where it reflects the underlying resource), <code>discardWorkingCopy</code> must be call as many 
+ * times as <code>becomeWorkingCopy</code>.
+ * </p>
+ * 
+ * @param problemRequestor a requestor which will get notified of problems detected during
+ * 	reconciling as they are discovered. The requestor can be set to <code>null</code> indicating
+ * 	that the client is not interested in problems.
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ * 	or <code>null</code> if no progress should be reported 
+ * @throws JavaModelException if this compilation unit could not become a working copy.
+ * @see #discardWorkingCopy()
+ * @since 3.0
+ */
+void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Commits the contents of this working copy to its underlying resource.
+ *
+ * <p>It is possible that the contents of the original resource have changed
+ * since this working copy was created, in which case there is an update conflict.
+ * The value of the <code>force</code> parameter effects the resolution of
+ * such a conflict:<ul>
+ * <li> <code>true</code> - in this case the contents of this working copy are applied to
+ * 	the underlying resource even though this working copy was created before
+ *		a subsequent change in the resource</li>
+ * <li> <code>false</code> - in this case a <code>JavaModelException</code> is thrown</li>
+ * </ul>
+ * <p>
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * </p>
+ * @param force a flag to handle the cases when the contents of the original resource have changed
+ * since this working copy was created
+ * @param monitor the given progress monitor
+ * @throws JavaModelException if this working copy could not commit. Reasons include:
+ * <ul>
+ * <li> A <code>CoreException</code> occurred while updating an underlying resource
+ * <li> This element is not a working copy (INVALID_ELEMENT_TYPES)
+ * <li> A update conflict (described above) (UPDATE_CONFLICT)
+ * </ul>
+ * @since 3.0
+ */
+void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException;
+/**
  * Creates and returns an import declaration in this compilation unit
  * with the given name.
  * <p>
@@ -51,7 +110,7 @@
  * @param monitor the progress monitor to notify
  * @return the newly inserted import declaration (or the previously existing one in case attempting to create a duplicate)
  *
- * @exception JavaModelException if the element could not be created. Reasons include:
+ * @throws JavaModelException if the element could not be created. Reasons include:
  * <ul>
  * <li> This Java element does not exist or the specified sibling does not exist (ELEMENT_DOES_NOT_EXIST)</li>
  * <li> A <code>CoreException</code> occurred while updating an underlying resource
@@ -71,7 +130,7 @@
  * @param monitor the progress monitor to notify
  * @return the newly inserted package declaration (or the previously existing one in case attempting to create a duplicate)
  *
- * @exception JavaModelException if the element could not be created. Reasons include:
+ * @throws JavaModelException if the element could not be created. Reasons include:
  * <ul>
  * <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
  * <li> A <code>CoreException</code> occurred while updating an underlying resource
@@ -102,7 +161,7 @@
  * @param monitor the progress monitor to notify
  * @return the newly inserted type
  *
- * @exception JavaModelException if the element could not be created. Reasons include:
+ * @throws JavaModelException if the element could not be created. Reasons include:
  * <ul>
  * <li>The specified sibling element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
  * <li> A <code>CoreException</code> occurred while updating an underlying resource
@@ -113,13 +172,70 @@
  */
 IType createType(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws JavaModelException;
 /**
+ * Changes this compilation unit in working copy mode back to its original mode.
+ * <p>
+ * This has no effect if this compilation unit was not in working copy mode.
+ * </p>
+ * <p>
+ * If <code>becomeWorkingCopy</code> was called several times on this
+ * compilation unit, <code>discardWorkingCopy</code> must be called as 
+ * many times before it switches back to the original mode.
+ * </p>
+ * 
+ * @throws JavaModelException if this working copy could not return in its original mode.
+ * @see #becomeWorkingCopy(IProblemRequestor, IProgressMonitor)
+ * @since 3.0
+ */
+void discardWorkingCopy() throws JavaModelException;
+/** 
+ * Finds the elements in this compilation unit that correspond to
+ * the given element.
+ * An element A corresponds to an element B if:
+ * <ul>
+ * <li>A has the same element name as B.
+ * <li>If A is a method, A must have the same number of arguments as
+ *     B and the simple names of the argument types must be equals.
+ * <li>The parent of A corresponds to the parent of B recursively up to
+ *     their respective compilation units.
+ * <li>A exists.
+ * </ul>
+ * Returns <code>null</code> if no such java elements can be found
+ * or if the given element is not included in a compilation unit.
+ * 
+ * @param element the given element
+ * @return the found elements in this compilation unit that correspond to the given element
+ * @since 3.0 
+ */
+IJavaElement[] findElements(IJavaElement element);
+/**
+ * Finds the primary type of this compilation unit (that is, the type with the same name as the
+ * compilation unit), or <code>null</code> if no such a type exists.
+ * 
+ * @return the found primary type of this compilation unit, or <code>null</code> if no such a type exists
+ * @since 3.0
+ */
+IType findPrimaryType();
+/**
+ * Finds the working copy for this compilation unit, given a <code>WorkingCopyOwner</code>. 
+ * If no working copy has been created for this compilation unit associated with this
+ * working copy owner, returns <code>null</code>.
+ * <p>
+ * Users of this method must not destroy the resulting working copy. 
+ * 
+ * @param owner the given <code>WorkingCopyOwner</code>
+ * @return the found working copy for this compilation unit, <code>null</code> if none
+ * @see WorkingCopyOwner
+ * @since 3.0
+ */
+ICompilationUnit findWorkingCopy(WorkingCopyOwner owner);
+/**
  * Returns all types declared in this compilation unit in the order
  * in which they appear in the source. 
  * This includes all top-level types and nested member types.
  * It does NOT include local types (types defined in methods).
  *
  * @return the array of top-level and member types defined in a compilation unit, in declaration order.
- * @exception JavaModelException if this element does not exist or if an
+ * @throws JavaModelException if this element does not exist or if an
  *		exception occurs while accessing its corresponding resource
  */
 IType[] getAllTypes() throws JavaModelException;
@@ -133,7 +249,7 @@
  * @param position a source position inside the compilation unit
  * @return the innermost Java element enclosing a given source position or <code>null</code>
  *	if none (excluding the compilation unit).
- * @exception JavaModelException if the compilation unit does not exist or if an
+ * @throws JavaModelException if the compilation unit does not exist or if an
  *		exception occurs while accessing its corresponding resource
  */
 IJavaElement getElementAt(int position) throws JavaModelException;
@@ -163,16 +279,39 @@
  * a convenience method - import declarations can also be
  * accessed from a compilation unit's import container.
  *
- * @exception JavaModelException if this element does not exist or if an
+ * @return the import declarations in this compilation unit
+ * @throws JavaModelException if this element does not exist or if an
  *		exception occurs while accessing its corresponding resource
  */
 IImportDeclaration[] getImports() throws JavaModelException;
 /**
+ * Returns the primary compilation unit (whose owner is the primary owner)
+ * this working copy was created from, or this compilation unit if this a primary
+ * compilation unit.
+ * <p>
+ * Note that the returned primary compilation unit can be in working copy mode.
+ * </p>
+ * 
+ * @return the primary compilation unit this working copy was created from,
+ * or this compilation unit if it is primary
+ * @since 3.0
+ */
+ICompilationUnit getPrimary();
+/**
+ * Returns the working copy owner of this working copy.
+ * Returns null if it is not a working copy or if it has no owner.
+ * 
+ * @return WorkingCopyOwner the owner of this working copy or <code>null</code>
+ * @since 3.0
+ */
+WorkingCopyOwner getOwner();
+/**
  * Returns the first package declaration in this compilation unit with the given package name
  * (there normally is at most one package declaration).
  * This is a handle-only method. The package declaration may or may not exist.
  *
  * @param name the name of the package declaration as defined by JLS2 7.4. (For example, <code>"java.lang"</code>)
+ * @return the first package declaration in this compilation unit with the given package name
  */
 IPackageDeclaration getPackageDeclaration(String name);
 /**
@@ -182,7 +321,7 @@
  *
  * @return an array of package declaration (normally of size one)
  *
- * @exception JavaModelException if this element does not exist or if an
+ * @throws JavaModelException if this element does not exist or if an
  *		exception occurs while accessing its corresponding resource
  */
 IPackageDeclaration[] getPackageDeclarations() throws JavaModelException;
@@ -200,9 +339,178 @@
  * Returns the top-level types declared in this compilation unit
  * in the order in which they appear in the source.
  *
- * @exception JavaModelException if this element does not exist or if an
+ * @return the top-level types declared in this compilation unit
+ * @throws JavaModelException if this element does not exist or if an
  *		exception occurs while accessing its corresponding resource
  */
 IType[] getTypes() throws JavaModelException;
+/**
+ * Returns a new working copy of this compilation unit if it is a primary compilation unit, 
+ * or this compilation unit if it is already a non-primary working copy.
+ * <p>
+ * Note: if intending to share a working copy amongst several clients, then 
+ * <code>#getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)</code> 
+ * should be used instead.
+ * </p><p>
+ * When the working copy instance is created, an ADDED IJavaElementDelta is 
+ * reported on this working copy.
+ * </p><p>
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * </p>
+* @param monitor a progress monitor used to report progress while opening this compilation unit
+ *                 or <code>null</code> if no progress should be reported 
+ * @throws JavaModelException if the contents of this element can
+ *   not be determined. 
+ * @return a new working copy of this element if this element is not
+ * a working copy, or this element if this element is already a working copy
+ * @since 3.0
+ */
+ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Returns a shared working copy on this compilation unit using the given working copy owner to create
+ * the buffer, or this compilation unit if it is already a non-primary working copy.
+ * This API can only answer an already existing working copy if it is based on the same
+ * original compilation unit AND was using the same working copy owner (that is, as defined by <code>Object.equals</code>).	 
+ * <p>
+ * The life time of a shared working copy is as follows:
+ * <ul>
+ * <li>The first call to <code>getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)</code> 
+ * 	creates a new working copy for this element</li>
+ * <li>Subsequent calls increment an internal counter.</li>
+ * <li>A call to <code>discardWorkingCopy()</code> decrements the internal counter.</li>
+ * <li>When this counter is 0, the working copy is discarded.
+ * </ul>
+ * So users of this method must discard exactly once the working copy.
+ * <p>
+ * Note that the working copy owner will be used for the life time of this working copy, that is if the 
+ * working copy is closed then reopened, this owner will be used.
+ * The buffer will be automatically initialized with the original's compilation unit content
+ * upon creation.
+ * <p>
+ * When the shared working copy instance is created, an ADDED IJavaElementDelta is reported on this
+ * working copy.
+ * </p><p>
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * </p>
+ * @param owner the working copy owner that creates a buffer that is used to get the content 
+ * 				of the working copy
+ * @param problemRequestor a requestor which will get notified of problems detected during
+ * 	reconciling as they are discovered. The requestor can be set to <code>null</code> indicating
+ * 	that the client is not interested in problems.
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ *                 or <code>null</code> if no progress should be reported 
+ * @throws JavaModelException if the contents of this element can
+ *   not be determined. 
+ * @return a new working copy of this element using the given factory to create
+ * the buffer, or this element if this element is already a working copy
+ * @since 3.0
+ */
+ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Returns whether the resource of this working copy has changed since the
+ * inception of this working copy.
+ * Returns <code>false</code> if this compilation unit is not in working copy mode.
+ * 
+ * @return whether the resource has changed
+ * @since 3.0
+ */
+public boolean hasResourceChanged();
+/**
+ * Returns whether this element is a working copy.
+ * 
+ * @return true if this element is a working copy, false otherwise
+ * @since 3.0
+ */
+boolean isWorkingCopy();
 
+/**
+ * Reconciles the contents of this working copy, and sends out a Java delta
+ * notification indicating the nature of the change of the working copy since
+ * the last time it was either reconciled or made consistent 
+ * (see <code>IOpenable#makeConsistent()</code>).
+ * .<p>
+ * It performs the reconciliation by locally caching the contents of 
+ * the working copy, updating the contents, then creating a delta 
+ * over the cached contents and the new contents, and finally firing
+ * this delta.
+ * <p>
+ * The boolean argument allows to force problem detection even if the
+ * working copy is already consistent.</p>
+ * <p>
+ * Compilation problems found in the new contents are notified through the
+ * <code>IProblemRequestor</code> interface which was passed at
+ * creation, and no longer as transient markers. Therefore this API answers
+ * nothing.</p>
+ * <p>
+ * Note: Since 3.0 added/removed/changed inner types generate change deltas.</p>
+ * <p>
+ * @param forceProblemDetection boolean indicating whether problem should be recomputed
+ *   even if the source hasn't changed.
+ * @param monitor a progress monitor
+ * @throws JavaModelException if the contents of the original element
+ *		cannot be accessed. Reasons include:
+ * <ul>
+ * <li> The original Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ * @since 3.0
+ */
+void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Reconciles the contents of this working copy, and sends out a Java delta
+ * notification indicating the nature of the change of the working copy since
+ * the last time it was either reconciled or made consistent 
+ * (see <code>IOpenable#makeConsistent()</code>).
+ * .<p>.
+ * It performs the reconciliation by locally caching the contents of 
+ * the working copy, updating the contents, then creating a delta 
+ * over the cached contents and the new contents, and finally firing
+ * this delta.
+ * <p>
+ * The boolean argument allows to force problem detection even if the
+ * working copy is already consistent.
+ * </p><p>
+ * This functionality allows to specify a working copy owner which is used during problem detection.
+ * All references contained in the working copy are resolved against other units; for which corresponding 
+ * owned working copies are going to take precedence over their original compilation units. 
+ * </p><p>
+ * Compilation problems found in the new contents are notified through the
+ * <code>IProblemRequestor</code> interface which was passed at
+ * creation, and no longer as transient markers. Therefore this API answers
+ * nothing.
+ * </p><p>
+ * Note: Since 3.0 added/removed/changed inner types generate change deltas.</p>
+ * </p>
+ *
+ * @param forceProblemDetection boolean indicating whether problem should be recomputed
+ *   even if the source hasn't changed.
+ * @param owner the owner of working copies that take precedence over the original compilation units
+ * @param monitor a progress monitor
+ * @throws JavaModelException if the contents of the original element
+ *		cannot be accessed. Reasons include:
+ * <ul>
+ * <li> The original Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ * @since 3.0
+ */
+void reconcile(boolean forceProblemDetection, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
+/**
+ * Restores the contents of this working copy to the current contents of
+ * this working copy's original element. Has no effect if this element
+ * is not a working copy.
+ *
+ * <p>Note: This is the inverse of committing the content of the
+ * working copy to the original element with <code>commit(boolean, IProgressMonitor)</code>.
+ *
+ * @throws JavaModelException if the contents of the original element
+ *		cannot be accessed.  Reasons include:
+ * <ul>
+ * <li> The original Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ * @since 3.0
+ */
+void restore() throws JavaModelException;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java
index edcce37..d56212b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompletionRequestor.java
@@ -29,23 +29,18 @@
  * 		new anonymous type declaration .
  * 
  * @param superTypeName Name of the super type of this new anonymous type declaration.
- * 
  * @param parameterPackageNames Names of the packages in which the parameter types are declared.
  *    	Should contain as many elements as parameterTypeNames.
- * 
- * @param parameterTypeNames Names of the parameters types. 
+ * @param parameterTypeNames Names of the parameter types. 
  * 		Should contain as many elements as parameterPackageNames.
- * 
+ * @param parameterNames Names of the parameters. 
+ * 		Should contain as many elements as parameterPackageNames.
  * @param completionName The completion for the anonymous type declaration.
  * 		Can include zero, one or two brackets. If the closing bracket is included,
  * 		then the cursor should be placed before it.
- * 
  * @param modifiers The modifiers of the constructor.
- * 
  * @param completionStart The start position of insertion of the name of this new anonymous type declaration.
- * 
  * @param completionEnd The end position of insertion of the name of this new anonymous type declaration.
- * 
  * @param relevance The relevance of the completion proposal
  * 		It is a positive integer which are used for determine if this proposal is more relevant than another proposal.
  * 		This value can only be used for compare relevance. A proposal is more relevant than another if his relevance
@@ -149,7 +144,7 @@
  * Code assist notification of an interface completion.
  * 
  * @param packageName Declaring package name of the interface.
- * @param className Name of the interface.
+ * @param interfaceName Name of the interface.
  * @param completionName The completion for the interface.	Can include ';' for imported interfaces.
  * @param modifiers The modifiers of the interface.
  * @param completionStart The start position of insertion of the name of the interface.
@@ -232,7 +227,9 @@
  * @param selector Name of the new method.
  * @param parameterPackageNames Names of the packages in which the parameter types are declared.
  *    	Should contain as many elements as parameterTypeNames.
- * @param parameterTypeNames Names of the parameters types.
+ * @param parameterTypeNames Names of the parameter types.
+ *    	Should contain as many elements as parameterPackageNames.
+ * @param parameterNames Names of the parameters.
  *    	Should contain as many elements as parameterPackageNames.
  * @param returnTypePackageName Name of the package in which the return type is declared.
  * @param returnTypeName Name of the return type of this new method, should be <code>null</code> for a constructor.
@@ -277,7 +274,9 @@
  * @param selector Name of the new method.
  * @param parameterPackageNames Names of the packages in which the parameter types are declared.
  *    	Should contain as many elements as parameterTypeNames.
- * @param parameterTypeNames Names of the parameters types.
+ * @param parameterTypeNames Names of the parameter types.
+ *    	Should contain as many elements as parameterPackageNames.
+ * @param parameterNames Names of the parameters.
  *    	Should contain as many elements as parameterPackageNames.
  * @param returnTypePackageName Name of the package in which the return type is declared.
  * @param returnTypeName Name of the return type of this new method, should be <code>null</code> for a constructor.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICorrectionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICorrectionRequestor.java
index fb8e54a..b22e019 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICorrectionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICorrectionRequestor.java
@@ -72,7 +72,7 @@
  * Notification of an interface correction.
  *
  * @param packageName Declaring package name of the interface.
- * @param className Name of the interface.
+ * @param interfaceName Name of the interface.
  * @param correctionName The correction for the interface.
  *   Can include ';' for imported interfaces.
  * @param modifiers The modifiers of the interface.
@@ -123,7 +123,9 @@
  * @param selector Name of the method.
  * @param parameterPackageNames Names of the packages in which the parameter types are declared.
  *    Should contain as many elements as parameterTypeNames.
- * @param parameterTypeNames Names of the parameters types.
+ * @param parameterTypeNames Names of the parameter types.
+ *    Should contain as many elements as parameterPackageNames.
+ * @param parameterNames Names of the parameters.
  *    Should contain as many elements as parameterPackageNames.
  * @param returnTypePackageName Name of the package in which the return type is declared.
  * @param returnTypeName Name of the return type of this method, should be <code>null</code> for a constructor.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IField.java
index 3260d86..2bccd29 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IField.java
@@ -19,11 +19,69 @@
 public interface IField extends IMember {
 /**
  * Returns the constant value associated with this field
- * or <code>null</code> if this field has none.
- * Returns either a subclass of <code>Number</code>, or a <code>String</code>,
- * depending on the type of the field.
- * For example, if the field is of type <code>short</code>, this returns
- * a <code>Short</code>.
+ * or <code>null</code> if this field has none. The field needs to be static and final to have
+ * a constant value.
+ * Returns an instance of the wrapper type corresponding to the the type of the field.
+ * <table border="1">
+ * <tr>
+ * <th>field type</th>
+ * <th>wrapper type</th>
+ * </tr>
+ * <tr>
+ * <td>int
+ * </td>
+ * <td>java.lang.Integer
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>byte
+ * </td>
+ * <td>java.lang.Byte
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>boolean
+ * </td>
+ * <td>java.lang.Boolean
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>char
+ * </td>
+ * <td>java.lang.Character
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>double
+ * </td>
+ * <td>java.lang.Double
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>float
+ * </td>
+ * <td>java.lang.Float
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>long
+ * </td>
+ * <td>java.lang.Long
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>short
+ * </td>
+ * <td>java.lang.Short
+ * </td>
+ * </tr>
+ * <tr>
+ * <td>java.lang.String
+ * </td>
+ * <td>java.lang.String
+ * </td>
+ * </tr>
+ * </table>
  *
  * @return  the constant value associated with this field or <code>null</code> if this field has none.
  * @exception JavaModelException if this element does not exist or if an
@@ -38,10 +96,10 @@
 /**
  * Returns the type signature of this field.
  *
- * @see Signature
  * @return the type signature of this field.
  * @exception JavaModelException if this element does not exist or if an
  *      exception occurs while accessing its corresponding resource
+ * @see Signature
  */
 String getTypeSignature() throws JavaModelException;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportDeclaration.java
index c000b96..1c49ffc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportDeclaration.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IImportDeclaration.java
@@ -29,6 +29,24 @@
  */
 String getElementName();
 /**
+ * Returns the modifier flags for this import. The flags can be examined using class
+ * <code>Flags</code>. Only the static flag is meaningful for import declarations.
+ * <p>
+ * Note: Static imports are an experimental language feature 
+ * under discussion in JSR-201 and under consideration for inclusion
+ * in the 1.5 release of J2SE. The support here is therefore tentative
+ * and subject to change.
+ * </p>
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource.
+ * @return the modifier flags for this import
+ * @see Flags
+ * @since 3.0
+ */
+// TODO 1.5 feature disabled for now, will re-enable at a later stage
+//int getFlags() throws JavaModelException;
+
+/**
  * Returns whether the import is on-demand. An import is on-demand if it ends
  * with <code>".*"</code>.
  * @return true if the import is on-demand, false otherwise
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IInitializer.java
index e291d19..36e75b2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IInitializer.java
@@ -17,4 +17,5 @@
  * </p>
  */
 public interface IInitializer extends IMember {
+	// interface used as a marker: defines no member
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
index 1fa8c15..f456b6e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java
@@ -109,6 +109,13 @@
 	 * A Java element with this type can be safely cast to <code>IImportDeclaration</code>.
 	 */
 	int IMPORT_DECLARATION = 13;
+	
+	/**
+	 * Constant representing a local variable declaration.
+	 * A Java element with this type can be safely cast to <code>ILocalVariable</code>.
+	 * @since 3.0
+	 */
+	int LOCAL_VARIABLE = 14;
 
 	/**
 	 * Returns whether this Java element exists in the model.
@@ -245,6 +252,19 @@
 	 * @since 2.0
 	 */
 	IPath getPath();
+	
+	/**
+	 * Returns the primary element (whose compilation unit is the primary compilation unit)
+	 * this working copy element was created from, or this element if it is a descendant of a
+	 * primary compilation unit or if it is not a descendant of a working copy (e.g. it is a
+	 * binary member).
+	 * The returned element may or may not exist.
+	 * 
+	 * @return the primary element this working copy element was created from, or this
+	 * 			element.
+	 * @since 3.0
+	 */
+	IJavaElement getPrimaryElement();
 
 	/**
 	 * Returns the innermost resource enclosing this element. 
@@ -252,11 +272,10 @@
 	 * this is the underlying resource corresponding to the archive. 
 	 * If this element is included in an external archive, <code>null</code>
 	 * is returned.
-	 * If this element is a working copy, <code>null</code> is returned.
 	 * This is a handle-only method.
 	 * 
 	 * @return the innermost resource enclosing this element, <code>null</code> if this 
-	 * element is a working copy or is included in an external archive
+	 * element is included in an external archive
 	 * @since 2.0
 	 */
 	IResource getResource();
@@ -299,6 +318,6 @@
 	 * @return <code>true</code> if the structure of this element is known
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource
-	 */
+	 */// TODO (philippe) predicate shouldn't throw an exception
 	boolean isStructureKnown() throws JavaModelException;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java
index 8e12ffc..58f2078 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElementDelta.java
@@ -120,7 +120,7 @@
 	 * Status constant indicating that the element has been changed,
 	 * as described by the change flags.
 	 * 
-	 * @see #getFlags
+	 * @see #getFlags()
 	 */
 	public int CHANGED = 4;
 
@@ -128,50 +128,50 @@
 	 * Change flag indicating that the content of the element has changed.
 	 * This flag is only valid for elements which correspond to files.
 	 */
-	public int F_CONTENT = 0x0001;
+	public int F_CONTENT = 0x00001;
 
 	/**
 	 * Change flag indicating that the modifiers of the element have changed.
 	 * This flag is only valid if the element is an <code>IMember</code>. 
 	 */
-	public int F_MODIFIERS = 0x0002;
+	public int F_MODIFIERS = 0x00002;
 
 	/**
 	 * Change flag indicating that there are changes to the children of the element.
 	 * This flag is only valid if the element is an <code>IParent</code>. 
 	 */
-	public int F_CHILDREN = 0x0008;
+	public int F_CHILDREN = 0x00008;
 
 	/**
 	 * Change flag indicating that the element was moved from another location.
 	 * The location of the old element can be retrieved using <code>getMovedFromElement</code>.
 	 */
-	public int F_MOVED_FROM = 0x0010;
+	public int F_MOVED_FROM = 0x00010;
 
 	/**
 	 * Change flag indicating that the element was moved to another location.
 	 * The location of the new element can be retrieved using <code>getMovedToElement</code>.
 	 */
-	public int F_MOVED_TO = 0x0020;
+	public int F_MOVED_TO = 0x00020;
 
 	/**
 	 * Change flag indicating that a classpath entry corresponding to the element has been added to the project's classpath. 
 	 * This flag is only valid if the element is an <code>IPackageFragmentRoot</code>.
 	 */
-	public int F_ADDED_TO_CLASSPATH = 0x0040;
+	public int F_ADDED_TO_CLASSPATH = 0x00040;
 
 	/**
 	 * Change flag indicating that a classpath entry corresponding to the element has been removed from the project's 
 	 * classpath. This flag is only valid if the element is an <code>IPackageFragmentRoot</code>.
 	 */
-	public int F_REMOVED_FROM_CLASSPATH = 0x0080;
+	public int F_REMOVED_FROM_CLASSPATH = 0x00080;
 
 	/**
 	 * Change flag indicating that a classpath entry corresponding to the element has changed position in the project's 
 	 * classpath. This flag is only valid if the element is an <code>IPackageFragmentRoot</code>.
 	 * @deprecated Use F_REORDER instead.
 	 */
-	public int F_CLASSPATH_REORDER = 0x0100;
+	public int F_CLASSPATH_REORDER = 0x00100;
 	/**
 	 * Change flag indicating that the element has changed position relatively to its siblings. 
 	 * If the element is an <code>IPackageFragmentRoot</code>,  a classpath entry corresponding 
@@ -179,39 +179,39 @@
 	 * 
 	 * @since 2.1
 	 */
-	public int F_REORDER = 0x0100;
+	public int F_REORDER = 0x00100;
 
 	/**
 	 * Change flag indicating that the underlying <code>IProject</code> has been
 	 * opened. This flag is only valid if the element is an <code>IJavaProject</code>. 
 	 */
-	public int F_OPENED = 0x0200;
+	public int F_OPENED = 0x00200;
 
 	/**
 	 * Change flag indicating that the underlying <code>IProject</code> has been
 	 * closed. This flag is only valid if the element is an <code>IJavaProject</code>. 
 	 */
-	public int F_CLOSED = 0x0400;
+	public int F_CLOSED = 0x00400;
 
 	/**
 	 * Change flag indicating that one of the supertypes of an <code>IType</code>
 	 * has changed.
 	 */
-	public int F_SUPER_TYPES = 0x0800;
+	public int F_SUPER_TYPES = 0x00800;
 
 	/**
 	 * Change flag indicating that the source attachment path or the source attachment root path of a classpath entry 
 	 * corresponding to the element was added. This flag is only valid if the element is an 
 	 * <code>IPackageFragmentRoot</code>.
 	 */
-	public int F_SOURCEATTACHED = 0x1000;	
+	public int F_SOURCEATTACHED = 0x01000;	
 
 	/**
 	 * Change flag indicating that the source attachment path or the source attachment root path of a classpath entry 
 	 * corresponding to the element was removed. This flag is only valid if the element is an 
 	 * <code>IPackageFragmentRoot</code>.
 	 */
-	public int F_SOURCEDETACHED = 0x2000;	
+	public int F_SOURCEDETACHED = 0x02000;	
 	
 	/**
 	 * Change flag indicating that this is a fine-grained delta, that is, an analysis down
@@ -226,17 +226,26 @@
      * 
      * @since 2.0
 	 */
-	public int F_FINE_GRAINED = 0x4000;
+	public int F_FINE_GRAINED = 0x04000;
 
 	/**
 	 * Change flag indicating that the element's archive content on the classpath has changed.
 	 * This flag is only valid if the element is an <code>IPackageFragmentRoot</code>
 	 * which is an archive.
 	 * 
-	 * @see IPackageFragmentRoot#isArchive
+	 * @see IPackageFragmentRoot#isArchive()
 	 * @since 2.0
 	 */
-	public int F_ARCHIVE_CONTENT_CHANGED = 0x8000;
+	public int F_ARCHIVE_CONTENT_CHANGED = 0x08000;
+	
+	/**
+	 * Change flag indicating that a compilation unit has become a primary working copy, or that a 
+	 * primary working copy has reverted to a compilation unit.
+	 * This flag is only valid if the element is an <code>ICompilationUnit</code>.
+	 * 
+	 * @since 3.0
+	 */
+	public int F_PRIMARY_WORKING_COPY = 0x10000;
 
 	/**
 	 * Returns deltas for the children that have been added.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModel.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModel.java
index 3133336..f83eb35 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModel.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModel.java
@@ -117,6 +117,7 @@
  * Returns the Java project with the given name. This is a handle-only method. 
  * The project may or may not exist.
  * 
+ * @param name the name of the Java project
  * @return the Java project with the given name
  */
 IJavaProject getJavaProject(String name);
@@ -137,7 +138,8 @@
  * Java nature).
  * </p>
  * 
- * @return an array of non-Java projects contained in the workspace.
+ * @return an array of non-Java projects (<code>IProject</code>s) contained 
+ *              in the workspace.
  * @throws JavaModelException if this element does not exist or if an
  *		exception occurs while accessing its corresponding resource
  * @since 2.1
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java
index 080e0ad..abc574d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelMarker.java
@@ -26,7 +26,6 @@
 	 */
 	public static final String JAVA_MODEL_PROBLEM_MARKER = JavaCore.PLUGIN_ID + ".problem"; //$NON-NLS-1$
 
-
 	/**
 	 * Java model transient problem marker type (value <code>"org.eclipse.jdt.core.transient_problem"</code>).
 	 * This can be used to recognize those markers in the workspace that flag transient
@@ -44,7 +43,6 @@
 	 * @since 2.1
 	 */
 	public static final String TASK_MARKER = JavaCore.PLUGIN_ID + ".task"; //$NON-NLS-1$
-
     
     /** 
 	 * Id marker attribute (value <code>"arguments"</code>).
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
index da8149c..82d95ad 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
@@ -7,6 +7,9 @@
  * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ * 
+ * TODO missing 2.1 and subsequent contributions
+ * COMPILER_FAILURE
  *******************************************************************************/
 package org.eclipse.jdt.core;
 
@@ -75,7 +78,7 @@
 	 * supplied do not exist. 
 	 * The element(s) can be retrieved using <code>getElements</code> on the status object.
 	 *
-	 * @see IJavaModelStatus#isDoesNotExist
+	 * @see IJavaModelStatus#isDoesNotExist()
 	 */
 	public static final int ELEMENT_DOES_NOT_EXIST = 969;
 
@@ -280,4 +283,18 @@
 	 * @since 2.1
 	 */
 	public static final int DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS = 1003;
+	
+	/**
+	 * Status constant indicating that a project is prerequisiting some library for which the
+	 * classfile JDK version level is more recent than the project JDK target level setting. 
+	 * This can indicate some binary incompatibility issues later on.
+	 * @since 3.0
+	 */
+	public static final int INCOMPATIBLE_JDK_LEVEL	= 1004;
+	
+	/**
+	 * Status constant indicating that a compiler failure occurred.
+	 * @since 3.0
+	 */
+	public static final int COMPILER_FAILURE	= 1005;	
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
index c386f85..c80de67 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
@@ -11,6 +11,8 @@
  *     IBM Corporation - deprecated getPackageFragmentRoots(IClasspathEntry) and 
  *                               added findPackageFragmentRoots(IClasspathEntry)
  *     IBM Corporation - added isOnClasspath(IResource)
+ *     IBM Corporation - added setOption(String, String)
+ *     IBM Corporation - added forceClasspathReload(IProgressMonitor)
  *******************************************************************************/
 package org.eclipse.jdt.core;
 
@@ -77,6 +79,33 @@
 	 * <code>IJavaElement</code> is found
 	 */
 	IJavaElement findElement(IPath path) throws JavaModelException;
+	
+	/**
+	 * Returns the <code>IJavaElement</code> corresponding to the given
+	 * classpath-relative path, or <code>null</code> if no such 
+	 * <code>IJavaElement</code> is found. The result is one of an
+	 * <code>ICompilationUnit</code>, <code>IClassFile</code>, or
+	 * <code>IPackageFragment</code>. If it is an <code>ICompilationUnit</code>,
+	 * its owner is the given owner.
+	 * <p>
+	 * When looking for a package fragment, there might be several potential
+	 * matches; only one of them is returned.
+	 *
+	 * <p>For example, the path "java/lang/Object.java", would result in the
+	 * <code>ICompilationUnit</code> or <code>IClassFile</code> corresponding to
+	 * "java.lang.Object". The path "java/lang" would result in the
+	 * <code>IPackageFragment</code> for "java.lang".
+	 * @param path the given classpath-relative path
+	 * @param owner the owner of the returned compilation unit, ignored if it is
+	 *   not a compilation unit.
+	 * @exception JavaModelException if the given path is <code>null</code>
+	 *  or absolute
+	 * @return the <code>IJavaElement</code> corresponding to the given
+	 * classpath-relative path, or <code>null</code> if no such 
+	 * <code>IJavaElement</code> is found
+	 * @since 3.0
+	 */
+	IJavaElement findElement(IPath path, WorkingCopyOwner owner) throws JavaModelException;
 
 	/**
 	 * Returns the first existing package fragment on this project's classpath
@@ -136,6 +165,7 @@
 	 * a class B defined as a member type of a class A in package x.y should have a 
 	 * the fully qualified name "x.y.A.B".
 	 * 
+	 * TODO (kent) need to change spec if secondary types are found
 	 * Note that in order to be found, a type name (or its toplevel enclosing
 	 * type name) must match its corresponding compilation unit name. As a 
 	 * consequence, secondary types cannot be found using this functionality.
@@ -153,6 +183,32 @@
 	IType findType(String fullyQualifiedName) throws JavaModelException;
 	/**
 	 * Returns the first type found following this project's classpath 
+	 * with the given fully qualified name or <code>null</code> if none is found.
+	 * The fully qualified name is a dot-separated name. For example,
+	 * a class B defined as a member type of a class A in package x.y should have a 
+	 * the fully qualified name "x.y.A.B".
+	 * If the returned type is part of a compilation unit, its owner is the given
+	 * owner.
+	 * 
+	 * TODO (kent) need to change spec if secondary types are found
+	 * Note that in order to be found, a type name (or its toplevel enclosing
+	 * type name) must match its corresponding compilation unit name. As a 
+	 * consequence, secondary types cannot be found using this functionality.
+	 * Secondary types can however be explicitely accessed through their enclosing
+	 * unit or found by the <code>SearchEngine</code>.
+	 * 
+	 * @param fullyQualifiedName the given fully qualified name
+	 * @param owner the owner of the returned type's compilation unit
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource
+	 * @return the first type found following this project's classpath 
+	 * with the given fully qualified name or <code>null</code> if none is found
+	 * @see IType#getFullyQualifiedName(char)
+	 * @since 3.0
+	 */
+	IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException;
+	/**
+	 * Returns the first type found following this project's classpath 
 	 * with the given package name and type qualified name
 	 * or <code>null</code> if none is found.
 	 * The package name is a dot-separated name.
@@ -160,6 +216,7 @@
 	 * a class B defined as a member type of a class A should have the 
 	 * type qualified name "A.B".
 	 * 
+	 * TODO (kent) need to change spec if secondary types are found
 	 * Note that in order to be found, a type name (or its toplevel enclosing
 	 * type name) must match its corresponding compilation unit name. As a 
 	 * consequence, secondary types cannot be found using this functionality.
@@ -174,11 +231,40 @@
 	 * with the given package name and type qualified name
 	 * or <code>null</code> if none is found
 	 * @see IType#getTypeQualifiedName(char)
-
 	 * @since 2.0
 	 */
 	IType findType(String packageName, String typeQualifiedName) throws JavaModelException;
-
+	/**
+	 * Returns the first type found following this project's classpath 
+	 * with the given package name and type qualified name
+	 * or <code>null</code> if none is found.
+	 * The package name is a dot-separated name.
+	 * The type qualified name is also a dot-separated name. For example,
+	 * a class B defined as a member type of a class A should have the 
+	 * type qualified name "A.B".
+	 * If the returned type is part of a compilation unit, its owner is the given
+	 * owner.
+	 * 
+	 * TODO (kent) need to change spec if secondary types are found
+	 * Note that in order to be found, a type name (or its toplevel enclosing
+	 * type name) must match its corresponding compilation unit name. As a 
+	 * consequence, secondary types cannot be found using this functionality.
+	 * Secondary types can however be explicitely accessed through their enclosing
+	 * unit or found by the <code>SearchEngine</code>.
+	 * 
+	 * @param packageName the given package name
+	 * @param typeQualifiedName the given type qualified name
+	 * @param owner the owner of the returned type's compilation unit
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource
+	 * @return the first type found following this project's classpath 
+	 * with the given package name and type qualified name
+	 * or <code>null</code> if none is found
+	 * @see IType#getTypeQualifiedName(char)
+	 * @since 3.0
+	 */
+	IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException;
+	
 	/**
 	 * Returns all of the existing package fragment roots that exist
 	 * on the classpath, in the order they are defined by the classpath.
@@ -203,7 +289,8 @@
 	 * (possibly in a folder)
 	 * </p>
 	 * 
-	 * @return an array of non-Java resources directly contained in this project
+	 * @return an array of non-Java resources (<code>IFile</code>s and/or 
+	 *              <code>IFolder</code>s) directly contained in this project
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource
 	 */
@@ -219,7 +306,7 @@
 	 * @param optionName the name of an option
 	 * @param inheritJavaCoreOptions - boolean indicating whether JavaCore options should be inherited as well
 	 * @return the String value of a given option
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#getDefaultOptions()
 	 * @since 2.1
 	 */
 	String getOption(String optionName, boolean inheritJavaCoreOptions);
@@ -235,7 +322,7 @@
 	 * @param inheritJavaCoreOptions - boolean indicating whether JavaCore options should be inherited as well
 	 * @return table of current settings of all options 
 	 *   (key type: <code>String</code>; value type: <code>String</code>)
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#getDefaultOptions()
 	 * @since 2.1
 	 */
 	Map getOptions(boolean inheritJavaCoreOptions);
@@ -257,8 +344,8 @@
 	 * 
 	 * @return the workspace-relative absolute path of the default output folder
 	 * @exception JavaModelException if this element does not exist
-	 * @see #setOutputLocation
-	 * @see IClasspathEntry#getOutputLocation
+	 * @see #setOutputLocation(org.eclipse.core.runtime.IPath, IProgressMonitor)
+	 * @see IClasspathEntry#getOutputLocation()
 	 */
 	IPath getOutputLocation() throws JavaModelException;
 
@@ -353,6 +440,7 @@
 	 * A classpath variable provides an indirection level for better sharing a classpath. As an example, it allows
 	 * a classpath to no longer refer directly to external JARs located in some user specific location. The classpath
 	 * can simply refer to some variables defining the proper locations of these external JARs.
+	 * TODO (jim) please reformulate to include classpath containers in resolution aspects
 	 *  <p>
 	 * Note that in case the project isn't yet opened, the classpath will directly be read from the associated <tt>.classpath</tt> file.
 	 * <p>
@@ -437,7 +525,7 @@
 	 * @param element the given element
 	 * @return <code>true</code> if the given element is on the classpath of
 	 * this project, <code>false</code> otherwise
-	 * @see IClasspathEntry#getExclusionPatterns
+	 * @see IClasspathEntry#getExclusionPatterns()
 	 * @since 2.0
 	 */
 	boolean isOnClasspath(IJavaElement element);
@@ -446,10 +534,10 @@
 	 * that is, referenced from a classpath entry and not explicitly excluded
 	 * using an exclusion pattern.
 	 * 
-	 * @param element the given element
+	 * @param resource the given resource
 	 * @return <code>true</code> if the given resource is on the classpath of
 	 * this project, <code>false</code> otherwise
-	 * @see IClasspathEntry#getExclusionPatterns
+	 * @see IClasspathEntry#getExclusionPatterns()
 	 * @since 2.1
 	 */
 	boolean isOnClasspath(IResource resource);
@@ -476,12 +564,36 @@
 		throws JavaModelException;
 
 	/**
+	 * Creates and returns a type hierarchy for all types in the given
+	 * region, considering subtypes within that region and considering types in the 
+	 * working copies with the given owner. 
+	 * In other words, the owner's working copies will take 
+	 * precedence over their original compilation units in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * <p>
+	 *
+	 * @param monitor the given progress monitor
+	 * @param region the given region
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource
+	 * @exception IllegalArgumentException if region is <code>null</code>
+	 * @return a type hierarchy for all types in the given
+	 * region, considering subtypes within that region
+	 * @since 3.0
+	 */
+	ITypeHierarchy newTypeHierarchy(IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)
+		throws JavaModelException;
+
+	/**
 	 * Creates and returns a type hierarchy for the given type considering
 	 * subtypes in the specified region.
 	 * 
-	 * @param monitor the given monitor
-	 * @param region the given region
 	 * @param type the given type
+	 * @param region the given region
+	 * @param monitor the given monitor
 	 * 
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource
@@ -497,6 +609,114 @@
 		throws JavaModelException;
 
 	/**
+	 * Creates and returns a type hierarchy for the given type considering
+	 * subtypes in the specified region and considering types in the 
+	 * working copies with the given owner. 
+	 * In other words, the owner's working copies will take 
+	 * precedence over their original compilation units in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * <p>
+	 * 
+	 * @param type the given type
+	 * @param region the given region
+	 * @param monitor the given monitor
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * 
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource
+	 *
+	 * @exception IllegalArgumentException if type or region is <code>null</code>
+	 * @return a type hierarchy for the given type considering
+	 * subtypes in the specified region
+	 * @since 3.0
+	 */
+	ITypeHierarchy newTypeHierarchy(
+		IType type,
+		IRegion region,
+		WorkingCopyOwner owner,
+		IProgressMonitor monitor)
+		throws JavaModelException;
+
+	/**
+	 * Returns the default output location for the project as defined by its <code>.classpath</code> file from disk, or <code>null</code>
+	 * if unable to read the file. 
+	 * <p>
+	 * This output location may differ from the in-memory one returned by <code>getOutputLocation</code>, in case the 
+	 * automatic reconciliation mechanism has not been performed yet. Usually, any change to the <code>.classpath</code> file 
+	 * is automatically noticed and reconciled at the next resource change notification event. 
+	 * However, if the file is modified within an operation, where this change needs to be taken into account before the 
+	 * operation ends, then the output location from disk can be read using this method, and further assigned to the project 
+	 * using <code>setRawClasspath(...)</code>.
+	 * <p>
+	 * The default output location is where class files are ordinarily generated
+	 * (and resource files, copied). Each source classpath entry can also
+	 * specify an output location for the generated class files (and copied
+	 * resource files) corresponding to compilation units under that source
+	 * folder. This makes it possible to arrange generated class files for
+	 * different source folders in different output folders, and not
+	 * necessarily the default output folder. This means that the generated
+	 * class files for the project may end up scattered across several folders,
+	 * rather than all in the default output folder (which is more standard).
+	 * <p>
+	 * In order to manually force a project classpath refresh, one can simply assign the project classpath using the result of this 
+	 * method, as follows:
+	 * <code>proj.setRawClasspath(proj.readRawClasspath(), proj.readOutputLocation(), monitor)</code>
+	 * (note that the <code>readRawClasspath/readOutputLocation</code> methods could return <code>null</code>).
+	 * <p>
+	 * @return the workspace-relative absolute path of the default output folder
+	 * @see #getOutputLocation()
+	 * @since 3.0
+	 */
+	IPath readOutputLocation();
+
+	/**
+	 * Returns the raw classpath for the project as defined by its <code>.classpath</code> file from disk, or <code>null</code>
+	 * if unable to read the file. 
+	 * <p>
+	 * This classpath may differ from the in-memory classpath returned by <code>getRawClasspath</code>, in case the 
+	 * automatic reconciliation mechanism has not been performed yet. Usually, any change to the <code>.classpath</code> file 
+	 * is automatically noticed and reconciled at the next resource change notification event. 
+	 * However, if the file is modified within an operation, where this change needs to be taken into account before the 
+	 * operation ends, then the classpath from disk can be read using this method, and further assigned to the project 
+	 * using <code>setRawClasspath(...)</code>.
+	 * <p>
+	 * A raw classpath may contain classpath variable and/or container entries. Classpath variable entries can be resolved 
+	 * individually (see <code>JavaCore#getClasspathVariable</code>), or the full classpath can be resolved at once using the 
+	 * helper method <code>getResolvedClasspath</code>.
+	 * TODO (jim) please reformulate to include classpath containers in resolution aspects
+	 * <p>
+	 * Note that no check is performed whether the project has the Java nature set, allowing an existing <code>.classpath</code> 
+	 * file to be considered independantly (unlike <code>getRawClasspath</code> which requires the Java nature to be associated 
+	 * with the project). 
+	 * <p>
+	 * In order to manually force a project classpath refresh, one can simply assign the project classpath using the result of this 
+	 * method, as follows:
+	 * <code>proj.setRawClasspath(proj.readRawClasspath(), proj.readOutputLocation(), monitor)</code>
+	 * (note that the <code>readRawClasspath/readOutputLocation</code> methods could return <code>null</code>).
+	 * <p>
+	 * @return the raw classpath from disk for the project, as a list of classpath entries
+	 * @see #getRawClasspath()
+	 * @see IClasspathEntry
+	 * @since 3.0
+	 */
+	IClasspathEntry[] readRawClasspath();
+
+	/**
+	 * Helper method for setting one option value only. Equivalent to <code>Map options = this.getOptions(false); map.put(optionName, optionValue); this.setOptions(map)</code>
+	 * <p>
+	 * For a complete description of the configurable options, see <code>JavaCore#getDefaultOptions</code>.
+	 * </p>
+	 * 
+	 * @param optionName the name of an option
+	 * @param optionValue the value of the option to set
+	 * @see JavaCore#getDefaultOptions()
+	 * @since 3.0
+	 */
+	void setOption(String optionName, String optionValue);
+
+	/**
 	 * Sets the project custom options. All and only the options explicitly included in the given table 
 	 * are remembered; all previous option settings are forgotten, including ones not explicitly
 	 * mentioned.
@@ -506,7 +726,7 @@
 	 * 
 	 * @param newOptions the new options (key type: <code>String</code>; value type: <code>String</code>),
 	 *   or <code>null</code> to flush all custom options (clients will automatically get the global JavaCore options).
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#getDefaultOptions()
 	 * @since 2.1
 	 */
 	void setOptions(Map newOptions);
@@ -538,8 +758,8 @@
 	 *  <li> The path is nested inside a package fragment root of this project (<code>INVALID_PATH</code>)
 	 *  <li> The output location is being modified during resource change event notification (CORE_EXCEPTION)	 
 	 * </ul>
-	 * @see #getOutputLocation
-     * @see IClasspathEntry#getOutputLocation
+	 * @see #getOutputLocation()
+     * @see IClasspathEntry#getOutputLocation()
 	 */
 	void setOutputLocation(IPath path, IProgressMonitor monitor)
 		throws JavaModelException;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ILocalVariable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ILocalVariable.java
new file mode 100644
index 0000000..f272190
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ILocalVariable.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.core;
+
+/**
+ * Represents a local variable declared in a method or an initializer.
+ * <code>ILocalVariable</code> are pseudo-elements created as the result of a <code>ICodeAssist.codeSelect(...)</code>
+ * operation. They are not part of the Java model (<code>exists()</code> returns whether the parent exists rather than 
+ * whether the local variable exists in the parent) and they are not included in the children of an <code>IMethod</code> 
+ * or an <code>IInitializer</code>.
+ * <p>
+ * In particular such a pseudo-element should not be used as a handle. For example its name range won't be updated
+ * if the underlying source changes.
+ * </p><p>
+ * This interface is not intended to be implemented by clients.
+ * </p>
+ * @since 3.0
+ */
+public interface ILocalVariable extends IJavaElement, ISourceReference {
+
+	/**
+	 * Returns the name of this local variable.
+	 * 
+	 * @return the name of this local variable.
+	 */
+	String getElementName();
+	
+	/**
+	 * Returns the source range of this local variable's name.
+	 *
+	 * @return the source range of this local variable's name
+	 */
+	ISourceRange getNameRange();
+	
+	/**
+	 * Returns the type signature of this local variable.
+	 *
+	 * @return the type signature of this local variable.
+	 * @see Signature
+	 */
+	String getTypeSignature();
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMember.java
index 4f0e009..f3ac244 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMember.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMember.java
@@ -18,7 +18,7 @@
  * This interface is not intended to be implemented by clients.
  * </p>
  */
-public interface IMember extends IJavaElement, ISourceReference, ISourceManipulation {
+public interface IMember extends IJavaElement, ISourceReference, ISourceManipulation, IParent {
 /**
  * Returns the class file in which this member is declared, or <code>null</code>
  * if this member is not declared in a class file (for example, a source type).
@@ -75,6 +75,20 @@
  */
 ISourceRange getNameRange() throws JavaModelException;
 /**
+ * Returns the local or anonymous type declared in this source member with the given simple name and/or
+ * with the specified position relative to the order they are defined in the source.
+ * The name is empty if it is an anonymous type.
+ * Numbering starts at 1 (thus the first occurrence is occurrence 1, not occurrence 0)..
+ * This is a handle-only method. The type may or may not exist.
+ * Throws a <code>RuntimeException</code> if this member is not a source member.
+ * 
+ * @param name the given simple name
+ * @param occurrenceCount the specified position
+ * @return the type with the given name and/or with the specified position relative to the order they are defined in the source
+ * @since 3.0
+ */
+IType getType(String name, int occurrenceCount);
+/**
  * Returns whether this member is from a class file.
  * This is a handle-only method.
  *
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java
index dd0afce..3b2acfc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IMethod.java
@@ -25,6 +25,7 @@
  * For the class initialization methods in binary types, this returns
  * the special name <code>"&lt;clinit&gt;"</code>.
  * This is a handle-only method.
+ * @return the simple name of this method
  */
 String getElementName();
 /**
@@ -89,12 +90,13 @@
  */
 String getReturnType() throws JavaModelException;
 /**
- * Returns the signature of the method. This includes the signatures for the parameter
+ * Returns the signature of this method. This includes the signatures for the parameter
  * types and return type, but does not include the method name or exception types.
  *
  * <p>For example, a source method declared as <code>public void foo(String text, int length)</code>
  * would return <code>"(QString;I)V"</code>.
  *
+ * @return the signature of this method
  * @exception JavaModelException if this element does not exist or if an
  *      exception occurs while accessing its corresponding resource.
  *
@@ -138,7 +140,7 @@
  * 
  * @param method the given method
  * @return true if this method is similar to the given method.
- * @see Signature#getSimpleName
+ * @see Signature#getSimpleName(char[])
  * @since 2.0
  */
 boolean isSimilar(IMethod method);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java
index 2b8a8d4..eda1ee7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IOpenable.java
@@ -97,7 +97,7 @@
  * @exception JavaModelException if this element does not exist or if an
  *		exception occurs while accessing its corresponding resource.
  * @return true if the element is consistent with its underlying resource or buffer, false otherwise.
- * @see IOpenable#makeConsistent
+ * @see IOpenable#makeConsistent(IProgressMonitor)
  */
 boolean isConsistent() throws JavaModelException;
 /**
@@ -108,14 +108,20 @@
 /**
  * Makes this element consistent with its underlying resource or buffer 
  * by updating the element's structure and properties as necessary.
- *
+ *<p>
+ * Note: Using this functionality on a working copy will interfere with any
+ * subsequent reconciling operation. Indeed, the next <code>ICompilationUnit#reconcile()</code> 
+ * operation will not account for changes which occurred before an
+ * explicit use of <code>#makeConsistent(IProgressMonitor)</code>
+ * <p>
  * @param progress the given progress monitor
  * @exception JavaModelException if the element is unable to access the contents
  * 		of its underlying resource. Reasons include:
  * <ul>
  *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
  * </ul>
- * @see IOpenable#isConsistent
+ * @see IOpenable#isConsistent()
+ * @see ICompilationUnit#reconcile(boolean, IProgressMonitor)
  */
 void makeConsistent(IProgressMonitor progress) throws JavaModelException;
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageDeclaration.java
index 0f82fd5..7cb6819 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageDeclaration.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageDeclaration.java
@@ -21,6 +21,8 @@
 /**
  * Returns the name of the package the statement refers to.
  * This is a handle-only method.
+ * 
+ * @return the name of the package the statement
  */
 String getElementName();
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java
index 3312c67..b0b44e8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragment.java
@@ -39,6 +39,8 @@
 	/**
 	 * Returns whether this fragment contains at least one Java resource.
 	 * @return true if this fragment contains at least one Java resource, false otherwise
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
 	 */
 	boolean containsJavaResources() throws JavaModelException;
 	/**
@@ -95,9 +97,10 @@
 	 * in this package (for example, <code>"Object.java"</code>).
 	 * The name has to be a valid compilation unit name.
 	 * This is a handle-only method.  The compilation unit may or may not be present.
-	 * @see JavaConventions#validateCompilationUnitName
+	 * 
 	 * @param name the given name
 	 * @return the compilation unit with the specified name in this package
+	 * @see JavaConventions#validateCompilationUnitName(String)
 	 */
 	ICompilationUnit getCompilationUnit(String name);
 	/**
@@ -106,6 +109,7 @@
 	 * <p>Note: it is possible that a package fragment contains only
 	 * class files (in other words, its kind is <code>K_BINARY</code>), in which
 	 * case this method returns an empty collection.
+	 * </p>
 	 *
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
@@ -113,6 +117,25 @@
 	 */
 	ICompilationUnit[] getCompilationUnits() throws JavaModelException;
 	/**
+	 * Returns all of the compilation units in this package fragment that are 
+	 * in working copy mode and that have the given owner.
+	 * <p>
+	 * Only existing working copies are returned. So a compilation unit handle that has no 
+	 * corresponding resource on disk will be included if and only if is in working copy mode.
+	 * </p>
+	 * <p>Note: it is possible that a package fragment contains only
+	 * class files (in other words, its kind is <code>K_BINARY</code>), in which
+	 * case this method returns an empty collection.
+	 * </p>
+	 *
+	 * @param owner the owner of the returned compilation units
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
+	 * @return all of the compilation units in this package fragment
+	 * @since 3.0
+	 */
+	ICompilationUnit[] getCompilationUnits(WorkingCopyOwner owner) throws JavaModelException;
+	/**
 	 * Returns the dot-separated package name of this fragment, for example
 	 * <code>"java.lang"</code>, or <code>""</code> (the empty string),
 	 * for the default package.
@@ -125,12 +148,11 @@
 	 * A package fragment can contain <code>.java</code> source files,
 	 * or <code>.class</code> files. This is a convenience method.
 	 *
-	 * @see IPackageFragmentRoot#K_SOURCE
-	 * @see IPackageFragmentRoot#K_BINARY
-	 *
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
 	 * @return this package fragment's root kind encoded as an integer
+	 * @see IPackageFragmentRoot#K_SOURCE
+	 * @see IPackageFragmentRoot#K_BINARY
 	 */
 	int getKind() throws JavaModelException;
 	/**
@@ -144,8 +166,13 @@
 	 * (possibly in a folder).
 	 * </p>
 	 * 
-	 * @return an array of non-Java resources contained in this package fragment
-	 * @see IClasspathEntry#getExclusionPatterns
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
+	 * @return an array of non-Java resources (<code>IFile</code>s, 
+	 *              <code>IFolder</code>s, or <code>IStorage</code>s if the
+	 *              package fragment is in an archive) contained in this package 
+	 *              fragment
+	 * @see IClasspathEntry#getExclusionPatterns()
 	 */
 	Object[] getNonJavaResources() throws JavaModelException;
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java
index ded1f77..5d2a506 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IPackageFragmentRoot.java
@@ -165,7 +165,7 @@
 	 * classpath (NAME_COLLISION) and <code>updateModelFlags</code>
 	 * has not been specified as <code>REPLACE</code></li>
 	 * </ul>
-	 * @see org.eclipse.core.resources.IResource#copy
+	 * @see org.eclipse.core.resources.IResource#copy(IPath, boolean, IProgressMonitor)
 	 * @since 2.1
 	 */
 	void copy(IPath destination, int updateResourceFlags, int updateModelFlags, IClasspathEntry sibling, IProgressMonitor monitor) throws JavaModelException;
@@ -191,7 +191,7 @@
 	 * <li> The name is not a valid package name (INVALID_NAME)
 	 * </ul>
 	 * @return a package fragment in this root with the given dot-separated package name
-	 * @see org.eclipse.core.resources.IFolder#create
+	 * @see org.eclipse.core.resources.IFolder#create(boolean, boolean, IProgressMonitor)
 	 */
 	IPackageFragment createPackageFragment(
 		String name,
@@ -239,7 +239,7 @@
 	 * or updating a classpath
 	 * </li>
 	 * </ul>
-	 * @see org.eclipse.core.resources.IResource#delete
+	 * @see org.eclipse.core.resources.IResource#delete(boolean, IProgressMonitor)
 	 * @since 2.1
 	 */
 	void delete(int updateResourceFlags, int updateModelFlags, IProgressMonitor monitor) throws JavaModelException;
@@ -251,12 +251,11 @@
 	 * In particular, <code>.class</code> files are ignored under a source package fragment root,
 	 * and <code>.java</code> files are ignored under a binary package fragment root.
 	 *
-	 * @see IPackageFragmentRoot#K_SOURCE
-	 * @see IPackageFragmentRoot#K_BINARY
-	 *
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
 	 * @return this package fragment root's kind encoded as an integer
+	 * @see IPackageFragmentRoot#K_SOURCE
+	 * @see IPackageFragmentRoot#K_BINARY
 	 */
 	int getKind() throws JavaModelException;
 	
@@ -271,8 +270,13 @@
 	 * (possibly in a folder). Thus when a nested source folder is excluded, it will appear
 	 * in the non-Java resources of the outer folder.
 	 * </p>
-	 * @return an array of non-Java resources contained in this package fragment root
-	 * @see IClasspathEntry#getExclusionPatterns
+	 * @return an array of non-Java resources (<code>IFile</code>s, 
+	 *              <code>IFolder</code>s, or <code>IStorage</code>s if the
+	 *              package fragment root is in archive) contained in this package 
+	 *              fragment root
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
+	 * @see IClasspathEntry#getExclusionPatterns()
 	 */
 	Object[] getNonJavaResources() throws JavaModelException;
 	
@@ -384,7 +388,7 @@
 	 * </p>
 	 * 
 	 * @param destination the destination path
-	 * @param updateFlags bit-wise or of update flag constants
+	 * @param updateResourceFlags bit-wise or of update flag constants
 	 * (<code>IResource.FORCE</code>, <code>IResource.KEEP_HISTORY</code> 
 	 * and <code>IResource.SHALLOW</code>)
 	 * @param updateModelFlags bit-wise or of update resource flag constants
@@ -413,7 +417,7 @@
 	 * classpath (NAME_COLLISION) and <code>updateModelFlags</code>
 	 * has not been specified as <code>REPLACE</code></li>
 	 * </ul>
-	 * @see org.eclipse.core.resources.IResource#move
+	 * @see org.eclipse.core.resources.IResource#move(IPath, boolean, IProgressMonitor)
 	 * @since 2.1
 	 */
 	void move(IPath destination, int updateResourceFlags, int updateModelFlags, IClasspathEntry sibling, IProgressMonitor monitor) throws JavaModelException;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IRegion.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IRegion.java
index 0d96a56..74095c3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IRegion.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IRegion.java
@@ -26,7 +26,7 @@
  * Instances can be created via the <code>JavaCore.newRegion</code>.
  * </p>
  *
- * @see JavaCore#newRegion
+ * @see JavaCore#newRegion()
  */
 public interface IRegion {
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceReference.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceReference.java
index 330aa10..0ea268f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceReference.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ISourceReference.java
@@ -30,7 +30,7 @@
  * This interface is not intended to be implemented by clients.
  * </p>
  *
- * @see IPackageFragmentRoot#attachSource
+ * @see IPackageFragmentRoot#attachSource(org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IPath, org.eclipse.core.runtime.IProgressMonitor)
  */
 public interface ISourceReference {
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
index 4db9c74..9baa8aa 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
@@ -16,8 +16,11 @@
 
 /**
  * Represents either a source type in a compilation unit (either a top-level
- * type or a member type) or a binary type in a class file.
+ * type, a member type, a local type or an anonymous type) 
+ * or a binary type in a class file.
  * <p>
+ * Note that the element name of an anonymous source type is always empty.
+ * </p><p>
  * If a binary type cannot be parsed, its structure remains unknown.
  * Use <code>IJavaElement.isStructureKnown</code> to determine whether this
  * is the case.
@@ -31,7 +34,7 @@
  * This interface is not intended to be implemented by clients.
  * </p>
  */
-public interface IType extends IMember, IParent {
+public interface IType extends IMember {
 	/**
 	 * Do code completion inside a code snippet in the context of the current type.
 	 * 
@@ -45,7 +48,7 @@
 	 * A possible value is -1, if the position is not known.
 	 * @param position the position with in snippet where the user 
 	 * is performing code assist.
-	 * @param localVariableTypesNames an array (possibly empty) of fully qualified 
+	 * @param localVariableTypeNames an array (possibly empty) of fully qualified 
 	 * type names of local variables visible at the current scope
 	 * @param localVariableNames an array (possibly empty) of local variable names 
 	 * that are visible at the current scope
@@ -53,6 +56,8 @@
 	 * local variables
 	 * @param isStatic whether the current scope is in a static context
 	 * @param requestor the completion requestor
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
 	 * @since 2.0
 	 */
 	void codeComplete(
@@ -67,6 +72,51 @@
 		throws JavaModelException;
 
 	/**
+	 * Do code completion inside a code snippet in the context of the current type.
+	 * It considers types in the working copies with the given owner first. In other words, 
+	 * the owner's working copies will take precedence over their original compilation units
+	 * in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * </p><p>
+	 * If the type can access to his source code and the insertion position is valid,
+	 * then completion is performed against source. Otherwise the completion is performed
+	 * against type structure and given locals variables.
+	 * </p>
+	 * 
+	 * @param snippet the code snippet
+	 * @param insertion the position with in source where the snippet
+	 * is inserted. This position must not be in comments.
+	 * A possible value is -1, if the position is not known.
+	 * @param position the position with in snippet where the user 
+	 * is performing code assist.
+	 * @param localVariableTypeNames an array (possibly empty) of fully qualified 
+	 * type names of local variables visible at the current scope
+	 * @param localVariableNames an array (possibly empty) of local variable names 
+	 * that are visible at the current scope
+	 * @param localVariableModifiers an array (possible empty) of modifiers for 
+	 * local variables
+	 * @param isStatic whether the current scope is in a static context
+	 * @param requestor the completion requestor
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
+	 * @since 3.0
+	 */
+	void codeComplete(
+		char[] snippet,
+		int insertion,
+		int position,
+		char[][] localVariableTypeNames,
+		char[][] localVariableNames,
+		int[] localVariableModifiers,
+		boolean isStatic,
+		ICompletionRequestor requestor,
+		WorkingCopyOwner owner)
+		throws JavaModelException;
+
+	/**
 	 * Creates and returns a field in this type with the
 	 * given contents.
 	 * <p>
@@ -343,6 +393,7 @@
 	 * For interfaces, the superclass name is always <code>"java.lang.Object"</code>.
 	 * For source types, the name as declared is returned, for binary types,
 	 * the resolved, qualified name is returned.
+	 * For anonymous types, the superclass name is the name appearing after the 'new' keyword'.
 	 *
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
@@ -358,6 +409,7 @@
 	 * An empty collection is returned if this type does not implement or
 	 * extend any interfaces. For source types, simple names are returned,
 	 * for binary types, qualified names are returned.
+	 * For anonymous types, an empty collection is always returned.
 	 *
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
@@ -370,7 +422,7 @@
 	 * Returns the member type declared in this type with the given simple name.
 	 * This is a handle-only method. The type may or may not exist.
 	 * 
-	 * @param the given simple name
+	 * @param name the given simple name
 	 * @return the member type declared in this type with the given simple name
 	 */
 	IType getType(String name);
@@ -479,7 +531,7 @@
 	 * Loads a previously saved ITypeHierarchy from an input stream. A type hierarchy can
 	 * be stored using ITypeHierachy#store(OutputStream).
 	 * 
-	 * Only hierarchies originally created by the following methods can be load:
+	 * Only hierarchies originally created by the following methods can be loaded:
 	 * <ul>
 	 * <li>IType#newSupertypeHierarchy(IProgressMonitor)</li>
 	 * <li>IType#newTypeHierarchy(IJavaProject, IProgressMonitor)</li>
@@ -492,7 +544,7 @@
 	 * @exception JavaModelException if the hierarchy could not be restored, reasons include:
 	 *      - type is not the focus of the hierarchy or 
 	 *		- unable to read the input stream (wrong format, IOException during reading, ...)
-	 * @see ITypeHierarchy#store(OutputStream, IProgressMonitor)
+	 * @see ITypeHierarchy#store(java.io.OutputStream, IProgressMonitor)
 	 * @since 2.1
 	 */
 	ITypeHierarchy loadTypeHierachy(InputStream input, IProgressMonitor monitor) throws JavaModelException;
@@ -500,9 +552,9 @@
 	 * Creates and returns a type hierarchy for this type containing
 	 * this type and all of its supertypes.
 	 *
+	 * @param monitor the given progress monitor
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
-	 * @param monitor the given progress monitor
 	 * @return a type hierarchy for this type containing this type and all of its supertypes
 	 */
 	ITypeHierarchy newSupertypeHierarchy(IProgressMonitor monitor) throws JavaModelException;
@@ -515,6 +567,27 @@
 	 * <p>
 	 * Note that passing an empty working copy will be as if the original compilation
 	 * unit had been deleted.
+	 * </p>
+	 *
+	 * @param workingCopies the working copies that take precedence over their original compilation units
+	 * @param monitor the given progress monitor
+	 * @return a type hierarchy for this type containing this type and all of its supertypes
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
+	 * @since 3.0
+	 */
+	ITypeHierarchy newSupertypeHierarchy(ICompilationUnit[] workingCopies, IProgressMonitor monitor)
+		throws JavaModelException;
+		
+	/**
+	 * Creates and returns a type hierarchy for this type containing
+	 * this type and all of its supertypes, considering types in the given 
+	 * working copies. In other words, the list of working copies will take 
+	 * precedence over their original compilation units in the workspace.
+	 * <p>
+	 * Note that passing an empty working copy will be as if the original compilation
+	 * unit had been deleted.
+	 * </p>
 	 *
 	 * @param workingCopies the working copies that take precedence over their original compilation units
 	 * @param monitor the given progress monitor
@@ -522,17 +595,78 @@
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
 	 * @since 2.0
+	 * @deprecated use #newSupertypeHierarchy(ICompilationUnit[], IProgressMonitor) instead
 	 */
 	ITypeHierarchy newSupertypeHierarchy(IWorkingCopy[] workingCopies, IProgressMonitor monitor)
 		throws JavaModelException;
 		
 	/**
 	 * Creates and returns a type hierarchy for this type containing
-	 * this type, all of its supertypes, and all its subtypes in the workspace.
+	 * this type and all of its supertypes, considering types in the 
+	 * working copies with the given owner. 
+	 * In other words, the owner's working copies will take 
+	 * precedence over their original compilation units in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * <p>
 	 *
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * @param monitor the given progress monitor
+	 * @return a type hierarchy for this type containing this type and all of its supertypes
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
+	 * @since 3.0
+	 */
+	ITypeHierarchy newSupertypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor)
+		throws JavaModelException;
+
+	/**
+	 * Creates and returns a type hierarchy for this type containing
+	 * this type, all of its supertypes, and all its subtypes 
+	 * in the context of the given project.
+	 *
+	 * @param project the given project
 	 * @param monitor the given progress monitor
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
+	 * @return a type hierarchy for this type containing
+	 * this type, all of its supertypes, and all its subtypes 
+	 * in the context of the given project
+	 */
+	ITypeHierarchy newTypeHierarchy(IJavaProject project, IProgressMonitor monitor) throws JavaModelException;
+	
+	/**
+	 * Creates and returns a type hierarchy for this type containing
+	 * this type, all of its supertypes, and all its subtypes 
+	 * in the context of the given project, considering types in the 
+	 * working copies with the given owner. 
+	 * In other words, the owner's working copies will take 
+	 * precedence over their original compilation units in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * <p>
+	 *
+	 * @param project the given project
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * @param monitor the given progress monitor
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
+	 * @return a type hierarchy for this type containing
+	 * this type, all of its supertypes, and all its subtypes 
+	 * in the context of the given project
+	 * @since 3.0
+	 */
+	ITypeHierarchy newTypeHierarchy(IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
+
+	/**
+	 * Creates and returns a type hierarchy for this type containing
+	 * this type, all of its supertypes, and all its subtypes in the workspace.
+	 *
+	 * @param monitor the given progress monitor
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
 	 * @return a type hierarchy for this type containing
 	 * this type, all of its supertypes, and all its subtypes in the workspace
 	 */
@@ -553,24 +687,50 @@
 	 * this type, all of its supertypes, and all its subtypes in the workspace
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
+	 * @since 3.0
+	 */
+	ITypeHierarchy newTypeHierarchy(ICompilationUnit[] workingCopies, IProgressMonitor monitor) throws JavaModelException;
+	
+	/**
+	 * Creates and returns a type hierarchy for this type containing
+	 * this type, all of its supertypes, and all its subtypes in the workspace, 
+	 * considering types in the given working copies. In other words, the list of working 
+	 * copies that will take precedence over their original compilation units in the workspace.
+	 * <p>
+	 * Note that passing an empty working copy will be as if the original compilation
+	 * unit had been deleted.
+	 *
+	 * @param workingCopies the working copies that take precedence over their original compilation units
+	 * @param monitor the given progress monitor
+	 * @return a type hierarchy for this type containing
+	 * this type, all of its supertypes, and all its subtypes in the workspace
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource.
 	 * @since 2.0
+	 * @deprecated use #newTypeHierarchy(ICompilationUnit[], IProgressMonitor) instead
 	 */
 	ITypeHierarchy newTypeHierarchy(IWorkingCopy[] workingCopies, IProgressMonitor monitor) throws JavaModelException;
 	
 	/**
 	 * Creates and returns a type hierarchy for this type containing
-	 * this type, all of its supertypes, and all its subtypes 
-	 * in the context of the given project.
+	 * this type, all of its supertypes, and all its subtypes in the workspace, 
+	 * considering types in the working copies with the given owner. 
+	 * In other words, the owner's working copies will take 
+	 * precedence over their original compilation units in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * <p>
 	 *
-	 * @param project the given project
+	 * @param owner the owner of working copies that take precedence over their original compilation units
 	 * @param monitor the given progress monitor
+	 * @return a type hierarchy for this type containing
+	 * this type, all of its supertypes, and all its subtypes in the workspace
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource.
-	 * @return a type hierarchy for this type containing
-	 * this type, all of its supertypes, and all its subtypes 
-	 * in the context of the given project
+	 * @since 3.0
 	 */
-	ITypeHierarchy newTypeHierarchy(IJavaProject project, IProgressMonitor monitor) throws JavaModelException;
+	ITypeHierarchy newTypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException;
 	
 	/**
 	 * Resolves the given type name within the context of this type (depending on the type hierarchy 
@@ -588,4 +748,34 @@
 	 * @return the resolved type names or <code>null</code> if unable to find any matching type
 	 */
 	String[][] resolveType(String typeName) throws JavaModelException;
+
+	/**
+	 * Resolves the given type name within the context of this type (depending on the type hierarchy 
+	 * and its imports) and using the given owner's working copies, considering types in the 
+	 * working copies with the given owner. In other words, the owner's working copies will take 
+	 * precedence over their original compilation units in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * </p>
+	 * <p>. 
+	 * Multiple answers might be found in case there are ambiguous matches.
+	 * </p>
+	 * <p>
+	 * Each matching type name is decomposed as an array of two strings, the first denoting the package
+	 * name (dot-separated) and the second being the type name.
+	 * Returns <code>null</code> if unable to find any matching type.
+	 *</p>
+	 *<p>
+	 * For example, resolution of <code>"Object"</code> would typically return
+	 * <code>{{"java.lang", "Object"}}</code>.
+	 * </p>
+	 * 
+	 * @param typeName the given type name
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * @exception JavaModelException if code resolve could not be performed. 
+	 * @return the resolved type names or <code>null</code> if unable to find any matching type
+	 * @since 3.0
+	 */
+	String[][] resolveType(String typeName, WorkingCopyOwner owner) throws JavaModelException;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchy.java
index fe4885b..ff27584 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ITypeHierarchy.java
@@ -121,11 +121,13 @@
 IType[] getAllSuperInterfaces(IType type);
 /**
  * Returns all resolved supertypes of the
- * given class, in bottom-up order. An empty array
+ * given type, in bottom-up order. An empty array
  * is returned if there are no resolved supertypes for the
- * given class.
- *
- * <p>NOTE: once a type hierarchy has been created, it is more efficient to
+ * given type.
+ * <p>
+ * Note that <code>java.lang.Object</code> is NOT considered to be a supertype 
+ * of any interface type.
+ * </p><p>NOTE: once a type hierarchy has been created, it is more efficient to
  * query the hierarchy for supertypes than to query a type recursively up
  * the supertype chain. Querying an element performs a dynamic resolution,
  * whereas the hierarchy returns a pre-computed result.
@@ -145,9 +147,10 @@
 IType[] getAllTypes();
 
 /**
- * Return the flags associated with this type (would be equivalent to <code>IMember.getFlags()</code>),
+ * Return the flags associated with the given type (would be equivalent to <code>IMember.getFlags()</code>),
  * or <code>-1</code> if this information wasn't cached on the hierarchy during its computation.
  * 
+ * @param type the given type
  * @return the modifier flags for this member
  * @see Flags
  * @since 2.0
@@ -248,7 +251,9 @@
  * in no particular order, limited to the types in this
  * type hierarchy's graph.
  * For classes, this returns its superclass and the interfaces that the class implements.
- * For interfaces, this returns the interfaces that the interface extends.
+ * For interfaces, this returns the interfaces that the interface extends. As a consequence 
+ * <code>java.lang.Object</code> is NOT considered to be a supertype of any interface 
+ * type.
  * 
  * @param type the given type
  * @return the resolved supertypes of the given type limited to the types in this
@@ -265,8 +270,8 @@
 /**
  * Re-computes the type hierarchy reporting progress.
  *
- * @exception JavaModelException if unable to refresh the hierarchy
  * @param monitor the given progress monitor
+ * @exception JavaModelException if unable to refresh the hierarchy
  */
 void refresh(IProgressMonitor monitor) throws JavaModelException;
 /**
@@ -291,7 +296,7 @@
  * @param outputStream output stream where the hierarchy will be stored
  * @param monitor the given progress monitor
  * @exception JavaModelException if unable to store the hierarchy in the ouput stream
- * @see IType#loadTypeHierachy(InputStream, IProgressMonitor)
+ * @see IType#loadTypeHierachy(java.io.InputStream, IProgressMonitor)
  * @since 2.1
  */
 void store(OutputStream outputStream, IProgressMonitor monitor) throws JavaModelException;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IWorkingCopy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IWorkingCopy.java
index 0309aee..1e0feac 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IWorkingCopy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IWorkingCopy.java
@@ -49,6 +49,7 @@
  * <p>
  * This interface is not intended to be implemented by clients.
  * </p>
+ * @deprecated Use <code>ICompilationUnit</code>instead
  */
 public interface IWorkingCopy {
 	
@@ -118,6 +119,7 @@
 	 * or <code>null</code> if this is not a working copy element.  This is a handle
 	 * only method, the returned element may or may not exist.
 	 * 
+	 * @param workingCopyElement the specified working copy element
 	 * @return the original element the specified working copy element was created from,
 	 * or <code>null</code> if this is not a working copy element
 	 */
@@ -269,6 +271,7 @@
 	 * Returns whether this working copy's original element's content
 	 * has not changed since the inception of this working copy.
 	 * 
+	 * @param resource this working copy's resource
 	 * @return true if this working copy's original element's content
 	 * has not changed since the inception of this working copy, false otherwise
 	 */
@@ -289,16 +292,14 @@
 	 * this delta.
 	 * <p>
 	 * If the working copy hasn't changed, then no problem will be detected,
-	 * this is equivalent to <code>IWorkingCopy#reconcile(false, null)</code>.
+	 * this is equivalent to <code>IWorkingCopy#reconcile(false, null)</code>.</p>
 	 * <p>
 	 * Compilation problems found in the new contents are notified through the
 	 * <code>IProblemRequestor</code> interface which was passed at
 	 * creation, and no longer as transient markers. Therefore this API will
-	 * return <code>null</code>.
+	 * return <code>null</code>.</p>
 	 * <p>
-	 * Note: It has been assumed that added inner types should
-	 * not generate change deltas.  The implementation has been
-	 * modified to reflect this assumption.
+ 	 * Note: Since 3.0 added/removed/changed inner types generate change deltas.</p>
 	 *
 	 * @exception JavaModelException if the contents of the original element
 	 *		cannot be accessed. Reasons include:
@@ -317,16 +318,14 @@
 	 * this delta.
 	 * <p>
 	 * The boolean argument allows to force problem detection even if the
-	 * working copy is already consistent.
+	 * working copy is already consistent.</p>
 	 * <p>
 	 * Compilation problems found in the new contents are notified through the
 	 * <code>IProblemRequestor</code> interface which was passed at
 	 * creation, and no longer as transient markers. Therefore this API answers
-	 * nothing.
+	 * nothing.</p>
 	 * <p>
-	 * Note: It has been assumed that added inner types should
-	 * not generate change deltas.  The implementation has been
-	 * modified to reflect this assumption.
+ 	 * Note: Since 3.0 added/removed/changed inner types generate change deltas.</p>
 	 *
 	 * @param forceProblemDetection boolean indicating whether problem should be recomputed
 	 *   even if the source hasn't changed.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
index 766d29e..ac0c4e4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaConventions.java
@@ -10,16 +10,11 @@
  *******************************************************************************/
 package org.eclipse.jdt.core;
 
-import java.io.File;
-import java.util.HashSet;
 import java.util.StringTokenizer;
 
-import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IWorkspace;
-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.IStatus;
 import org.eclipse.core.runtime.Status;
@@ -27,10 +22,10 @@
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.JavaModel;
 import org.eclipse.jdt.internal.core.JavaModelStatus;
-import org.eclipse.jdt.internal.core.Util;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Provides methods for checking Java-specific conventions such as name syntax.
@@ -41,47 +36,11 @@
  */
 public final class JavaConventions {
 
-	private final static char fgDot= '.';
+	private final static char DOT= '.';
 	private final static Scanner SCANNER = new Scanner();
 
-	/**
-	 * Not instantiable.
-	 */
-	private JavaConventions() {}
-
-	/*
-	 * Returns the index of the first argument paths which is strictly enclosing the path to check
-	 */
-	private static int indexOfEnclosingPath(IPath checkedPath, IPath[] paths, int pathCount) {
-
-		for (int i = 0; i < pathCount; i++){
-			if (paths[i].equals(checkedPath)) continue;
-			if (paths[i].isPrefixOf(checkedPath)) return i;
-		}
-		return -1;
-	}
-	
-	/*
-	 * Returns the index of the first argument paths which is equal to the path to check
-	 */
-	private static int indexOfMatchingPath(IPath checkedPath, IPath[] paths, int pathCount) {
-
-		for (int i = 0; i < pathCount; i++){
-			if (paths[i].equals(checkedPath)) return i;
-		}
-		return -1;
-	}
-
-	/*
-	 * Returns the index of the first argument paths which is strictly nested inside the path to check
-	 */
-	private static int indexOfNestedPath(IPath checkedPath, IPath[] paths, int pathCount) {
-
-		for (int i = 0; i < pathCount; i++){
-			if (checkedPath.equals(paths[i])) continue;
-			if (checkedPath.isPrefixOf(paths[i])) return i;
-		}
-		return -1;
+	private JavaConventions() {
+		// Not instantiable
 	}
 
 	/**
@@ -102,18 +61,16 @@
 		}
 		String extension1 = rootPath1.getFileExtension();
 		String extension2 = rootPath2.getFileExtension();
-		String jarExtension = "JAR"; //$NON-NLS-1$
-		String zipExtension = "ZIP"; //$NON-NLS-1$
-		if (extension1 != null && (extension1.equalsIgnoreCase(jarExtension) || extension1.equalsIgnoreCase(zipExtension))) {
+		if (extension1 != null && (extension1.equalsIgnoreCase(SuffixConstants.EXTENSION_JAR) || extension1.equalsIgnoreCase(SuffixConstants.EXTENSION_ZIP))) {
 			return false;
 		} 
-		if (extension2 != null && (extension2.equalsIgnoreCase(jarExtension) || extension2.equalsIgnoreCase(zipExtension))) {
+		if (extension2 != null && (extension2.equalsIgnoreCase(SuffixConstants.EXTENSION_JAR) || extension2.equalsIgnoreCase(SuffixConstants.EXTENSION_ZIP))) {
 			return false;
 		}
 		return rootPath1.isPrefixOf(rootPath2) || rootPath2.isPrefixOf(rootPath1);
 	}
 
-	/**
+	/*
 	 * Returns the current identifier extracted by the scanner (without unicode
 	 * escapes) from the given id.
 	 * Returns <code>null</code> if the id was not valid
@@ -170,7 +127,7 @@
 		if (name == null) {
 			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("convention.unit.nullName"), null); //$NON-NLS-1$
 		}
-		if (!Util.isJavaFileName(name)) {
+		if (!org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(name)) {
 			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("convention.unit.notJavaName"), null); //$NON-NLS-1$
 		}
 		String identifier;
@@ -212,7 +169,7 @@
 		if (name == null) {
 			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("convention.classFile.nullName"), null); //$NON-NLS-1$
 		}
-		if (!Util.isClassFileName(name)) {
+		if (!org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) {
 			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("convention.classFile.notClassFileName"), null); //$NON-NLS-1$
 		}
 		String identifier;
@@ -390,7 +347,7 @@
 		if ((length = name.length()) == 0) {
 			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("convention.package.emptyName"), null); //$NON-NLS-1$
 		}
-		if (name.charAt(0) == fgDot || name.charAt(length-1) == fgDot) {
+		if (name.charAt(0) == DOT || name.charAt(length-1) == DOT) {
 			return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("convention.package.dotName"), null); //$NON-NLS-1$
 		}
 		if (CharOperation.isWhitespace(name.charAt(0)) || CharOperation.isWhitespace(name.charAt(name.length() - 1))) {
@@ -398,12 +355,12 @@
 		}
 		int dot = 0;
 		while (dot != -1 && dot < length-1) {
-			if ((dot = name.indexOf(fgDot, dot+1)) != -1 && dot < length-1 && name.charAt(dot+1) == fgDot) {
+			if ((dot = name.indexOf(DOT, dot+1)) != -1 && dot < length-1 && name.charAt(dot+1) == DOT) {
 				return new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("convention.package.consecutiveDotsName"), null); //$NON-NLS-1$
 				}
 		}
 		IWorkspace workspace = ResourcesPlugin.getWorkspace();
-		StringTokenizer st = new StringTokenizer(name, new String(new char[] {fgDot}));
+		StringTokenizer st = new StringTokenizer(name, new String(new char[] {DOT}));
 		boolean firstToken = true;
 		while (st.hasMoreTokens()) {
 			String typeName = st.nextToken();
@@ -435,7 +392,8 @@
 	 *      <ul><li> A source folder can coincidate with its own output location, in which case this output can then contain library archives. 
 	 *                     However, a specific output location cannot coincidate with any library or a distinct source folder than the one referring to it. </li> 
 	 *              <li> A source/library folder can be nested in any source folder as long as the nested folder is excluded from the enclosing one. </li>
-	 * 			<li> An output location can be nested in a source folder, if the source folder coincidates with the project itself. </li>
+	 * 			<li> An output location can be nested in a source folder, if the source folder coincidates with the project itself, or if the output
+	 * 					location is excluded from the source folder.
 	 *      </ul>
 	 * </ul>
 	 * 
@@ -447,233 +405,16 @@
 	 *  be performed during the classpath setting operation (if validation fails, the classpath setting will not complete).
 	 *  <p>
 	 * @param javaProject the given java project
-	 * @param classpath a given classpath
-	 * @param outputLocation a given output location
+	 * @param rawClasspath the given classpath
+	 * @param projectOutputLocation the given output location
 	 * @return a status object with code <code>IStatus.OK</code> if
 	 *		the given classpath and output location are compatible, otherwise a status 
 	 *		object indicating what is wrong with the classpath or output location
 	 * @since 2.0
 	 */
 	public static IJavaModelStatus validateClasspath(IJavaProject javaProject, IClasspathEntry[] rawClasspath, IPath projectOutputLocation) {
-	
-		IProject project = javaProject.getProject();
-		IPath projectPath= project.getFullPath();
-	
-		/* validate output location */
-		if (projectOutputLocation == null) {
-			return new JavaModelStatus(IJavaModelStatusConstants.NULL_PATH);
-		}
-		if (projectOutputLocation.isAbsolute()) {
-			if (!projectPath.isPrefixOf(projectOutputLocation)) {
-				return new JavaModelStatus(IJavaModelStatusConstants.PATH_OUTSIDE_PROJECT, javaProject, projectOutputLocation.toString());
-			}
-		} else {
-			return new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, projectOutputLocation);
-		}
-	
-		boolean hasSource = false;
-		boolean hasLibFolder = false;
-	
 
-		// tolerate null path, it will be reset to default
-		if (rawClasspath == null) 
-			return JavaModelStatus.VERIFIED_OK;
-		
-		// retrieve resolved classpath
-		IClasspathEntry[] classpath; 
-		try {
-			classpath = ((JavaProject)javaProject).getResolvedClasspath(rawClasspath, null /*output*/, true/*ignore pb*/, false/*no marker*/, null /*no reverse map*/);
-		} catch(JavaModelException e){
-			return e.getJavaModelStatus();
-		}
-		int length = classpath.length; 
-
-		int outputCount = 1;
-		IPath[] outputLocations	= new IPath[length+1];
-		boolean[] allowNestingInOutputLocations = new boolean[length+1];
-		outputLocations[0] = projectOutputLocation;
-		
-		// retrieve and check output locations
-		IPath potentialNestedOutput = null;
-		int sourceEntryCount = 0;
-		for (int i = 0 ; i < length; i++) {
-			IClasspathEntry resolvedEntry = classpath[i];
-			switch(resolvedEntry.getEntryKind()){
-				case IClasspathEntry.CPE_SOURCE :
-					sourceEntryCount++;
-
-					if (resolvedEntry.getExclusionPatterns() != null && resolvedEntry.getExclusionPatterns().length > 0
-							&& JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, true))) {
-						return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS, resolvedEntry.getPath());
-					}
-					IPath customOutput; 
-					if ((customOutput = resolvedEntry.getOutputLocation()) != null) {
-
-						if (JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, true))) {
-							return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS, resolvedEntry.getPath());
-						}
-						// ensure custom output is in project
-						if (customOutput.isAbsolute()) {
-							if (!javaProject.getPath().isPrefixOf(customOutput)) {
-								return new JavaModelStatus(IJavaModelStatusConstants.PATH_OUTSIDE_PROJECT, javaProject, customOutput.toString());
-							}
-						} else {
-							return new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, customOutput);
-						}
-						
-						// ensure custom output doesn't conflict with other outputs
-						int index;
-						if ((index = indexOfMatchingPath(customOutput, outputLocations, outputCount)) != -1) {
-							continue; // already found
-						}
-						if ((index = indexOfEnclosingPath(customOutput, outputLocations, outputCount)) != -1) {
-							if (index == 0) {
-								// custom output is nested in project's output: need to check if all source entries have a custom
-								// output before complaining
-								if (potentialNestedOutput == null) potentialNestedOutput = customOutput;
-							} else {
-								return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestOutputInOutput", customOutput.makeRelative().toString(), outputLocations[index].makeRelative().toString())); //$NON-NLS-1$
-							}
-						}
-						outputLocations[outputCount++] = resolvedEntry.getOutputLocation();
-					}
-			}	
-		}	
-		// allow custom output nesting in project's output if all source entries have a custom output
-		if (potentialNestedOutput != null && sourceEntryCount > outputCount-1) {
-			return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestOutputInOutput", potentialNestedOutput.makeRelative().toString(), outputLocations[0].makeRelative().toString())); //$NON-NLS-1$
-		}
-		
-		for (int i = 0 ; i < length; i++) {
-			IClasspathEntry resolvedEntry = classpath[i];
-			IPath path = resolvedEntry.getPath();
-			int index;
-			switch(resolvedEntry.getEntryKind()){
-				
-				case IClasspathEntry.CPE_SOURCE :
-					hasSource = true;
-					if ((index = indexOfMatchingPath(path, outputLocations, outputCount)) != -1){
-						allowNestingInOutputLocations[index] = true;
-					}
-					break;
-
-				case IClasspathEntry.CPE_LIBRARY:
-					hasLibFolder |= !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(path.lastSegment());
-					if ((index = indexOfMatchingPath(path, outputLocations, outputCount)) != -1){
-						allowNestingInOutputLocations[index] = true;
-					}
-					break;
-			}
-		}
-		if (!hasSource && !hasLibFolder) { // if no source and no lib folder, then allowed
-			for (int i = 0; i < outputCount; i++) allowNestingInOutputLocations[i] = true;
-		}
-		
-		HashSet pathes = new HashSet(length);
-		
-		// check all entries
-		for (int i = 0 ; i < length; i++) {
-			IClasspathEntry entry = classpath[i];
-			if (entry == null) continue;
-			IPath entryPath = entry.getPath();
-			int kind = entry.getEntryKind();
-	
-			// complain if duplicate path
-			if (!pathes.add(entryPath)){
-				return new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, Util.bind("classpath.duplicateEntryPath", entryPath.makeRelative().toString())); //$NON-NLS-1$
-			}
-			// no further check if entry coincidates with project or output location
-			if (entryPath.equals(projectPath)){
-				// complain if self-referring project entry
-				if (kind == IClasspathEntry.CPE_PROJECT){
-					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, Util.bind("classpath.cannotReferToItself", entryPath.makeRelative().toString()));//$NON-NLS-1$
-				}
-				// tolerate nesting output in src if src==prj
-				continue;
-			}
-	
-			// allow nesting source entries in each other as long as the outer entry excludes the inner one
-			if (kind == IClasspathEntry.CPE_SOURCE 
-					|| (kind == IClasspathEntry.CPE_LIBRARY && !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(entryPath.lastSegment()))){
-				for (int j = 0; j < classpath.length; j++){
-					IClasspathEntry otherEntry = classpath[j];
-					if (otherEntry == null) continue;
-					int otherKind = otherEntry.getEntryKind();
-					IPath otherPath = otherEntry.getPath();
-					if (entry != otherEntry 
-						&& (otherKind == IClasspathEntry.CPE_SOURCE 
-								|| (otherKind == IClasspathEntry.CPE_LIBRARY 
-										&& !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(otherPath.lastSegment())))){
-						char[][] exclusionPatterns;
-						if (otherPath.isPrefixOf(entryPath) 
-								&& !otherPath.equals(entryPath)
-								&& !Util.isExcluded(entryPath.append("*"), exclusionPatterns = ((ClasspathEntry)otherEntry).fullExclusionPatternChars())) { //$NON-NLS-1$
-									
-							String exclusionPattern = entryPath.removeFirstSegments(otherPath.segmentCount()).segment(0);
-							if (Util.isExcluded(entryPath, exclusionPatterns)) {
-								return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.mustEndWithSlash", exclusionPattern, entryPath.makeRelative().toString())); //$NON-NLS-1$
-							} else {
-								if (otherKind == IClasspathEntry.CPE_SOURCE) {
-									exclusionPattern += '/';
-									return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestEntryInEntry", new String[] {entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString(), exclusionPattern})); //$NON-NLS-1$
-								} else {
-									return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestEntryInLibrary", new String[] {entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString()})); //$NON-NLS-1$
-								}
-							}
-						}
-					}
-				}
-			}
-			
-			// prevent nesting output location inside entry
-			int index;
-			if ((index = indexOfNestedPath(entryPath, outputLocations, outputCount)) != -1) {
-				return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestOutputInEntry", outputLocations[index].makeRelative().toString(), entryPath.makeRelative().toString())); //$NON-NLS-1$
-			}
-
-			// prevent nesting entry inside output location - when distinct from project or a source folder
-			if ((index = indexOfEnclosingPath(entryPath, outputLocations, outputCount)) != -1) {
-				if (!allowNestingInOutputLocations[index]) {
-					// allow nesting in project's output if all source entries have a custom output
-					if (index != 0 || sourceEntryCount > outputCount - 1) {
-						return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestEntryInOutput", entryPath.makeRelative().toString(), outputLocations[index].makeRelative().toString())); //$NON-NLS-1$
-					}
-				}
-			}
-		}
-		// ensure that no specific output is coincidating with another source folder (only allowed if matching current source folder)
-		// 36465 - for 2.0 backward compatibility, only check specific output locations (the default can still coincidate)
-		// perform one separate iteration so as to not take precedence over previously checked scenarii (in particular should
-		// diagnose nesting source folder issue before this one, for example, [src]"Project/", [src]"Project/source/" and output="Project/" should
-		// first complain about missing exclusion pattern
-		for (int i = 0 ; i < length; i++) {
-			IClasspathEntry entry = classpath[i];
-			if (entry == null) continue;
-			IPath entryPath = entry.getPath();
-			int kind = entry.getEntryKind();
-
-			if (kind == IClasspathEntry.CPE_SOURCE) {
-				IPath output = entry.getOutputLocation();
-				if (output == null) continue; // 36465 - for 2.0 backward compatibility, only check specific output locations (the default can still coincidate)
-				// if (output == null) output = projectOutputLocation; // if no specific output, still need to check using default output (this line would check default output)
-				for (int j = 0; j < length; j++) {
-					IClasspathEntry otherEntry = classpath[j];
-					if (otherEntry == entry) continue;
-					switch (otherEntry.getEntryKind()) {
-						case IClasspathEntry.CPE_SOURCE :
-							if (otherEntry.getPath().equals(output)) {
-								return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotUseDistinctSourceFolderAsOutput", entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString())); //$NON-NLS-1$
-							}
-							break;
-						case IClasspathEntry.CPE_LIBRARY :
-							if (otherEntry.getPath().equals(output)) {
-								return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotUseLibraryAsOutput", entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString())); //$NON-NLS-1$
-							}
-					}
-				}
-			}			
-		}
-		return JavaModelStatus.VERIFIED_OK;	
+		return ClasspathEntry.validateClasspath(javaProject, rawClasspath, projectOutputLocation);
 	}
 	
 	/**
@@ -681,146 +422,13 @@
 	 * a status object with code <code>IStatus.OK</code> if the entry is fine (that is, if the
 	 * given classpath entry denotes a valid element to be referenced onto a classpath).
 	 * 
-	 * @param javaProject the given java project
+	 * @param project the given java project
 	 * @param entry the given classpath entry
 	 * @param checkSourceAttachment a flag to determine if source attachement should be checked
 	 * @return a java model status describing the problem related to this classpath entry if any, a status object with code <code>IStatus.OK</code> if the entry is fine
 	 * @since 2.0
 	 */
-	public static IJavaModelStatus validateClasspathEntry(IJavaProject javaProject, IClasspathEntry entry, boolean checkSourceAttachment){
-		
-		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();			
-		IPath path = entry.getPath();
-		switch(entry.getEntryKind()){
-	
-			// container entry check
-			case IClasspathEntry.CPE_CONTAINER :
-				if (path != null && path.segmentCount() >= 1){
-					try {
-						IClasspathContainer container = JavaCore.getClasspathContainer(path, javaProject);
-						// container retrieval is performing validation check on container entry kinds.
-						if (container == null){
-							return new JavaModelStatus(IJavaModelStatusConstants.CP_CONTAINER_PATH_UNBOUND, javaProject, path);
-						}
-						IClasspathEntry[] containerEntries = container.getClasspathEntries();
-						if (containerEntries != null){
-							for (int i = 0, length = containerEntries.length; i < length; i++){
-								IClasspathEntry containerEntry = containerEntries[i];
-								int kind = containerEntry == null ? 0 : containerEntry.getEntryKind();
-								if (containerEntry == null
-									|| kind == IClasspathEntry.CPE_SOURCE
-									|| kind == IClasspathEntry.CPE_VARIABLE
-									|| kind == IClasspathEntry.CPE_CONTAINER){
-										String description = container.getDescription();
-										if (description == null) description = path.makeRelative().toString();
-										return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CP_CONTAINER_ENTRY, javaProject, path);
-								}
-								IJavaModelStatus containerEntryStatus = validateClasspathEntry(javaProject, containerEntry, checkSourceAttachment);
-								if (!containerEntryStatus.isOK()){
-									return containerEntryStatus;
-								}
-							}
-						}
-					} catch(JavaModelException e){
-						return new JavaModelStatus(e);
-					}
-				} else {
-					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalContainerPath", path.makeRelative().toString()));					 //$NON-NLS-1$
-				}
-				break;
-				
-			// variable entry check
-			case IClasspathEntry.CPE_VARIABLE :
-				if (path != null && path.segmentCount() >= 1){
-					entry = JavaCore.getResolvedClasspathEntry(entry);
-					if (entry == null){
-						return new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, javaProject, path);
-					}
-					return validateClasspathEntry(javaProject, entry, checkSourceAttachment);
-				} else {
-					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalVariablePath", path.makeRelative().toString()));					 //$NON-NLS-1$
-				}
-
-			// library entry check
-			case IClasspathEntry.CPE_LIBRARY :
-				if (path != null && path.isAbsolute() && !path.isEmpty()) {
-					IPath sourceAttachment = entry.getSourceAttachmentPath();
-					Object target = JavaModel.getTarget(workspaceRoot, path, true);
-					if (target instanceof IResource){
-						IResource resolvedResource = (IResource) target;
-						switch(resolvedResource.getType()){
-							case IResource.FILE :
-								if (Util.isArchiveFileName(resolvedResource.getFileExtension())) {
-									if (checkSourceAttachment 
-										&& sourceAttachment != null
-										&& !sourceAttachment.isEmpty()
-										&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
-										return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", sourceAttachment.makeRelative().toString(), path.makeRelative().toString())); //$NON-NLS-1$
-									}
-								}
-								break;
-							case IResource.FOLDER :	// internal binary folder
-								if (checkSourceAttachment 
-									&& sourceAttachment != null 
-									&& !sourceAttachment.isEmpty()
-									&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
-									return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", sourceAttachment.makeRelative().toString(), path.makeRelative().toString())); //$NON-NLS-1$
-								}
-						}
-					} else if (target instanceof File){
-						if (checkSourceAttachment 
-							&& sourceAttachment != null 
-							&& !sourceAttachment.isEmpty()
-							&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
-							return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", sourceAttachment.toString(), path.makeRelative().toString())); //$NON-NLS-1$
-						}
-					} else {
-						return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundLibrary", path.makeRelative().toString())); //$NON-NLS-1$
-					}
-				} else {
-					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalLibraryPath", path.makeRelative().toString())); //$NON-NLS-1$
-				}
-				break;
-
-			// project entry check
-			case IClasspathEntry.CPE_PROJECT :
-				if (path != null && path.isAbsolute() && !path.isEmpty()) {
-					IProject project = workspaceRoot.getProject(path.segment(0));
-					try {
-						if (!project.exists() || !project.hasNature(JavaCore.NATURE_ID)){
-							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundProject", path.makeRelative().segment(0).toString())); //$NON-NLS-1$
-						}
-						if (!project.isOpen()){
-							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.closedProject", path.segment(0).toString())); //$NON-NLS-1$
-						}
-					} catch (CoreException e){
-						return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundProject", path.segment(0).toString())); //$NON-NLS-1$
-					}
-				} else {
-					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalProjectPath", path.segment(0).toString())); //$NON-NLS-1$
-				}
-				break;
-
-			// project source folder
-			case IClasspathEntry.CPE_SOURCE :
-				if (entry.getExclusionPatterns() != null 
-						&& entry.getExclusionPatterns().length > 0
-						&& JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, true))) {
-					return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS, path);
-				}
-				if (entry.getOutputLocation() != null && JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, true))) {
-					return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS, path);
-				}
-				if (path != null && path.isAbsolute() && !path.isEmpty()) {
-					IPath projectPath= javaProject.getProject().getFullPath();
-					if (!projectPath.isPrefixOf(path) || JavaModel.getTarget(workspaceRoot, path, true) == null){
-						return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceFolder", path.makeRelative().toString())); //$NON-NLS-1$
-					}
-				} else {
-					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalSourceFolderPath", path.makeRelative().toString())); //$NON-NLS-1$
-				}
-				break;
-		}
-		return JavaModelStatus.VERIFIED_OK;		
+	public static IJavaModelStatus validateClasspathEntry(IJavaProject project, IClasspathEntry entry, boolean checkSourceAttachment){
+		return ClasspathEntry.validateClasspathEntry(project, entry, checkSourceAttachment, true/*recurse in container*/);
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index 3dc93bc..ffb1fef 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -30,6 +30,29 @@
  *                                 CODEASSIST_STATIC_FIELD_PREFIXES
  *                                 CODEASSIST_STATIC_FIELD_SUFFIXES
  *                                 COMPILER_PB_CHAR_ARRAY_IN_STRING_CONCATENATION
+ *     IBM Corporation - added the following constants:
+ *                                 COMPILER_PB_LOCAL_VARIABLE_HIDING
+ *                                 COMPILER_PB_SPECIAL_PARAMETER_HIDING_FIELD
+ *                                 COMPILER_PB_FIELD_HIDING
+ *                                 COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT
+ *                                 CORE_INCOMPATIBLE_JDK_LEVEL
+ *                                 VERSION_1_5
+ *                                 COMPILER_PB_SUPERFLUOUS_SEMICOLON
+ *     IBM Corporation - added the following constants:
+ *                                 COMPILER_PB_INDIRECT_STATIC_ACCESS
+ *                                 COMPILER_PB_BOOLEAN_METHOD_THROWING_EXCEPTION
+ *                                 COMPILER_PB_UNNECESSARY_CAST
+ *     IBM Corporation - added the following constants:
+ *                                 COMPILER_PB_INVALID_JAVADOC
+ *                                 COMPILER_PB_INVALID_JAVADOC_TAGS
+ *                                 COMPILER_PB_INVALID_JAVADOC_TAGS_VISIBILITY
+ *                                 COMPILER_PB_MISSING_JAVADOC_TAGS
+ *                                 COMPILER_PB_MISSING_JAVADOC_TAGS_VISIBILITY
+ *                                 COMPILER_PB_MISSING_JAVADOC_TAGS_OVERRIDING
+ *                                 COMPILER_PB_MISSING_JAVADOC_COMMENTS
+ *                                 COMPILER_PB_MISSING_JAVADOC_COMMENTS_VISIBILITY
+ *                                 COMPILER_PB_MISSING_JAVADOC_COMMENTS_OVERRIDING
+ *                                 COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD
  *******************************************************************************/
 package org.eclipse.jdt.core;
 
@@ -38,7 +61,11 @@
 
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * The plug-in runtime class for the Java model plug-in containing the core
@@ -56,7 +83,7 @@
  * automatically if not already active.
  * </p>
  */
-public final class JavaCore extends Plugin implements IExecutableExtension {
+public final class JavaCore extends Plugin {
 
 	private static Plugin JAVA_CORE_PLUGIN = null; 
 	/**
@@ -107,234 +134,399 @@
 	public static final String COMPILER_LINE_NUMBER_ATTR = PLUGIN_ID + ".compiler.debug.lineNumber"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String COMPILER_SOURCE_FILE_ATTR = PLUGIN_ID + ".compiler.debug.sourceFile"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String COMPILER_CODEGEN_UNUSED_LOCAL = PLUGIN_ID + ".compiler.codegen.unusedLocal"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String COMPILER_CODEGEN_TARGET_PLATFORM = PLUGIN_ID + ".compiler.codegen.targetPlatform"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
+	 * @deprecated - discontinued since turning off would violate language specs
 	 */
 	public static final String COMPILER_PB_UNREACHABLE_CODE = PLUGIN_ID + ".compiler.problem.unreachableCode"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
+	 * @deprecated - discontinued since turning off would violate language specs
 	 */
 	public static final String COMPILER_PB_INVALID_IMPORT = PLUGIN_ID + ".compiler.problem.invalidImport"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String COMPILER_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD = PLUGIN_ID + ".compiler.problem.overridingPackageDefaultMethod"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String COMPILER_PB_METHOD_WITH_CONSTRUCTOR_NAME = PLUGIN_ID + ".compiler.problem.methodWithConstructorName"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String COMPILER_PB_DEPRECATION = PLUGIN_ID + ".compiler.problem.deprecation"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_PB_DEPRECATION_IN_DEPRECATED_CODE = PLUGIN_ID + ".compiler.problem.deprecationInDeprecatedCode"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD = "org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
 	 */
 	public static final String COMPILER_PB_HIDDEN_CATCH_BLOCK = PLUGIN_ID + ".compiler.problem.hiddenCatchBlock"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String COMPILER_PB_UNUSED_LOCAL = PLUGIN_ID + ".compiler.problem.unusedLocal"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String COMPILER_PB_UNUSED_PARAMETER = PLUGIN_ID + ".compiler.problem.unusedParameter"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_PB_UNUSED_PARAMETER_WHEN_IMPLEMENTING_ABSTRACT = PLUGIN_ID + ".compiler.problem.unusedParameterWhenImplementingAbstract"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_PB_UNUSED_PARAMETER_WHEN_OVERRIDING_CONCRETE = PLUGIN_ID + ".compiler.problem.unusedParameterWhenOverridingConcrete"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String COMPILER_PB_UNUSED_IMPORT = PLUGIN_ID + ".compiler.problem.unusedImport"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String COMPILER_PB_SYNTHETIC_ACCESS_EMULATION = PLUGIN_ID + ".compiler.problem.syntheticAccessEmulation"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String COMPILER_PB_NON_NLS_STRING_LITERAL = PLUGIN_ID + ".compiler.problem.nonExternalizedStringLiteral"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String COMPILER_PB_ASSERT_IDENTIFIER = PLUGIN_ID + ".compiler.problem.assertIdentifier"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_PB_STATIC_ACCESS_RECEIVER = PLUGIN_ID + ".compiler.problem.staticAccessReceiver"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_INDIRECT_STATIC_ACCESS = PLUGIN_ID + ".compiler.problem.indirectStaticAccess"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_PB_NO_EFFECT_ASSIGNMENT = PLUGIN_ID + ".compiler.problem.noEffectAssignment"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_PB_INCOMPATIBLE_NON_INHERITED_INTERFACE_METHOD = PLUGIN_ID + ".compiler.problem.incompatibleNonInheritedInterfaceMethod"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_PB_UNUSED_PRIVATE_MEMBER = PLUGIN_ID + ".compiler.problem.unusedPrivateMember"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_LOCAL_VARIABLE_HIDING = PLUGIN_ID + ".compiler.problem.localVariableHiding"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_SPECIAL_PARAMETER_HIDING_FIELD = PLUGIN_ID + ".compiler.problem.specialParameterHidingField"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_FIELD_HIDING = PLUGIN_ID + ".compiler.problem.fieldHiding"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_POSSIBLE_ACCIDENTAL_BOOLEAN_ASSIGNMENT = PLUGIN_ID + ".compiler.problem.possibleAccidentalBooleanAssignment"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_SUPERFLUOUS_SEMICOLON = PLUGIN_ID + ".compiler.problem.superfluousSemicolon"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_BOOLEAN_METHOD_THROWING_EXCEPTION = PLUGIN_ID + ".compiler.problem.booleanMethodThrowingException"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_UNNECESSARY_TYPE_CHECK = PLUGIN_ID + ".compiler.problem.unnecessaryTypeCheck"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_UNDOCUMENTED_EMPTY_BLOCK = PLUGIN_ID + ".compiler.problem.undocumentedEmptyBlock"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_FINALLY_BLOCK_NOT_COMPLETING = PLUGIN_ID + ".compiler.problem.finallyBlockNotCompletingNormally"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_UNUSED_DECLARED_THROWN_EXCEPTION = PLUGIN_ID + ".compiler.problem.unusedDeclaredThrownException"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_UNQUALIFIED_FIELD_ACCESS = PLUGIN_ID + ".compiler.problem.unqualifiedFieldAccess"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_INVALID_JAVADOC = PLUGIN_ID + ".compiler.problem.invalidJavadoc"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #COMPILER_PB_INVALID_JAVADOC
+	 * @deprecated
+	 * TODO (frederic) remove after 3.0 M6
+	 */
+	public static final String COMPILER_PB_INVALID_ANNOTATION = COMPILER_PB_INVALID_JAVADOC;
+	public static final String OLD_COMPILER_PB_INVALID_ANNOTATION = PLUGIN_ID + ".compiler.problem.invalidAnnotation"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_INVALID_JAVADOC_TAGS = PLUGIN_ID + ".compiler.problem.invalidJavadocTags"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_INVALID_JAVADOC_TAGS_VISIBILITY = PLUGIN_ID + ".compiler.problem.invalidJavadocTagsVisibility"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_MISSING_JAVADOC_TAGS = PLUGIN_ID + ".compiler.problem.missingJavadocTags"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_MISSING_JAVADOC_TAGS_VISIBILITY = PLUGIN_ID + ".compiler.problem.missingJavadocTagsVisibility"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_MISSING_JAVADOC_TAGS_OVERRIDING = PLUGIN_ID + ".compiler.problem.missingJavadocTagsOverriding"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_MISSING_JAVADOC_COMMENTS = PLUGIN_ID + ".compiler.problem.missingJavadocComments"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 * @deprecated
+	 * TODO (frederic) remove after 3.0 M7
+	 */
+	public static final String COMPILER_PB_MISSING_JAVADOC = COMPILER_PB_MISSING_JAVADOC_COMMENTS;
+	public static final String OLD_COMPILER_PB_MISSING_JAVADOC = PLUGIN_ID + ".compiler.problem.missingJavadoc"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #COMPILER_PB_MISSING_JAVADOC
+	 * @deprecated
+	 * TODO (frederic) after 3.0 M6
+	 */
+	public static final String COMPILER_PB_MISSING_ANNOTATION = COMPILER_PB_MISSING_JAVADOC;
+	public static final String OLD_COMPILER_PB_MISSING_ANNOTATION = PLUGIN_ID + ".compiler.problem.missingAnnotation"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_MISSING_JAVADOC_COMMENTS_VISIBILITY = PLUGIN_ID + ".compiler.problem.missingJavadocCommentsVisibility"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String COMPILER_PB_MISSING_JAVADOC_COMMENTS_OVERRIDING = PLUGIN_ID + ".compiler.problem.missingJavadocCommentsOverriding"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_PB_CHAR_ARRAY_IN_STRING_CONCATENATION = PLUGIN_ID + ".compiler.problem.noImplicitStringConversion"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String COMPILER_PB_MAX_PER_UNIT = PLUGIN_ID + ".compiler.maxProblemPerUnit"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String COMPILER_SOURCE = PLUGIN_ID + ".compiler.source"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String COMPILER_COMPLIANCE = PLUGIN_ID + ".compiler.compliance"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_TASK_PRIORITIES = PLUGIN_ID + ".compiler.taskPriorities"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value for COMPILER_TASK_PRIORITIES.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_TASK_PRIORITY_HIGH = "HIGH"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value for COMPILER_TASK_PRIORITIES.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_TASK_PRIORITY_LOW = "LOW"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value for COMPILER_TASK_PRIORITIES.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_TASK_PRIORITY_NORMAL = "NORMAL"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String COMPILER_TASK_TAGS = PLUGIN_ID + ".compiler.taskTags"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String CORE_JAVA_BUILD_ORDER = PLUGIN_ID + ".computeJavaBuildOrder"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String CORE_JAVA_BUILD_RESOURCE_COPY_FILTER = PLUGIN_ID + ".builder.resourceCopyExclusionFilter"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CORE_JAVA_BUILD_DUPLICATE_RESOURCE = PLUGIN_ID + ".builder.duplicateResourceTask"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER = PLUGIN_ID + ".builder.cleanOutputFolder"; //$NON-NLS-1$	 	
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CORE_INCOMPLETE_CLASSPATH = PLUGIN_ID + ".incompleteClasspath"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CORE_CIRCULAR_CLASSPATH = PLUGIN_ID + ".circularClasspath"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String CORE_INCOMPATIBLE_JDK_LEVEL = PLUGIN_ID + ".incompatibleJDKLevel"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option ID.
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String CORE_JAVA_BUILD_INVALID_CLASSPATH = PLUGIN_ID + ".builder.invalidClasspath"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String CORE_ENCODING = PLUGIN_ID + ".encoding"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1 
 	 */
 	public static final String CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS = PLUGIN_ID + ".classpath.exclusionPatterns"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS = PLUGIN_ID + ".classpath.multipleOutputLocations"; //$NON-NLS-1$
@@ -350,121 +542,128 @@
 	public static final String DEFAULT_TASK_PRIORITY = "NORMAL"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
+	 * @deprecated
 	 */
 	public static final String FORMATTER_NEWLINE_OPENING_BRACE = PLUGIN_ID + ".formatter.newline.openingBrace"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
+	 * @deprecated
 	 */
 	public static final String FORMATTER_NEWLINE_CONTROL = PLUGIN_ID + ".formatter.newline.controlStatement"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
+	 * @deprecated
 	 */
 	public static final String FORMATTER_NEWLINE_ELSE_IF = PLUGIN_ID + ".formatter.newline.elseIf"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
+	 * @deprecated
 	 */
 	public static final String FORMATTER_NEWLINE_EMPTY_BLOCK = PLUGIN_ID + ".formatter.newline.emptyBlock"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
+	 * @deprecated
 	 */
 	public static final String FORMATTER_CLEAR_BLANK_LINES = PLUGIN_ID + ".formatter.newline.clearAll"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String FORMATTER_LINE_SPLIT = PLUGIN_ID + ".formatter.lineSplit"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
+	 * @deprecated
 	 */
 	public static final String FORMATTER_COMPACT_ASSIGNMENT = PLUGIN_ID + ".formatter.style.assignment"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String FORMATTER_TAB_CHAR = PLUGIN_ID + ".formatter.tabulation.char"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String FORMATTER_TAB_SIZE = PLUGIN_ID + ".formatter.tabulation.size"; //$NON-NLS-1$
 	/**
 	 * Possible configurable option ID
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
+	 * @deprecated
 	 */
 	public static final String FORMATTER_SPACE_CASTEXPRESSION = PLUGIN_ID + ".formatter.space.castexpression"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String CODEASSIST_VISIBILITY_CHECK = PLUGIN_ID + ".codeComplete.visibilityCheck"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String CODEASSIST_IMPLICIT_QUALIFICATION = PLUGIN_ID + ".codeComplete.forceImplicitQualification"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CODEASSIST_FIELD_PREFIXES = PLUGIN_ID + ".codeComplete.fieldPrefixes"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CODEASSIST_STATIC_FIELD_PREFIXES = PLUGIN_ID + ".codeComplete.staticFieldPrefixes"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CODEASSIST_LOCAL_PREFIXES = PLUGIN_ID + ".codeComplete.localPrefixes"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CODEASSIST_ARGUMENT_PREFIXES = PLUGIN_ID + ".codeComplete.argumentPrefixes"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CODEASSIST_FIELD_SUFFIXES = PLUGIN_ID + ".codeComplete.fieldSuffixes"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CODEASSIST_STATIC_FIELD_SUFFIXES = PLUGIN_ID + ".codeComplete.staticFieldSuffixes"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CODEASSIST_LOCAL_SUFFIXES = PLUGIN_ID + ".codeComplete.localSuffixes"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option ID.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CODEASSIST_ARGUMENT_SUFFIXES = PLUGIN_ID + ".codeComplete.argumentSuffixes"; //$NON-NLS-1$
@@ -473,141 +672,172 @@
 	
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String GENERATE = "generate"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String DO_NOT_GENERATE = "do not generate"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String PRESERVE = "preserve"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String OPTIMIZE_OUT = "optimize out"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String VERSION_1_1 = "1.1"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String VERSION_1_2 = "1.2"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String VERSION_1_3 = "1.3"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String VERSION_1_4 = "1.4"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String VERSION_1_5 = "1.5"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option value.
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String ABORT = "abort"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String ERROR = "error"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String WARNING = "warning"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String IGNORE = "ignore"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 */
 	public static final String COMPUTE = "compute"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String INSERT = "insert"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String DO_NOT_INSERT = "do not insert"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String PRESERVE_ONE = "preserve one"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String CLEAR_ALL = "clear all"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String NORMAL = "normal"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String COMPACT = "compact"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String TAB = "tab"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String SPACE = "space"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String ENABLED = "enabled"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static final String DISABLED = "disabled"; //$NON-NLS-1$
 	/**
 	 * Possible  configurable option value.
-	 * @see #getDefaultOptions
+	 * @see #getDefaultOptions()
 	 * @since 2.1
 	 */
 	public static final String CLEAN = "clean"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option value.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String PUBLIC = "public"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option value.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String PROTECTED = "protected"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option value.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String DEFAULT = "default"; //$NON-NLS-1$
+	/**
+	 * Possible  configurable option value.
+	 * @see #getDefaultOptions()
+	 * @since 3.0
+	 */
+	public static final String PRIVATE = "private"; //$NON-NLS-1$
 	
 	/**
 	 * Creates the Java core plug-in.
+	 * @param pluginDescriptor
 	 * @since 2.1
 	 */
 	public JavaCore(IPluginDescriptor pluginDescriptor) {
@@ -624,8 +854,8 @@
 	 * For finer control of the notification, use <code>addElementChangedListener(IElementChangedListener,int)</code>,
 	 * which allows to specify a different eventMask.
 	 * 
-	 * @see ElementChangedEvent
 	 * @param listener the listener
+	 * @see ElementChangedEvent
 	 */
 	public static void addElementChangedListener(IElementChangedListener listener) {
 		addElementChangedListener(listener, ElementChangedEvent.POST_CHANGE | ElementChangedEvent.POST_RECONCILE);
@@ -658,7 +888,7 @@
 	 * @since 2.0
 	 */
 	public static void addElementChangedListener(IElementChangedListener listener, int eventMask) {
-		JavaModelManager.getJavaModelManager().addElementChangedListener(listener, eventMask);
+		JavaModelManager.getJavaModelManager().deltaState.addElementChangedListener(listener, eventMask);
 	}
 
 	/**
@@ -698,17 +928,51 @@
 	 * Returns the Java model element corresponding to the given handle identifier
 	 * generated by <code>IJavaElement.getHandleIdentifier()</code>, or
 	 * <code>null</code> if unable to create the associated element.
+	 * 
+	 * @param handleIdentifier the given handle identifier
+	 * @return the Java element corresponding to the handle identifier
 	 */
 	public static IJavaElement create(String handleIdentifier) {
+		return create(handleIdentifier, DefaultWorkingCopyOwner.PRIMARY);
+	}
+
+	/**
+	 * Returns the Java model element corresponding to the given handle identifier
+	 * generated by <code>IJavaElement.getHandleIdentifier()</code>, or
+	 * <code>null</code> if unable to create the associated element.
+	 * If the returned Java element is an <code>ICompilationUnit</code>, its owner
+	 * is the given owner if such a working copy exists, otherwise the compilation unit 
+	 * is a primary compilation unit.
+	 * 
+	 * @param handleIdentifier the given handle identifier
+	 * @param owner the owner of the returned compilation unit, ignored if the returned
+	 *   element is not a compilation unit
+	 * @return the Java element corresponding to the handle identifier
+	 * @since 3.0
+	 */
+	public static IJavaElement create(String handleIdentifier, WorkingCopyOwner owner) {
 		if (handleIdentifier == null) {
 			return null;
 		}
-		try {
-			return JavaModelManager.getJavaModelManager().getHandleFromMemento(handleIdentifier);
-		} catch (JavaModelException e) {
-			return null;
-		}
+		String delimiters = new String(new char[] {
+			JavaElement.JEM_COUNT,
+			JavaElement.JEM_JAVAPROJECT,
+			JavaElement.JEM_PACKAGEFRAGMENTROOT,
+			JavaElement.JEM_PACKAGEFRAGMENT,
+			JavaElement.JEM_FIELD,
+			JavaElement.JEM_METHOD,
+			JavaElement.JEM_INITIALIZER,
+			JavaElement.JEM_COMPILATIONUNIT,
+			JavaElement.JEM_CLASSFILE,
+			JavaElement.JEM_TYPE,
+			JavaElement.JEM_PACKAGEDECLARATION,
+			JavaElement.JEM_IMPORTDECLARATION,
+			JavaElement.JEM_LOCALVARIABLE});
+		StringTokenizer memento = new StringTokenizer(handleIdentifier, delimiters, true);
+		JavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
+		return model.getHandleFromMemento(memento, owner);
 	}
+	
 	/**
 	 * Returns the Java element corresponding to the given file, or
 	 * <code>null</code> if unable to associate the given file
@@ -723,13 +987,13 @@
 	 * Creating a Java element has the side effect of creating and opening all of the
 	 * element's parents if they are not yet open.
 	 * 
-	 * @param the given file
+	 * @param file the given file
 	 * @return the Java element corresponding to the given file, or
 	 * <code>null</code> if unable to associate the given file
 	 * with a Java element
 	 */
 	public static IJavaElement create(IFile file) {
-		return JavaModelManager.create(file, null);
+		return JavaModelManager.create(file, null/*unknown java project*/);
 	}
 	/**
 	 * Returns the package fragment or package fragment root corresponding to the given folder, or
@@ -740,12 +1004,12 @@
 	 * Creating a Java element has the side effect of creating and opening all of the
 	 * element's parents if they are not yet open.
 	 * 
-	 * @param the given folder
+	 * @param folder the given folder
 	 * @return the package fragment or package fragment root corresponding to the given folder, or
 	 * <code>null</code> if unable to associate the given folder with a Java element
 	 */
 	public static IJavaElement create(IFolder folder) {
-		return JavaModelManager.create(folder, null);
+		return JavaModelManager.create(folder, null/*unknown java project*/);
 	}
 	/**
 	 * Returns the Java project corresponding to the given project.
@@ -789,7 +1053,7 @@
 	 * with a Java element
 	 */
 	public static IJavaElement create(IResource resource) {
-		return JavaModelManager.create(resource, null);
+		return JavaModelManager.create(resource, null/*unknown java project*/);
 	}
 	/**
 	 * Returns the Java model.
@@ -825,7 +1089,7 @@
 	 * to recognize the compilation unit
 	 */
 	public static ICompilationUnit createCompilationUnitFrom(IFile file) {
-		return JavaModelManager.createCompilationUnitFrom(file, null);
+		return JavaModelManager.createCompilationUnitFrom(file, null/*unknown java project*/);
 	}
 	/**
 	 * Creates and returns a handle for the given JAR file.
@@ -837,7 +1101,7 @@
 	 * (for example, if the JAR file represents a non-Java resource)
 	 */
 	public static IPackageFragmentRoot createJarPackageFragmentRootFrom(IFile file) {
-		return JavaModelManager.createJarPackageFragmentRootFrom(file, null);
+		return JavaModelManager.createJarPackageFragmentRootFrom(file, null/*unknown java project*/);
 	}
 
 	/** 
@@ -936,7 +1200,7 @@
 	 * <p>
 	 * A containerID is the first segment of any container path, used to identify the registered container initializer.
 	 * <p>
-	 * @param String - a containerID identifying a registered initializer
+	 * @param containerID - a containerID identifying a registered initializer
 	 * @return ClasspathContainerInitializer - the registered classpath container initializer or <code>null</code> if 
 	 * none was found.
 	 * @since 2.1
@@ -963,6 +1227,11 @@
 								return (ClasspathContainerInitializer)execExt;
 							}
 						} catch(CoreException e) {
+							// executable extension could not be created: ignore this initializer
+							if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+								System.out.println("CPContainer INIT - failed to instanciate initializer: "+containerID +" --> " + configElements[j].getAttribute("class"));//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+								e.printStackTrace();
+							}						
 						}
 					}
 				}
@@ -986,7 +1255,7 @@
 	 *
 	 * @param variableName the name of the classpath variable
 	 * @return the path, or <code>null</code> if none 
-	 * @see #setClasspathVariable
+	 * @see #setClasspathVariable(String, IPath)
 	 */
 	public static IPath getClasspathVariable(final String variableName) {
 	
@@ -1016,7 +1285,7 @@
 						initializer.initialize(variableName);
 					}
 				});
-				variablePath = (IPath) JavaModelManager.variableGet(variableName); // initializer should have performed side-effect
+				variablePath = JavaModelManager.variableGet(variableName); // initializer should have performed side-effect
 				if (variablePath == JavaModelManager.VariableInitializationInProgress) return null; // break cycle (initializer did not init or reentering call)
 				if (JavaModelManager.CP_RESOLVE_VERBOSE){
 					System.out.println("CPVariable INIT - after initialization: " + variableName + " --> " + variablePath); //$NON-NLS-2$//$NON-NLS-1$
@@ -1038,7 +1307,7 @@
 	 * or <code>null</code> if none was found while iterating over the contributions to extension point to
 	 * the extension point "org.eclipse.jdt.core.classpathVariableInitializer".
 	 * <p>
- 	 * @param the given variable
+ 	 * @param variable the given variable
  	 * @return ClasspathVariableInitializer - the registered classpath variable initializer or <code>null</code> if 
 	 * none was found.
 	 * @since 2.1
@@ -1066,8 +1335,13 @@
 							}
 						}
 					} catch(CoreException e){
+						// executable extension could not be created: ignore this initializer
+						if (JavaModelManager.CP_RESOLVE_VERBOSE) {
+							System.out.println("CPContainer INIT - failed to instanciate initializer: "+variable +" --> " + configElements[j].getAttribute("class"));//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
+							e.printStackTrace();
+						}						
 					}
-					}
+				}
 			}	
 		}
 		return null;
@@ -1081,7 +1355,7 @@
 	 * <p>
 	 *
 	 * @return the list of classpath variable names
-	 * @see #setClasspathVariable
+	 * @see #setClasspathVariable(String, IPath)
 	 */
 	public static String[] getClasspathVariableNames() {
 		return JavaModelManager.variableNames();
@@ -1132,23 +1406,9 @@
 	 *    For binary compatibility reason, .class files can be tagged to with certain VM versions and later.
 	 *    Note that "1.4" target require to toggle compliance mode to "1.4" too.
 	 *     - option id:         "org.eclipse.jdt.core.compiler.codegen.targetPlatform"
-	 *     - possible values:   { "1.1", "1.2", "1.3", "1.4" }
+	 *     - possible values:   { "1.1", "1.2", "1.3", "1.4", "1.5" }
 	 *     - default:           "1.1"
 	 *
-	 * COMPILER / Reporting Unreachable Code
-	 *    Unreachable code can optionally be reported as an error, warning or simply 
-	 *    ignored. The bytecode generation will always optimized it out.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.unreachableCode"
-	 *     - possible values:   { "error", "warning", "ignore" }
-	 *     - default:           "error"
-	 *
-	 * COMPILER / Reporting Invalid Import
-	 *    An import statement that cannot be resolved might optionally be reported 
-	 *    as an error, as a warning or ignored.
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidImport"
-	 *     - possible values:   { "error", "warning", "ignore" }
-	 *     - default:           "error"
-	 *
 	 * COMPILER / Reporting Attempt to Override Package-Default Method
 	 *    A package default method is not visible in a different package, and thus 
 	 *    cannot be overridden. When enabling this option, the compiler will signal 
@@ -1179,6 +1439,13 @@
 	 *     - possible values:   { "enabled", "disabled" }
 	 *     - default:           "disabled"
 	 *
+	 * COMPILER / Reporting Deprecation When Overriding Deprecated Method
+	 *    When enabled, the compiler will signal the declaration of a method overriding a deprecated one.
+	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.deprecation".
+	 *     - option id:        "org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "disabled"
+	 *
 	 * COMPILER / Reporting Hidden Catch Block
 	 *    Locally to a try statement, some catch blocks may hide others . For example,
 	 *      try {  throw new java.io.CharConversionException();
@@ -1232,6 +1499,26 @@
 	 *     - possible values:   { "error", "warning", "ignore" }
 	 *     - default:           "ignore"
 	 *
+	 * COMPILER / Reporting Assignment with no Effect
+	 *    When enabled, the compiler will issue an error or a warning whenever an assignment
+	 *    has no effect (e.g 'x = x').
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.noEffectAssignment"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "warning"
+	 * 
+	 * COMPILER / Reporting Superfluous Semicolon
+	 *    When enabled, the compiler will issue an error or a warning if a superfluous semicolon is met.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.superfluousSemicolon"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
+	 * COMPILER / Reporting Unnecessary Type Check
+	 *    When enabled, the compiler will issue an error or a warning when a cast or an instanceof operation 
+	 *    is unnecessary.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
 	 * COMPILER / Reporting Synthetic Access Emulation
 	 *    When enabled, the compiler will issue an error or a warning whenever it emulates 
 	 *    access to a non-accessible member of an enclosing type. Such access can have
@@ -1262,12 +1549,13 @@
 	 *     - possible values:   { "error", "warning", "ignore" }
 	 *     - default:           "warning"
 	 * 
-	 * COMPILER / Reporting Assignment with no Effect
-	 *    When enabled, the compiler will issue an error or a warning whenever an assignment
-	 *    has no effect (e.g 'x = x').
-	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.noEffectAssignment"
+	 * COMPILER / Reporting Indirect Reference to a Static Member
+	 *    When enabled, the compiler will issue an error or a warning whenever a static field
+	 *    or method is accessed in an indirect way. A reference to a static member should
+	 *    preferably be qualified with its declaring type name.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.indirectStaticAccess"
 	 *     - possible values:   { "error", "warning", "ignore" }
-	 *     - default:           "warning"
+	 *     - default:           "ignore"
 	 * 
 	 * COMPILER / Reporting Interface Method not Compatible with non-Inherited Methods
 	 *    When enabled, the compiler will issue an error or a warning whenever an interface
@@ -1287,19 +1575,143 @@
 	 *     - possible values:   { "error", "warning", "ignore" }
 	 *     - default:           "warning"
 	 *
+	 * COMPILER / Reporting Local Variable Declaration Hiding another Variable
+	 *    When enabled, the compiler will issue an error or a warning whenever a local variable
+	 *    declaration is hiding some field or local variable (either locally, inherited or defined in enclosing type).
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.localVariableHiding"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 *
+	 * COMPILER / Reporting Field Declaration Hiding another Variable
+	 *    When enabled, the compiler will issue an error or a warning whenever a field
+	 *    declaration is hiding some field or local variable (either locally, inherited or defined in enclosing type).
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.fieldHiding"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 *
+	 * COMPILER / Reporting Special Parameter Hiding another Field
+	 *    When enabled, the compiler will signal cases where a constructor or setter method parameter declaration 
+	 *    is hiding some field (either locally, inherited or defined in enclosing type).
+	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.localVariableHiding".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.specialParameterHidingField"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "disabled"
+	 * 
+	 * COMPILER / Reporting Possible Accidental Boolean Assignment
+	 *    When enabled, the compiler will issue an error or a warning if a boolean assignment is acting as the condition
+	 *    of a control statement  (where it probably was meant to be a boolean comparison).
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
+	 * COMPILER / Reporting Undocumented Empty Block
+	 *    When enabled, the compiler will issue an error or a warning when an empty block is detected and it is not
+	 *    documented with any comment.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 *
+	 * COMPILER / Reporting Finally Blocks Not Completing Normally
+	 *    When enabled, the compiler will issue an error or a warning when a finally block does not complete normally.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "warning"
+	 *
+	 * COMPILER / Reporting Unused Declared Thrown Exception
+	 *    When enabled, the compiler will issue an error or a warning when a method or a constructor is declaring a
+	 *    thrown checked exception, but never actually raises it in its body.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 *
+	 * COMPILER / Reporting Unqualified Access to Field
+	 *    When enabled, the compiler will issue an error or a warning when a field is access without any qualification.
+	 *    In order to improve code readability, it should be qualified, e.g. 'x' should rather be written 'this.x'.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 *
+	 * COMPILER / Reporting Invalid Javadoc Comment
+	 *    This is the generic control for the severity of Javadoc problems.
+	 *    When enabled, the compiler will issue an error or a warning for a problem in Javadoc.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadoc"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 *
+	 * COMPILER / Visibility Level For Invalid Javadoc Tags
+	 *    Set the minimum visibility level for Javadoc tag problems. Below this level problems will be ignored.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility"
+	 *     - possible values:   { "public", "protected", "default", "private" }
+	 *     - default:           "private"
+	 * 
+	 * COMPILER / Reporting Invalid Javadoc Tags
+	 *    When enabled, the compiler will signal unbound or unexpected reference tags in Javadoc.
+	 *    A 'throws' tag referencing an undeclared exception would be considered as unexpected.
+	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility".
+	 *    <br>
+	 *    The severity of the problem is controlled with option "org.eclipse.jdt.core.compiler.problem.invalidJavadoc".
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTags"
+	 *     - possible values:   { "disabled", "enabled" }
+	 *     - default:           "enabled"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Tags
+	 *    This is the generic control for the severity of Javadoc missing tag problems.
+	 *    When enabled, the compiler will issue an error or a warning when tags are missing in Javadoc comments.
+	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility".
+	 *    <br>
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTags"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
+	 * COMPILER / Visibility Level For Missing Javadoc Tags
+	 *    Set the minimum visibility level for Javadoc missing tag problems. Below this level problems will be ignored.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility"
+	 *     - possible values:   { "public", "protected", "default", "private" }
+	 *     - default:           "private"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Tags on Overriding Methods
+	 *    Specify whether the compiler will verify overriding methods in order to report Javadoc missing tag problems.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "enabled"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Comments
+	 *    This is the generic control for the severity of missing Javadoc comment problems.
+	 *    When enabled, the compiler will issue an error or a warning when Javadoc comments are missing.
+	 *    <br>Note that this diagnosis can be enabled based on the visibility of the construct associated with the expected Javadoc;
+	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility".
+	 *    <br>
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocComments"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
+	 * COMPILER / Visibility Level For Missing Javadoc Comments
+	 *    Set the minimum visibility level for missing Javadoc problems. Below this level problems will be ignored.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility"
+	 *     - possible values:   { "public", "protected", "default", "private" }
+	 *     - default:           "public"
+	 * 
+	 * COMPILER / Reporting Missing Javadoc Comments on Overriding Methods
+	 *    Specify whether the compiler will verify overriding methods in order to report missing Javadoc comment problems.
+	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding"
+	 *     - possible values:   { "enabled", "disabled" }
+	 *     - default:           "enabled"
+	 * 
 	 * COMPILER / Setting Source Compatibility Mode
-	 *    Specify whether source is 1.3 or 1.4 compatible. From 1.4 on, 'assert' is a keyword
+	 *    Specify whether which source level compatibility is used. From 1.4 on, 'assert' is a keyword
 	 *    reserved for assertion support. Also note, than when toggling to 1.4 mode, the target VM
 	 *   level should be set to "1.4" and the compliance mode should be "1.4".
 	 *     - option id:         "org.eclipse.jdt.core.compiler.source"
-	 *     - possible values:   { "1.3", "1.4" }
+	 *     - possible values:   { "1.3", "1.4", "1.5" }
 	 *     - default:           "1.3"
 	 * 
 	 * COMPILER / Setting Compliance Level
 	 *    Select the compliance level for the compiler. In "1.3" mode, source and target settings
 	 *    should not go beyond "1.3" level.
 	 *     - option id:         "org.eclipse.jdt.core.compiler.compliance"
-	 *     - possible values:   { "1.3", "1.4" }
+	 *     - possible values:   { "1.3", "1.4", "1.5" }
 	 *     - default:           "1.3"
 	 * 
 	 * COMPILER / Maximum number of problems reported per compilation unit
@@ -1312,7 +1724,11 @@
 	 *    When the tag list is not empty, the compiler will issue a task marker whenever it encounters
 	 *    one of the corresponding tag inside any comment in Java source code.
 	 *    Generated task messages will include the tag, and range until the next line separator or comment ending.
-	 *    Note that tasks messages are trimmed.
+	 *    Note that tasks messages are trimmed. If a tag is starting with a letter or digit, then it cannot be leaded by
+	 *    another letter or digit to be recognized ("fooToDo" will not be recognized as a task for tag "ToDo", but "foo#ToDo"
+	 *    will be detected for either tag "ToDo" or "#ToDo"). Respectively, a tag ending with a letter or digit cannot be followed
+	 *    by a letter or digit to be recognized ("ToDofoo" will not be recognized as a task for tag "ToDo", but "ToDo:foo" will
+	 *    be detected either for tag "ToDo" or "ToDo:").
 	 *     - option id:         "org.eclipse.jdt.core.compiler.taskTags"
 	 *     - possible values:   { "<tag>[,<tag>]*" } where <tag> is a String without any wild-card or leading/trailing spaces 
 	 *     - default:           ""
@@ -1380,6 +1796,13 @@
 	 *     - possible values:   { "error", "warning" }
 	 *     - default:           "error"
 	 * 
+	 * JAVACORE / Reporting Incompatible JDK Level for Required Binaries
+	 *    Indicate the severity of the problem reported when a project prerequisites another project 
+	 *    or library with an incompatible target JDK level (e.g. project targeting 1.1 vm, but compiled against 1.4 libraries).
+	 *     - option id:         "org.eclipse.jdt.core.incompatibleJDKLevel"
+	 *     - possible values:   { "error", "warning", "ignore" }
+	 *     - default:           "ignore"
+	 * 
 	 * JAVACORE / Enabling Usage of Classpath Exclusion Patterns
 	 *    When disabled, no entry on a project classpath can be associated with
 	 *    an exclusion pattern.
@@ -1535,7 +1958,7 @@
 	 * 
 	 * @return a mutable table containing the default settings of all known options
 	 *   (key type: <code>String</code>; value type: <code>String</code>)
-	 * @see #setOptions
+	 * @see #setOptions(Hashtable)
 	 */
  	public static Hashtable getDefaultOptions(){
 	
@@ -1563,6 +1986,9 @@
 		}		
 		// get encoding through resource plugin
 		defaultOptions.put(CORE_ENCODING, ResourcesPlugin.getEncoding()); 
+		// backward compatibility
+		defaultOptions.put(COMPILER_PB_INVALID_IMPORT, ERROR);		
+		defaultOptions.put(COMPILER_PB_UNREACHABLE_CODE, ERROR);
 		
 		return defaultOptions;
 	}
@@ -1586,7 +2012,7 @@
 	 * 
 	 * @param optionName the name of an option
 	 * @return the String value of a given option
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#getDefaultOptions()
 	 * @since 2.0
 	 */
 	public static String getOption(String optionName) {
@@ -1594,9 +2020,15 @@
 		if (CORE_ENCODING.equals(optionName)){
 			return ResourcesPlugin.getEncoding();
 		}
-		if (JavaModelManager.OptionNames.contains(optionName)){
+		// backward compatibility
+		if (COMPILER_PB_INVALID_IMPORT.equals(optionName)
+				|| COMPILER_PB_UNREACHABLE_CODE.equals(optionName)) {
+			return ERROR;
+		}
+		String propertyName = optionName;
+		if (JavaModelManager.OptionNames.contains(propertyName)){
 			Preferences preferences = getPlugin().getPluginPreferences();
-			return preferences.getString(optionName).trim();
+			return preferences.getString(propertyName).trim();
 		}
 		return null;
 	}
@@ -1610,8 +2042,8 @@
 	 * 
 	 * @return table of current settings of all options 
 	 *   (key type: <code>String</code>; value type: <code>String</code>)
-	 * @see JavaCore#getDefaultOptions
-	 */
+	 * @see JavaCore#getDefaultOptions()
+	 *///TODO should return a Map for 3.0
 	public static Hashtable getOptions() {
 		
 		Hashtable options = new Hashtable(10);
@@ -1634,12 +2066,41 @@
 			String[] propertyNames = preferences.propertyNames();
 			for (int i = 0; i < propertyNames.length; i++){
 				String propertyName = propertyNames[i];
+				String value = preferences.getString(propertyName).trim();
 				if (optionNames.contains(propertyName)){
-					options.put(propertyName, preferences.getString(propertyName).trim());
+					options.put(propertyName, value);
 				}
-			}		
+				// bug 45112 backward compatibility.
+				// TODO (frederic) remove after 3.0 M6
+				else if (CompilerOptions.OPTION_ReportInvalidAnnotation.equals(propertyName)) {
+					options.put(COMPILER_PB_INVALID_JAVADOC, value);
+				}
+				else if (CompilerOptions.OPTION_ReportMissingAnnotation.equals(propertyName)) {
+					if (ENABLED.equals(value)) {
+						value = preferences.getString(CompilerOptions.OPTION_ReportInvalidAnnotation);
+					} else {
+						value = IGNORE;
+					}
+					options.put(COMPILER_PB_MISSING_JAVADOC_COMMENTS, value);
+				}
+				// end bug 45112
+				// bug 46854 backward compatibility
+				// TODO (frederic) remove after 3.0 M7
+				else if (CompilerOptions.OPTION_ReportMissingJavadoc.equals(propertyName)) {
+					if (ENABLED.equals(value)) {
+						value = preferences.getString(COMPILER_PB_INVALID_JAVADOC);
+					} else {
+						value = IGNORE;
+					}
+					options.put(COMPILER_PB_MISSING_JAVADOC_COMMENTS, value);
+				}
+				// end bug 46854
+			}
 			// get encoding through resource plugin
 			options.put(CORE_ENCODING, ResourcesPlugin.getEncoding());
+			// backward compatibility
+			options.put(COMPILER_PB_INVALID_IMPORT, ERROR);
+			options.put(COMPILER_PB_UNREACHABLE_CODE, ERROR);
 		}
 		return options;
 	}
@@ -1700,7 +2161,7 @@
 						return JavaCore.newProjectEntry(resolvedPath, entry.isExported());
 						
 					case IResource.FILE : 
-						if (Util.isArchiveFileName(resolvedResource.getName())) {
+						if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resolvedResource.getName())) {
 							// internal binary archive
 							return JavaCore.newLibraryEntry(
 									resolvedPath,
@@ -1725,9 +2186,8 @@
 			File externalFile = (File) target;
 			if (externalFile.isFile()) {
 				String fileName = externalFile.getName().toLowerCase();
-				if (fileName.endsWith(".jar"  //$NON-NLS-1$
-					) || fileName.endsWith(".zip"  //$NON-NLS-1$
-					)) { // external binary archive
+				if (fileName.endsWith(SuffixConstants.SUFFIX_STRING_jar) || fileName.endsWith(SuffixConstants.SUFFIX_STRING_zip)) { 
+					// external binary archive
 					return JavaCore.newLibraryEntry(
 							resolvedPath,
 							getResolvedVariablePath(entry.getSourceAttachmentPath()),
@@ -1784,22 +2244,35 @@
 	 * @return the list of shared working copies for a given buffer factory
 	 * @see IWorkingCopy
 	 * @since 2.0
+	 * @deprecated - should use #getWorkingCopies(WorkingCopyOwner) instead
 	 */
 	public static IWorkingCopy[] getSharedWorkingCopies(IBufferFactory factory){
 		
 		// if factory is null, default factory must be used
 		if (factory == null) factory = BufferManager.getDefaultBufferManager().getDefaultBufferFactory();
-		Map sharedWorkingCopies = JavaModelManager.getJavaModelManager().sharedWorkingCopies;
-		
-		Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(factory);
-		if (perFactoryWorkingCopies == null) return JavaModelManager.NoWorkingCopy;
-		Collection copies = perFactoryWorkingCopies.values();
-		IWorkingCopy[] result = new IWorkingCopy[copies.size()];
-		copies.toArray(result);
-		return result;
+
+		return getWorkingCopies(BufferFactoryWrapper.create(factory));
 	}
 	
 	/**
+	 * Returns the working copies that have the given owner. 
+	 * Only compilation units in working copy mode are returned.
+	 * If the owner is <code>null</code>, primary working copies are returned.
+	 * 
+	 * @param owner the given working copy owner or <null> for primary working copy owner
+	 * @return the list of working copies for a given owner
+	 * @since 3.0
+	 */
+	public static ICompilationUnit[] getWorkingCopies(WorkingCopyOwner owner){
+		
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		if (owner == null) owner = DefaultWorkingCopyOwner.PRIMARY;
+		ICompilationUnit[] result = manager.getWorkingCopies(owner, false/*don't add primary WCs*/);
+		if (result == null) return JavaModelManager.NoWorkingCopy;
+		return result;
+	}
+		
+	/**
 	 * Initializes the default preferences settings for this plug-in.
 	 */
 	protected void initializeDefaultPluginPreferences() {
@@ -1808,95 +2281,18 @@
 		HashSet optionNames = JavaModelManager.OptionNames;
 		
 		// Compiler settings
+		Map compilerOptionsMap = new CompilerOptions().getMap(); // compiler defaults
+		for (Iterator iter = compilerOptionsMap.entrySet().iterator(); iter.hasNext();) {
+			Map.Entry entry = (Map.Entry) iter.next();
+			String optionName = (String) entry.getKey();
+			preferences.setDefault(optionName, (String)entry.getValue());
+			optionNames.add(optionName);
+		}
+		// override some compiler defaults
 		preferences.setDefault(COMPILER_LOCAL_VARIABLE_ATTR, GENERATE);
-		optionNames.add(COMPILER_LOCAL_VARIABLE_ATTR);
-
-		preferences.setDefault(COMPILER_LINE_NUMBER_ATTR, GENERATE); 
-		optionNames.add(COMPILER_LINE_NUMBER_ATTR);
-
-		preferences.setDefault(COMPILER_SOURCE_FILE_ATTR, GENERATE); 
-		optionNames.add(COMPILER_SOURCE_FILE_ATTR);
-
-		preferences.setDefault(COMPILER_CODEGEN_UNUSED_LOCAL, PRESERVE); 
-		optionNames.add(COMPILER_CODEGEN_UNUSED_LOCAL);
-
-		preferences.setDefault(COMPILER_CODEGEN_TARGET_PLATFORM, VERSION_1_1); 
-		optionNames.add(COMPILER_CODEGEN_TARGET_PLATFORM);
-
-		preferences.setDefault(COMPILER_PB_UNREACHABLE_CODE, ERROR); 
-		optionNames.add(COMPILER_PB_UNREACHABLE_CODE);
-
-		preferences.setDefault(COMPILER_PB_INVALID_IMPORT, ERROR); 
-		optionNames.add(COMPILER_PB_INVALID_IMPORT);
-
-		preferences.setDefault(COMPILER_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD, WARNING); 
-		optionNames.add(COMPILER_PB_OVERRIDING_PACKAGE_DEFAULT_METHOD);
-
-		preferences.setDefault(COMPILER_PB_METHOD_WITH_CONSTRUCTOR_NAME, WARNING); 
-		optionNames.add(COMPILER_PB_METHOD_WITH_CONSTRUCTOR_NAME);
-
-		preferences.setDefault(COMPILER_PB_DEPRECATION, WARNING);
-		optionNames.add(COMPILER_PB_DEPRECATION);
-
-		preferences.setDefault(COMPILER_PB_DEPRECATION_IN_DEPRECATED_CODE, DISABLED);
-		optionNames.add(COMPILER_PB_DEPRECATION_IN_DEPRECATED_CODE);
-
-		preferences.setDefault(COMPILER_PB_HIDDEN_CATCH_BLOCK, WARNING); 
-		optionNames.add(COMPILER_PB_HIDDEN_CATCH_BLOCK);
-
-		preferences.setDefault(COMPILER_PB_UNUSED_LOCAL, IGNORE); 
-		optionNames.add(COMPILER_PB_UNUSED_LOCAL);
-
-		preferences.setDefault(COMPILER_PB_UNUSED_PARAMETER, IGNORE); 
-		optionNames.add(COMPILER_PB_UNUSED_PARAMETER);
-
-		preferences.setDefault(COMPILER_PB_UNUSED_PARAMETER_WHEN_IMPLEMENTING_ABSTRACT, DISABLED); 
-		optionNames.add(COMPILER_PB_UNUSED_PARAMETER_WHEN_IMPLEMENTING_ABSTRACT);
-
-		preferences.setDefault(COMPILER_PB_UNUSED_PARAMETER_WHEN_OVERRIDING_CONCRETE, DISABLED); 
-		optionNames.add(COMPILER_PB_UNUSED_PARAMETER_WHEN_OVERRIDING_CONCRETE);
-
-		preferences.setDefault(COMPILER_PB_UNUSED_IMPORT, WARNING); 
-		optionNames.add(COMPILER_PB_UNUSED_IMPORT);
-
-		preferences.setDefault(COMPILER_PB_UNUSED_PRIVATE_MEMBER, IGNORE); 
-		optionNames.add(COMPILER_PB_UNUSED_PRIVATE_MEMBER);
-
-		preferences.setDefault(COMPILER_PB_SYNTHETIC_ACCESS_EMULATION, IGNORE); 
-		optionNames.add(COMPILER_PB_SYNTHETIC_ACCESS_EMULATION);
-
-		preferences.setDefault(COMPILER_PB_NON_NLS_STRING_LITERAL, IGNORE); 
-		optionNames.add(COMPILER_PB_NON_NLS_STRING_LITERAL);
-
-		preferences.setDefault(COMPILER_PB_ASSERT_IDENTIFIER, IGNORE); 
-		optionNames.add(COMPILER_PB_ASSERT_IDENTIFIER);
-
-		preferences.setDefault(COMPILER_PB_STATIC_ACCESS_RECEIVER, WARNING); 
-		optionNames.add(COMPILER_PB_STATIC_ACCESS_RECEIVER);
-
-		preferences.setDefault(COMPILER_PB_NO_EFFECT_ASSIGNMENT, WARNING); 
-		optionNames.add(COMPILER_PB_NO_EFFECT_ASSIGNMENT);
-
-		preferences.setDefault(COMPILER_PB_INCOMPATIBLE_NON_INHERITED_INTERFACE_METHOD, WARNING); 
-		optionNames.add(COMPILER_PB_INCOMPATIBLE_NON_INHERITED_INTERFACE_METHOD);
-
-		preferences.setDefault(COMPILER_PB_CHAR_ARRAY_IN_STRING_CONCATENATION, WARNING); 
-		optionNames.add(COMPILER_PB_CHAR_ARRAY_IN_STRING_CONCATENATION);
-
-		preferences.setDefault(COMPILER_TASK_TAGS, DEFAULT_TASK_TAG); //$NON-NLS-1$
-		optionNames.add(COMPILER_TASK_TAGS);
-
-		preferences.setDefault(COMPILER_TASK_PRIORITIES, DEFAULT_TASK_PRIORITY); //$NON-NLS-1$
-		optionNames.add(COMPILER_TASK_PRIORITIES);
-
-		preferences.setDefault(COMPILER_SOURCE, VERSION_1_3);
-		optionNames.add(COMPILER_SOURCE);
-
-		preferences.setDefault(COMPILER_COMPLIANCE, VERSION_1_3); 
-		optionNames.add(COMPILER_COMPLIANCE);
-
-		preferences.setDefault(COMPILER_PB_MAX_PER_UNIT, "100"); //$NON-NLS-1$
-		optionNames.add(COMPILER_PB_MAX_PER_UNIT);
+		preferences.setDefault(COMPILER_CODEGEN_UNUSED_LOCAL, PRESERVE);
+		preferences.setDefault(COMPILER_TASK_TAGS, DEFAULT_TASK_TAG);
+		preferences.setDefault(COMPILER_TASK_PRIORITIES, DEFAULT_TASK_PRIORITY);
 		
 		// Builder settings
 		preferences.setDefault(CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, ""); //$NON-NLS-1$
@@ -1915,11 +2311,14 @@
 		preferences.setDefault(CORE_JAVA_BUILD_ORDER, IGNORE); 
 		optionNames.add(CORE_JAVA_BUILD_ORDER);
 	
+		preferences.setDefault(CORE_INCOMPLETE_CLASSPATH, ERROR); 
+		optionNames.add(CORE_INCOMPLETE_CLASSPATH);
+		
 		preferences.setDefault(CORE_CIRCULAR_CLASSPATH, ERROR); 
 		optionNames.add(CORE_CIRCULAR_CLASSPATH);
 		
-		preferences.setDefault(CORE_INCOMPLETE_CLASSPATH, ERROR); 
-		optionNames.add(CORE_INCOMPLETE_CLASSPATH);
+		preferences.setDefault(CORE_INCOMPATIBLE_JDK_LEVEL, IGNORE); 
+		optionNames.add(CORE_INCOMPATIBLE_JDK_LEVEL);
 		
 		preferences.setDefault(CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, ENABLED); 
 		optionNames.add(CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS);
@@ -1931,6 +2330,13 @@
 		optionNames.add(CORE_ENCODING);
 		
 		// Formatter settings
+		Map codeFormatterOptionsMap = DefaultCodeFormatterConstants.getDefaultSettings(); // code formatter defaults
+		for (Iterator iter = codeFormatterOptionsMap.entrySet().iterator(); iter.hasNext();) {
+			Map.Entry entry = (Map.Entry) iter.next();
+			String optionName = (String) entry.getKey();
+			preferences.setDefault(optionName, (String)entry.getValue());
+			optionNames.add(optionName);
+		}		
 		preferences.setDefault(FORMATTER_NEWLINE_OPENING_BRACE, DO_NOT_INSERT); 
 		optionNames.add(FORMATTER_NEWLINE_OPENING_BRACE);
 
@@ -2174,7 +2580,8 @@
 	 */
 	public static IClasspathEntry newContainerEntry(IPath containerPath, boolean isExported) {
 			
-		if (containerPath == null || containerPath.segmentCount() < 1) {
+		if (containerPath == null) Assert.isTrue(false, "Container path cannot be null"); //$NON-NLS-1$
+		if (containerPath.segmentCount() < 1) {
 			Assert.isTrue(
 				false,
 				"Illegal classpath container path: \'" + containerPath.makeRelative().toString() + "\', must have at least one segment (containerID+hints)"); //$NON-NLS-1$//$NON-NLS-2$
@@ -2210,10 +2617,10 @@
 	 * The resulting entry is not exported to dependent projects. This method is equivalent to
 	 * <code>newLibraryEntry(-,-,-,false)</code>.
 	 * <p>
-	 * 
 	 * @param path the absolute path of the binary archive
 	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, 
-	 *    or <code>null</code> if none
+	 *    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
+	 *   and will be automatically converted to <code>null</code>.
 	 * @param sourceAttachmentRootPath the location of the root within the source archive or folder
 	 *    or <code>null</code> if this location should be automatically detected.
 	 * @return a new library classpath entry
@@ -2248,7 +2655,8 @@
 	 * 
 	 * @param path the absolute path of the binary archive
 	 * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, 
-	 *    or <code>null</code> if none
+	 *    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
+	 *   and will be automatically converted to <code>null</code>.
 	 * @param sourceAttachmentRootPath the location of the root within the source archive or folder
 	 *    or <code>null</code> if this location should be automatically detected.
 	 * @param isExported indicates whether this entry is contributed to dependent
@@ -2262,8 +2670,15 @@
 		IPath sourceAttachmentRootPath,
 		boolean isExported) {
 			
+		if (path == null) Assert.isTrue(false, "Library path cannot be null"); //$NON-NLS-1$
 		if (!path.isAbsolute()) Assert.isTrue(false, "Path for IClasspathEntry must be absolute"); //$NON-NLS-1$
-
+		if (sourceAttachmentPath != null) {
+			if (sourceAttachmentPath.isEmpty()) {
+				sourceAttachmentPath = null; // treat empty path as none
+			} else if (!sourceAttachmentPath.isAbsolute()) {
+				Assert.isTrue(false, "Source attachment path for IClasspathEntry must be absolute"); //$NON-NLS-1$
+			}
+		}
 		return new ClasspathEntry(
 			IPackageFragmentRoot.K_BINARY,
 			IClasspathEntry.CPE_LIBRARY,
@@ -2426,7 +2841,7 @@
 	 *    represented as relative paths
 	 * @return a new source classpath entry with the given exclusion patterns
 	 * @see #newSourceEntry(org.eclipse.core.runtime.IPath)
-	 * @see IClasspathEntry#getExclusionPatterns
+	 * @see IClasspathEntry#getExclusionPatterns()
 	 * 
 	 * @since 2.1
 	 */
@@ -2491,16 +2906,17 @@
 	 * @param path the absolute workspace-relative path of a source folder
 	 * @param exclusionPatterns the possibly empty list of exclusion patterns
 	 *    represented as relative paths
-	 * @param outputLocation the specific output location for this source entry (<code>null</code> if using project default ouput location)
+	 * @param specificOutputLocation the specific output location for this source entry (<code>null</code> if using project default ouput location)
 	 * @return a new source classpath entry with the given exclusion patterns
 	 * @see #newSourceEntry(org.eclipse.core.runtime.IPath)
-	 * @see IClasspathEntry#getExclusionPatterns
+	 * @see IClasspathEntry#getExclusionPatterns()
 	 * @see IClasspathEntry#getOutputLocation()
 	 * 
 	 * @since 2.1
 	 */
 	public static IClasspathEntry newSourceEntry(IPath path, IPath[] exclusionPatterns, IPath specificOutputLocation) {
 
+		if (path == null) Assert.isTrue(false, "Source path cannot be null"); //$NON-NLS-1$
 		if (!path.isAbsolute()) Assert.isTrue(false, "Path for IClasspathEntry must be absolute"); //$NON-NLS-1$
 		if (exclusionPatterns == null) Assert.isTrue(false, "Exclusion pattern set cannot be null"); //$NON-NLS-1$
 
@@ -2592,7 +3008,7 @@
 	 *    or <code>null</code> if none; if present, the first segment is the
 	 *    name of a classpath variable (not necessarily the same variable
 	 *    as the one that begins <code>variablePath</code>)
-	 * @param sourceAttachmentRootPath the location of the root within the source archive
+	 * @param variableSourceAttachmentRootPath the location of the root within the source archive
 	 *    or <code>null</code> if <code>archivePath</code> is also <code>null</code>
 	 * @param isExported indicates whether this entry is contributed to dependent
 	 * 	  projects in addition to the output location
@@ -2604,8 +3020,9 @@
 		IPath variableSourceAttachmentPath,
 		IPath variableSourceAttachmentRootPath,
 		boolean isExported) {
-			
-		if (variablePath == null || variablePath.segmentCount() < 1) {
+
+		if (variablePath == null) Assert.isTrue(false, "Variable path cannot be null"); //$NON-NLS-1$
+		if (variablePath.segmentCount() < 1) {
 			Assert.isTrue(
 				false,
 				"Illegal classpath variable path: \'" + variablePath.makeRelative().toString() + "\', must have at least one segment"); //$NON-NLS-1$//$NON-NLS-2$
@@ -2633,7 +3050,7 @@
 	 * <p>
 	 *
 	 * @param variableName the name of the classpath variable
-	 * @see #setClasspathVariable
+	 * @see #setClasspathVariable(String, IPath)
 	 *
 	 * @deprecated - use version with extra IProgressMonitor
 	 */
@@ -2653,7 +3070,7 @@
 	 *
 	 * @param variableName the name of the classpath variable
 	 * @param monitor the progress monitor to report progress
-	 * @see #setClasspathVariable
+	 * @see #setClasspathVariable(String, IPath)
 	 */
 	public static void removeClasspathVariable(
 		String variableName,
@@ -2662,6 +3079,7 @@
 		try {
 			updateVariableValues(new String[]{ variableName}, new IPath[]{ null }, monitor);
 		} catch (JavaModelException e) {
+			// cannot happen: ignore
 		}
 	}
 
@@ -2672,12 +3090,12 @@
 	 * @param listener the listener
 	 */
 	public static void removeElementChangedListener(IElementChangedListener listener) {
-		JavaModelManager.getJavaModelManager().removeElementChangedListener(listener);
+		JavaModelManager.getJavaModelManager().deltaState.removeElementChangedListener(listener);
 	}
 	/**
 	 * Runs the given action as an atomic Java model operation.
 	 * <p>
-	 * After running a method that modifies Java elements,
+	 * After running a method that modifies java elements,
 	 * registered listeners receive after-the-fact notification of
 	 * what just transpired, in the form of a element changed event.
 	 * This method allows clients to call a number of
@@ -2748,7 +3166,7 @@
 	 * @param affectedProjects - the set of projects for which this container is being bound
 	 * @param respectiveContainers - the set of respective containers for the affected projects
 	 * @param monitor a monitor to report progress
-	 * 
+	 * @throws JavaModelException
 	 * @see ClasspathContainerInitializer
 	 * @see #getClasspathContainer(IPath, IJavaProject)
 	 * @see IClasspathContainer
@@ -2762,13 +3180,13 @@
 	
 		if (JavaModelManager.CP_RESOLVE_VERBOSE){
 			System.out.println("CPContainer SET  - setting container: ["+containerPath+"] for projects: {" //$NON-NLS-1$ //$NON-NLS-2$
-				+ (Util.toString(affectedProjects, 
-						new Util.Displayable(){ 
+				+ (org.eclipse.jdt.internal.compiler.util.Util.toString(affectedProjects, 
+						new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){ 
 							public String displayString(Object o) { return ((IJavaProject) o).getElementName(); }
 						}))
 				+ "} with values: " //$NON-NLS-1$
-				+ (Util.toString(respectiveContainers, 
-						new Util.Displayable(){ 
+				+ (org.eclipse.jdt.internal.compiler.util.Util.toString(respectiveContainers, 
+						new org.eclipse.jdt.internal.compiler.util.Util.Displayable(){ 
 							public String displayString(Object o) { return ((IClasspathContainer) o).getDescription(); }
 						}))
 					);
@@ -2820,7 +3238,7 @@
 					oldContainer = null;
 				}
 			}
-			if (oldContainer != null && oldContainer.equals(respectiveContainers[i])){// TODO: could improve to only compare entries
+			if (oldContainer != null && oldContainer.equals(respectiveContainers[i])){
 				modifiedProjects[i] = null; // filter out this project - container did not change
 				continue;
 			}
@@ -2833,11 +3251,12 @@
 		
 		// trigger model refresh
 		try {
+			final boolean canChangeResources = !ResourcesPlugin.getWorkspace().isTreeLocked();
 			JavaCore.run(new IWorkspaceRunnable() {
-				public void run(IProgressMonitor monitor) throws CoreException {
+				public void run(IProgressMonitor progressMonitor) throws CoreException {
 					for(int i = 0; i < projectLength; i++){
 		
-						if (monitor != null && monitor.isCanceled()) return;
+						if (progressMonitor != null && progressMonitor.isCanceled()) return;
 		
 						JavaProject affectedProject = (JavaProject)modifiedProjects[i];
 						if (affectedProject == null) continue; // was filtered out
@@ -2850,10 +3269,10 @@
 						affectedProject.setRawClasspath(
 								affectedProject.getRawClasspath(),
 								SetClasspathOperation.ReuseOutputLocation,
-								monitor,
-								!ResourcesPlugin.getWorkspace().isTreeLocked(), // can save resources
+								progressMonitor,
+								canChangeResources,
 								oldResolvedPaths[i],
-								false, // updating - no validation
+								false, // updating - no need for early validation
 								false); // updating - no need to save
 					}
 				}
@@ -2891,7 +3310,8 @@
 	 *
 	 * @param variableName the name of the classpath variable
 	 * @param path the path
-	 * @see #getClasspathVariable
+	 * @throws JavaModelException
+	 * @see #getClasspathVariable(String)
 	 *
 	 * @deprecated - use API with IProgressMonitor
 	 */
@@ -2915,7 +3335,8 @@
 	 * @param variableName the name of the classpath variable
 	 * @param path the path
 	 * @param monitor a monitor to report progress
-	 * @see #getClasspathVariable
+	 * @throws JavaModelException
+	 * @see #getClasspathVariable(String)
 	 */
 	public static void setClasspathVariable(
 		String variableName,
@@ -2942,7 +3363,8 @@
 	 * @param paths an array of path updates for the modified classpath variables (null
 	 *       meaning that the corresponding value will be removed
 	 * @param monitor a monitor to report progress
-	 * @see #getClasspathVariable
+	 * @throws JavaModelException
+	 * @see #getClasspathVariable(String)
 	 * @since 2.0
 	 */
 	public static void setClasspathVariables(
@@ -2952,21 +3374,9 @@
 		throws JavaModelException {
 
 		if (variableNames.length != paths.length)	Assert.isTrue(false, "Variable names and paths collections should have the same size"); //$NON-NLS-1$
-		//TODO: should check that null cannot be used as variable paths
 		updateVariableValues(variableNames, paths, monitor);
 	}
 
-	/* (non-Javadoc)
-	 * Method declared on IExecutableExtension.
-	 * Record any necessary initialization data from the plugin.
-	 */
-	public void setInitializationData(
-		IConfigurationElement cfig,
-		String propertyName,
-		Object data)
-		throws CoreException {
-	}
-
 	/**
 	 * Sets the current table of options. All and only the options explicitly included in the given table 
 	 * are remembered; all previous option settings are forgotten, including ones not explicitly
@@ -2977,8 +3387,8 @@
 	 * 
 	 * @param newOptions the new options (key type: <code>String</code>; value type: <code>String</code>),
 	 *   or <code>null</code> to reset all options to their default values
-	 * @see JavaCore#getDefaultOptions
-	 */
+	 * @see JavaCore#getDefaultOptions()
+	 *///TODO should use a Map for 3.0
 	public static void setOptions(Hashtable newOptions) {
 		
 		// see #initializeDefaultPluginPreferences() for changing default settings
@@ -2995,7 +3405,26 @@
 			String value = (String)newOptions.get(key);
 			preferences.setValue(key, value);
 		}
-		
+
+		// Backward compatibility
+		String[] propertyNames = preferences.propertyNames();
+		for (int i = 0; i < propertyNames.length; i++){
+			String propertyName = propertyNames[i];
+			// bug 45112
+			if (CompilerOptions.OPTION_ReportInvalidAnnotation.equals(propertyName)) {
+				preferences.setToDefault(OLD_COMPILER_PB_INVALID_ANNOTATION);
+			}
+			else if (CompilerOptions.OPTION_ReportMissingAnnotation.equals(propertyName)) {
+				preferences.setToDefault(OLD_COMPILER_PB_MISSING_ANNOTATION);
+			}
+			// end bug 45112
+			// bug 46854
+			else if (CompilerOptions.OPTION_ReportMissingJavadoc.equals(propertyName)) {
+				preferences.setToDefault(OLD_COMPILER_PB_MISSING_JAVADOC);
+			}
+			// end bug 46854
+		}
+
 		// persist options
 		getPlugin().savePluginPreferences();
 	}
@@ -3011,10 +3440,10 @@
 
 		savePluginPreferences();
 		IWorkspace workspace = ResourcesPlugin.getWorkspace();
-		workspace.removeResourceChangeListener(JavaModelManager.getJavaModelManager().deltaProcessor);
+		workspace.removeResourceChangeListener(JavaModelManager.getJavaModelManager().deltaState);
 		workspace.removeSaveParticipant(this);
 
-		((JavaModelManager) JavaModelManager.getJavaModelManager()).shutdown();
+		JavaModelManager.getJavaModelManager().shutdown();
 	}
 
 	/**
@@ -3032,9 +3461,10 @@
 	 * Registers the JavaModelManager as a resource changed listener and save participant.
 	 * Starts the background indexing, and restore saved classpath variable values.
 	 * <p>
+	 * @throws CoreException
 	 * @see org.eclipse.core.runtime.Plugin#startup()
 	 */
-	public void startup() {
+	public void startup() throws CoreException {
 		
 		JavaModelManager manager = JavaModelManager.getJavaModelManager();
 		try {
@@ -3049,7 +3479,7 @@
 
 			IWorkspace workspace = ResourcesPlugin.getWorkspace();
 			workspace.addResourceChangeListener(
-				manager.deltaProcessor,
+				manager.deltaState,
 				IResourceChangeEvent.PRE_AUTO_BUILD
 					| IResourceChangeEvent.POST_AUTO_BUILD
 					| IResourceChangeEvent.POST_CHANGE
@@ -3058,8 +3488,6 @@
 
 			startIndexing();
 			workspace.addSaveParticipant(this, manager);
-			
-		} catch (CoreException e) {
 		} catch (RuntimeException e) {
 			manager.shutdown();
 			throw e;
@@ -3067,7 +3495,7 @@
 	}
 
 
-	/**
+	/*
 	 * Internal updating of a variable values (null path meaning removal), allowing to change multiple variable values at once.
 	 */
 	private static void updateVariableValues(
@@ -3078,14 +3506,14 @@
 		if (monitor != null && monitor.isCanceled()) return;
 		
 		if (JavaModelManager.CP_RESOLVE_VERBOSE){
-			System.out.println("CPVariable SET  - setting variables: {" + Util.toString(variableNames)  //$NON-NLS-1$
-				+ "} with values: " + Util.toString(variablePaths)); //$NON-NLS-1$
+			System.out.println("CPVariable SET  - setting variables: {" + org.eclipse.jdt.internal.compiler.util.Util.toString(variableNames)  //$NON-NLS-1$
+				+ "} with values: " + org.eclipse.jdt.internal.compiler.util.Util.toString(variablePaths)); //$NON-NLS-1$
 		}
 
 		int varLength = variableNames.length;
 		
 		// gather classpath information for updating
-		final HashMap affectedProjects = new HashMap(5);
+		final HashMap affectedProjectClasspaths = new HashMap(5);
 		JavaModelManager manager = JavaModelManager.getJavaModelManager();
 		IJavaModel model = manager.getJavaModel();
 	
@@ -3093,7 +3521,7 @@
 		int discardCount = 0;
 		for (int i = 0; i < varLength; i++){
 			String variableName = variableNames[i];
-			IPath oldPath = (IPath)JavaModelManager.variableGet(variableName); // if reentering will provide previous session value 
+			IPath oldPath = JavaModelManager.variableGet(variableName); // if reentering will provide previous session value 
 			if (oldPath == JavaModelManager.VariableInitializationInProgress){
 				IPath previousPath = (IPath)JavaModelManager.PreviousSessionVariables.get(variableName);
 				if (previousPath != null){
@@ -3144,14 +3572,14 @@
 						if (entry.getEntryKind() ==  IClasspathEntry.CPE_VARIABLE){
 	
 							if (variableName.equals(entry.getPath().segment(0))){
-								affectedProjects.put(project, project.getResolvedClasspath(true));
+								affectedProjectClasspaths.put(project, project.getResolvedClasspath(true));
 								continue nextProject;
 							}
 							IPath sourcePath, sourceRootPath;
 							if (((sourcePath = entry.getSourceAttachmentPath()) != null	&& variableName.equals(sourcePath.segment(0)))
 								|| ((sourceRootPath = entry.getSourceAttachmentRootPath()) != null	&& variableName.equals(sourceRootPath.segment(0)))) {
 	
-								affectedProjects.put(project, project.getResolvedClasspath(true));
+								affectedProjectClasspaths.put(project, project.getResolvedClasspath(true));
 								continue nextProject;
 							}
 						}												
@@ -3166,31 +3594,33 @@
 		final String[] dbgVariableNames = variableNames;
 				
 		// update affected project classpaths
-		if (!affectedProjects.isEmpty()) {
+		if (!affectedProjectClasspaths.isEmpty()) {
 			try {
+				final boolean canChangeResources = !ResourcesPlugin.getWorkspace().isTreeLocked();
 				JavaCore.run(
 					new IWorkspaceRunnable() {
-						public void run(IProgressMonitor monitor) throws CoreException {
+						public void run(IProgressMonitor progressMonitor) throws CoreException {
 							// propagate classpath change
-							Iterator projectsToUpdate = affectedProjects.keySet().iterator();
+							Iterator projectsToUpdate = affectedProjectClasspaths.keySet().iterator();
 							while (projectsToUpdate.hasNext()) {
 			
-								if (monitor != null && monitor.isCanceled()) return;
+								if (progressMonitor != null && progressMonitor.isCanceled()) return;
 			
-								JavaProject project = (JavaProject) projectsToUpdate.next();
+								JavaProject affectedProject = (JavaProject) projectsToUpdate.next();
 
 								if (JavaModelManager.CP_RESOLVE_VERBOSE){
-									System.out.println("CPVariable SET  - updating affected project: ["+project.getElementName()+"] due to setting variables: "+ Util.toString(dbgVariableNames)); //$NON-NLS-1$ //$NON-NLS-2$
+									System.out.println("CPVariable SET  - updating affected project: ["+affectedProject.getElementName() //$NON-NLS-1$
+										+"] due to setting variables: "+ org.eclipse.jdt.internal.compiler.util.Util.toString(dbgVariableNames)); //$NON-NLS-1$
 								}
-								
-								project
+
+								affectedProject
 									.setRawClasspath(
-										project.getRawClasspath(),
+										affectedProject.getRawClasspath(),
 										SetClasspathOperation.ReuseOutputLocation,
 										null, // don't call beginTask on the monitor (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=3717)
-										!ResourcesPlugin.getWorkspace().isTreeLocked(), // can change resources
-										(IClasspathEntry[]) affectedProjects.get(project),
-										false, // updating - no validation
+										canChangeResources, 
+										(IClasspathEntry[]) affectedProjectClasspaths.get(affectedProject),
+										false, // updating - no need for early validation
 										false); // updating - no need to save
 							}
 						}
@@ -3198,7 +3628,8 @@
 					monitor);
 			} catch (CoreException e) {
 				if (JavaModelManager.CP_RESOLVE_VERBOSE){
-					System.out.println("CPVariable SET  - FAILED DUE TO EXCEPTION: "+Util.toString(dbgVariableNames)); //$NON-NLS-1$
+					System.out.println("CPVariable SET  - FAILED DUE TO EXCEPTION: " //$NON-NLS-1$
+						+org.eclipse.jdt.internal.compiler.util.Util.toString(dbgVariableNames)); 
 					e.printStackTrace();
 				}
 				if (e instanceof JavaModelException) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
index 7163262..42a32bb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaModelException.java
@@ -10,6 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.core;
 
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IStatus;
 
@@ -35,7 +38,7 @@
  * The exception contains a Java-specific status object with severity
  * <code>IStatus.ERROR</code> and the given status code.
  *
- * @param exception the <code>Throwable</code>
+ * @param e the <code>Throwable</code>
  * @param code one of the Java-specific status codes declared in
  *   <code>IJavaModelStatusConstants</code>
  * @see IJavaModelStatusConstants
@@ -100,14 +103,34 @@
  *
  * @return <code>true</code> if this exception indicates that a Java model
  *   element does not exist
- * @see IJavaModelStatus#isDoesNotExist
+ * @see IJavaModelStatus#isDoesNotExist()
  * @see IJavaModelStatusConstants#ELEMENT_DOES_NOT_EXIST
  */
 public boolean isDoesNotExist() {
 	IJavaModelStatus javaModelStatus = getJavaModelStatus();
 	return javaModelStatus != null && javaModelStatus.isDoesNotExist();
 }
-/**
+public void printStackTrace(PrintStream output) {
+	synchronized(output) {
+		super.printStackTrace(output);
+		Throwable throwable = getException();
+		if (throwable != null) {
+			output.print("Caused by: "); //$NON-NLS-1$
+			throwable.printStackTrace(output);
+		}
+	}
+}
+public void printStackTrace(PrintWriter output) {
+	synchronized(output) {
+		super.printStackTrace(output);
+		Throwable throwable = getException();
+		if (throwable != null) {
+			output.print("Caused by: "); //$NON-NLS-1$
+			throwable.printStackTrace(output);
+		}
+	}
+}
+/*
  * Returns a printable representation of this exception suitable for debugging
  * purposes only.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java
index 0461d73..a09fac3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/NamingConventions.java
@@ -19,7 +19,7 @@
 /**
  * Provides methods for computing Java-specific names.
  * <p>
- * The bevavior of the methods is dependent of several JavaCore options.
+ * The behavior of the methods is dependent of several JavaCore options.
  * <p>
  * The possible options are :
  * <ul>
@@ -42,8 +42,8 @@
  * instantiated or subclassed by clients.
  * </p>
  * 
- * @see JavaCore#setOptions
- * @see JavaCore#getDefaultOptions
+ * @see JavaCore#setOptions(java.util.Hashtable)
+ * @see JavaCore#getDefaultOptions()
  * @since 2.1
  */
 public final class NamingConventions {
@@ -81,158 +81,157 @@
 		private int otherResultsCount = 0;
 		public void acceptNameWithPrefixAndSuffix(char[] name, boolean isFirstPrefix, boolean isFirstSuffix) {
 			if(isFirstPrefix && isFirstSuffix) {
-				int length = firstPrefixAndFirstSuffixResults.length;
-				if(length == firstPrefixAndFirstSuffixResultsCount) {
+				int length = this.firstPrefixAndFirstSuffixResults.length;
+				if(length == this.firstPrefixAndFirstSuffixResultsCount) {
 					System.arraycopy(
-						firstPrefixAndFirstSuffixResults,
+						this.firstPrefixAndFirstSuffixResults,
 						0,
-						firstPrefixAndFirstSuffixResults = new char[length * 2][],
+						this.firstPrefixAndFirstSuffixResults = new char[length * 2][],
 						0,
 						length);
 				}
-				firstPrefixAndFirstSuffixResults[firstPrefixAndFirstSuffixResultsCount++] = name;			
+				this.firstPrefixAndFirstSuffixResults[this.firstPrefixAndFirstSuffixResultsCount++] = name;			
 			} else if (isFirstPrefix) {
-				int length = firstPrefixAndSuffixResults.length;
-				if(length == firstPrefixAndSuffixResultsCount) {
+				int length = this.firstPrefixAndSuffixResults.length;
+				if(length == this.firstPrefixAndSuffixResultsCount) {
 					System.arraycopy(
-						firstPrefixAndSuffixResults,
+						this.firstPrefixAndSuffixResults,
 						0,
-						firstPrefixAndSuffixResults = new char[length * 2][],
+						this.firstPrefixAndSuffixResults = new char[length * 2][],
 						0,
 						length);
 				}
-				firstPrefixAndSuffixResults[firstPrefixAndSuffixResultsCount++] = name;
+				this.firstPrefixAndSuffixResults[this.firstPrefixAndSuffixResultsCount++] = name;
 			} else if(isFirstSuffix) {
-				int length = prefixAndFirstSuffixResults.length;
-				if(length == prefixAndFirstSuffixResultsCount) {
+				int length = this.prefixAndFirstSuffixResults.length;
+				if(length == this.prefixAndFirstSuffixResultsCount) {
 					System.arraycopy(
-						prefixAndFirstSuffixResults,
+						this.prefixAndFirstSuffixResults,
 						0,
-						prefixAndFirstSuffixResults = new char[length * 2][],
+						this.prefixAndFirstSuffixResults = new char[length * 2][],
 						0,
 						length);
 				}
-				prefixAndFirstSuffixResults[prefixAndFirstSuffixResultsCount++] = name;
+				this.prefixAndFirstSuffixResults[this.prefixAndFirstSuffixResultsCount++] = name;
 			} else {
-				int length = prefixAndSuffixResults.length;
-				if(length == prefixAndSuffixResultsCount) {
+				int length = this.prefixAndSuffixResults.length;
+				if(length == this.prefixAndSuffixResultsCount) {
 					System.arraycopy(
-						prefixAndSuffixResults,
+						this.prefixAndSuffixResults,
 						0,
-						prefixAndSuffixResults = new char[length * 2][],
+						this.prefixAndSuffixResults = new char[length * 2][],
 						0,
 						length);
 				}
-				prefixAndSuffixResults[prefixAndSuffixResultsCount++] = name;
+				this.prefixAndSuffixResults[this.prefixAndSuffixResultsCount++] = name;
 			}
 		}
 
 		public void acceptNameWithPrefix(char[] name, boolean isFirstPrefix) {
 			if(isFirstPrefix) {
-				int length = firstPrefixResults.length;
-				if(length == firstPrefixResultsCount) {
+				int length = this.firstPrefixResults.length;
+				if(length == this.firstPrefixResultsCount) {
 					System.arraycopy(
-						firstPrefixResults,
+						this.firstPrefixResults,
 						0,
-						firstPrefixResults = new char[length * 2][],
+						this.firstPrefixResults = new char[length * 2][],
 						0,
 						length);
 				}
-				firstPrefixResults[firstPrefixResultsCount++] = name;
+				this.firstPrefixResults[this.firstPrefixResultsCount++] = name;
 			} else{
-				int length = prefixResults.length;
-				if(length == prefixResultsCount) {
+				int length = this.prefixResults.length;
+				if(length == this.prefixResultsCount) {
 					System.arraycopy(
-						prefixResults,
+						this.prefixResults,
 						0,
-						prefixResults = new char[length * 2][],
+						this.prefixResults = new char[length * 2][],
 						0,
 						length);
 				}
-				prefixResults[prefixResultsCount++] = name;
+				this.prefixResults[this.prefixResultsCount++] = name;
 			}
 		}
 
 		public void acceptNameWithSuffix(char[] name, boolean isFirstSuffix) {
 			if(isFirstSuffix) {
-				int length = firstSuffixResults.length;
-				if(length == firstSuffixResultsCount) {
+				int length = this.firstSuffixResults.length;
+				if(length == this.firstSuffixResultsCount) {
 					System.arraycopy(
-						firstSuffixResults,
+						this.firstSuffixResults,
 						0,
-						firstSuffixResults = new char[length * 2][],
+						this.firstSuffixResults = new char[length * 2][],
 						0,
 						length);
 				}
-				firstSuffixResults[firstSuffixResultsCount++] = name;
+				this.firstSuffixResults[this.firstSuffixResultsCount++] = name;
 			} else {
-				int length = suffixResults.length;
-				if(length == suffixResultsCount) {
+				int length = this.suffixResults.length;
+				if(length == this.suffixResultsCount) {
 					System.arraycopy(
-						suffixResults,
+						this.suffixResults,
 						0,
-						suffixResults = new char[length * 2][],
+						this.suffixResults = new char[length * 2][],
 						0,
 						length);
 				}
-				suffixResults[suffixResultsCount++] = name;
+				this.suffixResults[this.suffixResultsCount++] = name;
 			}
 		}
 
 		public void acceptNameWithoutPrefixAndSuffix(char[] name) {
-			int length = otherResults.length;
-			if(length == otherResultsCount) {
+			int length = this.otherResults.length;
+			if(length == this.otherResultsCount) {
 				System.arraycopy(
-					otherResults,
+					this.otherResults,
 					0,
-					otherResults = new char[length * 2][],
+					this.otherResults = new char[length * 2][],
 					0,
 					length);
 			}
-			otherResults[otherResultsCount++] = name;
+			this.otherResults[this.otherResultsCount++] = name;
 		}
 		public char[][] getResults(){
 			int count = 
-				firstPrefixAndFirstSuffixResultsCount
-				+ firstPrefixAndSuffixResultsCount
-				+ prefixAndFirstSuffixResultsCount
-				+ prefixAndSuffixResultsCount
-				+ firstPrefixResultsCount
-				+ prefixResultsCount
-				+ firstSuffixResultsCount
-				+ suffixResultsCount
-				+ otherResultsCount;
+				this.firstPrefixAndFirstSuffixResultsCount
+				+ this.firstPrefixAndSuffixResultsCount
+				+ this.prefixAndFirstSuffixResultsCount
+				+ this.prefixAndSuffixResultsCount
+				+ this.firstPrefixResultsCount
+				+ this.prefixResultsCount
+				+ this.firstSuffixResultsCount
+				+ this.suffixResultsCount
+				+ this.otherResultsCount;
 				
 			char[][] results = new char[count][];
 			
 			int index = 0;
-			System.arraycopy(firstPrefixAndFirstSuffixResults, 0, results, index, firstPrefixAndFirstSuffixResultsCount);
-			index += firstPrefixAndFirstSuffixResultsCount;
-			System.arraycopy(firstPrefixAndSuffixResults, 0, results, index, firstPrefixAndSuffixResultsCount);
-			index += firstPrefixAndSuffixResultsCount;
-			System.arraycopy(prefixAndFirstSuffixResults, 0, results, index, prefixAndFirstSuffixResultsCount);
-			index += prefixAndFirstSuffixResultsCount;		
-			System.arraycopy(prefixAndSuffixResults, 0, results, index, prefixAndSuffixResultsCount);
-			index += prefixAndSuffixResultsCount;
-			System.arraycopy(firstPrefixResults, 0, results, index, firstPrefixResultsCount);
-			index += firstPrefixResultsCount;
-			System.arraycopy(prefixResults, 0, results, index, prefixResultsCount);
-			index += prefixResultsCount;
-			System.arraycopy(firstSuffixResults, 0, results, index, firstSuffixResultsCount);
-			index += firstSuffixResultsCount;
-			System.arraycopy(suffixResults, 0, results, index, suffixResultsCount);
-			index += suffixResultsCount;
-			System.arraycopy(otherResults, 0, results, index, otherResultsCount);
+			System.arraycopy(this.firstPrefixAndFirstSuffixResults, 0, results, index, this.firstPrefixAndFirstSuffixResultsCount);
+			index += this.firstPrefixAndFirstSuffixResultsCount;
+			System.arraycopy(this.firstPrefixAndSuffixResults, 0, results, index, this.firstPrefixAndSuffixResultsCount);
+			index += this.firstPrefixAndSuffixResultsCount;
+			System.arraycopy(this.prefixAndFirstSuffixResults, 0, results, index, this.prefixAndFirstSuffixResultsCount);
+			index += this.prefixAndFirstSuffixResultsCount;		
+			System.arraycopy(this.prefixAndSuffixResults, 0, results, index, this.prefixAndSuffixResultsCount);
+			index += this.prefixAndSuffixResultsCount;
+			System.arraycopy(this.firstPrefixResults, 0, results, index, this.firstPrefixResultsCount);
+			index += this.firstPrefixResultsCount;
+			System.arraycopy(this.prefixResults, 0, results, index, this.prefixResultsCount);
+			index += this.prefixResultsCount;
+			System.arraycopy(this.firstSuffixResults, 0, results, index, this.firstSuffixResultsCount);
+			index += this.firstSuffixResultsCount;
+			System.arraycopy(this.suffixResults, 0, results, index, this.suffixResultsCount);
+			index += this.suffixResultsCount;
+			System.arraycopy(this.otherResults, 0, results, index, this.otherResultsCount);
 			
 			return results;
 		}
 	}
 
 	
-	/**
-	 * Not instantiable.
-	 */
-	private NamingConventions() {}
+	private NamingConventions() {
+		// Not instantiable
+	}
 
 	private static char[] removePrefixAndSuffix(char[] name, char[][] prefixes, char[][] suffixes) {
 		// remove longer prefix
@@ -294,8 +293,8 @@
 	 * @param javaProject project which contains the argument.
 	 * @param argumentName argument's name.
 	 * @return char[] the name without prefix and suffix.
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static char[] removePrefixAndSuffixForArgumentName(IJavaProject javaProject, char[] argumentName) {
 		AssistOptions assistOptions = new AssistOptions(javaProject.getOptions(true));
@@ -325,8 +324,8 @@
 	 * @param javaProject project which contains the argument.
 	 * @param argumentName argument's name.
 	 * @return char[] the name without prefix and suffix.
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static String removePrefixAndSuffixForArgumentName(IJavaProject javaProject, String argumentName) {
 		return String.valueOf(removePrefixAndSuffixForArgumentName(javaProject, argumentName.toCharArray()));
@@ -356,8 +355,8 @@
 	 * <code>Flags</code>.
 	 * @return char[] the name without prefix and suffix.
 	 * @see Flags
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static char[] removePrefixAndSuffixForFieldName(IJavaProject javaProject, char[] fieldName, int modifiers) {
 		boolean isStatic = Flags.isStatic(modifiers);
@@ -392,8 +391,8 @@
 	 * <code>Flags</code>.
 	 * @return char[] the name without prefix and suffix.
 	 * @see Flags
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static String removePrefixAndSuffixForFieldName(IJavaProject javaProject, String fieldName, int modifiers) {
 		return String.valueOf(removePrefixAndSuffixForFieldName(javaProject, fieldName.toCharArray(), modifiers));
@@ -418,8 +417,8 @@
 	 * @param javaProject project which contains the variable.
 	 * @param localName variable's name.
 	 * @return char[] the name without prefix and suffix.
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static char[] removePrefixAndSuffixForLocalVariableName(IJavaProject javaProject, char[] localName) {
 		AssistOptions assistOptions = new AssistOptions(javaProject.getOptions(true));
@@ -449,8 +448,8 @@
 	 * @param javaProject project which contains the variable.
 	 * @param localName variable's name.
 	 * @return char[] the name without prefix and suffix.
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static String removePrefixAndSuffixForLocalVariableName(IJavaProject javaProject, String localName) {
 		return String.valueOf(removePrefixAndSuffixForLocalVariableName(javaProject, localName.toCharArray()));
@@ -481,8 +480,8 @@
 	 * @param excludedNames a list of names which cannot be suggested (already used names).
 	 *         Can be <code>null</code> if there is no excluded names.
 	 * @return char[][] an array of names.
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static char[][] suggestArgumentNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[][] excludedNames) {
 		NamingRequestor requestor = new NamingRequestor();
@@ -522,8 +521,8 @@
 	 * @param excludedNames a list of names which cannot be suggested (already used names).
 	 *         Can be <code>null</code> if there is no excluded names.
 	 * @return char[][] an array of names.
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static String[] suggestArgumentNames(IJavaProject javaProject, String packageName, String qualifiedTypeName, int dim, String[] excludedNames) {
 		return convertCharsToString(
@@ -563,8 +562,8 @@
 	 *         Can be <code>null</code> if there is no excluded names.
 	 * @return char[][] an array of names.
 	 * @see Flags
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static char[][] suggestFieldNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, int modifiers, char[][] excludedNames) {
 		NamingRequestor requestor = new NamingRequestor();
@@ -609,8 +608,8 @@
 	 *         Can be <code>null</code> if there is no excluded names.
 	 * @return char[][] an array of names.
 	 * @see Flags
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static String[] suggestFieldNames(IJavaProject javaProject, String packageName, String qualifiedTypeName, int dim, int modifiers, String[] excludedNames) {
 		return convertCharsToString(
@@ -648,8 +647,8 @@
 	 * @param excludedNames a list of names which cannot be suggested (already used names).
 	 *         Can be <code>null</code> if there is no excluded names.
 	 * @return char[][] an array of names.
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static char[][] suggestLocalVariableNames(IJavaProject javaProject, char[] packageName, char[] qualifiedTypeName, int dim, char[][] excludedNames) {
 		NamingRequestor requestor = new NamingRequestor();
@@ -689,8 +688,8 @@
 	 * @param excludedNames a list of names which cannot be suggested (already used names).
 	 *         Can be <code>null</code> if there is no excluded names.
 	 * @return char[][] an array of names.
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static String[] suggestLocalVariableNames(IJavaProject javaProject, String packageName, String qualifiedTypeName, int dim, String[] excludedNames) {
 		return convertCharsToString(
@@ -730,8 +729,8 @@
 	 *         Can be <code>null</code> if there is no excluded names.
 	 * @return char[] a name.
 	 * @see Flags
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static char[] suggestGetterName(IJavaProject project, char[] fieldName, int modifiers, boolean isBoolean, char[][] excludedNames) {
 		if (isBoolean) {
@@ -782,8 +781,8 @@
 	 *         Can be <code>null</code> if there is no excluded names.
 	 * @return char[] a name.
 	 * @see Flags
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static String suggestGetterName(IJavaProject project, String fieldName, int modifiers, boolean isBoolean, String[] excludedNames) {
 		return String.valueOf(
@@ -800,7 +799,7 @@
 	 * and possible prefixes or suffixes are removed.
 	 * <p>
 	 * If the field name is <code>preFieldNamesuf</code> and the prefix for field is <code>pre</code> and
-	 * the suffix for field is <code>suf</code> then the prosposed name is <code>setFieldName</code>.
+	 * the suffix for field is <code>suf</code> then the proposed name is <code>setFieldName</code>.
 	 * If there is no prefix and suffix the proposal is <code>setPreFieldNamesuf</code>.
 	 * </p>
 	 * <p>
@@ -822,8 +821,8 @@
 	 *         Can be <code>null</code> if there is no excluded names.
 	 * @return char[] a name.
 	 * @see Flags
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static char[] suggestSetterName(IJavaProject project, char[] fieldName, int modifiers, boolean isBoolean, char[][] excludedNames) {
 
@@ -856,7 +855,7 @@
 	 * and possible prefixes or suffixes are removed.
 	 * <p>
 	 * If the field name is <code>preFieldNamesuf</code> and the prefix for field is <code>pre</code> and
-	 * the suffix for field is <code>suf</code> then the prosposed name is <code>setFieldName</code>.
+	 * the suffix for field is <code>suf</code> then the proposed name is <code>setFieldName</code>.
 	 * If there is no prefix and suffix the proposal is <code>setPreFieldNamesuf</code>.
 	 * </p>
 	 * <p>
@@ -878,8 +877,8 @@
 	 *         Can be <code>null</code> if there is no excluded names.
 	 * @return char[] a name.
 	 * @see Flags
-	 * @see JavaCore#setOptions
-	 * @see JavaCore#getDefaultOptions
+	 * @see JavaCore#setOptions(java.util.Hashtable)
+	 * @see JavaCore#getDefaultOptions()
 	 */
 	public static String suggestSetterName(IJavaProject project, String fieldName, int modifiers, boolean isBoolean, String[] excludedNames) {
 		return String.valueOf(
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java
index 7dd5fe8..8cede51 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/Signature.java
@@ -36,9 +36,9 @@
  * <ul>
  *   <li><code>"[[I"</code> denotes <code>int[][]</code></li>
  *   <li><code>"Ljava.lang.String;"</code> denotes <code>java.lang.String</code> in compiled code</li>
- *   <li><code>"QString"</code> denotes <code>String</code> in source code</li>
- *   <li><code>"Qjava.lang.String"</code> denotes <code>java.lang.String</code> in source code</li>
- *   <li><code>"[QString"</code> denotes <code>String[]</code> in source code</li>
+ *   <li><code>"QString;"</code> denotes <code>String</code> in source code</li>
+ *   <li><code>"Qjava.lang.String;"</code> denotes <code>java.lang.String</code> in source code</li>
+ *   <li><code>"[QString;"</code> denotes <code>String[]</code> in source code</li>
  * </ul>
  * </p>
  * <p>
@@ -236,10 +236,17 @@
 	
 	private static final String EMPTY = new String(CharOperation.NO_CHAR);
 	
-/**
- * Not instantiable.
- */
-private Signature() {}
+private Signature() {
+	// Not instantiable
+}
+
+private static boolean checkPrimitiveType(char[] primitiveTypeName, char[] typeName) {
+	return CharOperation.fragmentEquals(primitiveTypeName, typeName, 0, true) &&
+		(typeName.length == primitiveTypeName.length
+		 || Character.isWhitespace(typeName[primitiveTypeName.length])
+		 || typeName[primitiveTypeName.length] == C_ARRAY
+		 || typeName[primitiveTypeName.length] == C_DOT);
+}
 
 private static long copyType(char[] signature, int sigPos, char[] dest, int index, boolean fullyQualifyTypeNames) {
 	int arrayCount = 0;
@@ -442,53 +449,53 @@
 	switch (typeName[0]) {
 		// primitive type?
 		case 'b' :
-			if (CharOperation.fragmentEquals(BOOLEAN, typeName, 0, true)) {
+			if (checkPrimitiveType(BOOLEAN, typeName)) {
 				sig = new char[arrayCount+1];
 				sig[arrayCount] = C_BOOLEAN;
 				break;
-			} else if (CharOperation.fragmentEquals(BYTE, typeName, 0, true)) {
+			} else if (checkPrimitiveType(BYTE, typeName)) {
 				sig = new char[arrayCount+1];
 				sig[arrayCount] = C_BYTE;
 				break;
 			}
 		case 'c':
-			if (CharOperation.fragmentEquals(CHAR, typeName, 0, true)) {
+			if (checkPrimitiveType(CHAR, typeName)) {
 				sig = new char[arrayCount+1];
 				sig[arrayCount] = C_CHAR;
 				break;
 			}
 		case 'd':
-			if (CharOperation.fragmentEquals(DOUBLE, typeName, 0, true)) {
+			if (checkPrimitiveType(DOUBLE, typeName)) {
 				sig = new char[arrayCount+1];
 				sig[arrayCount] = C_DOUBLE;
 				break;
 			}
 		case 'f':
-			if (CharOperation.fragmentEquals(FLOAT, typeName, 0, true)) {
+			if (checkPrimitiveType(FLOAT, typeName)) {
 				sig = new char[arrayCount+1];
 				sig[arrayCount] = C_FLOAT;
 				break;
 			}
 		case 'i':
-			if (CharOperation.fragmentEquals(INT, typeName, 0, true)) {
+			if (checkPrimitiveType(INT, typeName)) {
 				sig = new char[arrayCount+1];
 				sig[arrayCount] = C_INT;
 				break;
 			}
 		case 'l':
-			if (CharOperation.fragmentEquals(LONG, typeName, 0, true)) {
+			if (checkPrimitiveType(LONG, typeName)) {
 				sig = new char[arrayCount+1];
 				sig[arrayCount] = C_LONG;
 				break;
 			}
 		case 's':
-			if (CharOperation.fragmentEquals(SHORT, typeName, 0, true)) {
+			if (checkPrimitiveType(SHORT, typeName)) {
 				sig = new char[arrayCount+1];
 				sig[arrayCount] = C_SHORT;
 				break;
 			}
 		case 'v':
-			if (CharOperation.fragmentEquals(VOID, typeName, 0, true)) {
+			if (checkPrimitiveType(VOID, typeName)) {
 				sig = new char[arrayCount+1];
 				sig[arrayCount] = C_VOID;
 				break;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
index 424d7ba..4bff47c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
@@ -18,21 +18,21 @@
 
 import org.eclipse.core.runtime.*;
 import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IConfigurationElement;
-import org.eclipse.core.runtime.IExtension;
-import org.eclipse.core.runtime.IExtensionPoint;
-import org.eclipse.core.runtime.Plugin;
 import org.eclipse.jdt.core.compiler.IScanner;
+import org.eclipse.jdt.core.formatter.CodeFormatter;
 import org.eclipse.jdt.core.util.ClassFileBytesDisassembler;
 import org.eclipse.jdt.core.util.ClassFormatException;
 import org.eclipse.jdt.core.util.IClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.util.ClassFileReader;
 import org.eclipse.jdt.internal.core.util.Disassembler;
 import org.eclipse.jdt.internal.core.util.PublicScanner;
-import org.eclipse.jdt.internal.formatter.CodeFormatter;
+import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter;
 
 /**
  * Factory for creating various compiler tools, such as scanners, parsers and compilers.
@@ -52,6 +52,7 @@
 	 * @return an instance of a code formatter
 	 * @see ICodeFormatter
 	 * @see ToolFactory#createDefaultCodeFormatter(Map)
+	 * @deprecated - should use #createCodeFormatter(Map) instead. Extension point is discontinued
 	 */
 	public static ICodeFormatter createCodeFormatter(){
 		
@@ -71,6 +72,7 @@
 								return (ICodeFormatter)execExt;
 							}
 						} catch(CoreException e){
+							// unable to instantiate extension, will answer default formatter instead
 						}
 					}
 				}	
@@ -80,6 +82,21 @@
 	}
 
 	/**
+	 * Create an instance of the built-in code formatter. 
+	 * @param options - the options map to use for formatting with the default code formatter. Recognized options
+	 * 	are documented on <code>JavaCore#getDefaultOptions()</code>. If set to <code>null</code>, then use 
+	 * 	the current settings from <code>JavaCore#getOptions</code>.
+	 * @return an instance of the built-in code formatter
+	 * @see CodeFormatter
+	 * @see JavaCore#getOptions()
+	 * @since 3.0
+	 */
+	public static CodeFormatter createCodeFormatter(Map options){
+		if (options == null) options = JavaCore.getOptions();
+		return new DefaultCodeFormatter(options);
+	}
+
+	/**
 	 * Create an instance of the built-in code formatter. A code formatter implementation can be contributed via the 
 	 * extension point "org.eclipse.jdt.core.codeFormatter". If unable to find a registered extension, the factory will 
 	 * default to using the default code formatter.
@@ -91,11 +108,11 @@
 	 * @see ICodeFormatter
 	 * @see ToolFactory#createCodeFormatter()
 	 * @see JavaCore#getOptions()
+	 * @deprecated - use #createCodeFormatter(Map) instead
 	 */
 	public static ICodeFormatter createDefaultCodeFormatter(Map options){
-
 		if (options == null) options = JavaCore.getOptions();
-		return new CodeFormatter(options);
+		return new org.eclipse.jdt.internal.formatter.CodeFormatter(options);
 	}
 	
 	/**
@@ -106,7 +123,9 @@
 	 * @deprecated - should use factory method creating ClassFileBytesDisassembler instead 
 	 */
 	public static org.eclipse.jdt.core.util.IClassFileDisassembler createDefaultClassFileDisassembler(){
-		class DeprecatedDisassembler extends Disassembler implements org.eclipse.jdt.core.util.IClassFileDisassembler {};
+		class DeprecatedDisassembler extends Disassembler implements org.eclipse.jdt.core.util.IClassFileDisassembler {
+			// for backward compatibility, defines a disassembler which implements IClassFileDisassembler
+		}
 		return new DeprecatedDisassembler();
 	}
 	
@@ -181,6 +200,7 @@
 					return createDefaultClassFileReader(location.toOSString(), decodingFlag);
 				}
 			} catch(CoreException e){
+				// unable to read
 			}
 		}
 		return null;
@@ -202,16 +222,17 @@
 	 * @see IClassFileReader
 	 */
 	public static IClassFileReader createDefaultClassFileReader(String zipFileName, String zipEntryName, int decodingFlag){
+		ZipFile zipFile = null;
 		try {
 			if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
 				System.out.println("(" + Thread.currentThread() + ") [ToolFactory.createDefaultClassFileReader()] Creating ZipFile on " + zipFileName); //$NON-NLS-1$	//$NON-NLS-2$
 			}
-			ZipFile zipFile = new ZipFile(zipFileName);
+			zipFile = new ZipFile(zipFileName);
 			ZipEntry zipEntry = zipFile.getEntry(zipEntryName);
 			if (zipEntry == null) {
 				return null;
 			}
-			if (!zipEntryName.toLowerCase().endsWith(".class")) {//$NON-NLS-1$
+			if (!zipEntryName.toLowerCase().endsWith(SuffixConstants.SUFFIX_STRING_class)) {
 				return null;
 			}
 			byte classFileBytes[] = Util.getZipEntryByteContent(zipEntry, zipFile);
@@ -220,6 +241,14 @@
 			return null;
 		} catch(IOException e) {
 			return null;
+		} finally {
+			if (zipFile != null) {
+				try {
+					zipFile.close();
+				} catch(IOException e) {
+					// ignore
+				}
+			}
 		}
 	}	
 	
@@ -246,7 +275,7 @@
 	 * <p>
 	 * @param tokenizeComments if set to <code>false</code>, comments will be silently consumed
 	 * @param tokenizeWhiteSpace if set to <code>false</code>, white spaces will be silently consumed,
-	 * @param assertKeyword if set to <code>false</code>, occurrences of 'assert' will be reported as identifiers
+	 * @param assertMode if set to <code>false</code>, occurrences of 'assert' will be reported as identifiers
 	 * (<code>ITerminalSymbols#TokenNameIdentifier</code>), whereas if set to <code>true</code>, it
 	 * would report assert keywords (<code>ITerminalSymbols#TokenNameassert</code>). Java 1.4 has introduced
 	 * a new 'assert' keyword.
@@ -259,8 +288,51 @@
 	 */
 	public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean assertMode, boolean recordLineSeparator){
 
-		PublicScanner scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace, false/*nls*/, assertMode /*assert*/, null/*taskTags*/, null/*taskPriorities*/);
+		PublicScanner scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace, false/*nls*/, assertMode ? ClassFileConstants.JDK1_4 : ClassFileConstants.JDK1_3/*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/);
 		scanner.recordLineSeparator = recordLineSeparator;
 		return scanner;
 	}
+	
+	/**
+	 * Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
+	 * used to tokenize some source in a Java aware way.
+	 * Here is a typical scanning loop:
+	 * 
+	 * <code>
+	 * <pre>
+	 *   IScanner scanner = ToolFactory.createScanner(false, false, false, false);
+	 *   scanner.setSource("int i = 0;".toCharArray());
+	 *   while (true) {
+	 *     int token = scanner.getNextToken();
+	 *     if (token == ITerminalSymbols.TokenNameEOF) break;
+	 *     System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
+	 *   }
+	 * </pre>
+	 * </code>
+	 * 
+	 * <p>
+	 * The returned scanner will tolerate unterminated line comments (missing line separator). It can be made stricter
+	 * by using API with extra boolean parameter (<code>strictCommentMode</code>).
+	 * <p>
+	 * @param tokenizeComments if set to <code>false</code>, comments will be silently consumed
+	 * @param tokenizeWhiteSpace if set to <code>false</code>, white spaces will be silently consumed,
+	 * @param recordLineSeparator if set to <code>true</code>, the scanner will record positions of encountered line 
+	 * separator ends. In case of multi-character line separators, the last character position is considered. These positions
+	 * can then be extracted using <code>IScanner#getLineEnds</code>. Only non-unicode escape sequences are 
+	 * considered as valid line separators.
+	 * @param sourceLevel if set to <code>&quot;1.3&quot;</code> or <code>null</code>, occurrences of 'assert' will be reported as identifiers
+	 * (<code>ITerminalSymbols#TokenNameIdentifier</code>), whereas if set to <code>&quot;1.4&quot;</code>, it
+	 * would report assert keywords (<code>ITerminalSymbols#TokenNameassert</code>). Java 1.4 has introduced
+	 * a new 'assert' keyword.
+  	 * @return a scanner
+	 * @see org.eclipse.jdt.core.compiler.IScanner
+	 */
+	public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean recordLineSeparator, String sourceLevel) {
+		PublicScanner scanner = null;
+		long level = CompilerOptions.versionToJdkLevel(sourceLevel);
+		if (level == 0) level = ClassFileConstants.JDK1_3; // fault-tolerance
+		scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace, false/*nls*/,level /*sourceLevel*/, null/*taskTags*/, null/*taskPriorities*/);
+		scanner.recordLineSeparator = recordLineSeparator;
+		return scanner;
+	}	
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/WorkingCopyOwner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/WorkingCopyOwner.java
new file mode 100644
index 0000000..67dbbb4
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/WorkingCopyOwner.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.core;
+
+import org.eclipse.jdt.internal.core.BufferManager;
+
+/**
+ * The owner of an <code>ICompilationUnit</code> handle in working copy mode. 
+ * An owner is used to identify a working copy and to create its buffer.
+ * <p>
+ * Clients should subclass this class to instanciate a working copy owner that is specific to their need and that
+ * they can pass in to various APIs (e.g. <code>IType.resolveType(String, WorkingCopyOwner)</code>.
+ * Clients can also override the default implementation of <code>createBuffer(ICompilationUnit)</code>.
+ * </p>
+ * 
+ * @see ICompilationUnit#becomeWorkingCopy(IProblemRequestor, org.eclipse.core.runtime.IProgressMonitor)
+ * @see ICompilationUnit#discardWorkingCopy()
+ * @see ICompilationUnit#getWorkingCopy(org.eclipse.core.runtime.IProgressMonitor)
+ * @since 3.0
+ */
+public abstract class WorkingCopyOwner {
+	
+	/**
+	 * Creates a buffer for the given working copy.
+	 * The new buffer will be initialized with the contents of the underlying file
+	 * if and only if it was not already initialized by the compilation owner (a buffer is 
+	 * uninitialized if its content is <code>null</code>).
+	 * 
+	 * @param workingCopy the working copy of the buffer
+	 * @return IBuffer the created buffer for the given working copy
+	 * @see IBuffer
+	 */
+	public IBuffer createBuffer(ICompilationUnit workingCopy) {
+
+		return BufferManager.getDefaultBufferManager().createBuffer(workingCopy);
+	}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/IScanner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/IScanner.java
index 7828066..c7b9565 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/IScanner.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/IScanner.java
@@ -128,8 +128,8 @@
 	char[] getSource();
 
 	/**
-	 * Reposition the scanner on some portion of the original source. Once reaching the given <code>endPosition</code>
-	 * it will answer EOF tokens (<code>ITerminalSymbols.TokenNameEOF</code>).
+	 * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position.
+	 * Beyond this position, the scanner will answer EOF tokens (<code>ITerminalSymbols.TokenNameEOF</code>).
 	 * 
 	 * @param startPosition the given start position
 	 * @param endPosition the given end position
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java
index 52dc47e..a173aae 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/eval/IEvaluationContext.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.core.eval;
 
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.ICompletionRequestor;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaProject;
@@ -119,6 +120,39 @@
 		ICompletionRequestor requestor)
 		throws JavaModelException;
 	/**
+	 * Performs a code completion at the given position in the given code snippet,
+	 * reporting results to the given completion requestor.
+	 * It considers types in the working copies with the given owner first. In other words, 
+	 * the owner's working copies will take precedence over their original compilation units
+	 * in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * </p>
+	 * <p>
+	 * Note that code completion does not involve evaluation.
+	 * <p>
+	 *
+	 * @param codeSnippet the code snippet to complete in
+	 * @param position the character position in the code snippet to complete at,
+	 *   or -1 indicating the beginning of the snippet
+	 * @param requestor the code completion requestor capable of accepting all
+	 *    possible types of completions
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * @exception JavaModelException if code completion could not be performed. Reasons include:
+	 *  <ul>
+	 *	  <li>The position specified is less than -1 or is greater than the snippet's
+	 *	    length (INDEX_OUT_OF_BOUNDS)</li>
+	 *  </ul>
+	 * @since 3.0
+	 */
+	public void codeComplete(
+		String codeSnippet,
+		int position,
+		ICompletionRequestor requestor,
+		WorkingCopyOwner owner)
+		throws JavaModelException;
+	/**
 	 * Resolves and returns a collection of Java elements corresponding to the source
 	 * code at the given positions in the given code snippet.
 	 * <p>
@@ -141,6 +175,37 @@
 	public IJavaElement[] codeSelect(String codeSnippet, int offset, int length)
 		throws JavaModelException;
 	/**
+	 * Resolves and returns a collection of Java elements corresponding to the source
+	 * code at the given positions in the given code snippet.
+	 * It considers types in the working copies with the given owner first. In other words, 
+	 * the owner's working copies will take precedence over their original compilation units
+	 * in the workspace.
+	 * <p>
+	 * Note that if a working copy is empty, it will be as if the original compilation
+	 * unit had been deleted.
+	 * </p>
+	 * <p>
+	 * Note that code select does not involve evaluation, and problems are never
+	 * reported.
+	 * <p>
+	 *
+	 * @param codeSnippet the code snippet to resolve in
+	 * @param offset the position in the code snippet of the first character
+	 *   of the code to resolve
+	 * @param length the length of the selected code to resolve
+	 * @param owner the owner of working copies that take precedence over their original compilation units
+	 * @return the (possibly empty) list of selection Java elements
+	 * @exception JavaModelException if code resolve could not be performed.
+	 *   Reasons include:
+	 *   <ul>
+	 *	   <li>The position specified is less than -1 or is greater than the snippet's
+	 *	     length (INDEX_OUT_OF_BOUNDS)</li>
+	 *   </ul>
+	 * @since 3.0
+	 */
+	public IJavaElement[] codeSelect(String codeSnippet, int offset, int length, WorkingCopyOwner owner)
+		throws JavaModelException;
+	/**
 	 * Deletes the given variable from this evaluation context. Does nothing if
 	 * the given variable has already been deleted.
 	 *
@@ -328,6 +393,7 @@
 	 *	    length (INDEX_OUT_OF_BOUNDS)</li>
 	 *  </ul>
 	 * @deprecated - use codeComplete(String, int, ICompletionRequestor) instead
+	 * TODO remove before 3.0
 	 */
 	public void codeComplete(
 		String codeSnippet,
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java
index c34aa52..13a81e2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMException.java
@@ -20,7 +20,9 @@
 /**
  * Creates a new exception with no detail message.
  */
-public DOMException() {}
+public DOMException() {
+	// just create a new DOMException with no detail message
+}
 /**
  * Creates a new exception with the given detail message.
  *
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMFactory.java
index 59d6132..03fc117 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/jdom/DOMFactory.java
@@ -25,7 +25,9 @@
 /**
  * Creates a new DOM factory.
  */
-public DOMFactory() {}
+public DOMFactory() {
+	// constructor is explicitly API
+}
 /* (non-Javadoc)
  * Method declared on IDOMFactory.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java
index f07cd93..9c9f4a3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ByteCodeVisitorAdapter.java
@@ -21,498 +21,581 @@
 	 * @see IBytecodeVisitor#_aaload(int)
 	 */
 	public void _aaload(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_aastore(int)
 	 */
 	public void _aastore(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_aconst_null(int)
 	 */
 	public void _aconst_null(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_aload_0(int)
 	 */
 	public void _aload_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_aload_1(int)
 	 */
 	public void _aload_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_aload_2(int)
 	 */
 	public void _aload_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_aload_3(int)
 	 */
 	public void _aload_3(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_aload(int, int)
 	 */
 	public void _aload(int pc, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_anewarray(int, int, IConstantPoolEntry)
 	 */
 	public void _anewarray(int pc, int index, IConstantPoolEntry constantClass) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_areturn(int)
 	 */
 	public void _areturn(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_arraylength(int)
 	 */
 	public void _arraylength(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_astore_0(int)
 	 */
 	public void _astore_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_astore_1(int)
 	 */
 	public void _astore_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_astore_2(int)
 	 */
 	public void _astore_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_astore_3(int)
 	 */
 	public void _astore_3(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_astore(int, int)
 	 */
 	public void _astore(int pc, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_athrow(int)
 	 */
 	public void _athrow(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_baload(int)
 	 */
 	public void _baload(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_bastore(int)
 	 */
 	public void _bastore(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_bipush(int, byte)
 	 */
 	public void _bipush(int pc, byte _byte) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_caload(int)
 	 */
 	public void _caload(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_castore(int)
 	 */
 	public void _castore(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_checkcast(int, int, IConstantPoolEntry)
 	 */
 	public void _checkcast(int pc, int index, IConstantPoolEntry constantClass) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_d2f(int)
 	 */
 	public void _d2f(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_d2i(int)
 	 */
 	public void _d2i(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_d2l(int)
 	 */
 	public void _d2l(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dadd(int)
 	 */
 	public void _dadd(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_daload(int)
 	 */
 	public void _daload(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dastore(int)
 	 */
 	public void _dastore(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dcmpg(int)
 	 */
 	public void _dcmpg(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dcmpl(int)
 	 */
 	public void _dcmpl(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dconst_0(int)
 	 */
 	public void _dconst_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dconst_1(int)
 	 */
 	public void _dconst_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ddiv(int)
 	 */
 	public void _ddiv(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dload_0(int)
 	 */
 	public void _dload_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dload_1(int)
 	 */
 	public void _dload_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dload_2(int)
 	 */
 	public void _dload_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dload_3(int)
 	 */
 	public void _dload_3(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dload(int, int)
 	 */
 	public void _dload(int pc, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dmul(int)
 	 */
 	public void _dmul(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dneg(int)
 	 */
 	public void _dneg(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_drem(int)
 	 */
 	public void _drem(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dreturn(int)
 	 */
 	public void _dreturn(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dstore_0(int)
 	 */
 	public void _dstore_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dstore_1(int)
 	 */
 	public void _dstore_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dstore_2(int)
 	 */
 	public void _dstore_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dstore_3(int)
 	 */
 	public void _dstore_3(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dstore(int, int)
 	 */
 	public void _dstore(int pc, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dsub(int)
 	 */
 	public void _dsub(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dup_x1(int)
 	 */
 	public void _dup_x1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dup_x2(int)
 	 */
 	public void _dup_x2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dup(int)
 	 */
 	public void _dup(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dup2_x1(int)
 	 */
 	public void _dup2_x1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dup2_x2(int)
 	 */
 	public void _dup2_x2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_dup2(int)
 	 */
 	public void _dup2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_f2d(int)
 	 */
 	public void _f2d(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_f2i(int)
 	 */
 	public void _f2i(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_f2l(int)
 	 */
 	public void _f2l(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fadd(int)
 	 */
 	public void _fadd(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_faload(int)
 	 */
 	public void _faload(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fastore(int)
 	 */
 	public void _fastore(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fcmpg(int)
 	 */
 	public void _fcmpg(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fcmpl(int)
 	 */
 	public void _fcmpl(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fconst_0(int)
 	 */
 	public void _fconst_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fconst_1(int)
 	 */
 	public void _fconst_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fconst_2(int)
 	 */
 	public void _fconst_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fdiv(int)
 	 */
 	public void _fdiv(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fload_0(int)
 	 */
 	public void _fload_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fload_1(int)
 	 */
 	public void _fload_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fload_2(int)
 	 */
 	public void _fload_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fload_3(int)
 	 */
 	public void _fload_3(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fload(int, int)
 	 */
 	public void _fload(int pc, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fmul(int)
 	 */
 	public void _fmul(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fneg(int)
 	 */
 	public void _fneg(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_frem(int)
 	 */
 	public void _frem(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_freturn(int)
 	 */
 	public void _freturn(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fstore_0(int)
 	 */
 	public void _fstore_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fstore_1(int)
 	 */
 	public void _fstore_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fstore_2(int)
 	 */
 	public void _fstore_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fstore_3(int)
 	 */
 	public void _fstore_3(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fstore(int, int)
 	 */
 	public void _fstore(int pc, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_fsub(int)
 	 */
 	public void _fsub(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_getfield(int, int, IConstantPoolEntry)
 	 */
 	public void _getfield(int pc, int index, IConstantPoolEntry constantFieldref) {
+		// default behavior is to do nothing
 	}
 
 	/**
@@ -522,276 +605,322 @@
 		int pc,
 		int index,
 		IConstantPoolEntry constantFieldref) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_goto_w(int, int)
 	 */
 	public void _goto_w(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_goto(int, int)
 	 */
 	public void _goto(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_i2b(int)
 	 */
 	public void _i2b(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_i2c(int)
 	 */
 	public void _i2c(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_i2d(int)
 	 */
 	public void _i2d(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_i2f(int)
 	 */
 	public void _i2f(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_i2l(int)
 	 */
 	public void _i2l(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_i2s(int)
 	 */
 	public void _i2s(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iadd(int)
 	 */
 	public void _iadd(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iaload(int)
 	 */
 	public void _iaload(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iand(int)
 	 */
 	public void _iand(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iastore(int)
 	 */
 	public void _iastore(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iconst_0(int)
 	 */
 	public void _iconst_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iconst_1(int)
 	 */
 	public void _iconst_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iconst_2(int)
 	 */
 	public void _iconst_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iconst_3(int)
 	 */
 	public void _iconst_3(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iconst_4(int)
 	 */
 	public void _iconst_4(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iconst_5(int)
 	 */
 	public void _iconst_5(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iconst_m1(int)
 	 */
 	public void _iconst_m1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_idiv(int)
 	 */
 	public void _idiv(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_if_acmpeq(int, int)
 	 */
 	public void _if_acmpeq(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_if_acmpne(int, int)
 	 */
 	public void _if_acmpne(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_if_icmpeq(int, int)
 	 */
 	public void _if_icmpeq(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_if_icmpge(int, int)
 	 */
 	public void _if_icmpge(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_if_icmpgt(int, int)
 	 */
 	public void _if_icmpgt(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_if_icmple(int, int)
 	 */
 	public void _if_icmple(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_if_icmplt(int, int)
 	 */
 	public void _if_icmplt(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_if_icmpne(int, int)
 	 */
 	public void _if_icmpne(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ifeq(int, int)
 	 */
 	public void _ifeq(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ifge(int, int)
 	 */
 	public void _ifge(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ifgt(int, int)
 	 */
 	public void _ifgt(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ifle(int, int)
 	 */
 	public void _ifle(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iflt(int, int)
 	 */
 	public void _iflt(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ifne(int, int)
 	 */
 	public void _ifne(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ifnonnull(int, int)
 	 */
 	public void _ifnonnull(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ifnull(int, int)
 	 */
 	public void _ifnull(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iinc(int, int, int)
 	 */
 	public void _iinc(int pc, int index, int _const) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iload_0(int)
 	 */
 	public void _iload_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iload_1(int)
 	 */
 	public void _iload_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iload_2(int)
 	 */
 	public void _iload_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iload_3(int)
 	 */
 	public void _iload_3(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iload(int, int)
 	 */
 	public void _iload(int pc, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_imul(int)
 	 */
 	public void _imul(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ineg(int)
 	 */
 	public void _ineg(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_instanceof(int, int, IConstantPoolEntry)
 	 */
 	public void _instanceof(int pc, int index, IConstantPoolEntry constantClass) {
+		// default behavior is to do nothing
 	}
 
 	/**
@@ -802,6 +931,7 @@
 		int index,
 		byte nargs,
 		IConstantPoolEntry constantInterfaceMethodref) {
+		// default behavior is to do nothing
 	}
 
 	/**
@@ -811,6 +941,7 @@
 		int pc,
 		int index,
 		IConstantPoolEntry constantMethodref) {
+		// default behavior is to do nothing
 	}
 
 	/**
@@ -820,6 +951,7 @@
 		int pc,
 		int index,
 		IConstantPoolEntry constantMethodref) {
+		// default behavior is to do nothing
 	}
 
 	/**
@@ -829,222 +961,259 @@
 		int pc,
 		int index,
 		IConstantPoolEntry constantMethodref) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ior(int)
 	 */
 	public void _ior(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_irem(int)
 	 */
 	public void _irem(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ireturn(int)
 	 */
 	public void _ireturn(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ishl(int)
 	 */
 	public void _ishl(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ishr(int)
 	 */
 	public void _ishr(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_istore_0(int)
 	 */
 	public void _istore_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_istore_1(int)
 	 */
 	public void _istore_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_istore_2(int)
 	 */
 	public void _istore_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_istore_3(int)
 	 */
 	public void _istore_3(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_istore(int, int)
 	 */
 	public void _istore(int pc, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_isub(int)
 	 */
 	public void _isub(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_iushr(int)
 	 */
 	public void _iushr(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ixor(int)
 	 */
 	public void _ixor(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_jsr_w(int, int)
 	 */
 	public void _jsr_w(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_jsr(int, int)
 	 */
 	public void _jsr(int pc, int branchOffset) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_l2d(int)
 	 */
 	public void _l2d(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_l2f(int)
 	 */
 	public void _l2f(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_l2i(int)
 	 */
 	public void _l2i(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ladd(int)
 	 */
 	public void _ladd(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_laload(int)
 	 */
 	public void _laload(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_land(int)
 	 */
 	public void _land(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lastore(int)
 	 */
 	public void _lastore(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lcmp(int)
 	 */
 	public void _lcmp(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lconst_0(int)
 	 */
 	public void _lconst_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lconst_1(int)
 	 */
 	public void _lconst_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ldc_w(int, int, IConstantPoolEntry)
 	 */
 	public void _ldc_w(int pc, int index, IConstantPoolEntry constantPoolEntry) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ldc(int, int, IConstantPoolEntry)
 	 */
 	public void _ldc(int pc, int index, IConstantPoolEntry constantPoolEntry) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ldc2_w(int, int, IConstantPoolEntry)
 	 */
 	public void _ldc2_w(int pc, int index, IConstantPoolEntry constantPoolEntry) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ldiv(int)
 	 */
 	public void _ldiv(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lload_0(int)
 	 */
 	public void _lload_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lload_1(int)
 	 */
 	public void _lload_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lload_2(int)
 	 */
 	public void _lload_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lload_3(int)
 	 */
 	public void _lload_3(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lload(int, int)
 	 */
 	public void _lload(int pc, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lmul(int)
 	 */
 	public void _lmul(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lneg(int)
 	 */
 	public void _lneg(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
@@ -1055,96 +1224,112 @@
 		int defaultoffset,
 		int npairs,
 		int[][] offset_pairs) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lor(int)
 	 */
 	public void _lor(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lrem(int)
 	 */
 	public void _lrem(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lreturn(int)
 	 */
 	public void _lreturn(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lshl(int)
 	 */
 	public void _lshl(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lshr(int)
 	 */
 	public void _lshr(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lstore_0(int)
 	 */
 	public void _lstore_0(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lstore_1(int)
 	 */
 	public void _lstore_1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lstore_2(int)
 	 */
 	public void _lstore_2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lstore_3(int)
 	 */
 	public void _lstore_3(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lstore(int, int)
 	 */
 	public void _lstore(int pc, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lsub(int)
 	 */
 	public void _lsub(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lushr(int)
 	 */
 	public void _lushr(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_lxor(int)
 	 */
 	public void _lxor(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_monitorenter(int)
 	 */
 	public void _monitorenter(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_monitorexit(int)
 	 */
 	public void _monitorexit(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
@@ -1155,42 +1340,49 @@
 		int index,
 		int dimensions,
 		IConstantPoolEntry constantClass) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_new(int, int, IConstantPoolEntry)
 	 */
 	public void _new(int pc, int index, IConstantPoolEntry constantClass) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_newarray(int, int)
 	 */
 	public void _newarray(int pc, int atype) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_nop(int)
 	 */
 	public void _nop(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_pop(int)
 	 */
 	public void _pop(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_pop2(int)
 	 */
 	public void _pop2(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_putfield(int, int, IConstantPoolEntry)
 	 */
 	public void _putfield(int pc, int index, IConstantPoolEntry constantFieldref) {
+		// default behavior is to do nothing
 	}
 
 	/**
@@ -1200,42 +1392,49 @@
 		int pc,
 		int index,
 		IConstantPoolEntry constantFieldref) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_ret(int, int)
 	 */
 	public void _ret(int pc, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_return(int)
 	 */
 	public void _return(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_saload(int)
 	 */
 	public void _saload(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_sastore(int)
 	 */
 	public void _sastore(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_sipush(int, short)
 	 */
 	public void _sipush(int pc, short value) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_swap(int)
 	 */
 	public void _swap(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
@@ -1247,36 +1446,42 @@
 		int low,
 		int high,
 		int[] jump_offsets) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_wide(int, int, int, int)
 	 */
 	public void _wide(int pc, int iincopcode, int index, int _const) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_wide(int, int, int)
 	 */
 	public void _wide(int pc, int opcode, int index) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_breakpoint(int)
 	 */
 	public void _breakpoint(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_impdep1(int)
 	 */
 	public void _impdep1(int pc) {
+		// default behavior is to do nothing
 	}
 
 	/**
 	 * @see IBytecodeVisitor#_impdep2(int)
 	 */
 	public void _impdep2(int pc) {
+		// default behavior is to do nothing
 	}
 
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java
index b5e38ce..5375059 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/ClassFormatException.java
@@ -24,14 +24,11 @@
 	public static final int INVALID_ARGUMENTS_FOR_INVOKEINTERFACE = 5;
 	public static final int INVALID_BYTECODE = 6;
 	
-	private int errorID;
-	
 	/**
 	 * Constructor for ClassFormatException.
 	 */
 	public ClassFormatException(int errorID) {
-		super();
-		this.errorID = errorID;
+		// TODO what is the errorID?
 	}
 
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java
index 98ab372..d50280c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/util/CompilationUnitSorter.java
@@ -34,6 +34,7 @@
  	 * Private constructor to prevent instantiation.
  	 */
 	private CompilationUnitSorter() {
+		// Not instantiable
 	} 
 	
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Assert.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Assert.java
index 324a08b..7560dc5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Assert.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Assert.java
@@ -10,9 +10,11 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-public final class Assert {
 /* This class is not intended to be instantiated. */
+public final class Assert {
+
 private Assert() {
+	// cannot be instantiated
 }
 /** Asserts that an argument is legal. If the given boolean is
  * not <code>true</code>, an <code>IllegalArgumentException</code>
@@ -89,8 +91,6 @@
 }
 
 	public static class AssertionFailedException extends RuntimeException {
-		public AssertionFailedException() {
-		}
 		public AssertionFailedException(String detail) {
 			super(detail);
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
index d2eb5ac..a1aaf84 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
@@ -51,8 +51,9 @@
 
 	// otherwise retrieve it
 	try {
-		return Util.getFileCharContent(new File(new String(fileName)), this.encoding);
+		return Util.getFileCharContent(new File(new String(this.fileName)), this.encoding);
 	} catch (IOException e) {
+		// could not read file: returns an empty array
 	}
 	return CharOperation.NO_CHAR;
 }
@@ -66,6 +67,6 @@
 	return this.packageName;
 }
 public String toString(){
-	return "CompilationUnit: "+new String(fileName); //$NON-NLS-1$
+	return "CompilationUnit: "+new String(this.fileName); //$NON-NLS-1$
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BatchOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BatchOperation.java
index c088217..d01fef5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BatchOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BatchOperation.java
@@ -31,7 +31,7 @@
 	 */
 	protected void executeOperation() throws JavaModelException {
 		try {
-			this.runnable.run(fMonitor);
+			this.runnable.run(this.progressMonitor);
 		} catch (CoreException ce) {
 			if (ce instanceof JavaModelException) {
 				throw (JavaModelException)ce;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BecomeWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BecomeWorkingCopyOperation.java
new file mode 100644
index 0000000..e9ae186
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BecomeWorkingCopyOperation.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.JavaModelException;
+
+/**
+ * Switch and ICompilationUnit to working copy mode
+ * and signal the working copy addition through a delta.
+ */
+public class BecomeWorkingCopyOperation extends JavaModelOperation {
+	
+	IPath path;
+	IProblemRequestor problemRequestor;
+	
+	/*
+	 * Creates a BecomeWorkingCopyOperation for the given working copy.
+	 * perOwnerWorkingCopies map is not null if the working copy is a shared working copy.
+	 */
+	public BecomeWorkingCopyOperation(CompilationUnit workingCopy, IPath path, IProblemRequestor problemRequestor) {
+		super(new IJavaElement[] {workingCopy});
+		this.path = path;
+		this.problemRequestor = problemRequestor;
+	}
+	protected void executeOperation() throws JavaModelException {
+
+		// open the working copy now to ensure contents are that of the current state of this element
+		CompilationUnit workingCopy = getWorkingCopy();
+		JavaModelManager.getJavaModelManager().getPerWorkingCopyInfo(workingCopy, this.path, true/*create if needed*/, true/*record usage*/, this.problemRequestor);
+		workingCopy.openWhenClosed(workingCopy.createElementInfo(), this.progressMonitor);
+
+		if (!workingCopy.isPrimary()) {
+			// report added java delta for a non-primary working copy
+			JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+			delta.added(workingCopy);
+			addDelta(delta);
+		} else {
+			if (workingCopy.getResource().isAccessible()) {
+				// report a F_PRIMARY_WORKING_COPY change delta for a primary working copy
+				JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+				delta.changed(workingCopy, IJavaElementDelta.F_PRIMARY_WORKING_COPY);
+				addDelta(delta);
+			} else {
+				// report an ADDED delta
+				JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+				delta.added(workingCopy, IJavaElementDelta.F_PRIMARY_WORKING_COPY);
+				addDelta(delta);
+			}
+		}
+
+		this.resultElements = new IJavaElement[] {workingCopy};
+	}
+	/*
+	 * Returns the working copy this operation is working on.
+	 */
+	protected CompilationUnit getWorkingCopy() {
+		return (CompilationUnit)getElementToProcess();
+	}
+	/*
+	 * @see JavaModelOperation#isReadOnly
+	 */
+	public boolean isReadOnly() {
+		return true;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java
index a160530..c5f08dd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryField.java
@@ -11,7 +11,6 @@
 package org.eclipse.jdt.internal.core;
 
 import org.eclipse.jdt.core.IField;
-import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.internal.compiler.env.IBinaryField;
@@ -22,40 +21,50 @@
 
 /* package */ class BinaryField extends BinaryMember implements IField {
 
-/**
+/*
  * Constructs a handle to the field with the given name in the specified type. 
  */
-protected BinaryField(IType parent, String name) {
-	super(FIELD, parent, name);
+protected BinaryField(JavaElement parent, String name) {
+	super(parent, name);
 }
-/**
+public boolean equals(Object o) {
+	if (!(o instanceof BinaryField)) return false;
+	return super.equals(o);
+}
+/*
  * @see IField
  */
 public Object getConstant() throws JavaModelException {
 	IBinaryField info = (IBinaryField) getElementInfo();
 	return convertConstant(info.getConstant());
 }
-/**
+/*
  * @see IMember
  */
 public int getFlags() throws JavaModelException {
 	IBinaryField info = (IBinaryField) getElementInfo();
 	return info.getModifiers();
 }
-/**
+/*
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return FIELD;
+}
+/*
  * @see JavaElement#getHandleMemento()
  */
 protected char getHandleMementoDelimiter() {
 	return JavaElement.JEM_FIELD;
 }
-/**
+/*
  * @see IField
  */
 public String getTypeSignature() throws JavaModelException {
 	IBinaryField info = (IBinaryField) getElementInfo();
 	return new String(ClassFile.translatedName(info.getTypeName()));
 }
-/**
+/*
  * @private Debugging purposes
  */
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java
index 68df607..3ea9865 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMember.java
@@ -10,6 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.util.HashMap;
+
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
@@ -19,20 +21,35 @@
 /**
  * Common functionality for Binary member handles.
  */
-public class BinaryMember extends Member {
-/**
+public abstract class BinaryMember extends Member {
+/*
  * Constructs a binary member.
  */
-protected BinaryMember(int type, IJavaElement parent, String name) {
-	super(type, parent, name);
+protected BinaryMember(JavaElement parent, String name) {
+	super(parent, name);
 }
-/**
+/*
  * @see ISourceManipulation
  */
 public void copy(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException {
 	throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
 }
-/**
+/*
+ * @see JavaElement#generateInfos
+ */
+protected void generateInfos(Object info, HashMap newElements, IProgressMonitor pm) throws JavaModelException {
+	Openable openableParent = (Openable)getOpenableParent();
+	if (openableParent == null) return;
+	
+	ClassFileInfo openableParentInfo = (ClassFileInfo) JavaModelManager.getJavaModelManager().getInfo(openableParent);
+	if (openableParentInfo == null) {
+		openableParent.generateInfos(openableParent.createElementInfo(), newElements, pm);
+		openableParentInfo = (ClassFileInfo)newElements.get(openableParent);
+	}
+	if (openableParentInfo == null) return;
+	openableParentInfo.getBinaryChildren(newElements); // forces the initialization
+}
+/*
  * @see ISourceReference
  */
 public ISourceRange getNameRange() throws JavaModelException {
@@ -46,7 +63,7 @@
 		return SourceMapper.fgUnknownRange;
 	}
 }
-/**
+/*
  * @see ISourceReference
  */
 public ISourceRange getSourceRange() throws JavaModelException {
@@ -60,48 +77,31 @@
 		return SourceMapper.fgUnknownRange;
 	}
 }
-/**
+/*
  * @see IMember
  */
 public boolean isBinary() {
 	return true;
 }
-/**
+/*
  * @see IJavaElement
  */
 public boolean isStructureKnown() throws JavaModelException {
 	return ((IJavaElement)getOpenableParent()).isStructureKnown();
 }
-/**
+/*
  * @see ISourceManipulation
  */
 public void move(IJavaElement container, IJavaElement sibling, String rename, boolean force, IProgressMonitor monitor) throws JavaModelException {
 	throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
 }
-/**
- * Opens this element and all parents that are not already open.
- *
- * @exception NotPresentException this element is not present or accessable
- */
-protected void openHierarchy() throws JavaModelException {
-	Openable openableParent = (Openable)getOpenableParent();
-	if (openableParent != null) {
-		JavaElementInfo openableParentInfo = (JavaElementInfo) JavaModelManager.getJavaModelManager().getInfo((IJavaElement) openableParent);
-		if (openableParentInfo == null) {
-			openableParent.openWhenClosed(null);
-			openableParentInfo = (JavaElementInfo) JavaModelManager.getJavaModelManager().getInfo((IJavaElement) openableParent);
-		}
-		ClassFileInfo cfi = (ClassFileInfo) openableParentInfo;
-		cfi.getBinaryChildren(); // forces the initialization
-	}
-}
-/**
+/*
  * @see ISourceManipulation
  */
-public void rename(String name, boolean force, IProgressMonitor monitor) throws JavaModelException {
+public void rename(String newName, boolean force, IProgressMonitor monitor) throws JavaModelException {
 	throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
 }
-/**
+/*
  * Sets the contents of this element.
  * Throws an exception as this element is read only.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
index 0ee15b9..a3c58bd 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
@@ -17,6 +17,7 @@
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.internal.compiler.SourceElementRequestorAdapter;
 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * @see IMethod
@@ -30,18 +31,18 @@
 			public void enterMethod(
 				int declarationStart,
 				int modifiers,
-				char[] returnType,
-				char[] name,
+				char[] returnTypeName,
+				char[] selector,
 				int nameSourceStart,
 				int nameSourceEnd,
-				char[][] parameterTypes,
-				char[][] parameterNames,
-				char[][] exceptionTypes) {
-					if (parameterNames != null) {
-						int length = parameterNames.length;
+				char[][] paramTypes,
+				char[][] paramNames,
+				char[][] exceptions) {
+					if (paramNames != null) {
+						int length = paramNames.length;
 						this.parametersNames = new String[length];
 						for (int i = 0; i < length; i++) {
-							this.parametersNames[i] = new String(parameterNames[i]);
+							this.parametersNames[i] = new String(paramNames[i]);
 						}
 					}
 				}
@@ -49,17 +50,17 @@
 			public void enterConstructor(
 				int declarationStart,
 				int modifiers,
-				char[] name,
+				char[] selector,
 				int nameSourceStart,
 				int nameSourceEnd,
-				char[][] parameterTypes,
-				char[][] parameterNames,
-				char[][] exceptionTypes) {
-					if (parameterNames != null) {
-						int length = parameterNames.length;
+				char[][] paramTypes,
+				char[][] paramNames,
+				char[][] exceptions) {
+					if (paramNames != null) {
+						int length = paramNames.length;
 						this.parametersNames = new String[length];
 						for (int i = 0; i < length; i++) {
-							this.parametersNames[i] = new String(parameterNames[i]);
+							this.parametersNames[i] = new String(paramNames[i]);
 						}
 					}
 				}
@@ -74,42 +75,43 @@
 	 * to perform equality test. <code>null</code> indicates no
 	 * parameters.
 	 */
-	protected String[] fParameterTypes;
+	protected String[] parameterTypes;
 	/**
 	 * The parameter names for the method.
 	 */
-	protected String[] fParameterNames;
+	protected String[] parameterNames;
 
 	/**
 	 * An empty list of Strings
 	 */
-	protected static final String[] fgEmptyList= new String[] {};
-	protected String[] fExceptionTypes;
-	protected String fReturnType;
-protected BinaryMethod(IType parent, String name, String[] parameterTypes) {
-	super(METHOD, parent, name);
+	protected static final String[] NO_TYPES= new String[] {};
+	protected String[] exceptionTypes;
+	protected String returnType;
+protected BinaryMethod(JavaElement parent, String name, String[] paramTypes) {
+	super(parent, name);
 	Assert.isTrue(name.indexOf('.') == -1);
-	if (parameterTypes == null) {
-		fParameterTypes= fgEmptyList;
+	if (paramTypes == null) {
+		this.parameterTypes= NO_TYPES;
 	} else {
-		fParameterTypes= parameterTypes;
+		this.parameterTypes= paramTypes;
 	}
 }
 public boolean equals(Object o) {
-	return super.equals(o) && Util.equalArraysOrNull(fParameterTypes, ((BinaryMethod)o).fParameterTypes);
+	if (!(o instanceof BinaryMethod)) return false;
+	return super.equals(o) && Util.equalArraysOrNull(this.parameterTypes, ((BinaryMethod)o).parameterTypes);
 }
-/**
+/*
  * @see IMethod
  */
 public String[] getExceptionTypes() throws JavaModelException {
-	if (fExceptionTypes == null) {
+	if (this.exceptionTypes == null) {
 		IBinaryMethod info = (IBinaryMethod) getElementInfo();
 		char[][] eTypeNames = info.getExceptionTypeNames();
 		if (eTypeNames == null || eTypeNames.length == 0) {
-			fExceptionTypes = fgEmptyList;
+			this.exceptionTypes = NO_TYPES;
 		} else {
 			eTypeNames = ClassFile.translatedNames(eTypeNames);
-			fExceptionTypes = new String[eTypeNames.length];
+			this.exceptionTypes = new String[eTypeNames.length];
 			for (int j = 0, length = eTypeNames.length; j < length; j++) {
 				// 1G01HRY: ITPJCORE:WINNT - method.getExceptionType not in correct format
 				int nameLength = eTypeNames[j].length;
@@ -117,125 +119,135 @@
 				System.arraycopy(eTypeNames[j], 0, convertedName, 1, nameLength);
 				convertedName[0] = 'L';
 				convertedName[nameLength + 1] = ';';
-				fExceptionTypes[j] = new String(convertedName);
+				this.exceptionTypes[j] = new String(convertedName);
 			}
 		}
 	}
-	return fExceptionTypes;
+	return this.exceptionTypes;
 }
-/**
+/*
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return METHOD;
+}
+/*
  * @see IMember
  */
 public int getFlags() throws JavaModelException {
 	IBinaryMethod info = (IBinaryMethod) getElementInfo();
 	return info.getModifiers();
 }
-/**
+/*
  * @see JavaElement#getHandleMemento()
  */
 public String getHandleMemento() {
 	StringBuffer buff = new StringBuffer(((JavaElement) getParent()).getHandleMemento());
 	buff.append(getHandleMementoDelimiter());
 	buff.append(getElementName());
-	for (int i = 0; i < fParameterTypes.length; i++) {
+	for (int i = 0; i < this.parameterTypes.length; i++) {
 		buff.append(getHandleMementoDelimiter());
-		buff.append(fParameterTypes[i]);
+		buff.append(this.parameterTypes[i]);
+	}
+	if (this.occurrenceCount > 1) {
+		buff.append(JEM_COUNT);
+		buff.append(this.occurrenceCount);
 	}
 	return buff.toString();
 }
-/**
+/*
  * @see JavaElement#getHandleMemento()
  */
 protected char getHandleMementoDelimiter() {
 	return JavaElement.JEM_METHOD;
 }
-/**
+/*
  * @see IMethod
  */
 public int getNumberOfParameters() {
-	return fParameterTypes == null ? 0 : fParameterTypes.length;
+	return this.parameterTypes == null ? 0 : this.parameterTypes.length;
 }
-/**
+/*
  * @see IMethod
  * Look for source attachment information to retrieve the actual parameter names as stated in source.
  */
 public String[] getParameterNames() throws JavaModelException {
-	if (fParameterNames == null) {
+	if (this.parameterNames == null) {
 
 		// force source mapping if not already done
 		IType type = (IType) getParent();
 		SourceMapper mapper = getSourceMapper();
 		if (mapper != null) {
-			char[][] parameterNames = mapper.getMethodParameterNames(this);
+			char[][] paramNames = mapper.getMethodParameterNames(this);
 			
 			// map source and try to find parameter names
-			if(parameterNames == null) {
+			if(paramNames == null) {
 				char[] source = mapper.findSource(type);
 				if (source != null){
 					mapper.mapSource(type, source);
 				}
-				parameterNames = mapper.getMethodParameterNames(this);
+				paramNames = mapper.getMethodParameterNames(this);
 			}
 			
 			// if parameter names exist, convert parameter names to String array
-			if(parameterNames != null) {
-				fParameterNames = new String[parameterNames.length];
-				for (int i = 0; i < parameterNames.length; i++) {
-					fParameterNames[i] = new String(parameterNames[i]);
+			if(paramNames != null) {
+				this.parameterNames = new String[paramNames.length];
+				for (int i = 0; i < paramNames.length; i++) {
+					this.parameterNames[i] = new String(paramNames[i]);
 				}
 			}
 		}
 		// if still no parameter names, produce fake ones
-		if (fParameterNames == null) {
+		if (this.parameterNames == null) {
 			IBinaryMethod info = (IBinaryMethod) getElementInfo();
 			int paramCount = Signature.getParameterCount(new String(info.getMethodDescriptor()));
-			fParameterNames = new String[paramCount];
+			this.parameterNames = new String[paramCount];
 			for (int i = 0; i < paramCount; i++) {
-				fParameterNames[i] = "arg" + i; //$NON-NLS-1$
+				this.parameterNames[i] = "arg" + i; //$NON-NLS-1$
 			}
 		}
 	}
-	return fParameterNames;
+	return this.parameterNames;
 }
-/**
+/*
  * @see IMethod
  */
 public String[] getParameterTypes() {
-	return fParameterTypes;
+	return this.parameterTypes;
 }
-/**
+/*
  * @see IMethod
  */
 public String getReturnType() throws JavaModelException {
 	IBinaryMethod info = (IBinaryMethod) getElementInfo();
-	if (fReturnType == null) {
-		String returnType= Signature.getReturnType(new String(info.getMethodDescriptor()));
-		fReturnType= new String(ClassFile.translatedName(returnType.toCharArray()));
+	if (this.returnType == null) {
+		String returnTypeName= Signature.getReturnType(new String(info.getMethodDescriptor()));
+		this.returnType= new String(ClassFile.translatedName(returnTypeName.toCharArray()));
 	}
-	return fReturnType;
+	return this.returnType;
 }
-/**
+/*
  * @see IMethod
  */
 public String getSignature() throws JavaModelException {
 	IBinaryMethod info = (IBinaryMethod) getElementInfo();
 	return new String(info.getMethodDescriptor());
 }
-/**
+/*
  * @see IMethod
  */
 public boolean isConstructor() throws JavaModelException {
 	IBinaryMethod info = (IBinaryMethod) getElementInfo();
 	return info.isConstructor();
 }
-/**
+/*
  * @see IMethod#isMainMethod()
  */
 public boolean isMainMethod() throws JavaModelException {
 	return this.isMainMethod(this);
 }
 
-/**
+/*
  * @see IMethod#isSimilar(IMethod)
  */
 public boolean isSimilar(IMethod method) {
@@ -246,17 +258,15 @@
 			null);
 }
 
-/**
- */
 public String readableName() {
 
 	StringBuffer buffer = new StringBuffer(super.readableName());
 	buffer.append("("); //$NON-NLS-1$
-	String[] parameterTypes = this.getParameterTypes();
+	String[] paramTypes = this.parameterTypes;
 	int length;
-	if (parameterTypes != null && (length = parameterTypes.length) > 0) {
+	if (paramTypes != null && (length = paramTypes.length) > 0) {
 		for (int i = 0; i < length; i++) {
-			buffer.append(Signature.toString(parameterTypes[i]));
+			buffer.append(Signature.toString(paramTypes[i]));
 			if (i < length - 1) {
 				buffer.append(", "); //$NON-NLS-1$
 			}
@@ -265,16 +275,18 @@
 	buffer.append(")"); //$NON-NLS-1$
 	return buffer.toString();
 }
-/**
+/*
  * @private Debugging purposes
  */
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
 	buffer.append(this.tabString(tab));
 	if (info == null) {
 		buffer.append(getElementName());
+		toStringParameters(buffer);
 		buffer.append(" (not open)"); //$NON-NLS-1$
 	} else if (info == NO_INFO) {
 		buffer.append(getElementName());
+		toStringParameters(buffer);
 	} else {
 		try {
 			if (Flags.isStatic(this.getFlags())) {
@@ -285,21 +297,24 @@
 				buffer.append(' ');
 			}
 			buffer.append(this.getElementName());
-			buffer.append('(');
-			String[] parameterTypes = this.getParameterTypes();
-			int length;
-			if (parameterTypes != null && (length = parameterTypes.length) > 0) {
-				for (int i = 0; i < length; i++) {
-					buffer.append(Signature.toString(parameterTypes[i]));
-					if (i < length - 1) {
-						buffer.append(", "); //$NON-NLS-1$
-					}
-				}
-			}
-			buffer.append(')');
+			toStringParameters(buffer);
 		} catch (JavaModelException e) {
 			buffer.append("<JavaModelException in toString of " + getElementName()); //$NON-NLS-1$
 		}
 	}
 }
+private void toStringParameters(StringBuffer buffer) {
+	buffer.append('(');
+	String[] parameters = this.getParameterTypes();
+	int length;
+	if (parameters != null && (length = parameters.length) > 0) {
+		for (int i = 0; i < length; i++) {
+			buffer.append(Signature.toString(parameters[i]));
+			if (i < length - 1) {
+				buffer.append(", "); //$NON-NLS-1$
+			}
+		}
+	}
+	buffer.append(')');
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
index 4de1ca1..50c07b0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
@@ -12,6 +12,8 @@
 
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.StringTokenizer;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.*;
@@ -19,7 +21,9 @@
 import org.eclipse.jdt.core.search.SearchEngine;
 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Parent is an IClassFile.
@@ -27,7 +31,7 @@
  * @see IType
  */
 
-public class BinaryType extends BinaryMember implements IType {
+public class BinaryType extends BinaryMember implements IType, SuffixConstants {
 	
 	private static final IField[] NO_FIELDS = new IField[0];
 	private static final IMethod[] NO_METHODS = new IMethod[0];
@@ -35,118 +39,98 @@
 	private static final IInitializer[] NO_INITIALIZERS = new IInitializer[0];
 	private static final String[] NO_STRINGS = new String[0];
 	
-protected BinaryType(IJavaElement parent, String name) {
-	super(TYPE, parent, name);
+protected BinaryType(JavaElement parent, String name) {
+	super(parent, name);
 	Assert.isTrue(name.indexOf('.') == -1);
 }
-/**
- * @see IOpenable#close()
- */
-public void close() throws JavaModelException {
-	
-	Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this);
-	if (info != null) {
-		boolean wasVerbose = false;
-		try {
-			if (JavaModelManager.VERBOSE) {
-				System.out.println("CLOSING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors());  //$NON-NLS-1$//$NON-NLS-2$
-				wasVerbose = true;
-				JavaModelManager.VERBOSE = false;
-			}
-			ClassFileInfo cfi = getClassFileInfo();
-			if (cfi.hasReadBinaryChildren()) {
-				try {
-					IJavaElement[] children = getChildren();
-					for (int i = 0, size = children.length; i < size; ++i) {
-						JavaElement child = (JavaElement) children[i];
-						if (child instanceof BinaryType) {
-							((IOpenable)child.getParent()).close();
-						} else {
-							child.close();
-						}
-					}
-				} catch (JavaModelException e) {
-				}
-			}
-			closing(info);
-			JavaModelManager.getJavaModelManager().removeInfo(this);
-			if (JavaModelManager.VERBOSE){
-				System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
-				System.out.println("-> Openable cache filling ratio = " + JavaModelManager.getJavaModelManager().cache.openableFillingRatio() + "%"); //$NON-NLS-1$//$NON-NLS-2$
-			}
-		} finally {
-			JavaModelManager.VERBOSE = wasVerbose;
-		}
-	}
-}
-/**
+/*
  * Remove my cached children from the Java Model
  */
 protected void closing(Object info) throws JavaModelException {
 	ClassFileInfo cfi = getClassFileInfo();
 	cfi.removeBinaryChildren();
-	if (JavaModelManager.VERBOSE){
-		System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
-		System.out.println("-> Openable cache filling ratio = " + JavaModelManager.getJavaModelManager().cache.openableFillingRatio() + "%"); //$NON-NLS-1$//$NON-NLS-2$
-	}
 }
-/**
+/*
  * @see IType#codeComplete(char[], int, int, char[][], char[][], int[], boolean, ICompletionRequestor)
  */
 public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor) throws JavaModelException {
+	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY);
+}
+/*
+ * @see IType#codeComplete(char[], int, int, char[][], char[][], int[], boolean, ICompletionRequestor, WorkingCopyOwner)
+ */
+public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
 	if (requestor == null) {
-		throw new IllegalArgumentException(Util.bind("codeAssist.nullRequestor")); //$NON-NLS-1$
+		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
 	}
 	JavaProject project = (JavaProject) getJavaProject();
 	SearchableEnvironment environment = (SearchableEnvironment) project.getSearchableNameEnvironment();
 	NameLookup nameLookup = project.getNameLookup();
-	CompletionEngine engine = new CompletionEngine(environment, new CompletionRequestorWrapper(requestor,nameLookup), project.getOptions(true), project);
-	
+	CompletionRequestorWrapper requestorWrapper = new CompletionRequestorWrapper(requestor,nameLookup);
+	CompletionEngine engine = new CompletionEngine(environment, requestorWrapper, project.getOptions(true), project);
+	requestorWrapper.completionEngine = engine;
+
 	String source = getClassFile().getSource();
 	if (source != null && insertion > -1 && insertion < source.length()) {
-		String encoding = project.getOption(JavaCore.CORE_ENCODING, true); 
-		
-		char[] prefix = CharOperation.concat(source.substring(0, insertion).toCharArray(), new char[]{'{'});
-		char[] suffix =  CharOperation.concat(new char[]{'}'}, source.substring(insertion).toCharArray());
-		char[] fakeSource = CharOperation.concat(prefix, snippet, suffix);
-		
-		BasicCompilationUnit cu = 
-			new BasicCompilationUnit(
-				fakeSource, 
-				null,
-				getElementName(),
-				encoding); 
-
-		engine.complete(cu, prefix.length + position, prefix.length);
+		try {
+			// set the units to look inside
+			JavaModelManager manager = JavaModelManager.getJavaModelManager();
+			ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+			nameLookup.setUnitsToLookInside(workingCopies);
+	
+			// code complete
+			String encoding = project.getOption(JavaCore.CORE_ENCODING, true); 
+			
+			char[] prefix = CharOperation.concat(source.substring(0, insertion).toCharArray(), new char[]{'{'});
+			char[] suffix =  CharOperation.concat(new char[]{'}'}, source.substring(insertion).toCharArray());
+			char[] fakeSource = CharOperation.concat(prefix, snippet, suffix);
+			
+			BasicCompilationUnit cu = 
+				new BasicCompilationUnit(
+					fakeSource, 
+					null,
+					getElementName(),
+					encoding); 
+	
+			engine.complete(cu, prefix.length + position, prefix.length);
+		} finally {
+			if (nameLookup != null) {
+				nameLookup.setUnitsToLookInside(null);
+			}
+		}
 	} else {
 		engine.complete(this, snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
 	}
 }
-/**
+/*
  * @see IType#createField(String, IJavaElement, boolean, IProgressMonitor)
  */
 public IField createField(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws JavaModelException {
 	throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
 }
-/**
+/*
  * @see IType#createInitializer(String, IJavaElement, IProgressMonitor)
  */
 public IInitializer createInitializer(String contents, IJavaElement sibling, IProgressMonitor monitor) throws JavaModelException {
 	throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
 }
-/**
+/*
  * @see IType#createMethod(String, IJavaElement, boolean, IProgressMonitor)
  */
 public IMethod createMethod(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws JavaModelException {
 	throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
 }
-/**
+/*
  * @see IType#createType(String, IJavaElement, boolean, IProgressMonitor)
  */
 public IType createType(String contents, IJavaElement sibling, boolean force, IProgressMonitor monitor) throws JavaModelException {
 	throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
 }
-/**
+public boolean equals(Object o) {
+	if (!(o instanceof BinaryType)) return false;
+	return super.equals(o);
+}
+/*
  * @see IType#findMethods(IMethod)
  */
 public IMethod[] findMethods(IMethod method) {
@@ -157,7 +141,7 @@
 		return null;
 	}
 }
-/**
+/*
  * @see IParent#getChildren()
  */
 public IJavaElement[] getChildren() throws JavaModelException {
@@ -168,13 +152,29 @@
 	}
 	// get children
 	ClassFileInfo cfi = getClassFileInfo();
-	return cfi.getBinaryChildren();
+	if (cfi.binaryChildren == null) {
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		boolean hadTemporaryCache = manager.hasTemporaryCache();
+		try {
+			Object info = manager.getInfo(this);
+			HashMap newElements = manager.getTemporaryCache();
+			cfi.readBinaryChildren(newElements, (IBinaryType)info);
+			if (!hadTemporaryCache) {
+				manager.putInfos(this, newElements);
+			}
+		} finally {
+			if (!hadTemporaryCache) {
+				manager.resetTemporaryCache();
+			}
+		}
+	}
+	return cfi.binaryChildren;
 }
 protected ClassFileInfo getClassFileInfo() throws JavaModelException {
-	ClassFile cf = (ClassFile) fParent;
+	ClassFile cf = (ClassFile)this.parent;
 	return (ClassFileInfo) cf.getElementInfo();
 }
-/**
+/*
  * @see IMember#getDeclaringType()
  */
 public IType getDeclaringType() {
@@ -194,7 +194,7 @@
 				return null;
 			} 
 			
-			return getPackageFragment().getClassFile(new String(enclosingTypeName) + ".class").getType(); //$NON-NLS-1$;
+			return getPackageFragment().getClassFile(new String(enclosingTypeName) + SUFFIX_STRING_class).getType();
 		} catch (JavaModelException npe) {
 			return null;
 		}
@@ -217,21 +217,27 @@
 			return null;
 		} else {
 			String enclosingName = classFileName.substring(0, lastDollar);
-			String enclosingClassFileName = enclosingName + ".class"; //$NON-NLS-1$
+			String enclosingClassFileName = enclosingName + SUFFIX_STRING_class;
 			return 
 				new BinaryType(
-					this.getPackageFragment().getClassFile(enclosingClassFileName),
+					(JavaElement)this.getPackageFragment().getClassFile(enclosingClassFileName),
 					enclosingName.substring(enclosingName.lastIndexOf('$')+1));
 		}
 	}
 }
-/**
+/*
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return TYPE;
+}
+/*
  * @see IType#getField(String name)
  */
-public IField getField(String name) {
-	return new BinaryField(this, name);
+public IField getField(String fieldName) {
+	return new BinaryField(this, fieldName);
 }
-/**
+/*
  * @see IType#getFields()
  */
 public IField[] getFields() throws JavaModelException {
@@ -245,20 +251,20 @@
 		return array;
 	}
 }
-/**
+/*
  * @see IMember#getFlags()
  */
 public int getFlags() throws JavaModelException {
 	IBinaryType info = (IBinaryType) getElementInfo();
 	return info.getModifiers();
 }
-/**
+/*
  * @see IType#getFullyQualifiedName()
  */
 public String getFullyQualifiedName() {
 	return this.getFullyQualifiedName('$');
 }
-/**
+/*
  * @see IType#getFullyQualifiedName(char enclosingTypeSeparator)
  */
 public String getFullyQualifiedName(char enclosingTypeSeparator) {
@@ -268,25 +274,99 @@
 	}
 	return packageName + '.' + getTypeQualifiedName(enclosingTypeSeparator);
 }
-/**
+/*
+ * @see JavaElement
+ */
+public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner workingCopyOwner) {
+	switch (token.charAt(0)) {
+		case JEM_COUNT:
+			return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
+		case JEM_FIELD:
+			String fieldName = memento.nextToken();
+			JavaElement field = (JavaElement)getField(fieldName);
+			return field.getHandleFromMemento(memento, workingCopyOwner);
+		case JEM_INITIALIZER:
+			String count = memento.nextToken();
+			JavaElement initializer = (JavaElement)getInitializer(Integer.parseInt(count));
+			return initializer.getHandleFromMemento(memento, workingCopyOwner);
+		case JEM_METHOD:
+			String selector = memento.nextToken();
+			ArrayList params = new ArrayList();
+			nextParam: while (memento.hasMoreTokens()) {
+				token = memento.nextToken();
+				switch (token.charAt(0)) {
+					case JEM_TYPE:
+						break nextParam;
+					case JEM_METHOD:
+						String param = memento.nextToken();
+						StringBuffer buffer = new StringBuffer();
+						while (Signature.C_ARRAY == param.charAt(0)) {
+							buffer.append(Signature.C_ARRAY);
+							param = memento.nextToken();
+						}
+						params.add(buffer.toString() + param);
+						break;
+					default:
+						break nextParam;
+				}
+			}
+			String[] parameters = new String[params.size()];
+			params.toArray(parameters);
+			JavaElement method = (JavaElement)getMethod(selector, parameters);
+			if (token != null) {
+				switch (token.charAt(0)) {
+					case JEM_TYPE:
+					case JEM_LOCALVARIABLE:
+						return method.getHandleFromMemento(token, memento, workingCopyOwner);
+					default:
+						return method;
+				}
+			} else {
+				return method;
+			}
+		case JEM_TYPE:
+			String typeName;
+			if (memento.hasMoreTokens()) {
+				typeName = memento.nextToken();
+				char firstChar = typeName.charAt(0);
+				if (firstChar == JEM_FIELD || firstChar == JEM_INITIALIZER || firstChar == JEM_METHOD || firstChar == JEM_TYPE || firstChar == JEM_COUNT) {
+					token = typeName;
+					typeName = ""; //$NON-NLS-1$
+				} else {
+					token = null;
+				}
+			} else {
+				typeName = ""; //$NON-NLS-1$
+				token = null;
+			}
+			JavaElement type = (JavaElement)getType(typeName);
+			if (token == null) {
+				return type.getHandleFromMemento(memento, workingCopyOwner);
+			} else {
+				return type.getHandleFromMemento(token, memento, workingCopyOwner);
+			}
+	}
+	return null;
+}
+/*
  * @see IType#getInitializer(int occurrenceCount)
  */
-public IInitializer getInitializer(int occurrenceCount) {
-	return new Initializer(this, occurrenceCount);
+public IInitializer getInitializer(int count) {
+	return new Initializer(this, count);
 }
-/**
+/*
  * @see IType#getInitializers()
  */
 public IInitializer[] getInitializers() {
 	return NO_INITIALIZERS;
 }
-/**
+/*
  * @see IType#getMethod(String name, String[] parameterTypeSignatures)
  */
-public IMethod getMethod(String name, String[] parameterTypeSignatures) {
-	return new BinaryMethod(this, name, parameterTypeSignatures);
+public IMethod getMethod(String selector, String[] parameterTypeSignatures) {
+	return new BinaryMethod(this, selector, parameterTypeSignatures);
 }
-/**
+/*
  * @see IType#getMethods()
  */
 public IMethod[] getMethods() throws JavaModelException {
@@ -300,23 +380,23 @@
 		return array;
 	}
 }
-/**
+/*
  * @see IType#getPackageFragment()
  */
 public IPackageFragment getPackageFragment() {
-	IJavaElement parent = fParent;
-	while (parent != null) {
-		if (parent.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
-			return (IPackageFragment) parent;
+	IJavaElement parentElement = this.parent;
+	while (parentElement != null) {
+		if (parentElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
+			return (IPackageFragment)parentElement;
 		}
 		else {
-			parent = parent.getParent();
+			parentElement = parentElement.getParent();
 		}
 	}
 	Assert.isTrue(false);  // should not happen
 	return null;
 }
-/**
+/*
  * @see IType#getSuperclassName()
  */
 public String getSuperclassName() throws JavaModelException {
@@ -327,7 +407,7 @@
 	}
 	return new String(ClassFile.translatedName(superclassName));
 }
-/**
+/*
  * @see IType#getSuperInterfaceNames()
  */
 public String[] getSuperInterfaceNames() throws JavaModelException {
@@ -344,20 +424,20 @@
 	}
 	return strings;
 }
-/**
+/*
  * @see IType#getType(String)
  */
-public IType getType(String name) {
-	IClassFile classFile= getPackageFragment().getClassFile(getTypeQualifiedName() + "$" + name + ".class"); //$NON-NLS-2$ //$NON-NLS-1$
-	return new BinaryType(classFile, name);
+public IType getType(String typeName) {
+	IClassFile classFile= getPackageFragment().getClassFile(getTypeQualifiedName() + "$" + typeName + SUFFIX_STRING_class); //$NON-NLS-1$
+	return new BinaryType((JavaElement)classFile, typeName);
 }
-/**
+/*
  * @see IType#getTypeQualifiedName()
  */
 public String getTypeQualifiedName() {
 	return this.getTypeQualifiedName('$');
 }
-/**
+/*
  * @see IType#getTypeQualifiedName(char)
  */
 public String getTypeQualifiedName(char enclosingTypeSeparator) {
@@ -366,7 +446,7 @@
 		String classFileName = this.getClassFile().getElementName();
 		if (classFileName.indexOf('$') == -1) {
 			// top level class file: name of type is same as name of class file
-			return fName;
+			return this.name;
 		} else {
 			// anonymous or local class file
 			return classFileName.substring(0, classFileName.lastIndexOf('.')); // remove .class
@@ -375,10 +455,10 @@
 		return 
 			declaringType.getTypeQualifiedName(enclosingTypeSeparator)
 			+ enclosingTypeSeparator
-			+ fName;
+			+ this.name;
 	}
 }
-/**
+/*
  * @see IType#getTypes()
  */
 public IType[] getTypes() throws JavaModelException {
@@ -392,26 +472,26 @@
 		return array;
 	}
 }
-/**
+/*
  * @see IParent#hasChildren()
  */
 public boolean hasChildren() throws JavaModelException {
 	return getChildren().length > 0;
 }
-/**
+/*
  * @see IType#isAnonymous()
  */
 public boolean isAnonymous() throws JavaModelException {
 	IBinaryType info = (IBinaryType) getElementInfo();
 	return info.isAnonymous();
 }
-/**
+/*
  * @see IType#isClass()
  */
 public boolean isClass() throws JavaModelException {
 	return !isInterface();
 }
-/**
+/*
  * @see IType#isInterface()
  */
 public boolean isInterface() throws JavaModelException {
@@ -419,56 +499,141 @@
 	return info.isInterface();
 }
 
-/**
+/*
  * @see IType#isLocal()
  */
 public boolean isLocal() throws JavaModelException {
 	IBinaryType info = (IBinaryType) getElementInfo();
 	return info.isLocal();
 }
-/**
+/*
  * @see IType#isMember()
  */
 public boolean isMember() throws JavaModelException {
 	IBinaryType info = (IBinaryType) getElementInfo();
 	return info.isMember();
 }
-/**
+/*
  * @see IType
  */
 public ITypeHierarchy loadTypeHierachy(InputStream input, IProgressMonitor monitor) throws JavaModelException {
-	return TypeHierarchy.load(this, input);
+	return loadTypeHierachy(input, DefaultWorkingCopyOwner.PRIMARY, monitor);
 }
-/**
+/*
+ * @see IType
+ */
+public ITypeHierarchy loadTypeHierachy(InputStream input, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
+	return TypeHierarchy.load(this, input, owner);
+}
+/*
  * @see IType#newSupertypeHierarchy(IProgressMonitor monitor)
  */
 public ITypeHierarchy newSupertypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
-	return this.newSupertypeHierarchy(null, monitor);
+	return this.newSupertypeHierarchy(DefaultWorkingCopyOwner.PRIMARY, monitor);
+}
+/*
+ *@see IType#newSupertypeHierarchy(ICompilationUnit[], IProgressMonitor monitor)
+ */
+public ITypeHierarchy newSupertypeHierarchy(
+	ICompilationUnit[] workingCopies,
+	IProgressMonitor monitor)
+	throws JavaModelException {
+	
+	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), false);
+	runOperation(op, monitor);
+	return op.getResult();
 }
 /**
+ * @param workingCopies the working copies that take precedence over their original compilation units
+ * @param monitor the given progress monitor
+ * @return a type hierarchy for this type containing this type and all of its supertypes
+ * @exception JavaModelException if this element does not exist or if an
+ *		exception occurs while accessing its corresponding resource.
+ *
  * @see IType#newSupertypeHierarchy(IWorkingCopy[], IProgressMonitor)
+ * @deprecated
  */
 public ITypeHierarchy newSupertypeHierarchy(
 	IWorkingCopy[] workingCopies,
 	IProgressMonitor monitor)
 	throws JavaModelException {
-		
+	
+	ICompilationUnit[] copies;
+	if (workingCopies == null) {
+		copies = null;
+	} else {
+		int length = workingCopies.length;
+		System.arraycopy(workingCopies, 0, copies = new ICompilationUnit[length], 0, length);
+	}
+	return newSupertypeHierarchy(copies, monitor);
+}
+/*
+ * @see IType#newSupertypeHierarchy(WorkingCopyOwner, IProgressMonitor)
+ */
+public ITypeHierarchy newSupertypeHierarchy(
+	WorkingCopyOwner owner,
+	IProgressMonitor monitor)
+	throws JavaModelException {
+
+	ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
 	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), false);
 	runOperation(op, monitor);
 	return op.getResult();
 }
-
+/*
+ * @see IType#newTypeHierarchy(IJavaProject, IProgressMonitor)
+ */
+public ITypeHierarchy newTypeHierarchy(IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
+	return newTypeHierarchy(project, DefaultWorkingCopyOwner.PRIMARY, monitor);
+}
+/*
+ * @see IType#newTypeHierarchy(IJavaProject, WorkingCopyOwner, IProgressMonitor)
+ */
+public ITypeHierarchy newTypeHierarchy(IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
+	if (project == null) {
+		throw new IllegalArgumentException(Util.bind("hierarchy.nullProject")); //$NON-NLS-1$
+	}
+	ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
+	ICompilationUnit[] projectWCs = null;
+	if (workingCopies != null) {
+		int length = workingCopies.length;
+		projectWCs = new ICompilationUnit[length];
+		int index = 0;
+		for (int i = 0; i < length; i++) {
+			ICompilationUnit wc = workingCopies[i];
+			if (project.equals(wc.getJavaProject())) {
+				projectWCs[index++] = wc;
+			}
+		}
+		if (index != length) {
+			System.arraycopy(projectWCs, 0, projectWCs = new ICompilationUnit[index], 0, index);
+		}
+	}
+	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(
+		this, 
+		projectWCs,
+		project, 
+		true);
+	runOperation(op, monitor);
+	return op.getResult();
+}
 /**
+ * @param monitor the given progress monitor
+ * @exception JavaModelException if this element does not exist or if an
+ *		exception occurs while accessing its corresponding resource.
+ * @return a type hierarchy for this type containing
+ * 
  * @see IType#newTypeHierarchy(IProgressMonitor monitor)
+ * @deprecated
  */
 public ITypeHierarchy newTypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
 	return newTypeHierarchy((IWorkingCopy[])null, monitor);
 }
-/**
- * @see IType#newTypeHierarchy(IWorkingCopy[], IProgressMonitor)
+/*
+ * @see IType#newTypeHierarchy(ICompilationUnit[], IProgressMonitor)
  */
 public ITypeHierarchy newTypeHierarchy(
-	IWorkingCopy[] workingCopies,
+	ICompilationUnit[] workingCopies,
 	IProgressMonitor monitor)
 	throws JavaModelException {
 
@@ -476,50 +641,52 @@
 	runOperation(op, monitor);
 	return op.getResult();
 }
+/**
+ * @see IType#newTypeHierarchy(IWorkingCopy[], IProgressMonitor)
+ * @deprecated
+ */
+public ITypeHierarchy newTypeHierarchy(
+	IWorkingCopy[] workingCopies,
+	IProgressMonitor monitor)
+	throws JavaModelException {
 
-/**
- * @see IType#newTypeHierarchy(IJavaProject project, IProgressMonitor monitor)
- */
-public ITypeHierarchy newTypeHierarchy(IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
-	if (project == null) {
-		throw new IllegalArgumentException(Util.bind("hierarchy.nullProject")); //$NON-NLS-1$
+	ICompilationUnit[] copies;
+	if (workingCopies == null) {
+		copies = null;
+	} else {
+		int length = workingCopies.length;
+		System.arraycopy(workingCopies, 0, copies = new ICompilationUnit[length], 0, length);
 	}
-	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(
-		this, 
-		(IWorkingCopy[])null, // no working copies
-		project, 
-		true);
+	return newTypeHierarchy(copies, monitor);
+}
+/*
+ * @see IType#newTypeHierarchy(WorkingCopyOwner, IProgressMonitor)
+ */
+public ITypeHierarchy newTypeHierarchy(
+	WorkingCopyOwner owner,
+	IProgressMonitor monitor)
+	throws JavaModelException {
+		
+	ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
+	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), true);
 	runOperation(op, monitor);
-	return op.getResult();
+	return op.getResult();	
 }
-/**
- * Removes all cached info from the Java Model, including all children,
- * but does not close this element.
+/*
+ * @see IType#resolveType(String)
  */
-protected void removeInfo() {
-	Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this);
-	if (info != null) {
-		try {
-			IJavaElement[] children = getChildren();
-			for (int i = 0, size = children.length; i < size; ++i) {
-				JavaElement child = (JavaElement) children[i];
-				child.removeInfo();
-			}
-		} catch (JavaModelException e) {
-		}
-		JavaModelManager.getJavaModelManager().removeInfo(this);
-		try {
-			ClassFileInfo cfi = getClassFileInfo();
-			cfi.removeBinaryChildren();
-		} catch (JavaModelException npe) {
-		}
-	}
-}
-public String[][] resolveType(String typeName) throws JavaModelException {
+public String[][] resolveType(String typeName) {
 	// not implemented for binary types
 	return null;
 }
-/**
+/*
+ * @see IType#resolveType(String, WorkingCopyOwner)
+ */
+public String[][] resolveType(String typeName, WorkingCopyOwner owner) {
+	// not implemented for binary types
+	return null;
+}
+/*
  * @private Debugging purposes
  */
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java
index 78b6661..e9f96ec 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Buffer.java
@@ -21,6 +21,7 @@
 import org.eclipse.core.runtime.ISafeRunnable;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * @see IBuffer
@@ -31,14 +32,14 @@
 	protected char[] contents;
 	protected ArrayList changeListeners;
 	protected IOpenable owner;
-	protected int gapStart= -1;
-	protected int gapEnd= -1;
+	protected int gapStart = -1;
+	protected int gapEnd = -1;
 
-	protected Object lock= new Object();
+	protected Object lock = new Object();
 
-	protected static final int F_HAS_UNSAVED_CHANGES= 1;
-	protected static final int F_IS_READ_ONLY= 2;
-	protected static final int F_IS_CLOSED= 4;
+	protected static final int F_HAS_UNSAVED_CHANGES = 1;
+	protected static final int F_IS_READ_ONLY = 2;
+	protected static final int F_IS_CLOSED = 4;
 
 /**
  * Creates a new buffer on an underlying resource.
@@ -71,10 +72,13 @@
 			return;
 		}
 		int length = getLength();
-		moveAndResizeGap(length, text.length);
-		System.arraycopy(text, 0, this.contents, length, text.length);
-		this.gapStart += text.length;
-		this.flags |= F_HAS_UNSAVED_CHANGES;
+		synchronized(this.lock) {
+		    if (this.contents == null) return;
+			moveAndResizeGap(length, text.length);
+			System.arraycopy(text, 0, this.contents, length, text.length);
+			this.gapStart += text.length;
+			this.flags |= F_HAS_UNSAVED_CHANGES;
+		}
 		notifyChanged(new BufferChangedEvent(this, length, 0, new String(text)));
 	}
 }
@@ -91,7 +95,7 @@
 /**
  * @see IBuffer
  */
-public void close() throws IllegalArgumentException {
+public void close() {
 	BufferChangedEvent event = null;
 	synchronized (this.lock) {
 		if (isClosed())
@@ -108,6 +112,7 @@
  */
 public char getChar(int position) {
 	synchronized (this.lock) {
+	    if (this.contents == null) return Character.MIN_VALUE;
 		if (position < this.gapStart) {
 			return this.contents[position];
 		}
@@ -119,8 +124,8 @@
  * @see IBuffer
  */
 public char[] getCharacters() {
-	if (this.contents == null) return null;
 	synchronized (this.lock) {
+		if (this.contents == null) return null;
 		if (this.gapStart < 0) {
 			return this.contents;
 		}
@@ -144,6 +149,7 @@
  */
 public int getLength() {
 	synchronized (this.lock) {
+		if (this.contents == null) return -1;
 		int length = this.gapEnd - this.gapStart;
 		return (this.contents.length - length);
 	}
@@ -158,9 +164,8 @@
  * @see IBuffer
  */
 public String getText(int offset, int length) {
-	if (this.contents == null)
-		return ""; //$NON-NLS-1$
 	synchronized (this.lock) {
+		if (this.contents == null) return ""; //$NON-NLS-1$
 		if (offset + length < this.gapStart)
 			return new String(this.contents, offset, length);
 		if (this.gapStart < offset) {
@@ -195,11 +200,7 @@
  * @see IBuffer
  */
 public boolean isReadOnly() {
-	if (this.file == null) {
-		return (this.flags & F_IS_READ_ONLY) != 0;
-	} else {
-		return this.file.isReadOnly();
-	}
+	return (this.flags & F_IS_READ_ONLY) != 0;
 }
 /**
  * Moves the gap to location and adjust its size to the
@@ -283,6 +284,8 @@
 	if (!isReadOnly()) {
 		int textLength = text == null ? 0 : text.length;
 		synchronized (this.lock) {
+		    if (this.contents == null) return;
+		    
 			// move gap
 			moveAndResizeGap(position + length, textLength - length);
 
@@ -299,8 +302,8 @@
 				this.gapStart += textLength - length;
 				System.arraycopy(text, 0, this.contents, position, textLength);
 			}
+			this.flags |= F_HAS_UNSAVED_CHANGES;
 		}
-		this.flags |= F_HAS_UNSAVED_CHANGES;
 		String string = null;
 		if (textLength > 0) {
 			string = new String(text);
@@ -325,33 +328,35 @@
 	if (isReadOnly() || this.file == null) {
 		return;
 	}
-	synchronized (this.lock) {
-		if (!hasUnsavedChanges())
-			return;
-			
-		// use a platform operation to update the resource contents
-		try {
-			String encoding = ((IJavaElement)this.owner).getJavaProject().getOption(JavaCore.CORE_ENCODING, true);
-			String contents = this.getContents();
-			if (contents == null) return;
-			byte[] bytes = encoding == null 
-				? contents.getBytes() 
-				: contents.getBytes(encoding);
-			ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
+	if (!hasUnsavedChanges())
+		return;
+		
+	// use a platform operation to update the resource contents
+	try {
+		String encoding = ((IJavaElement)this.owner).getJavaProject().getOption(JavaCore.CORE_ENCODING, true);
+		String stringContents = this.getContents();
+		if (stringContents == null) return;
+		byte[] bytes = encoding == null 
+			? stringContents.getBytes() 
+			: stringContents.getBytes(encoding);
+		ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
 
+		if (this.file.exists()) {
 			this.file.setContents(
 				stream, 
 				force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
 				null);
-		} catch (IOException e) {
-			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
-		} catch (CoreException e) {
-			throw new JavaModelException(e);
-		}
-
-		// the resource no longer has unsaved changes
-		this.flags &= ~ (F_HAS_UNSAVED_CHANGES);
+		} else {
+			this.file.create(stream, force, null);
+		}	
+	} catch (IOException e) {
+		throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+	} catch (CoreException e) {
+		throw new JavaModelException(e);
 	}
+
+	// the resource no longer has unsaved changes
+	this.flags &= ~ (F_HAS_UNSAVED_CHANGES);
 }
 /**
  * @see IBuffer
@@ -360,8 +365,10 @@
 	// allow special case for first initialization 
 	// after creation by buffer factory
 	if (this.contents == null) {
-		this.contents = newContents;
-		this.flags &= ~ (F_HAS_UNSAVED_CHANGES);
+		synchronized (this.lock) {
+			this.contents = newContents;
+			this.flags &= ~ (F_HAS_UNSAVED_CHANGES);
+		}
 		return;
 	}
 	
@@ -370,13 +377,14 @@
 		if (newContents != null) {
 			string = new String(newContents);
 		}
-		BufferChangedEvent event = new BufferChangedEvent(this, 0, this.getLength(), string);
 		synchronized (this.lock) {
+		    if (this.contents == null) return; // ignore if buffer is closed (as per spec)
 			this.contents = newContents;
 			this.flags |= F_HAS_UNSAVED_CHANGES;
 			this.gapStart = -1;
 			this.gapEnd = -1;
 		}
+		BufferChangedEvent event = new BufferChangedEvent(this, 0, this.getLength(), string);
 		notifyChanged(event);
 	}
 }
@@ -403,14 +411,14 @@
 	buffer.append("\nIs readonly: " + this.isReadOnly()); //$NON-NLS-1$
 	buffer.append("\nIs closed: " + this.isClosed()); //$NON-NLS-1$
 	buffer.append("\nContents:\n"); //$NON-NLS-1$
-	char[] contents = this.getCharacters();
-	if (contents == null) {
+	char[] charContents = this.getCharacters();
+	if (charContents == null) {
 		buffer.append("<null>"); //$NON-NLS-1$
 	} else {
-		int length = contents.length;
+		int length = charContents.length;
 		for (int i = 0; i < length; i++) {
-			char car = contents[i];
-			switch (car) {
+			char c = charContents[i];
+			switch (c) {
 				case '\n': 
 					buffer.append("\\n\n"); //$NON-NLS-1$
 					break;
@@ -423,7 +431,7 @@
 					}
 					break;
 				default:
-					buffer.append(car);
+					buffer.append(c);
 					break;
 			}
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferCache.java
index 72716fb..b17beec 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferCache.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferCache.java
@@ -38,7 +38,10 @@
  */
 protected boolean close(LRUCacheEntry entry) {
 	IBuffer buffer= (IBuffer) entry._fValue;
-	if (buffer.hasUnsavedChanges()) {
+	
+	// prevent buffer that have unsaved changes or working copy buffer to be removed
+	// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=39311
+	if (!((Openable)buffer.getOwner()).canBufferBeRemovedFromCache(buffer)) {
 		return false;
 	} else {
 		buffer.close();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferFactoryWrapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferFactoryWrapper.java
new file mode 100644
index 0000000..377dc90
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferFactoryWrapper.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.IBuffer;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+
+/**
+ * Wraps an IBufferFactory.
+ * TODO remove when removing IBufferFactory
+ * @deprecated
+ */
+public class BufferFactoryWrapper extends WorkingCopyOwner {
+
+	public org.eclipse.jdt.core.IBufferFactory factory;
+		
+	private BufferFactoryWrapper(org.eclipse.jdt.core.IBufferFactory factory) {
+		this.factory = factory;
+	}
+	
+	public static WorkingCopyOwner create(org.eclipse.jdt.core.IBufferFactory factory) {
+		if (factory != null && factory == DefaultWorkingCopyOwner.PRIMARY.factory) {
+			return DefaultWorkingCopyOwner.PRIMARY;
+		} else {
+			return new BufferFactoryWrapper(factory);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.WorkingCopyOwner#createBuffer(org.eclipse.jdt.core.ICompilationUnit)
+	 */
+	public IBuffer createBuffer(ICompilationUnit workingCopy) {
+		if (this.factory == null) return super.createBuffer(workingCopy);
+		return this.factory.createBuffer(workingCopy);
+	}	
+	
+	public boolean equals(Object obj) {
+		if (!(obj instanceof BufferFactoryWrapper)) return false;
+		BufferFactoryWrapper other = (BufferFactoryWrapper)obj;
+		if (this.factory == null) return other.factory == null;
+		return this.factory.equals(other.factory);
+	}
+	public int hashCode() {
+		if (this.factory == null) return 0;
+		return this.factory.hashCode();
+	}
+	public String toString() {
+		return "FactoryWrapper for " + this.factory; //$NON-NLS-1$
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferManager.java
index 4672244..0c176f0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferManager.java
@@ -10,12 +10,12 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.text.NumberFormat;
 import java.util.Enumeration;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.jdt.core.IBuffer;
-import org.eclipse.jdt.core.IBufferFactory;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IOpenable;
 
@@ -23,30 +23,42 @@
  * The buffer manager manages the set of open buffers.
  * It implements an LRU cache of buffers.
  */
-public class BufferManager implements IBufferFactory {
+public class BufferManager {
 
 	protected static BufferManager DEFAULT_BUFFER_MANAGER;
+	protected static boolean VERBOSE;
 
 	/**
 	 * LRU cache of buffers. The key and value for an entry
 	 * in the table is the identical buffer.
 	 */
 	protected OverflowingLRUCache openBuffers = new BufferCache(60);
+	
+	/**
+	 * @deprecated
+	 */
+	protected org.eclipse.jdt.core.IBufferFactory defaultBufferFactory = new org.eclipse.jdt.core.IBufferFactory() {
+	    /**
+	     * @deprecated
+	     */
+		public IBuffer createBuffer(IOpenable owner) {
+			return BufferManager.this.createBuffer(owner);
+		}
+	};
 
 /**
- * Creates a new buffer manager.
- */
-public BufferManager() {
-}
-/**
  * Adds a buffer to the table of open buffers.
  */
 protected void addBuffer(IBuffer buffer) {
-	openBuffers.put(buffer.getOwner(), buffer);
+	if (VERBOSE) {
+		String owner = ((Openable)buffer.getOwner()).toStringWithAncestors();
+		System.out.println("Adding buffer for " + owner); //$NON-NLS-1$
+	}
+	this.openBuffers.put(buffer.getOwner(), buffer);
+	if (VERBOSE) {
+		System.out.println("-> Buffer cache filling ratio = " + NumberFormat.getInstance().format(this.openBuffers.fillingRatio()) + "%"); //$NON-NLS-1$//$NON-NLS-2$
+	}
 }
-/**
- * @see IBufferFactory#createBuffer(IOpenable)
- */
 public IBuffer createBuffer(IOpenable owner) {
 	IJavaElement element = (IJavaElement)owner;
 	IResource resource = element.getResource();
@@ -56,14 +68,13 @@
 			owner, 
 			element.isReadOnly());
 }
-
 /**
  * Returns the open buffer associated with the given owner,
  * or <code>null</code> if the owner does not have an open
  * buffer associated with it.
  */
 public IBuffer getBuffer(IOpenable owner) {
-	return (IBuffer)openBuffers.get(owner);
+	return (IBuffer)this.openBuffers.get(owner);
 }
 /**
  * Returns the default buffer manager.
@@ -76,9 +87,10 @@
 }
 /**
  * Returns the default buffer factory.
+ * @deprecated
  */
-public IBufferFactory getDefaultBufferFactory() {
-	return this;
+public org.eclipse.jdt.core.IBufferFactory getDefaultBufferFactory() {
+	return this.defaultBufferFactory;
 }
 /**
  * Returns an enumeration of all open buffers.
@@ -89,17 +101,23 @@
  * @return Enumeration of IBuffer
  */
 public Enumeration getOpenBuffers() {
-	synchronized (openBuffers) {
-		openBuffers.shrink();
-		return openBuffers.elements();
+	synchronized (this.openBuffers) {
+		this.openBuffers.shrink();
+		return this.openBuffers.elements();
 	}
 }
 
-
 /**
  * Removes a buffer from the table of open buffers.
  */
 protected void removeBuffer(IBuffer buffer) {
-	openBuffers.remove(buffer.getOwner());
+	if (VERBOSE) {
+		String owner = ((Openable)buffer.getOwner()).toStringWithAncestors();
+		System.out.println("Removing buffer for " + owner); //$NON-NLS-1$
+	}
+	this.openBuffers.remove(buffer.getOwner());
+	if (VERBOSE) {
+		System.out.println("-> Buffer cache filling ratio = " + NumberFormat.getInstance().format(this.openBuffers.fillingRatio()) + "%"); //$NON-NLS-1$//$NON-NLS-2$
+	}
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
index a5435b6..f106563 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
@@ -12,26 +12,28 @@
 
 import java.io.IOException;
 import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
 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.Path;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IBuffer;
-import org.eclipse.jdt.core.IBufferFactory;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.ICompletionRequestor;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModelMarker;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
-import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.IParent;
@@ -43,29 +45,61 @@
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * @see IClassFile
  */
 
-public class ClassFile extends Openable implements IClassFile {
-	protected BinaryType fBinaryType = null;
+public class ClassFile extends Openable implements IClassFile, SuffixConstants {
+	protected BinaryType binaryType = null;
+	private boolean checkAutomaticSourceMapping;
 /*
  * Creates a handle to a class file.
- *
- * @exception IllegalArgumentExcpetion if the name does not end with ".class"
  */
-protected ClassFile(IPackageFragment parent, String name) {
-	super(CLASS_FILE, parent, name);
-	if (!Util.isClassFileName(name)) {
-		throw new IllegalArgumentException(Util.bind("element.invalidClassFileName")); //$NON-NLS-1$
-	}
+protected ClassFile(PackageFragment parent, String name) {
+	super(parent, name);
+	this.checkAutomaticSourceMapping = false;
 }
 
 /**
+ * Creates the children elements for this class file adding the resulting
+ * new handles and info objects to the newElements table. Returns true
+ * if successful, or false if an error is encountered parsing the class file.
+ * 
+ * @see Openable
+ * @see Signature
+ */
+protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
+	// check whether the class file can be opened
+	if (!isValidClassFile()) throw newNotPresentException();
+	if (underlyingResource != null && !underlyingResource.isAccessible()) throw newNotPresentException();
+
+	IBinaryType typeInfo = getBinaryTypeInfo((IFile) underlyingResource);
+	if (typeInfo == null) {
+		// The structure of a class file is unknown if a class file format errors occurred
+		//during the creation of the diet class file representative of this ClassFile.
+		info.setChildren(new IJavaElement[] {});
+		return false;
+	}
+
+	// Make the type
+	IType type = new BinaryType(this, new String(simpleName(typeInfo.getName())));
+	info.addChild(type);
+	newElements.put(type, typeInfo);
+	return true;
+}
+/**
  * @see ICodeAssist#codeComplete(int, ICompletionRequestor)
  */
 public void codeComplete(int offset, ICompletionRequestor requestor) throws JavaModelException {
+	codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY);
+}
+/**
+ * @see ICodeAssist#codeComplete(int, ICompletionRequestor, WorkingCopyOwner)
+ */
+public void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
 	String source = getSource();
 	if (source != null) {
 		String encoding = this.getJavaProject().getOption(JavaCore.CORE_ENCODING, true);
@@ -74,25 +108,27 @@
 			new BasicCompilationUnit(
 				getSource().toCharArray(), 
 				null,
-				elementName.substring(0, elementName.length()-".class".length()) + ".java", //$NON-NLS-1$ //$NON-NLS-2$
+				elementName.substring(0, elementName.length()-SUFFIX_STRING_class.length()) + SUFFIX_STRING_java,
 				encoding); 
-		codeComplete(cu, cu, offset, requestor);
+		codeComplete(cu, cu, offset, requestor, owner);
 	}
 }
 /**
  * @see ICodeAssist#codeSelect(int, int)
  */
 public IJavaElement[] codeSelect(int offset, int length) throws JavaModelException {
+	return codeSelect(offset, length, DefaultWorkingCopyOwner.PRIMARY);
+}
+/**
+ * @see ICodeAssist#codeSelect(int, int, WorkingCopyOwner)
+ */
+public IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner owner) throws JavaModelException {
 	IBuffer buffer = getBuffer();
 	char[] contents;
 	if (buffer != null && (contents = buffer.getCharacters()) != null) {
-		IType current = this.getType();
-		IType parent;
-		while ((parent = current.getDeclaringType()) != null){
-			current = parent;
-		}
-		BasicCompilationUnit cu = new BasicCompilationUnit(contents, null, current.getElementName() + ".java", null); //$NON-NLS-1$
-		return super.codeSelect(cu, offset, length);
+	    String topLevelTypeName = getTopLevelTypeName();
+		BasicCompilationUnit cu = new BasicCompilationUnit(contents, null, topLevelTypeName + SUFFIX_STRING_java, null);
+		return super.codeSelect(cu, offset, length, owner);
 	} else {
 		//has no associated souce
 		return new IJavaElement[] {};
@@ -101,9 +137,18 @@
 /**
  * Returns a new element info for this element.
  */
-protected OpenableElementInfo createElementInfo() {
+protected Object createElementInfo() {
 	return new ClassFileInfo(this);
 }
+public boolean equals(Object o) {
+	if (!(o instanceof ClassFile)) return false;
+	return super.equals(o);
+}
+public boolean exists() {
+	if (!isValidClassFile()) return false;
+	return super.exists();
+}
+
 /**
  * Finds the deepest <code>IJavaElement</code> in the hierarchy of
  * <code>elt</elt>'s children (including <code>elt</code> itself)
@@ -125,34 +170,12 @@
 				}
 			}
 		} catch (JavaModelException npe) {
+			// elt doesn't exist: return the element
 		}
 	}
 	return elt;
 }
 /**
- * Creates the children elements for this class file adding the resulting
- * new handles and info objects to the newElements table. Returns true
- * if successful, or false if an error is encountered parsing the class file.
- * 
- * @see Openable
- * @see Signature
- */
-protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
-	IBinaryType typeInfo = getBinaryTypeInfo((IFile) underlyingResource);
-	if (typeInfo == null) {
-		// The structure of a class file is unknown if a class file format errors occurred
-		//during the creation of the diet class file representative of this ClassFile.
-		info.setChildren(new IJavaElement[] {});
-		return false;
-	}
-
-	// Make the type
-	IType type = new BinaryType(this, new String(simpleName(typeInfo.getName())));
-	info.addChild(type);
-	newElements.put(type, typeInfo);
-	return true;
-}
-/**
  * Returns the <code>ClassFileReader</code>specific for this IClassFile, based
  * on its underlying resource, or <code>null</code> if unable to create
  * the diet class file.
@@ -164,7 +187,7 @@
  * @exception JavaModelException when the IFile resource or JAR is not available
  * or when this class file is not present in the JAR
  */
-private IBinaryType getBinaryTypeInfo(IFile file) throws JavaModelException {
+public IBinaryType getBinaryTypeInfo(IFile file) throws JavaModelException {
 	JavaElement le = (JavaElement) getParent();
 	if (le instanceof JarPackageFragment) {
 		try {
@@ -194,7 +217,11 @@
 		} catch (IOException ioe) {
 			throw new JavaModelException(ioe, IJavaModelStatusConstants.IO_EXCEPTION);
 		} catch (CoreException e) {
-			throw new JavaModelException(e);
+			if (e instanceof JavaModelException) {
+				throw (JavaModelException)e;
+			} else {
+				throw new JavaModelException(e);
+			}
 		}
 	} else {
 		byte[] contents = Util.getResourceContentsAsByteArray(file);
@@ -230,11 +257,11 @@
  * @see IClassFile
  */
 public IJavaElement getElementAt(int position) throws JavaModelException {
-	IJavaElement parent = getParent();
-	while (parent.getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT) {
-		parent = parent.getParent();
+	IJavaElement parentElement = getParent();
+	while (parentElement.getElementType() != IJavaElement.PACKAGE_FRAGMENT_ROOT) {
+		parentElement = parentElement.getParent();
 	}
-	PackageFragmentRoot root = (PackageFragmentRoot) parent;
+	PackageFragmentRoot root = (PackageFragmentRoot) parentElement;
 	SourceMapper mapper = root.getSourceMapper();
 	if (mapper == null) {
 		return null;
@@ -247,6 +274,26 @@
 	}
 }
 /**
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return CLASS_FILE;
+}
+/*
+ * @see JavaElement
+ */
+public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner owner) {
+	switch (token.charAt(0)) {
+		case JEM_COUNT:
+			return getHandleUpdatingCountFromMemento(memento, owner);
+		case JEM_TYPE:
+			String typeName = memento.nextToken();
+			JavaElement type = new BinaryType(this, typeName);
+			return type.getHandleFromMemento(memento, owner);
+	}
+	return null;
+}
+/**
  * @see JavaElement#getHandleMemento()
  */
 protected char getHandleMementoDelimiter() {
@@ -297,29 +344,42 @@
 		return null;
 	}
 }
-/**
- * @see IClassFile
+/*
+ * Returns the name of the toplevel type of this class file.
  */
-public IType getType() throws JavaModelException {
-	if (fBinaryType == null) {
-		// Remove the ".class" from the name of the ClassFile - always works
-		// since constructor fails if name does not end with ".class"
-		String name = fName.substring(0, fName.lastIndexOf('.'));
-		name = name.substring(name.lastIndexOf('.') + 1);
-		int index = name.lastIndexOf('$');
-		if (index > -1) {
-			if (name.length() > (index + 1) && !Character.isDigit(name.charAt(index + 1))) {
-				name = name.substring(index + 1);
-			}
-		}
-		fBinaryType = new BinaryType(this, name);
-	}
-	return fBinaryType;
+public String getTopLevelTypeName() {
+    String topLevelTypeName = getElementName();
+    int firstDollar = topLevelTypeName.indexOf('$');
+    if (firstDollar != -1) {
+        topLevelTypeName = topLevelTypeName.substring(0, firstDollar);
+    } else {
+        topLevelTypeName = topLevelTypeName.substring(0, topLevelTypeName.length()-SUFFIX_CLASS.length);
+    }
+    return topLevelTypeName;
 }
 /**
  * @see IClassFile
  */
-public IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory) throws JavaModelException {
+public IType getType() {
+	if (this.binaryType == null) {
+		// Remove the ".class" from the name of the ClassFile - always works
+		// since constructor fails if name does not end with ".class"
+		String typeName = this.name.substring(0, this.name.lastIndexOf('.'));
+		typeName = typeName.substring(typeName.lastIndexOf('.') + 1);
+		int index = typeName.lastIndexOf('$');
+		if (index > -1) {
+			if (typeName.length() > (index + 1) && !Character.isDigit(typeName.charAt(index + 1))) {
+				typeName = typeName.substring(index + 1);
+			}
+		}
+		this.binaryType = new BinaryType(this, typeName);
+	}
+	return this.binaryType;
+}
+/*
+ * @see IClassFile
+ */
+public ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
 	// get the source if possible
 	char[] contents = null;
 	SourceMapper mapper = this.getSourceMapper();
@@ -331,7 +391,7 @@
 	}
 
 	ClassFileWorkingCopy workingCopy = new ClassFileWorkingCopy();
-	IBuffer buffer = factory == null ? this.getBuffer() : factory.createBuffer(workingCopy);
+	IBuffer buffer = owner == null ? this.getBuffer() : owner.createBuffer(workingCopy);
 	workingCopy.buffer = buffer;
 	
 	// set the buffer source
@@ -341,6 +401,13 @@
 	return workingCopy;
 }
 /**
+ * @see IClassFile
+ * @deprecated
+ */
+public IJavaElement getWorkingCopy(IProgressMonitor monitor, org.eclipse.jdt.core.IBufferFactory factory) throws JavaModelException {
+	return getWorkingCopy(BufferFactoryWrapper.create(factory), monitor);
+}
+/**
  * @see Openable
  */
 protected boolean hasBuffer() {
@@ -376,6 +443,16 @@
 public boolean isReadOnly() {
 	return true;
 }
+private boolean isValidClassFile() {
+	IPackageFragmentRoot root = getPackageFragmentRoot();
+	try {
+		if (root.getKind() != IPackageFragmentRoot.K_BINARY) return false;
+	} catch (JavaModelException e) {
+		return false;
+	}
+	if (!Util.isValidClassFileName(getElementName())) return false;
+	return true;
+}
 /**
  * Opens and returns buffer on the source code associated with this class file.
  * Maps the source code to the children elements of this class file.
@@ -384,65 +461,106 @@
  * 
  * @see Openable
  */
-protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException {
+protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException {
 	SourceMapper mapper = getSourceMapper();
 	if (mapper != null) {
-		char[] contents = mapper.findSource(getType());
-		if (contents != null) {
-			// create buffer
-			IBuffer buffer = getBufferFactory().createBuffer(this);
-			if (buffer == null) return null;
-			BufferManager bufManager = getBufferManager();
-			bufManager.addBuffer(buffer);
-			
-			// set the buffer source
-			if (buffer.getCharacters() == null){
-				buffer.setContents(contents);
+		return mapSource(mapper);
+	} else if (!this.checkAutomaticSourceMapping) {
+		/*
+		 * We try to see if we can automatically attach a source
+		 * source files located inside the same folder than its .class file
+		 * See bug 36510.
+		 */
+		PackageFragmentRoot root = getPackageFragmentRoot();
+		if (root.isArchive()) {
+			// root is a jar file or a zip file
+			String elementName = getElementName();
+			StringBuffer sourceFileName = new StringBuffer(elementName.substring(0, elementName.lastIndexOf('.')));
+			sourceFileName.append(SuffixConstants.SUFFIX_java);
+			JarPackageFragmentRoot jarPackageFragmentRoot = (JarPackageFragmentRoot) root;
+			ZipFile jar = null;
+			try {
+				jar = jarPackageFragmentRoot.getJar();
+				IPackageFragment packageFragment = (IPackageFragment) getParent();
+				ZipEntry zipEntry = null;
+				if (packageFragment.isDefaultPackage()) {
+					zipEntry = jar.getEntry(sourceFileName.toString());
+				} else {
+					zipEntry = jar.getEntry(getParent().getElementName() + '/' + sourceFileName.toString());
+				}
+				if (zipEntry != null) {
+					// found a source file
+					this.checkAutomaticSourceMapping = true;
+					root.attachSource(root.getPath(), null, null);
+					SourceMapper sourceMapper = getSourceMapper();
+					if (sourceMapper != null) {
+						return mapSource(sourceMapper);
+					}
+				}
+			} catch (CoreException e) {
+				if (e instanceof JavaModelException) throw (JavaModelException)e;
+				throw new JavaModelException(e);
+			} finally {
+				JavaModelManager.getJavaModelManager().closeZipFile(jar);
 			}
-			
-			// listen to buffer changes
-			buffer.addBufferChangedListener(this);	
-					
-			// do the source mapping
-			mapper.mapSource(getType(), contents);
-			
-			return buffer;
-		}
-	} else {
-		// Attempts to find the corresponding java file
-		String qualifiedName = getType().getFullyQualifiedName();
-		NameLookup lookup = ((JavaProject) getJavaProject()).getNameLookup();
-		ICompilationUnit cu = lookup.findCompilationUnit(qualifiedName);
-		if (cu != null) {
-			return cu.getBuffer();
+		} else {
+			// Attempts to find the corresponding java file
+			String qualifiedName = getType().getFullyQualifiedName();
+			NameLookup lookup = ((JavaProject) getJavaProject()).getNameLookup();
+			ICompilationUnit cu = lookup.findCompilationUnit(qualifiedName);
+			if (cu != null) {
+				return cu.getBuffer();
+			} else	{
+				// root is a class folder
+				IPath sourceFilePath = getPath().removeFileExtension().addFileExtension(EXTENSION_java);
+				IWorkspace workspace = ResourcesPlugin.getWorkspace();
+				if (workspace == null) {
+					this.checkAutomaticSourceMapping = true; // we don't want to check again
+					return null; // workaround for http://bugs.eclipse.org/bugs/show_bug.cgi?id=34069
+				}
+				if (JavaModel.getTarget(
+						workspace.getRoot(),
+						sourceFilePath.makeRelative(), // ensure path is relative (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517)
+						true) != null) {
+							
+					// found a source file
+					 // we don't need to check again. The source will be attached.
+					this.checkAutomaticSourceMapping = true;
+					root.attachSource(root.getPath(), null, null);
+					SourceMapper sourceMapper = getSourceMapper();
+					if (sourceMapper != null) {
+						return mapSource(sourceMapper);
+					}
+				}
+			}
 		}
 	}
 	return null;
 }
-protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
-	IResource resource = this.getResource();
-	if (resource != null && !resource.isAccessible()) throw newNotPresentException();
-	super.openWhenClosed(pm);
+private IBuffer mapSource(SourceMapper mapper) {
+	char[] contents = mapper.findSource(getType());
+	if (contents != null) {
+		// create buffer
+		IBuffer buffer = getBufferManager().createBuffer(this);
+		if (buffer == null) return null;
+		BufferManager bufManager = getBufferManager();
+		bufManager.addBuffer(buffer);
+		
+		// set the buffer source
+		if (buffer.getCharacters() == null){
+			buffer.setContents(contents);
+		}
+		
+		// listen to buffer changes
+		buffer.addBufferChangedListener(this);	
+				
+		// do the source mapping
+		mapper.mapSource(getType(), contents);
+		
+		return buffer;
+	}
+	return null;
 }
-/*
- * @see JavaElement#rootedAt(IJavaProject)
- */
-public IJavaElement rootedAt(IJavaProject project) {
-	return
-		new ClassFile(
-			(IPackageFragment)((JavaElement)fParent).rootedAt(project), 
-			fName);
-}
-/**
- * Returns the Java Model format of the simple class name for the
- * given className which is provided in diet class file format,
- * or <code>null</code> if the given className is <code>null</code>.
- * (This removes package name and enclosing type names).
- *
- * <p><code>ClassFileReader</code> format is similar to "java/lang/Object",
- * and corresponding Java Model simple name format is "Object".
- */
-
 /* package */ static char[] simpleName(char[] className) {
 	if (className == null)
 		return null;
@@ -543,6 +661,7 @@
 		offset,
 		new ICompletionRequestor(){
 			public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName, char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
+				// ignore
 			}
 			public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
 				requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
@@ -560,10 +679,11 @@
 					marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
 					requestor.acceptError(marker);
 				} catch(CoreException e){
+					// marker could not be created: ignore
 				}
 			}
-			public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-				requestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
+			public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
+				requestor.acceptField(declaringTypePackageName, declaringTypeName, fieldName, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
 			}
 			public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
 				requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd);
@@ -574,7 +694,7 @@
 			public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){
 				requestor.acceptLabel(labelName, completionStart, completionEnd);
 			}
-			public void acceptLocalVariable(char[] name,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){
+			public void acceptLocalVariable(char[] localVarName,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){
 				// ignore
 			}
 			public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
@@ -593,7 +713,7 @@
 			public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance){
 				requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd);
 			}
-			public void acceptVariableName(char[] typePackageName,char[] typeName,char[] name,char[] completionName,int completionStart,int completionEnd, int relevance){
+			public void acceptVariableName(char[] typePackageName,char[] typeName,char[] varName,char[] completionName,int completionStart,int completionEnd, int relevance){
 				// ignore
 			}
 		});
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
index bff3eb0..e952972 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileInfo.java
@@ -12,9 +12,8 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
 
+import org.eclipse.core.resources.IFile;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IJavaElement;
@@ -27,12 +26,13 @@
 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
 import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 
 /**
  * Element info for <code>ClassFile</code> handles.
  */
  
-/* package */ class ClassFileInfo extends OpenableElementInfo {
+/* package */ class ClassFileInfo extends OpenableElementInfo implements SuffixConstants {
 	/** 
 	 * The children of the <code>BinaryType</code> corresponding to our
 	 * <code>ClassFile</code>. These are kept here because we don't have
@@ -42,22 +42,22 @@
 	 * <code>getBinaryChildren()</code>, which in turn is called by
 	 * <code>BinaryType.getChildren()</code>. 
 	 */
-	protected IJavaElement[] fBinaryChildren = null;
+	protected JavaElement[] binaryChildren = null;
 	/**
 	 * Back-pointer to the IClassFile to allow lazy initialization.
 	 */
-	protected IClassFile fClassFile = null;
+	protected ClassFile classFile = null;
 /**
  * Creates a new <code>ClassFileInfo</code> for <code>classFile</code>.
  */
-ClassFileInfo(IClassFile classFile) {
-	fClassFile = classFile;
+ClassFileInfo(ClassFile classFile) {
+	this.classFile = classFile;
 }
 /**
  * Creates the handles and infos for the fields of the given binary type.
  * Adds new handles to the given vector.
  */
-private void generateFieldInfos(IType type, IBinaryType typeInfo, HashMap newElements, ArrayList children) {
+private void generateFieldInfos(IType type, IBinaryType typeInfo, HashMap newElements, ArrayList childrenHandles) {
 	// Make the fields
 	IBinaryField[] fields = typeInfo.getFields();
 	if (fields == null) {
@@ -65,16 +65,16 @@
 	}
 	for (int i = 0, fieldCount = fields.length; i < fieldCount; i++) {
 		IBinaryField fieldInfo = fields[i];
-		IField field = new BinaryField(type, new String(fieldInfo.getName()));
+		IField field = new BinaryField((JavaElement)type, new String(fieldInfo.getName()));
 		newElements.put(field, fieldInfo);
-		children.add(field);
+		childrenHandles.add(field);
 	}
 }
 /**
- * Creates the handles and infos for the inner types of the given binary type.
+ * Creates the handles for the inner types of the given binary type.
  * Adds new handles to the given vector.
  */
-private void generateInnerClassInfos(IType type, IBinaryType typeInfo, HashMap newElements, ArrayList children) {
+private void generateInnerClassHandles(IType type, IBinaryType typeInfo, ArrayList childrenHandles) {
 	// Add inner types
 	// If the current type is an inner type, innerClasses returns
 	// an extra entry for the current type.  This entry must be removed.
@@ -83,9 +83,9 @@
 	if (innerTypes != null) {
 		for (int i = 0, typeCount = innerTypes.length; i < typeCount; i++) {
 			IBinaryNestedType binaryType = innerTypes[i];
-			IClassFile classFile= ((IPackageFragment)fClassFile.getParent()).getClassFile(new String(ClassFile.unqualifiedName(binaryType.getName())) + ".class"); //$NON-NLS-1$
-			IType innerType = new BinaryType(classFile, new String(ClassFile.simpleName(binaryType.getName())));
-			children.add(innerType);
+			IClassFile parentClassFile= ((IPackageFragment)this.classFile.getParent()).getClassFile(new String(ClassFile.unqualifiedName(binaryType.getName())) + SUFFIX_STRING_class);
+			IType innerType = new BinaryType((JavaElement)parentClassFile, new String(ClassFile.simpleName(binaryType.getName())));
+			childrenHandles.add(innerType);
 		}
 	}
 }
@@ -93,7 +93,7 @@
  * Creates the handles and infos for the methods of the given binary type.
  * Adds new handles to the given vector.
  */
-private void generateMethodInfos(IType type, IBinaryType typeInfo, HashMap newElements, ArrayList children) {
+private void generateMethodInfos(IType type, IBinaryType typeInfo, HashMap newElements, ArrayList childrenHandles) {
 	IBinaryMethod[] methods = typeInfo.getMethods();
 	if (methods == null) {
 		return;
@@ -113,8 +113,8 @@
 		for (int j= 0; j < pNames.length; j++) {
 			pNames[j]= new String(parameterTypes[j]);
 		}
-		IMethod method = new BinaryMethod(type, selector, pNames);
-		children.add(method);
+		IMethod method = new BinaryMethod((JavaElement)type, selector, pNames);
+		childrenHandles.add(method);
 		newElements.put(method, methodInfo);
 	}
 }
@@ -122,62 +122,64 @@
  * Returns the list of children (<code>BinaryMember</code>s) of the
  * <code>BinaryType</code> of our <code>ClassFile</code>.
  */
-IJavaElement[] getBinaryChildren() throws JavaModelException {
-	if (fBinaryChildren == null) {
-		readBinaryChildren();
+IJavaElement[] getBinaryChildren(HashMap newElements) {
+	if (this.binaryChildren == null) {
+		readBinaryChildren(newElements, null/*type info not known here*/);
 	}
-	return fBinaryChildren;
+	return this.binaryChildren;
 }
 /**
  * Returns true iff the <code>readBinaryChildren</code> has already
  * been called.
  */
 boolean hasReadBinaryChildren() {
-	return fBinaryChildren != null;
+	return this.binaryChildren != null;
 }
 /**
  * Creates the handles for <code>BinaryMember</code>s defined in this
  * <code>ClassFile</code> and adds them to the
  * <code>JavaModelManager</code>'s cache.
  */
-private void readBinaryChildren() {
-	ArrayList children = new ArrayList();
-	HashMap newElements = new HashMap();
+protected void readBinaryChildren(HashMap newElements, IBinaryType typeInfo) {
+	ArrayList childrenHandles = new ArrayList();
 	BinaryType type = null;
-	IBinaryType typeInfo = null;
-	JavaModelManager manager = (JavaModelManager) JavaModelManager.getJavaModelManager();
 	try {
-		type = (BinaryType) fClassFile.getType();
-		typeInfo = (IBinaryType) manager.getInfo(type);
+		type = (BinaryType) this.classFile.getType();
+		if (typeInfo == null) {
+			typeInfo = (IBinaryType) newElements.get(type);
+			if (typeInfo == null) {
+				// create a classfile reader 
+			    typeInfo = this.classFile.getBinaryTypeInfo((IFile)this.classFile.getResource());
+			}
+		}
 	} catch (JavaModelException npe) {
 		return;
 	}
 	if (typeInfo != null) { //may not be a valid class file
-		generateFieldInfos(type, typeInfo, newElements, children);
-		generateMethodInfos(type, typeInfo, newElements, children);
-		generateInnerClassInfos(type, typeInfo, newElements, children);
+		generateFieldInfos(type, typeInfo, newElements, childrenHandles);
+		generateMethodInfos(type, typeInfo, newElements, childrenHandles);
+		generateInnerClassHandles(type, typeInfo, childrenHandles); // Note inner class are separate openables that are not opened here: no need to pass in newElements
 	}
 	
-	for (Iterator iter = newElements.entrySet().iterator(); iter.hasNext();) {
-		Map.Entry entry = (Map.Entry) iter.next();
-		manager.putInfo(
-			(IJavaElement) entry.getKey(), 
-			entry.getValue());
-	}
-	fBinaryChildren = new IJavaElement[children.size()];
-	children.toArray(fBinaryChildren);
+	this.binaryChildren = new JavaElement[childrenHandles.size()];
+	childrenHandles.toArray(this.binaryChildren);
 }
 /**
  * Removes the binary children handles and remove their infos from
  * the <code>JavaModelManager</code>'s cache.
  */
-void removeBinaryChildren() {
-	if (fBinaryChildren != null) {
-		JavaModelManager manager = (JavaModelManager) JavaModelManager.getJavaModelManager();
-		for (int i = 0; i <fBinaryChildren.length; i++) {
-			manager.removeInfo(fBinaryChildren[i]);
+void removeBinaryChildren() throws JavaModelException {
+	if (this.binaryChildren != null) {
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		for (int i = 0; i <this.binaryChildren.length; i++) {
+			JavaElement child = this.binaryChildren[i];
+			if (child instanceof BinaryType) {
+				manager.removeInfoAndChildren((JavaElement)child.getParent());
+			} else {
+				manager.removeInfoAndChildren(child);
+			}
 		}
-		fBinaryChildren = fgEmptyChildren;
+		this.binaryChildren = JavaElement.NO_ELEMENTS;
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java
index 66f3163..51ccef7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java
@@ -14,8 +14,8 @@
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IBuffer;
-import org.eclipse.jdt.core.IBufferFactory;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.ICompletionRequestor;
 import org.eclipse.jdt.core.IImportContainer;
@@ -26,7 +26,6 @@
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IOpenable;
 import org.eclipse.jdt.core.IPackageDeclaration;
-import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IProblemRequestor;
 import org.eclipse.jdt.core.ISourceRange;
 import org.eclipse.jdt.core.IType;
@@ -41,7 +40,13 @@
 	
 	public IBuffer buffer;
 	
-
+	/*
+	 * @see ICompilationUnit#becomeWorkingCopy(IProblemRequestor, IProgressMonitor)
+	 */
+	public void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException {
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+	}
+	
 	/*
 	 * @see ICompilationUnit#createImport(String, IJavaElement, IProgressMonitor)
 	 */
@@ -76,6 +81,13 @@
 	}
 
 	/*
+	 * @see ICompilationUnit#discardWorkingCopy
+	 */
+	public void discardWorkingCopy() throws JavaModelException {
+		// not a real working copy: ignore
+	}
+	
+	/*
 	 * @see ICompilationUnit#getAllTypes()
 	 */
 	public IType[] getAllTypes() throws JavaModelException {
@@ -118,6 +130,13 @@
 	}
 
 	/*
+	 * @see ICompilationUnit#getOwner()
+	 */
+	public WorkingCopyOwner getOwner() {
+		return null;
+	}
+
+	/*
 	 * @see ICompilationUnit#getPackageDeclaration(String)
 	 */
 	public IPackageDeclaration getPackageDeclaration(String name) {
@@ -213,18 +232,34 @@
 	public IJavaElement getParent() {
 		return null;
 	}
-/*
- * @see IJavaElement
- */
-public IPath getPath() {
-	return null;
-}
-/*
- * @see IJavaElement
- */
-public IResource getResource() {
-	return null;
-}
+
+	/*
+	 * @see IJavaElement
+	 */
+	public IPath getPath() {
+		return null;
+	}
+
+	/*
+	 * @see ICompilationUnit#getPrimary()
+	 */
+	public ICompilationUnit getPrimary() {
+		return this;
+	}
+	
+	/*
+	 * @see ICompilationUnit#getPrimaryElement()
+	 */
+	public IJavaElement getPrimaryElement() {
+		return getPrimary();
+	}
+	
+	/*
+	 * @see IJavaElement
+	 */
+	public IResource getResource() {
+		return null;
+	}
 
 	/*
 	 * @see IJavaElement#getUnderlyingResource()
@@ -243,7 +278,7 @@
 	/*
 	 * @see IJavaElement#isStructureKnown()
 	 */
-	public boolean isStructureKnown() throws JavaModelException {
+	public boolean isStructureKnown() {
 		return false;
 	}
 
@@ -279,26 +314,34 @@
 	 * @see IOpenable#close()
 	 */
 	public void close() throws JavaModelException {
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 	}
 
 	/*
 	 * @see IOpenable#getBuffer()
 	 */
-	public IBuffer getBuffer() throws JavaModelException {
+	public IBuffer getBuffer() {
 		return this.buffer;
 	}
 
 	/*
+	 * @see ICompilationUnit#hasResourceChanged()
+	 */
+	public boolean hasResourceChanged() {
+		return false;
+	}
+	
+	/*
 	 * @see IOpenable#hasUnsavedChanges()
 	 */
-	public boolean hasUnsavedChanges() throws JavaModelException {
+	public boolean hasUnsavedChanges() {
 		return false;
 	}
 
 	/*
 	 * @see IOpenable#isConsistent()
 	 */
-	public boolean isConsistent() throws JavaModelException {
+	public boolean isConsistent() {
 		return false;
 	}
 
@@ -332,43 +375,64 @@
 		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 	}
 
-	/*
+	/**
 	 * @see IWorkingCopy#commit(boolean, IProgressMonitor)
+	 * @deprecated
 	 */
-	public void commit(boolean force, IProgressMonitor monitor)
+	public void commit(boolean force, IProgressMonitor monitor) throws JavaModelException {
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+	}
+	
+	/*
+	 * @see IWorkingCopy#commitWorkingCopy(boolean, IProgressMonitor)
+	 */
+	public void commitWorkingCopy(boolean force, IProgressMonitor monitor)
 		throws JavaModelException {
 		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 	}
 
-	/*
+	/**
 	 * @see IWorkingCopy#destroy()
+	 * @deprecated
 	 */
 	public void destroy() {
+		// not a real working copy: ignore
 	}
 
-	/*
+	/**
 	 * @see IWorkingCopy#findSharedWorkingCopy(IBufferFactory)
+	 * @deprecated
 	 */
 	public IJavaElement findSharedWorkingCopy(IBufferFactory bufferFactory) {
 		return null;
 	}
+	
+	/**
+	 * @see ICompilationUnit#findWorkingCopy(WorkingCopyOwner)
+	 */
+	public ICompilationUnit findWorkingCopy(WorkingCopyOwner owner) {
+		return null;
+	}
 
-	/*
+	/**
 	 * @see IWorkingCopy#getOriginal(IJavaElement)
+	 * @deprecated
 	 */
 	public IJavaElement getOriginal(IJavaElement workingCopyElement) {
 		return null;
 	}
 
-	/*
+	/**
 	 * @see IWorkingCopy#getOriginalElement()
+	 * @deprecated
 	 */
 	public IJavaElement getOriginalElement() {
-		return new ClassFile((IPackageFragment)getParent(), getElementName());
+		return getPrimaryElement();
 	}
 
-		/*
+	/**
 	 * @see IWorkingCopy#getSharedWorkingCopy(IProgressMonitor, IBufferFactory)
+	 * @deprecated
 	 */
 	public IJavaElement getSharedWorkingCopy(
 		IProgressMonitor monitor,
@@ -378,28 +442,39 @@
 		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 	}
 
-	/*
+	/**
 	 * @see IWorkingCopy#getWorkingCopy()
+	 * @deprecated
 	 */
 	public IJavaElement getWorkingCopy() throws JavaModelException {
 		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 	}
-	/*
-	 * @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
+	
+	/**
+	 * @see ICompilationUnit#getWorkingCopy(IProgressMonitor)
 	 */
-	public IJavaElement getWorkingCopy(
-		IProgressMonitor monitor,
-		IBufferFactory factory,
-		IProblemRequestor problemRequestor) 
-		throws JavaModelException {
+	public ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException {
 		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 	}
-	/*
-	 * @see IWorkingCopy#hasManagedWorkingCopy()
-	 */
 
-	/*
+	/**
+	 * @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
+	 * @deprecated
+	 */
+	public IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException {
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+	}
+
+	/**
+	 * @see IWorkingCopy#getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)
+	 */
+	public ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException {
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+	}
+
+	/**
 	 * @see IWorkingCopy#isBasedOn(IResource)
+	 * @deprecated
 	 */
 	public boolean isBasedOn(IResource resource) {
 		return false;
@@ -414,13 +489,14 @@
 
 	/**
 	 * @see org.eclipse.jdt.core.IWorkingCopy#reconcile()
+	 * @deprecated
 	 */
 	public IMarker[] reconcile() throws JavaModelException {
 		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 	}
 
 	/**
-	 * @see IWorkingCopy#reconcile(boolean, IProgressMonitor)
+	 * @see ICompilationUnit#reconcile(boolean, IProgressMonitor)
 	 */
 	public void reconcile(
 		boolean forceProblemDetection,
@@ -430,6 +506,17 @@
 	}
 
 	/**
+	 * @see ICompilationUnit#reconcile(boolean, WorkingCopyOwner, IProgressMonitor)
+	 */
+	public void reconcile(
+		boolean forceProblemDetection,
+		WorkingCopyOwner owner,
+		IProgressMonitor monitor)
+		throws JavaModelException {
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+	}
+
+	/**
 	 * @see org.eclipse.jdt.core.IWorkingCopy#restore()
 	 */
 	public void restore() throws JavaModelException {
@@ -487,6 +574,14 @@
 	}
 
 	/**
+	 * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, ICompletionRequestor, WorkingCopyOwner)
+	 */
+	public void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner)
+		throws JavaModelException {
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+	}
+
+	/**
 	 * @see org.eclipse.jdt.core.ICodeAssist#codeSelect(int, int)
 	 */
 	public IJavaElement[] codeSelect(int offset, int length)
@@ -495,6 +590,14 @@
 	}
 
 	/**
+	 * @see org.eclipse.jdt.core.ICodeAssist#codeSelect(int, int, WorkingCopyOwner)
+	 */
+	public IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner owner)
+		throws JavaModelException {
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
+	}
+
+	/**
 	 * @see org.eclipse.jdt.core.ICodeAssist#codeComplete(int, ICodeCompletionRequestor)
 	 * @deprecated
 	 */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
index 5f30c85..84ed52a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java
@@ -10,15 +10,28 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.io.File;
+import java.util.HashMap;
+import java.util.HashSet;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+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.Path;
+import org.eclipse.jdt.core.IClasspathContainer;
 import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaModelStatus;
+import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.w3c.dom.Document;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.core.util.Util;
 import org.w3c.dom.Element;
 
 /**
@@ -147,7 +160,7 @@
 		if (this.fullCharExclusionPatterns == UNINIT_PATTERNS) {
 			int length = this.exclusionPatterns.length;
 			this.fullCharExclusionPatterns = new char[length][];
-			IPath prefixPath = path.removeTrailingSeparator();
+			IPath prefixPath = this.path.removeTrailingSeparator();
 			for (int i = 0; i < length; i++) {
 				this.fullCharExclusionPatterns[i] = 
 					prefixPath.append(this.exclusionPatterns[i]).toString().toCharArray();
@@ -159,13 +172,11 @@
 	/**
 	 * Returns the XML encoding of the class path.
 	 */
-	public Element elementEncode(
-		Document document,
-		IPath projectPath)
-		throws JavaModelException {
-
-		Element element = document.createElement("classpathentry"); //$NON-NLS-1$
-		element.setAttribute("kind", kindToString(this.entryKind));	//$NON-NLS-1$
+	public void elementEncode(XMLWriter writer, IPath projectPath, boolean indent, boolean newLine) {
+		HashMap parameters = new HashMap();
+		
+		parameters.put("kind", ClasspathEntry.kindToString(this.entryKind));//$NON-NLS-1$
+		
 		IPath xmlPath = this.path;
 		if (this.entryKind != IClasspathEntry.CPE_VARIABLE && this.entryKind != IClasspathEntry.CPE_CONTAINER) {
 			// translate to project relative from absolute (unless a device path)
@@ -180,15 +191,24 @@
 				}
 			}
 		}
-		element.setAttribute("path", xmlPath.toString()); //$NON-NLS-1$
+		parameters.put("path", String.valueOf(xmlPath));//$NON-NLS-1$
+		
 		if (this.sourceAttachmentPath != null) {
-			element.setAttribute("sourcepath", this.sourceAttachmentPath.toString()); //$NON-NLS-1$
+			xmlPath = this.sourceAttachmentPath;
+			// translate to project relative from absolute 
+			if (this.entryKind != IClasspathEntry.CPE_VARIABLE && projectPath != null && projectPath.isPrefixOf(xmlPath)) {
+				if (xmlPath.segment(0).equals(projectPath.segment(0))) {
+					xmlPath = xmlPath.removeFirstSegments(1);
+					xmlPath = xmlPath.makeRelative();
+				}
+			}
+			parameters.put("sourcepath", String.valueOf(xmlPath));//$NON-NLS-1$
 		}
 		if (this.sourceAttachmentRootPath != null) {
-			element.setAttribute("rootpath", this.sourceAttachmentRootPath.toString()); //$NON-NLS-1$
+			parameters.put("rootpath", String.valueOf(this.sourceAttachmentRootPath));//$NON-NLS-1$
 		}
 		if (this.isExported) {
-			element.setAttribute("exported", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+			parameters.put("exported", "true");//$NON-NLS-1$//$NON-NLS-2$
 		}
 		
 		if (this.exclusionPatterns.length > 0) {
@@ -197,15 +217,16 @@
 				if (i > 0) excludeRule.append('|');
 				excludeRule.append(this.exclusionPatterns[i]);
 			}
-			element.setAttribute("excluding", excludeRule.toString());  //$NON-NLS-1$
+			parameters.put("excluding", String.valueOf(excludeRule));//$NON-NLS-1$
 		}
 		
 		if (this.specificOutputLocation != null) {
 			IPath outputLocation = this.specificOutputLocation.removeFirstSegments(1);
 			outputLocation = outputLocation.makeRelative();
-			element.setAttribute("output", outputLocation.toString()); //$NON-NLS-1$ 
+			parameters.put("output", String.valueOf(outputLocation));//$NON-NLS-1$
 		}
-		return element;
+
+		writer.printTag("classpathentry", parameters, indent, newLine, true);//$NON-NLS-1$
 	}
 	
 	public static IClasspathEntry elementDecode(Element element, IJavaProject project) {
@@ -225,6 +246,9 @@
 			element.hasAttribute("sourcepath")	//$NON-NLS-1$
 			? new Path(element.getAttribute("sourcepath")) //$NON-NLS-1$
 			: null;
+		if (kind != IClasspathEntry.CPE_VARIABLE && sourceAttachmentPath != null && !sourceAttachmentPath.isAbsolute()) {
+			sourceAttachmentPath = projectPath.append(sourceAttachmentPath);
+		}
 		IPath sourceAttachmentRootPath = 
 			element.hasAttribute("rootpath") //$NON-NLS-1$
 			? new Path(element.getAttribute("rootpath")) //$NON-NLS-1$
@@ -582,4 +606,454 @@
 	
 		return JavaCore.getResolvedClasspathEntry(this);
 	}
+	
+	/**
+	 * Validate a given classpath and output location for a project, using the following rules:
+	 * <ul>
+	 *   <li> Classpath entries cannot collide with each other; that is, all entry paths must be unique.
+	 *   <li> The project output location path cannot be null, must be absolute and located inside the project.
+	 *   <li> Specific output locations (specified on source entries) can be null, if not they must be located inside the project,
+	 *   <li> A project entry cannot refer to itself directly (that is, a project cannot prerequisite itself).
+     *   <li> Classpath entries or output locations cannot coincidate or be nested in each other, except for the following scenarii listed below:
+	 *      <ul><li> A source folder can coincidate with its own output location, in which case this output can then contain library archives. 
+	 *                     However, a specific output location cannot coincidate with any library or a distinct source folder than the one referring to it. </li> 
+	 *              <li> A source/library folder can be nested in any source folder as long as the nested folder is excluded from the enclosing one. </li>
+	 * 			<li> An output location can be nested in a source folder, if the source folder coincidates with the project itself, or if the output
+	 * 					location is excluded from the source folder. </li>
+	 *      </ul>
+	 * </ul>
+	 * 
+	 *  Note that the classpath entries are not validated automatically. Only bound variables or containers are considered 
+	 *  in the checking process (this allows to perform a consistency check on a classpath which has references to
+	 *  yet non existing projects, folders, ...).
+	 *  <p>
+	 *  This validation is intended to anticipate classpath issues prior to assigning it to a project. In particular, it will automatically
+	 *  be performed during the classpath setting operation (if validation fails, the classpath setting will not complete).
+	 *  <p>
+	 * @param javaProject the given java project
+	 * @param classpath a given classpath
+	 * @param outputLocation a given output location
+	 * @return a status object with code <code>IStatus.OK</code> if
+	 *		the given classpath and output location are compatible, otherwise a status 
+	 *		object indicating what is wrong with the classpath or output location
+	 */
+	public static IJavaModelStatus validateClasspath(IJavaProject javaProject, IClasspathEntry[] rawClasspath, IPath projectOutputLocation) {
+	
+		IProject project = javaProject.getProject();
+		IPath projectPath= project.getFullPath();
+		String projectName = javaProject.getElementName();
+	
+		/* validate output location */
+		if (projectOutputLocation == null) {
+			return new JavaModelStatus(IJavaModelStatusConstants.NULL_PATH);
+		}
+		if (projectOutputLocation.isAbsolute()) {
+			if (!projectPath.isPrefixOf(projectOutputLocation)) {
+				return new JavaModelStatus(IJavaModelStatusConstants.PATH_OUTSIDE_PROJECT, javaProject, projectOutputLocation.toString());
+			}
+		} else {
+			return new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, projectOutputLocation);
+		}
+	
+		boolean hasSource = false;
+		boolean hasLibFolder = false;
+	
+
+		// tolerate null path, it will be reset to default
+		if (rawClasspath == null) 
+			return JavaModelStatus.VERIFIED_OK;
+		
+		// retrieve resolved classpath
+		IClasspathEntry[] classpath; 
+		try {
+			classpath = ((JavaProject)javaProject).getResolvedClasspath(rawClasspath, null /*output*/, true/*ignore pb*/, false/*no marker*/, null /*no reverse map*/);
+		} catch(JavaModelException e){
+			return e.getJavaModelStatus();
+		}
+		int length = classpath.length; 
+
+		int outputCount = 1;
+		IPath[] outputLocations	= new IPath[length+1];
+		boolean[] allowNestingInOutputLocations = new boolean[length+1];
+		outputLocations[0] = projectOutputLocation;
+		
+		// retrieve and check output locations
+		IPath potentialNestedOutput = null; // for error reporting purpose
+		int sourceEntryCount = 0;
+		boolean disableExclusionPatterns = JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, true));
+		boolean disableCustomOutputLocations = JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, true));
+		
+		for (int i = 0 ; i < length; i++) {
+			IClasspathEntry resolvedEntry = classpath[i];
+			switch(resolvedEntry.getEntryKind()){
+				case IClasspathEntry.CPE_SOURCE :
+					sourceEntryCount++;
+
+					if (disableExclusionPatterns && resolvedEntry.getExclusionPatterns() != null && resolvedEntry.getExclusionPatterns().length > 0) {
+						return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS, javaProject, resolvedEntry.getPath());
+					}
+					IPath customOutput; 
+					if ((customOutput = resolvedEntry.getOutputLocation()) != null) {
+
+						if (disableCustomOutputLocations) {
+							return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS, javaProject, resolvedEntry.getPath());
+						}
+						// ensure custom output is in project
+						if (customOutput.isAbsolute()) {
+							if (!javaProject.getPath().isPrefixOf(customOutput)) {
+								return new JavaModelStatus(IJavaModelStatusConstants.PATH_OUTSIDE_PROJECT, javaProject, customOutput.toString());
+							}
+						} else {
+							return new JavaModelStatus(IJavaModelStatusConstants.RELATIVE_PATH, customOutput);
+						}
+						
+						// ensure custom output doesn't conflict with other outputs
+						int index;
+						
+						// check exact match
+						if ((index = Util.indexOfMatchingPath(customOutput, outputLocations, outputCount)) != -1) {
+							continue; // already found
+						}
+						
+						// check nesting
+						if ((index = Util.indexOfEnclosingPath(customOutput, outputLocations, outputCount)) != -1) {
+							if (index == 0) {
+								// custom output is nested in project's output: need to check if all source entries have a custom
+								// output before complaining
+								if (potentialNestedOutput == null) potentialNestedOutput = customOutput;
+							} else {
+								return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestOutputInOutput", customOutput.makeRelative().toString(), outputLocations[index].makeRelative().toString())); //$NON-NLS-1$
+							}
+						}
+						outputLocations[outputCount++] = customOutput;
+					}
+			}	
+		}	
+		// allow custom output nesting in project's output if all source entries have a custom output
+		if (sourceEntryCount <= outputCount-1) {
+		    allowNestingInOutputLocations[0] = true;
+		} else if (potentialNestedOutput != null) {
+			return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestOutputInOutput", potentialNestedOutput.makeRelative().toString(), outputLocations[0].makeRelative().toString())); //$NON-NLS-1$
+		}
+
+		for (int i = 0 ; i < length; i++) {
+			IClasspathEntry resolvedEntry = classpath[i];
+			IPath path = resolvedEntry.getPath();
+			int index;
+			switch(resolvedEntry.getEntryKind()){
+				
+				case IClasspathEntry.CPE_SOURCE :
+					hasSource = true;
+					if ((index = Util.indexOfMatchingPath(path, outputLocations, outputCount)) != -1){
+						allowNestingInOutputLocations[index] = true;
+					}
+					break;
+
+				case IClasspathEntry.CPE_LIBRARY:
+					hasLibFolder |= !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(path.lastSegment());
+					if ((index = Util.indexOfMatchingPath(path, outputLocations, outputCount)) != -1){
+						allowNestingInOutputLocations[index] = true;
+					}
+					break;
+			}
+		}
+		if (!hasSource && !hasLibFolder) { // if no source and no lib folder, then allowed
+			for (int i = 0; i < outputCount; i++) allowNestingInOutputLocations[i] = true;
+		}
+		
+		HashSet pathes = new HashSet(length);
+		
+		// check all entries
+		for (int i = 0 ; i < length; i++) {
+			IClasspathEntry entry = classpath[i];
+			if (entry == null) continue;
+			IPath entryPath = entry.getPath();
+			int kind = entry.getEntryKind();
+			
+			// Build some common strings for status message
+			boolean isProjectRelative = entryPath.segment(0).toString().equals(projectName);
+			String entryPathMsg = isProjectRelative ? entryPath.removeFirstSegments(1).toString() : entryPath.makeRelative().toString();
+	
+			// complain if duplicate path
+			if (!pathes.add(entryPath)){
+				return new JavaModelStatus(IJavaModelStatusConstants.NAME_COLLISION, Util.bind("classpath.duplicateEntryPath", entryPathMsg, projectName)); //$NON-NLS-1$
+			}
+			// no further check if entry coincidates with project or output location
+			if (entryPath.equals(projectPath)){
+				// complain if self-referring project entry
+				if (kind == IClasspathEntry.CPE_PROJECT){
+					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, Util.bind("classpath.cannotReferToItself", entryPath.makeRelative().toString()));//$NON-NLS-1$
+				}
+				// tolerate nesting output in src if src==prj
+				continue;
+			}
+	
+			// allow nesting source entries in each other as long as the outer entry excludes the inner one
+			if (kind == IClasspathEntry.CPE_SOURCE 
+					|| (kind == IClasspathEntry.CPE_LIBRARY && !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(entryPath.lastSegment()))){
+				for (int j = 0; j < classpath.length; j++){
+					IClasspathEntry otherEntry = classpath[j];
+					if (otherEntry == null) continue;
+					int otherKind = otherEntry.getEntryKind();
+					IPath otherPath = otherEntry.getPath();
+					if (entry != otherEntry 
+						&& (otherKind == IClasspathEntry.CPE_SOURCE 
+								|| (otherKind == IClasspathEntry.CPE_LIBRARY 
+										&& !org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(otherPath.lastSegment())))){
+						char[][] exclusionPatterns;
+						if (otherPath.isPrefixOf(entryPath) 
+								&& !otherPath.equals(entryPath)
+								&& !Util.isExcluded(entryPath.append("*"), exclusionPatterns = ((ClasspathEntry)otherEntry).fullExclusionPatternChars())) { //$NON-NLS-1$
+									
+							String exclusionPattern = entryPath.removeFirstSegments(otherPath.segmentCount()).segment(0);
+							if (Util.isExcluded(entryPath, exclusionPatterns)) {
+								return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.mustEndWithSlash", exclusionPattern, entryPath.makeRelative().toString())); //$NON-NLS-1$
+							} else {
+								if (otherKind == IClasspathEntry.CPE_SOURCE) {
+									exclusionPattern += '/';
+									return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestEntryInEntry", new String[] {entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString(), exclusionPattern})); //$NON-NLS-1$
+								} else {
+									return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestEntryInLibrary", entryPath.makeRelative().toString(), otherEntry.getPath().makeRelative().toString())); //$NON-NLS-1$
+								}
+							}
+						}
+					}
+				}
+			}
+			
+			// prevent nesting output location inside entry unless enclosing is a source entry which explicitly exclude the output location
+		    char[][] exclusionPatterns = ((ClasspathEntry)entry).fullExclusionPatternChars();
+		    for (int j = 0; j < outputCount; j++){
+		        IPath currentOutput = outputLocations[j];
+    			if (entryPath.equals(currentOutput)) continue;
+				if (entryPath.isPrefixOf(currentOutput)) {
+				    if (kind != IClasspathEntry.CPE_SOURCE || !Util.isExcluded(currentOutput, exclusionPatterns)) {
+						return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestOutputInEntry", currentOutput.makeRelative().toString(), entryPath.makeRelative().toString())); //$NON-NLS-1$
+				    }
+				}
+		    }
+
+		    // prevent nesting entry inside output location - when distinct from project or a source folder
+		    for (int j = 0; j < outputCount; j++){
+		        if (allowNestingInOutputLocations[j]) continue;
+		        IPath currentOutput = outputLocations[j];
+				if (currentOutput.isPrefixOf(entryPath)) {
+					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotNestEntryInOutput", entryPath.makeRelative().toString(), currentOutput.makeRelative().toString())); //$NON-NLS-1$
+				}
+		    }			
+		}
+		// ensure that no specific output is coincidating with another source folder (only allowed if matching current source folder)
+		// 36465 - for 2.0 backward compatibility, only check specific output locations (the default can still coincidate)
+		// perform one separate iteration so as to not take precedence over previously checked scenarii (in particular should
+		// diagnose nesting source folder issue before this one, for example, [src]"Project/", [src]"Project/source/" and output="Project/" should
+		// first complain about missing exclusion pattern
+		for (int i = 0 ; i < length; i++) {
+			IClasspathEntry entry = classpath[i];
+			if (entry == null) continue;
+			IPath entryPath = entry.getPath();
+			int kind = entry.getEntryKind();
+
+			// Build some common strings for status message
+			boolean isProjectRelative = entryPath.segment(0).toString().equals(projectName);
+			String entryPathMsg = isProjectRelative ? entryPath.removeFirstSegments(1).toString() : entryPath.makeRelative().toString();
+	
+			if (kind == IClasspathEntry.CPE_SOURCE) {
+				IPath output = entry.getOutputLocation();
+				if (output == null) continue; // 36465 - for 2.0 backward compatibility, only check specific output locations (the default can still coincidate)
+				// if (output == null) output = projectOutputLocation; // if no specific output, still need to check using default output (this line would check default output)
+				for (int j = 0; j < length; j++) {
+					IClasspathEntry otherEntry = classpath[j];
+					if (otherEntry == entry) continue;
+
+					// Build some common strings for status message
+					boolean opStartsWithProject = otherEntry.getPath().segment(0).toString().equals(projectName);
+					String otherPathMsg = opStartsWithProject ? otherEntry.getPath().removeFirstSegments(1).toString() : otherEntry.getPath().makeRelative().toString();
+	
+					switch (otherEntry.getEntryKind()) {
+						case IClasspathEntry.CPE_SOURCE :
+							if (otherEntry.getPath().equals(output)) {
+								return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotUseDistinctSourceFolderAsOutput", new String[] {entryPathMsg, otherPathMsg, projectName})); //$NON-NLS-1$
+							}
+							break;
+						case IClasspathEntry.CPE_LIBRARY :
+							if (otherEntry.getPath().equals(output)) {
+								return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.cannotUseLibraryAsOutput", new String[] {entryPathMsg, otherPathMsg, projectName})); //$NON-NLS-1$
+							}
+					}
+				}
+			}			
+		}
+		return JavaModelStatus.VERIFIED_OK;	
+	}
+	
+	/**
+	 * Returns a Java model status describing the problem related to this classpath entry if any, 
+	 * a status object with code <code>IStatus.OK</code> if the entry is fine (that is, if the
+	 * given classpath entry denotes a valid element to be referenced onto a classpath).
+	 * 
+	 * @param javaProject the given java project
+	 * @param entry the given classpath entry
+	 * @param checkSourceAttachment a flag to determine if source attachement should be checked
+	 * @param recurseInContainers flag indicating whether validation should be applied to container entries recursively
+	 * @return a java model status describing the problem related to this classpath entry if any, a status object with code <code>IStatus.OK</code> if the entry is fine
+	 */
+	public static IJavaModelStatus validateClasspathEntry(IJavaProject project, IClasspathEntry entry, boolean checkSourceAttachment, boolean recurseInContainers){
+		
+		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();			
+		IPath path = entry.getPath();
+
+		// Build some common strings for status message
+		String projectName = project.getElementName();
+		boolean pathStartsWithProject = path.segment(0).toString().equals(projectName);
+		String entryPathMsg = pathStartsWithProject ? path.removeFirstSegments(1).toString() : path.makeRelative().toString();
+
+		switch(entry.getEntryKind()){
+	
+			// container entry check
+			case IClasspathEntry.CPE_CONTAINER :
+				if (path != null && path.segmentCount() >= 1){
+					try {
+						IClasspathContainer container = JavaCore.getClasspathContainer(path, project);
+						// container retrieval is performing validation check on container entry kinds.
+						if (container == null){
+							return new JavaModelStatus(IJavaModelStatusConstants.CP_CONTAINER_PATH_UNBOUND, project, path);
+						}
+						IClasspathEntry[] containerEntries = container.getClasspathEntries();
+						if (containerEntries != null){
+							for (int i = 0, length = containerEntries.length; i < length; i++){
+								IClasspathEntry containerEntry = containerEntries[i];
+								int kind = containerEntry == null ? 0 : containerEntry.getEntryKind();
+								if (containerEntry == null
+									|| kind == IClasspathEntry.CPE_SOURCE
+									|| kind == IClasspathEntry.CPE_VARIABLE
+									|| kind == IClasspathEntry.CPE_CONTAINER){
+										String description = container.getDescription();
+										if (description == null) description = path.makeRelative().toString();
+										return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CP_CONTAINER_ENTRY, project, path);
+								}
+								if (recurseInContainers) {
+									IJavaModelStatus containerEntryStatus = validateClasspathEntry(project, containerEntry, checkSourceAttachment, recurseInContainers);
+									if (!containerEntryStatus.isOK()){
+										return containerEntryStatus;
+									}
+								} 
+							}
+						}
+					} catch(JavaModelException e){
+						return new JavaModelStatus(e);
+					}
+				} else {
+					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalContainerPath", entryPathMsg, projectName));					 //$NON-NLS-1$
+				}
+				break;
+				
+			// variable entry check
+			case IClasspathEntry.CPE_VARIABLE :
+				if (path != null && path.segmentCount() >= 1){
+					entry = JavaCore.getResolvedClasspathEntry(entry);
+					if (entry == null){
+						return new JavaModelStatus(IJavaModelStatusConstants.CP_VARIABLE_PATH_UNBOUND, project, path);
+					}
+					return validateClasspathEntry(project, entry, checkSourceAttachment, recurseInContainers);
+				} else {
+					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalVariablePath", path.makeRelative().toString(), projectName));					 //$NON-NLS-1$
+				}
+
+			// library entry check
+			case IClasspathEntry.CPE_LIBRARY :
+				if (path != null && path.isAbsolute() && !path.isEmpty()) {
+					IPath sourceAttachment = entry.getSourceAttachmentPath();
+					Object target = JavaModel.getTarget(workspaceRoot, path, true);
+					if (target != null && project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true) != JavaCore.IGNORE) {
+						long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true));
+						long libraryJDK = Util.getJdkLevel(target);
+						if (libraryJDK != 0 && libraryJDK > projectTargetJDK) {
+							return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(libraryJDK)); 
+						}
+					}
+					if (target instanceof IResource){
+						IResource resolvedResource = (IResource) target;
+						switch(resolvedResource.getType()){
+							case IResource.FILE :
+								if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resolvedResource.getFileExtension())) {
+									if (checkSourceAttachment 
+										&& sourceAttachment != null
+										&& !sourceAttachment.isEmpty()
+										&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
+										return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", new String [] {sourceAttachment.makeRelative().toString(), path.makeRelative().toString(), projectName})); //$NON-NLS-1$
+									}
+								}
+								break;
+							case IResource.FOLDER :	// internal binary folder
+								if (checkSourceAttachment 
+									&& sourceAttachment != null 
+									&& !sourceAttachment.isEmpty()
+									&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
+									return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", new String [] {sourceAttachment.makeRelative().toString(), path.makeRelative().toString(), projectName})); //$NON-NLS-1$
+								}
+						}
+					} else if (target instanceof File){
+						if (checkSourceAttachment 
+							&& sourceAttachment != null 
+							&& !sourceAttachment.isEmpty()
+							&& JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){
+							return  new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceAttachment", new String [] {sourceAttachment.toString(), path.makeRelative().toString(), projectName})); //$NON-NLS-1$
+						}
+					} else {
+						return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundLibrary", path.makeRelative().toString(), projectName)); //$NON-NLS-1$
+					}
+				} else {
+					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalLibraryPath", path.makeRelative().toString(), projectName)); //$NON-NLS-1$
+				}
+				break;
+
+			// project entry check
+			case IClasspathEntry.CPE_PROJECT :
+				if (path != null && path.isAbsolute() && !path.isEmpty()) {
+					IProject prereqProjectRsc = workspaceRoot.getProject(path.segment(0));
+					IJavaProject prereqProject = JavaCore.create(prereqProjectRsc);
+					try {
+						if (!prereqProjectRsc.exists() || !prereqProjectRsc.hasNature(JavaCore.NATURE_ID)){
+							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundProject", path.makeRelative().segment(0).toString(), projectName)); //$NON-NLS-1$
+						}
+						if (!prereqProjectRsc.isOpen()){
+							return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.closedProject", path.segment(0).toString())); //$NON-NLS-1$
+						}
+						if (project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true) != JavaCore.IGNORE) {
+							long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true));
+							long prereqProjectTargetJDK = CompilerOptions.versionToJdkLevel(prereqProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true));
+							if (prereqProjectTargetJDK > projectTargetJDK) {
+								return new JavaModelStatus(IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL, project, path, CompilerOptions.versionFromJdkLevel(prereqProjectTargetJDK)); 
+							}
+						}
+					} catch (CoreException e){
+						return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundProject", path.segment(0).toString(), projectName)); //$NON-NLS-1$
+					}
+				} else {
+					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalProjectPath", path.segment(0).toString(), projectName)); //$NON-NLS-1$
+				}
+				break;
+
+			// project source folder
+			case IClasspathEntry.CPE_SOURCE :
+				if (entry.getExclusionPatterns() != null 
+						&& entry.getExclusionPatterns().length > 0
+						&& JavaCore.DISABLED.equals(project.getOption(JavaCore.CORE_ENABLE_CLASSPATH_EXCLUSION_PATTERNS, true))) {
+					return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_EXCLUSION_PATTERNS, project, path);
+				}
+				if (entry.getOutputLocation() != null && JavaCore.DISABLED.equals(project.getOption(JavaCore.CORE_ENABLE_CLASSPATH_MULTIPLE_OUTPUT_LOCATIONS, true))) {
+					return new JavaModelStatus(IJavaModelStatusConstants.DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS, project, path);
+				}
+				if (path != null && path.isAbsolute() && !path.isEmpty()) {
+					IPath projectPath= project.getProject().getFullPath();
+					if (!projectPath.isPrefixOf(path) || JavaModel.getTarget(workspaceRoot, path, true) == null){
+						return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.unboundSourceFolder", entryPathMsg, projectName)); //$NON-NLS-1$
+					}
+				} else {
+					return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Util.bind("classpath.illegalSourceFolderPath", entryPathMsg, projectName)); //$NON-NLS-1$
+				}
+				break;
+		}
+		return JavaModelStatus.VERIFIED_OK;		
+	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
index 82d9ab7..1c577b9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
@@ -10,13 +10,20 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.io.ByteArrayInputStream;
+import java.io.UnsupportedEncodingException;
+
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IBuffer;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModelStatus;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Commits the contents of a working copy compilation
@@ -58,47 +65,90 @@
 	protected void executeOperation() throws JavaModelException {
 		try {
 			beginTask(Util.bind("workingCopy.commit"), 2); //$NON-NLS-1$
-			WorkingCopy copy = (WorkingCopy)getCompilationUnit();
-			ICompilationUnit original = (ICompilationUnit) copy.getOriginalElement();
-		
+			CompilationUnit workingCopy = getCompilationUnit();
+			IFile resource = (IFile)workingCopy.getResource();
+			ICompilationUnit primary = workingCopy.getPrimary();
+			boolean isPrimary = workingCopy.isPrimary();
+
+			JavaElementDeltaBuilder deltaBuilder = null;
 			
-			// creates the delta builder (this remembers the content of the cu)	
-			if (!original.isOpen()) {
+			PackageFragmentRoot root = (PackageFragmentRoot)workingCopy.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+			if (isPrimary || (root.isOnClasspath() && resource.isAccessible() && Util.isValidCompilationUnitName(workingCopy.getElementName()))) {
+				
 				// force opening so that the delta builder can get the old info
-				original.open(null);
-			}
-			JavaElementDeltaBuilder deltaBuilder;
-			if (Util.isExcluded(original)) {
-				deltaBuilder = null;
-			} else {
-				deltaBuilder = new JavaElementDeltaBuilder(original);
-			}
-		
-			// save the cu
-			IBuffer originalBuffer = original.getBuffer();
-			if (originalBuffer == null) return;
-			char[] originalContents = originalBuffer.getCharacters();
-			boolean hasSaved = false;
-			try {
-				IBuffer copyBuffer = copy.getBuffer();
-				if (copyBuffer == null) return;
-				originalBuffer.setContents(copyBuffer.getCharacters());
-				original.save(fMonitor, fForce);
-				this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
-				hasSaved = true;
-			} finally {
-				if (!hasSaved){
-					// restore original buffer contents since something went wrong
-					originalBuffer.setContents(originalContents);
+				if (!isPrimary && !primary.isOpen()) {
+					primary.open(null);
 				}
+
+				// creates the delta builder (this remembers the content of the cu) if:
+				// - it is not excluded
+				// - and it is not a primary or it is a non-consistent primary
+				if (!Util.isExcluded(workingCopy) && (!isPrimary || !workingCopy.isConsistent())) {
+					deltaBuilder = new JavaElementDeltaBuilder(primary);
+				}
+			
+				// save the cu
+				IBuffer primaryBuffer = primary.getBuffer();
+				if (!isPrimary) {
+					if (primaryBuffer == null) return;
+					char[] primaryContents = primaryBuffer.getCharacters();
+					boolean hasSaved = false;
+					try {
+						IBuffer workingCopyBuffer = workingCopy.getBuffer();
+						if (workingCopyBuffer == null) return;
+						primaryBuffer.setContents(workingCopyBuffer.getCharacters());
+						primaryBuffer.save(this.progressMonitor, this.force);
+						primary.makeConsistent(this);
+						hasSaved = true;
+					} finally {
+						if (!hasSaved){
+							// restore original buffer contents since something went wrong
+							primaryBuffer.setContents(primaryContents);
+						}
+					}
+				} else {
+					// for a primary working copy no need to set the content of the buffer again
+					primaryBuffer.save(this.progressMonitor, this.force);
+					primary.makeConsistent(this);
+				}
+			} else {
+				// working copy on cu outside classpath OR resource doesn't exist yet
+				String encoding = workingCopy.getJavaProject().getOption(JavaCore.CORE_ENCODING, true);
+				String contents = workingCopy.getSource();
+				if (contents == null) return;
+				try {
+					byte[] bytes = encoding == null 
+						? contents.getBytes() 
+						: contents.getBytes(encoding);
+					ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
+					if (resource.exists()) {
+						resource.setContents(
+							stream, 
+							this.force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
+							null);
+					} else {
+						resource.create(
+							stream,
+							this.force,
+							this.progressMonitor);
+					}
+				} catch (CoreException e) {
+					throw new JavaModelException(e);
+				} catch (UnsupportedEncodingException e) {
+					throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+				}
+				
 			}
+
+			setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
+			
 			// make sure working copy is in sync
-			copy.updateTimeStamp((CompilationUnit)original);
-			copy.makeConsistent(this);
+			workingCopy.updateTimeStamp((CompilationUnit)primary);
+			workingCopy.makeConsistent(this);
 			worked(1);
 		
+			// build the deltas
 			if (deltaBuilder != null) {
-				// build the deltas
 				deltaBuilder.buildDeltas();
 			
 				// add the deltas to the list of deltas created during this operation
@@ -114,8 +164,8 @@
 	/**
 	 * Returns the compilation unit this operation is working on.
 	 */
-	protected ICompilationUnit getCompilationUnit() {
-		return (ICompilationUnit)getElementToProcess();
+	protected CompilationUnit getCompilationUnit() {
+		return (CompilationUnit)getElementToProcess();
 	}
 	/**
 	 * Possible failures: <ul>
@@ -129,13 +179,11 @@
 	 *  </ul>
 	 */
 	public IJavaModelStatus verify() {
-		ICompilationUnit cu = getCompilationUnit();
+		CompilationUnit cu = getCompilationUnit();
 		if (!cu.isWorkingCopy()) {
 			return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, cu);
 		}
-		ICompilationUnit original= (ICompilationUnit)cu.getOriginalElement();
-		IResource resource = original.getResource();
-		if (!cu.isBasedOn(resource) && !fForce) {
+		if (cu.hasResourceChanged() && !this.force) {
 			return new JavaModelStatus(IJavaModelStatusConstants.UPDATE_CONFLICT);
 		}
 		// no read-only check, since some repository adapters can change the flag on save
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
index 71803de..da89ba7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java
@@ -18,35 +18,33 @@
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.jdom.IDOMNode;
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
 import org.eclipse.jdt.internal.compiler.SourceElementParser;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * @see ICompilationUnit
  */
 
-public class CompilationUnit extends Openable implements ICompilationUnit, org.eclipse.jdt.internal.compiler.env.ICompilationUnit {
+public class CompilationUnit extends Openable implements ICompilationUnit, org.eclipse.jdt.internal.compiler.env.ICompilationUnit, SuffixConstants {
 	
-	public static boolean SHARED_WC_VERBOSE = false;
-	
-	// TODO: Remove when we are certain that every client is ready for this fix
-	public static final boolean FIX_BUG25184 = true;
+	public WorkingCopyOwner owner;
 
 /**
  * Constructs a handle to a compilation unit with the given name in the
- * specified package.
+ * specified package for the specified owner
  *
  * @exception IllegalArgumentException if the name of the compilation unit
  * does not end with ".java"
  */
-protected CompilationUnit(IPackageFragment parent, String name) {
-	super(COMPILATION_UNIT, parent, name);
-	if (!Util.isJavaFileName(name)) {
-		throw new IllegalArgumentException(org.eclipse.jdt.internal.core.Util.bind("convention.unit.notJavaName")); //$NON-NLS-1$
-	}
+protected CompilationUnit(PackageFragment parent, String name, WorkingCopyOwner owner) {
+	super(parent, name);
+	this.owner = owner;
 }
 /**
  * Accepts the given visitor onto the parsed tree of this compilation unit, after
@@ -62,48 +60,226 @@
  * <li> The visitor failed with this exception.</li>
  * </ul>
  */
-public void accept(IAbstractSyntaxTreeVisitor visitor) throws JavaModelException {
+public void accept(ASTVisitor visitor) throws JavaModelException {
 	CompilationUnitVisitor.visit(this, visitor);
-} 
-
-protected void buildStructure(OpenableElementInfo info, IProgressMonitor monitor) throws JavaModelException {
-
-	if (monitor != null && monitor.isCanceled()) return;
-
-	// remove existing (old) infos
-	removeInfo();
-
-	HashMap newElements = new HashMap(11);
-	info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource()));
-	JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
-	for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) {
-		IJavaElement key = (IJavaElement) iter.next();
-		Object value = newElements.get(key);
-		JavaModelManager.getJavaModelManager().putInfo(key, value);
-	}
-	// add the info for this at the end, to ensure that a getInfo cannot reply null in case the LRU cache needs
-	// to be flushed. Might lead to performance issues.
-	// see PR 1G2K5S7: ITPJCORE:ALL - NPE when accessing source for a binary type
-	JavaModelManager.getJavaModelManager().putInfo(this, info);	
 }
+/*
+ * @see ICompilationUnit#becomeWorkingCopy(IProblemRequestor, IProgressMonitor)
+ */
+public void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException {
+	JavaModelManager manager = JavaModelManager.getJavaModelManager();
+	IPath path = this.getPath();
+	JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = manager.getPerWorkingCopyInfo(this, path, false/*don't create*/, true /*record usage*/, null/*no problem requestor needed*/);
+	if (perWorkingCopyInfo == null) {
+		// close cu and its children
+		close();
 
+		BecomeWorkingCopyOperation operation = new BecomeWorkingCopyOperation(this, path, problemRequestor);
+		runOperation(operation, null);
+	}
+}
+protected boolean buildStructure(OpenableElementInfo info, final IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
+
+	// check if this compilation unit can be opened
+	if (!isWorkingCopy()) { // no check is done on root kind or exclusion pattern for working copies
+		if (((IPackageFragment)getParent()).getKind() == IPackageFragmentRoot.K_BINARY
+				|| !isValidCompilationUnit()
+				|| !underlyingResource.isAccessible()) {
+			throw newNotPresentException();
+		}
+	}
+	
+	// prevents reopening of non-primary working copies (they are closed when they are discarded and should not be reopened)
+	if (!isPrimary() && getPerWorkingCopyInfo() == null) {
+		throw newNotPresentException();
+	}
+
+	CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info;
+
+	// get buffer contents
+	IBuffer buffer = getBufferManager().getBuffer(CompilationUnit.this);
+	if (buffer == null) {
+		buffer = openBuffer(pm, unitInfo); // open buffer independently from the info, since we are building the info
+	}
+	final char[] contents = buffer == null ? null : buffer.getCharacters();
+
+	// generate structure and compute syntax problems if needed
+	CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements);
+	JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = getPerWorkingCopyInfo();
+	boolean computeProblems = perWorkingCopyInfo != null && perWorkingCopyInfo.isActive();
+	IProblemFactory problemFactory = new DefaultProblemFactory();
+	SourceElementParser parser = new SourceElementParser(
+		requestor, 
+		problemFactory, 
+		new CompilerOptions(getJavaProject().getOptions(true)),
+		true/*report local declarations*/);
+	requestor.parser = parser;
+	CompilationUnitDeclaration unit = parser.parseCompilationUnit(new org.eclipse.jdt.internal.compiler.env.ICompilationUnit() {
+			public char[] getContents() {
+				return contents;
+			}
+			public char[] getMainTypeName() {
+				return CompilationUnit.this.getMainTypeName();
+			}
+			public char[][] getPackageName() {
+				return CompilationUnit.this.getPackageName();
+			}
+			public char[] getFileName() {
+				return CompilationUnit.this.getFileName();
+			}
+		}, true /*full parse to find local elements*/);
+	
+	// update timestamp (might be IResource.NULL_STAMP if original does not exist)
+	if (underlyingResource == null) {
+		underlyingResource = getResource();
+	}
+	unitInfo.timestamp = ((IFile)underlyingResource).getModificationStamp();
+	
+	// compute other problems if needed
+	if (computeProblems){
+		perWorkingCopyInfo.beginReporting();
+		CompilationUnitProblemFinder.process(unit, this, parser, perWorkingCopyInfo, problemFactory, pm);
+		perWorkingCopyInfo.endReporting();
+	}
+	
+	return unitInfo.isStructureKnown();
+}
+/*
+ * @see Openable#canBeRemovedFromCache
+ */
+public boolean canBeRemovedFromCache() {
+	if (getPerWorkingCopyInfo() != null) return false; // working copies should remain in the cache until they are destroyed
+	return super.canBeRemovedFromCache();
+}
+/*
+ * @see Openable#canBufferBeRemovedFromCache
+ */
+public boolean canBufferBeRemovedFromCache(IBuffer buffer) {
+	if (getPerWorkingCopyInfo() != null) return false; // working copy buffers should remain in the cache until working copy is destroyed
+	return super.canBufferBeRemovedFromCache(buffer);
+}/*
+ * @see IOpenable#close
+ */
+public void close() throws JavaModelException {
+	if (getPerWorkingCopyInfo() != null) return; // a working copy must remain opened until it is discarded
+	super.close();
+}
+/*
+ * @see Openable#closing
+ */
+protected void closing(Object info) {
+	if (getPerWorkingCopyInfo() == null) {
+		super.closing(info);
+	} // else the buffer of a working copy must remain open for the lifetime of the working copy
+}
 /**
  * @see ICodeAssist#codeComplete(int, ICompletionRequestor)
  */
 public void codeComplete(int offset, ICompletionRequestor requestor) throws JavaModelException {
-	codeComplete(this, isWorkingCopy() ? (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) getOriginalElement() : this, offset, requestor);
+	codeComplete(offset, requestor, DefaultWorkingCopyOwner.PRIMARY);
+}
+/**
+ * @see ICodeAssist#codeComplete(int, ICompletionRequestor, WorkingCopyOwner)
+ */
+public void codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner workingCopyOwner) throws JavaModelException {
+	codeComplete(this, isWorkingCopy() ? (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) getOriginalElement() : this, offset, requestor, workingCopyOwner);
+}
+/**
+ * @see ICodeAssist#codeComplete(int, ICodeCompletionRequestor)
+ * @deprecated - use codeComplete(int, ICompletionRequestor)
+ */
+public void codeComplete(int offset, final ICodeCompletionRequestor requestor) throws JavaModelException {
+	
+	if (requestor == null){
+		codeComplete(offset, (ICompletionRequestor)null);
+		return;
+	}
+	codeComplete(
+		offset,
+		new ICompletionRequestor(){
+			public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
+				// ignore
+			}
+			public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
+				requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
+			}
+			public void acceptError(IProblem error) {
+				if (true) return; // was disabled in 1.0
+
+				try {
+					IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaModelMarker.TRANSIENT_PROBLEM);
+					marker.setAttribute(IJavaModelMarker.ID, error.getID());
+					marker.setAttribute(IMarker.CHAR_START, error.getSourceStart());
+					marker.setAttribute(IMarker.CHAR_END, error.getSourceEnd() + 1);
+					marker.setAttribute(IMarker.LINE_NUMBER, error.getSourceLineNumber());
+					marker.setAttribute(IMarker.MESSAGE, error.getMessage());
+					marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
+					requestor.acceptError(marker);
+				} catch(CoreException e){
+					// ignore
+				}
+			}
+			public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
+				requestor.acceptField(declaringTypePackageName, declaringTypeName, fieldName, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
+			}
+			public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
+				requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd);
+			}
+			public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance){
+				requestor.acceptKeyword(keywordName, completionStart, completionEnd);
+			}
+			public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){
+				requestor.acceptLabel(labelName, completionStart, completionEnd);
+			}
+			public void acceptLocalVariable(char[] localVarName,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){
+				// ignore
+			}
+			public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
+				// skip parameter names
+				requestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd);
+			}
+			public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
+				// ignore
+			}
+			public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance){
+				requestor.acceptModifier(modifierName, completionStart, completionEnd);
+			}
+			public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance){
+				requestor.acceptPackage(packageName, completionName, completionStart, completionEnd);
+			}
+			public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance){
+				requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd);
+			}
+			public void acceptVariableName(char[] typePackageName,char[] typeName,char[] varName,char[] completionName,int completionStart,int completionEnd, int relevance){
+				// ignore
+			}
+		});
 }
 /**
  * @see ICodeAssist#codeSelect(int, int)
  */
 public IJavaElement[] codeSelect(int offset, int length) throws JavaModelException {
-	return super.codeSelect(this, offset, length);
+	return codeSelect(offset, length, DefaultWorkingCopyOwner.PRIMARY);
+}
+/**
+ * @see ICodeAssist#codeSelect(int, int, WorkingCopyOwner)
+ */
+public IJavaElement[] codeSelect(int offset, int length, WorkingCopyOwner workingCopyOwner) throws JavaModelException {
+	return super.codeSelect(this, offset, length, workingCopyOwner);
 }
 /**
  * @see IWorkingCopy#commit(boolean, IProgressMonitor)
+ * @deprecated
  */
 public void commit(boolean force, IProgressMonitor monitor) throws JavaModelException {
-	throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this));
+	commitWorkingCopy(force, monitor);
+}
+/**
+ * @see ICompilationUnit#commitWorkingCopy(boolean, IProgressMonitor)
+ */
+public void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException {
+	CommitWorkingCopyOperation op= new CommitWorkingCopyOperation(this, force);
+	runOperation(op, monitor);
 }
 /**
  * @see ISourceManipulation#copy(IJavaElement, IJavaElement, String, boolean, IProgressMonitor)
@@ -123,28 +299,28 @@
 /**
  * Returns a new element info for this element.
  */
-protected OpenableElementInfo createElementInfo() {
+protected Object createElementInfo() {
 	return new CompilationUnitElementInfo();
 }
 /**
  * @see ICompilationUnit#createImport(String, IJavaElement, IProgressMonitor)
  */
-public IImportDeclaration createImport(String name, IJavaElement sibling, IProgressMonitor monitor) throws JavaModelException {
-	CreateImportOperation op = new CreateImportOperation(name, this);
+public IImportDeclaration createImport(String importName, IJavaElement sibling, IProgressMonitor monitor) throws JavaModelException {
+	CreateImportOperation op = new CreateImportOperation(importName, this);
 	if (sibling != null) {
 		op.createBefore(sibling);
 	}
 	runOperation(op, monitor);
-	return getImport(name);
+	return getImport(importName);
 }
 /**
  * @see ICompilationUnit#createPackageDeclaration(String, IProgressMonitor)
  */
-public IPackageDeclaration createPackageDeclaration(String name, IProgressMonitor monitor) throws JavaModelException {
+public IPackageDeclaration createPackageDeclaration(String pkg, IProgressMonitor monitor) throws JavaModelException {
 	
-	CreatePackageDeclarationOperation op= new CreatePackageDeclarationOperation(name, this);
+	CreatePackageDeclarationOperation op= new CreatePackageDeclarationOperation(pkg, this);
 	runOperation(op, monitor);
-	return getPackageDeclaration(name);
+	return getPackageDeclaration(pkg);
 }
 /**
  * @see ICompilationUnit#createType(String, IJavaElement, boolean, IProgressMonitor)
@@ -158,7 +334,7 @@
 			//not the default package...add the package declaration
 			source = "package " + pkg.getElementName() + ";"  + org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR + org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR; //$NON-NLS-1$ //$NON-NLS-2$
 		}
-		CreateCompilationUnitOperation op = new CreateCompilationUnitOperation(pkg, fName, source, force);
+		CreateCompilationUnitOperation op = new CreateCompilationUnitOperation(pkg, this.name, source, force);
 		runOperation(op, monitor);
 	}
 	CreateTypeOperation op = new CreateTypeOperation(this, content, force);
@@ -176,48 +352,68 @@
 	getJavaModel().delete(elements, force, monitor);
 }
 /**
- * This is not a working copy, do nothing.
- *
  * @see IWorkingCopy#destroy()
+ * @deprecated
  */
 public void destroy() {
+	try {
+		discardWorkingCopy();
+	} catch (JavaModelException e) {
+		e.printStackTrace();
+	}
 }
-
-
+/*
+ * @see ICompilationUnit#discardWorkingCopy
+ */
+public void discardWorkingCopy() throws JavaModelException {
+	// discard working copy and its children
+	DiscardWorkingCopyOperation op = new DiscardWorkingCopyOperation(this);
+	runOperation(op, null);
+}
 /**
  * Returns true if this handle represents the same Java element
  * as the given handle.
  *
- * <p>Compilation units must also check working copy state;
- *
  * @see Object#equals(java.lang.Object)
  */
-public boolean equals(Object o) {
-	return super.equals(o) && !((ICompilationUnit)o).isWorkingCopy();
+public boolean equals(Object obj) {
+	if (!(obj instanceof CompilationUnit)) return false;
+	CompilationUnit other = (CompilationUnit)obj;
+	return this.owner.equals(other.owner) && super.equals(obj);
 }
 /**
  * @see JavaElement#equalsDOMNode(IDOMNode)
  */
-protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
-	String name = getElementName();
-	if (node.getNodeType() == IDOMNode.COMPILATION_UNIT && name != null ) {
+protected boolean equalsDOMNode(IDOMNode node) {
+	String elementName = getElementName();
+	if (node.getNodeType() == IDOMNode.COMPILATION_UNIT && elementName != null ) {
 		String nodeName = node.getName();
 		if (nodeName == null) return false;		
-		if (name.equals(nodeName)) {
+		if (elementName.equals(nodeName)) {
 			return true;
 		} else {
-			// iterate through all the types inside the receiver and see if one of them can fit
-			IType[] types = getTypes();
-			String typeNodeName = nodeName.substring(0, nodeName.indexOf(".java")); //$NON-NLS-1$
-			for (int i = 0, max = types.length; i < max; i++) {
-				if (types[i].getElementName().equals(typeNodeName)) {
-					return true;
+			try {
+				// iterate through all the types inside the receiver and see if one of them can fit
+				IType[] types = getTypes();
+				String typeNodeName = nodeName.substring(0, nodeName.indexOf(SUFFIX_STRING_java));
+				for (int i = 0, max = types.length; i < max; i++) {
+					if (types[i].getElementName().equals(typeNodeName)) {
+						return true;
+					}
 				}
+			} catch (JavaModelException e) {
+				return false;
 			}
 		}
 	}
 	return false;
 }
+public boolean exists() {
+	// working copy always exists in the model until it is gotten rid of
+	if (getPerWorkingCopyInfo() != null) return true;	
+	
+	return super.exists();
+}
 /**
  * @see IWorkingCopy#findElements(IJavaElement)
  */
@@ -230,7 +426,7 @@
 	if (element == null) return null;
 	IJavaElement currentElement = this;
 	for (int i = children.size()-1; i >= 0; i--) {
-		IJavaElement child = (IJavaElement)children.get(i);
+		JavaElement child = (JavaElement)children.get(i);
 		switch (child.getElementType()) {
 			case IJavaElement.PACKAGE_DECLARATION:
 				currentElement = ((ICompilationUnit)currentElement).getPackageDeclaration(child.getElementName());
@@ -242,20 +438,29 @@
 				currentElement = ((IImportContainer)currentElement).getImport(child.getElementName());
 				break;
 			case IJavaElement.TYPE:
-				if (currentElement.getElementType() == IJavaElement.COMPILATION_UNIT) {
-					currentElement = ((ICompilationUnit)currentElement).getType(child.getElementName());
-				} else {
-					currentElement = ((IType)currentElement).getType(child.getElementName());
+				switch (currentElement.getElementType()) {
+					case IJavaElement.COMPILATION_UNIT:
+						currentElement = ((ICompilationUnit)currentElement).getType(child.getElementName());
+						break;
+					case IJavaElement.TYPE:
+						currentElement = ((IType)currentElement).getType(child.getElementName());
+						break;
+					case IJavaElement.FIELD:
+					case IJavaElement.INITIALIZER:
+					case IJavaElement.METHOD:
+						currentElement =  ((IMember)currentElement).getType(child.getElementName(), child.occurrenceCount);
+						break;
 				}
 				break;
 			case IJavaElement.INITIALIZER:
-				currentElement = ((IType)currentElement).getInitializer(((JavaElement)child).getOccurrenceCount());
+				currentElement = ((IType)currentElement).getInitializer(child.occurrenceCount);
 				break;
 			case IJavaElement.FIELD:
 				currentElement = ((IType)currentElement).getField(child.getElementName());
 				break;
 			case IJavaElement.METHOD:
-				return ((IType)currentElement).findMethods((IMethod)child);
+				currentElement = ((IType)currentElement).getMethod(child.getElementName(), ((IMethod)child).getParameterTypes());
+				break;
 		}
 		
 	}
@@ -279,44 +484,31 @@
 
 /**
  * @see IWorkingCopy#findSharedWorkingCopy(IBufferFactory)
+ * @deprecated
  */
 public IJavaElement findSharedWorkingCopy(IBufferFactory factory) {
 
 	// if factory is null, default factory must be used
 	if (factory == null) factory = this.getBufferManager().getDefaultBufferFactory();
-
-	// In order to be shared, working copies have to denote the same compilation unit 
-	// AND use the same buffer factory.
-	// Assuming there is a little set of buffer factories, then use a 2 level Map cache.
-	Map sharedWorkingCopies = JavaModelManager.getJavaModelManager().sharedWorkingCopies;
 	
-	Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(factory);
-	if (perFactoryWorkingCopies == null) return null;
-	return (WorkingCopy)perFactoryWorkingCopies.get(this);
+	return findWorkingCopy(BufferFactoryWrapper.create(factory));
 }
 
-protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
-
-	if (getParent() instanceof JarPackageFragment) {
-		// ignore .java files in jar
-		throw newNotPresentException();
+/**
+ * @see ICompilationUnit#findWorkingCopy(WorkingCopyOwner)
+ */
+public ICompilationUnit findWorkingCopy(WorkingCopyOwner workingCopyOwner) {
+	CompilationUnit cu = new CompilationUnit((PackageFragment)this.parent, getElementName(), workingCopyOwner);
+	if (workingCopyOwner == DefaultWorkingCopyOwner.PRIMARY) {
+		return cu;
 	} else {
-		// put the info now, because getting the contents requires it
-		JavaModelManager.getJavaModelManager().putInfo(this, info);
-		CompilationUnitElementInfo unitInfo = (CompilationUnitElementInfo) info;
-
-		// generate structure
-		CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements);
-		IProblemFactory factory = new DefaultProblemFactory();
-		SourceElementParser parser = new SourceElementParser(requestor, factory, new CompilerOptions(getJavaProject().getOptions(true)));
-		requestor.parser = parser;
-		parser.parseCompilationUnit(this, false);
-		if (isWorkingCopy()) {
-			CompilationUnit original = (CompilationUnit) getOriginalElement();
-			// might be IResource.NULL_STAMP if original does not exist
-			unitInfo.fTimestamp = ((IFile) original.getResource()).getModificationStamp();
+		// must be a working copy
+		JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = cu.getPerWorkingCopyInfo();
+		if (perWorkingCopyInfo != null) {
+			return perWorkingCopyInfo.getWorkingCopy();
+		} else {
+			return null;
 		}
-		return unitInfo.isStructureKnown();
 	}
 }
 /**
@@ -386,9 +578,36 @@
 		return e;
 	}
 }
+/**
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return COMPILATION_UNIT;
+}
 public char[] getFileName(){
 	return getElementName().toCharArray();
 }
+/*
+ * @see JavaElement
+ */
+public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner workingCopyOwner) {
+	switch (token.charAt(0)) {
+		case JEM_COUNT:
+			return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
+		case JEM_IMPORTDECLARATION:
+			JavaElement container = (JavaElement)getImportContainer();
+			return container.getHandleFromMemento(token, memento, workingCopyOwner);
+		case JEM_PACKAGEDECLARATION:
+			String pkgName = memento.nextToken();
+			JavaElement pkgDecl = (JavaElement)getPackageDeclaration(pkgName);
+			return pkgDecl.getHandleFromMemento(memento, workingCopyOwner);
+		case JEM_TYPE:
+			String typeName = memento.nextToken();
+			JavaElement type = (JavaElement)getType(typeName);
+			return type.getHandleFromMemento(memento, workingCopyOwner);
+	}
+	return null;
+}
 /**
  * @see JavaElement#getHandleMementoDelimiter()
  */
@@ -398,8 +617,8 @@
 /**
  * @see ICompilationUnit#getImport(String)
  */
-public IImportDeclaration getImport(String name) {
-	return new ImportDeclaration(getImportContainer(), name);
+public IImportDeclaration getImport(String importName) {
+	return new ImportDeclaration((ImportContainer)getImportContainer(), importName);
 }
 /**
  * @see ICompilationUnit#getImportContainer()
@@ -430,32 +649,46 @@
  * @see org.eclipse.jdt.internal.compiler.env.ICompilationUnit#getMainTypeName()
  */
 public char[] getMainTypeName(){
-	String name= getElementName();
+	String elementName = getElementName();
 	//remove the .java
-	name= name.substring(0, name.length() - 5);
-	return name.toCharArray();
+	elementName = elementName.substring(0, elementName.length() - 5);
+	return elementName.toCharArray();
 }
 /**
- * Returns <code>null</code>, this is not a working copy.
- *
  * @see IWorkingCopy#getOriginal(IJavaElement)
+ * @deprecated
  */
 public IJavaElement getOriginal(IJavaElement workingCopyElement) {
-	return null;
+	// backward compatibility
+	if (!isWorkingCopy()) return null;
+	CompilationUnit cu = (CompilationUnit)workingCopyElement.getAncestor(COMPILATION_UNIT);
+	if (cu == null || !this.owner.equals(cu.owner)) {
+		return null;
+	}
+	
+	return workingCopyElement.getPrimaryElement();
 }
 /**
- * Returns <code>null</code>, this is not a working copy.
- *
  * @see IWorkingCopy#getOriginalElement()
+ * @deprecated
  */
 public IJavaElement getOriginalElement() {
-	return null;
+	// backward compatibility
+	if (!isWorkingCopy()) return null;
+	
+	return getPrimaryElement();
+}
+/*
+ * @see ICompilationUnit#getOwner()
+ */
+public WorkingCopyOwner getOwner() {
+	return isPrimary() || !isWorkingCopy() ? null : this.owner;
 }
 /**
  * @see ICompilationUnit#getPackageDeclaration(String)
  */
-public IPackageDeclaration getPackageDeclaration(String name) {
-	return new PackageDeclaration(this, name);
+public IPackageDeclaration getPackageDeclaration(String pkg) {
+	return new PackageDeclaration(this, pkg);
 }
 /**
  * @see ICompilationUnit#getPackageDeclarations()
@@ -483,6 +716,26 @@
 		return this.getParent().getPath().append(this.getElementName());
 	}
 }
+/*
+ * Returns the per working copy info for the receiver, or null if none exist.
+ * Note: the use count of the per working copy info is NOT incremented.
+ */
+public JavaModelManager.PerWorkingCopyInfo getPerWorkingCopyInfo() {
+	return JavaModelManager.getJavaModelManager().getPerWorkingCopyInfo(this, getPath(), false/*don't create*/, false/*don't record usage*/, null/*no problem requestor needed*/);
+}
+/*
+ * @see ICompilationUnit#getPrimary()
+ */
+public ICompilationUnit getPrimary() {
+	return (ICompilationUnit)getPrimaryElement(true);
+}
+/*
+ * @see JavaElement#getPrimaryElement(boolean)
+ */
+public IJavaElement getPrimaryElement(boolean checkOwner) {
+	if (checkOwner && isPrimary()) return this;
+	return new CompilationUnit((PackageFragment)getParent(), getElementName(), DefaultWorkingCopyOwner.PRIMARY);
+}
 /**
  * @see IJavaElement#getResource()
  */
@@ -494,7 +747,6 @@
 		return ((IContainer)this.getParent().getResource()).getFile(new Path(this.getElementName()));
 	}
 }
-
 /**
  * @see ISourceReference#getSource()
  */
@@ -512,8 +764,8 @@
 /**
  * @see ICompilationUnit#getType(String)
  */
-public IType getType(String name) {
-	return new SourceType(this, name);
+public IType getType(String typeName) {
+	return new SourceType(this, typeName);
 }
 /**
  * @see ICompilationUnit#getTypes()
@@ -524,64 +776,63 @@
 	list.toArray(array);
 	return array;
 }
+/**
+ * @see IJavaElement
+ */
 public IResource getUnderlyingResource() throws JavaModelException {
-	if (FIX_BUG25184) {
-		return super.getUnderlyingResource();
-	} else {
-		return getResource();
-	}
+	if (isWorkingCopy() && !isPrimary()) return null;
+	return super.getUnderlyingResource();
 }
 /**
  * @see IWorkingCopy#getSharedWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
+ * @deprecated
  */
 public IJavaElement getSharedWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException {
 	
 	// if factory is null, default factory must be used
 	if (factory == null) factory = this.getBufferManager().getDefaultBufferFactory();
-
-	JavaModelManager manager = JavaModelManager.getJavaModelManager();
 	
-	// In order to be shared, working copies have to denote the same compilation unit 
-	// AND use the same buffer factory.
-	// Assuming there is a little set of buffer factories, then use a 2 level Map cache.
-	Map sharedWorkingCopies = manager.sharedWorkingCopies;
-	
-	Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(factory);
-	if (perFactoryWorkingCopies == null){
-		perFactoryWorkingCopies = new HashMap();
-		sharedWorkingCopies.put(factory, perFactoryWorkingCopies);
-	}
-	WorkingCopy workingCopy = (WorkingCopy)perFactoryWorkingCopies.get(this);
-	if (workingCopy != null) {
-		workingCopy.useCount++;
-
-		if (SHARED_WC_VERBOSE) {
-			System.out.println("Incrementing use count of shared working copy " + workingCopy.toStringWithAncestors()); //$NON-NLS-1$
-		}
-
-		return workingCopy;
-	} else {
-		CreateWorkingCopyOperation op = new CreateWorkingCopyOperation(this, perFactoryWorkingCopies, factory, problemRequestor);
-		runOperation(op, pm);
-		return op.getResultElements()[0];
-	}
+	return getWorkingCopy(BufferFactoryWrapper.create(factory), problemRequestor, pm);
 }
 /**
  * @see IWorkingCopy#getWorkingCopy()
+ * @deprecated
  */
 public IJavaElement getWorkingCopy() throws JavaModelException {
-	return this.getWorkingCopy(null, null, null);
+	return getWorkingCopy(null);
 }
-
+/**
+ * @see ICompilationUnit#getWorkingCopy(IProgressMonitor)
+ */
+public ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException {
+	return getWorkingCopy(new WorkingCopyOwner() {/*non shared working copy*/}, null/*no problem requestor*/, monitor);
+}
 /**
  * @see IWorkingCopy#getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)
+ * @deprecated
  */
-public IJavaElement getWorkingCopy(IProgressMonitor pm, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException {
-	CreateWorkingCopyOperation op = new CreateWorkingCopyOperation(this, null, factory, problemRequestor);
-	runOperation(op, pm);
-	return op.getResultElements()[0];
+public IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException {
+	return getWorkingCopy(BufferFactoryWrapper.create(factory), problemRequestor, monitor);
 }
-
+/**
+ * @see IWorkingCopy#getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)
+ */
+public ICompilationUnit getWorkingCopy(WorkingCopyOwner workingCopyOwner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException {
+	if (!isPrimary()) return this;
+	
+	JavaModelManager manager = JavaModelManager.getJavaModelManager();
+	
+	CompilationUnit workingCopy = new CompilationUnit((PackageFragment)getParent(), getElementName(), workingCopyOwner);
+	IPath path = getPath();
+	JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = 
+		manager.getPerWorkingCopyInfo(workingCopy, path, false/*don't create*/, true/*record usage*/, null/*not used since don't create*/);
+	if (perWorkingCopyInfo != null) {
+		return perWorkingCopyInfo.getWorkingCopy(); // return existing handle instead of the one created above
+	}
+	BecomeWorkingCopyOperation op = new BecomeWorkingCopyOperation(workingCopy, path, problemRequestor);
+	runOperation(op, monitor);
+	return workingCopy;
+}
 /**
  * @see Openable#hasBuffer()
  */
@@ -600,43 +851,87 @@
 		return true;
 	}
 }
+/*
+ * @see ICompilationUnit#hasResourceChanged()
+ */
+public boolean hasResourceChanged() {
+	if (!isWorkingCopy()) return false;
+	
+	// if resource got deleted, then #getModificationStamp() will answer IResource.NULL_STAMP, which is always different from the cached
+	// timestamp
+	Object info = JavaModelManager.getJavaModelManager().getInfo(this);
+	if (info == null) return false;
+	return ((CompilationUnitElementInfo)info).timestamp != getResource().getModificationStamp();
+}
 /**
- * Returns false, this is not a working copy.
- *
  * @see IWorkingCopy#isBasedOn(IResource)
+ * @deprecated
  */
 public boolean isBasedOn(IResource resource) {
-	return false;
+	if (!isWorkingCopy()) return false;
+	if (!getResource().equals(resource)) return false;
+	return !hasResourceChanged();
 }
 /**
  * @see IOpenable#isConsistent()
  */
-public boolean isConsistent() throws JavaModelException {
+public boolean isConsistent() {
 	return JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().get(this) == null;
 }
 /**
+ * 
+ * @see IOpenable
+ */
+public boolean isOpen() {
+	Object info = JavaModelManager.getJavaModelManager().getInfo(this);
+	return info != null && ((CompilationUnitElementInfo)info).isOpen();
+}
+public boolean isPrimary() {
+	return this.owner == DefaultWorkingCopyOwner.PRIMARY;
+}
+/**
  * @see Openable#isSourceElement()
  */
 protected boolean isSourceElement() {
 	return true;
 }
-/**
- * @see IWorkingCopy#isWorkingCopy()
+protected boolean isValidCompilationUnit() {
+	IPackageFragmentRoot root = getPackageFragmentRoot();
+	try {
+		if (root.getKind() != IPackageFragmentRoot.K_SOURCE) return false;
+	} catch (JavaModelException e) {
+		return false;
+	}
+	IResource resource = getResource();
+	if (resource != null) {
+		char[][] exclusionPatterns = ((PackageFragmentRoot)root).fullExclusionPatternChars();
+		if (Util.isExcluded(resource, exclusionPatterns)) return false;
+	}
+	if (!Util.isValidCompilationUnitName(getElementName())) return false;
+	return true;
+}
+/*
+ * @see ICompilationUnit#isWorkingCopy()
  */
 public boolean isWorkingCopy() {
-	return false;
+	// For backward compatibility, non primary working copies are always returning true; in removal
+	// delta, clients can still check that element was a working copy before being discarded.
+	return !isPrimary() || getPerWorkingCopyInfo() != null;
 }
 /**
  * @see IOpenable#makeConsistent(IProgressMonitor)
  */
 public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
-	if (!isConsistent()) { // TODO: this code isn't synchronized with regular opening of a working copy
-		// create a new info and make it the current info
-		OpenableElementInfo info = createElementInfo();
-		buildStructure(info, monitor);
-	}
+	if (isConsistent()) return;
+		
+	// close
+	JavaModelManager manager = JavaModelManager.getJavaModelManager();
+	// working copy: remove info from cache, but keep buffer open
+	manager.removeInfoAndChildren(this);
+	
+	// create a new info and make it the current info
+	openWhenClosed(createElementInfo(), monitor);
 }
-
 /**
  * @see ISourceManipulation#move(IJavaElement, IJavaElement, String, boolean, IProgressMonitor)
  */
@@ -657,21 +952,41 @@
 /**
  * @see Openable#openBuffer(IProgressMonitor)
  */
-protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException {
+protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException {
 
-	// create buffer -  compilation units only use default buffer factory
-	BufferManager bufManager = getBufferManager();
-	IBuffer buffer = getBufferFactory().createBuffer(this);
+	// create buffer
+	boolean isWorkingCopy = isWorkingCopy();
+	IBuffer buffer = 
+		isWorkingCopy 
+			? this.owner.createBuffer(this) 
+			: BufferManager.getDefaultBufferManager().createBuffer(this);
 	if (buffer == null) return null;
 	
 	// set the buffer source
-	if (buffer.getCharacters() == null){
-		IFile file = (IFile)this.getResource();
-		if (file == null || !file.exists()) throw newNotPresentException();
-		buffer.setContents(Util.getResourceContentsAsCharArray(file));
+	if (buffer.getCharacters() == null) {
+		if (isWorkingCopy) {
+			ICompilationUnit original;
+			if (!isPrimary() 
+					&& (original = new CompilationUnit((PackageFragment)getParent(), getElementName(), DefaultWorkingCopyOwner.PRIMARY)).isOpen()) {
+				buffer.setContents(original.getSource());
+			} else {
+				IFile file = (IFile)getResource();
+				if (file == null || !file.exists()) {
+					// initialize buffer with empty contents
+					buffer.setContents(CharOperation.NO_CHAR);
+				} else {
+					buffer.setContents(Util.getResourceContentsAsCharArray(file));
+				}
+			}
+		} else {
+			IFile file = (IFile)this.getResource();
+			if (file == null || !file.exists()) throw newNotPresentException();
+			buffer.setContents(Util.getResourceContentsAsCharArray(file));
+		}
 	}
 
 	// add buffer to buffer cache
+	BufferManager bufManager = getBufferManager();
 	bufManager.addBuffer(buffer);
 			
 	// listen to buffer changes
@@ -679,142 +994,137 @@
 	
 	return buffer;
 }
-protected void openParent(IProgressMonitor pm) throws JavaModelException {
-	if (FIX_BUG25184) {
-		super.openParent(pm);
-	} else {
-		try {
-			super.openParent(pm);
-		} catch(JavaModelException e){
-			// allow parent to not exist for compilation units defined outside classpath
-			if (!e.isDoesNotExist()){ 
-				throw e;
-			}
+/*
+ * @see Openable#openParent
+ */
+protected void openParent(Object childInfo, HashMap newElements, IProgressMonitor pm) throws JavaModelException {
+	try {
+		super.openParent(childInfo, newElements, pm);
+	} catch(JavaModelException e){
+		// allow parent to not exist for working copies defined outside classpath
+		if (!isWorkingCopy() && !e.isDoesNotExist()){ 
+			throw e;
 		}
 	}
 }
-protected boolean parentExists() {
-	if (FIX_BUG25184) {
-		return super.parentExists();
-	} else {
-		return true; // tolerate units outside classpath
-	}
-}
-
 /**
- * @see IWorkingCopy#reconcile()
+ * @see ICompilationUnit#reconcile()
+ * @deprecated
  */
 public IMarker[] reconcile() throws JavaModelException {
-	// Reconciling is not supported on non working copies
+	reconcile(false, null);
 	return null;
 }
-
 /**
- * @see IWorkingCopy#reconcile(boolean, IProgressMonitor)
+ * @see ICompilationUnit#reconcile(boolean, IProgressMonitor)
+ */
+public void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws JavaModelException {
+	reconcile(forceProblemDetection, DefaultWorkingCopyOwner.PRIMARY, monitor);
+}
+/**
+ * @see ICompilationUnit#reconcile(boolean, WorkingCopyOwner, IProgressMonitor)
  */
 public void reconcile(
 	boolean forceProblemDetection,
+	WorkingCopyOwner workingCopyOwner,
 	IProgressMonitor monitor)
 	throws JavaModelException {
-	// Reconciling is not supported on non working copies
-}
 
+	if (!isWorkingCopy()) return; // Reconciling is not supported on non working copies
+	
+	NameLookup lookup = null;
+	try {
+		// set the units to look inside only for problem detection purpose (40322)
+		if (forceProblemDetection) {
+			try {
+				lookup = ((JavaProject)getJavaProject()).getNameLookup();
+				JavaModelManager manager = JavaModelManager.getJavaModelManager();
+				ICompilationUnit[] workingCopies = manager.getWorkingCopies(workingCopyOwner, true/*add primary WCs*/);
+				lookup.setUnitsToLookInside(workingCopies);
+			} catch(JavaModelException e) {
+				// simple project may not find its namelookup, simply ignore working copies (41583)
+			}
+		}			
+		// reconcile
+		ReconcileWorkingCopyOperation op = new ReconcileWorkingCopyOperation(this, forceProblemDetection);
+		runOperation(op, monitor);
+	} finally {
+		if (lookup != null) {
+			lookup.setUnitsToLookInside(null);
+		}
+	}
+}
 /**
  * @see ISourceManipulation#rename(String, boolean, IProgressMonitor)
  */
-public void rename(String name, boolean force, IProgressMonitor monitor) throws JavaModelException {
-	if (name == null) {
+public void rename(String newName, boolean force, IProgressMonitor monitor) throws JavaModelException {
+	if (newName == null) {
 		throw new IllegalArgumentException(Util.bind("operation.nullName")); //$NON-NLS-1$
 	}
 	IJavaElement[] elements= new IJavaElement[] {this};
 	IJavaElement[] dests= new IJavaElement[] {this.getParent()};
-	String[] renamings= new String[] {name};
+	String[] renamings= new String[] {newName};
 	getJavaModel().rename(elements, dests, renamings, force, monitor);
 }
-/**
- * Does nothing - this is not a working copy.
- *
- * @see IWorkingCopy#restore()
+/*
+ * @see ICompilationUnit
  */
-public void restore () throws JavaModelException {
-}
-/**
- * @see ICodeAssist#codeComplete(int, ICodeCompletionRequestor)
- * @deprecated - use codeComplete(int, ICompletionRequestor)
- */
-public void codeComplete(int offset, final ICodeCompletionRequestor requestor) throws JavaModelException {
-	
-	if (requestor == null){
-		codeComplete(offset, (ICompletionRequestor)null);
-		return;
-	}
-	codeComplete(
-		offset,
-		new ICompletionRequestor(){
-			public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
-			}
-			public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-				requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
-			}
-			public void acceptError(IProblem error) {
-				if (true) return; // was disabled in 1.0
+public void restore() throws JavaModelException {
 
-				try {
-					IMarker marker = ResourcesPlugin.getWorkspace().getRoot().createMarker(IJavaModelMarker.TRANSIENT_PROBLEM);
-					marker.setAttribute(IJavaModelMarker.ID, error.getID());
-					marker.setAttribute(IMarker.CHAR_START, error.getSourceStart());
-					marker.setAttribute(IMarker.CHAR_END, error.getSourceEnd() + 1);
-					marker.setAttribute(IMarker.LINE_NUMBER, error.getSourceLineNumber());
-					marker.setAttribute(IMarker.MESSAGE, error.getMessage());
-					marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
-					requestor.acceptError(marker);
-				} catch(CoreException e){
-				}
-			}
-			public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-				requestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
-			}
-			public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
-				requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd);
-			}
-			public void acceptKeyword(char[] keywordName,int completionStart,int completionEnd, int relevance){
-				requestor.acceptKeyword(keywordName, completionStart, completionEnd);
-			}
-			public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){
-				requestor.acceptLabel(labelName, completionStart, completionEnd);
-			}
-			public void acceptLocalVariable(char[] name,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){
-				// ignore
-			}
-			public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
-				// skip parameter names
-				requestor.acceptMethod(declaringTypePackageName, declaringTypeName, selector, parameterPackageNames, parameterTypeNames, returnTypePackageName, returnTypeName, completionName, modifiers, completionStart, completionEnd);
-			}
-			public void acceptMethodDeclaration(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
-				// ignore
-			}
-			public void acceptModifier(char[] modifierName,int completionStart,int completionEnd, int relevance){
-				requestor.acceptModifier(modifierName, completionStart, completionEnd);
-			}
-			public void acceptPackage(char[] packageName,char[] completionName,int completionStart,int completionEnd, int relevance){
-				requestor.acceptPackage(packageName, completionName, completionStart, completionEnd);
-			}
-			public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance){
-				requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd);
-			}
-			public void acceptVariableName(char[] typePackageName,char[] typeName,char[] name,char[] completionName,int completionStart,int completionEnd, int relevance){
-				// ignore
-			}
-		});
+	if (!isWorkingCopy()) return;
+
+	CompilationUnit original = (CompilationUnit) getOriginalElement();
+	IBuffer buffer = this.getBuffer();
+	if (buffer == null) return;
+	buffer.setContents(original.getContents());
+	updateTimeStamp(original);
+	makeConsistent(null);
 }
 /**
- * @see JavaElement#rootedAt(IJavaProject)
+ * @see IOpenable
  */
-public IJavaElement rootedAt(IJavaProject project) {
-	return
-		new CompilationUnit(
-			(IPackageFragment)((JavaElement)fParent).rootedAt(project), 
-			fName);
+public void save(IProgressMonitor pm, boolean force) throws JavaModelException {
+	if (isWorkingCopy()) {
+		// no need to save the buffer for a working copy (this is a noop)
+		reconcile();   // not simply makeConsistent, also computes fine-grain deltas
+								// in case the working copy is being reconciled already (if not it would miss
+								// one iteration of deltas).
+	} else {		
+		super.save(pm, force);
+	}
+}
+/**
+ * @private Debugging purposes
+ */
+protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
+	if (!isPrimary()) {
+		buffer.append(this.tabString(tab));
+		buffer.append("[Working copy] "); //$NON-NLS-1$
+		buffer.append(getElementName());
+	} else {
+		if (isWorkingCopy()) {
+			buffer.append(this.tabString(tab));
+			buffer.append("[Working copy] "); //$NON-NLS-1$
+			buffer.append(getElementName());
+			if (info == null) {
+				buffer.append(" (not open)"); //$NON-NLS-1$
+			}
+		} else {
+			super.toStringInfo(tab, buffer, info);
+		}
+	}
+}
+/*
+ * Assume that this is a working copy
+ */
+protected void updateTimeStamp(CompilationUnit original) throws JavaModelException {
+	long timeStamp =
+		((IFile) original.getResource()).getModificationStamp();
+	if (timeStamp == IResource.NULL_STAMP) {
+		throw new JavaModelException(
+			new JavaModelStatus(IJavaModelStatusConstants.INVALID_RESOURCE));
+	}
+	((CompilationUnitElementInfo) getElementInfo()).timestamp = timeStamp;
 }
 
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java
index e1e140e..54a66a7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitElementInfo.java
@@ -17,26 +17,29 @@
 	/**
 	 * The length of this compilation unit's source code <code>String</code>
 	 */
-	protected int fSourceLength;
+	protected int sourceLength;
 
 	/** 
 	 * Timestamp of original resource at the time this element
 	 * was opened or last updated.
 	 */
-	protected long fTimestamp;
+	protected long timestamp;
 /**
  * Returns the length of the source string.
  */
 public int getSourceLength() {
-	return fSourceLength;
+	return this.sourceLength;
 }
 protected ISourceRange getSourceRange() {
-	return new SourceRange(0, fSourceLength);
+	return new SourceRange(0, this.sourceLength);
+}
+protected boolean isOpen() {
+	return true;
 }
 /**
  * Sets the length of the source string.
  */
 public void setSourceLength(int newSourceLength) {
-	fSourceLength = newSourceLength;
+	this.sourceLength = newSourceLength;
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
index ca389c8..f4dfee5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
@@ -10,7 +10,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import java.util.Locale;
 import java.util.Map;
 
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -28,9 +27,10 @@
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
 import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
-import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Responsible for resolving types inside a compilation unit being reconciled,
@@ -98,15 +98,15 @@
 		CompilationUnitDeclaration unit =
 			SourceTypeConverter.buildCompilationUnit(
 				sourceTypes,//sourceTypes[0] is always toplevel here
-				true, // need field and methods
-				true, // need member types
-				true, // need field initialization
-				lookupEnvironment.problemReporter,
+				SourceTypeConverter.FIELD_AND_METHOD // need field and methods
+				| SourceTypeConverter.MEMBER_TYPE // need member types
+				| SourceTypeConverter.FIELD_INITIALIZATION, // need field initialization
+				this.lookupEnvironment.problemReporter,
 				result);
 
 		if (unit != null) {
 			this.lookupEnvironment.buildTypeBindings(unit);
-			this.lookupEnvironment.completeTypeBindings(unit, true);
+			this.lookupEnvironment.completeTypeBindings(unit);
 		}
 	}
 
@@ -129,59 +129,17 @@
 	protected static ICompilerRequestor getRequestor() {
 		return new ICompilerRequestor() {
 			public void acceptResult(CompilationResult compilationResult) {
-			}
-		};
-	}
-
-	protected static IProblemFactory getProblemFactory(
-		final char[] fileName, 
-		final IProblemRequestor problemRequestor,
-		final IProgressMonitor monitor) {
-
-		return new DefaultProblemFactory(Locale.getDefault()) {
-			public IProblem createProblem(
-				char[] originatingFileName,
-				int problemId,
-				String[] problemArguments,
-				String[] messageArguments,
-				int severity,
-				int startPosition,
-				int endPosition,
-				int lineNumber) {
-
-				if (monitor != null && monitor.isCanceled()){
-					throw new AbortCompilation(true, null); // silent abort
-				}
-				
-				IProblem problem =
-					super.createProblem(
-						originatingFileName,
-						problemId,
-						problemArguments,
-						messageArguments,
-						severity,
-						startPosition,
-						endPosition,
-						lineNumber);
-				// only report local problems
-				if (CharOperation.equals(originatingFileName, fileName)){
-					if (JavaModelManager.VERBOSE){
-						System.out.println("PROBLEM FOUND while reconciling : "+problem.getMessage());//$NON-NLS-1$
-					}
-					problemRequestor.acceptProblem(problem);
-				}
-				if (monitor != null && monitor.isCanceled()){
-					throw new AbortCompilation(true, null); // silent abort
-				}
-
-				return problem;
+				// default requestor doesn't handle compilation results back
 			}
 		};
 	}
 
 	public static CompilationUnitDeclaration process(
+		CompilationUnitDeclaration unit,
 		ICompilationUnit unitElement, 
+		Parser parser,
 		IProblemRequestor problemRequestor,
+		IProblemFactory problemFactory,
 		IProgressMonitor monitor)
 		throws JavaModelException {
 
@@ -194,9 +152,11 @@
 				getHandlingPolicy(),
 				project.getOptions(true),
 				getRequestor(),
-				getProblemFactory(fileName, problemRequestor, monitor));
+				problemFactory);
+		if (parser != null) {
+			problemFinder.parser = parser;
+		}
 
-		CompilationUnitDeclaration unit = null;
 		try {
 			String encoding = project.getOption(JavaCore.CORE_ENCODING, true);
 			
@@ -205,7 +165,8 @@
 			if (packageFragment != null){
 				expectedPackageName = CharOperation.splitOn('.', packageFragment.getElementName().toCharArray());
 			}
-			unit = problemFinder.resolve(
+			if (unit == null) {
+				unit = problemFinder.resolve(
 					new BasicCompilationUnit(
 						unitElement.getSource().toCharArray(),
 						expectedPackageName,
@@ -214,7 +175,20 @@
 					true, // verify methods
 					true, // analyze code
 					true); // generate code
+			} else {
+				problemFinder.resolve(
+					unit,
+					null, // no need for source
+					true, // verify methods
+					true, // analyze code
+					true); // generate code
+			}
+			reportProblems(unit, problemRequestor, monitor);
 			return unit;
+		} catch(RuntimeException e) { 
+			// avoid breaking other tools due to internal compiler failure (40334)
+			Util.log(e, "Exception occurred during problem detection: "); //$NON-NLS-1$ 
+			throw new JavaModelException(e, IJavaModelStatusConstants.COMPILER_FAILURE);
 		} finally {
 			if (unit != null) {
 				unit.cleanUp();
@@ -222,5 +196,28 @@
 			problemFinder.lookupEnvironment.reset();			
 		}
 	}
+
+	public static CompilationUnitDeclaration process(
+		ICompilationUnit unitElement, 
+		IProblemRequestor problemRequestor,
+		IProgressMonitor monitor)
+		throws JavaModelException {
+			
+		return process(null/*no CompilationUnitDeclaration*/, unitElement, null/*use default Parser*/,problemRequestor, new DefaultProblemFactory(), monitor);
+	}
+
+	
+	private static void reportProblems(CompilationUnitDeclaration unit, IProblemRequestor problemRequestor, IProgressMonitor monitor) {
+		CompilationResult unitResult = unit.compilationResult;
+		IProblem[] problems = unitResult.getAllProblems();
+		for (int i = 0, problemLength = problems == null ? 0 : problems.length; i < problemLength; i++) {
+			if (JavaModelManager.VERBOSE){
+				System.out.println("PROBLEM FOUND while reconciling : "+problems[i].getMessage());//$NON-NLS-1$
+			}
+			if (monitor != null && monitor.isCanceled()) break;
+			problemRequestor.acceptProblem(problems[i]);				
+		}
+	}
+
 }	
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
index e60e452..c5b005b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
@@ -10,22 +10,19 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import java.util.Iterator;
 import java.util.Map;
 import java.util.Stack;
 
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IField;
-import org.eclipse.jdt.core.IImportContainer;
-import org.eclipse.jdt.core.IImportDeclaration;
 import org.eclipse.jdt.core.IInitializer;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.IPackageDeclaration;
 import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
@@ -40,17 +37,17 @@
 	/**
 	 * The handle to the compilation unit being parsed
 	 */
-	protected ICompilationUnit fUnit;
+	protected ICompilationUnit unit;
 
 	/**
 	 * The info object for the compilation unit being parsed
 	 */
-	protected CompilationUnitElementInfo fUnitInfo;
+	protected CompilationUnitElementInfo unitInfo;
 
 	/**
 	 * The import container info - null until created
 	 */
-	protected JavaElementInfo fImportContainerInfo= null;
+	protected JavaElementInfo importContainerInfo = null;
 
 	/**
 	 * Hashtable of children elements of the compilation unit.
@@ -58,7 +55,7 @@
 	 * the parser. Keys are handles, values are corresponding
 	 * info objects.
 	 */
-	protected Map fNewElements;
+	protected Map newElements;
 
 	/**
 	 * Stack of parent scope info objects. The info on the
@@ -66,19 +63,19 @@
 	 * For example, when we locate a method, the parent info object
 	 * will be the type the method is contained in.
 	 */
-	protected Stack fInfoStack;
+	protected Stack infoStack;
 
 	/**
 	 * Stack of parent handles, corresponding to the info stack. We
 	 * keep both, since info objects do not have back pointers to
 	 * handles.
 	 */
-	protected Stack fHandleStack;
+	protected Stack handleStack;
 
 	/**
 	 * The name of the source file being parsed.
 	 */
-	protected char[] fSourceFileName= null;
+	protected char[] sourceFileName= null;
 
 	/**
 	 * The dot-separated name of the package the compilation unit
@@ -86,20 +83,13 @@
 	 * compilation unit, and initialized by #acceptPackage.
 	 * Initialized to <code>null</code> for the default package.
 	 */
-	protected char[] fPackageName= null;
+	protected char[] packageName= null;
 
 	/**
 	 * The number of references reported thus far. Used to
 	 * expand the arrays of reference kinds and names.
 	 */
-	protected int fRefCount= 0;
-
-	/**
-	 * The initial size of the reference kind and name
-	 * arrays. If the arrays fill, they are doubled in
-	 * size
-	 */
-	protected static int fgReferenceAllocation= 50;
+	protected int referenceCount= 0;
 
 	/**
 	 * Problem requestor which will get notified of discovered problems
@@ -114,41 +104,38 @@
 	/**
 	 * Empty collections used for efficient initialization
 	 */
-	protected static String[] fgEmptyStringArray = new String[0];
-	protected static byte[] fgEmptyByte= new byte[]{};
-	protected static char[][] fgEmptyCharChar= new char[][]{};
-	protected static char[] fgEmptyChar= new char[]{};
-
+	protected static String[] NO_STRINGS = new String[0];
+	protected static byte[] NO_BYTES= new byte[]{};
 
 	protected HashtableOfObject fieldRefCache;
 	protected HashtableOfObject messageRefCache;
 	protected HashtableOfObject typeRefCache;
 	protected HashtableOfObject unknownRefCache;
 
-protected CompilationUnitStructureRequestor(ICompilationUnit unit, CompilationUnitElementInfo unitInfo, Map newElements) throws JavaModelException {
-	this.fUnit = unit;
-	this.fUnitInfo = unitInfo;
-	this.fNewElements = newElements;
-	this.fSourceFileName= unit.getElementName().toCharArray();
+protected CompilationUnitStructureRequestor(ICompilationUnit unit, CompilationUnitElementInfo unitInfo, Map newElements) {
+	this.unit = unit;
+	this.unitInfo = unitInfo;
+	this.newElements = newElements;
+	this.sourceFileName= unit.getElementName().toCharArray();
 } 
 /**
  * @see ISourceElementRequestor
  */
-public void acceptImport(int declarationStart, int declarationEnd, char[] name, boolean onDemand) {
-	JavaElementInfo parentInfo = (JavaElementInfo) fInfoStack.peek();
-	JavaElement parentHandle= (JavaElement)fHandleStack.peek();
+public void acceptImport(int declarationStart, int declarationEnd, char[] name, boolean onDemand, int modifiers) {
+	JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
+	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
 	if (!(parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT)) {
 		Assert.isTrue(false); // Should not happen
 	}
 
 	ICompilationUnit parentCU= (ICompilationUnit)parentHandle;
 	//create the import container and its info
-	IImportContainer importContainer= parentCU.getImportContainer();
-	if (fImportContainerInfo == null) {
-		fImportContainerInfo= new JavaElementInfo();
-		fImportContainerInfo.setIsStructureKnown(true);
+	ImportContainer importContainer= (ImportContainer)parentCU.getImportContainer();
+	if (this.importContainerInfo == null) {
+		this.importContainerInfo= new JavaElementInfo();
+		this.importContainerInfo.setIsStructureKnown(true);
 		parentInfo.addChild(importContainer);
-		fNewElements.put(importContainer, fImportContainerInfo);
+		this.newElements.put(importContainer, this.importContainerInfo);
 	}
 	
 	// tack on the '.*' if it is onDemand
@@ -162,12 +149,15 @@
 	ImportDeclaration handle = new ImportDeclaration(importContainer, importName);
 	resolveDuplicates(handle);
 	
-	SourceRefElementInfo info = new SourceRefElementInfo();
+	ImportDeclarationElementInfo info = new ImportDeclarationElementInfo();
 	info.setSourceRangeStart(declarationStart);
 	info.setSourceRangeEnd(declarationEnd);
+	info.setFlags(modifiers);
+	info.setName(name); // no trailing * if onDemand
+	info.setOnDemand(onDemand);
 
-	fImportContainerInfo.addChild(handle);
-	fNewElements.put(handle, info);
+	this.importContainerInfo.addChild(handle);
+	this.newElements.put(handle, info);
 }
 /*
  * Table of line separator position. This table is passed once at the end
@@ -176,19 +166,21 @@
  * A line separator might corresponds to several characters in the source,
  * 
  */
-public void acceptLineSeparatorPositions(int[] positions) {}
+public void acceptLineSeparatorPositions(int[] positions) {
+	// ignore line separator positions
+}
 /**
  * @see ISourceElementRequestor
  */
 public void acceptPackage(int declarationStart, int declarationEnd, char[] name) {
 
-		JavaElementInfo parentInfo = (JavaElementInfo) fInfoStack.peek();
-		JavaElement parentHandle= (JavaElement)fHandleStack.peek();
+		JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
+		JavaElement parentHandle= (JavaElement) this.handleStack.peek();
 		IPackageDeclaration handle = null;
-		fPackageName= name;
+		this.packageName= name;
 		
 		if (parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT) {
-			handle = new PackageDeclaration((ICompilationUnit) parentHandle, new String(name));
+			handle = new PackageDeclaration((CompilationUnit) parentHandle, new String(name));
 		}
 		else {
 			Assert.isTrue(false); // Should not happen
@@ -200,7 +192,7 @@
 		info.setSourceRangeEnd(declarationEnd);
 
 		parentInfo.addChild(handle);
-		fNewElements.put(handle, info);
+		this.newElements.put(handle, info);
 
 }
 public void acceptProblem(IProblem problem) {
@@ -214,10 +206,10 @@
  */
 /* default */ static String[] convertTypeNamesToSigs(char[][] typeNames) {
 	if (typeNames == null)
-		return fgEmptyStringArray;
+		return NO_STRINGS;
 	int n = typeNames.length;
 	if (n == 0)
-		return fgEmptyStringArray;
+		return NO_STRINGS;
 	String[] typeSigs = new String[n];
 	for (int i = 0; i < n; ++i) {
 		typeSigs[i] = Signature.createTypeSignature(typeNames[i], false);
@@ -243,10 +235,10 @@
  * @see ISourceElementRequestor
  */
 public void enterCompilationUnit() {
-	fInfoStack = new Stack();
-	fHandleStack= new Stack();
-	fInfoStack.push(fUnitInfo);
-	fHandleStack.push(fUnit);
+	this.infoStack = new Stack();
+	this.handleStack= new Stack();
+	this.infoStack.push(this.unitInfo);
+	this.handleStack.push(this.unit);
 }
 /**
  * @see ISourceElementRequestor
@@ -275,12 +267,12 @@
 	int nameSourceStart,
 	int nameSourceEnd) {
 
-		SourceTypeElementInfo parentInfo = (SourceTypeElementInfo) fInfoStack.peek();
-		JavaElement parentHandle= (JavaElement)fHandleStack.peek();
+		SourceTypeElementInfo parentInfo = (SourceTypeElementInfo) this.infoStack.peek();
+		JavaElement parentHandle= (JavaElement) this.handleStack.peek();
 		IField handle = null;
 		
 		if (parentHandle.getElementType() == IJavaElement.TYPE) {
-			handle = new SourceField((IType) parentHandle, new String(name));
+			handle = new SourceField(parentHandle, new String(name));
 		}
 		else {
 			Assert.isTrue(false); // Should not happen
@@ -296,10 +288,10 @@
 		info.setTypeName(type);
 
 		parentInfo.addChild(handle);
-		fNewElements.put(handle, info);
+		this.newElements.put(handle, info);
 
-		fInfoStack.push(info);
-		fHandleStack.push(handle);
+		this.infoStack.push(info);
+		this.handleStack.push(handle);
 }
 /**
  * @see ISourceElementRequestor
@@ -307,8 +299,8 @@
 public void enterInitializer(
 	int declarationSourceStart,
 	int modifiers) {
-		JavaElementInfo parentInfo = (JavaElementInfo) fInfoStack.peek();
-		JavaElement parentHandle= (JavaElement)fHandleStack.peek();
+		JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
+		JavaElement parentHandle= (JavaElement) this.handleStack.peek();
 		IInitializer handle = null;
 		
 		if (parentHandle.getElementType() == IJavaElement.TYPE) {
@@ -324,10 +316,10 @@
 		info.setFlags(modifiers);
 
 		parentInfo.addChild(handle);
-		fNewElements.put(handle, info);
+		this.newElements.put(handle, info);
 
-		fInfoStack.push(info);
-		fHandleStack.push(handle);
+		this.infoStack.push(info);
+		this.handleStack.push(handle);
 }
 /**
  * @see ISourceElementRequestor
@@ -375,24 +367,24 @@
 	char[][] exceptionTypes,
 	boolean isConstructor) {
 
-		SourceTypeElementInfo parentInfo = (SourceTypeElementInfo) fInfoStack.peek();
-		JavaElement parentHandle= (JavaElement)fHandleStack.peek();
+		SourceTypeElementInfo parentInfo = (SourceTypeElementInfo) this.infoStack.peek();
+		JavaElement parentHandle= (JavaElement) this.handleStack.peek();
 		IMethod handle = null;
 
 		// translate nulls to empty arrays
 		if (parameterTypes == null) {
-			parameterTypes= fgEmptyCharChar;
+			parameterTypes= CharOperation.NO_CHAR_CHAR;
 		}
 		if (parameterNames == null) {
-			parameterNames= fgEmptyCharChar;
+			parameterNames= CharOperation.NO_CHAR_CHAR;
 		}
 		if (exceptionTypes == null) {
-			exceptionTypes= fgEmptyCharChar;
+			exceptionTypes= CharOperation.NO_CHAR_CHAR;
 		}
 		
 		String[] parameterTypeSigs = convertTypeNamesToSigs(parameterTypes);
 		if (parentHandle.getElementType() == IJavaElement.TYPE) {
-			handle = new SourceMethod((IType) parentHandle, new String(name), parameterTypeSigs);
+			handle = new SourceMethod(parentHandle, new String(name), parameterTypeSigs);
 		}
 		else {
 			Assert.isTrue(false); // Should not happen
@@ -413,9 +405,9 @@
 		info.setExceptionTypeNames(exceptionTypes);
 
 		parentInfo.addChild(handle);
-		fNewElements.put(handle, info);
-		fInfoStack.push(info);
-		fHandleStack.push(handle);
+		this.newElements.put(handle, info);
+		this.infoStack.push(info);
+		this.handleStack.push(handle);
 }
 /**
  * Common processing for classes and interfaces.
@@ -429,29 +421,25 @@
 	char[] superclass,
 	char[][] superinterfaces) {
 
-	char[] enclosingTypeName= null;
-	char[] qualifiedName= null;
-	
-	JavaElementInfo parentInfo = (JavaElementInfo) fInfoStack.peek();
-	JavaElement parentHandle= (JavaElement)fHandleStack.peek();
+	JavaElementInfo parentInfo = (JavaElementInfo) this.infoStack.peek();
+	JavaElement parentHandle= (JavaElement) this.handleStack.peek();
 	IType handle = null;
 	String nameString= new String(name);
 	
-	if (parentHandle.getElementType() == IJavaElement.COMPILATION_UNIT) {
-		handle = ((ICompilationUnit) parentHandle).getType(nameString);
-		if (fPackageName == null) {
-			qualifiedName= nameString.toCharArray();
-		} else {
-			qualifiedName= (new String(fPackageName) + "." + nameString).toCharArray(); //$NON-NLS-1$
-		}
-	}
-	else if (parentHandle.getElementType() == IJavaElement.TYPE) {
-		handle = ((IType) parentHandle).getType(nameString);
-		enclosingTypeName= ((SourceTypeElementInfo)parentInfo).getName();
-		qualifiedName= (new String(((SourceTypeElementInfo)parentInfo).getQualifiedName()) + "." + nameString).toCharArray(); //$NON-NLS-1$
-	}
-	else {
-		Assert.isTrue(false); // Should not happen
+	switch(parentHandle.getElementType()) {
+		case IJavaElement.COMPILATION_UNIT:
+			handle = ((ICompilationUnit) parentHandle).getType(nameString);
+			break;
+		case IJavaElement.TYPE:
+			handle = ((IType) parentHandle).getType(nameString);
+			break;
+		case IJavaElement.FIELD:
+		case IJavaElement.INITIALIZER:
+		case IJavaElement.METHOD:
+			handle = ((IMember) parentHandle).getType(nameString, 1); //NB: occurenceCount is computed in resolveDuplicates
+			break;
+		default:
+			Assert.isTrue(false); // Should not happen
 	}
 	resolveDuplicates(handle);
 	
@@ -464,22 +452,13 @@
 	info.setNameSourceEnd(nameSourceEnd);
 	info.setSuperclassName(superclass);
 	info.setSuperInterfaceNames(superinterfaces);
-	info.setEnclosingTypeName(enclosingTypeName);
-	info.setSourceFileName(fSourceFileName);
-	info.setPackageName(fPackageName);
-	info.setQualifiedName(qualifiedName);
-	for (Iterator iter = fNewElements.keySet().iterator(); iter.hasNext();){
-		Object object = iter.next();
-		if (object instanceof IImportDeclaration)
-			info.addImport(((IImportDeclaration)object).getElementName().toCharArray());
-	}
-	
-
+	info.setSourceFileName(this.sourceFileName);
+	info.setPackageName(this.packageName);
 	parentInfo.addChild(handle);
-	fNewElements.put(handle, info);
+	this.newElements.put(handle, info);
 
-	fInfoStack.push(info);
-	fHandleStack.push(handle);
+	this.infoStack.push(info);
+	this.handleStack.push(handle);
 
 }
 /**
@@ -493,10 +472,10 @@
  * @see ISourceElementRequestor
  */
 public void exitCompilationUnit(int declarationEnd) {
-	fUnitInfo.setSourceLength(declarationEnd + 1);
+	this.unitInfo.setSourceLength(declarationEnd + 1);
 
 	// determine if there were any parsing errors
-	fUnitInfo.setIsStructureKnown(!this.hasSyntaxErrors);
+	this.unitInfo.setIsStructureKnown(!this.hasSyntaxErrors);
 }
 /**
  * @see ISourceElementRequestor
@@ -508,7 +487,7 @@
  * @see ISourceElementRequestor
  */
 public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {
-	SourceFieldElementInfo info = (SourceFieldElementInfo) fInfoStack.pop();
+	SourceFieldElementInfo info = (SourceFieldElementInfo) this.infoStack.pop();
 	info.setSourceRangeEnd(declarationSourceEnd);
 	
 	// remember initializer source if field is a constant
@@ -516,7 +495,7 @@
 		int flags = info.flags;
 		Object typeInfo;
 		if (Flags.isStatic(flags) && Flags.isFinal(flags)
-				|| ((typeInfo = fInfoStack.peek()) instanceof SourceTypeElementInfo
+				|| ((typeInfo = this.infoStack.peek()) instanceof SourceTypeElementInfo
 					 && (Flags.isInterface(((SourceTypeElementInfo)typeInfo).flags)))) {
 			int length = declarationEnd - initializationStart;
 			if (length > 0) {
@@ -526,7 +505,7 @@
 			}
 		}
 	}
-	fHandleStack.pop();
+	this.handleStack.pop();
 }
 /**
  * @see ISourceElementRequestor
@@ -544,9 +523,9 @@
  * common processing for classes and interfaces
  */
 protected void exitMember(int declarationEnd) {
-	SourceRefElementInfo info = (SourceRefElementInfo) fInfoStack.pop();
+	SourceRefElementInfo info = (SourceRefElementInfo) this.infoStack.pop();
 	info.setSourceRangeEnd(declarationEnd);
-	fHandleStack.pop();
+	this.handleStack.pop();
 }
 /**
  * @see ISourceElementRequestor
@@ -559,9 +538,9 @@
  * of the handle being created until there is no conflict.
  */
 protected void resolveDuplicates(IJavaElement handle) {
-	while (fNewElements.containsKey(handle)) {
+	while (this.newElements.containsKey(handle)) {
 		JavaElement h = (JavaElement) handle;
-		h.setOccurrenceCount(h.getOccurrenceCount() + 1);
+		h.occurrenceCount++;
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitVisitor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitVisitor.java
index 2664966..a950cb0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitVisitor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitVisitor.java
@@ -23,7 +23,7 @@
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
@@ -89,10 +89,10 @@
 		CompilationUnitDeclaration unit =
 			SourceTypeConverter.buildCompilationUnit(
 				sourceTypes,//sourceTypes[0] is always toplevel here
-				true, // need field and methods
-				true, // need member types
-				false, // no need for field initialization
-				lookupEnvironment.problemReporter,
+				SourceTypeConverter.FIELD_AND_METHOD // need field and methods
+				| SourceTypeConverter.MEMBER_TYPE, // need member types
+				// no need for field initialization
+				this.lookupEnvironment.problemReporter,
 				result);
 
 		if (unit != null) {
@@ -129,13 +129,14 @@
 	protected static ICompilerRequestor getRequestor() {
 		return new ICompilerRequestor() {
 			public void acceptResult(CompilationResult compilationResult) {
+				// nothing to do
 			}
 		};
 	}
 
 	public static void visit(
 		ICompilationUnit unitElement,
-		IAbstractSyntaxTreeVisitor visitor)
+		ASTVisitor visitor)
 		throws JavaModelException {
 
 		IJavaProject project = unitElement.getJavaProject();
@@ -176,7 +177,7 @@
 		}
 	}
 
-	protected static IProblemFactory getProblemFactory(final IAbstractSyntaxTreeVisitor visitor) {
+	protected static IProblemFactory getProblemFactory(final ASTVisitor visitor) {
 
 		return new DefaultProblemFactory(Locale.getDefault()) {
 			public IProblem createProblem(
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompletionRequestorWrapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompletionRequestorWrapper.java
index f62115a..10869ae 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompletionRequestorWrapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompletionRequestorWrapper.java
@@ -20,8 +20,19 @@
 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
 
 public class CompletionRequestorWrapper implements ICompletionRequestor {
-	static final char[] ARG = "arg".toCharArray();  //$NON-NLS-1$
+	private static Object NO_ATTACHED_SOURCE = new Object();
 	
+	static final char[] ARG = "arg".toCharArray();  //$NON-NLS-1$
+	static final char[] ARG0 = "arg0".toCharArray();  //$NON-NLS-1$
+	static final char[] ARG1 = "arg1".toCharArray();  //$NON-NLS-1$
+	static final char[] ARG2 = "arg2".toCharArray();  //$NON-NLS-1$
+	static final char[] ARG3 = "arg3".toCharArray();  //$NON-NLS-1$
+	static final char[][] ARGS1 = new char[][]{ARG0};
+	static final char[][] ARGS2 = new char[][]{ARG0, ARG1};
+	static final char[][] ARGS3 = new char[][]{ARG0, ARG1, ARG2};
+	static final char[][] ARGS4 = new char[][]{ARG0, ARG1, ARG2, ARG3};
+	
+	public CompletionEngine completionEngine;
 	ICompletionRequestor clientRequestor;
 	NameLookup nameLookup;
 	
@@ -309,8 +320,28 @@
 	int length = parameterTypeNames.length;
 	
 	char[] typeName = CharOperation.concat(declaringTypePackageName,declaringTypeName,'.');
-	IType type = nameLookup.findType(new String(typeName), false, NameLookup.ACCEPT_CLASSES & NameLookup.ACCEPT_INTERFACES);
-	if(type instanceof BinaryType){
+	Object cachedType = this.completionEngine.typeCache.get(typeName);
+	
+	IType type = null;
+	if(cachedType != null) {
+		if(cachedType != NO_ATTACHED_SOURCE && cachedType instanceof BinaryType) {
+			type = (BinaryType)cachedType;
+		}
+	} else { 
+		type = this.nameLookup.findType(new String(typeName), false, NameLookup.ACCEPT_CLASSES & NameLookup.ACCEPT_INTERFACES);
+		if(type instanceof BinaryType){
+			if(((BinaryType)type).getSourceMapper() != null) {
+				this.completionEngine.typeCache.put(typeName, type);
+			} else {
+				this.completionEngine.typeCache.put(typeName, NO_ATTACHED_SOURCE);
+				type = null;
+			}
+		} else {
+			type = null;
+		}
+	}
+	
+	if(type != null) {
 		String[] args = new String[length];
 		for(int i = 0;	i< length ; i++){
 			char[] parameterType = CharOperation.concat(parameterPackageNames[i],parameterTypeNames[i],'.');
@@ -326,14 +357,33 @@
 		} catch(JavaModelException e){
 			parameterNames = null;
 		}
-			
 	}
 	// default parameters name
 	if(parameterNames == null) {
-		parameterNames = new char[length][];
-		for (int i = 0; i < length; i++) {
-			parameterNames[i] = CharOperation.concat(ARG, String.valueOf(i).toCharArray());
+		switch (length) {
+			case 0 :
+				parameterNames = new char[length][];
+				break;
+			case 1 :
+				parameterNames = ARGS1;
+				break;
+			case 2 :
+				parameterNames = ARGS2;
+				break;
+			case 3 :
+				parameterNames = ARGS3;
+				break;
+			case 4 :
+				parameterNames = ARGS4;
+				break;
+			default :
+				parameterNames = new char[length][];
+				for (int i = 0; i < length; i++) {
+					parameterNames[i] = CharOperation.concat(ARG, String.valueOf(i).toCharArray());
+				}
+				break;
 		}
+		
 	}
 	return parameterNames;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java
index a718352..0d4befe 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyElementsOperation.java
@@ -24,6 +24,7 @@
 import org.eclipse.jdt.core.jdom.DOMFactory;
 import org.eclipse.jdt.core.jdom.IDOMCompilationUnit;
 import org.eclipse.jdt.core.jdom.IDOMNode;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 /**
@@ -59,10 +60,10 @@
  * </ul>
  *
  */
-public class CopyElementsOperation extends MultiOperation {
+public class CopyElementsOperation extends MultiOperation implements SuffixConstants {
 
 	
-	private Map fSources = new HashMap();
+	private Map sources = new HashMap();
 /**
  * When executed, this operation will copy the given elements to the
  * given containers.  The elements and destination containers must be in
@@ -99,14 +100,14 @@
 				return new CreateImportOperation(element.getElementName(), (ICompilationUnit) dest);
 			case IJavaElement.TYPE :
 				if (isRenamingMainType(element, dest)) {
-					return new RenameResourceElementsOperation(new IJavaElement[] {dest}, new IJavaElement[] {dest.getParent()}, new String[]{getNewNameFor(element) + ".java"}, fForce); //$NON-NLS-1$
+					return new RenameResourceElementsOperation(new IJavaElement[] {dest}, new IJavaElement[] {dest.getParent()}, new String[]{getNewNameFor(element) + SUFFIX_STRING_java}, this.force); //$NON-NLS-1$
 				} else {
-					return new CreateTypeOperation(dest, getSourceFor(element) + Util.LINE_SEPARATOR, fForce);
+					return new CreateTypeOperation(dest, getSourceFor(element) + Util.LINE_SEPARATOR, this.force);
 				}
 			case IJavaElement.METHOD :
-				return new CreateMethodOperation((IType) dest, getSourceFor(element) + Util.LINE_SEPARATOR, fForce);
+				return new CreateMethodOperation((IType) dest, getSourceFor(element) + Util.LINE_SEPARATOR, this.force);
 			case IJavaElement.FIELD :
-				return new CreateFieldOperation((IType) dest, getSourceFor(element) + Util.LINE_SEPARATOR, fForce);
+				return new CreateFieldOperation((IType) dest, getSourceFor(element) + Util.LINE_SEPARATOR, this.force);
 			case IJavaElement.INITIALIZER :
 				return new CreateInitializerOperation((IType) dest, getSourceFor(element) + Util.LINE_SEPARATOR);
 			default :
@@ -120,7 +121,7 @@
  * Returns the cached source for this element or compute it if not already cached.
  */
 private String getSourceFor(IJavaElement element) throws JavaModelException {
-	String source = (String) fSources.get(element);
+	String source = (String) this.sources.get(element);
 	if (source == null && element instanceof IMember) {
 		IMember member = (IMember)element;
 		ICompilationUnit cu = member.getCompilationUnit();
@@ -128,7 +129,7 @@
 		IDOMCompilationUnit domCU = new DOMFactory().createCompilationUnit(cuSource, cu.getElementName());
 		IDOMNode node = ((JavaElement)element).findNode(domCU);
 		source = new String(node.getCharacters());
-		fSources.put(element, source);
+		this.sources.put(element, source);
 	}
 	return source;
 }
@@ -158,7 +159,7 @@
 		return;
 	}
 	if (createElementInCUOperation) {
-		IJavaElement sibling = (IJavaElement) fInsertBeforeElements.get(element);
+		IJavaElement sibling = (IJavaElement) this.insertBeforeElements.get(element);
 		if (sibling != null) {
 			((CreateElementInCUOperation) op).setRelativePosition(sibling, CreateElementInCUOperation.INSERT_BEFORE);
 		} else
@@ -182,7 +183,7 @@
 	}
 
 	if (createElementInCUOperation && isMove() && !isRenamingMainType(element, destination)) {
-		DeleteElementsOperation deleteOp = new DeleteElementsOperation(new IJavaElement[] { element }, fForce);
+		DeleteElementsOperation deleteOp = new DeleteElementsOperation(new IJavaElement[] { element }, this.force);
 		executeNestedOperation(deleteOp, 1);
 	}
 }
@@ -215,7 +216,7 @@
 	if (!status.isOK()) {
 		return status;
 	}
-	if (fRenamingsList != null && fRenamingsList.length != fElementsToProcess.length) {
+	if (this.renamingsList != null && this.renamingsList.length != this.elementsToProcess.length) {
 		return new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS);
 	}
 	return JavaModelStatus.VERIFIED_OK;
@@ -250,13 +251,19 @@
 	if (element.getElementType() < IJavaElement.TYPE)
 		error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
 
+	Member localContext;
+	if (element instanceof Member && (localContext = ((Member)element).getOuterMostLocalContext()) != null && localContext != element) {
+		// JDOM doesn't support source manipulation in local/anonymous types
+		error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
+	}
+
 	if (element.isReadOnly())
 		error(IJavaModelStatusConstants.READ_ONLY, element);
 
 	IJavaElement dest = getDestinationParent(element);
 	verifyDestination(element, dest);
 	verifySibling(element, dest);
-	if (fRenamingsList != null) {
+	if (this.renamingsList != null) {
 		verifyRenaming(element);
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java
index 8593e80..32bc9dc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java
@@ -20,6 +20,7 @@
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.IJavaModelStatus;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public class CopyPackageFragmentRootOperation extends JavaModelOperation {
 	IPath destination;
@@ -69,10 +70,10 @@
 				if ((this.updateModelFlags & IPackageFragmentRoot.REPLACE) != 0) {
 					if (rootEntry.getPath().equals(this.destination)) return;
 					if ((destRes = workspaceRoot.findMember(this.destination)) != null) {
-						destRes.delete(this.updateResourceFlags, fMonitor);
+						destRes.delete(this.updateResourceFlags, progressMonitor);
 					}
 				}
-				rootResource.copy(this.destination, this.updateResourceFlags, fMonitor);
+				rootResource.copy(this.destination, this.updateResourceFlags, progressMonitor);
 			} catch (CoreException e) {
 				throw new JavaModelException(e);
 			}
@@ -95,7 +96,7 @@
 										&& folder.exists()) {
 									return true;
 								}
-								folder.create(updateResourceFlags, true, fMonitor);
+								folder.create(updateResourceFlags, true, progressMonitor);
 								return true;
 							}
 						} else {
@@ -104,9 +105,9 @@
 							IResource destRes;
 							if ((updateModelFlags & IPackageFragmentRoot.REPLACE) != 0
 									&& (destRes = workspaceRoot.findMember(destPath)) != null) {
-								destRes.delete(updateResourceFlags, fMonitor);
+								destRes.delete(updateResourceFlags, progressMonitor);
 							}
-							proxy.requestResource().copy(destPath, updateResourceFlags, fMonitor);
+							proxy.requestResource().copy(destPath, updateResourceFlags, progressMonitor);
 							return false;
 						}
 					} else {
@@ -115,9 +116,9 @@
 						IResource destRes;
 						if ((updateModelFlags & IPackageFragmentRoot.REPLACE) != 0
 								&& (destRes = workspaceRoot.findMember(destPath)) != null) {
-							destRes.delete(updateResourceFlags, fMonitor);
+							destRes.delete(updateResourceFlags, progressMonitor);
 						}
-						proxy.requestResource().copy(destPath, updateResourceFlags, fMonitor);
+						proxy.requestResource().copy(destPath, updateResourceFlags, progressMonitor);
 						return false;
 					}
 				}
@@ -146,7 +147,7 @@
 					newClasspath = new IClasspathEntry[length];
 					System.arraycopy(classpath, 0, newClasspath, 0, length);
 					newClasspath[i] = copy(rootEntry);
-					jProject.setRawClasspath(newClasspath, fMonitor);
+					jProject.setRawClasspath(newClasspath, progressMonitor);
 					return;
 				}
 			}
@@ -179,7 +180,7 @@
 		}
 		IClasspathEntry newEntry = copy(rootEntry);
 		newClasspath[position] = newEntry;
-		jProject.setRawClasspath(newClasspath, fMonitor);
+		jProject.setRawClasspath(newClasspath, progressMonitor);
 	}
 	/*
 	 * Copies the given classpath entry replacing its path with the destination path
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
index ef2fe10..a417f23 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java
@@ -20,7 +20,8 @@
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.jdom.*;
-import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This operation copies/moves/renames a collection of resources from their current
@@ -46,27 +47,34 @@
  * </ul>
  *
  */
-public class CopyResourceElementsOperation extends MultiOperation {
+public class CopyResourceElementsOperation extends MultiOperation implements SuffixConstants {
 	/**
-	 * A collection of renamed compilation units.  These cus do
-	 * not need to be saved as they no longer exist.
+	 * The list of new resources created during this operation.
 	 */
-	protected ArrayList fRenamedCompilationUnits = null;
+	protected ArrayList createdElements;
 	/**
 	 * Table specifying deltas for elements being 
 	 * copied/moved/renamed. Keyed by elements' project(s), and
 	 * values are the corresponding deltas.
 	 */
-	protected Map fDeltasPerProject= new HashMap(1);
+	protected Map deltasPerProject = new HashMap(1);
 	/**
 	 * The <code>DOMFactory</code> used to manipulate the source code of
 	 * <code>ICompilationUnit</code>.
 	 */
 	protected DOMFactory fFactory;
 	/**
-	 * The list of new resources created during this operation.
+	 * A collection of renamed compilation units.  These cus do
+	 * not need to be saved as they no longer exist.
 	 */
-	protected ArrayList fCreatedElements;
+	protected ArrayList fRenamedCompilationUnits = null;
+	/**
+	 * When executed, this operation will copy the given resources to the
+	 * given container.
+	 */
+	public CopyResourceElementsOperation(IJavaElement[] resourcesToCopy, IJavaElement destContainer, boolean force) {
+		this(resourcesToCopy, new IJavaElement[]{destContainer}, force);
+	}
 	/**
 	 * When executed, this operation will copy the given resources to the
 	 * given containers.  The resources and destination containers must be in
@@ -78,13 +86,6 @@
 		fFactory = new DOMFactory();
 	}
 	/**
-	 * When executed, this operation will copy the given resources to the
-	 * given container.
-	 */
-	public CopyResourceElementsOperation(IJavaElement[] resourcesToCopy, IJavaElement destContainer, boolean force) {
-		this(resourcesToCopy, new IJavaElement[]{destContainer}, force);
-	}
-	/**
 	 * Returns the children of <code>source</code> which are affected by this operation.
 	 * If <code>source</code> is a <code>K_SOURCE</code>, these are the <code>.java</code>
 	 * files, if it is a <code>K_BINARY</code>, they are the <code>.class</code> files.
@@ -127,11 +128,13 @@
 	}
 	/**
 	 * Creates any destination package fragment(s) which do not exists yet.
+	 * Return true if a read-only package fragment has been found among package fragments, false otherwise
 	 */
-	private void createNeededPackageFragments(IContainer sourceFolder, IPackageFragmentRoot root, String newFragName, boolean moveFolder) throws JavaModelException {
+	private boolean createNeededPackageFragments(IContainer sourceFolder, IPackageFragmentRoot root, String newFragName, boolean moveFolder) throws JavaModelException {
+		boolean containsReadOnlyPackageFragment = false;
 		IContainer parentFolder = (IContainer) root.getResource();
 		JavaElementDelta projectDelta = null;
-		String[] names = org.eclipse.jdt.internal.core.Util.getTrimmedSimpleNames(newFragName);
+		String[] names = Util.getTrimmedSimpleNames(newFragName);
 		StringBuffer sideEffectPackageName = new StringBuffer();
 		char[][] exclusionsPatterns = ((PackageFragmentRoot)root).fullExclusionPatternChars();
 		for (int i = 0; i < names.length; i++) {
@@ -141,38 +144,40 @@
 			if (subFolder == null) {
 				// create deepest folder only if not a move (folder will be moved in processPackageFragmentResource)
 				if (!(moveFolder && i == names.length-1)) {
-					createFolder(parentFolder, subFolderName, fForce);
+					createFolder(parentFolder, subFolderName, force);
 				}
 				parentFolder = parentFolder.getFolder(new Path(subFolderName));
 				sourceFolder = sourceFolder.getFolder(new Path(subFolderName));
 				if (sourceFolder.isReadOnly()) {
-					parentFolder.setReadOnly(true);
+					containsReadOnlyPackageFragment = true;
 				}
 				IPackageFragment sideEffectPackage = root.getPackageFragment(sideEffectPackageName.toString());
 				if (i < names.length - 1 // all but the last one are side effect packages
-						&& !org.eclipse.jdt.internal.core.Util.isExcluded(parentFolder, exclusionsPatterns)) { 
+						&& !Util.isExcluded(parentFolder, exclusionsPatterns)) { 
 					if (projectDelta == null) {
 						projectDelta = getDeltaFor(root.getJavaProject());
 					}
 					projectDelta.added(sideEffectPackage);
 				}
-				fCreatedElements.add(sideEffectPackage);
+				createdElements.add(sideEffectPackage);
 			} else {
 				parentFolder = (IContainer) subFolder;
 			}
 			sideEffectPackageName.append('.');
 		}
+		return containsReadOnlyPackageFragment;
 	}
+	
 	/**
 	 * Returns the <code>JavaElementDelta</code> for <code>javaProject</code>,
 	 * creating it and putting it in <code>fDeltasPerProject</code> if
 	 * it does not exist yet.
 	 */
 	private JavaElementDelta getDeltaFor(IJavaProject javaProject) {
-		JavaElementDelta delta = (JavaElementDelta) fDeltasPerProject.get(javaProject);
+		JavaElementDelta delta = (JavaElementDelta) deltasPerProject.get(javaProject);
 		if (delta == null) {
 			delta = new JavaElementDelta(javaProject);
-			fDeltasPerProject.put(javaProject, delta);
+			deltasPerProject.put(javaProject, delta);
 		}
 		return delta;
 	}
@@ -180,7 +185,7 @@
 	 * @see MultiOperation
 	 */
 	protected String getMainTaskName() {
-		return org.eclipse.jdt.internal.core.Util.bind("operation.copyResourceProgress"); //$NON-NLS-1$
+		return Util.bind("operation.copyResourceProgress"); //$NON-NLS-1$
 	}
 	/**
 	 * Sets the deltas to register the changes resulting from this operation
@@ -194,7 +199,7 @@
 	 * 	 
 	 */
 	protected void prepareDeltas(IJavaElement sourceElement, IJavaElement destinationElement, boolean isMove) {
-		if (org.eclipse.jdt.internal.core.Util.isExcluded(sourceElement) || org.eclipse.jdt.internal.core.Util.isExcluded(destinationElement)) return;
+		if (Util.isExcluded(sourceElement) || Util.isExcluded(destinationElement)) return;
 		IJavaProject destProject = destinationElement.getJavaProject();
 		if (isMove) {
 			IJavaProject sourceProject = sourceElement.getJavaProject();
@@ -219,13 +224,13 @@
 		String newContent = updatedContent(source, dest, newCUName); // null if unchanged
 	
 		// copy resource
-		IFile sourceResource = (IFile)(source.isWorkingCopy() ? source.getOriginalElement() : source).getResource();
+		IFile sourceResource = (IFile)source.getResource();
 		IContainer destFolder = (IContainer)dest.getResource(); // can be an IFolder or an IProject
 		IFile destFile = destFolder.getFile(new Path(destName));
 		if (!destFile.equals(sourceResource)) {
 			try {
 				if (destFile.exists()) {
-					if (fForce) {
+					if (force) {
 						// we can remove it
 						deleteResource(destFile, IResource.KEEP_HISTORY);
 					} else {
@@ -235,7 +240,7 @@
 							Util.bind("status.nameCollision", destFile.getFullPath().toString()))); //$NON-NLS-1$
 					}
 				}
-				int flags = fForce ? IResource.FORCE : IResource.NONE;
+				int flags = force ? IResource.FORCE : IResource.NONE;
 				if (this.isMove()) {
 					flags |= IResource.KEEP_HISTORY;
 					sourceResource.move(destFile.getFullPath(), flags, getSubProgressMonitor(1));
@@ -251,18 +256,27 @@
 			}
 	
 			// update new resource content
-			try {
-				if (newContent != null){
+			if (newContent != null){
+				boolean wasReadOnly = destFile.isReadOnly();
+				try {
 					String encoding = source.getJavaProject().getOption(JavaCore.CORE_ENCODING, true);
+					
+					// when the file was copied, its read-only flag was preserved -> temporary set it to false
+					// note this doesn't interfer with repository providers as this is a new resource that cannot be under
+					// version control yet
+					destFile.setReadOnly(false);
+					
 					destFile.setContents(
 						new ByteArrayInputStream(encoding == null ? newContent.getBytes() : newContent.getBytes(encoding)), 
-						fForce ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
+						force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
 						getSubProgressMonitor(1));
+				} catch(IOException e) {
+					throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+				} catch (CoreException e) {
+					throw new JavaModelException(e);
+				} finally {
+					destFile.setReadOnly(wasReadOnly);
 				}
-			} catch(IOException e) {
-				throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
-			} catch (CoreException e) {
-				throw new JavaModelException(e);
 			}
 		
 			// register the correct change deltas
@@ -277,7 +291,7 @@
 				prepareDeltas(source.getType(oldName), destCU.getType(newName), isMove());
 			}
 		} else {
-			if (!fForce) {
+			if (!force) {
 				throw new JavaModelException(new JavaModelStatus(
 					IJavaModelStatusConstants.NAME_COLLISION, 
 					Util.bind("status.nameCollision", destFile.getFullPath().toString()))); //$NON-NLS-1$
@@ -290,7 +304,7 @@
 					String encoding = source.getJavaProject().getOption(JavaCore.CORE_ENCODING, true);
 					destFile.setContents(
 						new ByteArrayInputStream(encoding == null ? newContent.getBytes() : newContent.getBytes(encoding)), 
-						fForce ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
+						force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
 						getSubProgressMonitor(1));
 				}
 			} catch(IOException e) {
@@ -304,7 +318,7 @@
 	 * Process all of the changed deltas generated by this operation.
 	 */
 	protected void processDeltas() {
-		for (Iterator deltas = this.fDeltasPerProject.values().iterator(); deltas.hasNext();){
+		for (Iterator deltas = this.deltasPerProject.values().iterator(); deltas.hasNext();){
 			addDelta((IJavaElementDelta) deltas.next());
 		}
 	}
@@ -319,7 +333,7 @@
 		switch (element.getElementType()) {
 			case IJavaElement.COMPILATION_UNIT :
 				processCompilationUnitResource((ICompilationUnit) element, (IPackageFragment) dest);
-				fCreatedElements.add(((IPackageFragment) dest).getCompilationUnit(element.getElementName()));
+				createdElements.add(((IPackageFragment) dest).getCompilationUnit(element.getElementName()));
 				break;
 			case IJavaElement.PACKAGE_FRAGMENT :
 				processPackageFragmentResource((IPackageFragment) element, (IPackageFragmentRoot) dest, getNewNameFor(element));
@@ -334,14 +348,14 @@
 	 * and <code>fResultElements</code>.
 	 */
 	protected void processElements() throws JavaModelException {
-		fCreatedElements = new ArrayList(fElementsToProcess.length);
+		createdElements = new ArrayList(elementsToProcess.length);
 		try {
 			super.processElements();
 		} catch (JavaModelException jme) {
 			throw jme;
 		} finally {
-			fResultElements = new IJavaElement[fCreatedElements.size()];
-			fCreatedElements.toArray(fResultElements);
+			resultElements = new IJavaElement[createdElements.size()];
+			createdElements.toArray(resultElements);
 			processDeltas();
 		}
 	}
@@ -377,12 +391,20 @@
 					}
 				}	
 			}
-			createNeededPackageFragments((IContainer) source.getParent().getResource(), root, newFragName, shouldMoveFolder);
+			boolean containsReadOnlySubPackageFragments = createNeededPackageFragments((IContainer) source.getParent().getResource(), root, newFragName, shouldMoveFolder);
+			boolean sourceIsReadOnly = srcFolder.isReadOnly();
 	
 			// Process resources
 			if (shouldMoveFolder) {
 				// move underlying resource
-				srcFolder.move(destPath, fForce, true /* keep history */, getSubProgressMonitor(1));
+				// TODO Revisit once bug 43044 is fixed
+				if (sourceIsReadOnly) {
+					srcFolder.setReadOnly(false);
+				}
+				srcFolder.move(destPath, force, true /* keep history */, getSubProgressMonitor(1));
+				if (sourceIsReadOnly) {
+					srcFolder.setReadOnly(true);
+				}
 				this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
 			} else {
 				// process the leaf resources
@@ -396,7 +418,7 @@
 						for (int i = 0, max = resources.length; i < max; i++) {
 							IResource destinationResource = ResourcesPlugin.getWorkspace().getRoot().findMember(destPath.append(resources[i].getName()));
 							if (destinationResource != null) {
-								if (fForce) {
+								if (force) {
 									deleteResource(destinationResource, IResource.KEEP_HISTORY);
 								} else {
 									throw new JavaModelException(new JavaModelStatus(
@@ -411,7 +433,7 @@
 						for (int i = 0, max = resources.length; i < max; i++) {
 							IResource destinationResource = ResourcesPlugin.getWorkspace().getRoot().findMember(destPath.append(resources[i].getName()));
 							if (destinationResource != null) {
-								if (fForce) {
+								if (force) {
 									// we need to delete this resource if this operation wants to override existing resources
 									deleteResource(destinationResource, IResource.KEEP_HISTORY);
 								} else {
@@ -426,15 +448,48 @@
 				}
 			}
 	
+			// Update package statement in compilation unit if needed
+			if (!newFrag.getElementName().equals(source.getElementName())) { // if package has been renamed, update the compilation units
+				for (int i = 0; i < resources.length; i++) {
+					if (resources[i].getName().endsWith(SUFFIX_STRING_java)) {
+						// we only consider potential compilation units
+						ICompilationUnit cu = newFrag.getCompilationUnit(resources[i].getName());
+						IDOMCompilationUnit domCU = fFactory.createCompilationUnit(cu.getSource(), cu.getElementName());
+						if (domCU != null) {
+							updatePackageStatement(domCU, newFragName);
+							IBuffer buffer = cu.getBuffer();
+							if (buffer == null) continue;
+							String bufferContents = buffer.getContents();
+							if (bufferContents == null) continue;
+							String domCUContents = domCU.getContents();
+							String cuContents = null;
+							if (domCUContents != null) {
+								cuContents = Util.normalizeCRs(domCU.getContents(), bufferContents);
+							} else {
+								// See PR http://dev.eclipse.org/bugs/show_bug.cgi?id=11285
+								cuContents = bufferContents;//$NON-NLS-1$
+							}
+							buffer.setContents(cuContents);
+							cu.save(null, false);
+						}
+					}
+				}
+			}
+			
 			// Discard empty old package (if still empty after the rename)
 			boolean isEmpty = true;
 			if (isMove()) {
 				// delete remaining files in this package (.class file in the case where Proj=src=bin)
+				// in case of a copy
+				updateReadOnlyPackageFragmentsForMove((IContainer) source.getParent().getResource(), root, newFragName, sourceIsReadOnly);
 				if (srcFolder.exists()) {
-					IResource[] remaingFiles = srcFolder.members();
-					for (int i = 0, length = remaingFiles.length; i < length; i++) {
-						IResource file = remaingFiles[i];
+					IResource[] remaining = srcFolder.members();
+					for (int i = 0, length = remaining.length; i < length; i++) {
+						IResource file = remaining[i];
 						if (file instanceof IFile) {
+							if (file.isReadOnly()) {
+								file.setReadOnly(false);
+							}
 							this.deleteResource(file, IResource.FORCE | IResource.KEEP_HISTORY);
 						} else {
 							isEmpty = false;
@@ -453,36 +508,10 @@
 					// delete recursively empty folders
 					deleteEmptyPackageFragment(source, false, rootResource);
 				}
+			} else if (containsReadOnlySubPackageFragments) {
+				// in case of a copy
+				updateReadOnlyPackageFragmentsForCopy((IContainer) source.getParent().getResource(), root, newFragName);
 			}
-	
-			// Update package statement in compilation unit if needed
-			if (!newFrag.getElementName().equals(source.getElementName())) { // if package has been renamed, update the compilation units
-				for (int i = 0; i < resources.length; i++) {
-					if (resources[i].getName().endsWith(".java")) { //$NON-NLS-1$
-						// we only consider potential compilation units
-						ICompilationUnit cu = newFrag.getCompilationUnit(resources[i].getName());
-						IDOMCompilationUnit domCU = fFactory.createCompilationUnit(cu.getSource(), cu.getElementName());
-						if (domCU != null) {
-							updatePackageStatement(domCU, newFragName);
-							IBuffer buffer = cu.getBuffer();
-							if (buffer == null) continue;
-							String bufferContents = buffer.getContents();
-							if (bufferContents == null) continue;
-							String domCUContents = domCU.getContents();
-							String cuContents = null;
-							if (domCUContents != null) {
-								cuContents = org.eclipse.jdt.internal.core.Util.normalizeCRs(domCU.getContents(), bufferContents);
-							} else {
-								// See PR http://dev.eclipse.org/bugs/show_bug.cgi?id=11285
-								cuContents = bufferContents;//$NON-NLS-1$
-							}
-							buffer.setContents(cuContents);
-							cu.save(null, false);
-						}
-					}
-				}
-			}
-	
 			//register the correct change deltas
 			prepareDeltas(source, newFrag, isMove() && isEmpty);
 		} catch (DOMException dom) {
@@ -521,7 +550,7 @@
 	/**
 	 * Makes sure that <code>cu</code> declares to be in the <code>pkgName</code> package.
 	 */
-	private void updatePackageStatement(IDOMCompilationUnit domCU, String pkgName) throws JavaModelException {
+	private void updatePackageStatement(IDOMCompilationUnit domCU, String pkgName) {
 		boolean defaultPackage = pkgName.equals(IPackageFragment.DEFAULT_PACKAGE_NAME);
 		boolean seenPackageNode = false;
 		Enumeration enum = domCU.getChildren();
@@ -540,13 +569,47 @@
 		if (!seenPackageNode && !defaultPackage) {
 			//the cu was in a default package...no package declaration
 			//create the new package declaration as the first child of the cu
-			IDOMPackage pkg = fFactory.createPackage("package " + pkgName + ";" + Util.LINE_SEPARATOR); //$NON-NLS-1$ //$NON-NLS-2$
+			IDOMPackage pkg = fFactory.createPackage("package " + pkgName + ";" + org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR); //$NON-NLS-1$ //$NON-NLS-2$
 			IDOMNode firstChild = domCU.getFirstChild();
 			if (firstChild != null) {
 				firstChild.insertSibling(pkg);
 			} // else the cu was empty: leave it empty
 		}
 	}
+	
+	private void updateReadOnlyPackageFragmentsForCopy(IContainer sourceFolder, IPackageFragmentRoot root, String newFragName) {
+		IContainer parentFolder = (IContainer) root.getResource();
+		String[] names = Util.getTrimmedSimpleNames(newFragName);
+		StringBuffer sideEffectPackageName = new StringBuffer();
+		for (int i = 0, nameLength = names.length; i < nameLength; i++) {
+			String subFolderName = names[i];
+			sideEffectPackageName.append(subFolderName);
+			parentFolder = parentFolder.getFolder(new Path(subFolderName));
+			sourceFolder = sourceFolder.getFolder(new Path(subFolderName));
+			if (sourceFolder.exists() && sourceFolder.isReadOnly()) {
+				parentFolder.setReadOnly(true);
+			}
+			sideEffectPackageName.append('.');
+		}
+	}
+
+	private void updateReadOnlyPackageFragmentsForMove(IContainer sourceFolder, IPackageFragmentRoot root, String newFragName, boolean sourceFolderIsReadOnly) {
+		IContainer parentFolder = (IContainer) root.getResource();
+		String[] names = Util.getTrimmedSimpleNames(newFragName);
+		StringBuffer sideEffectPackageName = new StringBuffer();
+		for (int i = 0, nameLength = names.length; i < nameLength; i++) {
+			String subFolderName = names[i];
+			sideEffectPackageName.append(subFolderName);
+			parentFolder = parentFolder.getFolder(new Path(subFolderName));
+			sourceFolder = sourceFolder.getFolder(new Path(subFolderName));
+			if ((sourceFolder.exists() && sourceFolder.isReadOnly()) || (i == nameLength - 1 && sourceFolderIsReadOnly)) {
+				parentFolder.setReadOnly(true);
+				// the source folder will be deleted anyway (move operation)
+				sourceFolder.setReadOnly(false);
+			}
+			sideEffectPackageName.append('.');
+		}
+	}
 		/**
 		 * Renames the main type in <code>cu</code>.
 		 */
@@ -585,7 +648,7 @@
 			return status;
 		}
 	
-		if (fRenamingsList != null && fRenamingsList.length != fElementsToProcess.length) {
+		if (this.renamingsList != null && this.renamingsList.length != elementsToProcess.length) {
 			return new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS);
 		}
 		return JavaModelStatus.VERIFIED_OK;
@@ -603,14 +666,15 @@
 		IResource resource = element.getResource();
 		if (resource instanceof IFolder) {
 			if (resource.isLinked()) {
-				error(JavaModelStatus.INVALID_RESOURCE, element);
+				error(IJavaModelStatusConstants.INVALID_RESOURCE, element);
 			}
 		}
 	
 		int elementType = element.getElementType();
 	
 		if (elementType == IJavaElement.COMPILATION_UNIT) {
-			if (isMove() && ((ICompilationUnit) element).isWorkingCopy())
+			CompilationUnit compilationUnit = (CompilationUnit)element;
+			if (isMove() && compilationUnit.isWorkingCopy() && !compilationUnit.isPrimary())
 				error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
 		} else if (elementType != IJavaElement.PACKAGE_FRAGMENT) {
 			error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
@@ -618,7 +682,7 @@
 		
 		JavaElement dest = (JavaElement) getDestinationParent(element);
 		verifyDestination(element, dest);
-		if (fRenamings != null) {
+		if (this.renamings != null) {
 			verifyRenaming(element);
 		}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateCompilationUnitOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateCompilationUnitOperation.java
index 3bb3d16..025deca 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateCompilationUnitOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateCompilationUnitOperation.java
@@ -29,6 +29,7 @@
 import org.eclipse.jdt.core.JavaConventions;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * <p>This operation creates a compilation unit (CU).
@@ -83,16 +84,16 @@
 		IFile compilationUnitFile = folder.getFile(new Path(fName));
 		if (compilationUnitFile.exists()) {
 			// update the contents of the existing unit if fForce is true
-			if (fForce) {
+			if (force) {
 				IBuffer buffer = unit.getBuffer();
 				if (buffer == null) return;
 				buffer.setContents(fSource);
 				unit.save(new NullProgressMonitor(), false);
-				fResultElements = new IJavaElement[] {unit};
+				resultElements = new IJavaElement[] {unit};
 				if (!Util.isExcluded(unit)
 						&& unit.getParent().exists()) {
-					for (int i = 0; i < fResultElements.length; i++) {
-						delta.changed(fResultElements[i], IJavaElementDelta.F_CONTENT);
+					for (int i = 0; i < resultElements.length; i++) {
+						delta.changed(resultElements[i], IJavaElementDelta.F_CONTENT);
 					}
 					addDelta(delta);
 				}
@@ -105,12 +106,12 @@
 			try {
 				String encoding = unit.getJavaProject().getOption(JavaCore.CORE_ENCODING, true);
 				InputStream stream = new ByteArrayInputStream(encoding == null ? fSource.getBytes() : fSource.getBytes(encoding));
-				createFile(folder, unit.getElementName(), stream, false);
-				fResultElements = new IJavaElement[] {unit};
+				createFile(folder, unit.getElementName(), stream, force);
+				resultElements = new IJavaElement[] {unit};
 				if (!Util.isExcluded(unit)
 						&& unit.getParent().exists()) {
-					for (int i = 0; i < fResultElements.length; i++) {
-						delta.added(fResultElements[i]);
+					for (int i = 0; i < resultElements.length; i++) {
+						delta.added(resultElements[i]);
 					}
 					addDelta(delta);
 				}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java
index a751d4c..195f6a3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateElementInCUOperation.java
@@ -20,6 +20,7 @@
 import org.eclipse.jdt.core.jdom.IDOMCompilationUnit;
 import org.eclipse.jdt.core.jdom.IDOMNode;
 import org.eclipse.jdt.internal.core.jdom.DOMNode;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * <p>This abstract class implements behavior common to <code>CreateElementInCUOperations</code>.
@@ -99,7 +100,7 @@
 	 * Only allow cancelling if this operation is not nested.
 	 */
 	protected void checkCanceled() {
-		if (!fNested) {
+		if (!isNested) {
 			super.checkCanceled();
 		}
 	}
@@ -137,7 +138,7 @@
 				if (buffer  == null) return;
 				char[] bufferContents = buffer.getCharacters();
 				if (bufferContents == null) return;
-				char[] elementContents = org.eclipse.jdt.internal.core.Util.normalizeCRs(fCreatedElement.getCharacters(), bufferContents);
+				char[] elementContents = Util.normalizeCRs(fCreatedElement.getCharacters(), bufferContents);
 				switch (fReplacementLength) {
 					case -1 : 
 						// element is append at the end
@@ -156,12 +157,12 @@
 				if (!isWorkingCopy)
 					this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
 				worked(1);
-				fResultElements = generateResultHandles();
+				resultElements = generateResultHandles();
 				if (!isWorkingCopy // if unit is working copy, then save will have already fired the delta
 						&& !Util.isExcluded(unit)
 						&& unit.getParent().exists()) {
-					for (int i = 0; i < fResultElements.length; i++) {
-						delta.added(fResultElements[i]);
+					for (int i = 0; i < resultElements.length; i++) {
+						delta.added(resultElements[i]);
 					}
 					addDelta(delta);
 				} // else unit is created outside classpath
@@ -199,7 +200,7 @@
 	/**
 	 * Creates and returns the handles for the elements this operation created.
 	 */
-	protected IJavaElement[] generateResultHandles() throws JavaModelException {
+	protected IJavaElement[] generateResultHandles() {
 		return new IJavaElement[]{generateResultHandle()};
 	}
 	/**
@@ -220,21 +221,16 @@
 	 * progress reporting.
 	 */
 	public abstract String getMainTaskName();
-	/**
-	 * Returns the elements created by this operation.
-	 */
-	public IJavaElement[] getResultElements() {
-		return fResultElements;
-	}
+
 	/**
 	 * Sets the default position in which to create the new type
-	 * member. By default, the new element is positioned as the
-	 * last child of the parent element in which it is created.
+	 * member. 
 	 * Operations that require a different default position must
 	 * override this method.
 	 */
 	protected void initializeDefaultPosition() {
-	
+		// By default, the new element is positioned as the
+		// last child of the parent element in which it is created.
 	}
 	/**
 	 * Inserts the given child into the given JDOM, 
@@ -271,6 +267,7 @@
 	 * Only used for <code>CreateTypeMemberOperation</code>
 	 */
 	protected void setAlteredName(String newName) {
+		// implementation in CreateTypeMemberOperation
 	}
 	/**
 	 * Instructs this operation to position the new element relative
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateFieldOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateFieldOperation.java
index 51ada30..a7f1415 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateFieldOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateFieldOperation.java
@@ -18,6 +18,7 @@
 import org.eclipse.jdt.core.jdom.DOMFactory;
 import org.eclipse.jdt.core.jdom.IDOMField;
 import org.eclipse.jdt.core.jdom.IDOMNode;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * <p>This operation creates a field declaration in a type.
@@ -48,13 +49,16 @@
 		fDOMNode = (new DOMFactory()).createField(fSource);
 		if (fDOMNode == null) {
 			fDOMNode = generateSyntaxIncorrectDOM();
+			if (fDOMNode == null) {
+				throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_CONTENTS));
+			}
 		}
 		if (fAlteredName != null && fDOMNode != null) {
 			fDOMNode.setName(fAlteredName);
 		}
 	}
 	if (!(fDOMNode instanceof IDOMField)) {
-		return null;
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_CONTENTS));
 	}
 	return fDOMNode;
 }
@@ -88,6 +92,7 @@
 			}
 		}
 	} catch (JavaModelException e) {
+		// type doesn't exist: ignore
 	}
 }
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateImportOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateImportOperation.java
index 8681705..5fb337f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateImportOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateImportOperation.java
@@ -22,6 +22,7 @@
 import org.eclipse.jdt.core.jdom.DOMFactory;
 import org.eclipse.jdt.core.jdom.IDOMImport;
 import org.eclipse.jdt.core.jdom.IDOMNode;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * <p>This operation adds an import declaration to an existing compilation unit.
@@ -57,7 +58,7 @@
 /**
  * @see CreateTypeMemberOperation#generateElementDOM
  */
-protected IDOMNode generateElementDOM() throws JavaModelException {
+protected IDOMNode generateElementDOM() {
 	if (fCUDOM.getChild(fImportName) == null) {
 		DOMFactory factory = new DOMFactory();
 		//not a duplicate
@@ -111,7 +112,8 @@
 				return;
 			}
 		}
-	} catch (JavaModelException npe) {
+	} catch (JavaModelException e) {
+		// cu doesn't exit: ignore
 	}
 }
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateInitializerOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateInitializerOperation.java
index 0e29139..ed7b3f7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateInitializerOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateInitializerOperation.java
@@ -11,11 +11,13 @@
 package org.eclipse.jdt.internal.core;
 
 import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.jdom.DOMFactory;
 import org.eclipse.jdt.core.jdom.IDOMInitializer;
 import org.eclipse.jdt.core.jdom.IDOMNode;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * <p>This operation creates a initializer in a type.
@@ -47,15 +49,19 @@
  * @see CreateTypeMemberOperation#generateElementDOM
  */
 protected IDOMNode generateElementDOM() throws JavaModelException {
-	IDOMInitializer domInitializer = (new DOMFactory()).createInitializer(fSource);
-	if (domInitializer == null) {
-		IDOMNode node = generateSyntaxIncorrectDOM();
-		if (!(node instanceof IDOMInitializer)) {
-			return null;
+	if (fDOMNode == null) {
+		fDOMNode = (new DOMFactory()).createInitializer(fSource);
+		if (fDOMNode == null) {
+			fDOMNode = generateSyntaxIncorrectDOM();
+			if (fDOMNode == null) {
+				throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_CONTENTS));
+			}
 		}
-		domInitializer = (IDOMInitializer) node;
+	}					
+	if (!(fDOMNode instanceof IDOMInitializer)) {
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_CONTENTS));
 	}
-	return domInitializer;
+	return fDOMNode;
 }
 /**
  * @see CreateElementInCUOperation#generateResultHandle
@@ -82,7 +88,8 @@
 					}
 			}
 		}
-	} catch (JavaModelException jme) {
+	} catch (JavaModelException e) {
+		// type doesn't exist: ignore
 	}
 	return null;
 }
@@ -111,6 +118,7 @@
 			}
 		}
 	} catch (JavaModelException e) {
+		// type doesn't exist: ignore
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateMethodOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateMethodOperation.java
index 4bbc568..0212b62 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateMethodOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateMethodOperation.java
@@ -19,6 +19,7 @@
 import org.eclipse.jdt.core.jdom.DOMFactory;
 import org.eclipse.jdt.core.jdom.IDOMMethod;
 import org.eclipse.jdt.core.jdom.IDOMNode;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * <p>This operation creates an instance method. 
@@ -64,15 +65,19 @@
 protected IDOMNode generateElementDOM() throws JavaModelException {
 	if (fDOMNode == null) {
 		fDOMNode = (new DOMFactory()).createMethod(fSource);
-		if (fDOMNode == null) { //syntactically incorrect source
+		if (fDOMNode == null) {
+			//syntactically incorrect source
 			fDOMNode = generateSyntaxIncorrectDOM();
+			if (fDOMNode == null) {
+				throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_CONTENTS));
+			}
 		}
 		if (fAlteredName != null && fDOMNode != null) {
 			fDOMNode.setName(fAlteredName);
 		}
 	}
 	if (!(fDOMNode instanceof IDOMMethod)) {
-		return null;
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_CONTENTS));
 	}
 	return fDOMNode;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageDeclarationOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageDeclarationOperation.java
index 1c88ff2..0e92abf 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageDeclarationOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageDeclarationOperation.java
@@ -24,6 +24,7 @@
 import org.eclipse.jdt.core.jdom.IDOMNode;
 import org.eclipse.jdt.core.jdom.IDOMPackage;
 import org.eclipse.jdt.internal.core.jdom.DOMNode;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * <p>This operation adds/replaces a package declaration in an existing compilation unit.
@@ -109,7 +110,8 @@
 			createBefore(types[0]);
 			return;
 		}
-	} catch (JavaModelException npe) {
+	} catch (JavaModelException e) {
+		// cu doesn't exist: ignore
 	}
 }
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java
index dc2a24b..eb926d1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java
@@ -23,6 +23,7 @@
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaConventions;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This operation creates a new package fragment under a given package fragment root. 
@@ -70,7 +71,7 @@
 	beginTask(Util.bind("operation.createPackageFragmentProgress"), names.length); //$NON-NLS-1$
 	IContainer parentFolder = (IContainer) root.getResource();
 	String sideEffectPackageName = ""; //$NON-NLS-1$
-	ArrayList resultElements = new ArrayList(names.length);
+	ArrayList results = new ArrayList(names.length);
 	char[][] exclusionPatterns = ((PackageFragmentRoot)root).fullExclusionPatternChars();
 	int i;
 	for (i = 0; i < names.length; i++) {
@@ -78,7 +79,7 @@
 		sideEffectPackageName += subFolderName;
 		IResource subFolder = parentFolder.findMember(subFolderName);
 		if (subFolder == null) {
-			createFolder(parentFolder, subFolderName, fForce);
+			createFolder(parentFolder, subFolderName, force);
 			parentFolder = parentFolder.getFolder(new Path(subFolderName));
 			IPackageFragment addedFrag = root.getPackageFragment(sideEffectPackageName);
 			if (!Util.isExcluded(parentFolder, exclusionPatterns)) {
@@ -87,16 +88,16 @@
 				}
 				delta.added(addedFrag);
 			}
-			resultElements.add(addedFrag);
+			results.add(addedFrag);
 		} else {
 			parentFolder = (IContainer) subFolder;
 		}
 		sideEffectPackageName += '.';
 		worked(1);
 	}
-	if (resultElements.size() > 0) {
-		fResultElements = new IJavaElement[resultElements.size()];
-		resultElements.toArray(fResultElements);
+	if (results.size() > 0) {
+		resultElements = new IJavaElement[results.size()];
+		results.toArray(resultElements);
 		if (delta != null) {
 			addDelta(delta);
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeHierarchyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeHierarchyOperation.java
index 431494e..a37978e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeHierarchyOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeHierarchyOperation.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModelStatus;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
@@ -17,7 +18,6 @@
 import org.eclipse.jdt.core.IRegion;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.ITypeHierarchy;
-import org.eclipse.jdt.core.IWorkingCopy;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
 import org.eclipse.jdt.internal.core.hierarchy.RegionBasedTypeHierarchy;
@@ -41,34 +41,46 @@
 	 */
 	protected TypeHierarchy typeHierarchy;
 	
-	public IWorkingCopy[] workingCopies;
-	
 /**
  * Constructs an operation to create a type hierarchy for the
  * given type within the specified region, in the context of
  * the given project.
  */
-public CreateTypeHierarchyOperation(IType element, IRegion region, IJavaProject project, boolean computeSubtypes) throws JavaModelException {
+public CreateTypeHierarchyOperation(IRegion region, IJavaProject project, ICompilationUnit[] workingCopies, IType element, boolean computeSubtypes) {
 	super(element);
-	this.typeHierarchy = new RegionBasedTypeHierarchy(region, project, element, computeSubtypes);
+	this.typeHierarchy = new RegionBasedTypeHierarchy(region, project, workingCopies, element, computeSubtypes);
 }
 /**
  * Constructs an operation to create a type hierarchy for the
  * given type and working copies.
  */
-public CreateTypeHierarchyOperation(IType element, IWorkingCopy[] workingCopies, IJavaSearchScope scope, boolean computeSubtypes) throws JavaModelException {
+public CreateTypeHierarchyOperation(IType element, ICompilationUnit[] workingCopies, IJavaSearchScope scope, boolean computeSubtypes) {
 	super(element);
-	this.typeHierarchy = new TypeHierarchy(element, scope, computeSubtypes);
-	this.workingCopies = workingCopies;
+	ICompilationUnit[] copies;
+	if (workingCopies != null) {
+		int length = workingCopies.length;
+		copies = new ICompilationUnit[length];
+		System.arraycopy(workingCopies, 0, copies, 0, length);
+	} else {
+		copies = null;
+	}
+	this.typeHierarchy = new TypeHierarchy(element, copies, scope, computeSubtypes);
 }
 /**
  * Constructs an operation to create a type hierarchy for the
  * given type and working copies.
  */
-public CreateTypeHierarchyOperation(IType element, IWorkingCopy[] workingCopies, IJavaProject project, boolean computeSubtypes) throws JavaModelException {
+public CreateTypeHierarchyOperation(IType element, ICompilationUnit[] workingCopies, IJavaProject project, boolean computeSubtypes) {
 	super(element);
-	this.typeHierarchy = new TypeHierarchy(element, project, computeSubtypes);
-	this.workingCopies = workingCopies;
+	ICompilationUnit[] copies;
+	if (workingCopies != null) {
+		int length = workingCopies.length;
+		copies = new ICompilationUnit[length];
+		System.arraycopy(workingCopies, 0, copies, 0, length);
+	} else {
+		copies = null;
+	}
+	this.typeHierarchy = new TypeHierarchy(element, copies, project, computeSubtypes);
 }
 /**
  * Performs the operation - creates the type hierarchy
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java
index b5278e7..f30ade4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeMemberOperation.java
@@ -49,7 +49,7 @@
 public CreateTypeMemberOperation(IJavaElement parentElement, String source, boolean force) {
 	super(parentElement);
 	fSource= source;
-	fForce= force;
+	this.force= force;
 }
 /**
  * @see CreateElementInCUOperation#generateNewCompilationUnitDOM
@@ -77,7 +77,7 @@
  * Generates a <code>IDOMNode</code> based on the source of this operation
  * when there is likely a syntax error in the source.
  */
-protected IDOMNode generateSyntaxIncorrectDOM() throws JavaModelException {
+protected IDOMNode generateSyntaxIncorrectDOM() {
 	//create some dummy source to generate a dom node
 	StringBuffer buff = new StringBuffer();
 	buff.append(Util.LINE_SEPARATOR + " public class A {" + Util.LINE_SEPARATOR); //$NON-NLS-1$
@@ -117,17 +117,21 @@
 	if (!status.isOK()) {
 		return status;
 	}
+	IJavaElement parent = getParentElement(); // non-null since check was done in supper
+	Member localContext;
+	if (parent instanceof Member && (localContext = ((Member)parent).getOuterMostLocalContext()) != null && localContext != parent) {
+		// JDOM doesn't support source manipulation in local/anonymous types
+		return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, parent);
+	}
 	if (fSource == null) {
 		return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CONTENTS);
 	}
-	if (!fForce) {
+	if (!force) {
 		//check for name collisions
 		try {
-			IDOMNode node= generateElementDOM();
-			if (node == null) {
-				return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CONTENTS);
-			}
+			generateElementDOM();
 		} catch (JavaModelException jme) {
+			return jme.getJavaModelStatus();
 		}
 		return verifyNameCollision();
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeOperation.java
index edaab05..86c498c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateTypeOperation.java
@@ -19,6 +19,7 @@
 import org.eclipse.jdt.core.jdom.DOMFactory;
 import org.eclipse.jdt.core.jdom.IDOMNode;
 import org.eclipse.jdt.core.jdom.IDOMType;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * <p>This operation creates a class or interface.
@@ -44,14 +45,18 @@
 	if (fDOMNode == null) {
 		fDOMNode = (new DOMFactory()).createType(fSource);
 		if (fDOMNode == null) {
+			//syntactically incorrect source
 			fDOMNode = generateSyntaxIncorrectDOM();
+			if (fDOMNode == null) {
+				throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_CONTENTS));
+			}
 		}
 		if (fAlteredName != null && fDOMNode != null) {
 			fDOMNode.setName(fAlteredName);
 		}
 	}
 	if (!(fDOMNode instanceof IDOMType)) {
-		return null;
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_CONTENTS));
 	}
 	return fDOMNode;
 }
@@ -60,12 +65,13 @@
  */
 protected IJavaElement generateResultHandle() {
 	IJavaElement parent= getParentElement();
-	int type= parent.getElementType();
-	if (type == IJavaElement.TYPE) {
-		return ((IType)parent).getType(fDOMNode.getName());
-	} else if (type == IJavaElement.COMPILATION_UNIT) {
-		return ((ICompilationUnit)parent).getType(fDOMNode.getName());
-	} 
+	switch (parent.getElementType()) {
+		case IJavaElement.COMPILATION_UNIT:
+			return ((ICompilationUnit)parent).getType(fDOMNode.getName());
+		case IJavaElement.TYPE:
+			return ((IType)parent).getType(fDOMNode.getName());
+		// Note: creating local/anonymous type is not supported 
+	}
 	return null;
 }
 /**
@@ -89,21 +95,23 @@
  */
 protected IJavaModelStatus verifyNameCollision() {
 	IJavaElement parent = getParentElement();
-	int type = parent.getElementType();
-	if (type == IJavaElement.TYPE) {
-		if (((IType) parent).getType(fDOMNode.getName()).exists()) {
-			return new JavaModelStatus(
-				IJavaModelStatusConstants.NAME_COLLISION, 
-				Util.bind("status.nameCollision", fDOMNode.getName())); //$NON-NLS-1$
-		}
-	} else
-		if (type == IJavaElement.COMPILATION_UNIT) {
+	switch (parent.getElementType()) {
+		case IJavaElement.COMPILATION_UNIT:
 			if (((ICompilationUnit) parent).getType(fDOMNode.getName()).exists()) {
 				return new JavaModelStatus(
 					IJavaModelStatusConstants.NAME_COLLISION, 
 					Util.bind("status.nameCollision", fDOMNode.getName())); //$NON-NLS-1$
 			}
-		}
+			break;
+		case IJavaElement.TYPE:
+			if (((IType) parent).getType(fDOMNode.getName()).exists()) {
+				return new JavaModelStatus(
+					IJavaModelStatusConstants.NAME_COLLISION, 
+					Util.bind("status.nameCollision", fDOMNode.getName())); //$NON-NLS-1$
+			}
+			break;
+		// Note: creating local/anonymous type is not supported 
+	}
 	return JavaModelStatus.VERIFIED_OK;
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateWorkingCopyOperation.java
deleted file mode 100644
index 387e4e5..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreateWorkingCopyOperation.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core;
-
-import java.util.Map;
-
-import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.JavaModelException;
-
-/**
- * Creates a new working copy and signal its addition through a delta.
- */
-public class CreateWorkingCopyOperation extends JavaModelOperation {
-	
-	Map perFactoryWorkingCopies;
-	IBufferFactory factory;
-	IProblemRequestor problemRequestor;
-	
-	/*
-	 * Creates a working copy from the given original cu and the given buffer factory.
-	 * perFactoryWorkingCopies map is not null if the working copy is a shared working copy.
-	 */
-	public CreateWorkingCopyOperation(ICompilationUnit originalElement, Map perFactoryWorkingCopies, IBufferFactory factory, IProblemRequestor problemRequestor) {
-		super(new IJavaElement[] {originalElement});
-		this.perFactoryWorkingCopies = perFactoryWorkingCopies;
-		this.factory = factory;
-		this.problemRequestor = problemRequestor;
-	}
-	protected void executeOperation() throws JavaModelException {
-		ICompilationUnit cu = getCompilationUnit();
-
-		WorkingCopy workingCopy = new WorkingCopy((IPackageFragment)cu.getParent(), cu.getElementName(), this.factory, this.problemRequestor);
-		// open the working copy now to ensure contents are that of the current state of this element
-		workingCopy.open(this.fMonitor);
-		
-		if (this.perFactoryWorkingCopies != null) {
-			this.perFactoryWorkingCopies.put(cu, workingCopy);
-			if (CompilationUnit.SHARED_WC_VERBOSE) {
-				System.out.println("Creating shared working copy " + workingCopy.toStringWithAncestors()); //$NON-NLS-1$
-			}
-		}
-
-		// report added java delta
-		JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
-		delta.added(workingCopy);
-		addDelta(delta);
-
-		fResultElements = new IJavaElement[] {workingCopy};
-	}
-	/**
-	 * Returns the compilation unit this operation is working on.
-	 */
-	protected ICompilationUnit getCompilationUnit() {
-		return (ICompilationUnit)getElementToProcess();
-	}
-	/**
-	 * @see JavaModelOperation#isReadOnly
-	 */
-	public boolean isReadOnly() {
-		return true;
-	}
-
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DefaultWorkingCopyOwner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DefaultWorkingCopyOwner.java
new file mode 100644
index 0000000..02dbe0f
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DefaultWorkingCopyOwner.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.IBuffer;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+
+/**
+ * A working copy owner that creates internal buffers.
+ * It also defines the PRIMARY working copy owner that is used by JDT/Core.
+ */
+public class DefaultWorkingCopyOwner extends WorkingCopyOwner {
+	
+	/**
+	 * Note this field is temporary public so that JDT/UI can reach in and change the factory. It will disapear before 3.0.
+	 * @deprecated
+	 */
+	public org.eclipse.jdt.core.IBufferFactory factory; // TODO remove before 3.0
+		
+	public static final DefaultWorkingCopyOwner PRIMARY =  new DefaultWorkingCopyOwner();
+	
+	private DefaultWorkingCopyOwner() {
+		// only one instance can be created
+	}
+
+	/**
+	 * @deprecated Marked deprecated as it is using deprecated code
+	 */
+	public IBuffer createBuffer(ICompilationUnit workingCopy) {
+		if (this.factory == null) return super.createBuffer(workingCopy);
+		return this.factory.createBuffer(workingCopy); // TODO (jerome) change to use a org.eclipse.text buffer
+	}
+	public String toString() {
+		return "Primary owner"; //$NON-NLS-1$
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
index b3661d5..d33e759 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteElementsOperation.java
@@ -24,6 +24,7 @@
 import org.eclipse.jdt.core.jdom.DOMFactory;
 import org.eclipse.jdt.core.jdom.IDOMCompilationUnit;
 import org.eclipse.jdt.internal.core.jdom.DOMNode;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This operation deletes a collection of elements (and
@@ -42,12 +43,12 @@
 	 * values are <code>IRegion</code>s of elements to be processed in each
 	 * compilation unit.
 	 */ 
-	protected Map fChildrenToRemove;
+	protected Map childrenToRemove;
 	/**
 	 * The <code>DOMFactory</code> used to manipulate the source code of
 	 * <code>ICompilationUnit</code>s.
 	 */
-	protected DOMFactory fFactory;
+	protected DOMFactory factory;
 	/**
 	 * When executed, this operation will delete the given elements. The elements
 	 * to delete cannot be <code>null</code> or empty, and must be contained within a
@@ -55,7 +56,7 @@
 	 */
 	public DeleteElementsOperation(IJavaElement[] elementsToDelete, boolean force) {
 		super(elementsToDelete, force);
-		fFactory = new DOMFactory();
+		factory = new DOMFactory();
 	}
 	
 	/**
@@ -71,28 +72,28 @@
 	 * duplicates specified in elements to be processed.
 	 */
 	protected void groupElements() throws JavaModelException {
-		fChildrenToRemove = new HashMap(1);
+		childrenToRemove = new HashMap(1);
 		int uniqueCUs = 0;
-		for (int i = 0, length = fElementsToProcess.length; i < length; i++) {
-			IJavaElement e = fElementsToProcess[i];
+		for (int i = 0, length = elementsToProcess.length; i < length; i++) {
+			IJavaElement e = elementsToProcess[i];
 			ICompilationUnit cu = getCompilationUnitFor(e);
 			if (cu == null) {
-				throw new JavaModelException(new JavaModelStatus(JavaModelStatus.READ_ONLY, e));
+				throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, e));
 			} else {
-				IRegion region = (IRegion) fChildrenToRemove.get(cu);
+				IRegion region = (IRegion) childrenToRemove.get(cu);
 				if (region == null) {
 					region = new Region();
-					fChildrenToRemove.put(cu, region);
+					childrenToRemove.put(cu, region);
 					uniqueCUs += 1;
 				}
 				region.add(e);
 			}
 		}
-		fElementsToProcess = new IJavaElement[uniqueCUs];
-		Iterator iter = fChildrenToRemove.keySet().iterator();
+		elementsToProcess = new IJavaElement[uniqueCUs];
+		Iterator iter = childrenToRemove.keySet().iterator();
 		int i = 0;
 		while (iter.hasNext()) {
-			fElementsToProcess[i++] = (IJavaElement) iter.next();
+			elementsToProcess[i++] = (IJavaElement) iter.next();
 		}
 	}
 	/**
@@ -109,13 +110,13 @@
 		IBuffer buffer = cu.getBuffer();
 		if (buffer == null) return;
 		JavaElementDelta delta = new JavaElementDelta(cu);
-		IJavaElement[] cuElements = ((IRegion) fChildrenToRemove.get(cu)).getElements();
+		IJavaElement[] cuElements = ((IRegion) childrenToRemove.get(cu)).getElements();
 		for (int i = 0, length = cuElements.length; i < length; i++) {
 			IJavaElement e = cuElements[i];
 			if (e.exists()) {
 				char[] contents = buffer.getCharacters();
 				if (contents == null) continue;
-				IDOMCompilationUnit cuDOM = fFactory.createCompilationUnit(contents, cu.getElementName());
+				IDOMCompilationUnit cuDOM = factory.createCompilationUnit(contents, cu.getElementName());
 				DOMNode node = (DOMNode)((JavaElement) e).findNode(cuDOM);
 				if (node == null) Assert.isTrue(false, "Failed to locate " + e.getElementName() + " in " + cuDOM.getName()); //$NON-NLS-1$//$NON-NLS-2$
 
@@ -131,7 +132,7 @@
 			}
 		}
 		if (delta.getAffectedChildren().length > 0) {
-			cu.save(getSubProgressMonitor(1), fForce);
+			cu.save(getSubProgressMonitor(1), force);
 			if (!cu.isWorkingCopy()) { // if unit is working copy, then save will have already fired the delta
 				addDelta(delta);
 				this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
@@ -151,11 +152,18 @@
 	 * @see MultiOperation
 	 */
 	protected void verify(IJavaElement element) throws JavaModelException {
-		IJavaElement[] children = ((IRegion) fChildrenToRemove.get(element)).getElements();
+		IJavaElement[] children = ((IRegion) childrenToRemove.get(element)).getElements();
 		for (int i = 0; i < children.length; i++) {
 			IJavaElement child = children[i];
 			if (child.getCorrespondingResource() != null)
 				error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, child);
+
+			Member localContext;
+			if (child instanceof Member && (localContext = ((Member)child).getOuterMostLocalContext()) != null && localContext != child) {
+				// JDOM doesn't support source manipulation in local/anonymous types
+				error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, child);
+			}
+
 			if (child.isReadOnly())
 				error(IJavaModelStatusConstants.READ_ONLY, child);
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java
index 5c7bc1d..fc68fc7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java
@@ -57,7 +57,7 @@
 		IResource rootResource = root.getResource();
 		if (rootEntry.getEntryKind() != IClasspathEntry.CPE_SOURCE || exclusionPatterns == null) {
 			try {
-				rootResource.delete(this.updateResourceFlags, fMonitor);
+				rootResource.delete(this.updateResourceFlags, progressMonitor);
 			} catch (CoreException e) {
 				throw new JavaModelException(e);
 			}
@@ -72,11 +72,11 @@
 							return !equalsOneOf(path, nestedFolders);
 						} else {
 							// subtree doesn't contain any nested source folders
-							proxy.requestResource().delete(updateResourceFlags, fMonitor);
+							proxy.requestResource().delete(updateResourceFlags, progressMonitor);
 							return false;
 						}
 					} else {
-						proxy.requestResource().delete(updateResourceFlags, fMonitor);
+						proxy.requestResource().delete(updateResourceFlags, progressMonitor);
 						return false;
 					}
 				}
@@ -129,7 +129,7 @@
 			if (newCPIndex < newClasspath.length) {
 				System.arraycopy(newClasspath, 0, newClasspath = new IClasspathEntry[newCPIndex], 0, newCPIndex);
 			}
-			project.setRawClasspath(newClasspath, fMonitor);
+			project.setRawClasspath(newClasspath, progressMonitor);
 		}
 	}	
 	protected IJavaModelStatus verify() {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java
index 375a141..aae4d4d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java
@@ -10,14 +10,17 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import org.eclipse.core.resources.*;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.IOpenable;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This operation deletes a collection of resources and all of their children.
@@ -41,7 +44,7 @@
 private void deletePackageFragment(IPackageFragment frag)
 	throws JavaModelException {
 	IResource res = frag.getResource();
-	if (res != null && res.getType() == IResource.FOLDER) {
+	if (res != null) {
 		// collect the children to remove
 		IJavaElement[] childrenOfInterest = frag.getChildren();
 		if (childrenOfInterest.length > 0) {
@@ -50,7 +53,7 @@
 			for (int i = 0; i < childrenOfInterest.length; i++) {
 				resources[i] = childrenOfInterest[i].getCorrespondingResource();
 			}
-			deleteResources(resources, fForce);
+			deleteResources(resources, force);
 		}
 
 		// Discard non-java resources
@@ -63,25 +66,25 @@
 		for (int i = 0, max = nonJavaResources.length, index = 0; i < max; i++){
 			if (nonJavaResources[i] instanceof IResource) actualNonJavaResources[index++] = (IResource)nonJavaResources[i];
 		}
-		deleteResources(actualNonJavaResources, fForce);
+		deleteResources(actualNonJavaResources, force);
 		
 		// delete remaining files in this package (.class file in the case where Proj=src=bin)
 		IResource[] remainingFiles;
 		try {
-			remainingFiles = ((IFolder) res).members();
+			remainingFiles = ((IContainer) res).members();
 		} catch (CoreException ce) {
 			throw new JavaModelException(ce);
 		}
 		boolean isEmpty = true;
 		for (int i = 0, length = remainingFiles.length; i < length; i++) {
 			IResource file = remainingFiles[i];
-			if (file instanceof IFile) {
+			if (file instanceof IFile && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(file.getName())) {
 				this.deleteResource(file, IResource.FORCE | IResource.KEEP_HISTORY);
 			} else {
 				isEmpty = false;
 			}
 		}
-		if (isEmpty) {
+		if (isEmpty && !frag.isDefaultPackage()/*don't delete default package's folder: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38450*/) {
 			// delete recursively empty folders
 			IResource fragResource =  frag.getResource();
 			if (fragResource != null) {
@@ -104,13 +107,13 @@
 	switch (element.getElementType()) {
 		case IJavaElement.CLASS_FILE :
 		case IJavaElement.COMPILATION_UNIT :
-			deleteResource(element.getResource(), fForce ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY);
+			deleteResource(element.getResource(), force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY);
 			break;
 		case IJavaElement.PACKAGE_FRAGMENT :
 			deletePackageFragment((IPackageFragment) element);
 			break;
 		default :
-			throw new JavaModelException(new JavaModelStatus(JavaModelStatus.INVALID_ELEMENT_TYPES, element));
+			throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element));
 	}
 	// ensure the element is closed
 	if (element instanceof IOpenable) {
@@ -122,17 +125,17 @@
  */
 protected void verify(IJavaElement element) throws JavaModelException {
 	if (element == null || !element.exists())
-		error(JavaModelStatus.ELEMENT_DOES_NOT_EXIST, element);
+		error(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, element);
 
 	int type = element.getElementType();
 	if (type <= IJavaElement.PACKAGE_FRAGMENT_ROOT || type > IJavaElement.COMPILATION_UNIT)
-		error(JavaModelStatus.INVALID_ELEMENT_TYPES, element);
+		error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
 	else if (type == IJavaElement.PACKAGE_FRAGMENT && element instanceof JarPackageFragment)
-		error(JavaModelStatus.INVALID_ELEMENT_TYPES, element);
+		error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
 	IResource resource = element.getResource();
 	if (resource instanceof IFolder) {
 		if (resource.isLinked()) {
-			error(JavaModelStatus.INVALID_RESOURCE, element);
+			error(IJavaModelStatusConstants.INVALID_RESOURCE, element);
 		}
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java
new file mode 100644
index 0000000..00b080c
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java
@@ -0,0 +1,289 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core;
+
+import java.util.*;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.core.resources.*;
+import org.eclipse.core.resources.IResourceChangeEvent;
+import org.eclipse.core.resources.IResourceChangeListener;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.IJavaModel;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaModelException;
+
+/**
+ * Keep the global states used during Java element delta processing.
+ */
+public class DeltaProcessingState implements IResourceChangeListener {
+	
+	/*
+	 * Collection of listeners for Java element deltas
+	 */
+	public IElementChangedListener[] elementChangedListeners = new IElementChangedListener[5];
+	public int[] elementChangedListenerMasks = new int[5];
+	public int elementChangedListenerCount = 0;
+
+	/*
+	 * The delta processor for the current thread.
+	 */
+	private ThreadLocal deltaProcessors = new ThreadLocal();
+	
+	/* A table from IPath (from a classpath entry) to RootInfo */
+	public HashMap roots = new HashMap();
+	
+	/* A table from IPath (from a classpath entry) to ArrayList of RootInfo
+	 * Used when an IPath corresponds to more than one root */
+	public HashMap otherRoots = new HashMap();
+	
+	/* A table from IPath (from a classpath entry) to RootInfo
+	 * from the last time the delta processor was invoked. */
+	public HashMap oldRoots = new HashMap();
+	
+	/* A table from IPath (from a classpath entry) to ArrayList of RootInfo
+	 * from the last time the delta processor was invoked.
+	 * Used when an IPath corresponds to more than one root */
+	public HashMap oldOtherRoots = new HashMap();
+	
+	/* A table from IPath (a source attachment path from a classpath entry) to IPath (a root path) */
+	public HashMap sourceAttachments = new HashMap();
+
+	/* Whether the roots tables should be recomputed */
+	public boolean rootsAreStale = true;
+	
+	/* Threads that are currently running initializeRoots() */
+	private Set initializingThreads = Collections.synchronizedSet(new HashSet());	
+	
+	public Hashtable externalTimeStamps = new Hashtable();
+
+	/**
+	 * Workaround for bug 15168 circular errors not reported  
+	 * This is a cache of the projects before any project addition/deletion has started.
+	 */
+	public IJavaProject[] modelProjectsCache;
+		
+	/*
+	 * 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++;
+	}
+
+	public DeltaProcessor getDeltaProcessor() {
+		DeltaProcessor deltaProcessor = (DeltaProcessor)this.deltaProcessors.get();
+		if (deltaProcessor != null) return deltaProcessor;
+		deltaProcessor = new DeltaProcessor(this, JavaModelManager.getJavaModelManager());
+		this.deltaProcessors.set(deltaProcessor);
+		return deltaProcessor;
+	}
+
+	public void initializeRoots() {
+		
+		// recompute root infos only if necessary
+		HashMap newRoots = null;
+		HashMap newOtherRoots = null;
+		HashMap newSourceAttachments = null;
+		if (this.rootsAreStale) {
+			Thread currentThread = Thread.currentThread();
+			boolean addedCurrentThread = false;			
+			try {
+				// if reentering initialization (through a container initializer for example) no need to compute roots again
+				// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=47213
+				if (!this.initializingThreads.add(currentThread)) return;
+				addedCurrentThread = true;
+
+				newRoots = new HashMap();
+				newOtherRoots = new HashMap();
+				newSourceAttachments = new HashMap();
+		
+				IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
+				IJavaProject[] projects;
+				try {
+					projects = model.getJavaProjects();
+				} catch (JavaModelException e) {
+					// nothing can be done
+					return;
+				}
+				for (int i = 0, length = projects.length; i < length; i++) {
+					IJavaProject project = projects[i];
+					IClasspathEntry[] classpath;
+					try {
+						classpath = project.getResolvedClasspath(true);
+					} catch (JavaModelException e) {
+						// continue with next project
+						continue;
+					}
+					for (int j= 0, classpathLength = classpath.length; j < classpathLength; j++) {
+						IClasspathEntry entry = classpath[j];
+						if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue;
+						
+						// root path
+						IPath path = entry.getPath();
+						if (newRoots.get(path) == null) {
+							newRoots.put(path, new DeltaProcessor.RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars(), entry.getEntryKind()));
+						} else {
+							ArrayList rootList = (ArrayList)newOtherRoots.get(path);
+							if (rootList == null) {
+								rootList = new ArrayList();
+								newOtherRoots.put(path, rootList);
+							}
+							rootList.add(new DeltaProcessor.RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars(), entry.getEntryKind()));
+						}
+						
+						// source attachment path
+						if (entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY) continue;
+						QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + path.toOSString()); //$NON-NLS-1$;
+						String propertyString = null;
+						try {
+							propertyString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
+						} catch (CoreException e) {
+							continue;
+						}
+						IPath sourceAttachmentPath;
+						if (propertyString != null) {
+							int index= propertyString.lastIndexOf(PackageFragmentRoot.ATTACHMENT_PROPERTY_DELIMITER);
+							sourceAttachmentPath = (index < 0) ?  new Path(propertyString) : new Path(propertyString.substring(0, index));
+						} else {
+							sourceAttachmentPath = entry.getSourceAttachmentPath();
+						}
+						if (sourceAttachmentPath != null) {
+							newSourceAttachments.put(sourceAttachmentPath, path);
+						}
+					}
+				}
+			} finally {
+				if (addedCurrentThread) {
+					this.initializingThreads.remove(currentThread);
+				}
+			}
+		}
+		synchronized(this) {
+			this.oldRoots = this.roots;
+			this.oldOtherRoots = this.otherRoots;			
+			if (this.rootsAreStale && newRoots != null) { // double check again
+				this.roots = newRoots;
+				this.otherRoots = newOtherRoots;
+				this.sourceAttachments = newSourceAttachments;
+				this.rootsAreStale = false;
+			}
+		}
+	}
+
+	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;
+			}
+		}
+	}
+
+	public void resourceChanged(IResourceChangeEvent event) {
+		try {
+			getDeltaProcessor().resourceChanged(event);
+		} finally {
+			// TODO (jerome) see 47631, may want to get rid of following so as to reuse delta processor ? 
+			if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
+				this.deltaProcessors.set(null);
+			}
+		}
+
+	}
+
+	/*
+	 * Update the roots that are affected by the addition or the removal of the given container resource.
+	 */
+	public synchronized void updateRoots(IPath containerPath, IResourceDelta containerDelta, DeltaProcessor deltaProcessor) {
+		Map updatedRoots;
+		Map otherUpdatedRoots;
+		if (containerDelta.getKind() == IResourceDelta.REMOVED) {
+			updatedRoots = this.oldRoots;
+			otherUpdatedRoots = this.oldOtherRoots;
+		} else {
+			updatedRoots = this.roots;
+			otherUpdatedRoots = this.otherRoots;
+		}
+		Iterator iterator = updatedRoots.keySet().iterator();
+		while (iterator.hasNext()) {
+			IPath path = (IPath)iterator.next();
+			if (containerPath.isPrefixOf(path) && !containerPath.equals(path)) {
+				IResourceDelta rootDelta = containerDelta.findMember(path.removeFirstSegments(1));
+				if (rootDelta == null) continue;
+				DeltaProcessor.RootInfo rootInfo = (DeltaProcessor.RootInfo)updatedRoots.get(path);
+	
+				if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
+					deltaProcessor.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);
+				}
+				
+				ArrayList rootList = (ArrayList)otherUpdatedRoots.get(path);
+				if (rootList != null) {
+					Iterator otherProjects = rootList.iterator();
+					while (otherProjects.hasNext()) {
+						rootInfo = (DeltaProcessor.RootInfo)otherProjects.next();
+						if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
+							deltaProcessor.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);
+						}
+					}
+				}
+			}
+		}
+	}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index 19e3dfe..7bb54ad 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -22,31 +22,32 @@
 import org.eclipse.core.resources.IProject;
 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.IWorkspace;
 import org.eclipse.core.resources.IWorkspaceRoot;
 import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.*;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Preferences;
-import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.ElementChangedEvent;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaElementDelta;
 import org.eclipse.jdt.core.IJavaModel;
-import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.internal.core.builder.JavaBuilder;
+import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
+import org.eclipse.jdt.internal.core.search.AbstractSearchScope;
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This class is used by <code>JavaModelManager</code> to convert
@@ -54,78 +55,12 @@
  * It also does some processing on the <code>JavaElement</code>s involved
  * (e.g. closing them or updating classpaths).
  */
-public class DeltaProcessor implements IResourceChangeListener {
+public class DeltaProcessor {
 	
-	final static int IGNORE = 0;
-	final static int SOURCE = 1;
-	final static int BINARY = 2;
-	
-	final static String EXTERNAL_JAR_ADDED = "external jar added"; //$NON-NLS-1$
-	final static String EXTERNAL_JAR_REMOVED = "external jar removed"; //$NON-NLS-1$
-	final static String EXTERNAL_JAR_CHANGED = "external jar changed"; //$NON-NLS-1$
-	final static String EXTERNAL_JAR_UNCHANGED = "external jar unchanged"; //$NON-NLS-1$
-	final static String INTERNAL_JAR_IGNORE = "internal jar ignore"; //$NON-NLS-1$
-	
-	final static int NON_JAVA_RESOURCE = -1;
-	
-	/**
-	 * The <code>JavaElementDelta</code> corresponding to the <code>IResourceDelta</code> being translated.
-	 */
-	protected JavaElementDelta currentDelta;
-	
-	protected IndexManager indexManager = new IndexManager();
-		
-	/* A table from IPath (from a classpath entry) to RootInfo */
-	public Map roots;
-	
-	/* A table from IPath (from a classpath entry) to ArrayList of RootInfo
-	 * Used when an IPath corresponds to more than one root */
-	Map otherRoots;
-	
-	/* Whether the roots tables should be recomputed */
-	public boolean rootsAreStale = true;
-	
-	/* A table from IPath (from a classpath entry) to RootInfo
-	 * from the last time the delta processor was invoked. */
-	public Map oldRoots;
-
-	/* A table from IPath (from a classpath entry) to ArrayList of RootInfo
-	 * from the last time the delta processor was invoked.
-	 * Used when an IPath corresponds to more than one root */
-	Map oldOtherRoots;
-	
-	/* A table from IPath (a source attachment path from a classpath entry) to IPath (a root path) */
-	Map sourceAttachments;
-
-	/* The java element that was last created (see createElement(IResource)). 
-	 * This is used as a stack of java elements (using getParent() to pop it, and 
-	 * using the various get*(...) to push it. */
-	Openable currentElement;
-		
-	public HashMap externalTimeStamps = new HashMap();
-	public HashSet projectsToUpdate = new HashSet();
-	// list of root projects which namelookup caches need to be updated for dependents
-	// TODO: (jerome) is it needed? projectsToUpdate might be sufficient
-	public HashSet projectsForDependentNamelookupRefresh = new HashSet();  
-	
-	JavaModelManager manager;
-	
-	/* A table from IJavaProject to an array of IPackageFragmentRoot.
-	 * This table contains the pkg fragment roots of the project that are being deleted.
-	 */
-	Map removedRoots;
-	
-	/*
-	 * A list of IJavaElement used as a scope for external archives refresh during POST_CHANGE.
-	 * This is null if no refresh is needed.
-	 */
-	HashSet refreshedElements;
-	public static boolean VERBOSE = false;
-	
-	class OutputsInfo {
+	static class OutputsInfo {
+		int outputCount;
 		IPath[] paths;
 		int[] traverseModes;
-		int outputCount;
 		OutputsInfo(IPath[] paths, int[] traverseModes, int outputCount) {
 			this.paths = paths;
 			this.traverseModes = traverseModes;
@@ -158,14 +93,17 @@
 			return buffer.toString();
 		}
 	}
-	class RootInfo {
+	
+	static class RootInfo {
+		char[][] exclusionPatterns;
 		IJavaProject project;
 		IPath rootPath;
-		char[][] exclusionPatterns;
-		RootInfo(IJavaProject project, IPath rootPath, char[][] exclusionPatterns) {
+		int entryKind;
+		RootInfo(IJavaProject project, IPath rootPath, char[][] exclusionPatterns, int entryKind) {
 			this.project = project;
 			this.rootPath = rootPath;
 			this.exclusionPatterns = exclusionPatterns;
+			this.entryKind = entryKind;
 		}
 		boolean isRootOfProject(IPath path) {
 			return this.rootPath.equals(path) && this.project.getProject().getFullPath().isPrefixOf(path);
@@ -198,7 +136,90 @@
 		}
 	}
 
-	DeltaProcessor(JavaModelManager manager) {
+	private final static int IGNORE = 0;
+	private final static int SOURCE = 1;
+	private final static int BINARY = 2;
+	
+	private final static String EXTERNAL_JAR_ADDED = "external jar added"; //$NON-NLS-1$
+	private final static String EXTERNAL_JAR_CHANGED = "external jar changed"; //$NON-NLS-1$
+	private final static String EXTERNAL_JAR_REMOVED = "external jar removed"; //$NON-NLS-1$
+	private final static String EXTERNAL_JAR_UNCHANGED = "external jar unchanged"; //$NON-NLS-1$
+	private final static String INTERNAL_JAR_IGNORE = "internal jar ignore"; //$NON-NLS-1$
+	
+	private final static int NON_JAVA_RESOURCE = -1;
+	public static boolean VERBOSE = false;
+
+	public static final int DEFAULT_CHANGE_EVENT = 0; // must not collide with ElementChangedEvent event masks
+
+	/*
+	 * Answer a combination of the lastModified stamp and the size.
+	 * Used for detecting external JAR changes
+	 */
+	public static long getTimeStamp(File file) {
+		return file.lastModified() + file.length();
+	}
+	
+	/*
+	 * The global state of delta processing.
+	 */
+	private DeltaProcessingState state;
+	
+	/*
+	 * The Java model manager
+	 */
+	private JavaModelManager manager;
+	
+	/*
+	 * The <code>JavaElementDelta</code> corresponding to the <code>IResourceDelta</code> being translated.
+	 */
+	private JavaElementDelta currentDelta;
+
+	/* The java element that was last created (see createElement(IResource)). 
+	 * This is used as a stack of java elements (using getParent() to pop it, and 
+	 * using the various get*(...) to push it. */
+	private Openable currentElement;
+		
+	/*
+	 * Queue of deltas created explicily by the Java Model that
+	 * have yet to be fired.
+	 */
+	public 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
+	 */
+	public HashMap reconcileDeltas = new HashMap();
+
+	/*
+	 * Turns delta firing on/off. By default it is on.
+	 */
+	private boolean isFiring= true;
+	
+	/*
+	 * Used to update the JavaModel for <code>IJavaElementDelta</code>s.
+	 */
+	private final ModelUpdater modelUpdater = new ModelUpdater();
+
+	/* A set of IJavaProject whose namelookup caches need to be refreshed */
+	private HashSet namelookupsToRefresh = new HashSet();  
+
+	/*
+	 * A list of IJavaElement used as a scope for external archives refresh during POST_CHANGE.
+	 * This is null if no refresh is needed.
+	 */
+	private HashSet refreshedElements;
+	
+	/* A table from IJavaProject to an array of IPackageFragmentRoot.
+	 * This table contains the pkg fragment roots of the project that are being deleted.
+	 */
+	public Map removedRoots;
+	
+	/* A set of IJavaProject whose package fragment roots need to be refreshed */
+	private HashSet rootsToRefresh = new HashSet();
+	
+	public DeltaProcessor(DeltaProcessingState state, JavaModelManager manager) {
+		this.state = state;
 		this.manager = manager;
 	}
 
@@ -206,22 +227,31 @@
 	 * Adds the dependents of the given project to the list of the projects
 	 * to update.
 	 */
-	void addDependentProjects(IPath projectPath, HashSet result) {
+	private void addDependentProjects(IPath projectPath, HashSet result) {
+		IJavaProject[] projects = null;
 		try {
-			IJavaProject[] projects = this.manager.getJavaModel().getJavaProjects();
-			for (int i = 0, length = projects.length; i < length; i++) {
-				IJavaProject project = projects[i];
-				IClasspathEntry[] classpath = ((JavaProject)project).getExpandedClasspath(true);
-				for (int j = 0, length2 = classpath.length; j < length2; j++) {
-					IClasspathEntry entry = classpath[j];
-						if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT
-								&& entry.getPath().equals(projectPath)) {
-							result.add(project);
-						}
+			projects = this.manager.getJavaModel().getJavaProjects();
+		} catch (JavaModelException e) {
+			// java model doesn't exist
+			return;
+		}
+		for (int i = 0, length = projects.length; i < length; i++) {
+			IJavaProject project = projects[i];
+			IClasspathEntry[] classpath = null;
+			try {
+				classpath = ((JavaProject)project).getExpandedClasspath(true);
+			} catch (JavaModelException e) {
+				// project doesn't exist: continue with next project
+				continue;
+			}
+			for (int j = 0, length2 = classpath.length; j < length2; j++) {
+				IClasspathEntry entry = classpath[j];
+					if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT
+							&& entry.getPath().equals(projectPath)) {
+						result.add(project);
 					}
 				}
-		} catch (JavaModelException e) {
-		}
+			}
 	}
 	/*
 	 * Adds the given element to the list of elements used as a scope for external jars refresh.
@@ -233,19 +263,9 @@
 		this.refreshedElements.add(element);
 	}
 	/*
-	 * Adds the given project and its dependents to the list of the projects
-	 * to update.
-	 */
-	void addToProjectsToUpdateWithDependents(IProject project) {
-		this.projectsToUpdate.add(JavaCore.create(project));
-		this.addDependentProjects(project.getFullPath(), this.projectsToUpdate);
-	}
-	
-	/**
 	 * Adds the given child handle to its parent's cache of children. 
 	 */
-	protected void addToParentInfo(Openable child) {
-
+	private void addToParentInfo(Openable child) {
 		Openable parent = (Openable) child.getParent();
 		if (parent != null && parent.isOpen()) {
 			try {
@@ -256,15 +276,21 @@
 			}
 		}
 	}
-
-	/**
+	/*
+	 * Adds the given project and its dependents to the list of the roots to refresh.
+	 */
+	private void addToRootsToRefreshWithDependents(IJavaProject javaProject) {
+		this.rootsToRefresh.add(javaProject);
+		this.addDependentProjects(javaProject.getPath(), this.rootsToRefresh);
+	}
+	/*
 	 * Check all external archive (referenced by given roots, projects or model) status and issue a corresponding root delta.
 	 * Also triggers index updates
 	 */
-	public void checkExternalArchiveChanges(IJavaElement[] refreshedElements, IProgressMonitor monitor) throws JavaModelException {
+	public void checkExternalArchiveChanges(IJavaElement[] elementsToRefresh, IProgressMonitor monitor) throws JavaModelException {
 		try {
-			for (int i = 0, length = refreshedElements.length; i < length; i++) {
-				this.addForRefresh(refreshedElements[i]);
+			for (int i = 0, length = elementsToRefresh.length; i < length; i++) {
+				this.addForRefresh(elementsToRefresh[i]);
 			}
 			boolean hasDelta = this.createExternalArchiveDelta(monitor);
 			if (monitor != null && monitor.isCanceled()) return; 
@@ -279,7 +305,7 @@
 						true); // generateMarkerOnError
 				}		
 				if (this.currentDelta != null) { // if delta has not been fired while creating markers
-					this.manager.fire(this.currentDelta, JavaModelManager.DEFAULT_CHANGE_EVENT);
+					this.fire(this.currentDelta, DEFAULT_CHANGE_EVENT);
 				}
 			}
 		} finally {
@@ -288,284 +314,132 @@
 		}
 	}
 	/*
-	 * Check if external archives have changed and create the corresponding deltas.
-	 * Returns whether at least on delta was created.
-	 */
-	public boolean createExternalArchiveDelta(IProgressMonitor monitor) throws JavaModelException {
-		
-		if (this.refreshedElements == null) return false;
-			
-		HashMap externalArchivesStatus = new HashMap();
-		boolean hasDelta = false;
-		
-		// find JARs to refresh
-		HashSet archivePathsToRefresh = new HashSet();
-		try {
-			Iterator iterator = this.refreshedElements.iterator();
-			while (iterator.hasNext()) {
-				IJavaElement element = (IJavaElement)iterator.next();
-				switch(element.getElementType()){
-					case IJavaElement.PACKAGE_FRAGMENT_ROOT :
-						archivePathsToRefresh.add(element.getPath());
-						break;
-					case IJavaElement.JAVA_PROJECT :
-						IJavaProject project = (IJavaProject) element;
-						if (!JavaProject.hasJavaNature(project.getProject())) {
-							// project is not accessible or has lost its Java nature
-							break;
-						}
-						IClasspathEntry[] classpath = project.getResolvedClasspath(true);
-						for (int j = 0, cpLength = classpath.length; j < cpLength; j++){
-							if (classpath[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
-								archivePathsToRefresh.add(classpath[j].getPath());
-							}
-						}
-						break;
-					case IJavaElement.JAVA_MODEL :
-						IJavaProject[] projects = manager.getJavaModel().getOldJavaProjectsList();
-						for (int j = 0, projectsLength = projects.length; j < projectsLength; j++){
-							project = projects[j];
-							if (!JavaProject.hasJavaNature(project.getProject())) {
-								// project is not accessible or has lost its Java nature
-								continue;
-							}
-							classpath = project.getResolvedClasspath(true);
-							for (int k = 0, cpLength = classpath.length; k < cpLength; k++){
-								if (classpath[k].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
-									archivePathsToRefresh.add(classpath[k].getPath());
-								}
-							}
-						}
-						break;
-				}
-			}
-		} finally {
-			this.refreshedElements = null;
-		}
-		
-		// perform refresh
-		IJavaProject[] projects = manager.getJavaModel().getOldJavaProjectsList();
-		IWorkspaceRoot wksRoot = ResourcesPlugin.getWorkspace().getRoot();
-		for (int i = 0, length = projects.length; i < length; i++) {
-			
-			if (monitor != null && monitor.isCanceled()) break; 
-			
-			IJavaProject project = projects[i];
-			if (!JavaProject.hasJavaNature(project.getProject())) {
-				// project is not accessible or has lost its Java nature
-				continue;
-			}
-			IClasspathEntry[] entries = project.getResolvedClasspath(true);
-			for (int j = 0; j < entries.length; j++){
-				if (entries[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
-					
-					IPath entryPath = entries[j].getPath();
-					
-					if (!archivePathsToRefresh.contains(entryPath)) continue; // not supposed to be refreshed
-					
-					String status = (String)externalArchivesStatus.get(entryPath); 
-					if (status == null){
-						
-						// compute shared status
-						Object targetLibrary = JavaModel.getTarget(wksRoot, entryPath, true);
-		
-						if (targetLibrary == null){ // missing JAR
-							if (this.externalTimeStamps.containsKey(entryPath)){
-								this.externalTimeStamps.remove(entryPath);
-								externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
-								// the jar was physically removed: remove the index
-								indexManager.removeIndex(entryPath);
-							}
-		
-						} else if (targetLibrary instanceof File){ // external JAR
-		
-							File externalFile = (File)targetLibrary;
-							
-							// check timestamp to figure if JAR has changed in some way
-							Long oldTimestamp =(Long) this.externalTimeStamps.get(entryPath);
-							long newTimeStamp = getTimeStamp(externalFile);
-							if (oldTimestamp != null){
-		
-								if (newTimeStamp == 0){ // file doesn't exist
-									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
-									this.externalTimeStamps.remove(entryPath);
-									// remove the index
-									indexManager.removeIndex(entryPath);
-		
-								} else if (oldTimestamp.longValue() != newTimeStamp){
-									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_CHANGED);
-									this.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
-									// first remove the index so that it is forced to be re-indexed
-									indexManager.removeIndex(entryPath);
-									// then index the jar
-									indexManager.indexLibrary(entryPath, project.getProject());
-								} else {
-									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
-								}
-							} else {
-								if (newTimeStamp == 0){ // jar still doesn't exist
-									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
-								} else {
-									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_ADDED);
-									this.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
-									// index the new jar
-									indexManager.indexLibrary(entryPath, project.getProject());
-								}
-							}
-						} else { // internal JAR
-							externalArchivesStatus.put(entryPath, INTERNAL_JAR_IGNORE);
-						}
-					}
-					// according to computed status, generate a delta
-					status = (String)externalArchivesStatus.get(entryPath); 
-					if (status != null){
-						if (status == EXTERNAL_JAR_ADDED){
-							PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
-							if (VERBOSE){
-								System.out.println("- External JAR ADDED, affecting root: "+root.getElementName()); //$NON-NLS-1$
-							} 
-							elementAdded(root, null, null);
-							hasDelta = true;
-						} else if (status == EXTERNAL_JAR_CHANGED) {
-							PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
-							if (VERBOSE){
-								System.out.println("- External JAR CHANGED, affecting root: "+root.getElementName()); //$NON-NLS-1$
-							}
-							// reset the corresponding project built state, since the builder would miss this change
-							this.manager.setLastBuiltState(project.getProject(), null /*no state*/);
-							contentChanged(root, null);
-							hasDelta = true;
-						} else if (status == EXTERNAL_JAR_REMOVED) {
-							PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
-							if (VERBOSE){
-								System.out.println("- External JAR REMOVED, affecting root: "+root.getElementName()); //$NON-NLS-1$
-							}
-							elementRemoved(root, null, null);
-							hasDelta = true;
-						}
-					}
-				}
-			}
-		}
-		return hasDelta;
-	}
-	JavaElementDelta currentDelta() {
-		if (this.currentDelta == null) {
-			this.currentDelta = new JavaElementDelta(this.manager.getJavaModel());
-		}
-		return this.currentDelta;
-	}
-	
-	/*
 	 * Process the given delta and look for projects being added, opened, closed or
 	 * with a java nature being added or removed.
 	 * Note that projects being deleted are checked in deleting(IProject).
 	 * In all cases, add the project's dependents to the list of projects to update
 	 * so that the classpath related markers can be updated.
 	 */
-	public void checkProjectsBeingAddedOrRemoved(IResourceDelta delta) {
+	private void checkProjectsBeingAddedOrRemoved(IResourceDelta delta) {
 		IResource resource = delta.getResource();
+		boolean processChildren = false;
+
 		switch (resource.getType()) {
 			case IResource.ROOT :
 				// workaround for bug 15168 circular errors not reported 
-				if (this.manager.javaProjectsCache == null) {
+				if (this.state.modelProjectsCache == null) {
 					try {
-						this.manager.javaProjectsCache = this.manager.getJavaModel().getJavaProjects();
+						this.state.modelProjectsCache = this.manager.getJavaModel().getJavaProjects();
 					} catch (JavaModelException e) {
+						// java model doesn't exist: never happens
 					}
 				}
-				
-				IResourceDelta[] children = delta.getAffectedChildren();
-				for (int i = 0, length = children.length; i < length; i++) {
-					this.checkProjectsBeingAddedOrRemoved(children[i]);
-				}
+				processChildren = true;
 				break;
 			case IResource.PROJECT :
 				// NB: No need to check project's nature as if the project is not a java project:
 				//     - if the project is added or changed this is a noop for projectsBeingDeleted
 				//     - if the project is closed, it has already lost its java nature
-				int deltaKind = delta.getKind();
-				if (deltaKind == IResourceDelta.ADDED) {
-					// remember project and its dependents
-					IProject project = (IProject)resource;
-					this.addToProjectsToUpdateWithDependents(project);
-					
-					// workaround for bug 15168 circular errors not reported 
-					if (JavaProject.hasJavaNature(project)) {
-						this.addToParentInfo((JavaProject)JavaCore.create(project));
-					}
-
-				} else if (deltaKind == IResourceDelta.CHANGED) {
-					IProject project = (IProject)resource;
-					if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
-						// project opened or closed: remember  project and its dependents
-						this.addToProjectsToUpdateWithDependents(project);
+				switch (delta.getKind()) {
+					case IResourceDelta.ADDED :
+						// remember project and its dependents
+						IProject project = (IProject)resource;
+						JavaProject javaProject = (JavaProject)JavaCore.create(project);
+						this.addToRootsToRefreshWithDependents(javaProject);
+						// workaround for bug 15168 circular errors not reported 
+						if (JavaProject.hasJavaNature(project)) {
+							this.addToParentInfo(javaProject);
+						}
+						this.state.rootsAreStale = true; 
+						break;
 						
-						// workaround for bug 15168 circular errors not reported 
-						if (project.isOpen()) {
-							if (JavaProject.hasJavaNature(project)) {
-								this.addToParentInfo((JavaProject)JavaCore.create(project));
-							}
-						} else {
-							JavaProject javaProject = (JavaProject)this.manager.getJavaModel().findJavaProject(project);
-							if (javaProject != null) {
-								try {
-									javaProject.close();
-								} catch (JavaModelException e) {
-								}
-								this.removeFromParentInfo(javaProject);
-							}
-						}
-					} else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
-						boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(project) != null;
-						boolean isJavaProject = JavaProject.hasJavaNature(project);
-						if (wasJavaProject != isJavaProject) {
-							// java nature added or removed: remember  project and its dependents
-							this.addToProjectsToUpdateWithDependents(project);
-
-							// workaround for bug 15168 circular errors not reported 
-							if (isJavaProject) {
-								this.addToParentInfo((JavaProject)JavaCore.create(project));
-							} else {
-								JavaProject javaProject = (JavaProject)JavaCore.create(project);
+					case IResourceDelta.CHANGED : 
+							project = (IProject)resource;
+							if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
+								// project opened or closed: remember  project and its dependents
+								javaProject = (JavaProject)JavaCore.create(project);
+								this.addToRootsToRefreshWithDependents(javaProject);
 								
-								// flush classpath markers
-								javaProject.
-									flushClasspathProblemMarkers(
-										true, // flush cycle markers
-										true  //flush classpath format markers
-									);
-									
-								// remove problems and tasks created  by the builder
-								JavaBuilder.removeProblemsAndTasksFor(project);
-
-								// close project
-								try {
-									javaProject.close();
-								} catch (JavaModelException e) {
+								// workaround for bug 15168 circular errors not reported 
+								if (project.isOpen()) {
+									if (JavaProject.hasJavaNature(project)) {
+										this.addToParentInfo(javaProject);
+									}
+								} else {
+									try {
+										javaProject.close();
+									} catch (JavaModelException e) {
+										// java project doesn't exist: ignore
+									}
+									this.removeFromParentInfo(javaProject);
+									this.manager.removePerProjectInfo(javaProject);
 								}
-								this.removeFromParentInfo(javaProject);
-							}
-						} else {
-							// in case the project was removed then added then changed (see bug 19799)
-							if (JavaProject.hasJavaNature(project)) { // need nature check - 18698
-								this.addToParentInfo((JavaProject)JavaCore.create(project));
-							}
-						}
-					} else {
-						// workaround for bug 15168 circular errors not reported 
-						// in case the project was removed then added then changed
-						if (JavaProject.hasJavaNature(project)) { // need nature check - 18698
-							this.addToParentInfo((JavaProject)JavaCore.create(project));
-						}						
-					}					
+							} else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
+								boolean wasJavaProject = this.manager.getJavaModel().findJavaProject(project) != null;
+								boolean isJavaProject = JavaProject.hasJavaNature(project);
+								if (wasJavaProject != isJavaProject) { 
+									// java nature added or removed: remember  project and its dependents
+									javaProject = (JavaProject)JavaCore.create(project);
+									this.addToRootsToRefreshWithDependents(javaProject);
+		
+									// workaround for bug 15168 circular errors not reported 
+									if (isJavaProject) {
+										this.addToParentInfo(javaProject);
+									} else {
+										// remove classpath cache so that initializeRoots() will not consider the project has a classpath
+										this.manager.removePerProjectInfo((JavaProject)JavaCore.create(project));
+										// close project
+										try {
+											javaProject.close();
+										} catch (JavaModelException e) {
+											// java project doesn't exist: ignore
+										}
+										this.removeFromParentInfo(javaProject);
+									}
+									this.state.rootsAreStale = true;
+								} else {
+									// in case the project was removed then added then changed (see bug 19799)
+									if (isJavaProject) { // need nature check - 18698
+										this.addToParentInfo((JavaProject)JavaCore.create(project));
+										processChildren = true;
+									}
+								}
+							} else {
+								// workaround for bug 15168 circular errors not reported 
+								// in case the project was removed then added then changed
+								if (JavaProject.hasJavaNature(project)) { // need nature check - 18698
+									this.addToParentInfo((JavaProject)JavaCore.create(project));
+									processChildren = true;
+								}						
+							}		
+							break;
+
+					case IResourceDelta.REMOVED : 
+							// remove classpath cache so that initializeRoots() will not consider the project has a classpath
+							this.manager.removePerProjectInfo((JavaProject)JavaCore.create(resource));
+							this.state.rootsAreStale = true;
+							break;
 				}
 				break;
+			case IResource.FILE :
+				IFile file = (IFile) resource;
+				/* classpath file change */
+				if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
+					reconcileClasspathFileUpdate(delta, (JavaProject)JavaCore.create(file.getProject()));
+					this.state.rootsAreStale = true;
+				}
+				break;
+				
+		}
+		if (processChildren) {
+			IResourceDelta[] children = delta.getAffectedChildren();
+			for (int i = 0; i < children.length; i++) {
+				checkProjectsBeingAddedOrRemoved(children[i]);
+			}
 		}
 	}
-
 	private void checkSourceAttachmentChange(IResourceDelta delta, IResource res) {
-		IPath rootPath = (IPath)this.sourceAttachments.get(res.getFullPath());
+		IPath rootPath = (IPath)this.state.sourceAttachments.get(res.getFullPath());
 		if (rootPath != null) {
 			RootInfo rootInfo = this.rootInfo(rootPath, delta.getKind());
 			if (rootInfo != null) {
@@ -578,6 +452,7 @@
 						root.close();
 					}
 				} catch (JavaModelException e) {
+					// root doesn't exist: ignore
 				}
 				if (root == null) return;
 				switch (delta.getKind()) {
@@ -595,19 +470,17 @@
 			} 
 		}
 	}
-
-	/**
+	/*
 	 * Closes the given element, which removes it from the cache of open elements.
 	 */
-	protected static void close(Openable element) {
-
+	private void close(Openable element) {
 		try {
 			element.close();
 		} catch (JavaModelException e) {
 			// do nothing
 		}
 	}
-	/**
+	/*
 	 * Generic processing for elements with changed contents:<ul>
 	 * <li>The element is closed such that any subsequent accesses will re-open
 	 * the element reflecting its new structure.
@@ -615,21 +488,23 @@
 	 * </ul>
 	 * Delta argument could be null if processing an external JAR change
 	 */
-	protected void contentChanged(Openable element, IResourceDelta delta) {
+	private void contentChanged(Openable element) {
 
-		close(element);
-		int flags = IJavaElementDelta.F_CONTENT;
-		if (element instanceof JarPackageFragmentRoot){
-			flags |= IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED;
+		// filter out changes to primary compilation unit in working copy mode
+		if (!isPrimaryWorkingCopy(element, element.getElementType())) {
+			close(element);
+			int flags = IJavaElementDelta.F_CONTENT;
+			if (element instanceof JarPackageFragmentRoot){
+				flags |= IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED;
+			}
+			currentDelta().changed(element, flags);
 		}
-		currentDelta().changed(element, flags);
 	}
-	
-	/**
+	/*
 	 * Creates the openables corresponding to this resource.
 	 * Returns null if none was found.
 	 */
-	protected Openable createElement(IResource resource, int elementType, RootInfo rootInfo) {
+	private Openable createElement(IResource resource, int elementType, RootInfo rootInfo) {
 		if (resource == null) return null;
 		
 		IPath path = resource.getFullPath();
@@ -659,7 +534,7 @@
 					} else {
 						// java project may have been been closed or removed (look for
 						// element amongst old java project s list).
-						element =  (Openable) manager.getJavaModel().findJavaProject(proj);
+						element =  (Openable) this.manager.getJavaModel().findJavaProject(proj);
 					}
 				}
 				break;
@@ -707,7 +582,7 @@
 							}
 							break;
 						case IJavaElement.PACKAGE_FRAGMENT:
-							Openable pkg = (Openable)this.currentElement;
+							Openable pkg = this.currentElement;
 							if (pkg.getPath().equals(path.removeLastSegments(1))) {
 								pkgFragment = (IPackageFragment)pkg;
 							} // else case of package x which is a prefix of x.y
@@ -742,15 +617,210 @@
 			return this.currentElement;
 		}
 	}
-	/**
+	/*
+	 * Check if external archives have changed and create the corresponding deltas.
+	 * Returns whether at least on delta was created.
+	 */
+	private boolean createExternalArchiveDelta(IProgressMonitor monitor) {
+		
+		if (this.refreshedElements == null) return false;
+			
+		HashMap externalArchivesStatus = new HashMap();
+		boolean hasDelta = false;
+		
+		// find JARs to refresh
+		HashSet archivePathsToRefresh = new HashSet();
+		try {
+			Iterator iterator = this.refreshedElements.iterator();
+			while (iterator.hasNext()) {
+				IJavaElement element = (IJavaElement)iterator.next();
+				switch(element.getElementType()){
+					case IJavaElement.PACKAGE_FRAGMENT_ROOT :
+						archivePathsToRefresh.add(element.getPath());
+						break;
+					case IJavaElement.JAVA_PROJECT :
+						IJavaProject project = (IJavaProject) element;
+						if (!JavaProject.hasJavaNature(project.getProject())) {
+							// project is not accessible or has lost its Java nature
+							break;
+						}
+						IClasspathEntry[] classpath;
+						try {
+							classpath = project.getResolvedClasspath(true);
+							for (int j = 0, cpLength = classpath.length; j < cpLength; j++){
+								if (classpath[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
+									archivePathsToRefresh.add(classpath[j].getPath());
+								}
+							}
+						} catch (JavaModelException e) {
+							// project doesn't exist -> ignore
+						}
+						break;
+					case IJavaElement.JAVA_MODEL :
+						IJavaProject[] projects;
+						try {
+							projects = this.manager.getJavaModel().getOldJavaProjectsList();
+						} catch (JavaModelException e1) {
+							// cannot retrieve old projects list -> ignore
+							continue;
+						}
+						for (int j = 0, projectsLength = projects.length; j < projectsLength; j++){
+							project = projects[j];
+							if (!JavaProject.hasJavaNature(project.getProject())) {
+								// project is not accessible or has lost its Java nature
+								continue;
+							}
+							try {
+								classpath = project.getResolvedClasspath(true);
+							} catch (JavaModelException e2) {
+								// project doesn't exist -> ignore
+								continue;
+							}
+							for (int k = 0, cpLength = classpath.length; k < cpLength; k++){
+								if (classpath[k].getEntryKind() == IClasspathEntry.CPE_LIBRARY){
+									archivePathsToRefresh.add(classpath[k].getPath());
+								}
+							}
+						}
+						break;
+				}
+			}
+		} finally {
+			this.refreshedElements = null;
+		}
+		
+		// perform refresh
+		IJavaProject[] projects;
+		try {
+			projects = this.manager.getJavaModel().getOldJavaProjectsList();
+		} catch (JavaModelException e) {
+			// cannot retrieve old projects list -> give up
+			return false;
+		}
+		IWorkspaceRoot wksRoot = ResourcesPlugin.getWorkspace().getRoot();
+		for (int i = 0, length = projects.length; i < length; i++) {
+			
+			if (monitor != null && monitor.isCanceled()) break; 
+			
+			IJavaProject project = projects[i];
+			if (!JavaProject.hasJavaNature(project.getProject())) {
+				// project is not accessible or has lost its Java nature
+				continue;
+			}
+			IClasspathEntry[] entries;
+			try {
+				entries = project.getResolvedClasspath(true);
+			} catch (JavaModelException e1) {
+				// project does not exist -> ignore
+				continue;
+			}
+			for (int j = 0; j < entries.length; j++){
+				if (entries[j].getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
+					
+					IPath entryPath = entries[j].getPath();
+					
+					if (!archivePathsToRefresh.contains(entryPath)) continue; // not supposed to be refreshed
+					
+					String status = (String)externalArchivesStatus.get(entryPath); 
+					if (status == null){
+						
+						// compute shared status
+						Object targetLibrary = JavaModel.getTarget(wksRoot, entryPath, true);
+		
+						if (targetLibrary == null){ // missing JAR
+							if (this.state.externalTimeStamps.remove(entryPath) != null){
+								externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
+								// the jar was physically removed: remove the index
+								this.manager.indexManager.removeIndex(entryPath);
+							}
+		
+						} else if (targetLibrary instanceof File){ // external JAR
+		
+							File externalFile = (File)targetLibrary;
+							
+							// check timestamp to figure if JAR has changed in some way
+							Long oldTimestamp =(Long) this.state.externalTimeStamps.get(entryPath);
+							long newTimeStamp = getTimeStamp(externalFile);
+							if (oldTimestamp != null){
+		
+								if (newTimeStamp == 0){ // file doesn't exist
+									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_REMOVED);
+									this.state.externalTimeStamps.remove(entryPath);
+									// remove the index
+									this.manager.indexManager.removeIndex(entryPath);
+		
+								} else if (oldTimestamp.longValue() != newTimeStamp){
+									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_CHANGED);
+									this.state.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
+									// first remove the index so that it is forced to be re-indexed
+									this.manager.indexManager.removeIndex(entryPath);
+									// then index the jar
+									this.manager.indexManager.indexLibrary(entryPath, project.getProject());
+								} else {
+									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
+								}
+							} else {
+								if (newTimeStamp == 0){ // jar still doesn't exist
+									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_UNCHANGED);
+								} else {
+									externalArchivesStatus.put(entryPath, EXTERNAL_JAR_ADDED);
+									this.state.externalTimeStamps.put(entryPath, new Long(newTimeStamp));
+									// index the new jar
+									this.manager.indexManager.indexLibrary(entryPath, project.getProject());
+								}
+							}
+						} else { // internal JAR
+							externalArchivesStatus.put(entryPath, INTERNAL_JAR_IGNORE);
+						}
+					}
+					// according to computed status, generate a delta
+					status = (String)externalArchivesStatus.get(entryPath); 
+					if (status != null){
+						if (status == EXTERNAL_JAR_ADDED){
+							PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
+							if (VERBOSE){
+								System.out.println("- External JAR ADDED, affecting root: "+root.getElementName()); //$NON-NLS-1$
+							} 
+							elementAdded(root, null, null);
+							hasDelta = true;
+						} else if (status == EXTERNAL_JAR_CHANGED) {
+							PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
+							if (VERBOSE){
+								System.out.println("- External JAR CHANGED, affecting root: "+root.getElementName()); //$NON-NLS-1$
+							}
+							// reset the corresponding project built state, since the builder would miss this change
+							this.manager.setLastBuiltState(project.getProject(), null /*no state*/);
+							contentChanged(root);
+							hasDelta = true;
+						} else if (status == EXTERNAL_JAR_REMOVED) {
+							PackageFragmentRoot root = (PackageFragmentRoot)project.getPackageFragmentRoot(entryPath.toString());
+							if (VERBOSE){
+								System.out.println("- External JAR REMOVED, affecting root: "+root.getElementName()); //$NON-NLS-1$
+							}
+							elementRemoved(root, null, null);
+							hasDelta = true;
+						}
+					}
+				}
+			}
+		}
+		return hasDelta;
+	}
+	private JavaElementDelta currentDelta() {
+		if (this.currentDelta == null) {
+			this.currentDelta = new JavaElementDelta(this.manager.getJavaModel());
+		}
+		return this.currentDelta;
+	}
+	/*
 	 * Note that the project is about to be deleted.
 	 */
-	public void deleting(IProject project) {
+	private void deleting(IProject project) {
 		
 		try {
 			// discard indexing jobs that belong to this project so that the project can be 
 			// deleted without interferences from the index manager
-			this.indexManager.discardJobs(project.getName());
+			this.manager.indexManager.discardJobs(project.getName());
 
 			JavaProject javaProject = (JavaProject)JavaCore.create(project);
 			
@@ -771,20 +841,17 @@
 			
 			javaProject.close();
 
-			// workaround for bug 15168 circular errors not reported  
-			if (this.manager.javaProjectsCache == null) {
-				this.manager.javaProjectsCache = this.manager.getJavaModel().getJavaProjects();
+			// workaround for bug 15168 circular errors not reported
+			if (this.state.modelProjectsCache == null) {
+				this.state.modelProjectsCache = this.manager.getJavaModel().getJavaProjects();
 			}
 			this.removeFromParentInfo(javaProject);
 
 		} catch (JavaModelException e) {
+			// java project doesn't exist: ignore
 		}
-		
-		this.addDependentProjects(project.getFullPath(), this.projectsToUpdate);
 	}
-
-
-	/**
+	/*
 	 * Processing for an element that has been added:<ul>
 	 * <li>If the element is a project, do nothing, and do not process
 	 * children, as when a project is created it does not yet have any
@@ -794,7 +861,7 @@
 	 * </ul>
 	 * Delta argument could be null if processing an external JAR change
 	 */
-	protected void elementAdded(Openable element, IResourceDelta delta, RootInfo rootInfo) {
+	private void elementAdded(Openable element, IResourceDelta delta, RootInfo rootInfo) {
 		int elementType = element.getElementType();
 		
 		if (elementType == IJavaElement.JAVA_PROJECT) {
@@ -808,25 +875,36 @@
 				} else {
 					currentDelta().added(element);
 				}
-				this.projectsToUpdate.add(element);
-				this.updateRoots(element.getPath(), delta);
-				this.projectsForDependentNamelookupRefresh.add((JavaProject) element);
+				this.state.updateRoots(element.getPath(), delta, this);
+				
+				// refresh pkg fragment roots and namelookup of the project (and its dependents)
+				this.rootsToRefresh.add(element);
+				this.namelookupsToRefresh.add(element);
 			}
 		} else {			
-			addToParentInfo(element);
+			if (delta == null || (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) {
+				// regular element addition
+				if (!isPrimaryWorkingCopy(element, elementType)) { // filter out changes to primary compilation unit in working copy mode
+					addToParentInfo(element);
+					
+					// Force the element to be closed as it might have been opened 
+					// before the resource modification came in and it might have a new child
+					// For example, in an IWorkspaceRunnable:
+					// 1. create a package fragment p using a java model operation
+					// 2. open package p
+					// 3. add file X.java in folder p
+					// When the resource delta comes in, only the addition of p is notified, 
+					// but the package p is already opened, thus its children are not recomputed
+					// and it appears empty.
+					close(element);
 			
-			// Force the element to be closed as it might have been opened 
-			// before the resource modification came in and it might have a new child
-			// For example, in an IWorkspaceRunnable:
-			// 1. create a package fragment p using a java model operation
-			// 2. open package p
-			// 3. add file X.java in folder p
-			// When the resource delta comes in, only the addition of p is notified, 
-			// but the package p is already opened, thus its children are not recomputed
-			// and it appears empty.
-			close(element);
+					currentDelta().added(element);
+				}
+			} else {
+				// element is moved
+				addToParentInfo(element);
+				close(element);
 			
-			if (delta != null && (delta.getFlags() & IResourceDelta.MOVED_FROM) != 0) {
 				IPath movedFromPath = delta.getMovedFromPath();
 				IResource res = delta.getResource();
 				IResource movedFromRes;
@@ -859,26 +937,23 @@
 				} else {
 					currentDelta().movedTo(element, movedFromElement);
 				}
-			} else {
-				currentDelta().added(element);
 			}
 			
 			switch (elementType) {
 				case IJavaElement.PACKAGE_FRAGMENT_ROOT :
 					// when a root is added, and is on the classpath, the project must be updated
 					JavaProject project = (JavaProject) element.getJavaProject();
-					this.projectsToUpdate.add(project);
-					this.projectsForDependentNamelookupRefresh.add(project);
+
+					// refresh pkg fragment roots and namelookup of the project (and its dependents)
+					this.rootsToRefresh.add(project);
+					this.namelookupsToRefresh.add(project);
 					
 					break;
 				case IJavaElement.PACKAGE_FRAGMENT :
-					// get rid of namelookup since it holds onto obsolete cached info 
+					//refresh namelookup since it holds onto obsolete cached info 
 					project = (JavaProject) element.getJavaProject();
-					try {
-						project.getJavaProjectElementInfo().setNameLookup(null);
-						this.projectsForDependentNamelookupRefresh.add(project);						
-					} catch (JavaModelException e) {
-					}
+					this.namelookupsToRefresh.add(project);						
+
 					// add subpackages
 					if (delta != null){
 						PackageFragmentRoot root = element.getPackageFragmentRoot();
@@ -905,8 +980,7 @@
 			}
 		}
 	}
-
-	/**
+	/*
 	 * Generic processing for a removed element:<ul>
 	 * <li>Close the element, removing its structure from the cache
 	 * <li>Remove the element from its parent's cache of children
@@ -914,14 +988,20 @@
 	 * </ul>
 	 * Delta argument could be null if processing an external JAR change
 	 */
-	protected void elementRemoved(Openable element, IResourceDelta delta, RootInfo rootInfo) {
+	private void elementRemoved(Openable element, IResourceDelta delta, RootInfo rootInfo) {
 		
-		if (element.isOpen()) {
-			close(element);
-		}
-		removeFromParentInfo(element);
 		int elementType = element.getElementType();
-		if (delta != null && (delta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
+		if (delta == null || (delta.getFlags() & IResourceDelta.MOVED_TO) == 0) {
+			// regular element removal
+			if (!isPrimaryWorkingCopy(element, elementType)) { // filter out changes to primary compilation unit in working copy mode
+				close(element);
+				removeFromParentInfo(element);
+				currentDelta().removed(element);
+			}
+		} else {
+			// element is moved
+			close(element);
+			removeFromParentInfo(element);
 			IPath movedToPath = delta.getMovedToPath();
 			IResource res = delta.getResource();
 			IResource movedToRes;
@@ -962,33 +1042,33 @@
 			} else {
 				currentDelta().movedFrom(element, movedToElement);
 			}
-		} else {
-			currentDelta().removed(element);
 		}
 
 		switch (elementType) {
 			case IJavaElement.JAVA_MODEL :
-				this.indexManager.reset();
+				this.manager.indexManager.reset();
 				break;
 			case IJavaElement.JAVA_PROJECT :
-				this.manager.removePerProjectInfo(
-					(JavaProject) element);
-				this.updateRoots(element.getPath(), delta);
-				this.projectsForDependentNamelookupRefresh.add((JavaProject) element);
+				this.state.updateRoots(element.getPath(), delta, this);
+
+				// refresh pkg fragment roots and namelookup of the project (and its dependents)
+				this.rootsToRefresh.add(element);
+				this.namelookupsToRefresh.add(element);
+
 				break;
 			case IJavaElement.PACKAGE_FRAGMENT_ROOT :
 				JavaProject project = (JavaProject) element.getJavaProject();
-				this.projectsToUpdate.add(project);
-				this.projectsForDependentNamelookupRefresh.add(project);				
+
+				// refresh pkg fragment roots and namelookup of the project (and its dependents)
+				this.rootsToRefresh.add(project);
+				this.namelookupsToRefresh.add(project);				
+
 				break;
 			case IJavaElement.PACKAGE_FRAGMENT :
-				//1G1TW2T - get rid of namelookup since it holds onto obsolete cached info 
+				//refresh namelookup since it holds onto obsolete cached info 
 				project = (JavaProject) element.getJavaProject();
-				try {
-					project.getJavaProjectElementInfo().setNameLookup(null); 
-					this.projectsForDependentNamelookupRefresh.add(project);
-				} catch (JavaModelException e) { 
-				}
+				this.namelookupsToRefresh.add(project);
+
 				// remove subpackages
 				if (delta != null){
 					PackageFragmentRoot root = element.getPackageFragmentRoot();
@@ -1014,7 +1094,6 @@
 				break;
 		}
 	}
-
 	/*
 	 * Returns the type of the java element the given delta matches to.
 	 * Returns NON_JAVA_RESOURCE if unknown (e.g. a non-java resource or excluded .java file)
@@ -1065,98 +1144,122 @@
 				return NON_JAVA_RESOURCE;
 		}
 	}
-
-	/**
-	 * Answer a combination of the lastModified stamp and the size.
-	 * Used for detecting external JAR changes
+	/*
+	 * Flushes all deltas without firing them.
 	 */
-	public static long getTimeStamp(File file) {
-		return file.lastModified() + file.length();
+	public void flush() {
+		this.javaModelDeltas = new ArrayList();
 	}
-
-	public void initializeRoots() {
-		// remember roots infos as old roots infos
-		this.oldRoots = this.roots == null ? new HashMap() : this.roots;
-		this.oldOtherRoots = this.otherRoots == null ? new HashMap() : this.otherRoots;
-		
-		// recompute root infos only if necessary
-		if (!rootsAreStale) return;
-
-		this.roots = new HashMap();
-		this.otherRoots = new HashMap();
-		this.sourceAttachments = new HashMap();
-		
-		IJavaModel model = this.manager.getJavaModel();
-		IJavaProject[] projects;
-		try {
-			projects = model.getJavaProjects();
-		} catch (JavaModelException e) {
-			// nothing can be done
-			return;
+	/*
+	 * Finds the root info this path is included in.
+	 * Returns null if not found.
+	 */
+	private RootInfo enclosingRootInfo(IPath path, int kind) {
+		while (path != null && path.segmentCount() > 0) {
+			RootInfo rootInfo =  this.rootInfo(path, kind);
+			if (rootInfo != null) return rootInfo;
+			path = path.removeLastSegments(1);
 		}
-		for (int i = 0, length = projects.length; i < length; i++) {
-			IJavaProject project = projects[i];
-			IClasspathEntry[] classpath;
-			try {
-				classpath = project.getResolvedClasspath(true);
-			} catch (JavaModelException e) {
-				// continue with next project
-				continue;
-			}
-			for (int j= 0, classpathLength = classpath.length; j < classpathLength; j++) {
-				IClasspathEntry entry = classpath[j];
-				if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue;
-				
-				// root path
-				IPath path = entry.getPath();
-				if (this.roots.get(path) == null) {
-					this.roots.put(path, new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
-				} else {
-					ArrayList rootList = (ArrayList)this.otherRoots.get(path);
-					if (rootList == null) {
-						rootList = new ArrayList();
-						this.otherRoots.put(path, rootList);
-					}
-					rootList.add(new RootInfo(project, path, ((ClasspathEntry)entry).fullExclusionPatternChars()));
-				}
-				
-				// source attachment path
-				if (entry.getEntryKind() != IClasspathEntry.CPE_LIBRARY) continue;
-				QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + path.toOSString()); //$NON-NLS-1$;
-				String propertyString = null;
-				try {
-					propertyString = ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName);
-				} catch (CoreException e) {
-					continue;
-				}
-				IPath sourceAttachmentPath;
-				if (propertyString != null) {
-					int index= propertyString.lastIndexOf(JarPackageFragmentRoot.ATTACHMENT_PROPERTY_DELIMITER);
-					sourceAttachmentPath = (index < 0) ?  new Path(propertyString) : new Path(propertyString.substring(0, index));
-				} else {
-					sourceAttachmentPath = entry.getSourceAttachmentPath();
-				}
-				if (sourceAttachmentPath != null) {
-					this.sourceAttachments.put(sourceAttachmentPath, path);
-				}
+		return null;
+	}
+	/*
+	 * 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 (VERBOSE && eventType == DEFAULT_CHANGE_EVENT) {
+			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) {
+			Iterator scopes = this.manager.searchScopes.keySet().iterator();
+			while (scopes.hasNext()) {
+				AbstractSearchScope scope = (AbstractSearchScope)scopes.next();
+				scope.processDelta(deltaToNotify);
 			}
 		}
-		this.rootsAreStale = false;
+			
+		// 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.state.elementChangedListeners;
+		int[] listenerMask = this.state.elementChangedListenerMasks;
+		int listenerCount = this.state.elementChangedListenerCount;
+
+		switch (eventType) {
+			case DEFAULT_CHANGE_EVENT:
+				firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount);
+				fireReconcileDelta(listeners, listenerMask, listenerCount);
+				break;
+			case ElementChangedEvent.POST_CHANGE:
+				firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount);
+				fireReconcileDelta(listeners, listenerMask, listenerCount);
+				break;
+		}
 	}
 
+	private void firePostChangeDelta(
+		IJavaElementDelta deltaToNotify,
+		IElementChangedListener[] listeners,
+		int[] listenerMask,
+		int listenerCount) {
+			
+		// post change deltas
+		if (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 (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);
+		} 
+	}
 	/*
 	 * Returns whether a given delta contains some information relevant to the JavaModel,
 	 * in particular it will not consider SYNC or MARKER only deltas.
 	 */
-	public boolean isAffectedBy(IResourceDelta rootDelta){
+	private boolean isAffectedBy(IResourceDelta rootDelta){
 		//if (rootDelta == null) System.out.println("NULL DELTA");
 		//long start = System.currentTimeMillis();
 		if (rootDelta != null) {
 			// use local exception to quickly escape from delta traversal
-			class FoundRelevantDeltaException extends RuntimeException {}
+			class FoundRelevantDeltaException extends RuntimeException {
+				// only the class name is used (to differenciate from other RuntimeExceptions)
+			}
 			try {
 				rootDelta.accept(new IResourceDeltaVisitor() {
-					public boolean visit(IResourceDelta delta) throws CoreException {
+					public boolean visit(IResourceDelta delta) /* throws CoreException */ {
 						switch (delta.getKind()){
 							case IResourceDelta.ADDED :
 							case IResourceDelta.REMOVED :
@@ -1180,7 +1283,16 @@
 		//System.out.println("IGNORE SYNC DELTA took: "+ (System.currentTimeMillis() - start));
 		return false;
 	}
-	
+	/*
+	 * Returns whether the given element is a primary compilation unit in working copy mode.
+	 */
+	private boolean isPrimaryWorkingCopy(IJavaElement element, int elementType) {
+		if (elementType == IJavaElement.COMPILATION_UNIT) {
+			CompilationUnit cu = (CompilationUnit)element;
+			return cu.isPrimary() && cu.isWorkingCopy();
+		}
+		return false;
+	}
 	/*
 	 * Returns whether the given resource is in one of the given output folders and if
 	 * it is filtered out from this output folder.
@@ -1211,15 +1323,106 @@
 		}
 		return false;
 	}
+	/*
+	 * Merges all awaiting deltas.
+	 */
+	private IJavaElementDelta mergeDeltas(Collection deltas) {
+		if (deltas.size() == 0) return null;
+		if (deltas.size() == 1) return (IJavaElementDelta)deltas.iterator().next();
+		
+		if (VERBOSE) {
+			System.out.println("MERGING " + deltas.size() + " DELTAS ["+Thread.currentThread()+"]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		}
+		
+		Iterator iterator = deltas.iterator();
+		JavaElementDelta rootDelta = new JavaElementDelta(this.manager.javaModel);
+		boolean insertedTree = false;
+		while (iterator.hasNext()) {
+			JavaElementDelta delta = (JavaElementDelta)iterator.next();
+			if (VERBOSE) {
+				System.out.println(delta.toString());
+			}
+			IJavaElement element = delta.getElement();
+			if (this.manager.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;
+		}
+	}	
+	private 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 (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 (VERBOSE) {
+					System.out.println(" -> " + (System.currentTimeMillis()-start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+		}
+	}
+	private void notifyTypeHierarchies(IElementChangedListener[] listeners, int listenerCount) {
+		for (int i= 0; i < listenerCount; i++) {
+			final IElementChangedListener listener = listeners[i];
+			if (!(listener instanceof TypeHierarchy)) continue;
 
-	/**
+			// 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 {
+					TypeHierarchy typeHierarchy = (TypeHierarchy)listener;
+					if (typeHierarchy.hasFineGrainChanges()) {
+						// case of changes in primary working copies
+						typeHierarchy.needsRefresh = true;
+						typeHierarchy.fireChange();
+					}
+				}
+			});
+		}
+	}
+	/*
 	 * Generic processing for elements with changed contents:<ul>
 	 * <li>The element is closed such that any subsequent accesses will re-open
 	 * the element reflecting its new structure.
 	 * <li>An entry is made in the delta reporting a content change (K_CHANGE with F_CONTENT flag set).
 	 * </ul>
 	 */
-	protected void nonJavaResourcesChanged(Openable element, IResourceDelta delta)
+	private void nonJavaResourcesChanged(Openable element, IResourceDelta delta)
 		throws JavaModelException {
 
 		// reset non-java resources if element was open
@@ -1257,6 +1460,16 @@
 		}
 		elementDelta.addResourceDelta(delta);
 	}
+	/*
+	 * Returns the other root infos for the given path. Look in the old other roots table if kind is REMOVED.
+	 */
+	private ArrayList otherRootsInfo(IPath path, int kind) {
+		if (kind == IResourceDelta.REMOVED) {
+			return (ArrayList)this.state.oldOtherRoots.get(path);
+		} else {
+			return (ArrayList)this.state.otherRoots.get(path);
+		}
+	}	
 	private OutputsInfo outputsInfo(RootInfo rootInfo, IResource res) {
 		try {
 			IJavaProject proj =
@@ -1298,88 +1511,10 @@
 				}
 			}
 		} catch (JavaModelException e) {
+			// java project doesn't exist: ignore
 		}
 		return null;
 	}
-	
-	/**
-	 * Check whether the updated file is affecting some of the properties of a given project (like
-	 * its classpath persisted as a file).
-	 * Also force classpath problems to be refresh if not running in autobuild mode.
-	 * NOTE: It can induce resource changes, and cannot be called during POST_CHANGE notification.
-	 *
-	 */
-	public void performPreBuildCheck(
-		IResourceDelta delta,
-		IJavaElement parent) {
-	
-		IResource resource = delta.getResource();
-		IJavaElement element = null;
-		boolean processChildren = false;
-	
-		switch (resource.getType()) {
-	
-			case IResource.ROOT :
-				if (delta.getKind() == IResourceDelta.CHANGED) {
-					element = JavaCore.create(resource);
-					processChildren = true;
-				}
-				break;
-			case IResource.PROJECT :
-				int kind = delta.getKind();
-				switch (kind) {
-					case IResourceDelta.CHANGED:
-						// do not visit non-java projects (see bug 16140 Non-java project gets .classpath)
-						IProject project = (IProject)resource;
-						if (JavaProject.hasJavaNature(project)) {
-							element = JavaCore.create(resource);
-							processChildren = true;
-						} else if (JavaModelManager.getJavaModelManager().getJavaModel().findJavaProject(project) != null) {
-							// project had the java nature
-							this.rootsAreStale = true;
-
-							// remove classpath cache so that initializeRoots() will not consider the project has a classpath
-							this.manager.removePerProjectInfo((JavaProject)JavaCore.create(project));
-						}
-						break;
-					case IResourceDelta.ADDED:
-						this.rootsAreStale = true;
-						break;
-					case IResourceDelta.REMOVED:
-						// remove classpath cache so that initializeRoots() will not consider the project has a classpath
-						this.manager.removePerProjectInfo((JavaProject)JavaCore.create(resource));
-						
-						this.rootsAreStale = true;
-						break;
-				}
-				break;
-			case IResource.FILE :
-				if (parent.getElementType() == IJavaElement.JAVA_PROJECT) {
-					IFile file = (IFile) resource;
-					JavaProject project = (JavaProject) parent;
-	
-					/* check classpath file change */
-					if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
-						reconcileClasspathFileUpdate(delta, file, project);
-						this.rootsAreStale = true;
-						break;
-					}
-//					/* check custom preference file change */
-//					if (file.getName().equals(JavaProject.PREF_FILENAME)) {
-//						reconcilePreferenceFileUpdate(delta, file, project);
-//						break;
-//					}
-				}
-				break;
-		}
-		if (processChildren) {
-			IResourceDelta[] children = delta.getAffectedChildren();
-			for (int i = 0; i < children.length; i++) {
-				performPreBuildCheck(children[i], element);
-			}
-		}
-	}
-	
 	private void popUntilPrefixOf(IPath path) {
 		while (this.currentElement != null) {
 			IPath currentElementPath = null;
@@ -1405,13 +1540,12 @@
 			this.currentElement = (Openable)this.currentElement.getParent();
 		}
 	}
-
-	/**
+	/*
 	 * Converts a <code>IResourceDelta</code> rooted in a <code>Workspace</code> into
 	 * the corresponding set of <code>IJavaElementDelta</code>, rooted in the
 	 * relevant <code>JavaModel</code>s.
 	 */
-	public IJavaElementDelta processResourceDelta(IResourceDelta changes) {
+	private IJavaElementDelta processResourceDelta(IResourceDelta changes) {
 
 		try {
 			IJavaModel model = this.manager.getJavaModel();
@@ -1426,7 +1560,7 @@
 					return null;
 				}
 			}
-			this.initializeRoots();
+			this.state.initializeRoots();
 			this.currentElement = null;
 			
 			// get the workspace delta, and start processing there.
@@ -1453,135 +1587,69 @@
 				}
 				
 				// traverse delta
-				if (!this.traverseDelta(delta, elementType, rootInfo, null) 
+				this.traverseDelta(delta, elementType, rootInfo, null);
+				
+				if (elementType == NON_JAVA_RESOURCE
 						|| (wasJavaProject != isJavaProject && (delta.getKind()) == IResourceDelta.CHANGED)) { // project has changed nature (description or open/closed)
 					try {
 						// add child as non java resource
 						nonJavaResourcesChanged((JavaModel)model, delta);
 					} catch (JavaModelException e) {
+						// java model could not be opened
 					}
 				}
 
 			}
-			
-			// update package fragment roots of projects that were affected
-			Iterator iterator = this.projectsToUpdate.iterator();
-			while (iterator.hasNext()) {
-				JavaProject project = (JavaProject)iterator.next();
-				project.updatePackageFragmentRoots();
-			}
-	
-			updateDependentNamelookups();
+			refreshPackageFragmentRoots();
+			refreshNamelookups();
 
 			return this.currentDelta;
 		} finally {
 			this.currentDelta = null;
-			this.projectsToUpdate.clear();
-			this.projectsForDependentNamelookupRefresh.clear();
+			this.rootsToRefresh.clear();
+			this.namelookupsToRefresh.clear();
 		}
 	}
-
-	/**
+	/*
 	 * Update the JavaModel according to a .classpath file change. The file can have changed as a result of a previous
 	 * call to JavaProject#setRawClasspath or as a result of some user update (through repository)
 	 */
-	void reconcileClasspathFileUpdate(IResourceDelta delta, IFile file, JavaProject project) {
-			
+	private void reconcileClasspathFileUpdate(IResourceDelta delta, JavaProject project) {
+
 		switch (delta.getKind()) {
 			case IResourceDelta.REMOVED : // recreate one based on in-memory classpath
-				try {
-					JavaModelManager.PerProjectInfo info = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
-					if (info.classpath != null) { // if there is an in-memory classpath
-						project.saveClasspath(info.classpath, info.outputLocation);
-					}
-				} catch (JavaModelException e) {
-					if (project.getProject().isAccessible()) {
-						Util.log(e, "Could not save classpath for "+ project.getPath()); //$NON-NLS-1$
-					}
-				}
+//				try {
+//					JavaModelManager.PerProjectInfo info = project.getPerProjectInfo();
+//					if (info.rawClasspath != null) { // if there is an in-memory classpath
+//						project.saveClasspath(info.rawClasspath, info.outputLocation);
+//					}
+//				} catch (JavaModelException e) {
+//					if (project.getProject().isAccessible()) {
+//						Util.log(e, "Could not save classpath for "+ project.getPath()); //$NON-NLS-1$
+//					}
+//				}
 				break;
 			case IResourceDelta.CHANGED :
 				if ((delta.getFlags() & IResourceDelta.CONTENT) == 0  // only consider content change
-						&& (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) // and also move and overide scenario (see http://dev.eclipse.org/bugs/show_bug.cgi?id=21420)
+					&& (delta.getFlags() & IResourceDelta.MOVED_FROM) == 0) {// and also move and overide scenario (see http://dev.eclipse.org/bugs/show_bug.cgi?id=21420)
 					break;
+				}
+			// fall through
 			case IResourceDelta.ADDED :
-				// check if any actual difference
-				project.flushClasspathProblemMarkers(false, true);
-				boolean wasSuccessful = false; // flag recording if .classpath file change got reflected
 				try {
-					// force to (re)read the property file
-					IClasspathEntry[] fileEntries = project.readClasspathFile(true/*create markers*/, false/*don't log problems*/);
-					if (fileEntries == null)
-						break; // could not read, ignore 
-					JavaModelManager.PerProjectInfo info = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
-					if (info.classpath != null) { // if there is an in-memory classpath
-						if (project.isClasspathEqualsTo(info.classpath, info.outputLocation, fileEntries)) {
-							wasSuccessful = true;
-							break;
-						}
-					}
-		
-					// will force an update of the classpath/output location based on the file information
-					// extract out the output location
-					IPath outputLocation = null;
-					if (fileEntries != null && fileEntries.length > 0) {
-						IClasspathEntry entry = fileEntries[fileEntries.length - 1];
-						if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
-							outputLocation = entry.getPath();
-							IClasspathEntry[] copy = new IClasspathEntry[fileEntries.length - 1];
-							System.arraycopy(fileEntries, 0, copy, 0, copy.length);
-							fileEntries = copy;
-						}
-					}
-					// restore output location				
-					if (outputLocation == null) {
-						outputLocation = SetClasspathOperation.ReuseOutputLocation;
-						// clean mode will also default to reusing current one
-					}
-					project.setRawClasspath(
-						fileEntries, 
-						outputLocation, 
-						null, // monitor
-						true, // canChangeResource
-						project.getResolvedClasspath(true), // ignoreUnresolvedVariable
-						true, // needValidation
-						false); // no need to save
-					
-					// if reach that far, the classpath file change got absorbed
-					wasSuccessful = true;
+					project.forceClasspathReload(null);
 				} catch (RuntimeException e) {
-					// setRawClasspath might fire a delta, and a listener may throw an exception
-					if (project.getProject().isAccessible()) {
-						Util.log(e, "Could not set classpath for "+ project.getPath()); //$NON-NLS-1$
+					if (VERBOSE) {
+						e.printStackTrace();
 					}
-					break;
-				} catch (JavaModelException e) { // CP failed validation
-					if (project.getProject().isAccessible()) {
-						if (e.getJavaModelStatus().getException() instanceof CoreException) {
-							// happens if the .classpath could not be written to disk
-							project.createClasspathProblemMarker(new JavaModelStatus(
-									IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
-									Util.bind("classpath.couldNotWriteClasspathFile", project.getElementName(), e.getMessage()))); //$NON-NLS-1$
-						} else {
-							project.createClasspathProblemMarker(new JavaModelStatus(
-									IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
-									Util.bind("classpath.invalidClasspathInClasspathFile", project.getElementName(), e.getMessage()))); //$NON-NLS-1$
-						}			
-					}
-					break;
-				} finally {
-					if (!wasSuccessful) { 
-						try {
-							project.setRawClasspath0(JavaProject.INVALID_CLASSPATH);
-							project.updatePackageFragmentRoots();
-						} catch (JavaModelException e) {
-						}
+				} catch (JavaModelException e) {	
+					if (VERBOSE) {
+						e.printStackTrace();
 					}
 				}
 		}
 	}
-
-	/**
+	/*
 	 * Update the JavaModel according to a .jprefs file change. The file can have changed as a result of a previous
 	 * call to JavaProject#setOptions or as a result of some user update (through repository)
 	 * Unused until preference file get shared (.jpref)
@@ -1640,13 +1708,48 @@
 				//fCurrentDelta.changed(project, IJavaElementDelta.F_OPTIONS_CHANGED);				
 		}
 	}
-
-	/**
+	/*
+	 * Traverse the set of projects which have changed namespace, and refresh their 
+	 * name lookups and their dependents
+	 */
+	private void refreshNamelookups() {
+		Iterator iterator;
+		// update namelookup of dependent projects
+		iterator = this.namelookupsToRefresh.iterator();
+		HashSet affectedDependents = new HashSet();
+		while (iterator.hasNext()) {
+			JavaProject project = (JavaProject)iterator.next();
+			project.resetNameLookup();
+			addDependentProjects(project.getPath(), affectedDependents);
+		}
+		iterator = affectedDependents.iterator();
+		while (iterator.hasNext()) {
+			JavaProject project = (JavaProject) iterator.next();
+			project.resetNameLookup();
+		}
+	}
+	/* 
+	 * Refresh package fragment roots of projects that were affected
+	 */
+	private void refreshPackageFragmentRoots() {
+		Iterator iterator = this.rootsToRefresh.iterator();
+		while (iterator.hasNext()) {
+			JavaProject project = (JavaProject)iterator.next();
+			project.updatePackageFragmentRoots();
+		}
+	}
+	/*
+	 * Registers the given delta with this delta processor.
+	 */
+	public void registerJavaModelDelta(IJavaElementDelta delta) {
+		this.javaModelDeltas.add(delta);
+	}
+	/*
 	 * Removes the given element from its parents cache of children. If the
 	 * element does not have a parent, or the parent is not currently open,
 	 * this has no effect. 
 	 */
-	protected void removeFromParentInfo(Openable child) {
+	private void removeFromParentInfo(Openable child) {
 
 		Openable parent = (Openable) child.getParent();
 		if (parent != null && parent.isOpen()) {
@@ -1658,7 +1761,7 @@
 			}
 		}
 	}
-	/**
+	/*
 	 * Notification that some resource changes have happened
 	 * on the platform, and that the Java Model should update any required
 	 * internal structures such that its elements remain consistent.
@@ -1679,54 +1782,47 @@
 						if(resource.getType() == IResource.PROJECT 
 							&& ((IProject) resource).hasNature(JavaCore.NATURE_ID)) {
 								
-							this.deleting((IProject)resource);
+							deleting((IProject)resource);
 						}
 					} catch(CoreException e){
+						// project doesn't exist or is not open: ignore
 					}
 					return;
 					
 				case IResourceChangeEvent.PRE_AUTO_BUILD :
+					// this.processPostChange = false;
 					if(isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
-						this.checkProjectsBeingAddedOrRemoved(delta);
-						
-						// update the classpath related markers
-						this.updateClasspathMarkers();
-	
-						// the following will close project if affected by the property file change
-						try {
-							// don't fire classpath change deltas right away, but batch them
-							this.manager.stopDeltas();
-							this.performPreBuildCheck(delta, null); 
-						} finally {
-							this.manager.startDeltas();
-						}
+						updateClasspathMarkers(delta);
+						JavaBuilder.buildStarting();
 					}
-					// only fire already computed deltas (resource ones will be processed in post change only)
-					this.manager.fire(null, ElementChangedEvent.PRE_AUTO_BUILD);
+					// does not fire any deltas
 					break;
 
 				case IResourceChangeEvent.POST_AUTO_BUILD :
-					JavaBuilder.finishedBuilding(event);
+					JavaBuilder.buildFinished();
 					break;
 					
 				case IResourceChangeEvent.POST_CHANGE :
-					if (isAffectedBy(delta)) {
+					if (isAffectedBy(delta)) { // avoid populating for SYNC or MARKER deltas
 						try {
-							if (this.refreshedElements != null) {
-								try {
+							try {
+								stopDeltas();
+								checkProjectsBeingAddedOrRemoved(delta);
+								if (this.refreshedElements != null) {
 									createExternalArchiveDelta(null);
-								} catch (JavaModelException e) {
-									e.printStackTrace();
 								}
+								IJavaElementDelta translatedDelta = processResourceDelta(delta);
+								if (translatedDelta != null) { 
+									registerJavaModelDelta(translatedDelta);
+								}
+							} finally {
+								startDeltas();
 							}
-							IJavaElementDelta translatedDelta = this.processResourceDelta(delta);
-							if (translatedDelta != null) { 
-								this.manager.registerJavaModelDelta(translatedDelta);
-							}
-							this.manager.fire(null, ElementChangedEvent.POST_CHANGE);
+							notifyTypeHierarchies(this.state.elementChangedListeners, this.state.elementChangedListenerCount);
+							fire(null, ElementChangedEvent.POST_CHANGE);
 						} finally {
 							// workaround for bug 15168 circular errors not reported 
-							this.manager.javaProjectsCache = null;
+							this.state.modelProjectsCache = null;
 							this.removedRoots = null;
 						}
 					}
@@ -1734,46 +1830,34 @@
 		}
 	}
 	/*
-	 * Finds the root info this path is included in.
-	 * Returns null if not found.
-	 */
-	RootInfo enclosingRootInfo(IPath path, int kind) {
-		while (path != null && path.segmentCount() > 0) {
-			RootInfo rootInfo =  this.rootInfo(path, kind);
-			if (rootInfo != null) return rootInfo;
-			path = path.removeLastSegments(1);
-		}
-		return null;
-	}
-	/*
 	 * Returns the root info for the given path. Look in the old roots table if kind is REMOVED.
 	 */
-	RootInfo rootInfo(IPath path, int kind) {
+	private RootInfo rootInfo(IPath path, int kind) {
 		if (kind == IResourceDelta.REMOVED) {
-			return (RootInfo)this.oldRoots.get(path);
+			return (RootInfo)this.state.oldRoots.get(path);
 		} else {
-			return (RootInfo)this.roots.get(path);
+			return (RootInfo)this.state.roots.get(path);
 		}
 	}
 	/*
-	 * Returns the other root infos for the given path. Look in the old other roots table if kind is REMOVED.
+	 * Turns the firing mode to on. That is, deltas that are/have been
+	 * registered will be fired.
 	 */
-	ArrayList otherRootsInfo(IPath path, int kind) {
-		if (kind == IResourceDelta.REMOVED) {
-			return (ArrayList)this.oldOtherRoots.get(path);
-		} else {
-			return (ArrayList)this.otherRoots.get(path);
-		}
-	}	
-
-	/**
+	private 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.
+	 */
+	private void stopDeltas() {
+		this.isFiring= false;
+	}
+	/*
 	 * Converts an <code>IResourceDelta</code> and its children into
 	 * the corresponding <code>IJavaElementDelta</code>s.
-	 * Return whether the delta corresponds to a java element.
-	 * If it is not a java element, it will be added as a non-java
-	 * resource by the sender of this method.
 	 */
-	protected boolean traverseDelta(
+	private void traverseDelta(
 		IResourceDelta delta, 
 		int elementType, 
 		RootInfo rootInfo,
@@ -1845,39 +1929,42 @@
 				boolean isNestedRoot = rootInfo != null && childRootInfo != null;
 				if (!isResFilteredFromOutput 
 						&& !isNestedRoot) { // do not treat as non-java rsc if nested root
-					if (!this.traverseDelta(child, childType, rootInfo == null ? childRootInfo : rootInfo, outputsInfo)) { // traverse delta for child in the same project
-						// it is a non-java resource
-						try {
-							if (rootInfo != null) { // if inside a package fragment root
-								if (!isValidParent) continue; 
-								if (parent == null) {
-									// find the parent of the non-java resource to attach to
-									if (this.currentElement == null 
-											|| !this.currentElement.getJavaProject().equals(rootInfo.project)) {
-										// force the currentProject to be used
-										this.currentElement = (Openable)rootInfo.project;
-									}
-									if (elementType == IJavaElement.JAVA_PROJECT
-										|| (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT 
-											&& res instanceof IProject)) { 
-										// NB: attach non-java resource to project (not to its package fragment root)
-										parent = (Openable)rootInfo.project;
-									} else {
-										parent = this.createElement(res, elementType, rootInfo);
-									}
-									if (parent == null) {
-										isValidParent = false;
-										continue;
-									}
+
+					this.traverseDelta(child, childType, rootInfo == null ? childRootInfo : rootInfo, outputsInfo); // traverse delta for child in the same project
+
+					if (childType == NON_JAVA_RESOURCE) {
+						if (rootInfo != null) { // if inside a package fragment root
+							if (!isValidParent) continue; 
+							if (parent == null) {
+								// find the parent of the non-java resource to attach to
+								if (this.currentElement == null
+										|| !rootInfo.project.equals(this.currentElement.getJavaProject())) { // note if currentElement is the IJavaModel, getJavaProject() is null
+									// force the currentProject to be used
+									this.currentElement = (Openable)rootInfo.project;
 								}
-								// add child as non java resource
-								nonJavaResourcesChanged(parent, child);
-							} else {
-								// the non-java resource (or its parent folder) will be attached to the java project
-								if (orphanChildren == null) orphanChildren = new IResourceDelta[length];
-								orphanChildren[i] = child;
+								if (elementType == IJavaElement.JAVA_PROJECT
+									|| (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT 
+										&& res instanceof IProject)) { 
+									// NB: attach non-java resource to project (not to its package fragment root)
+									parent = (Openable)rootInfo.project;
+								} else {
+									parent = this.createElement(res, elementType, rootInfo);
+								}
+								if (parent == null) {
+									isValidParent = false;
+									continue;
+								}
 							}
-						} catch (JavaModelException e) {
+							// add child as non java resource
+							try {
+								nonJavaResourcesChanged(parent, child);
+							} catch (JavaModelException e) {
+								// ignore
+							}
+						} else {
+							// the non-java resource (or its parent folder) will be attached to the java project
+							if (orphanChildren == null) orphanChildren = new IResourceDelta[length];
+							orphanChildren[i] = child;
 						}
 					} else {
 						oneChildOnClasspath = true;
@@ -1892,7 +1979,6 @@
 				if (isNestedRoot 
 						|| (childRootInfo == null && (childRootInfo = this.rootInfo(childPath, childKind)) != null)) {
 					this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root
-					// NB: No need to check the return value as the child can only be on the classpath
 				}
 	
 				// if the child is a package fragment root of one or several other projects
@@ -1919,78 +2005,181 @@
 							try {
 								nonJavaResourcesChanged(adoptiveProject, orphanChildren[i]);
 							} catch (JavaModelException e) {
+								// ignore
 							}
 						}
 					}
 				}
 			} // else resource delta will be added by parent
-			return elementType != NON_JAVA_RESOURCE; // TODO: (jerome) do we still need to return? (check could be done by caller)
-		} else {
-			return elementType != NON_JAVA_RESOURCE;
+		} // else resource delta will be added by parent
+	}
+
+	/*
+	 * Check whether .classpath files are affected by the given delta.
+	 * Creates/removes problem markers if needed.
+	 * Remember the affected projects in the given set.
+	 */
+	private void updateClasspathMarkers(IResourceDelta delta, HashSet affectedProjects, Map preferredClasspaths, Map preferredOutputs) {
+		IResource resource = delta.getResource();
+		boolean processChildren = false;
+		
+		switch (resource.getType()) {
+	
+			case IResource.ROOT :
+				if (delta.getKind() == IResourceDelta.CHANGED) {
+					processChildren = true;
+				}
+				break;
+			case IResource.PROJECT :
+				IProject project = (IProject)resource;
+				int kind = delta.getKind();
+				boolean isJavaProject = JavaProject.hasJavaNature(project);
+				switch (kind) {
+					case IResourceDelta.ADDED:
+						processChildren = isJavaProject;
+						affectedProjects.add(project.getFullPath());
+						break;
+					case IResourceDelta.CHANGED:
+						processChildren = isJavaProject;
+						if ((delta.getFlags() & IResourceDelta.OPEN) != 0) {
+							// project opened or closed: remember  project and its dependents
+							affectedProjects.add(project.getFullPath());
+							if (isJavaProject) {
+								JavaProject javaProject = (JavaProject)JavaCore.create(project);
+								javaProject.updateClasspathMarkers(preferredClasspaths, preferredOutputs); // in case .classpath got modified while closed
+							}
+						} else if ((delta.getFlags() & IResourceDelta.DESCRIPTION) != 0) {
+							if (!JavaProject.hasJavaNature(project)) {
+								// project no longer has Java nature, discard Java related obsolete markers
+								JavaProject javaProject = (JavaProject)JavaCore.create(project);
+								affectedProjects.add(project.getFullPath());
+								// flush classpath markers
+								javaProject.
+									flushClasspathProblemMarkers(
+										true, // flush cycle markers
+										true  //flush classpath format markers
+									);
+									
+								// remove problems and tasks created  by the builder
+								JavaBuilder.removeProblemsAndTasksFor(project);
+							}
+						}
+						break;
+					case IResourceDelta.REMOVED:
+						affectedProjects.add(project.getFullPath());
+						break;
+				}
+				break;
+			case IResource.FILE :
+				/* check classpath file change */
+				IFile file = (IFile) resource;
+				if (file.getName().equals(JavaProject.CLASSPATH_FILENAME)) {
+					affectedProjects.add(file.getProject().getFullPath());
+					JavaProject javaProject = (JavaProject)JavaCore.create(file.getProject());
+					javaProject.updateClasspathMarkers(preferredClasspaths, preferredOutputs);
+					break;
+				}
+//				/* check custom preference file change */
+//				if (file.getName().equals(JavaProject.PREF_FILENAME)) {
+//					reconcilePreferenceFileUpdate(delta, file, project);
+//					break;
+//				}
+				break;
+		}
+		if (processChildren) {
+			IResourceDelta[] children = delta.getAffectedChildren();
+			for (int i = 0; i < children.length; i++) {
+				updateClasspathMarkers(children[i], affectedProjects, preferredClasspaths, preferredOutputs);
+			}
 		}
 	}
 
-	/**
+	/*
 	 * Update the classpath markers and cycle markers for the projects to update.
 	 */
-	void updateClasspathMarkers() {
-		try {
-			if (!ResourcesPlugin.getWorkspace().isAutoBuilding()) {
-				Iterator iterator = this.projectsToUpdate.iterator();
-				while (iterator.hasNext()) {
-					try {
-						JavaProject project = (JavaProject)iterator.next();
-						
-						 // force classpath marker refresh
-						project.getResolvedClasspath(
-							true, // ignoreUnresolvedEntry
-							true); // generateMarkerOnError
-						
-					} catch (JavaModelException e) {
+	private void updateClasspathMarkers(IResourceDelta delta) {
+		
+		Map preferredClasspaths = new HashMap(5);
+		Map preferredOutputs = new HashMap(5);
+		HashSet affectedProjects = new HashSet(5);
+		
+		// read .classpath files that have changed, and create markers if format is wrong
+		updateClasspathMarkers(delta, affectedProjects, preferredClasspaths, preferredOutputs); 
+	
+		if (!affectedProjects.isEmpty()) {
+			try {
+				if (!ResourcesPlugin.getWorkspace().isAutoBuilding()) {
+					IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+					IProject[] projects = workspaceRoot.getProjects();
+					int length = projects.length;
+					for (int i = 0; i < length; i++){
+						IProject project = projects[i];
+						JavaProject javaProject = (JavaProject)JavaCore.create(project);
+						if (preferredClasspaths.get(javaProject) == null) { // not already updated
+							try {
+								IPath projectPath = project.getFullPath();
+								IClasspathEntry[] classpath = javaProject.getResolvedClasspath(true); // allowed to reuse model cache
+								for (int j = 0, cpLength = classpath.length; j < cpLength; j++) {
+									IClasspathEntry entry = classpath[j];
+									switch (entry.getEntryKind()) {
+										case IClasspathEntry.CPE_PROJECT:
+											if (affectedProjects.contains(entry.getPath())) {
+												javaProject.updateClasspathMarkers(null, null);
+											}
+											break;
+										case IClasspathEntry.CPE_LIBRARY:
+											IPath entryPath = entry.getPath();
+											IPath libProjectPath = entryPath.removeLastSegments(entryPath.segmentCount()-1);
+											if (!libProjectPath.equals(projectPath) // if library contained in another project
+													&& affectedProjects.contains(libProjectPath)) {
+												javaProject.updateClasspathMarkers(null, null);
+											}
+											break;
+									}
+								}
+							} catch(JavaModelException e) {
+									// project no longer exists
+							}
+						}
 					}
 				}
+				// update all cycle markers
+				JavaProject.updateAllCycleMarkers(preferredClasspaths);
+			} catch(JavaModelException e) {
+				// project no longer exists
 			}
-			if (!this.projectsToUpdate.isEmpty()){
-				try {
-					// update all cycle markers
-					JavaProject.updateAllCycleMarkers();
-				} catch (JavaModelException e) {
-				}
-			}				
-		} finally {
-			this.projectsToUpdate = new HashSet();
 		}
 	}
-
+	
 	/*
 	 * Update the current delta (ie. add/remove/change the given element) and update the correponding index.
 	 * Returns whether the children of the given delta must be processed.
 	 * @throws a JavaModelException if the delta doesn't correspond to a java element of the given type.
 	 */
-	private boolean updateCurrentDeltaAndIndex(IResourceDelta delta, int elementType, RootInfo rootInfo) {
+	public boolean updateCurrentDeltaAndIndex(IResourceDelta delta, int elementType, RootInfo rootInfo) {
 		Openable element;
 		switch (delta.getKind()) {
 			case IResourceDelta.ADDED :
 				IResource deltaRes = delta.getResource();
-				element = this.createElement(deltaRes, elementType, rootInfo);
+				element = createElement(deltaRes, elementType, rootInfo);
 				if (element == null) {
 					// resource might be containing shared roots (see bug 19058)
-					this.updateRoots(deltaRes.getFullPath(), delta);
+					this.state.updateRoots(deltaRes.getFullPath(), delta, this);
 					return false;
 				}
-				this.updateIndex(element, delta);
-				this.elementAdded(element, delta, rootInfo);
+				updateIndex(element, delta);
+				elementAdded(element, delta, rootInfo);
 				return false;
 			case IResourceDelta.REMOVED :
 				deltaRes = delta.getResource();
-				element = this.createElement(deltaRes, elementType, rootInfo);
+				element = createElement(deltaRes, elementType, rootInfo);
 				if (element == null) {
 					// resource might be containing shared roots (see bug 19058)
-					this.updateRoots(deltaRes.getFullPath(), delta);
+					this.state.updateRoots(deltaRes.getFullPath(), delta, this);
 					return false;
 				}
-				this.updateIndex(element, delta);
-				this.elementRemoved(element, delta, rootInfo);
+				updateIndex(element, delta);
+				elementRemoved(element, delta, rootInfo);
 	
 				if (deltaRes.getType() == IResource.PROJECT){			
 					// reset the corresponding project built state, since cannot reuse if added back
@@ -2001,33 +2190,32 @@
 				int flags = delta.getFlags();
 				if ((flags & IResourceDelta.CONTENT) != 0) {
 					// content has changed
-					element = this.createElement(delta.getResource(), elementType, rootInfo);
+					element = createElement(delta.getResource(), elementType, rootInfo);
 					if (element == null) return false;
-					this.updateIndex(element, delta);
-					this.contentChanged(element, delta);
+					updateIndex(element, delta);
+					contentChanged(element);
 				} else if (elementType == IJavaElement.JAVA_PROJECT) {
 					if ((flags & IResourceDelta.OPEN) != 0) {
 						// project has been opened or closed
 						IProject res = (IProject)delta.getResource();
-						element = this.createElement(res, elementType, rootInfo);
+						element = createElement(res, elementType, rootInfo);
 						if (element == null) {
 							// resource might be containing shared roots (see bug 19058)
-							this.updateRoots(res.getFullPath(), delta);
+							this.state.updateRoots(res.getFullPath(), delta, this);
 							return false;
 						}
 						if (res.isOpen()) {
 							if (JavaProject.hasJavaNature(res)) {
-								this.elementAdded(element, delta, rootInfo);
-								this.indexManager.indexAll(res);
+								elementAdded(element, delta, rootInfo);
+								this.manager.indexManager.indexAll(res);
 							}
 						} else {
 							JavaModel javaModel = this.manager.getJavaModel();
 							boolean wasJavaProject = javaModel.findJavaProject(res) != null;
 							if (wasJavaProject) {
-								this.elementRemoved(element, delta, rootInfo);
-								this.indexManager.discardJobs(element.getElementName());
-								this.indexManager.removeIndexFamily(res.getFullPath());
-								
+								elementRemoved(element, delta, rootInfo);
+								this.manager.indexManager.discardJobs(element.getElementName());
+								this.manager.indexManager.removeIndexFamily(res.getFullPath());
 							}
 						}
 						return false; // when a project is open/closed don't process children
@@ -2042,12 +2230,12 @@
 							element = this.createElement(res, elementType, rootInfo);
 							if (element == null) return false; // note its resources are still visible as roots to other projects
 							if (isJavaProject) {
-								this.elementAdded(element, delta, rootInfo);
-								this.indexManager.indexAll(res);
+								elementAdded(element, delta, rootInfo);
+								this.manager.indexManager.indexAll(res);
 							} else {
-								this.elementRemoved(element, delta, rootInfo);
-								this.indexManager.discardJobs(element.getElementName());
-								this.indexManager.removeIndexFamily(res.getFullPath());
+								elementRemoved(element, delta, rootInfo);
+								this.manager.indexManager.discardJobs(element.getElementName());
+								this.manager.indexManager.removeIndexFamily(res.getFullPath());
 								// reset the corresponding project built state, since cannot reuse if added back
 								this.manager.setLastBuiltState(res, null /*no state*/);
 							}
@@ -2059,210 +2247,168 @@
 		}
 		return true;
 	}
-
-	/**
-	 * Traverse the set of projects which have changed namespace, and refresh their dependents
-	 */
-	public void updateDependentNamelookups() {
-		Iterator iterator;
-		// update namelookup of dependent projects
-		iterator = this.projectsForDependentNamelookupRefresh.iterator();
-		HashSet affectedDependents = new HashSet();
-		while (iterator.hasNext()) {
-			JavaProject project = (JavaProject)iterator.next();
-			addDependentProjects(project.getPath(), affectedDependents);
-		}
-		iterator = affectedDependents.iterator();
-		while (iterator.hasNext()) {
-			JavaProject project = (JavaProject) iterator.next();
-			if (project.isOpen()){
-				try {
-					((JavaProjectElementInfo)project.getElementInfo()).setNameLookup(null);
-				} catch (JavaModelException e) {
+	private void updateIndex(Openable element, IResourceDelta delta) {
+	
+		IndexManager indexManager = this.manager.indexManager;
+		if (indexManager == null)
+			return;
+	
+		switch (element.getElementType()) {
+			case IJavaElement.JAVA_PROJECT :
+				switch (delta.getKind()) {
+					case IResourceDelta.ADDED :
+						indexManager.indexAll(element.getJavaProject().getProject());
+						break;
+					case IResourceDelta.REMOVED :
+						indexManager.removeIndexFamily(element.getJavaProject().getProject().getFullPath());
+						// NB: Discarding index jobs belonging to this project was done during PRE_DELETE
+						break;
+					// NB: Update of index if project is opened, closed, or its java nature is added or removed
+					//     is done in updateCurrentDeltaAndIndex
 				}
-			}
-		}
-	}
-
-protected void updateIndex(Openable element, IResourceDelta delta) {
-
-	if (indexManager == null)
-		return;
-
-	switch (element.getElementType()) {
-		case IJavaElement.JAVA_PROJECT :
-			switch (delta.getKind()) {
-				case IResourceDelta.ADDED :
-					this.indexManager.indexAll(element.getJavaProject().getProject());
+				break;
+			case IJavaElement.PACKAGE_FRAGMENT_ROOT :
+				if (element instanceof JarPackageFragmentRoot) {
+					JarPackageFragmentRoot root = (JarPackageFragmentRoot)element;
+					// index jar file only once (if the root is in its declaring project)
+					IPath jarPath = root.getPath();
+					switch (delta.getKind()) {
+						case IResourceDelta.ADDED:
+							// index the new jar
+							indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
+							break;
+						case IResourceDelta.CHANGED:
+							// first remove the index so that it is forced to be re-indexed
+							indexManager.removeIndex(jarPath);
+							// then index the jar
+							indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
+							break;
+						case IResourceDelta.REMOVED:
+							// the jar was physically removed: remove the index
+							indexManager.discardJobs(jarPath.toString());
+							indexManager.removeIndex(jarPath);
+							break;
+					}
 					break;
-				case IResourceDelta.REMOVED :
-					this.indexManager.removeIndexFamily(element.getJavaProject().getProject().getFullPath());
-					// NB: Discarding index jobs belonging to this project was done during PRE_DELETE
-					break;
-				// NB: Update of index if project is opened, closed, or its java nature is added or removed
-				//     is done in updateCurrentDeltaAndIndex
-			}
-			break;
-		case IJavaElement.PACKAGE_FRAGMENT_ROOT :
-			if (element instanceof JarPackageFragmentRoot) {
-				JarPackageFragmentRoot root = (JarPackageFragmentRoot)element;
-				// index jar file only once (if the root is in its declaring project)
-				IPath jarPath = root.getPath();
+				} else {
+					int kind = delta.getKind();
+					if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) {
+						IPackageFragmentRoot root = (IPackageFragmentRoot)element;
+						this.updateRootIndex(root, root.getPackageFragment(""), delta); //$NON-NLS-1$
+						break;
+					}
+				}
+				// don't break as packages of the package fragment root can be indexed below
+			case IJavaElement.PACKAGE_FRAGMENT :
 				switch (delta.getKind()) {
 					case IResourceDelta.ADDED:
-						// index the new jar
-						indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
-						break;
-					case IResourceDelta.CHANGED:
-						// first remove the index so that it is forced to be re-indexed
-						indexManager.removeIndex(jarPath);
-						// then index the jar
-						indexManager.indexLibrary(jarPath, root.getJavaProject().getProject());
-						break;
 					case IResourceDelta.REMOVED:
-						// the jar was physically removed: remove the index
-						this.indexManager.discardJobs(jarPath.toString());
-						this.indexManager.removeIndex(jarPath);
+						IPackageFragment pkg = null;
+						if (element instanceof IPackageFragmentRoot) {
+							IPackageFragmentRoot root = (IPackageFragmentRoot)element;
+							pkg = root.getPackageFragment(""); //$NON-NLS-1$
+						} else {
+							pkg = (IPackageFragment)element;
+						}
+						RootInfo rootInfo = rootInfo(pkg.getParent().getPath(), delta.getKind());
+						boolean isSource = 
+							rootInfo == null // if null, defaults to source
+							|| rootInfo.entryKind == IClasspathEntry.CPE_SOURCE;
+						IResourceDelta[] children = delta.getAffectedChildren();
+						for (int i = 0, length = children.length; i < length; i++) {
+							IResourceDelta child = children[i];
+							IResource resource = child.getResource();
+							if (resource instanceof IFile) {
+								String name = resource.getName();
+								if (isSource) {
+									if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(name)) {
+										Openable cu = (Openable)pkg.getCompilationUnit(name);
+										this.updateIndex(cu, child);
+									}
+								} else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) {
+									Openable classFile = (Openable)pkg.getClassFile(name);
+									this.updateIndex(classFile, child);
+								}
+							}
+						}
 						break;
 				}
 				break;
-			} else {
-				int kind = delta.getKind();
-				if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) {
-					IPackageFragmentRoot root = (IPackageFragmentRoot)element;
-					this.updateRootIndex(root, root.getPackageFragment(""), delta); //$NON-NLS-1$
-					break;
-				}
-			}
-			// don't break as packages of the package fragment root can be indexed below
-		case IJavaElement.PACKAGE_FRAGMENT :
-			switch (delta.getKind()) {
-				case IResourceDelta.ADDED:
-				case IResourceDelta.REMOVED:
-					IPackageFragment pkg = null;
-					if (element instanceof IPackageFragmentRoot) {
-						IPackageFragmentRoot root = (IPackageFragmentRoot)element;
-						pkg = root.getPackageFragment(""); //$NON-NLS-1$
-					} else {
-						pkg = (IPackageFragment)element;
-					}
-					IResourceDelta[] children = delta.getAffectedChildren();
-					for (int i = 0, length = children.length; i < length; i++) {
-						IResourceDelta child = children[i];
-						IResource resource = child.getResource();
-						if (resource instanceof IFile) {
-							String name = resource.getName();
-							if (Util.isJavaFileName(name)) {
-								Openable cu = (Openable)pkg.getCompilationUnit(name);
-								this.updateIndex(cu, child);
-							} else if (Util.isClassFileName(name)) {
-								Openable classFile = (Openable)pkg.getClassFile(name);
-								this.updateIndex(classFile, child);
-							}
-						}
-					}
-					break;
-			}
-			break;
-		case IJavaElement.CLASS_FILE :
-			IFile file = (IFile) delta.getResource();
-			IJavaProject project = element.getJavaProject();
-			IPath binaryFolderPath = element.getPackageFragmentRoot().getPath();
-			// if the class file is part of the binary output, it has been created by
-			// the java builder -> ignore
-			try {
-				if (binaryFolderPath.equals(project.getOutputLocation())) {
-					break;
-				}
-			} catch (JavaModelException e) {
-			}
-			switch (delta.getKind()) {
-				case IResourceDelta.CHANGED :
-					// no need to index if the content has not changed
-					if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
+			case IJavaElement.CLASS_FILE :
+				IFile file = (IFile) delta.getResource();
+				IJavaProject project = element.getJavaProject();
+				IPath binaryFolderPath = element.getPackageFragmentRoot().getPath();
+				// if the class file is part of the binary output, it has been created by
+				// the java builder -> ignore
+				try {
+					if (binaryFolderPath.equals(project.getOutputLocation())) {
 						break;
-				case IResourceDelta.ADDED :
-					indexManager.addBinary(file, binaryFolderPath);
-					break;
-				case IResourceDelta.REMOVED :
-					indexManager.remove(file.getFullPath().toString(), binaryFolderPath);
-					break;
-			}
-			break;
-		case IJavaElement.COMPILATION_UNIT :
-			file = (IFile) delta.getResource();
-			switch (delta.getKind()) {
-				case IResourceDelta.CHANGED :
-					// no need to index if the content has not changed
-					if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
+					}
+				} catch (JavaModelException e) {
+					// project doesn't exist: ignore
+				}
+				switch (delta.getKind()) {
+					case IResourceDelta.CHANGED :
+						// no need to index if the content has not changed
+						if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
+							break;
+					case IResourceDelta.ADDED :
+						indexManager.addBinary(file, binaryFolderPath);
 						break;
-				case IResourceDelta.ADDED :
-					indexManager.addSource(file, file.getProject().getProject().getFullPath());
-					break;
-				case IResourceDelta.REMOVED :
-					indexManager.remove(file.getFullPath().toString(), file.getProject().getProject().getFullPath());
-					break;
-			}
-	}
-}
-/**
- * Upadtes the index of the given root (assuming it's an addition or a removal).
- * This is done recusively, pkg being the current package.
- */
-private void updateRootIndex(IPackageFragmentRoot root, IPackageFragment pkg, IResourceDelta delta) {
-	this.updateIndex((Openable)pkg, delta);
-	IResourceDelta[] children = delta.getAffectedChildren();
-	String name = pkg.getElementName();
-	for (int i = 0, length = children.length; i < length; i++) {
-		IResourceDelta child = children[i];
-		IResource resource = child.getResource();
-		if (resource instanceof IFolder) {
-			String subpkgName = 
-				name.length() == 0 ? 
-					resource.getName() : 
-					name + "." + resource.getName(); //$NON-NLS-1$
-			IPackageFragment subpkg = root.getPackageFragment(subpkgName);
-			this.updateRootIndex(root, subpkg, child);
+					case IResourceDelta.REMOVED :
+						indexManager.remove(file.getFullPath().toString(), binaryFolderPath);
+						break;
+				}
+				break;
+			case IJavaElement.COMPILATION_UNIT :
+				file = (IFile) delta.getResource();
+				switch (delta.getKind()) {
+					case IResourceDelta.CHANGED :
+						// no need to index if the content has not changed
+						if ((delta.getFlags() & IResourceDelta.CONTENT) == 0)
+							break;
+					case IResourceDelta.ADDED :
+						indexManager.addSource(file, file.getProject().getProject().getFullPath());
+						break;
+					case IResourceDelta.REMOVED :
+						indexManager.remove(file.getFullPath().toString(), file.getProject().getProject().getFullPath());
+						break;
+				}
 		}
 	}
-}
-/*
- * Update the roots that are affected by the addition or the removal of the given container resource.
- */
-private void updateRoots(IPath containerPath, IResourceDelta containerDelta) {
-	Map roots;
-	Map otherRoots;
-	if (containerDelta.getKind() == IResourceDelta.REMOVED) {
-		roots = this.oldRoots;
-		otherRoots = this.oldOtherRoots;
-	} else {
-		roots = this.roots;
-		otherRoots = this.otherRoots;
-	}
-	Iterator iterator = roots.keySet().iterator();
-	while (iterator.hasNext()) {
-		IPath path = (IPath)iterator.next();
-		if (containerPath.isPrefixOf(path) && !containerPath.equals(path)) {
-			IResourceDelta rootDelta = containerDelta.findMember(path.removeFirstSegments(1));
-			if (rootDelta == null) continue;
-			RootInfo rootInfo = (RootInfo)roots.get(path);
+	/*
+	 * Update Java Model given some delta
+	 */
+	public void updateJavaModel(IJavaElementDelta customDelta) {
 
-			if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
-				this.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);
+		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);
 			}
-			
-			ArrayList rootList = (ArrayList)otherRoots.get(path);
-			if (rootList != null) {
-				Iterator otherProjects = rootList.iterator();
-				while (otherProjects.hasNext()) {
-					rootInfo = (RootInfo)otherProjects.next();
-					if (!rootInfo.project.getPath().isPrefixOf(path)) { // only consider roots that are not included in the container
-						this.updateCurrentDeltaAndIndex(rootDelta, IJavaElement.PACKAGE_FRAGMENT_ROOT, rootInfo);
-					}
-				}
+		} else {
+			this.modelUpdater.processJavaDelta(customDelta);
+		}
+	}
+	/*
+	 * Updates the index of the given root (assuming it's an addition or a removal).
+	 * This is done recusively, pkg being the current package.
+	 */
+	private void updateRootIndex(IPackageFragmentRoot root, IPackageFragment pkg, IResourceDelta delta) {
+		this.updateIndex((Openable)pkg, delta);
+		IResourceDelta[] children = delta.getAffectedChildren();
+		String name = pkg.getElementName();
+		for (int i = 0, length = children.length; i < length; i++) {
+			IResourceDelta child = children[i];
+			IResource resource = child.getResource();
+			if (resource instanceof IFolder) {
+				String subpkgName = 
+					name.length() == 0 ? 
+						resource.getName() : 
+						name + "." + resource.getName(); //$NON-NLS-1$
+				IPackageFragment subpkg = root.getPackageFragment(subpkgName);
+				this.updateRootIndex(root, subpkg, child);
 			}
 		}
 	}
 }
-
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DestroyWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DestroyWorkingCopyOperation.java
deleted file mode 100644
index 630666a..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DestroyWorkingCopyOperation.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core;
-
-import java.util.Map;
-
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.JavaModelException;
-
-/**
- * Destroys a working copy (remove it from its cache if it is shared)
- * and signal its removal through a delta.
- */
-public class DestroyWorkingCopyOperation extends JavaModelOperation {
-	
-	public DestroyWorkingCopyOperation(IJavaElement workingCopy) {
-		super(new IJavaElement[] {workingCopy});
-	}
-	/**
-	 * @exception JavaModelException if setting the source
-	 * 	of the original compilation unit fails
-	 */
-	protected void executeOperation() throws JavaModelException {
-		WorkingCopy workingCopy = getWorkingCopy();
-		workingCopy.close();
-		
-		// if original element is not on classpath flush it from the cache 
-		IJavaElement originalElement = workingCopy.getOriginalElement();
-		if (!workingCopy.getParent().exists()) {
-			((CompilationUnit)originalElement).close();
-		}
-		
-		// remove working copy from the cache if it is shared
-		JavaModelManager manager = JavaModelManager.getJavaModelManager();
-		
-		// In order to be shared, working copies have to denote the same compilation unit 
-		// AND use the same buffer factory.
-		// Assuming there is a little set of buffer factories, then use a 2 level Map cache.
-		Map sharedWorkingCopies = manager.sharedWorkingCopies;
-		
-		Map perFactoryWorkingCopies = (Map) sharedWorkingCopies.get(workingCopy.bufferFactory);
-		if (perFactoryWorkingCopies != null){
-			if (perFactoryWorkingCopies.remove(originalElement) != null
-					&& CompilationUnit.SHARED_WC_VERBOSE) {
-				System.out.println("Destroying shared working copy " + workingCopy.toStringWithAncestors());//$NON-NLS-1$
-			}
-		}
-		
-		// report removed java delta
-		JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
-		delta.removed(workingCopy);
-		addDelta(delta);
-		removeReconcileDelta(workingCopy);
-	}
-	/**
-	 * Returns the working copy this operation is working on.
-	 */
-	protected WorkingCopy getWorkingCopy() {
-		return (WorkingCopy)getElementToProcess();
-	}
-	/**
-	 * @see JavaModelOperation#isReadOnly
-	 */
-	public boolean isReadOnly() {
-		return true;
-	}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DiscardWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DiscardWorkingCopyOperation.java
new file mode 100644
index 0000000..e38a97d
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DiscardWorkingCopyOperation.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.JavaModelException;
+
+/**
+ * Discards a working copy (decrement its use count and remove its working copy info if the use count is 0)
+ * and signal its removal through a delta.
+ */
+public class DiscardWorkingCopyOperation extends JavaModelOperation {
+	
+	public DiscardWorkingCopyOperation(IJavaElement workingCopy) {
+		super(new IJavaElement[] {workingCopy});
+	}
+	protected void executeOperation() throws JavaModelException {
+		CompilationUnit workingCopy = getWorkingCopy();
+		
+		int useCount = JavaModelManager.getJavaModelManager().discardPerWorkingCopyInfo(workingCopy);
+		if (useCount == 0) {
+			if (!workingCopy.isPrimary()) {
+				// report removed java delta for a non-primary working copy
+				JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+				delta.removed(workingCopy);
+				addDelta(delta);
+				removeReconcileDelta(workingCopy);
+			} else {
+				if (workingCopy.getResource().isAccessible()) {
+					// report a F_PRIMARY_WORKING_COPY change delta for a primary working copy
+					JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+					delta.changed(workingCopy, IJavaElementDelta.F_PRIMARY_WORKING_COPY);
+					addDelta(delta);
+				} else {
+					// report a REMOVED delta
+					JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+					delta.removed(workingCopy, IJavaElementDelta.F_PRIMARY_WORKING_COPY);
+					addDelta(delta);
+				}
+			}
+		}
+	}
+	/**
+	 * Returns the working copy this operation is working on.
+	 */
+	protected CompilationUnit getWorkingCopy() {
+		return (CompilationUnit)getElementToProcess();
+	}
+	/**
+	 * @see JavaModelOperation#isReadOnly
+	 */
+	public boolean isReadOnly() {
+		return true;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java
index 52e9ec8..8e46fd8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java
@@ -10,7 +10,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import org.eclipse.jdt.core.IOpenable;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.internal.core.util.LRUCache;
 
@@ -38,9 +37,9 @@
  * by closing the element.
  */
 protected boolean close(LRUCacheEntry entry) {
-	IOpenable element = (IOpenable) entry._fKey;
+	Openable element = (Openable) entry._fKey;
 	try {
-		if (element.hasUnsavedChanges()) {
+		if (!element.canBeRemovedFromCache()) {
 			return false;
 		} else {
 			// We must close an entire JarPackageFragmentRoot at once.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/FailedReconciliationException.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/FailedReconciliationException.java
deleted file mode 100644
index 247f45a..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/FailedReconciliationException.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core;
-
-public class FailedReconciliationException extends RuntimeException {
-/**
- * FailReconciliationException constructor comment.
- */
-public FailedReconciliationException() {
-	super();
-}
-/**
- * FailReconciliationException constructor comment.
- * @param s java.lang.String
- */
-public FailedReconciliationException(String s) {
-	super(s);
-}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/HandleFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/HandleFactory.java
deleted file mode 100644
index e1d47a7..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/HandleFactory.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.IClassFile;
-import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.core.index.impl.JarFileEntryDocument;
-
-/**
- * Creates java element handles.
- */
-public class HandleFactory {
-
-	/**
-	 * Cache package fragment root information to optimize speed performance.
-	 */
-	private String lastPkgFragmentRootPath;
-	private IPackageFragmentRoot lastPkgFragmentRoot;
-
-	/**
-	 * Cache package handles to optimize memory.
-	 */
-	private Map packageHandles;
-
-	private IWorkspace workspace;
-	private JavaModel javaModel;
-
-
-	public HandleFactory(IWorkspace workspace) {
-		this.workspace = workspace;
-		this.javaModel = JavaModelManager.getJavaModelManager().getJavaModel();
-	}
-	/**
-	 * Creates an Openable handle from the given resource path.
-	 * The resource path can be a path to a file in the workbench (eg. /Proj/com/ibm/jdt/core/HandleFactory.java)
-	 * or a path to a file in a jar file - it then contains the path to the jar file and the path to the file in the jar
-	 * (eg. c:/jdk1.2.2/jre/lib/rt.jar|java/lang/Object.class or /Proj/rt.jar|java/lang/Object.class)
-	 * NOTE: This assumes that the resource path is the toString() of an IPath, 
-	 *       in other words, it uses the IPath.SEPARATOR for file path
-	 *            and it uses '/' for entries in a zip file.
-	 * If not null, uses the given scope as a hint for getting Java project handles.
-	 */
-	public Openable createOpenable(String resourcePath, IJavaSearchScope scope) {
-		int separatorIndex;
-		if ((separatorIndex= resourcePath.indexOf(JarFileEntryDocument.JAR_FILE_ENTRY_SEPARATOR)) > -1) {
-			// path to a class file inside a jar
-			String jarPath= resourcePath.substring(0, separatorIndex);
-			// Optimization: cache package fragment root handle and package handles
-			if (!jarPath.equals(this.lastPkgFragmentRootPath)) {
-				IPackageFragmentRoot root= this.getJarPkgFragmentRoot(jarPath, scope);
-				if (root == null)
-					return null; // match is outside classpath
-				this.lastPkgFragmentRootPath= jarPath;
-				this.lastPkgFragmentRoot= root;
-				this.packageHandles= new HashMap(5);
-			}
-			// create handle
-			String classFilePath= resourcePath.substring(separatorIndex + 1);
-			int lastSlash= classFilePath.lastIndexOf('/');
-			String packageName= lastSlash > -1 ? classFilePath.substring(0, lastSlash).replace('/', '.') : IPackageFragment.DEFAULT_PACKAGE_NAME;
-			IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(packageName);
-			if (pkgFragment == null) {
-				pkgFragment= this.lastPkgFragmentRoot.getPackageFragment(packageName);
-				this.packageHandles.put(packageName, pkgFragment);
-			}
-			IClassFile classFile= pkgFragment.getClassFile(classFilePath.substring(lastSlash + 1));
-			return (Openable) classFile;
-		} else {
-			// path to a file in a directory
-			// Optimization: cache package fragment root handle and package handles
-			int length = -1;
-			if (this.lastPkgFragmentRootPath == null 
-				|| !(resourcePath.startsWith(this.lastPkgFragmentRootPath) 
-					&& (length = this.lastPkgFragmentRootPath.length()) > 0
-					&& resourcePath.charAt(length) == '/')) {
-				IPackageFragmentRoot root= this.getPkgFragmentRoot(resourcePath);
-				if (root == null)
-					return null; // match is outside classpath
-				this.lastPkgFragmentRoot= root;
-				this.lastPkgFragmentRootPath= this.lastPkgFragmentRoot.getPath().toString();
-				this.packageHandles= new HashMap(5);
-			}
-			// create handle
-			int lastSlash= resourcePath.lastIndexOf(IPath.SEPARATOR);
-			String packageName= lastSlash > (length= this.lastPkgFragmentRootPath.length()) ? resourcePath.substring(length + 1, lastSlash).replace(IPath.SEPARATOR, '.') : IPackageFragment.DEFAULT_PACKAGE_NAME;
-			IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(packageName);
-			if (pkgFragment == null) {
-				pkgFragment= this.lastPkgFragmentRoot.getPackageFragment(packageName);
-				this.packageHandles.put(packageName, pkgFragment);
-			}
-			String simpleName= resourcePath.substring(lastSlash + 1);
-			if (Util.isJavaFileName(simpleName)) {
-				ICompilationUnit unit= pkgFragment.getCompilationUnit(simpleName);
-				return (Openable) unit;
-			} else {
-				IClassFile classFile= pkgFragment.getClassFile(simpleName);
-				return (Openable) classFile;
-			}
-		}
-	}
-/**
-	 * Returns the package fragment root that corresponds to the given jar path.
-	 * See createOpenable(...) for the format of the jar path string.
-	 * If not null, uses the given scope as a hint for getting Java project handles.
-	 */
-	private IPackageFragmentRoot getJarPkgFragmentRoot(String jarPathString, IJavaSearchScope scope) {
-
-		IPath jarPath= new Path(jarPathString);
-		
-		Object target = JavaModel.getTarget(this.workspace.getRoot(), jarPath, false);
-		if (target instanceof IFile) {
-			// internal jar: is it on the classpath of its project?
-			//  e.g. org.eclipse.swt.win32/ws/win32/swt.jar 
-			//        is NOT on the classpath of org.eclipse.swt.win32
-			IFile jarFile = (IFile)target;
-			IJavaProject javaProject = this.javaModel.getJavaProject(jarFile);
-			IClasspathEntry[] classpathEntries;
-			try {
-				classpathEntries = javaProject.getResolvedClasspath(true);
-				for (int j= 0, entryCount= classpathEntries.length; j < entryCount; j++) {
-					if (classpathEntries[j].getPath().equals(jarPath)) {
-						return javaProject.getPackageFragmentRoot(jarFile);
-					}
-				}
-			} catch (JavaModelException e) {
-				// ignore and try to find another project
-			}
-		}
-		
-		// walk projects in the scope and find the first one that has the given jar path in its classpath
-		IJavaProject[] projects;
-		if (scope != null) {
-			IPath[] enclosingProjectsAndJars = scope.enclosingProjectsAndJars();
-			int length = enclosingProjectsAndJars.length;
-			projects = new IJavaProject[length];
-			int index = 0;
-			for (int i = 0; i < length; i++) {
-				IPath path = enclosingProjectsAndJars[i];
-				if (!Util.isArchiveFileName(path.lastSegment())) {
-					projects[index++] = this.javaModel.getJavaProject(path.segment(0));
-				}
-			}
-			if (index < length) {
-				System.arraycopy(projects, 0, projects = new IJavaProject[index], 0, index);
-			}
-			IPackageFragmentRoot root = getJarPkgFragmentRoot(jarPath, target, projects);
-			if (root != null) {
-				return root;
-			}
-		} 
-		
-		// not found in the scope, walk all projects
-		try {
-			projects = this.javaModel.getJavaProjects();
-		} catch (JavaModelException e) {
-			// java model is not accessible
-			return null;
-		}
-		return getJarPkgFragmentRoot(jarPath, target, projects);
-	}
-	private IPackageFragmentRoot getJarPkgFragmentRoot(
-		IPath jarPath,
-		Object target,
-		IJavaProject[] projects) {
-		for (int i= 0, projectCount= projects.length; i < projectCount; i++) {
-			try {
-				JavaProject javaProject= (JavaProject)projects[i];
-				IClasspathEntry[] classpathEntries= javaProject.getResolvedClasspath(true);
-				for (int j= 0, entryCount= classpathEntries.length; j < entryCount; j++) {
-					if (classpathEntries[j].getPath().equals(jarPath)) {
-						if (target instanceof IFile) {
-							// internal jar
-							return javaProject.getPackageFragmentRoot((IFile)target);
-						} else {
-							// external jar
-							return javaProject.getPackageFragmentRoot0(jarPath);
-						}
-					}
-				}
-			} catch (JavaModelException e) {
-				// JavaModelException from getResolvedClasspath - a problem occured while accessing project: nothing we can do, ignore
-			}
-		}
-		return null;
-	}
-/**
-	 * Returns the package fragment root that contains the given resource path.
-	 */
-	private IPackageFragmentRoot getPkgFragmentRoot(String pathString) {
-
-		IPath path= new Path(pathString);
-		IProject[] projects= this.workspace.getRoot().getProjects();
-		for (int i= 0, max= projects.length; i < max; i++) {
-			try {
-				IProject project = projects[i];
-				if (!project.isAccessible() 
-					|| !project.hasNature(JavaCore.NATURE_ID)) continue;
-				IJavaProject javaProject= this.javaModel.getJavaProject(project);
-				IPackageFragmentRoot[] roots= javaProject.getPackageFragmentRoots();
-				for (int j= 0, rootCount= roots.length; j < rootCount; j++) {
-					PackageFragmentRoot root= (PackageFragmentRoot)roots[j];
-					if (root.getPath().isPrefixOf(path) && !Util.isExcluded(path, root.fullExclusionPatternChars())) {
-						return root;
-					}
-				}
-			} catch (CoreException e) {
-				// CoreException from hasNature - should not happen since we check that the project is accessible
-				// JavaModelException from getPackageFragmentRoots - a problem occured while accessing project: nothing we can do, ignore
-			}
-		}
-		return null;
-	}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IPathRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IPathRequestor.java
index a1c777b..1eaab30 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IPathRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/IPathRequestor.java
@@ -11,5 +11,5 @@
 package org.eclipse.jdt.internal.core;
 
 public interface IPathRequestor {
-	void acceptPath(String path);
+	void acceptPath(String path, boolean containsLocalTypes);
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportContainer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportContainer.java
index a75352a..3560647 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportContainer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportContainer.java
@@ -10,7 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import org.eclipse.jdt.core.ICompilationUnit;
+import java.util.StringTokenizer;
+
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IImportContainer;
 import org.eclipse.jdt.core.IImportDeclaration;
 import org.eclipse.jdt.core.IJavaElement;
@@ -22,27 +24,56 @@
  * @see IImportContainer
  */
 public class ImportContainer extends SourceRefElement implements IImportContainer {
-protected ImportContainer(ICompilationUnit parent) {
-	super(IMPORT_CONTAINER, parent, ""); //$NON-NLS-1$
+protected ImportContainer(CompilationUnit parent) {
+	super(parent, ""); //$NON-NLS-1$
+}
+public boolean equals(Object o) {
+	if (!(o instanceof ImportContainer)) return false;
+	return super.equals(o);
 }
 /**
- * @see JavaElement#getHandleMemento()
+ * @see IJavaElement
  */
-public String getHandleMemento(){
-	return ((JavaElement)getParent()).getHandleMemento();
+public int getElementType() {
+	return IMPORT_CONTAINER;
+}
+/*
+ * @see JavaElement
+ */
+public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner workingCopyOwner) {
+	switch (token.charAt(0)) {
+		case JEM_COUNT:
+			return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
+		case JEM_IMPORTDECLARATION:
+			if (memento.hasMoreTokens()) {
+				String importName = memento.nextToken();
+				JavaElement importDecl = (JavaElement)getImport(importName);
+				return importDecl.getHandleFromMemento(memento, workingCopyOwner);
+			} else {
+				return this;
+			}
+	}
+	return null;
 }
 /**
  * @see JavaElement#getHandleMemento()
  */
 protected char getHandleMementoDelimiter() {
-	Assert.isTrue(false, "Should not be called"); //$NON-NLS-1$
-	return 0;
+	return JavaElement.JEM_IMPORTDECLARATION;
 }
 /**
  * @see IImportContainer
  */
-public IImportDeclaration getImport(String name) {
-	return new ImportDeclaration(this, name);
+public IImportDeclaration getImport(String importName) {
+	return new ImportDeclaration(this, importName);
+}
+/*
+ * @see JavaElement#getPrimaryElement(boolean)
+ */
+public IJavaElement getPrimaryElement(boolean checkOwner) {
+	CompilationUnit cu = (CompilationUnit)this.parent;
+	if (checkOwner && cu.isPrimary()) return this;
+	return cu.getImportContainer();
 }
 /**
  * @see ISourceReference
@@ -58,7 +89,7 @@
  * Import containers only exist if they have children.
  * @see IParent
  */
-public boolean hasChildren() throws JavaModelException {
+public boolean hasChildren() {
 	return true;
 }
 /**
@@ -84,7 +115,7 @@
  */
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
 	buffer.append(this.tabString(tab));
-	buffer.append("[import container]"); //$NON-NLS-1$
+	buffer.append("<import container>"); //$NON-NLS-1$
 	if (info == null) {
 		buffer.append(" (not open)"); //$NON-NLS-1$
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java
index 068c2cb..ac604dc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclaration.java
@@ -10,12 +10,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import org.eclipse.jdt.core.IImportContainer;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IImportDeclaration;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.jdom.IDOMNode;
 
 /**
+ * Handle for an import declaration. Info object is a ImportDeclarationElementInfo.
  * @see IImportDeclaration
  */
 
@@ -23,29 +24,69 @@
 
 
 /**
- * Constructs an ImportDeclartaion in the given import container
+ * Constructs an ImportDeclaration in the given import container
  * with the given name.
  */
-protected ImportDeclaration(IImportContainer parent, String name) {
-	super(IMPORT_DECLARATION, parent, name);
+protected ImportDeclaration(ImportContainer parent, String name) {
+	super(parent, name);
+}
+public boolean equals(Object o) {
+	if (!(o instanceof ImportDeclaration)) return false;
+	return super.equals(o);
 }
 /**
  * @see JavaElement#equalsDOMNode
  */
-protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
+protected boolean equalsDOMNode(IDOMNode node) {
 	return (node.getNodeType() == IDOMNode.IMPORT) && getElementName().equals(node.getName());
 }
 /**
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return IMPORT_DECLARATION;
+}
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.core.IImportDeclaration#getFlags()
+ */
+public int getFlags() throws JavaModelException {
+	ImportDeclarationElementInfo info = (ImportDeclarationElementInfo)getElementInfo();
+	return info.getModifiers();
+}
+/**
+ * @see JavaElement#getHandleMemento()
+ * For import declarations, the handle delimiter is associated to the import container already
+ */
+public String getHandleMemento(){
+	StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
+	buff.append(getElementName());
+	if (this.occurrenceCount > 1) {
+		buff.append(JEM_COUNT);
+		buff.append(this.occurrenceCount);
+	}
+	return buff.toString();
+}
+/**
  * @see JavaElement#getHandleMemento()
  */
 protected char getHandleMementoDelimiter() {
-	return JavaElement.JEM_IMPORTDECLARATION;
+	// For import declarations, the handle delimiter is associated to the import container already
+	Assert.isTrue(false, "Should not be called"); //$NON-NLS-1$
+	return 0;
+}
+/*
+ * @see JavaElement#getPrimaryElement(boolean)
+ */
+public IJavaElement getPrimaryElement(boolean checkOwner) {
+	CompilationUnit cu = (CompilationUnit)this.parent.getParent();
+	if (checkOwner && cu.isPrimary()) return this;
+	return cu.getImport(this.name);
 }
 /**
  * Returns true if the import is on-demand (ends with ".*")
  */
 public boolean isOnDemand() {
-	return fName.endsWith(".*"); //$NON-NLS-1$
+	return this.name.endsWith(".*"); //$NON-NLS-1$
 }
 /**
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclarationElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclarationElementInfo.java
new file mode 100644
index 0000000..be3b883
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ImportDeclarationElementInfo.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.internal.compiler.env.ISourceImport;
+
+/**
+ * Element info for IImportDeclaration elements.
+ * @see IImportDeclaration
+ */
+public class ImportDeclarationElementInfo extends MemberElementInfo implements ISourceImport{
+	
+	// record if import is on demand, the import name doesn't have trailing start
+	boolean onDemand;
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.env.ISourceImport#onDemand()
+	 */
+	public boolean onDemand() {
+		return this.onDemand;
+	}
+
+	public void setOnDemand(boolean onDemand) {
+		this.onDemand = onDemand;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Initializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Initializer.java
index 6a327ad..61aeee9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Initializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Initializer.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.core;
 
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IInitializer;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
@@ -18,6 +19,7 @@
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.jdom.IDOMNode;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * @see IInitializer
@@ -25,30 +27,44 @@
 
 /* package */ class Initializer extends Member implements IInitializer {
 
-protected Initializer(IType parent, int occurrenceCount) {
-	super(INITIALIZER, parent, ""); //$NON-NLS-1$
+protected Initializer(JavaElement parent, int count) {
+	super(parent, ""); //$NON-NLS-1$
 	// 0 is not valid: this first occurrence is occurrence 1.
-	if (occurrenceCount <= 0)
+	if (count <= 0)
 		throw new IllegalArgumentException();
-	fOccurrenceCount = occurrenceCount;
+	this.occurrenceCount = count;
+}
+public boolean equals(Object o) {
+	if (!(o instanceof Initializer)) return false;
+	return super.equals(o);
 }
 /**
  * @see JavaElement#equalsDOMNode
  */
-protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
+protected boolean equalsDOMNode(IDOMNode node) {
 	if (node.getNodeType() == IDOMNode.INITIALIZER) {
-		return node.getContents().trim().equals(getSource());
+		try {
+			return node.getContents().trim().equals(getSource());
+		} catch (JavaModelException e) {
+			return false;
+		}
 	} else {
 		return false;
 	}
 }
 /**
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return INITIALIZER;
+}
+/**
  * @see JavaElement#getHandleMemento()
  */
 public String getHandleMemento(){
 	StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
 	buff.append(getHandleMementoDelimiter());
-	buff.append(fOccurrenceCount);
+	buff.append(this.occurrenceCount);
 	return buff.toString();
 }
 /**
@@ -58,7 +74,7 @@
 	return JavaElement.JEM_INITIALIZER;
 }
 public int hashCode() {
-	return Util.combineHashCodes(fParent.hashCode(), fOccurrenceCount);
+	return Util.combineHashCodes(this.parent.hashCode(), this.occurrenceCount);
 }
 /**
  */
@@ -69,31 +85,48 @@
 /**
  * @see ISourceManipulation
  */
-public void rename(String name, boolean force, IProgressMonitor monitor) throws JavaModelException {
+public void rename(String newName, boolean force, IProgressMonitor monitor) throws JavaModelException {
 	throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, this));
 }
 /**
  * @see IMember
  */
-public ISourceRange getNameRange() throws JavaModelException {
+public ISourceRange getNameRange() {
 	return null;
 }
+/*
+ * @see JavaElement#getPrimaryElement(boolean)
+ */
+public IJavaElement getPrimaryElement(boolean checkOwner) {
+	if (checkOwner) {
+		CompilationUnit cu = (CompilationUnit)getAncestor(COMPILATION_UNIT);
+		if (cu == null || cu.isPrimary()) return this;
+	}
+	IJavaElement primaryParent = this.parent.getPrimaryElement(false);
+	return ((IType)primaryParent).getInitializer(this.occurrenceCount);
+}
 /**
  * @private Debugging purposes
  */
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
 	buffer.append(this.tabString(tab));
 	if (info == null) {
-		buffer.append("<initializer>"); //$NON-NLS-1$
-		buffer.append(" (not open)"); //$NON-NLS-1$
+		buffer.append("<initializer #"); //$NON-NLS-1$
+		buffer.append(this.occurrenceCount);
+		buffer.append("> (not open)"); //$NON-NLS-1$
 	} else if (info == NO_INFO) {
-		buffer.append(getElementName());
+		buffer.append("<initializer #"); //$NON-NLS-1$
+		buffer.append(this.occurrenceCount);
+		buffer.append(">"); //$NON-NLS-1$
 	} else {
 		try {
+			buffer.append("<"); //$NON-NLS-1$
 			if (Flags.isStatic(this.getFlags())) {
 				buffer.append("static "); //$NON-NLS-1$
 			}
-			buffer.append("initializer"); //$NON-NLS-1$
+		buffer.append("initializer #"); //$NON-NLS-1$
+		buffer.append(this.occurrenceCount);
+		buffer.append(">"); //$NON-NLS-1$
 		} catch (JavaModelException e) {
 			buffer.append("<JavaModelException in toString of " + getElementName()); //$NON-NLS-1$
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InitializerElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InitializerElementInfo.java
index 9b5ef51..bb05101 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InitializerElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InitializerElementInfo.java
@@ -13,5 +13,6 @@
 /** 
  * Element info for IInitializer elements. 
  */
-/* package */ class InitializerElementInfo extends MemberElementInfo {
+public class InitializerElementInfo extends MemberElementInfo {
+	// used only as a marker class: contains no methods
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java
index 17ea5fc..47c5a7b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/InternalNamingConventions.java
@@ -31,7 +31,7 @@
 				false /*comment*/, 
 				false /*whitespace*/, 
 				false /*nls*/, 
-				compilerOptions.sourceLevel >= CompilerOptions.JDK1_4 /*assert*/, 
+				compilerOptions.sourceLevel /*sourceLevel*/, 
 				null /*taskTags*/, 
 				null/*taskPriorities*/);
 	}
@@ -135,6 +135,7 @@
 					break;
 			}	
 		} catch(InvalidInputException e){
+			// ignore
 		}
 
 		// compute variable name for non base type
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java
index ea7a551..4054f55 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragment.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.core;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.Iterator;
 
 import org.eclipse.core.resources.IResource;
@@ -19,20 +20,19 @@
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 
 /**
  * A package fragment that represents a package fragment found in a JAR.
  *
  * @see IPackageFragment
  */
-class JarPackageFragment extends PackageFragment {
+class JarPackageFragment extends PackageFragment implements SuffixConstants {
 /**
  * Constructs a package fragment that is contained within a jar or a zip.
  */
-protected JarPackageFragment(IPackageFragmentRoot root, String name) {
+protected JarPackageFragment(PackageFragmentRoot root, String name) {
 	super(root, name);
 }
 /**
@@ -41,9 +41,9 @@
  */
 protected boolean computeChildren(OpenableElementInfo info) {
 	JarPackageFragmentInfo jInfo= (JarPackageFragmentInfo)info;
-	if (jInfo.fEntryNames != null){
+	if (jInfo.entryNames != null){
 		ArrayList vChildren = new ArrayList();
-		for (Iterator iter = jInfo.fEntryNames.iterator(); iter.hasNext();) {
+		for (Iterator iter = jInfo.entryNames.iterator(); iter.hasNext();) {
 			String child = (String) iter.next();
 			IClassFile classFile = getClassFile(child);
 			vChildren.add(classFile);
@@ -52,7 +52,7 @@
 		vChildren.toArray(children);
 		info.setChildren(children);
 	} else {
-		info.setChildren(JavaElementInfo.fgEmptyChildren);
+		info.setChildren(NO_ELEMENTS);
 	}
 	return true;
 }
@@ -70,7 +70,7 @@
 	for (int i = 0; i < max; i++) {
 		String resName = resNames[i];
 		// consider that a .java file is not a non-java resource (see bug 12246 Packages view shows .class and .java files when JAR has source)
-		if (!resName.toLowerCase().endsWith(".java")) { //$NON-NLS-1$
+		if (!resName.toLowerCase().endsWith(SUFFIX_STRING_java)) {
 			if (!this.isDefaultPackage()) {
 				resName = this.getElementName().replace('.', '/') + "/" + resName;//$NON-NLS-1$
 			}
@@ -92,14 +92,24 @@
 /**
  * @see IPackageFragment
  */
-public ICompilationUnit createCompilationUnit(String name, String contents, boolean force, IProgressMonitor monitor) throws JavaModelException {
+public ICompilationUnit createCompilationUnit(String cuName, String contents, boolean force, IProgressMonitor monitor) throws JavaModelException {
 	throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
 }
 /**
  * @see JavaElement
  */
-protected OpenableElementInfo createElementInfo() {
-	return new JarPackageFragmentInfo();
+protected Object createElementInfo() {
+	return null; // not used for JarPackageFragments: info is created when jar is opened
+}
+/*
+ * @see JavaElement#generateInfos
+ */
+protected void generateInfos(Object info, HashMap newElements, IProgressMonitor pm) throws JavaModelException {
+	// Open my jar: this creates all the pkg infos
+	Openable openableParent = (Openable)this.parent;
+	if (!openableParent.isOpen()) {
+		openableParent.generateInfos(openableParent.createElementInfo(), newElements, pm);
+	}
 }
 /**
  * @see IPackageFragment
@@ -114,15 +124,15 @@
  * A jar package fragment never contains compilation units.
  * @see IPackageFragment
  */
-public ICompilationUnit[] getCompilationUnits() throws JavaModelException {
-	return fgEmptyCompilationUnitList;
+public ICompilationUnit[] getCompilationUnits() {
+	return NO_COMPILATION_UNITS;
 }
 /**
  * A package fragment in a jar has no corresponding resource.
  *
  * @see IJavaElement
  */
-public IResource getCorrespondingResource() throws JavaModelException {
+public IResource getCorrespondingResource() {
 	return null;
 }
 /**
@@ -142,28 +152,6 @@
 public boolean isReadOnly() {
 	return true;
 }
-/**
- * @see Openable#openWhenClosed()
- */
-protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
-	// Open my jar
-	getOpenableParent().open(pm);
-}
-/**
- * A package fragment in an archive cannot refresh its children.
- */
-public void refreshChildren() {
-	// do nothing
-}
-/*
- * @see JavaElement#rootedAt(IJavaProject)
- */
-public IJavaElement rootedAt(IJavaProject project) {
-	return
-		new JarPackageFragment(
-			(IPackageFragmentRoot)((JavaElement)fParent).rootedAt(project), 
-			fName);
-}
 protected Object[] storedNonJavaResources() throws JavaModelException {
 	return ((JarPackageFragmentInfo) getElementInfo()).getNonJavaResources();
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentInfo.java
index 5d8235b..2a171ed 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentInfo.java
@@ -22,23 +22,23 @@
 	 * The names of the zip entries that are the class files associated
 	 * with this package fragment info in the JAR file of the JarPackageFragmentRootInfo.
 	 */
-	protected ArrayList fEntryNames;
+	protected ArrayList entryNames;
 /**
  */
 boolean containsJavaResources() {
-	return fEntryNames != null && fEntryNames.size() != 0;
+	return this.entryNames != null && this.entryNames.size() != 0;
 }
 /**
  * Returns an array of non-java resources contained in the receiver.
  */
 Object[] getNonJavaResources() {
-	return fNonJavaResources;
+	return this.nonJavaResources;
 }
 /**
  * Set the names of the zip entries that are the types associated
  * with this package fragment info in the JAR file of the JarPackageFragmentRootInfo.
  */
 protected void setEntryNames(ArrayList entries) {
-	fEntryNames = entries;
+	this.entryNames = entries;
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
index 35db42b..3ce52cb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
@@ -47,7 +47,7 @@
 	 * based on a JAR file that is not contained in a <code>IJavaProject</code> and
 	 * does not have an associated <code>IResource</code>.
 	 */
-	protected JarPackageFragmentRoot(IPath jarPath, IJavaProject project) {
+	protected JarPackageFragmentRoot(IPath jarPath, JavaProject project) {
 		super(null, project, jarPath.lastSegment());
 		this.jarPath = jarPath;
 	}
@@ -55,7 +55,7 @@
 	 * Constructs a package fragment root which is the root of the Java package directory hierarchy 
 	 * based on a JAR file.
 	 */
-	protected JarPackageFragmentRoot(IResource resource, IJavaProject project) {
+	protected JarPackageFragmentRoot(IResource resource, JavaProject project) {
 		super(resource, project, resource.getName());
 		this.jarPath = resource.getFullPath();
 	}
@@ -66,134 +66,123 @@
 	 * by the path of class files contained in the jar of this package fragment root.
 	 * Has the side effect of opening the package fragment children.
 	 */
-	protected boolean computeChildren(OpenableElementInfo info) throws JavaModelException {
+	protected boolean computeChildren(OpenableElementInfo info, Map newElements) throws JavaModelException {
+		
 		ArrayList vChildren= new ArrayList();
-		computeJarChildren((JarPackageFragmentRootInfo) info, vChildren);
+		final int JAVA = 0;
+		final int NON_JAVA = 1;
+		ZipFile jar= null;
+		try {
+			jar= getJar();
+	
+			HashMap packageFragToTypes= new HashMap();
+	
+			// always create the default package
+			packageFragToTypes.put(IPackageFragment.DEFAULT_PACKAGE_NAME, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
+	
+			for (Enumeration e= jar.entries(); e.hasMoreElements();) {
+				ZipEntry member= (ZipEntry) e.nextElement();
+				String entryName= member.getName();
+	
+				if (member.isDirectory()) {
+					
+					int last = entryName.length() - 1;
+					entryName= entryName.substring(0, last);
+					entryName= entryName.replace('/', '.');
+	
+					// add the package name & all of its parent packages
+					while (true) {
+						// extract the package name
+						if (packageFragToTypes.containsKey(entryName)) break;
+						packageFragToTypes.put(entryName, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
+						
+						if ((last = entryName.lastIndexOf('.')) < 0) break;
+						entryName = entryName.substring(0, last);
+					}
+				} else {
+					//store the class file / non-java rsc entry name to be cached in the appropriate package fragment
+					//zip entries only use '/'
+					int lastSeparator= entryName.lastIndexOf('/');
+					String packageName;
+					String fileName;
+					if (lastSeparator != -1) { //not in the default package
+						entryName= entryName.replace('/', '.');
+						fileName= entryName.substring(lastSeparator + 1);
+						packageName= entryName.substring(0, lastSeparator);
+					} else {
+						fileName = entryName;
+						packageName =  IPackageFragment.DEFAULT_PACKAGE_NAME;
+					}
+					
+					// add the package name & all of its parent packages
+					String currentPackageName = packageName;
+					while (true) {
+						// extract the package name
+						if (packageFragToTypes.containsKey(currentPackageName)) break;
+						packageFragToTypes.put(currentPackageName, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
+						
+						int last;
+						if ((last = currentPackageName.lastIndexOf('.')) < 0) break;
+						currentPackageName = currentPackageName.substring(0, last);
+					}
+					// add classfile info amongst children
+					ArrayList[] children = (ArrayList[]) packageFragToTypes.get(packageName);
+					if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
+						if (children[JAVA] == EMPTY_LIST) children[JAVA] = new ArrayList();
+						children[JAVA].add(fileName);
+					} else {
+						if (children[NON_JAVA] == EMPTY_LIST) children[NON_JAVA] = new ArrayList();
+						children[NON_JAVA].add(fileName);
+					}
+				}
+			}
+			//loop through all of referenced packages, creating package fragments if necessary
+			// and cache the entry names in the infos created for those package fragments
+			Iterator packages = packageFragToTypes.keySet().iterator();
+			while (packages.hasNext()) {
+				String packName = (String) packages.next();
+				
+				ArrayList[] entries= (ArrayList[]) packageFragToTypes.get(packName);
+				JarPackageFragment packFrag= (JarPackageFragment) getPackageFragment(packName);
+				JarPackageFragmentInfo fragInfo= new JarPackageFragmentInfo();
+				if (entries[0].size() > 0){
+					fragInfo.setEntryNames(entries[JAVA]);
+				}
+				int resLength= entries[NON_JAVA].size();
+				if (resLength == 0) {
+					packFrag.computeNonJavaResources(NO_STRINGS, fragInfo, jar.getName());
+				} else {
+					String[] resNames= new String[resLength];
+					entries[NON_JAVA].toArray(resNames);
+					packFrag.computeNonJavaResources(resNames, fragInfo, jar.getName());
+				}
+				packFrag.computeChildren(fragInfo);
+				newElements.put(packFrag, fragInfo);
+				vChildren.add(packFrag);
+			}
+		} catch (CoreException e) {
+			if (e instanceof JavaModelException) throw (JavaModelException)e;
+			throw new JavaModelException(e);
+		} finally {
+			JavaModelManager.getJavaModelManager().closeZipFile(jar);
+		}
+
+
 		IJavaElement[] children= new IJavaElement[vChildren.size()];
 		vChildren.toArray(children);
 		info.setChildren(children);
 		return true;
 	}
 /**
- * Determine all of the package fragments associated with this package fragment root.
- * Cache the zip entries for each package fragment in the info for the package fragment.
- * The package fragment children are all opened.
- * Add all of the package fragments to vChildren.
- *
- * @exception JavaModelException The resource (the jar) associated with this package fragment root does not exist
- */
-protected void computeJarChildren(JarPackageFragmentRootInfo info, ArrayList vChildren) throws JavaModelException {
-	final int JAVA = 0;
-	final int NON_JAVA = 1;
-	ZipFile jar= null;
-	try {
-		jar= getJar();
-
-		HashMap packageFragToTypes= new HashMap();
-
-		// always create the default package
-		packageFragToTypes.put(IPackageFragment.DEFAULT_PACKAGE_NAME, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
-
-		for (Enumeration e= jar.entries(); e.hasMoreElements();) {
-			ZipEntry member= (ZipEntry) e.nextElement();
-			String entryName= member.getName();
-
-			if (member.isDirectory()) {
-				
-				int last = entryName.length() - 1;
-				entryName= entryName.substring(0, last);
-				entryName= entryName.replace('/', '.');
-
-				// add the package name & all of its parent packages
-				while (true) {
-					// extract the package name
-					if (packageFragToTypes.containsKey(entryName)) break;
-					packageFragToTypes.put(entryName, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
-					
-					if ((last = entryName.lastIndexOf('.')) < 0) break;
-					entryName = entryName.substring(0, last);
-				}
-			} else {
-				//store the class file / non-java rsc entry name to be cached in the appropriate package fragment
-				//zip entries only use '/'
-				int lastSeparator= entryName.lastIndexOf('/');
-				String packageName;
-				String fileName;
-				if (lastSeparator != -1) { //not in the default package
-					entryName= entryName.replace('/', '.');
-					fileName= entryName.substring(lastSeparator + 1);
-					packageName= entryName.substring(0, lastSeparator);
-				} else {
-					fileName = entryName;
-					packageName =  IPackageFragment.DEFAULT_PACKAGE_NAME;
-				}
-				
-				// add the package name & all of its parent packages
-				String currentPackageName = packageName;
-				while (true) {
-					// extract the package name
-					if (packageFragToTypes.containsKey(currentPackageName)) break;
-					packageFragToTypes.put(currentPackageName, new ArrayList[] { EMPTY_LIST, EMPTY_LIST });
-					
-					int last;
-					if ((last = currentPackageName.lastIndexOf('.')) < 0) break;
-					currentPackageName = currentPackageName.substring(0, last);
-				}
-				// add classfile info amongst children
-				ArrayList[] children = (ArrayList[]) packageFragToTypes.get(packageName);
-				if (Util.isClassFileName(entryName)) {
-					if (children[JAVA] == EMPTY_LIST) children[JAVA] = new ArrayList();
-					children[JAVA].add(fileName);
-				} else {
-					if (children[NON_JAVA] == EMPTY_LIST) children[NON_JAVA] = new ArrayList();
-					children[NON_JAVA].add(fileName);
-				}
-			}
-		}
-		//loop through all of referenced packages, creating package fragments if necessary
-		// and cache the entry names in the infos created for those package fragments
-		Iterator packages = packageFragToTypes.keySet().iterator();
-		while (packages.hasNext()) {
-			String packName = (String) packages.next();
-			
-			ArrayList[] entries= (ArrayList[]) packageFragToTypes.get(packName);
-			JarPackageFragment packFrag= (JarPackageFragment) getPackageFragment(packName);
-			JarPackageFragmentInfo fragInfo= (JarPackageFragmentInfo) packFrag.createElementInfo();
-			if (entries[0].size() > 0){
-				fragInfo.setEntryNames(entries[JAVA]);
-			}
-			int resLength= entries[NON_JAVA].size();
-			if (resLength == 0) {
-				packFrag.computeNonJavaResources(NO_STRINGS, fragInfo, jar.getName());
-			} else {
-				String[] resNames= new String[resLength];
-				entries[NON_JAVA].toArray(resNames);
-				packFrag.computeNonJavaResources(resNames, fragInfo, jar.getName());
-			}
-			packFrag.computeChildren(fragInfo);
-			JavaModelManager.getJavaModelManager().putInfo(packFrag, fragInfo);
-			vChildren.add(packFrag);
-		}
-	} catch (CoreException e) {
-		if (e instanceof JavaModelException) throw (JavaModelException)e;
-		throw new JavaModelException(e);
-	} finally {
-		JavaModelManager.getJavaModelManager().closeZipFile(jar);
-	}
-}
-	/**
 	 * Returns a new element info for this element.
 	 */
-	protected OpenableElementInfo createElementInfo() {
+	protected Object createElementInfo() {
 		return new JarPackageFragmentRootInfo();
 	}
 	/**
 	 * A Jar is always K_BINARY.
-	 *
-	 * @exception NotPresentException if the project and root do
-	 *      not exist.
 	 */
-	protected int determineKind(IResource underlyingResource) throws JavaModelException {
+	protected int determineKind(IResource underlyingResource) {
 		return IPackageFragmentRoot.K_BINARY;
 	}
 	/**
@@ -309,12 +298,6 @@
 	}
 
 	/**
-	 * An archive cannot refresh its children.
-	 */
-	public void refreshChildren() {
-		// do nothing
-	}
-/**
  * Returns whether the corresponding resource or associated file exists
  */
 protected boolean resourceExists() {
@@ -328,20 +311,4 @@
 		return super.resourceExists();
 	}
 }
-/*
- * @see JavaElement#rootedAt(IJavaProject)
- */
-public IJavaElement rootedAt(IJavaProject project) {
-	if (isExternal()) {
-		return
-			new JarPackageFragmentRoot(
-				this.jarPath,
-				project);
-	} else {
-		return
-			new JarPackageFragmentRoot(
-				getResource(),
-				project);
-	}
-}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
index 0fbfbdd..9e1a8a0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
@@ -10,7 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.util.*;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
 
 import org.eclipse.core.resources.IResourceStatus;
 import org.eclipse.core.resources.ResourcesPlugin;
@@ -18,6 +21,7 @@
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.jdom.IDOMCompilationUnit;
 import org.eclipse.jdt.core.jdom.IDOMNode;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Root of Java element handle hierarchy.
@@ -26,17 +30,19 @@
  */
 public abstract class JavaElement extends PlatformObject implements IJavaElement {
 
-	public static final char JEM_JAVAPROJECT= '=';
-	public static final char JEM_PACKAGEFRAGMENTROOT= Path.SEPARATOR;
-	public static final char JEM_PACKAGEFRAGMENT= '<';
-	public static final char JEM_FIELD= '^';
-	public static final char JEM_METHOD= '~';
-	public static final char JEM_INITIALIZER= '|';
-	public static final char JEM_COMPILATIONUNIT= '{';
-	public static final char JEM_CLASSFILE= '(';
-	public static final char JEM_TYPE= '[';
-	public static final char JEM_PACKAGEDECLARATION= '%';
-	public static final char JEM_IMPORTDECLARATION= '#';
+	public static final char JEM_JAVAPROJECT = '=';
+	public static final char JEM_PACKAGEFRAGMENTROOT = IPath.SEPARATOR;
+	public static final char JEM_PACKAGEFRAGMENT = '<';
+	public static final char JEM_FIELD = '^';
+	public static final char JEM_METHOD = '~';
+	public static final char JEM_INITIALIZER = '|';
+	public static final char JEM_COMPILATIONUNIT = '{';
+	public static final char JEM_CLASSFILE = '(';
+	public static final char JEM_TYPE = '[';
+	public static final char JEM_PACKAGEDECLARATION = '%';
+	public static final char JEM_IMPORTDECLARATION = '#';
+	public static final char JEM_COUNT = '!';
+	public static final char JEM_LOCALVARIABLE = '@';
 
 	/**
 	 * A count to uniquely identify this element in the case
@@ -46,31 +52,25 @@
 	 * them.  The occurrence count starts at 1 (thus the first 
 	 * occurrence is occurrence 1, not occurrence 0).
 	 */
-	protected int fOccurrenceCount = 1;
-
-
-	/**
-	 * This element's type - one of the constants defined
-	 * in IJavaLanguageElementTypes.
-	 */
-	protected int fLEType = 0;
+	public int occurrenceCount = 1;
 
 	/**
 	 * This element's parent, or <code>null</code> if this
 	 * element does not have a parent.
 	 */
-	protected IJavaElement fParent;
+	protected JavaElement parent;
 
 	/**
 	 * This element's name, or an empty <code>String</code> if this
 	 * element does not have a name.
 	 */
-	protected String fName;
+	protected String name;
 
+	protected static final JavaElement[] NO_ELEMENTS = new JavaElement[0];
 	protected static final Object NO_INFO = new Object();
 	
 	/**
-	 * Constructs a handle for a java element of the specified type, with
+	 * Constructs a handle for a java element with
 	 * the given parent element and name.
 	 *
 	 * @param type - one of the constants defined in IJavaLanguageElement
@@ -79,50 +79,24 @@
 	 *		Java element type constants
 	 *
 	 */
-	protected JavaElement(int type, IJavaElement parent, String name) throws IllegalArgumentException {
-		if (type < JAVA_MODEL || type > IMPORT_DECLARATION) {
-			throw new IllegalArgumentException(Util.bind("element.invalidType")); //$NON-NLS-1$
-		}
-		fLEType= type;
-		fParent= parent;
-		fName= name;
+	protected JavaElement(JavaElement parent, String name) throws IllegalArgumentException {
+		this.parent = parent;
+		this.name = name;
 	}
 	/**
 	 * @see IOpenable
 	 */
 	public void close() throws JavaModelException {
-		Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this);
-		if (info != null) {
-			boolean wasVerbose = false;
-			try {
-				if (JavaModelManager.VERBOSE) {
-					System.out.println("CLOSING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors());  //$NON-NLS-1$//$NON-NLS-2$
-					wasVerbose = true;
-					JavaModelManager.VERBOSE = false;
-				}
-				if (this instanceof IParent) {
-					IJavaElement[] children = ((JavaElementInfo) info).getChildren();
-					for (int i = 0, size = children.length; i < size; ++i) {
-						JavaElement child = (JavaElement) children[i];
-						child.close();
-					}
-				}
-				closing(info);
-				JavaModelManager.getJavaModelManager().removeInfo(this);
-				if (wasVerbose) {
-					System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
-					System.out.println("-> Openable cache filling ratio = " + JavaModelManager.getJavaModelManager().cache.openableFillingRatio() + "%"); //$NON-NLS-1$//$NON-NLS-2$
-				}
-			} finally {
-				JavaModelManager.VERBOSE = wasVerbose;
-			}
-		}
+		JavaModelManager.getJavaModelManager().removeInfoAndChildren(this);
 	}
 	/**
 	 * This element is being closed.  Do any necessary cleanup.
 	 */
-	protected void closing(Object info) throws JavaModelException {
-	}
+	protected abstract void closing(Object info) throws JavaModelException;
+	/*
+	 * Returns a new element info for this element.
+	 */
+	protected abstract Object createElementInfo();
 	/**
 	 * Returns true if this handle represents the same Java element
 	 * as the given handle. By default, two handles represent the same
@@ -139,23 +113,19 @@
 		if (this == o) return true;
 	
 		// Java model parent is null
-		if (fParent == null) return super.equals(o);
+		if (this.parent == null) return super.equals(o);
 	
-		if (o instanceof JavaElement) {
-			JavaElement other = (JavaElement) o;
-			if (fLEType != other.fLEType) return false;
-			
-			return fName.equals(other.fName) &&
-					fParent.equals(other.fParent) &&
-					fOccurrenceCount == other.fOccurrenceCount;
-		}
-		return false;
+		// assume instanceof check is done in subclass
+		JavaElement other = (JavaElement) o;		
+		return this.occurrenceCount == other.occurrenceCount &&
+				this.name.equals(other.name) &&
+				this.parent.equals(other.parent);
 	}
 	/**
 	 * Returns true if this <code>JavaElement</code> is equivalent to the given
 	 * <code>IDOMNode</code>.
 	 */
-	protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
+	protected boolean equalsDOMNode(IDOMNode node) {
 		return false;
 	}
 	/**
@@ -167,6 +137,7 @@
 			getElementInfo();
 			return true;
 		} catch (JavaModelException e) {
+			// element doesn't exist: return false
 		}
 		return false;
 	}
@@ -194,13 +165,9 @@
 				element = element.getParent();
 			}
 			if (path.size() == 0) {
-				try {
-					if (equalsDOMNode(dom)) {
-						return dom;
-					} else {
-						return null;
-					}
-				} catch(JavaModelException e) {
+				if (equalsDOMNode(dom)) {
+					return dom;
+				} else {
 					return null;
 				}
 			}
@@ -213,29 +180,29 @@
 	 */
 	protected IDOMNode followPath(ArrayList path, int position, IDOMNode node) {
 	
-		try {
-			if (equalsDOMNode(node)) {
-				if (position == (path.size() - 1)) {
-					return node;
-				} else {
-					if (node.getFirstChild() != null) {
-						position++;
-						return ((JavaElement)path.get(position)).followPath(path, position, node.getFirstChild());
-					} else {
-						return null;
-					}
-				}
-			} else if (node.getNextNode() != null) {
-				return followPath(path, position, node.getNextNode());
+		if (equalsDOMNode(node)) {
+			if (position == (path.size() - 1)) {
+				return node;
 			} else {
-				return null;
+				if (node.getFirstChild() != null) {
+					position++;
+					return ((JavaElement)path.get(position)).followPath(path, position, node.getFirstChild());
+				} else {
+					return null;
+				}
 			}
-		} catch (JavaModelException e) {
+		} else if (node.getNextNode() != null) {
+			return followPath(path, position, node.getNextNode());
+		} else {
 			return null;
 		}
-	
 	}
 	/**
+	 * Generates the element infos for this element, its ancestors (if they are not opened) and its children (if it is an Openable).
+	 * Puts the newly created element info in the given map.
+	 */
+	protected abstract void generateInfos(Object info, HashMap newElements, IProgressMonitor pm) throws JavaModelException;
+	/**
 	 * @see IJavaElement
 	 */
 	public IJavaElement getAncestor(int ancestorType) {
@@ -251,7 +218,12 @@
 	 * @see IParent 
 	 */
 	public IJavaElement[] getChildren() throws JavaModelException {
-		return ((JavaElementInfo)getElementInfo()).getChildren();
+		Object elementInfo = getElementInfo();
+		if (elementInfo instanceof JavaElementInfo) {
+			return ((JavaElementInfo)elementInfo).getChildren();
+		} else {
+			return NO_ELEMENTS;
+		}
 	}
 	/**
 	 * Returns a collection of (immediate) children of this node of the
@@ -287,48 +259,56 @@
 	 * Returns the info for this handle.  
 	 * If this element is not already open, it and all of its parents are opened.
 	 * Does not return null.
-	 * NOTE: BinaryType infos are NJOT rooted under JavaElementInfo.
+	 * NOTE: BinaryType infos are NOT rooted under JavaElementInfo.
 	 * @exception JavaModelException if the element is not present or not accessible
 	 */
 	public Object getElementInfo() throws JavaModelException {
+		return getElementInfo(null);
+	}
+	/**
+	 * Returns the info for this handle.  
+	 * If this element is not already open, it and all of its parents are opened.
+	 * Does not return null.
+	 * NOTE: BinaryType infos are NOT rooted under JavaElementInfo.
+	 * @exception JavaModelException if the element is not present or not accessible
+	 */
+	public Object getElementInfo(IProgressMonitor monitor) throws JavaModelException {
 
-		// workaround to ensure parent project resolved classpath is available to avoid triggering initializers
-		// while the JavaModelManager lock is acquired (can cause deadlocks in clients)
-		IJavaProject project = getJavaProject();
-		if (project != null && !project.isOpen()) {
-			// TODO: need to revisit, since deadlock could still occur if perProjectInfo is removed concurrent before entering the lock
-			try {
-				project.getResolvedClasspath(true); // trigger all possible container/variable initialization outside the model lock
-			} catch (JavaModelException e) {
-				// project is not accessible or is not a java project
-			}
-		}
-
-		// element info creation is done inside a lock on the JavaModelManager
-		JavaModelManager manager;
-		synchronized(manager = JavaModelManager.getJavaModelManager()){
-			Object info = manager.getInfo(this);
-			if (info == null) {
-				openHierarchy();
-				info= manager.getInfo(this);
-				if (info == null) {
-					throw newNotPresentException();
-				}
-			}
-			return info;
-		}
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		Object info = manager.getInfo(this);
+		if (info != null) return info;
+		return openWhenClosed(createElementInfo(), monitor);
 	}
 	/**
 	 * @see IAdaptable
 	 */
 	public String getElementName() {
-		return fName;
+		return this.name;
 	}
-	/**
-	 * @see IJavaElement
+	/*
+	 * Creates a Java element handle from the given memento.
+	 * The given token is the current delimiter indicating the type of the next token(s).
+	 * The given working copy owner is used only for compilation unit handles.
 	 */
-	public int getElementType() {
-		return fLEType;
+	public abstract IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner owner);
+	/*
+	 * Creates a Java element handle from the given memento.
+	 * The given working copy owner is used only for compilation unit handles.
+	 */
+	public IJavaElement getHandleFromMemento(StringTokenizer memento, WorkingCopyOwner owner) {
+		if (!memento.hasMoreTokens()) return this;
+		String token = memento.nextToken();
+		return getHandleFromMemento(token, memento, owner);
+	}
+	/*
+	 * Update the occurence count of the receiver and creates a Java element handle from the given memento.
+	 * The given working copy owner is used only for compilation unit handles.
+	 */
+	public IJavaElement getHandleUpdatingCountFromMemento(StringTokenizer memento, WorkingCopyOwner owner) {
+		this.occurrenceCount = Integer.parseInt(memento.nextToken());
+		if (!memento.hasMoreTokens()) return this;
+		String token = memento.nextToken();
+		return getHandleFromMemento(token, memento, owner);
 	}
 	/**
 	 * @see IJavaElement
@@ -343,6 +323,10 @@
 		StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
 		buff.append(getHandleMementoDelimiter());
 		buff.append(getElementName());
+		if (this.occurrenceCount > 1) {
+			buff.append(JEM_COUNT);
+			buff.append(this.occurrenceCount);
+		}
 		return buff.toString();
 	}
 	/**
@@ -371,12 +355,6 @@
 		} while ((current = current.getParent()) != null);
 		return null;
 	}
-	/**
-	 * Returns the occurrence count of the handle.
-	 */
-	protected int getOccurrenceCount() {
-		return fOccurrenceCount;
-	}
 	/*
 	 * @see IJavaElement
 	 */
@@ -390,16 +368,27 @@
 	 * <p>Subclasses that are not IOpenable's must override this method.
 	 */
 	public IOpenable getOpenableParent() {
-		
-		return (IOpenable)fParent;
+		return (IOpenable)this.parent;
 	}
 	/**
 	 * @see IJavaElement
 	 */
 	public IJavaElement getParent() {
-		return fParent;
+		return this.parent;
 	}
-	
+	/*
+	 * @see IJavaElement#getPrimaryElement()
+	 */
+	public IJavaElement getPrimaryElement() {
+		return getPrimaryElement(true);
+	}
+	/*
+	 * Returns the primary element. If checkOwner, and the cu owner is primary,
+	 * return this element.
+	 */
+	public IJavaElement getPrimaryElement(boolean checkOwner) {
+		return this;
+	}
 	/**
 	 * Returns the element that is located at the given source position
 	 * in this element.  This is a helper method for <code>ICompilationUnit#getElementAt</code>,
@@ -441,25 +430,32 @@
 	}
 
 	/**
+	 * @see IParent 
+	 */
+	public boolean hasChildren() throws JavaModelException {
+		return getChildren().length > 0;
+	}
+
+	/**
 	 * Returns the hash code for this Java element. By default,
 	 * the hash code for an element is a combination of its name
 	 * and parent's hash code. Elements with other requirements must
 	 * override this method.
 	 */
 	public int hashCode() {
-		if (fParent == null) return super.hashCode();
-		return Util.combineHashCodes(fName.hashCode(), fParent.hashCode());
+		if (this.parent == null) return super.hashCode();
+		return Util.combineHashCodes(this.name.hashCode(), this.parent.hashCode());
 	}
 	/**
 	 * Returns true if this element is an ancestor of the given element,
 	 * otherwise false.
 	 */
-	protected boolean isAncestorOf(IJavaElement e) {
-		IJavaElement parent= e.getParent();
-		while (parent != null && !parent.equals(this)) {
-			parent= parent.getParent();
+	public boolean isAncestorOf(IJavaElement e) {
+		IJavaElement parentElement= e.getParent();
+		while (parentElement != null && !parentElement.equals(this)) {
+			parentElement= parentElement.getParent();
 		}
-		return parent != null;
+		return parentElement != null;
 	}
 	
 	/**
@@ -480,30 +476,39 @@
 	protected JavaModelException newNotPresentException() {
 		return new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, this));
 	}
-	/**
-	 * Opens this element and all parents that are not already open.
-	 *
-	 * @exception JavaModelException this element is not present or accessible
+	/*
+	 * Opens an <code>Openable</code> that is known to be closed (no check for <code>isOpen()</code>).
+	 * Returns the created element info.
 	 */
-	protected void openHierarchy() throws JavaModelException {
-		if (this instanceof IOpenable) {
-			((Openable) this).openWhenClosed(null);
-		} else {
-			Openable openableParent = (Openable)getOpenableParent();
-			if (openableParent != null) {
-				JavaElementInfo openableParentInfo = (JavaElementInfo) JavaModelManager.getJavaModelManager().getInfo((IJavaElement) openableParent);
-				if (openableParentInfo == null) {
-					openableParent.openWhenClosed(null);
-				} else {
-					throw newNotPresentException();
+	protected Object openWhenClosed(Object info, IProgressMonitor monitor) throws JavaModelException {
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		boolean hadTemporaryCache = manager.hasTemporaryCache();
+		try {
+			HashMap newElements = manager.getTemporaryCache();
+			generateInfos(info, newElements, monitor);
+			if (info == null) {
+				info = newElements.get(this);
+			}
+			if (info == null) { // a source ref element could not be opened
+				// close any buffer that was opened for the openable parent
+				Iterator iterator = newElements.keySet().iterator();
+				while (iterator.hasNext()) {
+					IJavaElement element = (IJavaElement)iterator.next();
+					if (element instanceof Openable) {
+						((Openable)element).closeBuffer();
+					}
 				}
+				throw newNotPresentException();
+			}
+			if (!hadTemporaryCache) {
+				manager.putInfos(this, newElements);
+			}
+		} finally {
+			if (!hadTemporaryCache) {
+				manager.resetTemporaryCache();
 			}
 		}
-	}
-	/**
-	 * This element has just been opened.  Do any necessary setup.
-	 */
-	protected void opening(Object info) {
+		return info;
 	}
 	/**
 	 */
@@ -511,35 +516,16 @@
 		return this.getElementName();
 	}
 	/**
-	 * Removes all cached info from the Java Model, including all children,
-	 * but does not close this element.
-	 */
-	protected void removeInfo() {
-		Object info = JavaModelManager.getJavaModelManager().peekAtInfo(this);
-		if (info != null) {
-			if (this instanceof IParent) {
-				IJavaElement[] children = ((JavaElementInfo)info).getChildren();
-				for (int i = 0, size = children.length; i < size; ++i) {
-					JavaElement child = (JavaElement) children[i];
-					child.removeInfo();
-				}
-			}
-			JavaModelManager.getJavaModelManager().removeInfo(this);
-		}
-	}
-	/**
-	 * Returns a copy of this element rooted at the given project.
-	 */
-	public abstract IJavaElement rootedAt(IJavaProject project);
-	/**
 	 * Runs a Java Model Operation
 	 */
 	public static void runOperation(JavaModelOperation operation, IProgressMonitor monitor) throws JavaModelException {
 		try {
-			if (operation.isReadOnly() || ResourcesPlugin.getWorkspace().isTreeLocked()) {
+			if (operation.isReadOnly()) {
 				operation.run(monitor);
 			} else {
-				// use IWorkspace.run(...) to ensure that a build will be done in autobuild mode
+				// Use IWorkspace.run(...) to ensure that a build will be done in autobuild mode.
+				// Note that if the tree is locked, this will throw a CoreException, but this is ok
+				// as this operation is modifying the tree (not read-only) and a CoreException will be thrown anyway.
 				ResourcesPlugin.getWorkspace().run(operation, monitor);
 			}
 		} catch (CoreException ce) {
@@ -556,12 +542,6 @@
 			}
 		}
 	}
-	/**
-	 * Sets the occurrence count of the handle.
-	 */
-	protected void setOccurrenceCount(int count) {
-		fOccurrenceCount = count;
-	}
 	protected String tabString(int tab) {
 		StringBuffer buffer = new StringBuffer();
 		for (int i = tab; i > 0; i--)
@@ -607,11 +587,11 @@
 	 *  Debugging purposes
 	 */
 	protected void toStringAncestors(StringBuffer buffer) {
-		JavaElement parent = (JavaElement)this.getParent();
-		if (parent != null && parent.getParent() != null) {
+		JavaElement parentElement = (JavaElement)this.getParent();
+		if (parentElement != null && parentElement.getParent() != null) {
 			buffer.append(" [in "); //$NON-NLS-1$
-			parent.toStringInfo(0, buffer, NO_INFO);
-			parent.toStringAncestors(buffer);
+			parentElement.toStringInfo(0, buffer, NO_INFO);
+			parentElement.toStringAncestors(buffer);
 			buffer.append("]"); //$NON-NLS-1$
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java
index d7b79af..92d1b3d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDelta.java
@@ -15,30 +15,21 @@
 import org.eclipse.core.resources.IResourceDelta;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaElementDelta;
-import org.eclipse.jdt.core.IJavaProject;
 
 /**
  * @see IJavaElementDelta
  */
-public class JavaElementDelta implements IJavaElementDelta {
-	/**
-	 * The element that this delta describes the change to.
-	 * @see #getElement()
-	 */
-	protected IJavaElement fChangedElement;
-	/**
-	 * @see #getKind()
-	 */
-	private int fKind = 0;
-	/**
-	 * @see #getFlags()
-	 */
-	private int fChangeFlags = 0;
+public class JavaElementDelta extends SimpleDelta implements IJavaElementDelta {
 	/**
 	 * @see #getAffectedChildren()
 	 */
 	protected IJavaElementDelta[] fAffectedChildren = fgEmptyDelta;
 
+	/*
+	 * The element that this delta describes the change to.
+	 */
+	protected IJavaElement changedElement;
+	
 	/**
 	 * Collection of resource deltas that correspond to non java resources deltas.
 	 */
@@ -74,30 +65,29 @@
  * </ul>
  */
 public JavaElementDelta(IJavaElement element) {
-	super();
-	fChangedElement = element;
+	this.changedElement = element;
 }
 /**
  * Adds the child delta to the collection of affected children.  If the
  * child is already in the collection, walk down the hierarchy.
  */
 protected void addAffectedChild(JavaElementDelta child) {
-	switch (fKind) {
+	switch (this.kind) {
 		case ADDED:
 		case REMOVED:
 			// no need to add a child if this parent is added or removed
 			return;
 		case CHANGED:
-			fChangeFlags |= F_CHILDREN;
+			this.changeFlags |= F_CHILDREN;
 			break;
 		default:
-			fKind = CHANGED;
-			fChangeFlags |= F_CHILDREN;
+			this.kind = CHANGED;
+			this.changeFlags |= F_CHILDREN;
 	}
 
 	// if a child delta is added to a compilation unit delta or below, 
 	// it's a fine grained delta
-	if (fChangedElement.getElementType() >= IJavaElement.COMPILATION_UNIT) {
+	if (this.changedElement.getElementType() >= IJavaElement.COMPILATION_UNIT) {
 		this.fineGrained();
 	}
 	
@@ -105,12 +95,12 @@
 		fAffectedChildren = new IJavaElementDelta[] {child};
 		return;
 	}
-	IJavaElementDelta existingChild = null;
+	JavaElementDelta existingChild = null;
 	int existingChildIndex = -1;
 	if (fAffectedChildren != null) {
 		for (int i = 0; i < fAffectedChildren.length; i++) {
 			if (this.equalsAndSameParent(fAffectedChildren[i].getElement(), child.getElement())) { // handle case of two jars that can be equals but not in the same project
-				existingChild = fAffectedChildren[i];
+				existingChild = (JavaElementDelta)fAffectedChildren[i];
 				existingChildIndex = i;
 				break;
 			}
@@ -133,7 +123,7 @@
 			case REMOVED:
 				switch (child.getKind()) {
 					case ADDED: // child was removed then added -> it is changed
-						child.fKind = CHANGED;
+						child.kind = CHANGED;
 						fAffectedChildren[existingChildIndex] = child;
 						return;
 					case CHANGED: // child was removed then changed -> it is removed
@@ -151,17 +141,19 @@
 						IJavaElementDelta[] children = child.getAffectedChildren();
 						for (int i = 0; i < children.length; i++) {
 							JavaElementDelta childsChild = (JavaElementDelta) children[i];
-							((JavaElementDelta) existingChild).addAffectedChild(childsChild);
+							existingChild.addAffectedChild(childsChild);
 						}
 						
-						// update flags if needed
-						switch (((JavaElementDelta) existingChild).fChangeFlags) {
-							case F_ADDED_TO_CLASSPATH:
-							case F_REMOVED_FROM_CLASSPATH:
-							case F_SOURCEATTACHED:
-							case F_SOURCEDETACHED:
-								((JavaElementDelta) existingChild).fChangeFlags |= ((JavaElementDelta) child).fChangeFlags;
-								break;
+						// update flags
+						boolean childHadContentFlag = (child.changeFlags & F_CONTENT) != 0;
+						boolean existingChildHadChildrenFlag = (existingChild.changeFlags & F_CHILDREN) != 0;
+						existingChild.changeFlags |= child.changeFlags;
+						
+						// remove F_CONTENT flag if existing child had F_CHILDREN flag set 
+						// (case of fine grained delta (existing child) and delta coming from 
+						// DeltaProcessor (child))
+						if (childHadContentFlag && existingChildHadChildrenFlag) {
+							existingChild.changeFlags &= ~F_CONTENT;
 						}
 						
 						// add the non-java resource deltas if needed
@@ -169,8 +161,8 @@
 						// as non-java resource deltas are always created last (by the DeltaProcessor)
 						IResourceDelta[] resDeltas = child.getResourceDeltas();
 						if (resDeltas != null) {
-							((JavaElementDelta)existingChild).resourceDeltas = resDeltas;
-							((JavaElementDelta)existingChild).resourceDeltasCounter = child.resourceDeltasCounter;
+							existingChild.resourceDeltas = resDeltas;
+							existingChild.resourceDeltasCounter = child.resourceDeltasCounter;
 						}
 						return;
 				}
@@ -179,7 +171,7 @@
 				// unknown -> existing child becomes the child with the existing child's flags
 				int flags = existingChild.getFlags();
 				fAffectedChildren[existingChildIndex] = child;
-				child.fChangeFlags |= flags;
+				child.changeFlags |= flags;
 		}
 	}
 }
@@ -190,8 +182,12 @@
  * and then an add operation should call this method.
  */
 public void added(IJavaElement element) {
+	added(element, 0);
+}
+public void added(IJavaElement element, int flags) {
 	JavaElementDelta addedDelta = new JavaElementDelta(element);
-	addedDelta.fKind = ADDED;
+	addedDelta.added();
+	addedDelta.changeFlags |= flags;
 	insertDeltaTree(element, addedDelta);
 }
 /**
@@ -199,17 +195,17 @@
  * child is already in the collection, walk down the hierarchy.
  */
 protected void addResourceDelta(IResourceDelta child) {
-	switch (fKind) {
+	switch (this.kind) {
 		case ADDED:
 		case REMOVED:
 			// no need to add a child if this parent is added or removed
 			return;
 		case CHANGED:
-			fChangeFlags |= F_CONTENT;
+			this.changeFlags |= F_CONTENT;
 			break;
 		default:
-			fKind = CHANGED;
-			fChangeFlags |= F_CONTENT;
+			this.kind = CHANGED;
+			this.changeFlags |= F_CONTENT;
 	}
 	if (resourceDeltas == null) {
 		resourceDeltas = new IResourceDelta[5];
@@ -230,50 +226,21 @@
  */
 public void changed(IJavaElement element, int changeFlag) {
 	JavaElementDelta changedDelta = new JavaElementDelta(element);
-	changedDelta.fKind = CHANGED;
-	changedDelta.fChangeFlags |= changeFlag;
+	changedDelta.changed(changeFlag);
 	insertDeltaTree(element, changedDelta);
 }
 /**
  * Mark this delta as a content changed delta.
  */
 public void contentChanged() {
-	fChangeFlags |= F_CONTENT;
+	this.changeFlags |= F_CONTENT;
 }
 /**
- * Clone this delta so that its elements are rooted at the given project.
- */
-public IJavaElementDelta clone(IJavaProject project) {
-	JavaElementDelta clone = 
-		new JavaElementDelta(((JavaElement)fChangedElement).rootedAt(project));
-	if (fAffectedChildren != fgEmptyDelta) {
-		int length = fAffectedChildren.length;
-		IJavaElementDelta[] cloneChildren = new IJavaElementDelta[length];
-		for (int i= 0; i < length; i++) {
-			cloneChildren[i] = ((JavaElementDelta)fAffectedChildren[i]).clone(project);
-		}
-		clone.fAffectedChildren = cloneChildren;
-	}	
-	clone.fChangeFlags = fChangeFlags;
-	clone.fKind = fKind;
-	if (fMovedFromHandle != null) {
-		clone.fMovedFromHandle = ((JavaElement)fMovedFromHandle).rootedAt(project);
-	}
-	if (fMovedToHandle != null) {
-		clone.fMovedToHandle = ((JavaElement)fMovedToHandle).rootedAt(project);
-	}
-	clone.resourceDeltas = this.resourceDeltas;
-	clone.resourceDeltasCounter = this.resourceDeltasCounter;
-	return clone;
-}
-
-/**
  * Creates the nested deltas for a closed element.
  */
 public void closed(IJavaElement element) {
 	JavaElementDelta delta = new JavaElementDelta(element);
-	delta.fKind = CHANGED;
-	delta.fChangeFlags |= F_CLOSED;
+	delta.changed(F_CLOSED);
 	insertDeltaTree(element, delta);
 }
 /**
@@ -287,8 +254,8 @@
 	if (ancestors == null) {
 		if (this.equalsAndSameParent(delta.getElement(), getElement())) { // handle case of two jars that can be equals but not in the same project
 			// the element being changed is the root element
-			fKind= delta.fKind;
-			fChangeFlags = delta.fChangeFlags;
+			this.kind= delta.kind;
+			this.changeFlags = delta.changeFlags;
 			fMovedToHandle = delta.fMovedToHandle;
 			fMovedFromHandle = delta.fMovedFromHandle;
 		}
@@ -314,7 +281,7 @@
  * in the delta tree, or null, if no delta for the given element is found.
  */
 protected JavaElementDelta find(IJavaElement e) {
-	if (this.equalsAndSameParent(fChangedElement, e)) { // handle case of two jars that can be equals but not in the same project
+	if (this.equalsAndSameParent(this.changedElement, e)) { // handle case of two jars that can be equals but not in the same project
 		return this;
 	} else {
 		for (int i = 0; i < fAffectedChildren.length; i++) {
@@ -330,10 +297,7 @@
  * Mark this delta as a fine-grained delta.
  */
 public void fineGrained() {
-	if (fKind == 0) { // if not set yet
-		fKind = CHANGED;
-	}
-	fChangeFlags |= F_FINE_GRAINED;
+	changed(F_FINE_GRAINED);
 }
 /**
  * @see IJavaElementDelta
@@ -359,7 +323,7 @@
 		return null;
 	}
 	ArrayList parents = new ArrayList();
-	while (!parent.equals(fChangedElement)) {
+	while (!parent.equals(this.changedElement)) {
 		parents.add(parent);
 		parent = parent.getParent();
 		if (parent == null) {
@@ -410,7 +374,7 @@
 		if (this.equalsAndSameParent(delta.getElement(), element)) { // handle case of two jars that can be equals but not in the same project
 			return delta;
 		} else {
-			delta = ((JavaElementDelta)delta).getDeltaFor(element);
+			delta = delta.getDeltaFor(element);
 			if (delta != null)
 				return delta;
 		}
@@ -421,19 +385,7 @@
  * @see IJavaElementDelta
  */
 public IJavaElement getElement() {
-	return fChangedElement;
-}
-/**
- * @see IJavaElementDelta
- */
-public int getFlags() {
-	return fChangeFlags;
-}
-/**
- * @see IJavaElementDelta
- */
-public int getKind() {
-	return fKind;
+	return this.changedElement;
 }
 /**
  * @see IJavaElementDelta
@@ -492,8 +444,8 @@
  */
 public void movedFrom(IJavaElement movedFromElement, IJavaElement movedToElement) {
 	JavaElementDelta removedDelta = new JavaElementDelta(movedFromElement);
-	removedDelta.fKind = REMOVED;
-	removedDelta.fChangeFlags |= F_MOVED_TO;
+	removedDelta.kind = REMOVED;
+	removedDelta.changeFlags |= F_MOVED_TO;
 	removedDelta.fMovedToHandle = movedToElement;
 	insertDeltaTree(movedFromElement, removedDelta);
 }
@@ -505,8 +457,8 @@
  */
 public void movedTo(IJavaElement movedToElement, IJavaElement movedFromElement) {
 	JavaElementDelta addedDelta = new JavaElementDelta(movedToElement);
-	addedDelta.fKind = ADDED;
-	addedDelta.fChangeFlags |= F_MOVED_FROM;
+	addedDelta.kind = ADDED;
+	addedDelta.changeFlags |= F_MOVED_FROM;
 	addedDelta.fMovedFromHandle = movedFromElement;
 	insertDeltaTree(movedToElement, addedDelta);
 }
@@ -515,8 +467,7 @@
  */
 public void opened(IJavaElement element) {
 	JavaElementDelta delta = new JavaElementDelta(element);
-	delta.fKind = CHANGED;
-	delta.fChangeFlags |= F_OPENED;
+	delta.changed(F_OPENED);
 	insertDeltaTree(element, delta);
 }
 /**
@@ -556,12 +507,15 @@
  * and then the delete operation should call this method.
  */
 public void removed(IJavaElement element) {
+	removed(element, 0);
+}
+public void removed(IJavaElement element, int flags) {
 	JavaElementDelta removedDelta= new JavaElementDelta(element);
 	insertDeltaTree(element, removedDelta);
 	JavaElementDelta actualDelta = getDeltaFor(element);
 	if (actualDelta != null) {
-		actualDelta.fKind = REMOVED;
-		actualDelta.fChangeFlags = 0;
+		actualDelta.removed();
+		actualDelta.changeFlags |= flags;
 		actualDelta.fAffectedChildren = fgEmptyDelta;
 	}
 }
@@ -573,8 +527,7 @@
  */
 public void sourceAttached(IJavaElement element) {
 	JavaElementDelta attachedDelta = new JavaElementDelta(element);
-	attachedDelta.fKind = CHANGED;
-	attachedDelta.fChangeFlags |= F_SOURCEATTACHED;
+	attachedDelta.changed(F_SOURCEATTACHED);
 	insertDeltaTree(element, attachedDelta);
 }
 /**
@@ -585,8 +538,7 @@
  */
 public void sourceDetached(IJavaElement element) {
 	JavaElementDelta detachedDelta = new JavaElementDelta(element);
-	detachedDelta.fKind = CHANGED;
-	detachedDelta.fChangeFlags |= F_SOURCEDETACHED;
+	detachedDelta.changed(F_SOURCEDETACHED);
 	insertDeltaTree(element, detachedDelta);
 }
 /** 
@@ -601,103 +553,7 @@
 		buffer.append('\t');
 	}
 	buffer.append(((JavaElement)getElement()).toDebugString());
-	buffer.append("["); //$NON-NLS-1$
-	switch (getKind()) {
-		case IJavaElementDelta.ADDED :
-			buffer.append('+');
-			break;
-		case IJavaElementDelta.REMOVED :
-			buffer.append('-');
-			break;
-		case IJavaElementDelta.CHANGED :
-			buffer.append('*');
-			break;
-		default :
-			buffer.append('?');
-			break;
-	}
-	buffer.append("]: {"); //$NON-NLS-1$
-	int changeFlags = getFlags();
-	boolean prev = false;
-	if ((changeFlags & IJavaElementDelta.F_CHILDREN) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("CHILDREN"); //$NON-NLS-1$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_CONTENT) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("CONTENT"); //$NON-NLS-1$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_MOVED_FROM) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("MOVED_FROM(" + ((JavaElement)getMovedFromElement()).toStringWithAncestors() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_MOVED_TO) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("MOVED_TO(" + ((JavaElement)getMovedToElement()).toStringWithAncestors() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("ADDED TO CLASSPATH"); //$NON-NLS-1$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("REMOVED FROM CLASSPATH"); //$NON-NLS-1$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_REORDER) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("REORDERED"); //$NON-NLS-1$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("ARCHIVE CONTENT CHANGED"); //$NON-NLS-1$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_SOURCEATTACHED) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("SOURCE ATTACHED"); //$NON-NLS-1$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_SOURCEDETACHED) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("SOURCE DETACHED"); //$NON-NLS-1$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_MODIFIERS) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("MODIFIERS CHANGED"); //$NON-NLS-1$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_SUPER_TYPES) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("SUPER TYPES CHANGED"); //$NON-NLS-1$
-		prev = true;
-	}
-	if ((changeFlags & IJavaElementDelta.F_FINE_GRAINED) != 0) {
-		if (prev)
-			buffer.append(" | "); //$NON-NLS-1$
-		buffer.append("FINE GRAINED"); //$NON-NLS-1$
-		prev = true;
-	}
-	buffer.append("}"); //$NON-NLS-1$
+	toDebugString(buffer);
 	IJavaElementDelta[] children = getAffectedChildren();
 	if (children != null) {
 		for (int i = 0; i < children.length; ++i) {
@@ -731,6 +587,83 @@
 	}
 	return buffer.toString();
 }
+protected boolean toDebugString(StringBuffer buffer, int flags) {
+	boolean prev = super.toDebugString(buffer, flags);
+
+	if ((flags & IJavaElementDelta.F_CHILDREN) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("CHILDREN"); //$NON-NLS-1$
+		prev = true;
+	}
+	if ((flags & IJavaElementDelta.F_CONTENT) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("CONTENT"); //$NON-NLS-1$
+		prev = true;
+	}
+	if ((flags & IJavaElementDelta.F_MOVED_FROM) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("MOVED_FROM(" + ((JavaElement)getMovedFromElement()).toStringWithAncestors() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+		prev = true;
+	}
+	if ((flags & IJavaElementDelta.F_MOVED_TO) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("MOVED_TO(" + ((JavaElement)getMovedToElement()).toStringWithAncestors() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
+		prev = true;
+	}
+	if ((flags & IJavaElementDelta.F_ADDED_TO_CLASSPATH) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("ADDED TO CLASSPATH"); //$NON-NLS-1$
+		prev = true;
+	}
+	if ((flags & IJavaElementDelta.F_REMOVED_FROM_CLASSPATH) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("REMOVED FROM CLASSPATH"); //$NON-NLS-1$
+		prev = true;
+	}
+	if ((flags & IJavaElementDelta.F_REORDER) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("REORDERED"); //$NON-NLS-1$
+		prev = true;
+	}
+	if ((flags & IJavaElementDelta.F_ARCHIVE_CONTENT_CHANGED) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("ARCHIVE CONTENT CHANGED"); //$NON-NLS-1$
+		prev = true;
+	}
+	if ((flags & IJavaElementDelta.F_SOURCEATTACHED) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("SOURCE ATTACHED"); //$NON-NLS-1$
+		prev = true;
+	}
+	if ((flags & IJavaElementDelta.F_SOURCEDETACHED) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("SOURCE DETACHED"); //$NON-NLS-1$
+		prev = true;
+	}
+	if ((flags & IJavaElementDelta.F_FINE_GRAINED) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("FINE GRAINED"); //$NON-NLS-1$
+		prev = true;
+	}
+	if ((flags & IJavaElementDelta.F_PRIMARY_WORKING_COPY) != 0) {
+		if (prev)
+			buffer.append(" | "); //$NON-NLS-1$
+		buffer.append("PRIMARY WORKING COPY"); //$NON-NLS-1$
+		prev = true;
+	}
+	return prev;
+}
 /** 
  * Returns a string representation of this delta's
  * structure suitable for debug purposes.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
index 04d6dd5..dd1926e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
@@ -392,14 +392,14 @@
 /**
  * Trims deletion deltas to only report the highest level of deletion
  */
-private void trimDelta(JavaElementDelta delta) {
-	if (delta.getKind() == IJavaElementDelta.REMOVED) {
-		IJavaElementDelta[] children = delta.getAffectedChildren();
+private void trimDelta(JavaElementDelta elementDelta) {
+	if (elementDelta.getKind() == IJavaElementDelta.REMOVED) {
+		IJavaElementDelta[] children = elementDelta.getAffectedChildren();
 		for(int i = 0, length = children.length; i < length; i++) {
-			delta.removeAffectedChild((JavaElementDelta)children[i]);
+			elementDelta.removeAffectedChild((JavaElementDelta)children[i]);
 		}
 	} else {
-		IJavaElementDelta[] children = delta.getAffectedChildren();
+		IJavaElementDelta[] children = elementDelta.getAffectedChildren();
 		for(int i = 0, length = children.length; i < length; i++) {
 			trimDelta((JavaElementDelta)children[i]);
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java
index fa1717f..2a15394 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElementInfo.java
@@ -23,31 +23,28 @@
 	 * object. This is an empty array if this element has
 	 * no children.
 	 */
-	protected IJavaElement[] fChildren;
+	protected IJavaElement[] children;
 
 	/**
-	 * Shared empty collection used for efficiency.
-	 */
-	protected static IJavaElement[] fgEmptyChildren = new IJavaElement[]{};
-	/**
 	 * Is the structure of this element known
 	 * @see IJavaElement#isStructureKnown()
 	 */
-	protected boolean fIsStructureKnown = false;
+	protected boolean isStructureKnown = false;
 
 	/**
 	 * Shared empty collection used for efficiency.
 	 */
 	static Object[] NO_NON_JAVA_RESOURCES = new Object[] {};	
+	
 	protected JavaElementInfo() {
-		fChildren = fgEmptyChildren;
+		this.children = JavaElement.NO_ELEMENTS;
 	}
 	public void addChild(IJavaElement child) {
-		if (fChildren == fgEmptyChildren) {
+		if (this.children == JavaElement.NO_ELEMENTS) {
 			setChildren(new IJavaElement[] {child});
 		} else {
 			if (!includesChild(child)) {
-				setChildren(growAndAddToArray(fChildren, child));
+				setChildren(growAndAddToArray(this.children, child));
 			}
 		}
 	}
@@ -60,7 +57,7 @@
 		}
 	}
 	public IJavaElement[] getChildren() {
-		return fChildren;
+		return this.children;
 	}
 	/**
 	 * Adds the new element to a new array that contains all of the elements of the old array.
@@ -78,8 +75,8 @@
 	 */
 	protected boolean includesChild(IJavaElement child) {
 		
-		for (int i= 0; i < fChildren.length; i++) {
-			if (fChildren[i].equals(child)) {
+		for (int i= 0; i < this.children.length; i++) {
+			if (this.children[i].equals(child)) {
 				return true;
 			}
 		}
@@ -89,7 +86,7 @@
 	 * @see IJavaElement#isStructureKnown()
 	 */
 	public boolean isStructureKnown() {
-		return fIsStructureKnown;
+		return this.isStructureKnown;
 	}
 	/**
 	 * Returns an array with all the same elements as the specified array except for
@@ -112,17 +109,17 @@
 	}
 	public void removeChild(IJavaElement child) {
 		if (includesChild(child)) {
-			setChildren(removeAndShrinkArray(fChildren, child));
+			setChildren(removeAndShrinkArray(this.children, child));
 		}
 	}
 	public void setChildren(IJavaElement[] children) {
-		fChildren = children;
+		this.children = children;
 	}
 	/**
 	 * Sets whether the structure of this element known
 	 * @see IJavaElement#isStructureKnown()
 	 */
 	public void setIsStructureKnown(boolean newIsStructureKnown) {
-		fIsStructureKnown = newIsStructureKnown;
+		this.isStructureKnown = newIsStructureKnown;
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
index 2c9333f..f3d3fd1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
@@ -26,15 +26,12 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.core.IClassFile;
-import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModel;
 import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Implementation of <code>IJavaModel<code>. The Java Model maintains a cache of
@@ -62,7 +59,22 @@
  * @exception Error if called more than once
  */
 protected JavaModel() throws Error {
-	super(JAVA_MODEL, null, "" /*workspace has empty name*/); //$NON-NLS-1$
+	super(null, "" /*workspace has empty name*/); //$NON-NLS-1$
+}
+protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource)	/*throws JavaModelException*/ {
+
+	// determine my children
+	IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+	for (int i = 0, max = projects.length; i < max; i++) {
+		IProject project = projects[i];
+		if (JavaProject.hasJavaNature(project)) {
+			info.addChild(getJavaProject(project));
+		}
+	}
+
+	newElements.put(this, info);
+	
+	return true;
 }
 /*
  * @see IJavaModel
@@ -101,7 +113,7 @@
 /**
  * Returns a new element info for this element.
  */
-protected OpenableElementInfo createElementInfo() {
+protected Object createElementInfo() {
 	return new JavaModelInfo();
 }
 
@@ -115,6 +127,10 @@
 		runOperation(new DeleteElementsOperation(elements, force), monitor);
 	}
 }
+public boolean equals(Object o) {
+	if (!(o instanceof JavaModel)) return false;
+	return super.equals(o);
+}
 /**
  * Finds the given project in the list of the java model's children.
  * Returns null if not found.
@@ -129,10 +145,16 @@
 			}
 		}
 	} catch (JavaModelException e) {
+		// java model doesn't exist: cannot find any project
 	}
 	return null;
 }
-
+/**
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return JAVA_MODEL;
+}
 /**
  * Flushes the cache of external files known to be existing.
  */
@@ -140,199 +162,19 @@
 	existingExternalFiles = new HashSet();
 }
 
-/**
+/*
+ * @see JavaElement
  */
-protected boolean generateInfos(
-	OpenableElementInfo info,
-	IProgressMonitor pm,
-	Map newElements,
-	IResource underlyingResource)	throws JavaModelException {
-
-	JavaModelManager.getJavaModelManager().putInfo(this, info);
-	// determine my children
-	IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
-	for (int i = 0, max = projects.length; i < max; i++) {
-		IProject project = projects[i];
-		if (JavaProject.hasJavaNature(project)) {
-			info.addChild(getJavaProject(project));
-		}
+public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner owner) {
+	switch (token.charAt(0)) {
+		case JEM_COUNT:
+			return getHandleUpdatingCountFromMemento(memento, owner);
+		case JEM_JAVAPROJECT:
+			String projectName = memento.nextToken();
+			JavaElement project = (JavaElement)getJavaProject(projectName);
+			return project.getHandleFromMemento(memento, owner);
 	}
-	return true;
-}
-/**
- * Returns the <code>IJavaElement</code> represented by the <code>String</code>
- * memento.
- * @see getHandleMemento()
- */
-protected IJavaElement getHandleFromMementoForBinaryMembers(String memento, IPackageFragmentRoot root, int rootEnd, int end) throws JavaModelException {
-
-	//deal with class file and binary members
-	IPackageFragment frag = null;
-	if (rootEnd == end - 1) {
-		//default package
-		frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
-	} else {
-		frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
-	}
-	int oldEnd = end;
-	end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
-	if (end == -1) {
-		//we ended with a class file 
-		return frag.getClassFile(memento.substring(oldEnd + 1));
-	}
-	IClassFile cf = frag.getClassFile(memento.substring(oldEnd + 1, end));
-	oldEnd = end;
-	end = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
-	oldEnd = end;
-	end = memento.indexOf(JavaElement.JEM_FIELD, end);
-	if (end != -1) {
-		//binary field
-		IType type = cf.getType();
-		return type.getField(memento.substring(end + 1));
-	}
-	end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
-	if (end != -1) {
-		//binary method
-		oldEnd = end;
-		IType type = cf.getType();
-		String methodName;
-		end = memento.lastIndexOf(JavaElement.JEM_METHOD);
-		String[] parameterTypes = null;
-		if (end == oldEnd) {
-			methodName = memento.substring(end + 1);
-			//no parameter types
-			parameterTypes = new String[] {};
-		} else {
-			String parameters = memento.substring(oldEnd + 1);
-			StringTokenizer tokenizer = new StringTokenizer(parameters, new String(new char[] {JavaElement.JEM_METHOD}));
-			parameterTypes = new String[tokenizer.countTokens() - 1];
-			methodName= tokenizer.nextToken();
-			int i = 0;
-			while (tokenizer.hasMoreTokens()) {
-				parameterTypes[i] = tokenizer.nextToken();
-				i++;
-			}
-		}
-		return type.getMethod(methodName, parameterTypes);
-	}
-
-	//binary type
-	return cf.getType();
-}
-/**
- * Returns the <code>IPackageFragmentRoot</code> represented by the <code>String</code>
- * memento.
- * @see getHandleMemento()
- */
-protected IPackageFragmentRoot getHandleFromMementoForRoot(String memento, JavaProject project, int projectEnd, int rootEnd) {
-	String rootName = null;
-	if (rootEnd == projectEnd - 1) {
-		//default root
-		rootName = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
-	} else {
-		rootName = memento.substring(projectEnd + 1, rootEnd);
-	}
-	return project.getPackageFragmentRoot(new Path(rootName));
-}
-/**
- * Returns the <code>IJavaElement</code> represented by the <code>String</code>
- * memento.
- * @see getHandleMemento()
- */
-protected IJavaElement getHandleFromMementoForSourceMembers(String memento, IPackageFragmentRoot root, int rootEnd, int end) throws JavaModelException {
-
-	//deal with compilation units and source members
-	IPackageFragment frag = null;
-	if (rootEnd == end - 1) {
-		//default package
-		frag= root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME);
-	} else {
-		frag= root.getPackageFragment(memento.substring(rootEnd + 1, end));
-	}
-	int oldEnd = end;
-	end = memento.indexOf(JavaElement.JEM_PACKAGEDECLARATION, end);
-	if (end != -1) {
-		//package declaration
-		ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, end));
-		return cu.getPackageDeclaration(memento.substring(end + 1));
-	}
-	end = memento.indexOf(JavaElement.JEM_IMPORTDECLARATION, oldEnd);
-	if (end != -1) {
-		//import declaration
-		ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, end));
-		return cu.getImport(memento.substring(end + 1));
-	}
-	int typeStart = memento.indexOf(JavaElement.JEM_TYPE, oldEnd);
-	if (typeStart == -1) {
-		//we ended with a compilation unit
-		return frag.getCompilationUnit(memento.substring(oldEnd + 1));
-	}
-
-	//source members
-	ICompilationUnit cu = frag.getCompilationUnit(memento.substring(oldEnd + 1, typeStart));
-	end = memento.indexOf(JavaElement.JEM_FIELD, oldEnd);
-	if (end != -1) {
-		//source field
-		IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
-		return type.getField(memento.substring(end + 1));
-	}
-	end = memento.indexOf(JavaElement.JEM_METHOD, oldEnd);
-	if (end != -1) {
-		//source method
-		IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
-		oldEnd = end;
-		String methodName;
-		end = memento.lastIndexOf(JavaElement.JEM_METHOD);
-		String[] parameterTypes = null;
-		if (end == oldEnd) {
-			methodName = memento.substring(end + 1);
-			//no parameter types
-			parameterTypes = new String[] {};
-		} else {
-			String parameters = memento.substring(oldEnd + 1);
-			StringTokenizer mTokenizer = new StringTokenizer(parameters, new String(new char[] {JavaElement.JEM_METHOD}));
-			parameterTypes = new String[mTokenizer.countTokens() - 1];
-			methodName = mTokenizer.nextToken();
-			int i = 0;
-			while (mTokenizer.hasMoreTokens()) {
-				parameterTypes[i] = mTokenizer.nextToken();
-				i++;
-			}
-		}
-		return type.getMethod(methodName, parameterTypes);
-	}
-	
-	end = memento.indexOf(JavaElement.JEM_INITIALIZER, oldEnd);
-	if (end != -1 ) {
-		//initializer
-		IType type = getHandleFromMementoForSourceType(memento, cu, typeStart, end);
-		return type.getInitializer(Integer.parseInt(memento.substring(end + 1)));
-	}
-	//source type
-	return getHandleFromMementoForSourceType(memento, cu, typeStart, memento.length());
-}
-/**
- * Returns the <code>IJavaElement</code> represented by the <code>String</code>
- * memento.
- * @see getHandleMemento()
- */
-protected IType getHandleFromMementoForSourceType(String memento, ICompilationUnit cu, int typeStart, int typeEnd) throws JavaModelException {
-	int end = memento.lastIndexOf(JavaElement.JEM_TYPE);
-	IType type = null;
-	if (end == typeStart) {
-		String typeName = memento.substring(typeStart + 1, typeEnd);
-		type = cu.getType(typeName);
-		
-	} else {
-		String typeNames = memento.substring(typeStart + 1, typeEnd);
-		StringTokenizer tokenizer = new StringTokenizer(typeNames, new String(new char[] {JavaElement.JEM_TYPE}));
-		type = cu.getType(tokenizer.nextToken());
-		while (tokenizer.hasMoreTokens()) {
-			//deal with inner types
-			type= type.getType(tokenizer.nextToken());
-		}
-	}
-	return type;
+	return null;
 }
 /**
  * @see JavaElement#getHandleMemento()
@@ -351,8 +193,8 @@
 /**
  * @see IJavaModel
  */
-public IJavaProject getJavaProject(String name) {
-	return new JavaProject(ResourcesPlugin.getWorkspace().getRoot().getProject(name), this);
+public IJavaProject getJavaProject(String projectName) {
+	return new JavaProject(ResourcesPlugin.getWorkspace().getRoot().getProject(projectName), this);
 }
 /**
  * Returns the active Java project associated with the specified
@@ -398,10 +240,9 @@
  */
 public IJavaProject[] getOldJavaProjectsList() throws JavaModelException {
 	JavaModelManager manager = JavaModelManager.getJavaModelManager();
-	return 
-		manager.javaProjectsCache == null ? 
+	return manager.deltaState.modelProjectsCache == null ? 
 			this.getJavaProjects() : 
-			manager.javaProjectsCache; 
+			manager.deltaState.modelProjectsCache; 
 }
 /*
  * @see IJavaElement
@@ -418,7 +259,7 @@
 /**
  * @see IOpenable
  */
-public IResource getUnderlyingResource() throws JavaModelException {
+public IResource getUnderlyingResource() {
 	return null;
 }
 /**
@@ -446,7 +287,7 @@
 	if (elementsScope == null){
 		elementsScope = new IJavaElement[] { this };
 	}
-	JavaModelManager.getJavaModelManager().deltaProcessor.checkExternalArchiveChanges(elementsScope, monitor);
+	JavaModelManager.getJavaModelManager().getDeltaProcessor().checkExternalArchiveChanges(elementsScope, monitor);
 }
 
 /**
@@ -462,13 +303,6 @@
 	
 	runOperation(op, monitor);
 }
-/*
- * @see JavaElement#rootedAt(IJavaProject)
- */
-public IJavaElement rootedAt(IJavaProject project) {
-	return this;
-
-}
 /**
  * Configures and runs the <code>MultiOperation</code>.
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelInfo.java
index 801fdee..49154de 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelInfo.java
@@ -27,32 +27,27 @@
 	Object[] nonJavaResources;
 
 /**
- * Constructs a new Java Model Info 
- */
-protected JavaModelInfo() {
-}
-/**
  * Compute the non-java resources contained in this java project.
  */
 private Object[] computeNonJavaResources() {
 	IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
 	int length = projects.length;
-	Object[] nonJavaResources = null;
+	Object[] resources = null;
 	int index = 0;
 	for (int i = 0; i < length; i++) {
 		IProject project = projects[i];
 		if (!JavaProject.hasJavaNature(project)) {
-			if (nonJavaResources == null) {
-				nonJavaResources = new Object[length];
+			if (resources == null) {
+				resources = new Object[length];
 			}
-			nonJavaResources[index++] = project;
+			resources[index++] = project;
 		}
 	}
 	if (index == 0) return NO_NON_JAVA_RESOURCES;
 	if (index < length) {
-		System.arraycopy(nonJavaResources, 0, nonJavaResources = new Object[index], 0, index);
+		System.arraycopy(resources, 0, resources = new Object[index], 0, index);
 	}
-	return nonJavaResources;
+	return resources;
 }
 
 /**
@@ -60,11 +55,9 @@
  */
 Object[] getNonJavaResources() {
 
-	Object[] nonJavaResources = this.nonJavaResources;
-	if (nonJavaResources == null) {
-		nonJavaResources = computeNonJavaResources();
-		this.nonJavaResources = nonJavaResources;
+	if (this.nonJavaResources == null) {
+		this.nonJavaResources = computeNonJavaResources();
 	}
-	return nonJavaResources;
+	return this.nonJavaResources;
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index c2241ac..320e8c7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.core;
 
 import java.io.*;
+import java.text.NumberFormat;
 import java.util.*;
 import java.util.zip.ZipFile;
 
@@ -21,6 +22,7 @@
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
 import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.search.SearchEngine;
 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
@@ -29,6 +31,8 @@
 import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
 import org.eclipse.jdt.internal.core.search.AbstractSearchScope;
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
+import org.eclipse.jdt.internal.core.search.processing.JobManager;
+import org.eclipse.jdt.internal.core.util.Util;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -82,6 +86,11 @@
 	public static final String FORMATTER_EXTPOINT_ID = "codeFormatter" ; //$NON-NLS-1$
 	
 	/**
+	 * Name of the extension point for contributing a search participant
+	 * TODO search participant
+	 */
+	public static final String SEARCH_PARTICIPANT_EXTPOINT_ID = "searchParticipant" ; //$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$
@@ -93,6 +102,7 @@
 		public String toString() { return getDescription(); }
 	};
 	
+	private static final String BUFFER_MANAGER_DEBUG = JavaCore.PLUGIN_ID + "/debug/buffermanager" ; //$NON-NLS-1$
 	private static final String INDEX_MANAGER_DEBUG = JavaCore.PLUGIN_ID + "/debug/indexmanager" ; //$NON-NLS-1$
 	private static final String COMPILER_DEBUG = JavaCore.PLUGIN_ID + "/debug/compiler" ; //$NON-NLS-1$
 	private static final String JAVAMODEL_DEBUG = JavaCore.PLUGIN_ID + "/debug/javamodel" ; //$NON-NLS-1$
@@ -104,10 +114,9 @@
 	private static final String BUILDER_DEBUG = JavaCore.PLUGIN_ID + "/debug/builder" ; //$NON-NLS-1$
 	private static final String COMPLETION_DEBUG = JavaCore.PLUGIN_ID + "/debug/completion" ; //$NON-NLS-1$
 	private static final String SELECTION_DEBUG = JavaCore.PLUGIN_ID + "/debug/selection" ; //$NON-NLS-1$
-	private static final String SHARED_WC_DEBUG = JavaCore.PLUGIN_ID + "/debug/sharedworkingcopy" ; //$NON-NLS-1$
 	private static final String SEARCH_DEBUG = JavaCore.PLUGIN_ID + "/debug/search" ; //$NON-NLS-1$
 
-	public final static IWorkingCopy[] NoWorkingCopy = new IWorkingCopy[0];
+	public final static ICompilationUnit[] NoWorkingCopy = new ICompilationUnit[0];
 	
 	/**
 	 * Returns whether the given full path (for a package) conflicts with the output location
@@ -184,6 +193,7 @@
 				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);
@@ -252,11 +262,11 @@
 	
 		if (file.getFileExtension() != null) {
 			String name = file.getName();
-			if (Util.isValidCompilationUnitName(name))
+			if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(name))
 				return createCompilationUnitFrom(file, project);
-			if (Util.isValidClassFileName(name))
+			if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name))
 				return createClassFileFrom(file, project);
-			if (Util.isArchiveFileName(name))
+			if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(name))
 				return createJarPackageFragmentRootFrom(file, project);
 		}
 		return null;
@@ -363,6 +373,7 @@
 				}
 			}
 		} catch (JavaModelException e) {
+			// project doesn't exist: return null
 		}
 		return null;
 	}
@@ -379,7 +390,7 @@
 		IPath resourcePath = resource.getFullPath();
 		try {
 			IClasspathEntry[] entries = 
-				Util.isJavaFileName(resourcePath.lastSegment())
+				org.eclipse.jdt.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);
 				
@@ -394,21 +405,17 @@
 					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('/', '.');
-						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);
 					}
+					String pkgName = Util.packageName(pkgPath);
+					if (pkgName == null || JavaConventions.validatePackageName(pkgName).getSeverity() == IStatus.ERROR) {
+						return null;
+					}
+					return root.getPackageFragment(pkgName);
 				}
 			}
 		} catch (JavaModelException npe) {
@@ -426,6 +433,11 @@
 	 * 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.
@@ -433,90 +445,93 @@
 	protected Map elementsOutOfSynchWithBuffers = new HashMap(11);
 	
 	/**
-	 * Turns delta firing on/off. By default it is on.
+	 * Holds the state used for delta processing.
 	 */
-	private boolean isFiring= true;
+	public DeltaProcessingState deltaState = new DeltaProcessingState();
 
-	/**
-	 * 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;
-
+	public IndexManager indexManager = new IndexManager();
+	
 	/**
 	 * 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);
+	protected Map perProjectInfos = new HashMap(5);
 	
 	/**
-	 * A map from ICompilationUnit to IWorkingCopy
-	 * of the shared working copies.
+	 * Table from WorkingCopyOwner to a table of IPath (working copy's path) to PerWorkingCopyInfo.
+	 * NOTE: this object itself is used as a lock to synchronize creation/removal of per working copy infos
 	 */
-	public Map sharedWorkingCopies = new HashMap();
+	protected Map perWorkingCopyInfos = new HashMap(5);
 	
 	/**
-	 * A weak set of the known scopes.
+	 * A weak set of the known search scopes.
 	 */
-	protected WeakHashMap scopes = new WeakHashMap();
+	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 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 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 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
+	 * (for a given thread, the object value is a HashMap from IPath to java.io.ZipFile)
 	 */
-	private HashMap zipFiles = new HashMap();
+	private ThreadLocal zipFiles = new ThreadLocal();
 	
 	
 	/**
@@ -545,47 +560,10 @@
 	}
 
 	/**
-	 * 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++;
+		// singleton: prevent others from creating a new instance
 	}
 
 	/**
@@ -593,36 +571,33 @@
 	 * 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());
-		}
+		if (this.zipFiles.get() != null) return;
+		this.zipFiles.set(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
+		if (this.zipFiles.get() != 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$
 			}
-			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) {
-			}
+			zipFile.close();
+		} catch (IOException e) {
+			// problem occured closing zip file: cannot do much more
 		}
 	}
-	
-
 
 	/**
 	 * Configure the plugin with respect to option settings defined in ".options" file
 	 */
 	public void configurePluginDebugOptions(){
 		if(JavaCore.getPlugin().isDebugging()){
-			String option = Platform.getDebugOption(BUILDER_DEBUG);
+			String option = Platform.getDebugOption(BUFFER_MANAGER_DEBUG);
+			if(option != null) BufferManager.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
+			
+			option = Platform.getDebugOption(BUILDER_DEBUG);
 			if(option != null) JavaBuilder.DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
 			
 			option = Platform.getDebugOption(COMPILER_DEBUG);
@@ -641,7 +616,7 @@
 			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$
+			if(option != null) JobManager.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
 			
 			option = Platform.getDebugOption(JAVAMODEL_DEBUG);
 			if(option != null) JavaModelManager.VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
@@ -655,183 +630,92 @@
 			option = Platform.getDebugOption(SELECTION_DEBUG);
 			if(option != null) SelectionEngine.DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
 
-			option = Platform.getDebugOption(SHARED_WC_DEBUG);
-			if(option != null) CompilationUnit.SHARED_WC_VERBOSE = 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.
+	 * Returns the new use count (or -1 if it didn't exist).
+	 */
+	public int discardPerWorkingCopyInfo(CompilationUnit workingCopy) throws JavaModelException {
+		synchronized(perWorkingCopyInfos) {
+			WorkingCopyOwner owner = workingCopy.owner;
+			Map pathToPerWorkingCopyInfos = (Map)this.perWorkingCopyInfos.get(owner);
+			if (pathToPerWorkingCopyInfos == null) return -1;
+			
+			IPath path = workingCopy.getPath();
+			PerWorkingCopyInfo info = (PerWorkingCopyInfo)pathToPerWorkingCopyInfos.get(path);
+			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
+				pathToPerWorkingCopyInfos.remove(path);
+				if (pathToPerWorkingCopyInfos.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) {
-			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();
+		// nothing to do for jdt.core
 	}
 
 	/**
 	 * 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) {
+		Thread currentThread = Thread.currentThread();
+		HashMap map = (HashMap)this.zipFiles.get();
+		if (map == null) return;
+		this.zipFiles.set(null);
+		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) {
+				// problem occured closing zip file: cannot do much more
 			}
-		}	
+		}
 	}
 	
-
+	public DeltaProcessor getDeltaProcessor() {
+		return this.deltaState.getDeltaProcessor();
+	}
 	
 	/** 
 	 * Returns the set of elements which are out of synch with their buffers.
@@ -840,66 +724,21 @@
 		return this.elementsOutOfSynchWithBuffers;
 	}
 
-	/**
-	 * 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);
-		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);
-	}
 	public IndexManager getIndexManager() {
-		return this.deltaProcessor.indexManager;
+		return this.indexManager;
 	}
 
 	/**
 	 *  Returns the info for the element.
 	 */
-	public Object getInfo(IJavaElement element) {
+	public synchronized Object getInfo(IJavaElement element) {
+		HashMap tempCache = (HashMap)this.temporaryCache.get();
+		if (tempCache != null) {
+			Object result = tempCache.get(element);
+			if (result != null) {
+				return result;
+			}
+		}
 		return this.cache.getInfo(element);
 	}
 
@@ -943,11 +782,11 @@
 	 * 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);
+		synchronized(perProjectInfos) { // use the perProjectInfo collection as its own lock
+			PerProjectInfo info= (PerProjectInfo) perProjectInfos.get(project);
 			if (info == null && create) {
 				info= new PerProjectInfo(project);
-				perProjectInfo.put(project, info);
+				perProjectInfos.put(project, info);
 			}
 			return info;
 		}
@@ -968,6 +807,44 @@
 		}
 		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, IPath path, boolean create, boolean recordUsage, IProblemRequestor problemRequestor) {
+		synchronized(perWorkingCopyInfos) { // use the perWorkingCopyInfo collection as its own lock
+			WorkingCopyOwner owner = workingCopy.owner;
+			Map pathToPerWorkingCopyInfos = (Map)this.perWorkingCopyInfos.get(owner);
+			if (pathToPerWorkingCopyInfos == null && create) {
+				pathToPerWorkingCopyInfos = new HashMap();
+				this.perWorkingCopyInfos.put(owner, pathToPerWorkingCopyInfos);
+			}
+
+			PerWorkingCopyInfo info = pathToPerWorkingCopyInfos == null ? null : (PerWorkingCopyInfo) pathToPerWorkingCopyInfos.get(path);
+			if (info == null && create) {
+				info= new PerWorkingCopyInfo(workingCopy, problemRequestor);
+				pathToPerWorkingCopyInfos.put(path, info);
+			}
+			if (info != null && recordUsage) info.useCount++;
+			return info;
+		}
+	}	
+	
+	/*
+	 * 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 name of the variables for which an CP variable initializer is registered through an extension point
@@ -1028,65 +905,84 @@
 		IPath workingLocation= project.getPluginWorkingLocation(descr);
 		return workingLocation.append("state.dat").toFile(); //$NON-NLS-1$
 	}
-
+	
+	/*
+	 * 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 pathToPerWorkingCopyInfos = (Map)perWorkingCopyInfos.get(owner);
+			if (pathToPerWorkingCopyInfos == null) return primaryWCs;
+			int primaryLength = primaryWCs == null ? 0 : primaryWCs.length;
+			int size = pathToPerWorkingCopyInfos.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 = pathToPerWorkingCopyInfos.values().iterator();
+			int index = primaryLength;
+			while(iterator.hasNext()) {
+				result[index++] = ((JavaModelManager.PerWorkingCopyInfo)iterator.next()).getWorkingCopy();
+			}
+			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.
+	 * of open ZipFiles. The path must be absolute.
 	 *
 	 * @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$
-			}
+		HashMap map;
+		ZipFile zipFile;
+		if ((map = (HashMap)this.zipFiles.get()) != null 
+				&& (zipFile = (ZipFile)map.get(path)) != null) {
+				
+			return zipFile;
 		}
+		String fileSystemPath= null;
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IResource file = root.findMember(path);
+		if (file != null) {
+			// internal resource
+			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 {
+			// external resource
+			fileSystemPath= path.toOSString();
+		}
+
+		try {
+			if (ZIP_ACCESS_VERBOSE) {
+				System.out.println("(" + Thread.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(IStatus.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 {
@@ -1130,6 +1026,7 @@
 				}
 			}
 		} catch(IOException e){
+			// problem loading xml file: nothing we can do
 		} finally {
 			if (xmlString != null){
 				ResourcesPlugin.getWorkspace().getRoot().setPersistentProperty(qName, null); // flush old one
@@ -1184,68 +1081,50 @@
 	}
 
 	/**
-	 * 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) {
+	 */
+	protected synchronized Object peekAtInfo(IJavaElement element) {
+		HashMap tempCache = (HashMap)this.temporaryCache.get();
+		if (tempCache != null) {
+			Object result = tempCache.get(element);
+			if (result != null) {
+				return result;
+			}
+		}
 		return this.cache.peekAtInfo(element);
 	}
 
 	/**
 	 * @see ISaveParticipant
 	 */
-	public void prepareToSave(ISaveContext context) throws CoreException {
+	public void prepareToSave(ISaveContext context) /*throws CoreException*/ {
+		// nothing to do
 	}
-	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) {
+		while (openedElement != null) {
+			if (!newElements.containsKey(openedElement)) {
+				break;
+			}
+			if (this.cache.peekAtInfo(openedElement) != null) {
+				return;
+			}
+			openedElement = openedElement.getParent();
+		}
+		
+		Iterator iterator = newElements.keySet().iterator();
+		while (iterator.hasNext()) {
+			IJavaElement element = (IJavaElement)iterator.next();
+			Object info = newElements.get(element);
+			this.cache.putInfo(element, info);
+		}
 	}
 
 	/**
@@ -1323,13 +1202,6 @@
 			}
 		}
 	}
-
-	/**
-	 * Registers the given delta with this manager.
-	 */
-	protected void registerJavaModelDelta(IJavaElementDelta delta) {
-		this.javaModelDeltas.add(delta);
-	}
 	
 	/**
 	 * Remembers the given scope in a weak set
@@ -1337,60 +1209,67 @@
 	 */
 	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); 
+		this.searchScopes.put(scope, null); 
 	}
-
-	/**
-	 * removeElementChangedListener method comment.
+	
+	/*
+	 * 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 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);
+	public synchronized Object removeInfoAndChildren(JavaElement element) throws JavaModelException {
+		Object info = 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;
 				}
-				
-				// 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;
+				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(perProjectInfos) { // use the perProjectInfo collection as its own lock
+			IProject project = javaProject.getProject();
+			PerProjectInfo info= (PerProjectInfo) perProjectInfos.get(project);
+			if (info != null) {
+				perProjectInfos.remove(project);
 			}
 		}
 	}
 	
-	protected void removeInfo(IJavaElement element) {
-		this.cache.removeInfo(element);
-	}
-
-	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){
+		// nothing to do
 	}
 
 	private void saveState(PerProjectInfo info, ISaveContext context) throws CoreException {
@@ -1426,12 +1305,20 @@
 				out.close();
 			}
 		} catch (RuntimeException e) {
-			try {file.delete();} catch(SecurityException se) {}
+			try {
+				file.delete();
+			} catch(SecurityException se) {
+				// could not delete file: cannot do much more
+			}
 			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) {}
+			try {
+				file.delete();
+			} catch(SecurityException se) {
+				// could not delete file: cannot do much more
+			}
 			throw new CoreException(
 				new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
 					Util.bind("build.cannotSaveState", info.project.getName()), e)); //$NON-NLS-1$
@@ -1456,7 +1343,7 @@
 		}
 
 		ArrayList vStats= null; // lazy initialized
-		for (Iterator iter =  perProjectInfo.values().iterator(); iter.hasNext();) {
+		for (Iterator iter =  perProjectInfos.values().iterator(); iter.hasNext();) {
 			try {
 				PerProjectInfo info = (PerProjectInfo) iter.next();
 				saveState(info, context);
@@ -1532,65 +1419,30 @@
 	 * 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 (JavaProject.hasJavaNature(project)) {
+			// 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) {}
+			} catch(SecurityException se) {
+				// could not delete file: cannot do much more
+			}
 		}
 	}
 
 	public void shutdown () {
-		if (this.deltaProcessor.indexManager != null){ // no more indexing
-			this.deltaProcessor.indexManager.shutdown();
+		if (this.indexManager != null){ // no more indexing
+			this.indexManager.shutdown();
 		}
-		try {
-			IJavaModel model = this.getJavaModel();
-			if (model != null) {
-				model.close();
-			}
-		} catch (JavaModelException e) {
-		}
+		// Note: no need to close the Java model as this just removes Java element infos from the Java model cache
 	}
-
-	/**
-	 * 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);
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java
index 047bc10..16a6eb8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java
@@ -17,7 +17,7 @@
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
 import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.internal.core.util.PerThreadObject;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Defines behavior common to all Java Model operations
@@ -67,87 +67,88 @@
 	 * or <code>null</code> if this operation
 	 * does not operate on specific elements.
 	 */
-	protected IJavaElement[] fElementsToProcess;
+	protected IJavaElement[] elementsToProcess;
 	/**
 	 * The parent elements this operation operates with
 	 * or <code>null</code> if this operation
 	 * does not operate with specific parent elements.
 	 */
-	protected IJavaElement[] fParentElements;
+	protected IJavaElement[] parentElements;
 	/**
 	 * An empty collection of <code>IJavaElement</code>s - the common
 	 * empty result if no elements are created, or if this
 	 * operation is not actually executed.
 	 */
-	protected static IJavaElement[] fgEmptyResult= new IJavaElement[] {};
+	protected static IJavaElement[] NO_ELEMENTS= new IJavaElement[] {};
 
 
 	/**
 	 * The elements created by this operation - empty
 	 * until the operation actually creates elements.
 	 */
-	protected IJavaElement[] fResultElements= fgEmptyResult;
+	protected IJavaElement[] resultElements= NO_ELEMENTS;
 
 	/**
 	 * The progress monitor passed into this operation
 	 */
-	protected IProgressMonitor fMonitor= null;
+	protected IProgressMonitor progressMonitor= null;
 	/**
 	 * A flag indicating whether this operation is nested.
 	 */
-	protected boolean fNested = false;
+	protected boolean isNested = false;
 	/**
 	 * Conflict resolution policy - by default do not force (fail on a conflict).
 	 */
-	protected boolean fForce= false;
+	protected boolean force = false;
 
 	/*
 	 * A per thread stack of java model operations (PerThreadObject of ArrayList).
 	 */
-	protected static PerThreadObject operationStacks = new PerThreadObject();
+	protected static ThreadLocal operationStacks = new ThreadLocal();
 	protected JavaModelOperation() {
+		// default constructor used in subclasses
 	}
 	/**
 	 * A common constructor for all Java Model operations.
 	 */
 	protected JavaModelOperation(IJavaElement[] elements) {
-		fElementsToProcess = elements;
+		this.elementsToProcess = elements;
 	}
 	/**
 	 * Common constructor for all Java Model operations.
 	 */
 	protected JavaModelOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements) {
-		fElementsToProcess = elementsToProcess;
-		fParentElements= parentElements;
+		this.elementsToProcess = elementsToProcess;
+		this.parentElements= parentElements;
 	}
 	/**
 	 * A common constructor for all Java Model operations.
 	 */
 	protected JavaModelOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements, boolean force) {
-		fElementsToProcess = elementsToProcess;
-		fParentElements= parentElements;
-		fForce= force;
+		this.elementsToProcess = elementsToProcess;
+		this.parentElements= parentElements;
+		this.force= force;
 	}
 	/**
 	 * A common constructor for all Java Model operations.
 	 */
 	protected JavaModelOperation(IJavaElement[] elements, boolean force) {
-		fElementsToProcess = elements;
-		fForce= force;
+		this.elementsToProcess = elements;
+		this.force= force;
 	}
 	
 	/**
 	 * Common constructor for all Java Model operations.
 	 */
 	protected JavaModelOperation(IJavaElement element) {
-		fElementsToProcess = new IJavaElement[]{element};
+		this.elementsToProcess = new IJavaElement[]{element};
 	}
 	/**
 	 * A common constructor for all Java Model operations.
 	 */
 	protected JavaModelOperation(IJavaElement element, boolean force) {
-		fElementsToProcess = new IJavaElement[]{element};
-		fForce= force;
+		this.elementsToProcess = new IJavaElement[]{element};
+		this.force= force;
 	}
 	
 	/*
@@ -164,13 +165,13 @@
 	 * Registers the given delta with the Java Model Manager.
 	 */
 	protected void addDelta(IJavaElementDelta delta) {
-		JavaModelManager.getJavaModelManager().registerJavaModelDelta(delta);
+		JavaModelManager.getJavaModelManager().getDeltaProcessor().registerJavaModelDelta(delta);
 	}
 	/*
 	 * Registers the given reconcile delta with the Java Model Manager.
 	 */
-	protected void addReconcileDelta(IWorkingCopy workingCopy, IJavaElementDelta delta) {
-		HashMap reconcileDeltas = JavaModelManager.getJavaModelManager().reconcileDeltas;
+	protected void addReconcileDelta(ICompilationUnit workingCopy, IJavaElementDelta delta) {
+		HashMap reconcileDeltas = JavaModelManager.getJavaModelManager().getDeltaProcessor().reconcileDeltas;
 		JavaElementDelta previousDelta = (JavaElementDelta)reconcileDeltas.get(workingCopy);
 		if (previousDelta != null) {
 			IJavaElementDelta[] children = delta.getAffectedChildren();
@@ -185,15 +186,15 @@
 	/*
 	 * Deregister the reconcile delta for the given working copy
 	 */
-	protected void removeReconcileDelta(IWorkingCopy workingCopy) {
-		JavaModelManager.getJavaModelManager().reconcileDeltas.remove(workingCopy);		
+	protected void removeReconcileDelta(ICompilationUnit workingCopy) {
+		JavaModelManager.getJavaModelManager().getDeltaProcessor().reconcileDeltas.remove(workingCopy);		
 	}
 	/**
 	 * @see IProgressMonitor
 	 */
 	public void beginTask(String name, int totalWork) {
-		if (fMonitor != null) {
-			fMonitor.beginTask(name, totalWork);
+		if (progressMonitor != null) {
+			progressMonitor.beginTask(name, totalWork);
 		}
 	}
 	/**
@@ -214,11 +215,11 @@
 	 * @see JavaModelOperation#verify()
 	 */
 	protected IJavaModelStatus commonVerify() {
-		if (fElementsToProcess == null || fElementsToProcess.length == 0) {
+		if (elementsToProcess == null || elementsToProcess.length == 0) {
 			return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
 		}
-		for (int i = 0; i < fElementsToProcess.length; i++) {
-			if (fElementsToProcess[i] == null) {
+		for (int i = 0; i < elementsToProcess.length; i++) {
+			if (elementsToProcess[i] == null) {
 				return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
 			}
 		}
@@ -240,12 +241,12 @@
 	/**
 	 * Convenience method to create a file
 	 */
-	protected void createFile(IContainer folder, String name, InputStream contents, boolean force) throws JavaModelException {
+	protected void createFile(IContainer folder, String name, InputStream contents, boolean forceFlag) throws JavaModelException {
 		IFile file= folder.getFile(new Path(name));
 		try {
 			file.create(
 				contents, 
-				force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
+				forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
 				getSubProgressMonitor(1));
 				this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
 		} catch (CoreException e) {
@@ -255,12 +256,12 @@
 	/**
 	 * Convenience method to create a folder
 	 */
-	protected void createFolder(IContainer parentFolder, String name, boolean force) throws JavaModelException {
+	protected void createFolder(IContainer parentFolder, String name, boolean forceFlag) throws JavaModelException {
 		IFolder folder= parentFolder.getFolder(new Path(name));
 		try {
 			// we should use true to create the file locally. Only VCM should use tru/false
 			folder.create(
-				force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
+				forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY,
 				true, // local
 				getSubProgressMonitor(1));
 				this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
@@ -273,7 +274,7 @@
 	 */
 	protected void deleteEmptyPackageFragment(
 		IPackageFragment fragment,
-		boolean force,
+		boolean forceFlag,
 		IResource rootResource)
 		throws JavaModelException {
 	
@@ -281,7 +282,7 @@
 	
 		try {
 			resource.delete(
-				force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
+				forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
 				getSubProgressMonitor(1));
 			this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
 			while (resource instanceof IFolder) {
@@ -290,7 +291,7 @@
 				resource = resource.getParent();
 				if (!resource.equals(rootResource) && resource.members().length == 0) {
 					resource.delete(
-						force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
+						forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
 						getSubProgressMonitor(1));
 					this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
 				}
@@ -313,14 +314,14 @@
 	/**
 	 * Convenience method to delete resources
 	 */
-	protected void deleteResources(IResource[] resources, boolean force) throws JavaModelException {
+	protected void deleteResources(IResource[] resources, boolean forceFlag) throws JavaModelException {
 		if (resources == null || resources.length == 0) return;
 		IProgressMonitor subProgressMonitor = getSubProgressMonitor(resources.length);
 		IWorkspace workspace = resources[0].getWorkspace();
 		try {
 			workspace.delete(
 				resources,
-				force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
+				forceFlag ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
 				subProgressMonitor);
 				this.setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE); 
 		} catch (CoreException e) {
@@ -331,8 +332,8 @@
 	 * @see IProgressMonitor
 	 */
 	public void done() {
-		if (fMonitor != null) {
-			fMonitor.done();
+		if (progressMonitor != null) {
+			progressMonitor.done();
 		}
 	}
 	/*
@@ -356,11 +357,9 @@
 	protected void execute() throws JavaModelException {
 		IJavaModelStatus status= verify();
 		if (status.isOK()) {
-			// if first time here, computes the root infos before executing the operation
-			DeltaProcessor deltaProcessor = JavaModelManager.getJavaModelManager().deltaProcessor;
-			if (deltaProcessor.roots == null) {
-				deltaProcessor.initializeRoots();
-			}
+			// computes the root infos before executing the operation
+			// noop if aready initialized
+			JavaModelManager.getJavaModelManager().deltaState.initializeRoots();
 
 			executeOperation();
 		} else {
@@ -423,10 +422,10 @@
 	 * Returns an empty stack if no operations are currently running in this thread. 
 	 */
 	protected ArrayList getCurrentOperationStack() {
-		ArrayList stack = (ArrayList)operationStacks.getCurrent();
+		ArrayList stack = (ArrayList)operationStacks.get();
 		if (stack == null) {
 			stack = new ArrayList();
-			operationStacks.setCurrent(stack);
+			operationStacks.set(stack);
 		}
 		return stack;
 	}
@@ -435,26 +434,26 @@
 	 * or <code>null</code> if not applicable.
 	 */
 	protected IJavaElement[] getElementsToProcess() {
-		return fElementsToProcess;
+		return elementsToProcess;
 	}
 	/**
 	 * Returns the element to which this operation applies,
 	 * or <code>null</code> if not applicable.
 	 */
 	protected IJavaElement getElementToProcess() {
-		if (fElementsToProcess == null || fElementsToProcess.length == 0) {
+		if (elementsToProcess == null || elementsToProcess.length == 0) {
 			return null;
 		}
-		return fElementsToProcess[0];
+		return elementsToProcess[0];
 	}
 	/**
 	 * Returns the Java Model this operation is operating in.
 	 */
 	public IJavaModel getJavaModel() {
-		if (fElementsToProcess == null || fElementsToProcess.length == 0) {
+		if (elementsToProcess == null || elementsToProcess.length == 0) {
 			return getParentElement().getJavaModel();
 		} else {
-			return fElementsToProcess[0].getJavaModel();
+			return elementsToProcess[0].getJavaModel();
 		}
 	}
 	protected IPath[] getNestedFolders(IPackageFragmentRoot root) throws JavaModelException {
@@ -479,31 +478,31 @@
 	 * or <code>null</code> if not applicable.
 	 */
 	protected IJavaElement getParentElement() {
-		if (fParentElements == null || fParentElements.length == 0) {
+		if (parentElements == null || parentElements.length == 0) {
 			return null;
 		}
-		return fParentElements[0];
+		return parentElements[0];
 	}
 	/**
 	 * Returns the parent elements to which this operation applies,
 	 * or <code>null</code> if not applicable.
 	 */
 	protected IJavaElement[] getParentElements() {
-		return fParentElements;
+		return parentElements;
 	}
 	/**
 	 * Returns the elements created by this operation.
 	 */
 	public IJavaElement[] getResultElements() {
-		return fResultElements;
+		return resultElements;
 	}
 	/**
 	 * Creates and returns a subprogress monitor if appropriate.
 	 */
 	protected IProgressMonitor getSubProgressMonitor(int workAmount) {
 		IProgressMonitor sub = null;
-		if (fMonitor != null) {
-			sub = new SubProgressMonitor(fMonitor, workAmount, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+		if (progressMonitor != null) {
+			sub = new SubProgressMonitor(progressMonitor, workAmount, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
 		}
 		return sub;
 	}
@@ -516,16 +515,16 @@
 		return !this.isReadOnly() && this.getAttribute(HAS_MODIFIED_RESOURCE_ATTR) == TRUE; 
 	}
 	public void internalWorked(double work) {
-		if (fMonitor != null) {
-			fMonitor.internalWorked(work);
+		if (progressMonitor != null) {
+			progressMonitor.internalWorked(work);
 		}
 	}
 	/**
 	 * @see IProgressMonitor
 	 */
 	public boolean isCanceled() {
-		if (fMonitor != null) {
-			return fMonitor.isCanceled();
+		if (progressMonitor != null) {
+			return progressMonitor.isCanceled();
 		}
 		return false;
 	}
@@ -563,8 +562,8 @@
 	 */
 	protected void moveResources(IResource[] resources, IPath destinationPath) throws JavaModelException {
 		IProgressMonitor subProgressMonitor = null;
-		if (fMonitor != null) {
-			subProgressMonitor = new SubProgressMonitor(fMonitor, resources.length, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
+		if (progressMonitor != null) {
+			subProgressMonitor = new SubProgressMonitor(progressMonitor, resources.length, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK);
 		}
 		IWorkspace workspace = resources[0].getWorkspace();
 		try {
@@ -590,7 +589,7 @@
 		int size = stack.size();
 		if (size > 0) {
 			if (size == 1) { // top level operation 
-				operationStacks.setCurrent(null); // release reference (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=33927)
+				operationStacks.set(null); // release reference (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=33927)
 			}
 			return (JavaModelOperation)stack.remove(size-1);
 		} else {
@@ -666,6 +665,25 @@
 	protected void pushOperation(JavaModelOperation operation) {
 		getCurrentOperationStack().add(operation);
 	}
+	/*
+	 * Removes all actions with the given id from the queue of post actions.
+	 * Does nothing if no such action is in the queue.
+	 */
+	protected void removeAllPostAction(String actionID) {
+		if (POST_ACTION_VERBOSE) {
+			System.out.println("(" + Thread.currentThread() + ") [JavaModelOperation.removeAllPostAction(String)] Removing actions " + actionID); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		
+		JavaModelOperation topLevelOp = (JavaModelOperation)getCurrentOperationStack().get(0);
+		IPostAction[] postActions = topLevelOp.actions;
+		if (postActions == null) return;
+		int index = this.actionsStart-1;
+		while ((index = topLevelOp.firstActionWithID(actionID, index+1)) >= 0) {
+			// remove action[index]
+			System.arraycopy(postActions, index+1, postActions, index, topLevelOp.actionsEnd - index);
+			postActions[topLevelOp.actionsEnd--] = null;
+		}
+	}
 	
 	/**
 	 * Main entry point for Java Model operations.  Executes this operation
@@ -676,9 +694,10 @@
 	 */
 	public void run(IProgressMonitor monitor) throws CoreException {
 		JavaModelManager manager = JavaModelManager.getJavaModelManager();
-		int previousDeltaCount = manager.javaModelDeltas.size();
+		DeltaProcessor deltaProcessor = manager.getDeltaProcessor();
+		int previousDeltaCount = deltaProcessor.javaModelDeltas.size();
 		try {
-			fMonitor = monitor;
+			progressMonitor = monitor;
 			pushOperation(this);
 			try {
 				this.execute();
@@ -690,8 +709,8 @@
 		} finally {
 			try {
 				// update JavaModel using deltas that were recorded during this operation
-				for (int i = previousDeltaCount, size = manager.javaModelDeltas.size(); i < size; i++) {
-					manager.updateJavaModel((IJavaElementDelta)manager.javaModelDeltas.get(i));
+				for (int i = previousDeltaCount, size = deltaProcessor.javaModelDeltas.size(); i < size; i++) {
+					deltaProcessor.updateJavaModel((IJavaElementDelta)deltaProcessor.javaModelDeltas.get(i));
 				}
 				
 				// fire only iff:
@@ -699,9 +718,9 @@
 				// - the operation did produce some delta(s)
 				// - but the operation has not modified any resource
 				if (this.isTopLevelOperation()) {
-					if ((manager.javaModelDeltas.size() > previousDeltaCount || !manager.reconcileDeltas.isEmpty()) 
+					if ((deltaProcessor.javaModelDeltas.size() > previousDeltaCount || !deltaProcessor.reconcileDeltas.isEmpty()) 
 							&& !this.hasModifiedResource()) {
-						manager.fire(null, JavaModelManager.DEFAULT_CHANGE_EVENT);
+						deltaProcessor.fire(null, DeltaProcessor.DEFAULT_CHANGE_EVENT);
 					} // else deltas are fired while processing the resource delta
 				}
 			} finally {
@@ -732,8 +751,8 @@
 	 * @see IProgressMonitor
 	 */
 	public void setCanceled(boolean b) {
-		if (fMonitor != null) {
-			fMonitor.setCanceled(b);
+		if (progressMonitor != null) {
+			progressMonitor.setCanceled(b);
 		}
 	}
 	/**
@@ -741,22 +760,22 @@
 	 * @see CreateElementInCUOperation#checkCanceled
 	 */
 	protected void setNested(boolean nested) {
-		fNested = nested;
+		isNested = nested;
 	}
 	/**
 	 * @see IProgressMonitor
 	 */
 	public void setTaskName(String name) {
-		if (fMonitor != null) {
-			fMonitor.setTaskName(name);
+		if (progressMonitor != null) {
+			progressMonitor.setTaskName(name);
 		}
 	}
 	/**
 	 * @see IProgressMonitor
 	 */
 	public void subTask(String name) {
-		if (fMonitor != null) {
-			fMonitor.subTask(name);
+		if (progressMonitor != null) {
+			progressMonitor.subTask(name);
 		}
 	}
 	/**
@@ -777,8 +796,8 @@
 	 * @see IProgressMonitor
 	 */
 	public void worked(int work) {
-		if (fMonitor != null) {
-			fMonitor.worked(work);
+		if (progressMonitor != null) {
+			progressMonitor.worked(work);
 			checkCanceled();
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
index f1ea5f2..d116030 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
@@ -24,6 +24,7 @@
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * @see IJavaModelStatus
@@ -35,22 +36,22 @@
 	 * The elements related to the failure, or <code>null</code>
 	 * if no elements are involved.
 	 */
-	protected IJavaElement[] fElements = new IJavaElement[0];
+	protected IJavaElement[] elements = new IJavaElement[0];
 	/**
 	 * The path related to the failure, or <code>null</code>
 	 * if no path is involved.
 	 */
-	protected IPath fPath;
+	protected IPath path;
 	/**
 	 * The <code>String</code> related to the failure, or <code>null</code>
 	 * if no <code>String</code> is involved.
 	 */
-	protected String fString;
+	protected String string;
 	/**
 	 * Empty children
 	 */
-	protected final static IStatus[] fgEmptyChildren = new IStatus[] {};
-	protected IStatus[] fChildren= fgEmptyChildren;
+	protected final static IStatus[] NO_CHILDREN = new IStatus[] {};
+	protected IStatus[] children= NO_CHILDREN;
 
 	/**
 	 * Singleton OK object
@@ -69,7 +70,7 @@
 	 */
 	public JavaModelStatus(int code) {
 		super(ERROR, JavaCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
-		fElements= JavaElementInfo.fgEmptyChildren;
+		this.elements= JavaElement.NO_ELEMENTS;
 	}
 	/**
 	 * Constructs an Java model status with the given corresponding
@@ -77,8 +78,8 @@
 	 */
 	public JavaModelStatus(int code, IJavaElement[] elements) {
 		super(ERROR, JavaCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
-		fElements= elements;
-		fPath= null;
+		this.elements= elements;
+		this.path= null;
 	}
 	/**
 	 * Constructs an Java model status with no corresponding elements.
@@ -91,24 +92,24 @@
 	 */
 	public JavaModelStatus(int severity, int code, String string) {
 		super(severity, JavaCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
-		fElements= JavaElementInfo.fgEmptyChildren;
-		fPath= null;
-		fString = string;
+		this.elements= JavaElement.NO_ELEMENTS;
+		this.path= null;
+		this.string = string;
 	}	
 	/**
 	 * Constructs an Java model status with no corresponding elements.
 	 */
 	public JavaModelStatus(int code, Throwable throwable) {
 		super(ERROR, JavaCore.PLUGIN_ID, code, "JavaModelStatus", throwable); //$NON-NLS-1$
-		fElements= JavaElementInfo.fgEmptyChildren;
+		this.elements= JavaElement.NO_ELEMENTS;
 	}
 	/**
 	 * Constructs an Java model status with no corresponding elements.
 	 */
 	public JavaModelStatus(int code, IPath path) {
 		super(ERROR, JavaCore.PLUGIN_ID, code, "JavaModelStatus", null); //$NON-NLS-1$
-		fElements= JavaElementInfo.fgEmptyChildren;
-		fPath= path;
+		this.elements= JavaElement.NO_ELEMENTS;
+		this.path= path;
 	}
 	/**
 	 * Constructs an Java model status with the given corresponding
@@ -123,7 +124,7 @@
 	 */
 	public JavaModelStatus(int code, IJavaElement element, String string) {
 		this(code, new IJavaElement[]{element});
-		fString = string;
+		this.string = string;
 	}
 	
 	/**
@@ -132,14 +133,23 @@
 	 */
 	public JavaModelStatus(int code, IJavaElement element, IPath path) {
 		this(code, new IJavaElement[]{element});
-		fPath = path;
+		this.path = path;
+	}	
+	/**
+	 * Constructs an Java model status with the given corresponding
+	 * element, path and string
+	 */
+	public JavaModelStatus(int code, IJavaElement element, IPath path, String string) {
+		this(code, new IJavaElement[]{element});
+		this.path = path;
+		this.string = string;
 	}	
 	/**
 	 * Constructs an Java model status with no corresponding elements.
 	 */
 	public JavaModelStatus(CoreException coreException) {
 		super(ERROR, JavaCore.PLUGIN_ID, CORE_EXCEPTION, "JavaModelStatus", coreException); //$NON-NLS-1$
-		fElements= JavaElementInfo.fgEmptyChildren;
+		elements= JavaElement.NO_ELEMENTS;
 	}
 	protected int getBits() {
 		int severity = 1 << (getCode() % 100 / 33);
@@ -150,13 +160,13 @@
 	 * @see IStatus
 	 */
 	public IStatus[] getChildren() {
-		return fChildren;
+		return children;
 	}
 	/**
 	 * @see IJavaModelStatus
 	 */
 	public IJavaElement[] getElements() {
-		return fElements;
+		return elements;
 	}
 	/**
 	 * Returns the message that is relevant to the code of this status.
@@ -181,10 +191,10 @@
 					return Util.bind("status.JDOMError"); //$NON-NLS-1$
 
 				case ELEMENT_DOES_NOT_EXIST:
-					return Util.bind("element.doesNotExist",((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$
+					return Util.bind("element.doesNotExist",((JavaElement)elements[0]).toStringWithAncestors()); //$NON-NLS-1$
 
 				case EVALUATION_ERROR:
-					return Util.bind("status.evaluationError", fString); //$NON-NLS-1$
+					return Util.bind("status.evaluationError", string); //$NON-NLS-1$
 
 				case INDEX_OUT_OF_BOUNDS:
 					return Util.bind("status.indexOutOfBounds"); //$NON-NLS-1$
@@ -193,60 +203,60 @@
 					return Util.bind("status.invalidContents"); //$NON-NLS-1$
 
 				case INVALID_DESTINATION:
-					return Util.bind("status.invalidDestination", ((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$
+					return Util.bind("status.invalidDestination", ((JavaElement)elements[0]).toStringWithAncestors()); //$NON-NLS-1$
 
 				case INVALID_ELEMENT_TYPES:
 					StringBuffer buff= new StringBuffer(Util.bind("operation.notSupported")); //$NON-NLS-1$
-					for (int i= 0; i < fElements.length; i++) {
+					for (int i= 0; i < elements.length; i++) {
 						if (i > 0) {
 							buff.append(", "); //$NON-NLS-1$
 						}
-						buff.append(((JavaElement)fElements[i]).toStringWithAncestors());
+						buff.append(((JavaElement)elements[i]).toStringWithAncestors());
 					}
 					return buff.toString();
 
 				case INVALID_NAME:
-					return Util.bind("status.invalidName", fString); //$NON-NLS-1$
+					return Util.bind("status.invalidName", string); //$NON-NLS-1$
 
 				case INVALID_PACKAGE:
-					return Util.bind("status.invalidPackage", fString); //$NON-NLS-1$
+					return Util.bind("status.invalidPackage", string); //$NON-NLS-1$
 
 				case INVALID_PATH:
-					if (fString != null) {
-						return fString;
+					if (string != null) {
+						return string;
 					} else {
 						return Util.bind("status.invalidPath", getPath() == null ? "null" : getPath().toString()); //$NON-NLS-1$ //$NON-NLS-2$
 					}
 
 				case INVALID_PROJECT:
-					return Util.bind("status.invalidProject", fString); //$NON-NLS-1$
+					return Util.bind("status.invalidProject", string); //$NON-NLS-1$
 
 				case INVALID_RESOURCE:
-					return Util.bind("status.invalidResource", fString); //$NON-NLS-1$
+					return Util.bind("status.invalidResource", string); //$NON-NLS-1$
 
 				case INVALID_RESOURCE_TYPE:
-					return Util.bind("status.invalidResourceType", fString); //$NON-NLS-1$
+					return Util.bind("status.invalidResourceType", string); //$NON-NLS-1$
 
 				case INVALID_SIBLING:
-					if (fString != null) {
-						return Util.bind("status.invalidSibling", fString); //$NON-NLS-1$
+					if (string != null) {
+						return Util.bind("status.invalidSibling", string); //$NON-NLS-1$
 					} else {
-						return Util.bind("status.invalidSibling", ((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$
+						return Util.bind("status.invalidSibling", ((JavaElement)elements[0]).toStringWithAncestors()); //$NON-NLS-1$
 					}
 
 				case IO_EXCEPTION:
 					return Util.bind("status.IOException"); //$NON-NLS-1$
 
 				case NAME_COLLISION:
-					if (fElements != null && fElements.length > 0) {
-						IJavaElement element = fElements[0];
+					if (elements != null && elements.length > 0) {
+						IJavaElement element = elements[0];
 						String name = element.getElementName();
 						if (element instanceof IPackageFragment && name.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) {
 							return Util.bind("operation.cannotRenameDefaultPackage"); //$NON-NLS-1$
 						}
 					}
-					if (fString != null) {
-						return fString;
+					if (string != null) {
+						return string;
 					} else {
 						return Util.bind("status.nameCollision", ""); //$NON-NLS-1$ //$NON-NLS-2$
 					}
@@ -263,10 +273,10 @@
 					return Util.bind("operation.needString"); //$NON-NLS-1$
 
 				case PATH_OUTSIDE_PROJECT:
-					return Util.bind("operation.pathOutsideProject", fString, ((JavaElement)fElements[0]).toStringWithAncestors()); //$NON-NLS-1$
+					return Util.bind("operation.pathOutsideProject", string, ((JavaElement)elements[0]).toStringWithAncestors()); //$NON-NLS-1$
 
 				case READ_ONLY:
-					IJavaElement element = fElements[0];
+					IJavaElement element = elements[0];
 					String name = element.getElementName();
 					if (element instanceof IPackageFragment && name.equals(IPackageFragment.DEFAULT_PACKAGE_NAME)) {
 						return Util.bind("status.defaultPackageReadOnly"); //$NON-NLS-1$
@@ -286,22 +296,21 @@
 					return Util.bind("status.noLocalContents", getPath().toString()); //$NON-NLS-1$
 
 				case CP_CONTAINER_PATH_UNBOUND:
-					IPath path = this.fPath;
-					IJavaProject javaProject = (IJavaProject)fElements[0];
-					ClasspathContainerInitializer initializer = JavaCore.getClasspathContainerInitializer(path.segment(0));
+					IJavaProject javaProject = (IJavaProject)elements[0];
+					ClasspathContainerInitializer initializer = JavaCore.getClasspathContainerInitializer(this.path.segment(0));
 					String description = null;
-					if (initializer != null) description = initializer.getDescription(path, javaProject);
+					if (initializer != null) description = initializer.getDescription(this.path, javaProject);
 					if (description == null) description = path.makeRelative().toString();
-					return Util.bind("classpath.unboundContainerPath", description); //$NON-NLS-1$
+					return Util.bind("classpath.unboundContainerPath", description, javaProject.getElementName()); //$NON-NLS-1$
 
 				case INVALID_CP_CONTAINER_ENTRY:
-					path = this.fPath;
-					javaProject = (IJavaProject)fElements[0];
+					javaProject = (IJavaProject)elements[0];
 					IClasspathContainer container = null;
 					description = null;
 					try {
 						container = JavaCore.getClasspathContainer(path, javaProject);
 					} catch(JavaModelException e){
+						// project doesn't exist: ignore
 					}
 					if (container == null) {
 						 initializer = JavaCore.getClasspathContainerInitializer(path.segment(0));
@@ -310,26 +319,45 @@
 						description = container.getDescription();
 					}
 					if (description == null) description = path.makeRelative().toString();
-					return Util.bind("classpath.invalidContainer", description); //$NON-NLS-1$
+					return Util.bind("classpath.invalidContainer", description, javaProject.getElementName()); //$NON-NLS-1$
 
 			case CP_VARIABLE_PATH_UNBOUND:
-					path = this.fPath;
-					return Util.bind("classpath.unboundVariablePath", path.makeRelative().toString()); //$NON-NLS-1$
+				javaProject = (IJavaProject)elements[0];
+				return Util.bind("classpath.unboundVariablePath", path.makeRelative().toString(), javaProject.getElementName()); //$NON-NLS-1$
 					
 			case CLASSPATH_CYCLE: 
-					javaProject = (IJavaProject)fElements[0];
-					return Util.bind("classpath.cycle", javaProject.getElementName()); //$NON-NLS-1$
+				javaProject = (IJavaProject)elements[0];
+				return Util.bind("classpath.cycle", javaProject.getElementName()); //$NON-NLS-1$
 												 
 			case DISABLED_CP_EXCLUSION_PATTERNS:
-					path = this.fPath;
-					return Util.bind("classpath.disabledExclusionPatterns", path.makeRelative().toString()); //$NON-NLS-1$
+				javaProject = (IJavaProject)elements[0];
+				String projectName = javaProject.getElementName();
+				IPath newPath = path;
+				if (path.segment(0).toString().equals(projectName)) {
+					newPath = path.removeFirstSegments(1);
+				}
+				return Util.bind("classpath.disabledExclusionPatterns", newPath.makeRelative().toString(), projectName); //$NON-NLS-1$
 
 			case DISABLED_CP_MULTIPLE_OUTPUT_LOCATIONS:
-					path = this.fPath;
-					return Util.bind("classpath.disabledMultipleOutputLocations", path.makeRelative().toString()); //$NON-NLS-1$
+				javaProject = (IJavaProject)elements[0];
+				projectName = javaProject.getElementName();
+				newPath = path;
+				if (path.segment(0).toString().equals(projectName)) {
+					newPath = path.removeFirstSegments(1);
+				}
+				return Util.bind("classpath.disabledMultipleOutputLocations", newPath.makeRelative().toString(), projectName); //$NON-NLS-1$
+
+			case INCOMPATIBLE_JDK_LEVEL:
+					javaProject = (IJavaProject)elements[0];
+					return Util.bind("classpath.incompatibleLibraryJDKLevel", new String[]{	//$NON-NLS-1$
+						javaProject.getElementName(), 
+						javaProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true), 
+						path.makeRelative().toString(),
+						string,
+					});
 			}
-			if (fString != null) {
-				return fString;
+			if (string != null) {
+				return string;
 			} else {
 				return ""; // //$NON-NLS-1$
 			}
@@ -346,16 +374,16 @@
 	 * @see IJavaModelStatus#getPath()
 	 */
 	public IPath getPath() {
-		return fPath;
+		return path;
 	}
 	/**
 	 * @see IStatus#getSeverity()
 	 */
 	public int getSeverity() {
-		if (fChildren == fgEmptyChildren) return super.getSeverity();
+		if (children == NO_CHILDREN) return super.getSeverity();
 		int severity = -1;
-		for (int i = 0, max = fChildren.length; i < max; i++) {
-			int childrenSeverity = fChildren[i].getSeverity();
+		for (int i = 0, max = children.length; i < max; i++) {
+			int childrenSeverity = children[i].getSeverity();
 			if (childrenSeverity > severity) {
 				severity = childrenSeverity;
 			}
@@ -367,7 +395,7 @@
 	 * @deprecated
 	 */
 	public String getString() {
-		return fString;
+		return string;
 	}
 	/**
 	 * @see IJavaModelStatus#isDoesNotExist()
@@ -379,7 +407,7 @@
 	 * @see IStatus#isMultiStatus()
 	 */
 	public boolean isMultiStatus() {
-		return fChildren != fgEmptyChildren;
+		return children != NO_CHILDREN;
 	}
 	/**
 	 * @see IStatus#isOK()
@@ -394,8 +422,8 @@
 		if (! isMultiStatus()) {
 			return matches(this, mask);
 		} else {
-			for (int i = 0, max = fChildren.length; i < max; i++) {
-				if (matches((JavaModelStatus) fChildren[i], mask))
+			for (int i = 0, max = children.length; i < max; i++) {
+				if (matches((JavaModelStatus) children[i], mask))
 					return true;
 			}
 			return false;
@@ -418,7 +446,7 @@
 	 */
 	public static IJavaModelStatus newMultiStatus(IJavaModelStatus[] children) {
 		JavaModelStatus jms = new JavaModelStatus();
-		jms.fChildren = children;
+		jms.children = children;
 		return jms;
 	}
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
index dd29624..5e59741 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -10,27 +10,71 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import java.io.*;
-import java.util.*; 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.StringTokenizer;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
-import org.apache.xerces.dom.DocumentImpl;
-import org.apache.xml.serialize.Method;
-import org.apache.xml.serialize.OutputFormat;
-import org.apache.xml.serialize.Serializer;
-import org.apache.xml.serialize.SerializerFactory;
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
-import org.eclipse.jdt.core.*;
+import org.eclipse.core.resources.ICommand;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IProjectNature;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+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.Path;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.jdt.core.IClasspathContainer;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaModelMarker;
+import org.eclipse.jdt.core.IJavaModelStatus;
+import org.eclipse.jdt.core.IJavaModelStatusConstants;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IRegion;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeHierarchy;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.WorkingCopyOwner;
 import org.eclipse.jdt.core.eval.IEvaluationContext;
 import org.eclipse.jdt.internal.codeassist.ISearchableNameEnvironment;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.eval.EvaluationContextWrapper;
+import org.eclipse.jdt.internal.core.util.Util;
 import org.eclipse.jdt.internal.eval.EvaluationContext;
-import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
@@ -57,7 +101,7 @@
  */
 public class JavaProject
 	extends Openable
-	implements IJavaProject, IProjectNature {
+	implements IJavaProject, IProjectNature, SuffixConstants {
 
 	/**
 	 * Whether the underlying file system is case sensitive.
@@ -72,7 +116,7 @@
 	/**
 	 * The platform project this <code>IJavaProject</code> is based on
 	 */
-	protected IProject fProject;
+	protected IProject project;
 	
 	/**
 	 * Name of file containing project classpath
@@ -95,7 +139,9 @@
 	 * Returns a canonicalized path from the given external path.
 	 * Note that the return path contains the same number of segments
 	 * and it contains a device only if the given path contained one.
+	 * @param externalPath IPath
 	 * @see java.io.File for the definition of a canonicalized path
+	 * @return IPath
 	 */
 	public static IPath canonicalizedPath(IPath externalPath) {
 		
@@ -172,15 +218,15 @@
 	/**
 	 * Constructor needed for <code>IProject.getNature()</code> and <code>IProject.addNature()</code>.
 	 *
-	 * @see #setProject
+	 * @see #setProject(IProject)
 	 */
 	public JavaProject() {
-		super(JAVA_PROJECT, null, null);
+		super(null, null);
 	}
 
-	public JavaProject(IProject project, IJavaElement parent) {
-		super(JAVA_PROJECT, parent, project.getName());
-		fProject = project;
+	public JavaProject(IProject project, JavaElement parent) {
+		super(parent, project.getName());
+		this.project = project;
 	}
 
 	/**
@@ -188,7 +234,7 @@
 	 */
 	protected void addToBuildSpec(String builderID) throws CoreException {
 
-		IProjectDescription description = getProject().getDescription();
+		IProjectDescription description = this.project.getDescription();
 		ICommand javaCommand = getJavaCommand(description);
 
 		if (javaCommand == null) {
@@ -200,18 +246,83 @@
 		}
 	}
 
-	protected void closing(Object info) throws JavaModelException {
+	/**
+	 * @see Openable
+	 */
+	protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
+	
+		// check whether the java project can be opened
+		if (!underlyingResource.isAccessible()) {
+			throw newNotPresentException();
+		}
+		
+		IWorkspace workspace = ResourcesPlugin.getWorkspace();
+		IWorkspaceRoot wRoot = workspace.getRoot();
+		// cannot refresh cp markers on opening (emulate cp check on startup) since can create deadlocks (see bug 37274)
+		IClasspathEntry[] resolvedClasspath = getResolvedClasspath(true/*ignore unresolved variable*/);
+
+		// compute the pkg fragment roots
+		computeChildren((JavaProjectElementInfo)info);				
+
+		// remember the timestamps of external libraries the first time they are looked up
+		for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
+			IClasspathEntry entry = resolvedClasspath[i];
+			if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
+				IPath path = entry.getPath();
+				Object target = JavaModel.getTarget(wRoot, path, true);
+				if (target instanceof java.io.File) {
+					Map externalTimeStamps = JavaModelManager.getJavaModelManager().deltaState.externalTimeStamps;
+					if (externalTimeStamps.get(path) == null) {
+						long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target);
+						externalTimeStamps.put(path, new Long(timestamp));							
+					}
+				}
+			}
+		}			
+
+		return true;
+	}
+	protected void closing(Object info) {
 		
 		// forget source attachment recommendations
-		IPackageFragmentRoot[] roots = this.getPackageFragmentRoots();
-		for (int i = 0; i < roots.length; i++) {
-			if (roots[i] instanceof JarPackageFragmentRoot){
-				((JarPackageFragmentRoot) roots[i]).setSourceAttachmentProperty(null); 
+		Object[] children = ((JavaElementInfo)info).children;
+		for (int i = 0, length = children.length; i < length; i++) {
+			Object child = children[i];
+			if (child instanceof JarPackageFragmentRoot){
+				((JarPackageFragmentRoot)child).setSourceAttachmentProperty(null); 
 			}
 		}
 		
 		super.closing(info);
 	}
+	/**
+	 * Computes the collection of package fragment roots (local ones) and set it on the given info.
+	 * Need to check *all* package fragment roots in order to reset NameLookup
+	 * @param info JavaProjectElementInfo
+	 * @throws JavaModelException
+	 */
+	public void computeChildren(JavaProjectElementInfo info) throws JavaModelException {
+		IClasspathEntry[] classpath = getResolvedClasspath(true);
+		NameLookup lookup = info.getNameLookup();
+		if (lookup != null){
+			IPackageFragmentRoot[] oldRoots = lookup.fPackageFragmentRoots;
+			IPackageFragmentRoot[] newRoots = computePackageFragmentRoots(classpath, true);
+			checkIdentical: { // compare all pkg fragment root lists
+				if (oldRoots.length == newRoots.length){
+					for (int i = 0, length = oldRoots.length; i < length; i++){
+						if (!oldRoots[i].equals(newRoots[i])){
+							break checkIdentical;
+						}
+					}
+					return; // no need to update
+				}	
+			}
+			info.setNameLookup(null); // discard name lookup (hold onto roots)
+		}				
+		info.setNonJavaResources(null);
+		info.setChildren(
+			computePackageFragmentRoots(classpath, false));		
+	}
 	
 
 
@@ -224,41 +335,45 @@
 		boolean ignoreUnresolvedVariable,
 		boolean generateMarkerOnError,
 		HashSet visitedProjects, 
-		ObjectVector accumulatedEntries) throws JavaModelException {
+		ObjectVector accumulatedEntries,
+		Map preferredClasspaths,
+		Map preferredOutputs) throws JavaModelException {
 		
 		if (visitedProjects.contains(this)){
 			return; // break cycles if any
 		}
 		visitedProjects.add(this);
 
-		if (generateMarkerOnError && !this.equals(initialProject)){
-			generateMarkerOnError = false;
-		}
+		IClasspathEntry[] preferredClasspath = preferredClasspaths != null ? (IClasspathEntry[])preferredClasspaths.get(this) : null;
+		IPath preferredOutput = preferredOutputs != null ? (IPath)preferredOutputs.get(this) : null;
 		IClasspathEntry[] immediateClasspath = 
-			getResolvedClasspath(ignoreUnresolvedVariable, generateMarkerOnError);
+			preferredClasspath != null 
+				? getResolvedClasspath(preferredClasspath, preferredOutput, ignoreUnresolvedVariable, generateMarkerOnError, null)
+				: getResolvedClasspath(ignoreUnresolvedVariable, generateMarkerOnError);
 			
 		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
+		boolean isInitialProject = this.equals(initialProject);
 		for (int i = 0, length = immediateClasspath.length; i < length; i++){
 			IClasspathEntry entry = immediateClasspath[i];
-
-			boolean isInitialProject = this.equals(initialProject);
 			if (isInitialProject || entry.isExported()){
 				
 				accumulatedEntries.add(entry);
 				
 				// recurse in project to get all its indirect exports (only consider exported entries from there on)				
-				if (entry.getEntryKind() == ClasspathEntry.CPE_PROJECT) {
+				if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
 					IResource member = workspaceRoot.findMember(entry.getPath()); 
 					if (member != null && member.getType() == IResource.PROJECT){ // double check if bound to project (23977)
 						IProject projRsc = (IProject) member;
 						if (JavaProject.hasJavaNature(projRsc)) {				
-							JavaProject project = (JavaProject) JavaCore.create(projRsc);
-							project.computeExpandedClasspath(
+							JavaProject javaProject = (JavaProject) JavaCore.create(projRsc);
+							javaProject.computeExpandedClasspath(
 								initialProject, 
 								ignoreUnresolvedVariable, 
-								generateMarkerOnError,
+								false /* no marker when recursing in prereq*/,
 								visitedProjects, 
-								accumulatedEntries);
+								accumulatedEntries,
+								preferredClasspaths,
+								preferredOutputs);
 						}
 					}
 				}
@@ -271,6 +386,10 @@
 	 * Note: this follows project classpath references to find required project contributions,
 	 * eliminating duplicates silently.
 	 * Only works with resolved entries
+	 * @param resolvedClasspath IClasspathEntry[]
+	 * @param retrieveExportedRoots boolean
+	 * @return IPackageFragmentRoot[]
+	 * @throws JavaModelException
 	 */
 	public IPackageFragmentRoot[] computePackageFragmentRoots(IClasspathEntry[] resolvedClasspath, boolean retrieveExportedRoots) throws JavaModelException {
 
@@ -290,6 +409,8 @@
 	/**
 	 * Computes the package fragment roots identified by the given entry.
 	 * Only works with resolved entry
+	 * @param resolvedEntry IClasspathEntry
+	 * @return IPackageFragmentRoot[]
 	 */
 	public IPackageFragmentRoot[] computePackageFragmentRoots(IClasspathEntry resolvedEntry) {
 		try {
@@ -307,6 +428,13 @@
 	 * Returns the package fragment roots identified by the given entry. In case it refers to
 	 * a project, it will follow its classpath so as to find exported roots as well.
 	 * Only works with resolved entry
+	 * @param resolvedEntry IClasspathEntry
+	 * @param accumulatedRoots ObjectVector
+	 * @param rootIDs HashSet
+	 * @param insideOriginalProject boolean
+	 * @param checkExistency boolean
+	 * @param retrieveExportedRoots boolean
+	 * @throws JavaModelException
 	 */
 	public void computePackageFragmentRoots(
 		IClasspathEntry resolvedEntry,
@@ -319,7 +447,7 @@
 		String rootID = ((ClasspathEntry)resolvedEntry).rootID();
 		if (rootIDs.contains(rootID)) return;
 
-		IPath projectPath = getProject().getFullPath();
+		IPath projectPath = this.project.getFullPath();
 		IPath entryPath = resolvedEntry.getPath();
 		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
 		
@@ -367,7 +495,7 @@
 						}
 					} else {
 						// external target - only JARs allowed
-						if (((java.io.File)target).isFile() && (Util.isArchiveFileName(entryPath.lastSegment()))) {
+						if (((java.io.File)target).isFile() && (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(entryPath.lastSegment()))) {
 							accumulatedRoots.add(
 								new JarPackageFragmentRoot(entryPath, this));
 							rootIDs.add(rootID);
@@ -412,6 +540,13 @@
 	 * Note: this follows project classpath references to find required project contributions,
 	 * eliminating duplicates silently.
 	 * Only works with resolved entries
+	 * @param resolvedClasspath IClasspathEntry[]
+	 * @param accumulatedRoots ObjectVector
+	 * @param rootIDs HashSet
+	 * @param insideOriginalProject boolean
+	 * @param checkExistency boolean
+	 * @param retrieveExportedRoots boolean
+	 * @throws JavaModelException
 	 */
 	public void computePackageFragmentRoots(
 		IClasspathEntry[] resolvedClasspath,
@@ -437,6 +572,8 @@
 
 	/**
 	 * Compute the file name to use for a given shared property
+	 * @param qName QualifiedName
+	 * @return String
 	 */
 	public String computeSharedPropertyFileName(QualifiedName qName) {
 
@@ -496,10 +633,10 @@
 			switch (innerMostEntry.getEntryKind()) {
 				case IClasspathEntry.CPE_SOURCE:
 					// .class files are not visible in source folders 
-					return !Util.isClassFileName(fullPath.lastSegment());
+					return !org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(fullPath.lastSegment());
 				case IClasspathEntry.CPE_LIBRARY:
 					// .java files are not visible in library folders
-					return !Util.isJavaFileName(fullPath.lastSegment());
+					return !org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(fullPath.lastSegment());
 			}
 		}
 		if (innerMostOutput != null) {
@@ -511,14 +648,14 @@
 	/**
 	 * Record a new marker denoting a classpath problem
 	 */
-	IMarker createClasspathProblemMarker(IJavaModelStatus status) {
+	void createClasspathProblemMarker(IJavaModelStatus status) {
 			
 		IMarker marker = null;
 		int severity;
 		String[] arguments = new String[0];
 		boolean isCycleProblem = false, isClasspathFileFormatProblem = false;
 		switch (status.getCode()) {
-
+	
 			case  IJavaModelStatusConstants.CLASSPATH_CYCLE :
 				isCycleProblem = true;
 				if (JavaCore.ERROR.equals(getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true))) {
@@ -527,12 +664,23 @@
 					severity = IMarker.SEVERITY_WARNING;
 				}
 				break;
-
+	
 			case  IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT :
 				isClasspathFileFormatProblem = true;
 				severity = IMarker.SEVERITY_ERROR;
 				break;
-
+	
+			case  IJavaModelStatusConstants.INCOMPATIBLE_JDK_LEVEL :
+				String setting = getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true);
+				if (JavaCore.ERROR.equals(setting)) {
+					severity = IMarker.SEVERITY_ERROR;
+				} else if (JavaCore.WARNING.equals(setting)) {
+					severity = IMarker.SEVERITY_WARNING;
+				} else {
+					return; // setting == IGNORE
+				}
+				break;
+				
 			default:
 				IPath path = status.getPath();
 				if (path != null) arguments = new String[] { path.toString() };
@@ -545,7 +693,7 @@
 		}
 		
 		try {
-			marker = getProject().createMarker(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER);
+			marker = this.project.createMarker(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER);
 			marker.setAttributes(
 				new String[] { 
 					IMarker.MESSAGE, 
@@ -567,15 +715,16 @@
 				}
 			);
 		} catch (CoreException e) {
+			// could not create marker: cannot do much
+			// TODO (jerome) print stack trace in VERBOSE mode only
+			e.printStackTrace();
 		}
-		return marker;
 	}
 	
 	/**
 	 * Returns a new element info for this element.
 	 */
-	protected OpenableElementInfo createElementInfo() {
-
+	protected Object createElementInfo() {
 		return new JavaProjectElementInfo();
 	}
 
@@ -624,7 +773,7 @@
 			}
 		} catch (IOException e) {
 			// bad format
-			if (createMarker && this.getProject().isAccessible()) {
+			if (createMarker && this.project.isAccessible()) {
 					this.createClasspathProblemMarker(new JavaModelStatus(
 							IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
 							Util.bind("classpath.xmlFormatError", this.getElementName(), e.getMessage()))); //$NON-NLS-1$
@@ -637,7 +786,7 @@
 			return INVALID_CLASSPATH;
 		} catch (Assert.AssertionFailedException e) { 
 			// failed creating CP entries from file
-			if (createMarker && this.getProject().isAccessible()) {
+			if (createMarker && this.project.isAccessible()) {
 				this.createClasspathProblemMarker(new JavaModelStatus(
 						IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
 						Util.bind("classpath.illegalEntryInClasspathFile", this.getElementName(), e.getMessage()))); //$NON-NLS-1$
@@ -674,58 +823,47 @@
 	 * Returns a default class path.
 	 * This is the root of the project
 	 */
-	protected IClasspathEntry[] defaultClasspath() throws JavaModelException {
+	protected IClasspathEntry[] defaultClasspath() {
 
 		return new IClasspathEntry[] {
-			 JavaCore.newSourceEntry(getProject().getFullPath())};
+			 JavaCore.newSourceEntry(this.project.getFullPath())};
 	}
 
 	/**
 	 * Returns a default output location.
 	 * This is the project bin folder
 	 */
-	protected IPath defaultOutputLocation() throws JavaModelException {
-		return getProject().getFullPath().append("bin"); //$NON-NLS-1$
+	protected IPath defaultOutputLocation() {
+		return this.project.getFullPath().append("bin"); //$NON-NLS-1$
 	}
 
 	/**
 	 * Returns the XML String encoding of the class path.
 	 */
-	protected String encodeClasspath(IClasspathEntry[] classpath, IPath outputLocation, boolean useLineSeparator) throws JavaModelException {
-
-		Document document = new DocumentImpl();
-		Element cpElement = document.createElement("classpath"); //$NON-NLS-1$
-		document.appendChild(cpElement);
-
-		for (int i = 0; i < classpath.length; ++i) {
-			cpElement.appendChild(((ClasspathEntry)classpath[i]).elementEncode(document, getProject().getFullPath()));
-		}
-
-		if (outputLocation != null) {
-			outputLocation = outputLocation.removeFirstSegments(1);
-			outputLocation = outputLocation.makeRelative();
-			Element oElement = document.createElement("classpathentry"); //$NON-NLS-1$
-			oElement.setAttribute("kind", ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT));	//$NON-NLS-1$
-			oElement.setAttribute("path", outputLocation.toString()); //$NON-NLS-1$
-			cpElement.appendChild(oElement);
-		}
-
-		// produce a String output
+	protected String encodeClasspath(IClasspathEntry[] classpath, IPath outputLocation, boolean indent) throws JavaModelException {
 		try {
 			ByteArrayOutputStream s = new ByteArrayOutputStream();
-			OutputFormat format = new OutputFormat();
-			if (useLineSeparator) {
-				format.setIndenting(true);
-				format.setLineSeparator(System.getProperty("line.separator"));  //$NON-NLS-1$
-			} else {
-				format.setPreserveSpace(true);
-			}			
-			Serializer serializer =
-				SerializerFactory.getSerializerFactory(Method.XML).makeSerializer(
-					new OutputStreamWriter(s, "UTF8"), //$NON-NLS-1$
-					format);
-			serializer.asDOMSerializer().serialize(document);
-			return s.toString("UTF8"); //$NON-NLS-1$
+			OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); //$NON-NLS-1$
+			XMLWriter xmlWriter = new XMLWriter(writer);
+			
+			xmlWriter.startTag("classpath", indent); //$NON-NLS-1$
+			for (int i = 0; i < classpath.length; ++i) {
+				((ClasspathEntry)classpath[i]).elementEncode(xmlWriter, this.project.getFullPath(), indent, true);
+			}
+	
+			if (outputLocation != null) {
+				outputLocation = outputLocation.removeFirstSegments(1);
+				outputLocation = outputLocation.makeRelative();
+				HashMap parameters = new HashMap();
+				parameters.put("kind", ClasspathEntry.kindToString(ClasspathEntry.K_OUTPUT));//$NON-NLS-1$
+				parameters.put("path", String.valueOf(outputLocation));//$NON-NLS-1$
+				xmlWriter.printTag("classpathentry", parameters, indent, true, true);//$NON-NLS-1$
+			}
+	
+			xmlWriter.endTag("classpath", indent);//$NON-NLS-1$
+			writer.flush();
+			writer.close();
+			return s.toString("UTF8");//$NON-NLS-1$
 		} catch (IOException e) {
 			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
 		}
@@ -737,23 +875,23 @@
 	 * project if they are identical or if they represent a project with 
 	 * the same underlying resource and occurrence counts.
 	 *
-	 * @see JavaElement#equals
+	 * @see JavaElement#equals(Object)
 	 */
 	public boolean equals(Object o) {
-
+	
 		if (this == o)
 			return true;
-
+	
 		if (!(o instanceof JavaProject))
 			return false;
-
+	
 		JavaProject other = (JavaProject) o;
-		return getProject().equals(other.getProject())
-			&& fOccurrenceCount == other.fOccurrenceCount;
+		return this.project.equals(other.getProject())
+			&& this.occurrenceCount == other.occurrenceCount;
 	}
 
 	public boolean exists() {
-		if (!hasJavaNature(fProject)) return false;
+		if (!hasJavaNature(this.project)) return false;
 		return super.exists();
 	}	
 
@@ -761,7 +899,14 @@
 	 * @see IJavaProject
 	 */
 	public IJavaElement findElement(IPath path) throws JavaModelException {
+		return findElement(path, DefaultWorkingCopyOwner.PRIMARY);
+	}
 
+	/**
+	 * @see IJavaProject
+	 */
+	public IJavaElement findElement(IPath path, WorkingCopyOwner owner) throws JavaModelException {
+		
 		if (path == null || path.isAbsolute()) {
 			throw new JavaModelException(
 				new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, path));
@@ -790,8 +935,8 @@
 					return pkgFragments[0];
 				}
 			} else if (
-				extension.equalsIgnoreCase("java") //$NON-NLS-1$
-					|| extension.equalsIgnoreCase("class")) {  //$NON-NLS-1$
+				extension.equalsIgnoreCase(EXTENSION_java)
+					|| extension.equalsIgnoreCase(EXTENSION_class)) {
 				IPath packagePath = path.removeLastSegments(1);
 				String packageName = packagePath.toString().replace(IPath.SEPARATOR, '.');
 				String typeName = path.lastSegment();
@@ -802,11 +947,25 @@
 				} else {
 					qualifiedName = typeName;
 				}
-				IType type =
-					getNameLookup().findType(
+				IType type = null;
+				NameLookup lookup = null;
+				try {
+					// set units to look inside
+					lookup = getNameLookup();
+					JavaModelManager manager = JavaModelManager.getJavaModelManager();
+					ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+					lookup.setUnitsToLookInside(workingCopies);
+					
+					// lookup type
+					type = lookup.findType(
 						qualifiedName,
 						false,
 						NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
+				} finally {
+					if (lookup != null) {
+						lookup.setUnitsToLookInside(null);
+					}
+				}
 				if (type != null) {
 					return type.getParent();
 				} else {
@@ -835,7 +994,7 @@
 		return findPackageFragment0(JavaProject.canonicalizedPath(path));
 	}
 
-	/**
+	/*
 	 * non path canonicalizing version
 	 */
 	public IPackageFragment findPackageFragment0(IPath path) 
@@ -853,7 +1012,7 @@
 		return findPackageFragmentRoot0(JavaProject.canonicalizedPath(path));
 	}
 
-	/**
+	/*
 	 * no path canonicalization 
 	 */
 	public IPackageFragmentRoot findPackageFragmentRoot0(IPath path)
@@ -886,6 +1045,7 @@
 				}
 			}
 		} catch (JavaModelException e) {
+			// project doesn't exist: return an empty array
 		}
 		return new IPackageFragmentRoot[] {};
 	}
@@ -894,11 +1054,33 @@
 	 * @see IJavaProject#findType(String)
 	 */
 	public IType findType(String fullyQualifiedName) throws JavaModelException {
-		IType type = 
-			this.getNameLookup().findType(
-				fullyQualifiedName, 
+		return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
+	}
+
+	/**
+	 * @see IJavaProject#findType(String, WorkingCopyOwner)
+	 */
+	public IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
+		
+		IType type = null;
+		NameLookup lookup = null;
+		try {
+			// set units to look inside
+			lookup = getNameLookup();
+			JavaModelManager manager = JavaModelManager.getJavaModelManager();
+			ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+			lookup.setUnitsToLookInside(workingCopies);
+			
+			// lookup type
+			type = lookup.findType(
+				fullyQualifiedName,
 				false,
 				NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
+		} finally {
+			if (lookup != null) {
+				lookup.setUnitsToLookInside(null);
+			}
+		}
 		if (type == null) {
 			// try to find enclosing type
 			int lastDot = fullyQualifiedName.lastIndexOf('.');
@@ -918,22 +1100,41 @@
 	 * @see IJavaProject#findType(String, String)
 	 */
 	public IType findType(String packageName, String typeQualifiedName) throws JavaModelException {
-		return 
-			this.getNameLookup().findType(
+		return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
+	}
+
+	/**
+	 * @see IJavaProject#findType(String, String, WorkingCopyOwner)
+	 */
+	public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
+		NameLookup lookup = null;
+		try {
+			// set units to look inside
+			lookup = getNameLookup();
+			JavaModelManager manager = JavaModelManager.getJavaModelManager();
+			ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+			lookup.setUnitsToLookInside(workingCopies);
+			
+			// lookup type
+			return lookup.findType(
 				typeQualifiedName, 
 				packageName,
 				false,
 				NameLookup.ACCEPT_CLASSES | NameLookup.ACCEPT_INTERFACES);
+		} finally {
+			if (lookup != null) {
+				lookup.setUnitsToLookInside(null);
+			}
+		}
 	}	
 	
 	/**
 	 * Remove all markers denoting classpath problems
-	 */
+	 */ //TODO (philippe) should improve to use a bitmask instead of booleans (CYCLE, FORMAT, VALID)
 	protected void flushClasspathProblemMarkers(boolean flushCycleMarkers, boolean flushClasspathFormatMarkers) {
 		try {
-			IProject project = getProject();
-			if (project.exists()) {
-				IMarker[] markers = project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
+			if (this.project.isAccessible()) {
+				IMarker[] markers = this.project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
 				for (int i = 0, length = markers.length; i < length; i++) {
 					IMarker marker = markers[i];
 					if (flushCycleMarkers && flushClasspathFormatMarkers) {
@@ -949,53 +1150,117 @@
 				}
 			}
 		} catch (CoreException e) {
+			// could not flush markers: not much we can do
+			// TODO (jerome) print stack trace in VERBOSE mode only
+			e.printStackTrace();
 		}
 	}
 
-	/**
-	 * @see Openable
+	/*
+	 * Force the project to reload its <code>.classpath</code> file from disk and update the classpath accordingly.
+	 * Usually, a change to the <code>.classpath</code> file is automatically noticed and reconciled at the next 
+	 * resource change notification event. If required to consider such a change prior to the next automatic
+	 * refresh, then this functionnality should be used to trigger a refresh. In particular, if a change to the file is performed,
+	 * during an operation where this change needs to be reflected before the operation ends, then an explicit refresh is
+	 * necessary.
+	 * Note that classpath markers are NOT created.
+	 * 
+	 * @param monitor a progress monitor for reporting operation progress
+	 * @exception JavaModelException if the classpath could not be updated. Reasons
+	 * include:
+	 * <ul>
+	 * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+	 * <li> Two or more entries specify source roots with the same or overlapping paths (NAME_COLLISION)
+	 * <li> A entry of kind <code>CPE_PROJECT</code> refers to this project (INVALID_PATH)
+	 *  <li>This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+	 *	<li>The output location path refers to a location not contained in this project (<code>PATH_OUTSIDE_PROJECT</code>)
+	 *	<li>The output location path is not an absolute path (<code>RELATIVE_PATH</code>)
+	 *  <li>The output location path is nested inside a package fragment root of this project (<code>INVALID_PATH</code>)
+	 * <li> The classpath is being modified during resource change event notification (CORE_EXCEPTION)
+	 * </ul>
 	 */
-	protected boolean generateInfos(
-		OpenableElementInfo info,
-		IProgressMonitor pm,
-		Map newElements,
-		IResource underlyingResource) throws JavaModelException {
+	protected void forceClasspathReload(IProgressMonitor monitor) throws JavaModelException {
 
-		boolean validInfo = false;
+		if (monitor != null && monitor.isCanceled()) return;
+		
+		// check if any actual difference
+		boolean wasSuccessful = false; // flag recording if .classpath file change got reflected
 		try {
-			if (getProject().isOpen()) {
-				// put the info now, because computing the roots requires it
-				JavaModelManager.getJavaModelManager().putInfo(this, info);
-
-				// compute the pkg fragment roots
-				updatePackageFragmentRoots();				
-	
-				// remember the timestamps of external libraries the first time they are looked up
-				IClasspathEntry[] resolvedClasspath = getResolvedClasspath(true/*ignore unresolved variable*/);
-				for (int i = 0, length = resolvedClasspath.length; i < length; i++) {
-					IClasspathEntry entry = resolvedClasspath[i];
-					if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
-						IPath path = entry.getPath();
-						Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true);
-						if (target instanceof java.io.File) {
-							Map externalTimeStamps = JavaModelManager.getJavaModelManager().deltaProcessor.externalTimeStamps;
-							if (externalTimeStamps.get(path) == null) {
-								long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target);
-								externalTimeStamps.put(path, new Long(timestamp));							
-							}
-						}
-					}
-				}			
-
-				// only valid if reaches here				
-				validInfo = true;
+			// force to (re)read the property file
+			IClasspathEntry[] fileEntries = readClasspathFile(false/*don't create markers*/, false/*don't log problems*/);
+			if (fileEntries == null) {
+				return; // could not read, ignore 
 			}
+			JavaModelManager.PerProjectInfo info = getPerProjectInfo();
+			if (info.rawClasspath != null) { // if there is an in-memory classpath
+				if (isClasspathEqualsTo(info.rawClasspath, info.outputLocation, fileEntries)) {
+					wasSuccessful = true;
+					return;
+				}
+			}
+
+			// will force an update of the classpath/output location based on the file information
+			// extract out the output location
+			IPath outputLocation = null;
+			if (fileEntries != null && fileEntries.length > 0) {
+				IClasspathEntry entry = fileEntries[fileEntries.length - 1];
+				if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
+					outputLocation = entry.getPath();
+					IClasspathEntry[] copy = new IClasspathEntry[fileEntries.length - 1];
+					System.arraycopy(fileEntries, 0, copy, 0, copy.length);
+					fileEntries = copy;
+				}
+			}
+			// restore output location				
+			if (outputLocation == null) {
+				outputLocation = SetClasspathOperation.ReuseOutputLocation;
+				// clean mode will also default to reusing current one
+			}
+			IClasspathEntry[] oldResolvedClasspath = info.resolvedClasspath;
+			setRawClasspath(
+				fileEntries, 
+				outputLocation, 
+				monitor, 
+				!ResourcesPlugin.getWorkspace().isTreeLocked(), // canChangeResource
+				oldResolvedClasspath != null ? oldResolvedClasspath : getResolvedClasspath(true), // ignoreUnresolvedVariable
+				true, // needValidation
+				false); // no need to save
+			
+			// if reach that far, the classpath file change got absorbed
+			wasSuccessful = true;
+		} catch (RuntimeException e) {
+			// setRawClasspath might fire a delta, and a listener may throw an exception
+			if (this.project.isAccessible()) {
+				Util.log(e, "Could not set classpath for "+ getPath()); //$NON-NLS-1$
+			}
+			throw e; // rethrow 
+		} catch (JavaModelException e) { // CP failed validation
+			if (!ResourcesPlugin.getWorkspace().isTreeLocked()) {
+				if (this.project.isAccessible()) {
+					if (e.getJavaModelStatus().getException() instanceof CoreException) {
+						// happens if the .classpath could not be written to disk
+						createClasspathProblemMarker(new JavaModelStatus(
+								IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
+								Util.bind("classpath.couldNotWriteClasspathFile", getElementName(), e.getMessage()))); //$NON-NLS-1$
+					} else {
+						createClasspathProblemMarker(new JavaModelStatus(
+								IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
+								Util.bind("classpath.invalidClasspathInClasspathFile", getElementName(), e.getMessage()))); //$NON-NLS-1$
+					}			
+				}
+			}
+			throw e; // rethrow
 		} finally {
-			if (!validInfo)
-				JavaModelManager.getJavaModelManager().removeInfo(this);
+			if (!wasSuccessful) { 
+				try {
+					this.getPerProjectInfo().updateClasspathInformation(JavaProject.INVALID_CLASSPATH);
+					updatePackageFragmentRoots();
+				} catch (JavaModelException e) {
+					// ignore
+				}
+			}
 		}
-		return validInfo;
-	}
+	}	
 
 	/**
 	 * @see IJavaProject
@@ -1009,6 +1274,9 @@
 	/**
 	 * Returns the classpath entry that refers to the given path
 	 * or <code>null</code> if there is no reference to the path.
+	 * @param path IPath
+	 * @return IClasspathEntry
+	 * @throws JavaModelException
 	 */
 	public IClasspathEntry getClasspathEntryFor(IPath path)
 		throws JavaModelException {
@@ -1027,9 +1295,8 @@
 	 */
 	public IMarker getCycleMarker(){
 		try {
-			IProject project = getProject();
-			if (project.exists()) {
-				IMarker[] markers = project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
+			if (this.project.isAccessible()) {
+				IMarker[] markers = this.project.findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
 				for (int i = 0, length = markers.length; i < length; i++) {
 					IMarker marker = markers[i];
 					String cycleAttr = (String)marker.getAttribute(IJavaModelMarker.CYCLE_DETECTED);
@@ -1039,31 +1306,50 @@
 				}
 			}
 		} catch (CoreException e) {
+			// could not get markers: return null
 		}
 		return null;
 	}
 
 	/**
+	 * @see IJavaElement
+	 */
+	public int getElementType() {
+		return JAVA_PROJECT;
+	}
+
+	/**
 	 * This is a helper method returning the expanded classpath for the project, as a list of classpath entries, 
 	 * where all classpath variable entries have been resolved and substituted with their final target entries.
 	 * All project exports have been appended to project entries.
+	 * @param ignoreUnresolvedVariable boolean
+	 * @return IClasspathEntry[]
+	 * @throws JavaModelException
 	 */
 	public IClasspathEntry[] getExpandedClasspath(boolean ignoreUnresolvedVariable)	throws JavaModelException {
 			
-			return getExpandedClasspath(ignoreUnresolvedVariable, false);
+			return getExpandedClasspath(ignoreUnresolvedVariable, false/*don't create markers*/, null, null);
 	}
 		
 	/**
 	 * Internal variant which can create marker on project for invalid entries,
 	 * it will also perform classpath expansion in presence of project prerequisites
 	 * exporting their entries.
+	 * @param ignoreUnresolvedVariable boolean
+	 * @param generateMarkerOnError boolean
+	 * @param preferredClasspaths Map
+	 * @param preferredOutputs Map
+	 * @return IClasspathEntry[]
+	 * @throws JavaModelException
 	 */
 	public IClasspathEntry[] getExpandedClasspath(
 		boolean ignoreUnresolvedVariable,
-		boolean generateMarkerOnError) throws JavaModelException {
+		boolean generateMarkerOnError,
+		Map preferredClasspaths,
+		Map preferredOutputs) throws JavaModelException {
 	
 		ObjectVector accumulatedEntries = new ObjectVector();		
-		computeExpandedClasspath(this, ignoreUnresolvedVariable, generateMarkerOnError, new HashSet(5), accumulatedEntries);
+		computeExpandedClasspath(this, ignoreUnresolvedVariable, generateMarkerOnError, new HashSet(5), accumulatedEntries, preferredClasspaths, preferredOutputs);
 		
 		IClasspathEntry[] expandedPath = new IClasspathEntry[accumulatedEntries.size()];
 		accumulatedEntries.copyInto(expandedPath);
@@ -1071,6 +1357,35 @@
 		return expandedPath;
 	}
 
+	/*
+	 * @see JavaElement
+	 */
+	public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner owner) {
+		switch (token.charAt(0)) {
+			case JEM_COUNT:
+				return getHandleUpdatingCountFromMemento(memento, owner);
+			case JEM_PACKAGEFRAGMENTROOT:
+				String rootPath = IPackageFragmentRoot.DEFAULT_PACKAGEROOT_PATH;
+				token = null;
+				while (memento.hasMoreTokens()) {
+					token = memento.nextToken();
+					char firstChar = token.charAt(0);
+					if (firstChar != JEM_PACKAGEFRAGMENT && firstChar != JEM_COUNT) {
+						rootPath += token;
+					} else {
+						break;
+					}
+				}
+				JavaElement root = (JavaElement)getPackageFragmentRoot(new Path(rootPath));
+				if (token != null && token.charAt(0) == JEM_PACKAGEFRAGMENT) {
+					return root.getHandleFromMemento(token, memento, owner);
+				} else {
+					return root.getHandleFromMemento(memento, owner);
+				}
+		}
+		return null;
+	}
+
 	/**
 	 * Returns the <code>char</code> that marks the start of this handles
 	 * contribution to a memento.
@@ -1083,8 +1398,7 @@
 	/**
 	 * Find the specific Java command amongst the build spec of a given description
 	 */
-	private ICommand getJavaCommand(IProjectDescription description)
-		throws CoreException {
+	private ICommand getJavaCommand(IProjectDescription description) {
 
 		ICommand[] commands = description.getBuildSpec();
 		for (int i = 0; i < commands.length; ++i) {
@@ -1105,7 +1419,8 @@
 	}
 
 	/**
-	 * @see IJavaProject
+	 * @return NameLookup
+	 * @throws JavaModelException
 	 */
 	public NameLookup getNameLookup() throws JavaModelException {
 
@@ -1133,13 +1448,13 @@
 	 */	
 	public String getOption(String optionName, boolean inheritJavaCoreOptions) {
 		
-		if (JavaModelManager.OptionNames.contains(optionName)){
-			
+		String propertyName = optionName;
+		if (JavaModelManager.OptionNames.contains(propertyName)){
 			Preferences preferences = getPreferences();
-			if (preferences == null || preferences.isDefault(optionName)) {
-				return inheritJavaCoreOptions ? JavaCore.getOption(optionName) : null;
+			if (preferences == null || preferences.isDefault(propertyName)) {
+				return inheritJavaCoreOptions ? JavaCore.getOption(propertyName) : null;
 			}
-			return preferences.getString(optionName).trim();
+			return preferences.getString(propertyName).trim();
 		}
 		return null;
 	}
@@ -1170,10 +1485,37 @@
 		String[] propertyNames = preferences.propertyNames();
 		for (int i = 0; i < propertyNames.length; i++){
 			String propertyName = propertyNames[i];
+			String value = preferences.getString(propertyName).trim();
 			if (optionNames.contains(propertyName)){
-				options.put(propertyName, preferences.getString(propertyName).trim());
+				options.put(propertyName, value);
+			}		
+			// bug 45112 backward compatibility.
+			// TODO (frederic) remove after 3.0 M6
+			else if (CompilerOptions.OPTION_ReportInvalidAnnotation.equals(propertyName)) {
+				options.put(JavaCore.COMPILER_PB_INVALID_JAVADOC, value);
 			}
+			else if (CompilerOptions.OPTION_ReportMissingAnnotation.equals(propertyName)) {
+				if (JavaCore.ENABLED.equals(value)) {
+					value = preferences.getString(JavaCore.COMPILER_PB_INVALID_JAVADOC);
+				} else {
+					value = JavaCore.IGNORE;
+				}
+				options.put(JavaCore.COMPILER_PB_MISSING_JAVADOC_COMMENTS, value);
+			}
+			// end bug 45112
+			// bug 46854 backward compatibility
+			// TODO (frederic) remove after 3.0 M7
+			else if (CompilerOptions.OPTION_ReportMissingJavadoc.equals(propertyName)) {
+				if (JavaCore.ENABLED.equals(value)) {
+					value = preferences.getString(JavaCore.COMPILER_PB_INVALID_JAVADOC);
+				} else {
+					value = JavaCore.IGNORE;
+				}
+				options.put(JavaCore.COMPILER_PB_MISSING_JAVADOC_COMMENTS, value);
+			}
+			// end bug 46854
 		}		
+
 		return options;
 	}
 	
@@ -1181,13 +1523,24 @@
 	 * @see IJavaProject
 	 */
 	public IPath getOutputLocation() throws JavaModelException {
+		// Do not create marker but log problems while getting output location
+		return this.getOutputLocation(false, true);
+	}
+	
+	/**
+	 * @param createMarkers boolean
+	 * @param logProblems boolean
+	 * @return IPath
+	 * @throws JavaModelException
+	 */
+	public IPath getOutputLocation(boolean createMarkers, boolean logProblems) throws JavaModelException {
 
-		JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(fProject);
+		JavaModelManager.PerProjectInfo perProjectInfo = getPerProjectInfo();
 		IPath outputLocation = perProjectInfo.outputLocation;
 		if (outputLocation != null) return outputLocation;
 
 		// force to read classpath - will position output location as well
-		this.getRawClasspath();
+		this.getRawClasspath(createMarkers, logProblems);
 		outputLocation = perProjectInfo.outputLocation;
 		if (outputLocation == null) {
 			return defaultOutputLocation();
@@ -1196,6 +1549,7 @@
 	}
 
 	/**
+	 * @param path IPath
 	 * @return A handle to the package fragment root identified by the given path.
 	 * This method is handle-only and the element may or may not exist. Returns
 	 * <code>null</code> if unable to generate a handle from the path (for example,
@@ -1212,30 +1566,32 @@
 				return null;
 			case 1:
 				// default root
-				return getPackageFragmentRoot(getProject());
+				return getPackageFragmentRoot(this.project);
 			default:
 				// a path ending with .jar/.zip is still ambiguous and could still resolve to a source/lib folder 
 				// thus will try to guess based on existing resource
-				if (Util.isArchiveFileName(path.lastSegment())) {
-					IResource resource = getProject().getWorkspace().getRoot().findMember(path); 
+				if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(path.lastSegment())) {
+					IResource resource = this.project.getWorkspace().getRoot().findMember(path); 
 					if (resource != null && resource.getType() == IResource.FOLDER){
 						return getPackageFragmentRoot(resource);
 					}
 					return getPackageFragmentRoot0(path);
 				} else {
-					return getPackageFragmentRoot(getProject().getWorkspace().getRoot().getFolder(path));
+					return getPackageFragmentRoot(this.project.getWorkspace().getRoot().getFolder(path));
 				}
 		}
 	}
 
 	/**
 	 * The path is known to match a source/library folder entry.
+	 * @param path IPath
+	 * @return IPackageFragmentRoot
 	 */
 	public IPackageFragmentRoot getFolderPackageFragmentRoot(IPath path) {
 		if (path.segmentCount() == 1) { // default project root
-			return getPackageFragmentRoot(getProject());
+			return getPackageFragmentRoot(this.project);
 		}
-		return getPackageFragmentRoot(getProject().getWorkspace().getRoot().getFolder(path));
+		return getPackageFragmentRoot(this.project.getWorkspace().getRoot().getFolder(path));
 	}
 	
 	/**
@@ -1245,7 +1601,7 @@
 
 		switch (resource.getType()) {
 			case IResource.FILE:
-				if (Util.isArchiveFileName(resource.getName())) {
+				if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resource.getName())) {
 					return new JarPackageFragmentRoot(resource, this);
 				} else {
 					return null;
@@ -1267,7 +1623,7 @@
 		return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new Path(jarPath)));
 	}
 	
-	/**
+	/*
 	 * no path canonicalization
 	 */
 	public IPackageFragmentRoot getPackageFragmentRoot0(IPath jarPath) {
@@ -1335,6 +1691,8 @@
 	/**
 	 * Returns all the package fragments found in the specified
 	 * package fragment roots.
+	 * @param roots IPackageFragmentRoot[]
+	 * @return IPackageFragment[]
 	 */
 	public IPackageFragment[] getPackageFragmentsInRoots(IPackageFragmentRoot[] roots) {
 
@@ -1355,29 +1713,32 @@
 		return fragments;
 	}
 	
-	/*
+	/**
 	 * @see IJavaElement
 	 */
 	public IPath getPath() {
-		return this.getProject().getFullPath();
+		return this.project.getFullPath();
+	}
+	
+	public JavaModelManager.PerProjectInfo getPerProjectInfo() throws JavaModelException {
+		return JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.project);
 	}
 	
 	/**
-	 * @see IJavaProject
+	 * @see IJavaProject#getProject()
 	 */
 	public IProject getProject() {
-
-		return fProject;
+		return this.project;
 	}
 
 	/**
 	 * Returns the project custom preference pool.
 	 * Project preferences may include custom encoding.
+	 * @return Preferences
 	 */	
 	public Preferences getPreferences(){
-		IProject project = getProject();
-		if (!JavaProject.hasJavaNature(project)) return null;
-		JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(project, true);
+		if (!JavaProject.hasJavaNature(this.project)) return null;
+		JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, true);
 		Preferences preferences =  perProjectInfo.preferences;
 		if (preferences != null) return preferences;
 		preferences = loadPreferences();
@@ -1390,12 +1751,26 @@
 	 * @see IJavaProject
 	 */
 	public IClasspathEntry[] getRawClasspath() throws JavaModelException {
+		// Do not create marker but log problems while getting raw classpath
+		return getRawClasspath(false, true);
+	}
 
-		JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(fProject);
-		IClasspathEntry[] classpath = perProjectInfo.classpath;
-		if (classpath != null) return classpath;
-		classpath = this.readClasspathFile(false/*don't create markers*/, true/*log problems*/);
-		
+	/*
+	 * Internal variant allowing to parameterize problem creation/logging
+	 */
+	public IClasspathEntry[] getRawClasspath(boolean createMarkers, boolean logProblems) throws JavaModelException {
+
+		JavaModelManager.PerProjectInfo perProjectInfo = null;
+		IClasspathEntry[] classpath;
+		if (createMarkers) {
+			this.flushClasspathProblemMarkers(false/*cycle*/, true/*format*/);
+			classpath = this.readClasspathFile(createMarkers, logProblems);
+		} else {
+			perProjectInfo = getPerProjectInfo();
+			classpath = perProjectInfo.rawClasspath;
+			if (classpath != null) return classpath;
+			classpath = this.readClasspathFile(createMarkers, logProblems);
+		}
 		// extract out the output location
 		IPath outputLocation = null;
 		if (classpath != null && classpath.length > 0) {
@@ -1416,13 +1791,14 @@
 			classpath = INVALID_CLASSPATH;
 		}
 		*/
-		perProjectInfo.classpath = classpath;
-		perProjectInfo.outputLocation = outputLocation;
+		if (!createMarkers) {
+			perProjectInfo.rawClasspath = classpath;
+			perProjectInfo.outputLocation = outputLocation;
+		}
 		return classpath;
 	}
-
 	/**
-	 * @see IJavaProject#getRequiredProjectNames
+	 * @see IJavaProject#getRequiredProjectNames()
 	 */
 	public String[] getRequiredProjectNames() throws JavaModelException {
 
@@ -1444,39 +1820,45 @@
 	/**
 	 * Internal variant which can create marker on project for invalid entries
 	 * and caches the resolved classpath on perProjectInfo
+	 * @param ignoreUnresolvedEntry boolean
+	 * @param generateMarkerOnError boolean
+	 * @return IClasspathEntry[]
+	 * @throws JavaModelException
 	 */
 	public IClasspathEntry[] getResolvedClasspath(
 		boolean ignoreUnresolvedEntry,
 		boolean generateMarkerOnError)
 		throws JavaModelException {
 
-		JavaModelManager manager = JavaModelManager.getJavaModelManager();
-		JavaModelManager.PerProjectInfo perProjectInfo = manager.getPerProjectInfoCheckExistence(fProject);
-		
-		// reuse cache if not needing to refresh markers or checking bound variables
-		if (ignoreUnresolvedEntry && !generateMarkerOnError && perProjectInfo != null){
-			// resolved path is cached on its info
-			IClasspathEntry[] infoPath = perProjectInfo.lastResolvedClasspath;
-			if (infoPath != null) return infoPath;
+		JavaModelManager.PerProjectInfo perProjectInfo = null;
+		if (ignoreUnresolvedEntry && !generateMarkerOnError) {
+			perProjectInfo = getPerProjectInfo();
+			if (perProjectInfo != null) {
+				// resolved path is cached on its info
+				IClasspathEntry[] infoPath = perProjectInfo.resolvedClasspath;
+				if (infoPath != null) return infoPath;
+			}
 		}
 		Map reverseMap = perProjectInfo == null ? null : new HashMap(5);
 		IClasspathEntry[] resolvedPath = getResolvedClasspath(
-			getRawClasspath(), 
+			getRawClasspath(generateMarkerOnError, !generateMarkerOnError), 
 			generateMarkerOnError ? getOutputLocation() : null, 
 			ignoreUnresolvedEntry, 
 			generateMarkerOnError,
 			reverseMap);
 
 		if (perProjectInfo != null){
-			if (perProjectInfo.classpath == null // .classpath file could not be read
+			if (perProjectInfo.rawClasspath == null // .classpath file could not be read
 				&& generateMarkerOnError 
-				&& JavaProject.hasJavaNature(fProject)) {
+				&& JavaProject.hasJavaNature(this.project)) {
+					// flush .classpath format markers (bug 39877), but only when file cannot be read (bug 42366)
+					this.flushClasspathProblemMarkers(false, true);
 					this.createClasspathProblemMarker(new JavaModelStatus(
 						IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
 						Util.bind("classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$
 				}
 
-			perProjectInfo.lastResolvedClasspath = resolvedPath;
+			perProjectInfo.resolvedClasspath = resolvedPath;
 			perProjectInfo.resolvedPathToRawEntries = reverseMap;
 		}
 		return resolvedPath;
@@ -1484,6 +1866,13 @@
 	
 	/**
 	 * Internal variant which can process any arbitrary classpath
+	 * @param classpathEntries IClasspathEntry[] 
+	 * @param projectOutputLocation IPath
+	 * @param ignoreUnresolvedEntry boolean
+	 * @param generateMarkerOnError boolean
+	 * @param reverseMap Map
+	 * @return IClasspathEntry[] 
+	 * @throws JavaModelException
 	 */
 	public IClasspathEntry[] getResolvedClasspath(
 		IClasspathEntry[] classpathEntries,
@@ -1509,7 +1898,7 @@
 			
 			/* validation if needed */
 			if (generateMarkerOnError || !ignoreUnresolvedEntry) {
-				status = JavaConventions.validateClasspathEntry(this, rawEntry, false);
+				status = ClasspathEntry.validateClasspathEntry(this, rawEntry, false /*ignore src attach*/, false /*do not recurse in containers, done later to accumulate*/);
 				if (generateMarkerOnError && !status.isOK()) createClasspathProblemMarker(status);
 			}
 
@@ -1540,9 +1929,8 @@
 					// container was bound
 					for (int j = 0, containerLength = containerEntries.length; j < containerLength; j++){
 						IClasspathEntry cEntry = containerEntries[j];
-						
 						if (generateMarkerOnError) {
-							IJavaModelStatus containerStatus = JavaConventions.validateClasspathEntry(this, cEntry, false);
+							IJavaModelStatus containerStatus = ClasspathEntry.validateClasspathEntry(this, cEntry, false, true /*recurse*/);
 							if (!containerStatus.isOK()) createClasspathProblemMarker(containerStatus);
 						}
 						// if container is exported, then its nested entries must in turn be exported  (21749)
@@ -1570,21 +1958,22 @@
 		resolvedEntries.toArray(resolvedPath);
 
 		if (generateMarkerOnError && projectOutputLocation != null) {
-			status = JavaConventions.validateClasspath(this, resolvedPath, projectOutputLocation);
+			status = ClasspathEntry.validateClasspath(this, resolvedPath, projectOutputLocation);
 			if (!status.isOK()) createClasspathProblemMarker(status);
 		}
 		return resolvedPath;
 	}
 
-	/*
+	/**
 	 * @see IJavaElement
 	 */
 	public IResource getResource() {
-		return this.getProject();
+		return this.project;
 	}
 
 	/**
-	 * @see IJavaProject
+	 * @return ISearchableNameEnvironment
+	 * @throws JavaModelException
 	 */
 	public ISearchableNameEnvironment getSearchableNameEnvironment()
 		throws JavaModelException {
@@ -1602,12 +1991,15 @@
 	 * which form of storage to use appropriately. Shared properties produce real resource files which
 	 * can be shared through a VCM onto a server. Persistent properties are not shareable.
 	 *
+	 * @param key String
 	 * @see JavaProject#setSharedProperty(String, String)
+	 * @return String
+	 * @throws CoreException
 	 */
 	public String getSharedProperty(String key) throws CoreException {
 
 		String property = null;
-		IFile rscFile = getProject().getFile(key);
+		IFile rscFile = this.project.getFile(key);
 		if (rscFile.exists()) {
 			property = new String(Util.getResourceContentsAsByteArray(rscFile));
 		}
@@ -1627,7 +2019,7 @@
 	 */
 	public IResource getUnderlyingResource() throws JavaModelException {
 		if (!exists()) throw newNotPresentException();
-		return getProject();
+		return this.project;
 	}
 
 	/**
@@ -1635,7 +2027,7 @@
 	 */
 	public boolean hasBuildState() {
 
-		return JavaModelManager.getJavaModelManager().getLastBuiltState(this.getProject(), null) != null;
+		return JavaModelManager.getJavaModelManager().getLastBuiltState(this.project, null) != null;
 	}
 
 	/**
@@ -1643,7 +2035,9 @@
 	 */
 	public boolean hasClasspathCycle(IClasspathEntry[] preferredClasspath) {
 		HashSet cycleParticipants = new HashSet();
-		updateCycleParticipants(preferredClasspath, new ArrayList(2), cycleParticipants, ResourcesPlugin.getWorkspace().getRoot(), new HashSet(2));
+		HashMap preferredClasspaths = new HashMap(1);
+		preferredClasspaths.put(this, preferredClasspath);
+		updateCycleParticipants(new ArrayList(2), cycleParticipants, ResourcesPlugin.getWorkspace().getRoot(), new HashSet(2), preferredClasspaths);
 		return !cycleParticipants.isEmpty();
 	}
 	
@@ -1652,12 +2046,14 @@
 	}
 
 	public int hashCode() {
-		return fProject.hashCode();
+		return this.project.hashCode();
 	}
 
 	/**
 	 * Returns true if the given project is accessible and it has
 	 * a java nature, otherwise false.
+	 * @param project IProject
+	 * @return boolean
 	 */
 	public static boolean hasJavaNature(IProject project) { 
 		try {
@@ -1670,6 +2066,7 @@
 	
 	/**
 	 * Answers true if the project potentially contains any source. A project which has no source is immutable.
+	 * @return boolean
 	 */
 	public boolean hasSource() {
 
@@ -1692,9 +2089,12 @@
 	/**
 	 * Compare current classpath with given one to see if any different.
 	 * Note that the argument classpath contains its binary output.
+	 * @param newClasspath IClasspathEntry[]
+	 * @param newOutputLocation IPath
+	 * @param otherClasspathWithOutput IClasspathEntry[]
+	 * @return boolean
 	 */
-	public boolean isClasspathEqualsTo(IClasspathEntry[] newClasspath, IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput)
-		throws JavaModelException {
+	public boolean isClasspathEqualsTo(IClasspathEntry[] newClasspath, IPath newOutputLocation, IClasspathEntry[] otherClasspathWithOutput) {
 
 		if (otherClasspathWithOutput != null && otherClasspathWithOutput.length > 0) {
 
@@ -1778,8 +2178,8 @@
 	 	
 	 	Preferences preferences = new Preferences();
 	 	
-//		File prefFile = getProject().getLocation().append(PREF_FILENAME).toFile();
-		IPath projectMetaLocation = getProject().getPluginWorkingLocation(JavaCore.getPlugin().getDescriptor());
+//		File prefFile = this.project.getLocation().append(PREF_FILENAME).toFile();
+		IPath projectMetaLocation = this.project.getPluginWorkingLocation(JavaCore.getPlugin().getDescriptor());
 		if (projectMetaLocation != null) {
 			File prefFile = projectMetaLocation.append(PREF_FILENAME).toFile();
 			if (prefFile.exists()) { // load preferences from file
@@ -1803,7 +2203,7 @@
 	 }
 	 
 	/**
-	 * @see IJavaProject#newEvaluationContext
+	 * @see IJavaProject#newEvaluationContext()
 	 */
 	public IEvaluationContext newEvaluationContext() {
 
@@ -1817,12 +2217,25 @@
 		IRegion region,
 		IProgressMonitor monitor)
 		throws JavaModelException {
+			
+		return newTypeHierarchy(region, DefaultWorkingCopyOwner.PRIMARY, monitor);
+	}
+
+	/**
+	 * @see IJavaProject
+	 */
+	public ITypeHierarchy newTypeHierarchy(
+		IRegion region,
+		WorkingCopyOwner owner,
+		IProgressMonitor monitor)
+		throws JavaModelException {
 
 		if (region == null) {
 			throw new IllegalArgumentException(Util.bind("hierarchy.nullRegion"));//$NON-NLS-1$
 		}
+		ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
 		CreateTypeHierarchyOperation op =
-			new CreateTypeHierarchyOperation(null, region, this, true);
+			new CreateTypeHierarchyOperation(region, this, workingCopies, null, true);
 		runOperation(op, monitor);
 		return op.getResult();
 	}
@@ -1835,6 +2248,19 @@
 		IRegion region,
 		IProgressMonitor monitor)
 		throws JavaModelException {
+			
+		return newTypeHierarchy(type, region, DefaultWorkingCopyOwner.PRIMARY, monitor);
+	}
+
+	/**
+	 * @see IJavaProject
+	 */
+	public ITypeHierarchy newTypeHierarchy(
+		IType type,
+		IRegion region,
+		WorkingCopyOwner owner,
+		IProgressMonitor monitor)
+		throws JavaModelException {
 
 		if (type == null) {
 			throw new IllegalArgumentException(Util.bind("hierarchy.nullFocusType"));//$NON-NLS-1$
@@ -1842,24 +2268,12 @@
 		if (region == null) {
 			throw new IllegalArgumentException(Util.bind("hierarchy.nullRegion"));//$NON-NLS-1$
 		}
+		ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
 		CreateTypeHierarchyOperation op =
-			new CreateTypeHierarchyOperation(type, region, this, true);
+			new CreateTypeHierarchyOperation(region, this, workingCopies, type, true);
 		runOperation(op, monitor);
 		return op.getResult();
 	}
-
-	/**
-	 * Open project if resource isn't closed
-	 */
-	protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
-
-		if (!this.fProject.isOpen()) {
-			throw newNotPresentException();
-		} else {
-			super.openWhenClosed(pm);
-		}
-	}
-
 	public String[] projectPrerequisites(IClasspathEntry[] entries)
 		throws JavaModelException {
 			
@@ -1892,11 +2306,18 @@
 
 		try {
 			String xmlClasspath = getSharedProperty(CLASSPATH_FILENAME);
-			if (xmlClasspath == null) return null;
+			if (xmlClasspath == null) {
+				if (createMarker && this.project.isAccessible()) {
+						this.createClasspathProblemMarker(new JavaModelStatus(
+							IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
+							Util.bind("classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$
+				}
+				return null;
+			}
 			return decodeClasspath(xmlClasspath, createMarker, logProblems);
 		} catch(CoreException e) {
 			// file does not exist (or not accessible)
-			if (createMarker && this.getProject().isAccessible()) {
+			if (createMarker && this.project.isAccessible()) {
 					this.createClasspathProblemMarker(new JavaModelStatus(
 						IJavaModelStatusConstants.INVALID_CLASSPATH_FILE_FORMAT,
 						Util.bind("classpath.cannotReadClasspathFile", this.getElementName()))); //$NON-NLS-1$
@@ -1911,11 +2332,48 @@
 	}
 
 	/**
+	 * @see IJavaProject
+	 */
+	public IPath readOutputLocation() {
+
+		// Read classpath file without creating markers nor logging problems
+		IClasspathEntry[] classpath = this.readClasspathFile(false, false);
+		// extract the output location
+		IPath outputLocation = null;
+		if (classpath != null && classpath.length > 0) {
+			IClasspathEntry entry = classpath[classpath.length - 1];
+			if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
+				outputLocation = entry.getPath();
+			}
+		}
+		return outputLocation;
+	}
+
+	/**
+	 * @see IJavaProject
+	 */
+	public IClasspathEntry[] readRawClasspath() {
+
+		// Read classpath file without creating markers nor logging problems
+		IClasspathEntry[] classpath = this.readClasspathFile(false, false);
+		// discard the output location
+		if (classpath != null && classpath.length > 0) {
+			IClasspathEntry entry = classpath[classpath.length - 1];
+			if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
+				IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
+				System.arraycopy(classpath, 0, copy, 0, copy.length);
+				classpath = copy;
+			}
+		}
+		return classpath;
+	}
+
+	/**
 	 * Removes the given builder from the build spec for the given project.
 	 */
 	protected void removeFromBuildSpec(String builderID) throws CoreException {
 
-		IProjectDescription description = getProject().getDescription();
+		IProjectDescription description = this.project.getDescription();
 		ICommand[] commands = description.getBuildSpec();
 		for (int i = 0; i < commands.length; ++i) {
 			if (commands[i].getBuilderName().equals(builderID)) {
@@ -1923,38 +2381,46 @@
 				System.arraycopy(commands, 0, newCommands, 0, i);
 				System.arraycopy(commands, i + 1, newCommands, i, commands.length - i - 1);
 				description.setBuildSpec(newCommands);
-				getProject().setDescription(description, null);
+				this.project.setDescription(description, null);
 				return;
 			}
 		}
 	}
-
-
-	/**
-	 * @see JavaElement#rootedAt(IJavaProject)
+	
+	/*
+	 * Resets this project's name lookup
 	 */
-	public IJavaElement rootedAt(IJavaProject project) {
-		return project;
-	
+	public void resetNameLookup() {
+		if (isOpen()){
+			try {
+				((JavaProjectElementInfo)getElementInfo()).setNameLookup(null);
+			} catch (JavaModelException e) {
+				// project was closed and deleted by another thread: ignore
+			}
+		}
 	}
-	
+
 	/**
 	 * Answers an ID which is used to distinguish project/entries during package
 	 * fragment root computations
+	 * @return String
 	 */
 	public String rootID(){
-		return "[PRJ]"+this.getProject().getFullPath(); //$NON-NLS-1$
+		return "[PRJ]"+this.project.getFullPath(); //$NON-NLS-1$
 	}
 	
 	/**
 	 * Saves the classpath in a shareable format (VCM-wise) only when necessary, that is, if  it is semantically different
 	 * from the existing one in file. Will never write an identical one.
 	 * 
-	 * @return Return whether the .classpath file was modified.
+	 * @param newClasspath IClasspathEntry[]
+	 * @param newOutputLocation IPath
+	 * @return boolean Return whether the .classpath file was modified.
+	 * @throws JavaModelException
 	 */
 	public boolean saveClasspath(IClasspathEntry[] newClasspath, IPath newOutputLocation) throws JavaModelException {
 
-		if (!getProject().exists()) return false;
+		if (!this.project.isAccessible()) return false;
 
 		IClasspathEntry[] fileEntries = readClasspathFile(false /*don't create markers*/, false/*don't log problems*/);
 		if (fileEntries != null && isClasspathEqualsTo(newClasspath, newOutputLocation, fileEntries)) {
@@ -1970,14 +2436,12 @@
 			throw new JavaModelException(e);
 		}
 	}
-
 	/**
 	 * Save project custom preferences to shareable file (.jprefs)
 	 */
 	private void savePreferences(Preferences preferences) {
 		
-		IProject project = getProject();
-		if (!JavaProject.hasJavaNature(project)) return; // ignore
+		if (!JavaProject.hasJavaNature(this.project)) return; // ignore
 		
 		if (preferences == null || (!preferences.needsSaving() && preferences.propertyNames().length != 0)) {
 			// nothing to save
@@ -1987,8 +2451,8 @@
 		// preferences need to be saved
 		// the preferences file is located in the plug-in's state area
 		// at a well-known name (.jprefs)
-//		File prefFile = getProject().getLocation().append(PREF_FILENAME).toFile();
-		File prefFile = project.getPluginWorkingLocation(JavaCore.getPlugin().getDescriptor()).append(PREF_FILENAME).toFile();
+//		File prefFile = this.project.getLocation().append(PREF_FILENAME).toFile();
+		File prefFile = this.project.getPluginWorkingLocation(JavaCore.getPlugin().getDescriptor()).append(PREF_FILENAME).toFile();
 		if (preferences.propertyNames().length == 0) {
 			// there are no preference settings
 			// rather than write an empty file, just delete any existing file
@@ -2046,7 +2510,18 @@
 
 		// Commit the spec change into the project
 		description.setBuildSpec(newCommands);
-		getProject().setDescription(description, null);
+		this.project.setDescription(description, null);
+	}
+
+	/**
+	 * @see org.eclipse.jdt.core.IJavaProject#setOption(java.lang.String, java.lang.String)
+	 */
+	public void setOption(String optionName, String optionValue) {
+		if (!JavaModelManager.OptionNames.contains(optionName)) return; // unrecognized option
+		Preferences preferences = getPreferences();
+		preferences.setDefault(optionName, CUSTOM_DEFAULT_OPTION_VALUE); // empty string isn't the default (26251)
+		preferences.setValue(optionName, optionValue);
+		savePreferences(preferences);
 	}
 
 	/**
@@ -2067,7 +2542,26 @@
 				preferences.setValue(key, value);
 			}
 		}
-		
+
+		// Backward compatibility
+		String[] propertyNames = preferences.propertyNames();
+		for (int i = 0; i < propertyNames.length; i++){
+			String propertyName = propertyNames[i];
+			// bug 45112
+			if (CompilerOptions.OPTION_ReportInvalidAnnotation.equals(propertyName)) {
+				preferences.setToDefault(JavaCore.OLD_COMPILER_PB_INVALID_ANNOTATION);
+			}
+			else if (CompilerOptions.OPTION_ReportMissingAnnotation.equals(propertyName)) {
+				preferences.setToDefault(JavaCore.OLD_COMPILER_PB_MISSING_ANNOTATION);
+			}
+			// end bug 45112
+			// bug 46854
+			else if (CompilerOptions.OPTION_ReportMissingJavadoc.equals(propertyName)) {
+				preferences.setToDefault(JavaCore.OLD_COMPILER_PB_MISSING_JAVADOC);
+			}
+			// end bug 46854
+		}
+
 		// persist options
 		savePreferences(preferences);	
 	}
@@ -2079,7 +2573,7 @@
 		throws JavaModelException {
 
 		if (path == null) {
-			throw new IllegalArgumentException(Util.bind("path.nullpath")); //$NON-NLS-1$
+			throw new IllegalArgumentException(Util.bind("path.nullPath")); //$NON-NLS-1$
 		}
 		if (path.equals(getOutputLocation())) {
 			return;
@@ -2091,9 +2585,8 @@
 	 * Set cached preferences, no preference file is saved, only info is updated
 	 */
 	public void setPreferences(Preferences preferences) {
-		IProject project = getProject();
-		if (!JavaProject.hasJavaNature(project)) return; // ignore
-		JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(project, true);
+		if (!JavaProject.hasJavaNature(this.project)) return; // ignore
+		JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfo(this.project, true);
 		perProjectInfo.preferences = preferences;
 	}
 
@@ -2102,17 +2595,17 @@
 	 * and fills in its parent and name.
 	 * Called by IProject.getNature().
 	 *
-	 * @see IProjectNature#setProject
+	 * @see IProjectNature#setProject(IProject)
 	 */
 	public void setProject(IProject project) {
 
-		fProject = project;
-		fParent = JavaModelManager.getJavaModelManager().getJavaModel();
-		fName = project.getName();
+		this.project = project;
+		this.parent = JavaModelManager.getJavaModelManager().getJavaModel();
+		this.name = project.getName();
 	}
 
 	/**
-	 * @see IJavaProject
+	 * @see IJavaProject#setRawClasspath(IClasspathEntry[],IPath,IProgressMonitor)
 	 */
 	public void setRawClasspath(
 		IClasspathEntry[] entries,
@@ -2140,8 +2633,7 @@
 		boolean needSave)
 		throws JavaModelException {
 
-		JavaModelManager manager =
-			(JavaModelManager) JavaModelManager.getJavaModelManager();
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
 		try {
 			IClasspathEntry[] newRawPath = newEntries;
 			if (newRawPath == null) { //are we already with the default classpath
@@ -2159,7 +2651,7 @@
 			runOperation(op, monitor);
 			
 		} catch (JavaModelException e) {
-			manager.flush();
+			manager.getDeltaProcessor().flush();
 			throw e;
 		}
 	}
@@ -2183,28 +2675,6 @@
 	}
 
 	/**
-	 * NOTE: <code>null</code> specifies default classpath, and an empty
-	 * array specifies an empty classpath.
-	 *
-	 * @exception NotPresentException if this project does not exist.
-	 */
-	protected void setRawClasspath0(IClasspathEntry[] rawEntries)
-		throws JavaModelException {
-
-		JavaModelManager.PerProjectInfo info = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(fProject);
-	
-		synchronized (info) {
-			if (rawEntries != null) {
-				info.classpath = rawEntries;
-			}
-			
-			// clear cache of resolved classpath
-			info.lastResolvedClasspath = null;
-			info.resolvedPathToRawEntries = null;
-		}
-	}
-
-	/**
 	 * Record a shared persistent property onto a project.
 	 * Note that it is orthogonal to IResource persistent properties, and client code has to decide
 	 * which form of storage to use appropriately. Shared properties produce real resource files which
@@ -2213,11 +2683,14 @@
 	 * shared properties end up in resource files, and thus cannot be modified during
 	 * delta notifications (a CoreException would then be thrown).
 	 * 
+	 * @param key String
+	 * @param value String
 	 * @see JavaProject#getSharedProperty(String key)
+	 * @throws CoreException
 	 */
 	public void setSharedProperty(String key, String value) throws CoreException {
 
-		IFile rscFile = getProject().getFile(key);
+		IFile rscFile = this.project.getFile(key);
 		InputStream inputStream = new ByteArrayInputStream(value.getBytes());
 		// update the resource content
 		if (rscFile.exists()) {
@@ -2233,74 +2706,86 @@
 
 	/**
 	 * Update cycle markers for all java projects
+	 * @param preferredClasspaths Map
+	 * @throws JavaModelException
 	 */
-	public static void updateAllCycleMarkers() throws JavaModelException {
+	public static void updateAllCycleMarkers(Map preferredClasspaths) throws JavaModelException {
 
 		//long start = System.currentTimeMillis();
 
-		JavaModelManager manager = JavaModelManager.getJavaModelManager();
-		IJavaProject[] projects = manager.getJavaModel().getJavaProjects();
 		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
-
+		IProject[] rscProjects = workspaceRoot.getProjects();
+		int length = rscProjects.length;
+		JavaProject[] projects = new JavaProject[length];
+				
 		HashSet cycleParticipants = new HashSet();
 		HashSet traversed = new HashSet();
-		int length = projects.length;
 		
 		// compute cycle participants
 		ArrayList prereqChain = new ArrayList();
 		for (int i = 0; i < length; i++){
-			JavaProject project = (JavaProject)projects[i];
-			if (!traversed.contains(project.getPath())){
-				prereqChain.clear();
-				project.updateCycleParticipants(null, prereqChain, cycleParticipants, workspaceRoot, traversed);
+			if (hasJavaNature(rscProjects[i])) {
+				JavaProject project = (projects[i] = (JavaProject)JavaCore.create(rscProjects[i]));
+				if (!traversed.contains(project.getPath())){
+					prereqChain.clear();
+					project.updateCycleParticipants(prereqChain, cycleParticipants, workspaceRoot, traversed, preferredClasspaths);
+				}
 			}
 		}
 		//System.out.println("updateAllCycleMarkers: " + (System.currentTimeMillis() - start) + " ms");
 
 		for (int i = 0; i < length; i++){
-			JavaProject project = (JavaProject)projects[i];
-			
-			if (cycleParticipants.contains(project.getPath())){
-				IMarker cycleMarker = project.getCycleMarker();
-				String circularCPOption = project.getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true);
-				int circularCPSeverity = JavaCore.ERROR.equals(circularCPOption) ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING;
-				if (cycleMarker != null) {
-					// update existing cycle marker if needed
-					try {
-						int existingSeverity = ((Integer)cycleMarker.getAttribute(IMarker.SEVERITY)).intValue();
-						if (existingSeverity != circularCPSeverity) {
-							cycleMarker.setAttribute(IMarker.SEVERITY, circularCPSeverity);
+			JavaProject project = projects[i];
+			if (project != null) {
+				if (cycleParticipants.contains(project.getPath())){
+					IMarker cycleMarker = project.getCycleMarker();
+					String circularCPOption = project.getOption(JavaCore.CORE_CIRCULAR_CLASSPATH, true);
+					int circularCPSeverity = JavaCore.ERROR.equals(circularCPOption) ? IMarker.SEVERITY_ERROR : IMarker.SEVERITY_WARNING;
+					if (cycleMarker != null) {
+						// update existing cycle marker if needed
+						try {
+							int existingSeverity = ((Integer)cycleMarker.getAttribute(IMarker.SEVERITY)).intValue();
+							if (existingSeverity != circularCPSeverity) {
+								cycleMarker.setAttribute(IMarker.SEVERITY, circularCPSeverity);
+							}
+						} catch (CoreException e) {
+							throw new JavaModelException(e);
 						}
-					} catch (CoreException e) {
-						throw new JavaModelException(e);
+					} else {
+						// create new marker
+						project.createClasspathProblemMarker(
+							new JavaModelStatus(IJavaModelStatusConstants.CLASSPATH_CYCLE, project)); 
 					}
 				} else {
-					// create new marker
-					project.createClasspathProblemMarker(
-						new JavaModelStatus(IJavaModelStatusConstants.CLASSPATH_CYCLE, project)); 
-				}
-			} else {
-				project.flushClasspathProblemMarkers(true, false);
-			}			
+					project.flushClasspathProblemMarkers(true, false);
+				}			
+			}
 		}
 	}
 
 	/**
 	 * If a cycle is detected, then cycleParticipants contains all the paths of projects involved in this cycle (directly and indirectly),
 	 * no cycle if the set is empty (and started empty)
+	 * @param prereqChain ArrayList
+	 * @param cycleParticipants HashSet
+	 * @param workspaceRoot IWorkspaceRoot
+	 * @param traversed HashSet
+	 * @param preferredClasspaths Map
 	 */
 	public void updateCycleParticipants(
-			IClasspathEntry[] preferredClasspath, 
 			ArrayList prereqChain, 
 			HashSet cycleParticipants, 
 			IWorkspaceRoot workspaceRoot,
-			HashSet traversed){
+			HashSet traversed,
+			Map preferredClasspaths){
 
 		IPath path = this.getPath();
 		prereqChain.add(path);
 		traversed.add(path);
 		try {
-			IClasspathEntry[] classpath = preferredClasspath == null ? getResolvedClasspath(true) : preferredClasspath;
+			IClasspathEntry[] classpath = null;
+			if (preferredClasspaths != null) classpath = (IClasspathEntry[])preferredClasspaths.get(this);
+			if (classpath == null) classpath = getResolvedClasspath(true);
 			for (int i = 0, length = classpath.length; i < length; i++) {
 				IClasspathEntry entry = classpath[i];
 				
@@ -2315,52 +2800,69 @@
 						if (!traversed.contains(prereqProjectPath)) {
 							IResource member = workspaceRoot.findMember(prereqProjectPath);
 							if (member != null && member.getType() == IResource.PROJECT){
-								JavaProject project = (JavaProject)JavaCore.create((IProject)member);
-								project.updateCycleParticipants(null, prereqChain, cycleParticipants, workspaceRoot, traversed);
+								JavaProject javaProject = (JavaProject)JavaCore.create((IProject)member);
+								javaProject.updateCycleParticipants(prereqChain, cycleParticipants, workspaceRoot, traversed, preferredClasspaths);
 							}
 						}
 					}
 				}
 			}
 		} catch(JavaModelException e){
+			// project doesn't exist: ignore
 		}
 		prereqChain.remove(path);
 	}
+		
+	public void updateClasspathMarkers(Map preferredClasspaths, Map preferredOutputs) {
+		
+		this.flushClasspathProblemMarkers(false/*cycle*/, true/*format*/);
+		this.flushClasspathProblemMarkers(false/*cycle*/, false/*format*/);
+
+		IClasspathEntry[] classpath = this.readClasspathFile(true/*marker*/, false/*log*/);
+		IPath output = null;
+		// discard the output location
+		if (classpath != null && classpath.length > 0) {
+			IClasspathEntry entry = classpath[classpath.length - 1];
+			if (entry.getContentKind() == ClasspathEntry.K_OUTPUT) {
+				IClasspathEntry[] copy = new IClasspathEntry[classpath.length - 1];
+				System.arraycopy(classpath, 0, copy, 0, copy.length);
+				classpath = copy;
+				output = entry.getPath();
+			}
+		}					
+		// remember invalid path so as to avoid reupdating it again later on
+		if (preferredClasspaths != null) {
+			preferredClasspaths.put(this, classpath == null ? INVALID_CLASSPATH : classpath);
+		}
+		if (preferredOutputs != null) {
+			preferredOutputs.put(this, output == null ? defaultOutputLocation() : output);
+		}
+		
+		 // force classpath marker refresh
+		 if (classpath != null && output != null) {
+		 	for (int i = 0; i < classpath.length; i++) {
+				IJavaModelStatus status = ClasspathEntry.validateClasspathEntry(this, classpath[i], false/*src attach*/, true /*recurse in container*/);
+				if (!status.isOK()) this.createClasspathProblemMarker(status);					 
+			 }
+			IJavaModelStatus status = ClasspathEntry.validateClasspath(this, classpath, output);
+			if (!status.isOK()) this.createClasspathProblemMarker(status);
+		 }
+	}
+	
 	/**
 	 * Reset the collection of package fragment roots (local ones) - only if opened.
-	 * Need to check *all* package fragment roots in order to reset NameLookup
 	 */
 	public void updatePackageFragmentRoots(){
 		
 			if (this.isOpen()) {
 				try {
 					JavaProjectElementInfo info = getJavaProjectElementInfo();
-
-					IClasspathEntry[] classpath = getResolvedClasspath(true);
-					NameLookup lookup = info.getNameLookup();
-					if (lookup != null){
-						IPackageFragmentRoot[] oldRoots = lookup.fPackageFragmentRoots;
-						IPackageFragmentRoot[] newRoots = computePackageFragmentRoots(classpath, true);
-						checkIdentical: { // compare all pkg fragment root lists
-							if (oldRoots.length == newRoots.length){
-								for (int i = 0, length = oldRoots.length; i < length; i++){
-									if (!oldRoots[i].equals(newRoots[i])){
-										break checkIdentical;
-									}
-								}
-								return; // no need to update
-							}	
-						}
-						info.setNameLookup(null); // discard name lookup (hold onto roots)
-					}				
-					info.setNonJavaResources(null);
-					info.setChildren(
-						computePackageFragmentRoots(classpath, false));		
-
+					computeChildren(info);
 				} catch(JavaModelException e){
 					try {
 						close(); // could not do better
 					} catch(JavaModelException ex){
+						// ignore
 					}
 				}
 			}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
index be86c50..d487621 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java
@@ -16,6 +16,7 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /** 
  * Info for IJavaProject.
@@ -93,7 +94,7 @@
 						String resName = res.getName();
 						
 						// ignore a jar file on the classpath
-						if (Util.isArchiveFileName(resName) && this.isClasspathEntryOrOutputLocation(resFullPath, classpath, projectOutput)) {
+						if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resName) && this.isClasspathEntryOrOutputLocation(resFullPath, classpath, projectOutput)) {
 							break;
 						}
 						// ignore .java file if src == project
@@ -212,7 +213,7 @@
 	/**
 	 * Set the fNonJavaResources to res value
 	 */
-	synchronized void setNonJavaResources(Object[] resources) {
+	void setNonJavaResources(Object[] resources) {
 
 		fNonJavaResources = resources;
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java
new file mode 100644
index 0000000..4551114
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core;
+
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.WorkingCopyOwner;
+import org.eclipse.jdt.internal.core.util.Util;
+
+
+public class LocalVariable extends JavaElement implements ILocalVariable {
+
+	public int declarationSourceStart, declarationSourceEnd;
+	public int nameStart, nameEnd;
+	String typeSignature;
+	
+	public LocalVariable(
+			JavaElement parent, 
+			String name, 
+			int declarationSourceStart, 
+			int declarationSourceEnd,
+			int nameStart, 
+			int nameEnd,
+			String typeSignature) {
+		
+		super(parent, name);
+		this.declarationSourceStart = declarationSourceStart;
+		this.declarationSourceEnd = declarationSourceEnd;
+		this.nameStart = nameStart;
+		this.nameEnd = nameEnd;
+		this.typeSignature = typeSignature;
+	}
+
+	protected void closing(Object info) {
+		// a local variable has no info
+	}
+
+	protected Object createElementInfo() {
+		// a local variable has no info
+		return null;
+	}
+
+	public boolean equals(Object o) {
+		if (!(o instanceof LocalVariable)) return false;
+		LocalVariable other = (LocalVariable)o;
+		return 
+			this.declarationSourceStart == other.declarationSourceStart 
+			&& this.declarationSourceEnd == other.declarationSourceEnd
+			&& this.nameStart == other.nameStart
+			&& this.nameEnd == other.nameEnd
+			&& super.equals(o);
+	}
+	
+	public boolean exists() {
+		return this.parent.exists(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=46192
+	}
+
+	protected void generateInfos(Object info, HashMap newElements, IProgressMonitor pm) {
+		// a local variable has no info
+	}
+
+	public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner owner) {
+		switch (token.charAt(0)) {
+			case JEM_COUNT:
+				return getHandleUpdatingCountFromMemento(memento, owner);
+		}
+		return this;
+	}
+
+	/*
+	 * @see JavaElement#getHandleMemento()
+	 */
+	public String getHandleMemento(){
+		StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
+		buff.append(getHandleMementoDelimiter());
+		buff.append(this.name);
+		buff.append(JEM_COUNT);
+		buff.append(this.declarationSourceStart);
+		buff.append(JEM_COUNT);
+		buff.append(this.declarationSourceEnd);
+		buff.append(JEM_COUNT);
+		buff.append(this.nameStart);
+		buff.append(JEM_COUNT);
+		buff.append(this.nameEnd);
+		buff.append(JEM_COUNT);
+		buff.append(this.typeSignature);
+		if (this.occurrenceCount > 1) {
+			buff.append(JEM_COUNT);
+			buff.append(this.occurrenceCount);
+		}
+		return buff.toString();
+	}
+
+	protected char getHandleMementoDelimiter() {
+		return JavaElement.JEM_LOCALVARIABLE;
+	}
+
+	public IResource getCorrespondingResource() {
+		return null;
+	}
+
+	public int getElementType() {
+		return LOCAL_VARIABLE;
+	}
+
+	public ISourceRange getNameRange() {
+		return new SourceRange(this.nameStart, this.nameEnd-this.nameStart+1);
+	}
+	
+	public IPath getPath() {
+		return this.parent.getPath();
+	}
+
+	public IResource getResource() {
+		return this.parent.getResource();
+	}
+
+	/**
+	 * @see ISourceReference
+	 */
+	public String getSource() throws JavaModelException {
+		IOpenable openable = this.parent.getOpenableParent();
+		IBuffer buffer = openable.getBuffer();
+		if (buffer == null) {
+			return null;
+		}
+		ISourceRange range = getSourceRange();
+		int offset = range.getOffset();
+		int length = range.getLength();
+		if (offset == -1 || length == 0 ) {
+			return null;
+		}
+		try {
+			return buffer.getText(offset, length);
+		} catch(RuntimeException e) {
+			return null;
+		}
+	}
+	
+	/**
+	 * @see ISourceReference
+	 */
+	public ISourceRange getSourceRange() {
+		return new SourceRange(this.declarationSourceStart, this.declarationSourceEnd-this.declarationSourceStart+1);
+	}
+	
+	public String getTypeSignature() {
+		return this.typeSignature;
+	}
+
+	public IResource getUnderlyingResource() throws JavaModelException {
+		return this.parent.getUnderlyingResource();
+	}
+
+	public int hashCode() {
+		return Util.combineHashCodes(this.parent.hashCode(), this.nameStart);
+	}
+	
+	public boolean isStructureKnown() throws JavaModelException {
+        return true;
+    }
+	
+	protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
+		buffer.append(this.tabString(tab));
+		if (info != NO_INFO) {
+			buffer.append(Signature.toString(this.getTypeSignature()));
+			buffer.append(" "); //$NON-NLS-1$
+		}
+		buffer.append(this.getElementName());
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
index e9385db..f30f42d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
@@ -11,7 +11,9 @@
 package org.eclipse.jdt.internal.core;
 
 import java.util.ArrayList;
+import java.util.StringTokenizer;
 
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.IJavaElement;
@@ -29,9 +31,9 @@
  * @see IMember
  */
 
-/* package */ abstract class Member extends SourceRefElement implements IMember {
-protected Member(int type, IJavaElement parent, String name) {
-	super(type, parent, name);
+public abstract class Member extends SourceRefElement implements IMember {
+protected Member(JavaElement parent, String name) {
+	super(parent, name);
 }
 protected boolean areSimilarMethods(
 	String name1, String[] params1, 
@@ -92,7 +94,7 @@
 /**
  * @see JavaElement#equalsDOMNode
  */
-protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
+protected boolean equalsDOMNode(IDOMNode node) {
 	return getElementName().equals(node.getName());
 }
 /*
@@ -137,9 +139,9 @@
  * @see IMember
  */
 public IType getDeclaringType() {
-	JavaElement parent = (JavaElement)getParent();
-	if (parent.fLEType == TYPE) {
-		return (IType) parent;
+	JavaElement parentElement = (JavaElement)getParent();
+	if (parentElement.getElementType() == TYPE) {
+		return (IType) parentElement;
 	}
 	return null;
 }
@@ -150,12 +152,83 @@
 	MemberElementInfo info = (MemberElementInfo) getElementInfo();
 	return info.getModifiers();
 }
+/*
+ * @see JavaElement
+ */
+public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner workingCopyOwner) {
+	switch (token.charAt(0)) {
+		case JEM_COUNT:
+			return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
+		case JEM_TYPE:
+			String typeName;
+			if (memento.hasMoreTokens()) {
+				typeName = memento.nextToken();
+				char firstChar = typeName.charAt(0);
+				if (firstChar == JEM_FIELD || firstChar == JEM_INITIALIZER || firstChar == JEM_METHOD || firstChar == JEM_TYPE || firstChar == JEM_COUNT) {
+					token = typeName;
+					typeName = ""; //$NON-NLS-1$
+				} else {
+					token = null;
+				}
+			} else {
+				typeName = ""; //$NON-NLS-1$
+				token = null;
+			}
+			JavaElement type = (JavaElement)getType(typeName, 1);
+			if (token == null) {
+				return type.getHandleFromMemento(memento, workingCopyOwner);
+			} else {
+				return type.getHandleFromMemento(token, memento, workingCopyOwner);
+			}
+		case JEM_LOCALVARIABLE:
+			String varName = memento.nextToken();
+			memento.nextToken(); // JEM_COUNT
+			int declarationStart = Integer.parseInt(memento.nextToken());
+			memento.nextToken(); // JEM_COUNT
+			int declarationEnd = Integer.parseInt(memento.nextToken());
+			memento.nextToken(); // JEM_COUNT
+			int nameStart = Integer.parseInt(memento.nextToken());
+			memento.nextToken(); // JEM_COUNT
+			int nameEnd = Integer.parseInt(memento.nextToken());
+			memento.nextToken(); // JEM_COUNT
+			String typeSignature = memento.nextToken();
+			return new LocalVariable(this, varName, declarationStart, declarationEnd, nameStart, nameEnd, typeSignature);
+	}
+	return null;
+}
 /**
  * @see JavaElement#getHandleMemento()
  */
 protected char getHandleMementoDelimiter() {
 	return JavaElement.JEM_TYPE;
 }
+/*
+ * Returns the outermost context defining a local element. Per construction, it can only be a
+ * method/field/initializarer member; thus, returns null if this member is already a top-level type or member type.
+ * e.g for X.java/X/Y/foo()/Z/bar()/T, it will return X.java/X/Y/foo()
+ */
+public Member getOuterMostLocalContext() {
+	IJavaElement current = this;
+	Member lastLocalContext = null;
+	parentLoop: while (true) {
+		switch (current.getElementType()) {
+			case CLASS_FILE:
+			case COMPILATION_UNIT:
+				break parentLoop; // done recursing
+			case TYPE:
+				// cannot be a local context
+				break;
+			case INITIALIZER:
+			case FIELD:
+			case METHOD:
+				 // these elements can define local members
+				lastLocalContext = (Member) current;
+				break;
+		}		
+		current = current.getParent();
+	} 
+	return lastLocalContext;
+}
 /**
  * @see IMember
  */
@@ -166,6 +239,19 @@
 /**
  * @see IMember
  */
+public IType getType(String typeName, int count) {
+	// TODO (jerome) disable after M6
+//	if (isBinary()) {
+//		throw new IllegalArgumentException("Not a source member " + toStringWithAncestors()); //$NON-NLS-1$
+//	} else {
+		SourceType type = new SourceType(this, typeName);
+		type.occurrenceCount = count;
+		return type;
+//	}
+}
+/**
+ * @see IMember
+ */
 public boolean isBinary() {
 	return false;
 }
@@ -175,8 +261,8 @@
 		if (Flags.isStatic(flags) && Flags.isPublic(flags)) {
 			String[] paramTypes= method.getParameterTypes();
 			if (paramTypes.length == 1) {
-				String name=  Signature.toString(paramTypes[0]);
-				return "String[]".equals(Signature.getSimpleName(name)); //$NON-NLS-1$
+				String typeSignature=  Signature.toString(paramTypes[0]);
+				return "String[]".equals(Signature.getSimpleName(typeSignature)); //$NON-NLS-1$
 			}
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModelUpdater.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModelUpdater.java
index 3dd6944..eb3e7b6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModelUpdater.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ModelUpdater.java
@@ -92,10 +92,7 @@
 			case IJavaElement.PACKAGE_FRAGMENT :
 				// get rid of namelookup since it holds onto obsolete cached info 
 				JavaProject project = (JavaProject) element.getJavaProject();
-				try {
-					project.getJavaProjectElementInfo().setNameLookup(null);
-				} catch (JavaModelException e) {
-				}
+				project.resetNameLookup();
 				break;
 		}
 	}
@@ -140,10 +137,7 @@
 			case IJavaElement.PACKAGE_FRAGMENT :
 				//1G1TW2T - get rid of namelookup since it holds onto obsolete cached info 
 				JavaProject project = (JavaProject) element.getJavaProject();
-				try {
-					project.getJavaProjectElementInfo().setNameLookup(null);
-				} catch (JavaModelException e) {
-				}
+				project.resetNameLookup();
 				break;
 		}
 	}
@@ -214,8 +208,9 @@
 				root = (IPackageFragmentRoot) element;
 				break;
 			case IJavaElement.COMPILATION_UNIT :
-				// filter out working copies (we don't want to add/remove them to/from the package fragment
-				if (((IWorkingCopy)element).isWorkingCopy()) {
+				// filter out working copies that are not primary (we don't want to add/remove them to/from the package fragment
+				CompilationUnit cu = (CompilationUnit)element;
+				if (cu.isWorkingCopy() && !cu.isPrimary()) {
 					return;
 				}
 			case IJavaElement.CLASS_FILE :
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveElementsOperation.java
index dc008aa..bce98b6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveElementsOperation.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.core;
 
 import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This operation moves elements from their current
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java
index f2bfa13..adbed48 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java
@@ -54,7 +54,7 @@
 			if (newCPIndex < newClasspath.length) {
 				System.arraycopy(newClasspath, 0, newClasspath = new IClasspathEntry[newCPIndex], 0, newCPIndex);
 			}
-			project.setRawClasspath(newClasspath, fMonitor);
+			project.setRawClasspath(newClasspath, progressMonitor);
 		}
 	}
 
@@ -122,9 +122,9 @@
 				IResource destRes;
 				if ((this.updateModelFlags & IPackageFragmentRoot.REPLACE) != 0
 						&& (destRes = workspaceRoot.findMember(this.destination)) != null) {
-					destRes.delete(this.updateResourceFlags, fMonitor);
+					destRes.delete(this.updateResourceFlags, progressMonitor);
 				}
-				rootResource.move(this.destination, this.updateResourceFlags, fMonitor);
+				rootResource.move(this.destination, this.updateResourceFlags, progressMonitor);
 			} catch (CoreException e) {
 				throw new JavaModelException(e);
 			}
@@ -147,7 +147,7 @@
 										&& folder.exists()) {
 									return true;
 								}
-								folder.create(updateResourceFlags, true, fMonitor);
+								folder.create(updateResourceFlags, true, progressMonitor);
 								return true;
 							}
 						} else {
@@ -156,9 +156,9 @@
 							IResource destRes;
 							if ((updateModelFlags & IPackageFragmentRoot.REPLACE) != 0
 									&& (destRes = workspaceRoot.findMember(destPath)) != null) {
-								destRes.delete(updateResourceFlags, fMonitor);
+								destRes.delete(updateResourceFlags, progressMonitor);
 							}
-							proxy.requestResource().move(destPath, updateResourceFlags, fMonitor);
+							proxy.requestResource().move(destPath, updateResourceFlags, progressMonitor);
 							return false;
 						}
 					} else {
@@ -167,9 +167,9 @@
 						IResource destRes;
 						if ((updateModelFlags & IPackageFragmentRoot.REPLACE) != 0
 								&& (destRes = workspaceRoot.findMember(destPath)) != null) {
-							destRes.delete(updateResourceFlags, fMonitor);
+							destRes.delete(updateResourceFlags, progressMonitor);
 						}
-						proxy.requestResource().move(destPath, updateResourceFlags, fMonitor);
+						proxy.requestResource().move(destPath, updateResourceFlags, progressMonitor);
 						return false;
 					}
 				}
@@ -221,7 +221,7 @@
 			if (newCPIndex < newClasspath.length) {
 				System.arraycopy(newClasspath, 0, newClasspath = new IClasspathEntry[newCPIndex], 0, newCPIndex);
 			}
-			project.setRawClasspath(newClasspath, fMonitor);
+			project.setRawClasspath(newClasspath, progressMonitor);
 		}
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveResourceElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveResourceElementsOperation.java
index 3bda54d..55dc1c2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveResourceElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MoveResourceElementsOperation.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.core;
 
 import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This operation moves resources (package fragments and compilation units) from their current
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java
index b1e6384..97e6315 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MultiOperation.java
@@ -27,45 +27,28 @@
  */
 public abstract class MultiOperation extends JavaModelOperation {
 	/**
-	 * The list of renamings supplied to the operation
+	 * Table specifying insertion positions for elements being 
+	 * copied/moved/renamed. Keyed by elements being processed, and
+	 * values are the corresponding insertion point.
+	 * @see processElements(IProgressMonitor)
 	 */
-	protected String[] fRenamingsList= null;
+	protected Map insertBeforeElements = new HashMap(1);
 	/**
 	 * Table specifying the new parent for elements being 
 	 * copied/moved/renamed.
 	 * Keyed by elements being processed, and
 	 * values are the corresponding destination parent.
 	 */
-	protected Map fParentElements;
-	/**
-	 * Table specifying insertion positions for elements being 
-	 * copied/moved/renamed. Keyed by elements being processed, and
-	 * values are the corresponding insertion point.
-	 * @see processElements(IProgressMonitor)
-	 */
-	protected Map fInsertBeforeElements= new HashMap(1);
+	protected Map newParents;
 	/**
 	 * This table presents the data in <code>fRenamingList</code> in a more
 	 * convenient way.
 	 */
-	protected Map fRenamings;
+	protected Map renamings;
 	/**
-	 * Creates a new <code>MultiOperation</code>.
+	 * The list of renamings supplied to the operation
 	 */
-	protected MultiOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements, boolean force) {
-		super(elementsToProcess, parentElements, force);
-		fParentElements = new HashMap(elementsToProcess.length);
-		if (elementsToProcess.length == parentElements.length) {
-			for (int i = 0; i < elementsToProcess.length; i++) {
-				fParentElements.put(elementsToProcess[i], parentElements[i]);
-			}
-		} else { //same destination for all elements to be moved/copied/renamed
-			for (int i = 0; i < elementsToProcess.length; i++) {
-				fParentElements.put(elementsToProcess[i], parentElements[0]);
-			}
-		}
-	
-	}
+	protected String[] renamingsList = null;
 	/**
 	 * Creates a new <code>MultiOperation</code> on <code>elementsToProcess</code>.
 	 */
@@ -73,6 +56,23 @@
 		super(elementsToProcess, force);
 	}
 	/**
+	 * Creates a new <code>MultiOperation</code>.
+	 */
+	protected MultiOperation(IJavaElement[] elementsToProcess, IJavaElement[] parentElements, boolean force) {
+		super(elementsToProcess, parentElements, force);
+		this.newParents = new HashMap(elementsToProcess.length);
+		if (elementsToProcess.length == parentElements.length) {
+			for (int i = 0; i < elementsToProcess.length; i++) {
+				this.newParents.put(elementsToProcess[i], parentElements[i]);
+			}
+		} else { //same destination for all elements to be moved/copied/renamed
+			for (int i = 0; i < elementsToProcess.length; i++) {
+				this.newParents.put(elementsToProcess[i], parentElements[0]);
+			}
+		}
+	
+	}
+	/**
 	 * Convenience method to create a <code>JavaModelException</code>
 	 * embending a <code>JavaModelStatus</code>.
 	 */
@@ -93,7 +93,7 @@
 	 * Returns the parent of the element being copied/moved/renamed.
 	 */
 	protected IJavaElement getDestinationParent(IJavaElement child) {
-		return (IJavaElement)fParentElements.get(child);
+		return (IJavaElement)this.newParents.get(child);
 	}
 	/**
 	 * Returns the name to be used by the progress monitor.
@@ -104,8 +104,8 @@
 	 * if there are no renamings specified.
 	 */
 	protected String getNewNameFor(IJavaElement element) {
-		if (fRenamings != null)
-			return (String) fRenamings.get(element);
+		if (this.renamings != null)
+			return (String) this.renamings.get(element);
 		else
 			return null;
 	}
@@ -114,11 +114,11 @@
 	 * values are the new name.
 	 */
 	private void initializeRenamings() {
-		if (fRenamingsList != null && fRenamingsList.length == fElementsToProcess.length) {
-			fRenamings = new HashMap(fRenamingsList.length);
-			for (int i = 0; i < fRenamingsList.length; i++) {
-				if (fRenamingsList[i] != null) {
-					fRenamings.put(fElementsToProcess[i], fRenamingsList[i]);
+		if (this.renamingsList != null && this.renamingsList.length == elementsToProcess.length) {
+			this.renamings = new HashMap(this.renamingsList.length);
+			for (int i = 0; i < this.renamingsList.length; i++) {
+				if (this.renamingsList[i] != null) {
+					this.renamings.put(elementsToProcess[i], this.renamingsList[i]);
 				}
 			}
 		}
@@ -151,13 +151,13 @@
 	 * be completed.
 	 */
 	protected void processElements() throws JavaModelException {
-		beginTask(getMainTaskName(), fElementsToProcess.length);
+		beginTask(getMainTaskName(), elementsToProcess.length);
 		IJavaModelStatus[] errors = new IJavaModelStatus[3];
 		int errorsCounter = 0;
-		for (int i = 0; i < fElementsToProcess.length; i++) {
+		for (int i = 0; i < elementsToProcess.length; i++) {
 			try {
-				verify(fElementsToProcess[i]);
-				processElement(fElementsToProcess[i]);
+				verify(elementsToProcess[i]);
+				processElement(elementsToProcess[i]);
 			} catch (JavaModelException jme) {
 				if (errorsCounter == errors.length) {
 					// resize
@@ -187,7 +187,7 @@
 	 * inserted at the end of the container.
 	 */
 	public void setInsertBefore(IJavaElement modifiedElement, IJavaElement newSibling) {
-		fInsertBeforeElements.put(modifiedElement, newSibling);
+		this.insertBeforeElements.put(modifiedElement, newSibling);
 	}
 	/**
 	 * Sets the new names to use for each element being copied. The renamings
@@ -201,8 +201,8 @@
 	 * is changed.  Therefore, if a new name is specified for the child,
 	 * the child's name will not be changed.
 	 */
-	public void setRenamings(String[] renamings) {
-		fRenamingsList = renamings;
+	public void setRenamings(String[] renamingsList) {
+		this.renamingsList = renamingsList;
 		initializeRenamings();
 	}
 	/**
@@ -239,8 +239,11 @@
 			case IJavaElement.COMPILATION_UNIT :
 				if (destType != IJavaElement.PACKAGE_FRAGMENT)
 					error(IJavaModelStatusConstants.INVALID_DESTINATION, element);
-				else if (isMove() && ((ICompilationUnit) element).isWorkingCopy())
-					error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
+				else {
+					CompilationUnit cu = (CompilationUnit)element;
+					if (isMove() && cu.isWorkingCopy() && !cu.isPrimary())
+						error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
+				}
 				break;
 			case IJavaElement.PACKAGE_FRAGMENT :
 				IPackageFragment fragment = (IPackageFragment) element;
@@ -290,7 +293,7 @@
 	 * its parent is the destination container of this <code>element</code>.
 	 */
 	protected void verifySibling(IJavaElement element, IJavaElement destination) throws JavaModelException {
-		IJavaElement insertBeforeElement = (IJavaElement) fInsertBeforeElements.get(element);
+		IJavaElement insertBeforeElement = (IJavaElement) this.insertBeforeElements.get(element);
 		if (insertBeforeElement != null) {
 			if (!insertBeforeElement.exists() || !insertBeforeElement.getParent().equals(destination)) {
 				error(IJavaModelStatusConstants.INVALID_SIBLING, insertBeforeElement);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
index ae93e99..e02fc53 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
@@ -11,14 +11,18 @@
 package org.eclipse.jdt.internal.core;
 
 import java.io.File;
+import java.util.*;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IWorkspace;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.ICompilationUnit;
@@ -27,10 +31,14 @@
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.IWorkingCopy;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.internal.core.util.PerThreadObject;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.ITypeNameRequestor;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.Util;
+
 /**
  * A <code>NameLookup</code> provides name resolution within a Java project.
  * The name lookup facility uses the project's classpath to prioritize the 
@@ -47,7 +55,7 @@
  * in real time through an <code>IJavaElementRequestor</code>.
  *
  */
-public class NameLookup {
+public class NameLookup implements SuffixConstants {
 	/**
 	 * Accept flag for specifying classes.
 	 */
@@ -86,7 +94,7 @@
 	 * Allows working copies to take precedence over compilation units.
 	 * The cache is a 2-level cache, first keyed by thread.
 	 */
-	protected PerThreadObject unitsToLookInside = new PerThreadObject();
+	protected ThreadLocal unitsToLookInside = new ThreadLocal();
 
 	public NameLookup(IJavaProject project) throws JavaModelException {
 		configureFromProject(project);
@@ -196,7 +204,7 @@
 		if (index != -1) {
 			cuName= cuName.substring(0, index);
 		}
-		cuName += ".java"; //$NON-NLS-1$
+		cuName += SUFFIX_STRING_java;
 		IPackageFragment[] frags= (IPackageFragment[]) fPackageFragments.get(pkgName);
 		if (frags != null) {
 			for (int i= 0; i < frags.length; i++) {
@@ -355,8 +363,11 @@
 	 * 
 	 */
 	public IType findType(String typeName, String packageName, boolean partialMatch, int acceptFlags) {
-		if (packageName == null) {
+		if (packageName == null || packageName.length() == 0) {
 			packageName= IPackageFragment.DEFAULT_PACKAGE_NAME;
+		} else if (typeName.length() > 0 && Character.isLowerCase(typeName.charAt(0))) {
+			// see if this is a known package and not a type
+			if (findPackageFragments(packageName + "." + typeName, false) != null) return null; //$NON-NLS-1$
 		}
 		JavaElementRequestor elementRequestor = new JavaElementRequestor();
 		seekPackageFragments(packageName, false, elementRequestor);
@@ -431,16 +442,62 @@
 	 * @see #ACCEPT_INTERFACES
 	 */
 	public IType findType(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags) {
-		if (pkg == null) {
-			return null;
-		}
+		if (pkg == null) return null;
+
 		// Return first found (ignore duplicates).
-//synchronized(JavaModelManager.getJavaModelManager()){	
 		SingleTypeRequestor typeRequestor = new SingleTypeRequestor();
 		seekTypes(name, pkg, partialMatch, acceptFlags, typeRequestor);
-		IType type= typeRequestor.getType();
+		IType type = typeRequestor.getType();
+//		if (type == null)
+//			type = findSecondaryType(name, pkg, partialMatch, acceptFlags);
 		return type;
-//}
+	}
+
+	// TODO (kent) enable once index support is in
+	IType findSecondaryType(String typeName, IPackageFragment pkg, boolean partialMatch, final int acceptFlags) {
+		try {
+			final ArrayList paths = new ArrayList();
+			ITypeNameRequestor nameRequestor = new ITypeNameRequestor() {
+				public void acceptClass(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path) {
+					if ((acceptFlags & ACCEPT_CLASSES) != 0)
+						if (enclosingTypeNames == null || enclosingTypeNames.length == 0) // accept only top level types
+							paths.add(path);
+				}
+				public void acceptInterface(char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path) {
+					if ((acceptFlags & ACCEPT_INTERFACES) != 0)
+						if (enclosingTypeNames == null || enclosingTypeNames.length == 0) // accept only top level types
+							paths.add(path);
+				}
+			};
+
+			new SearchEngine().searchAllTypeNames(
+				workspace,
+				pkg.getElementName().toCharArray(),
+				typeName.toCharArray(),
+				partialMatch ? IJavaSearchConstants.PREFIX_MATCH : IJavaSearchConstants.EXACT_MATCH,
+				partialMatch ? IJavaSearchConstants.CASE_INSENSITIVE : IJavaSearchConstants.CASE_SENSITIVE,
+				IJavaSearchConstants.TYPE,
+				SearchEngine.createJavaSearchScope(new IJavaElement[] {pkg}, false),
+				nameRequestor,
+				IJavaSearchConstants.CANCEL_IF_NOT_READY_TO_SEARCH,
+				null);
+
+			if (!paths.isEmpty()) {
+				for (int i = 0, l = paths.size(); i < l; i++) {
+					String pathname = (String) paths.get(i);
+					if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(pathname)) {
+						IFile file = workspace.getRoot().getFile(new Path(pathname));
+						ICompilationUnit unit = JavaCore.createCompilationUnitFrom(file);
+						return unit.getType(typeName);
+					}
+				}
+			}
+		} catch (JavaModelException e) {
+			// ignore
+		} catch (OperationCanceledException ignore) {
+			// ignore
+		}
+		return null;
 	}
 
 	/**
@@ -622,13 +679,55 @@
 	 * Performs type search in a source package.
 	 */
 	protected void seekTypesInSourcePackage(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
+		
 		ICompilationUnit[] compilationUnits = null;
 		try {
 			compilationUnits = pkg.getCompilationUnits();
 		} catch (JavaModelException npe) {
 			return; // the package is not present
 		}
+
+		// replace with working copies to look inside
 		int length= compilationUnits.length;
+		boolean[] isWorkingCopy = new boolean[length];
+		Map workingCopies = (Map) this.unitsToLookInside.get();
+		int workingCopiesSize;
+		if (workingCopies != null && (workingCopiesSize = workingCopies.size()) > 0) {
+			Map temp = new HashMap(workingCopiesSize);
+			temp.putAll(workingCopies);
+			for (int i = 0; i < length; i++) {
+				ICompilationUnit unit = compilationUnits[i];
+				ICompilationUnit workingCopy = (ICompilationUnit)temp.remove(unit);
+				if (workingCopy != null) {
+					compilationUnits[i] = workingCopy;
+					isWorkingCopy[i] = true;
+				}
+			}
+			// add remaining working copies that belong to this package
+			int index = 0;
+			Collection values = temp.values();
+			Iterator iterator = values.iterator();
+			while (iterator.hasNext()) {
+				ICompilationUnit workingCopy = (ICompilationUnit)iterator.next();
+				if (pkg.equals(workingCopy.getParent())) {
+					if (index == 0) {
+						int valuesLength = values.size();
+						index = length;
+						length += valuesLength;
+						System.arraycopy(compilationUnits, 0, compilationUnits = new ICompilationUnit[length], 0, index);
+						System.arraycopy(isWorkingCopy, 0, isWorkingCopy = new boolean[length], 0, index);
+					}
+					isWorkingCopy[index] = true; 
+					compilationUnits[index++] = workingCopy;
+				}
+			}
+			if (index > 0 && index < length) {
+				System.arraycopy(compilationUnits, 0, compilationUnits = new ICompilationUnit[index], 0, index);
+				System.arraycopy(isWorkingCopy, 0, isWorkingCopy = new boolean[index], 0, index);
+				length = index;
+			}
+		}
+			
 		String matchName = name;
 		int index= name.indexOf('$');
 		boolean potentialMemberType = false;
@@ -644,10 +743,10 @@
 		 * the compilationUnits always will. So add it if we're looking for 
 		 * an exact match.
 		 */
-		String unitName = partialMatch ? matchName.toLowerCase() : matchName + ".java"; //$NON-NLS-1$
+		String unitName = partialMatch ? matchName.toLowerCase() : matchName + SUFFIX_STRING_java;
 		String potentialUnitName = null;
 		if (potentialMemberType) {
-			potentialUnitName = partialMatch ? potentialMatchName.toLowerCase() : potentialMatchName + ".java"; //$NON-NLS-1$
+			potentialUnitName = partialMatch ? potentialMatchName.toLowerCase() : potentialMatchName + SUFFIX_STRING_java;
 		}
 
 		for (int i= 0; i < length; i++) {
@@ -655,14 +754,9 @@
 				return;
 			ICompilationUnit compilationUnit= compilationUnits[i];
 			
-			// unit to look inside
-			ICompilationUnit unitToLookInside = null;
-			Map workingCopies = (Map) this.unitsToLookInside.getCurrent();
-			if (workingCopies != null 
-					&& (unitToLookInside = (ICompilationUnit)workingCopies.get(compilationUnit)) != null){
-					compilationUnit = unitToLookInside;
-				}
-			if ((unitToLookInside != null && !potentialMemberType) || nameMatches(unitName, compilationUnit, partialMatch)) {
+			if ((isWorkingCopy[i] && !potentialMemberType)
+					|| nameMatches(unitName, compilationUnit, partialMatch)) {
+						
 				IType[] types= null;
 				try {
 					types= compilationUnit.getTypes();
@@ -701,24 +795,20 @@
 /**
  * Remembers a set of compilation units that will be looked inside
  * when looking up a type. If they are working copies, they take
- * precedence of their compilation units.
+ * precedence over their compilation units.
  * <code>null</code> means that no special compilation units should be used.
  */
-public void setUnitsToLookInside(IWorkingCopy[] unitsToLookInside) {
+public void setUnitsToLookInside(ICompilationUnit[] unitsToLookInside) {
 	
 	if (unitsToLookInside == null) {
-		this.unitsToLookInside.setCurrent(null); 
+		this.unitsToLookInside.set(null); 
 	} else {
 		HashMap workingCopies = new HashMap();
-		this.unitsToLookInside.setCurrent(workingCopies);
+		this.unitsToLookInside.set(workingCopies);
 		for (int i = 0, length = unitsToLookInside.length; i < length; i++) {
-			IWorkingCopy unitToLookInside = unitsToLookInside[i];
-			ICompilationUnit original = (ICompilationUnit)unitToLookInside.getOriginalElement();
-			if (original != null) {
-				workingCopies.put(original, unitToLookInside);
-			} else {
-				workingCopies.put(unitToLookInside, unitToLookInside);
-			}
+			ICompilationUnit unitToLookInside = unitsToLookInside[i];
+			ICompilationUnit original = unitToLookInside.getPrimary();
+			workingCopies.put(original, unitToLookInside);
 		}
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java
index 5749c58..ef25cbe 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java
@@ -10,9 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.text.NumberFormat;
+import java.util.*;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
 
 import org.eclipse.core.resources.*;
@@ -26,7 +27,6 @@
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
 import org.eclipse.jdt.internal.codeassist.ISearchableNameEnvironment;
-import org.eclipse.jdt.internal.codeassist.ISelectionRequestor;
 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
 
 
@@ -38,129 +38,25 @@
  */
 public abstract class Openable extends JavaElement implements IOpenable, IBufferChangedListener {
 
-protected Openable(int type, IJavaElement parent, String name) {
-	super(type, parent, name);
-}
-	/**
-	 * The buffer associated with this element has changed. Registers
-	 * this element as being out of synch with its buffer's contents.
-	 * If the buffer has been closed, this element is set as NOT out of
-	 * synch with the contents.
-	 *
-	 * @see IBufferChangedListener
-	 */
-	public void bufferChanged(BufferChangedEvent event) {
-		if (event.getBuffer().isClosed()) {
-			JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
-			getBufferManager().removeBuffer(event.getBuffer());
-		} else {
-			JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().put(this, this);
-		}
-	}	
-/**
- * Updates the info objects for this element and all of its children by
- * removing the current infos, generating new infos, and then placing
- * the new infos into the Java Model cache tables.
- */
-protected void buildStructure(OpenableElementInfo info, IProgressMonitor monitor) throws JavaModelException {
-
-	if (monitor != null && monitor.isCanceled()) return;
-	
-	// remove existing (old) infos
-	removeInfo();
-	HashMap newElements = new HashMap(11);
-	info.setIsStructureKnown(generateInfos(info, monitor, newElements, getResource()));
-	JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
-	for (Iterator iter = newElements.keySet().iterator(); iter.hasNext();) {
-		IJavaElement key = (IJavaElement) iter.next();
-		Object value = newElements.get(key);
-		JavaModelManager.getJavaModelManager().putInfo(key, value);
-	}
-		
-	// add the info for this at the end, to ensure that a getInfo cannot reply null in case the LRU cache needs
-	// to be flushed. Might lead to performance issues.
-	// see PR 1G2K5S7: ITPJCORE:ALL - NPE when accessing source for a binary type
-	JavaModelManager.getJavaModelManager().putInfo(this, info);	
+protected Openable(JavaElement parent, String name) {
+	super(parent, name);
 }
 /**
- * Close the buffer associated with this element, if any.
+ * The buffer associated with this element has changed. Registers
+ * this element as being out of synch with its buffer's contents.
+ * If the buffer has been closed, this element is set as NOT out of
+ * synch with the contents.
+ *
+ * @see IBufferChangedListener
  */
-protected void closeBuffer(OpenableElementInfo info) {
-	if (!hasBuffer()) return; // nothing to do
-	IBuffer buffer = null;
-	buffer = getBufferManager().getBuffer(this);
-	if (buffer != null) {
-		buffer.close();
-		buffer.removeBufferChangedListener(this);
+public void bufferChanged(BufferChangedEvent event) {
+	if (event.getBuffer().isClosed()) {
+		JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
+		getBufferManager().removeBuffer(event.getBuffer());
+	} else {
+		JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().put(this, this);
 	}
-}
-/**
- * This element is being closed.  Do any necessary cleanup.
- */
-protected void closing(Object info) throws JavaModelException {
-	OpenableElementInfo openableInfo = (OpenableElementInfo) info;
-	closeBuffer(openableInfo);
-	super.closing(info);
-}
-/**
- * @see ICodeAssist
- */
-protected void codeComplete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, ICompletionRequestor requestor) throws JavaModelException {
-	if (requestor == null) {
-		throw new IllegalArgumentException(Util.bind("codeAssist.nullRequestor")); //$NON-NLS-1$
-	}
-	IBuffer buffer = getBuffer();
-	if (buffer == null) {
-		return;
-	}
-	if (position < -1 || position > buffer.getLength()) {
-		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS));
-	}
-	JavaProject project = (JavaProject) getJavaProject();
-	SearchableEnvironment environment = (SearchableEnvironment) project.getSearchableNameEnvironment();
-	NameLookup nameLookup = project.getNameLookup();
-	environment.unitToSkip = unitToSkip;
-
-	CompletionEngine engine = new CompletionEngine(environment, new CompletionRequestorWrapper(requestor,nameLookup), project.getOptions(true), project);
-	engine.complete(cu, position, 0);
-	environment.unitToSkip = null;
-}
-/**
- * @see ICodeAssist
- */
-protected IJavaElement[] codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length) throws JavaModelException {
-	SelectionRequestor requestor= new SelectionRequestor(((JavaProject)getJavaProject()).getNameLookup(), this);
-	this.codeSelect(cu, offset, length, requestor);
-	return requestor.getElements();
-}
-/**
- * @see ICodeAssist
- */
-protected void codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length, ISelectionRequestor requestor) throws JavaModelException {
-	IBuffer buffer = getBuffer();
-	if (buffer == null) {
-		return;
-	}
-	int end= buffer.getLength();
-	if (offset < 0 || length < 0 || offset + length > end ) {
-		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INDEX_OUT_OF_BOUNDS));
-	}
-
-	// fix for 1FVGGKF
-	JavaProject project = (JavaProject)getJavaProject();
-	ISearchableNameEnvironment environment = project.getSearchableNameEnvironment();
-	
-	// fix for 1FVXGDK
-	SelectionEngine engine = new SelectionEngine(environment, requestor, project.getOptions(true));
-	engine.select(cu, offset, offset + length - 1);
-}
-/**
- * Returns a new element info for this element.
- */
-protected OpenableElementInfo createElementInfo() {
-	return new OpenableElementInfo();
-}
-
+}	
 /**
  * Builds this element's structure and properties in the given
  * info object, based on this element's current contents (reuse buffer
@@ -171,7 +67,151 @@
  * if successful, or false if an error is encountered while determining
  * the structure of this element.
  */
-protected abstract boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException;
+protected abstract boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException;
+/*
+ * Returns whether this element can be removed from the Java model cache to make space.
+ */
+public boolean canBeRemovedFromCache() {
+	try {
+		return !hasUnsavedChanges();
+	} catch (JavaModelException e) {
+		return false;
+	}
+}
+/*
+ * Returns whether the buffer of this element can be removed from the Java model cache to make space.
+ */
+public boolean canBufferBeRemovedFromCache(IBuffer buffer) {
+	return !buffer.hasUnsavedChanges();
+}
+/**
+ * Close the buffer associated with this element, if any.
+ */
+protected void closeBuffer() {
+	if (!hasBuffer()) return; // nothing to do
+	IBuffer buffer = getBufferManager().getBuffer(this);
+	if (buffer != null) {
+		buffer.close();
+		buffer.removeBufferChangedListener(this);
+	}
+}
+/**
+ * This element is being closed.  Do any necessary cleanup.
+ */
+protected void closing(Object info) {
+	closeBuffer();
+}
+protected void codeComplete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
+	if (requestor == null) {
+		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
+	}
+	IBuffer buffer = getBuffer();
+	if (buffer == null) {
+		return;
+	}
+	if (position < -1 || position > buffer.getLength()) {
+		throw new IllegalArgumentException("Completion position "+position+" is not located in supplied source range (0, "+buffer.getLength()+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	}
+	JavaProject project = (JavaProject) getJavaProject();
+	SearchableEnvironment environment = null;
+	NameLookup nameLookup = null;
+	try {
+		// set unit to skip
+		environment = (SearchableEnvironment) project.getSearchableNameEnvironment();
+		environment.unitToSkip = unitToSkip;
+	
+		// set the units to look inside
+		nameLookup = project.getNameLookup();
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+		nameLookup.setUnitsToLookInside(workingCopies);
+
+		// code complete
+		CompletionRequestorWrapper requestorWrapper = new CompletionRequestorWrapper(requestor,nameLookup);
+		CompletionEngine engine = new CompletionEngine(environment, requestorWrapper, project.getOptions(true), project);
+		requestorWrapper.completionEngine = engine;
+		engine.complete(cu, position, 0);
+	} finally {
+		if (environment != null) {
+			environment.unitToSkip = null;
+		}
+		if (nameLookup != null) {
+			nameLookup.setUnitsToLookInside(null);
+		}
+	}
+}
+protected IJavaElement[] codeSelect(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, int offset, int length, WorkingCopyOwner owner) throws JavaModelException {
+	NameLookup nameLookup = null;
+	try {
+		// set the units to look inside
+		nameLookup = ((JavaProject)getJavaProject()).getNameLookup();
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+		nameLookup.setUnitsToLookInside(workingCopies);
+
+		// code select
+		SelectionRequestor requestor= new SelectionRequestor(nameLookup, this);
+		IBuffer buffer = getBuffer();
+		if (buffer == null) {
+			return requestor.getElements();
+		}
+		int end= buffer.getLength();
+		if (offset < 0 || length < 0 || offset + length > end ) {
+			throw new IllegalArgumentException("Selected range ("+offset+ ", " + (offset+length)+") is not located in supplied source range (0, "+end+")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+		}
+	
+		// fix for 1FVGGKF
+		JavaProject project = (JavaProject)getJavaProject();
+		ISearchableNameEnvironment environment = project.getSearchableNameEnvironment();
+		
+		// fix for 1FVXGDK
+		SelectionEngine engine = new SelectionEngine(environment, requestor, project.getOptions(true));
+		engine.select(cu, offset, offset + length - 1);
+		return requestor.getElements();
+	} finally {
+		if (nameLookup != null) {
+			nameLookup.setUnitsToLookInside(null);
+		}
+	}
+}
+/*
+ * Returns a new element info for this element.
+ */
+protected Object createElementInfo() {
+	return new OpenableElementInfo();
+}
+protected void generateInfos(Object info, HashMap newElements, IProgressMonitor monitor) throws JavaModelException {
+
+	if (JavaModelManager.VERBOSE){
+		System.out.println("OPENING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
+	}
+	
+	// open the parent if necessary
+	openParent(info, newElements, monitor);
+	if (monitor != null && monitor.isCanceled()) return;
+
+	 // puts the info before building the structure so that questions to the handle behave as if the element existed
+	 // (case of compilation units becoming working copies)
+	newElements.put(this, info);
+
+	// build the structure of the openable (this will open the buffer if needed)
+	try {
+		OpenableElementInfo openableElementInfo = (OpenableElementInfo)info;
+		boolean isStructureKnown = buildStructure(openableElementInfo, monitor, newElements, getResource());
+		openableElementInfo.setIsStructureKnown(isStructureKnown);
+	} catch (JavaModelException e) {
+		newElements.remove(this);
+		throw e;
+	}
+	
+	// remove out of sync buffer for this element
+	JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this);
+
+	if (JavaModelManager.VERBOSE) {
+		System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
+		System.out.println("-> Openable cache filling ratio = " + NumberFormat.getInstance().format(JavaModelManager.getJavaModelManager().cache.openableFillingRatio()) + "%"); //$NON-NLS-1$//$NON-NLS-2$
+	}
+}
 /**
  * Note: a buffer with no unsaved changes can be closed by the Java Model
  * since it has a finite number of buffers allowed open at one time. If this
@@ -184,22 +224,20 @@
 public IBuffer getBuffer() throws JavaModelException {
 	if (hasBuffer()) {
 		// ensure element is open
-		if (!isOpen()) {
-			getElementInfo();
-		}
+		Object info = getElementInfo();
 		IBuffer buffer = getBufferManager().getBuffer(this);
 		if (buffer == null) {
 			// try to (re)open a buffer
-			buffer = openBuffer(null);
+			buffer = openBuffer(null, info);
 		}
 		return buffer;
 	} else {
 		return null;
 	}
 }
-
 /**
  * Answers the buffer factory to use for creating new buffers
+ * @deprecated
  */
 public IBufferFactory getBufferFactory(){
 	return getBufferManager().getDefaultBufferFactory();
@@ -233,14 +271,14 @@
  * @see IJavaElement
  */
 public IResource getUnderlyingResource() throws JavaModelException {
-	IResource parentResource = fParent.getUnderlyingResource();
+	IResource parentResource = this.parent.getUnderlyingResource();
 	if (parentResource == null) {
 		return null;
 	}
 	int type = parentResource.getType();
 	if (type == IResource.FOLDER || type == IResource.PROJECT) {
 		IContainer folder = (IContainer) parentResource;
-		IResource resource = folder.findMember(fName);
+		IResource resource = folder.findMember(this.name);
 		if (resource == null) {
 			throw newNotPresentException();
 		} else {
@@ -251,16 +289,6 @@
 	}
 }
 
-public boolean exists() {
-	
-	IPackageFragmentRoot root = this.getPackageFragmentRoot();
-	if (root == null || root == this || !root.isArchive()) {
-		return parentExists() && resourceExists();
-	} else {
-		return super.exists();
-	}
-}	
-
 /**
  * Returns true if this element may have an associated source buffer,
  * otherwise false. Subclasses must override as required.
@@ -288,10 +316,11 @@
 	}
 	// for package fragments, package fragment roots, and projects must check open buffers
 	// to see if they have an child with unsaved changes
-	if (fLEType == PACKAGE_FRAGMENT ||
-		fLEType == PACKAGE_FRAGMENT_ROOT ||
-		fLEType == JAVA_PROJECT ||
-		fLEType == JAVA_MODEL) { // fix for 1FWNMHH
+	int elementType = getElementType();
+	if (elementType == PACKAGE_FRAGMENT ||
+		elementType == PACKAGE_FRAGMENT_ROOT ||
+		elementType == JAVA_PROJECT ||
+		elementType == JAVA_MODEL) { // fix for 1FWNMHH
 		Enumeration openBuffers= getBufferManager().getOpenBuffers();
 		while (openBuffers.hasMoreElements()) {
 			IBuffer buffer= (IBuffer)openBuffers.nextElement();
@@ -311,7 +340,7 @@
  *
  * @see IOpenable
  */
-public boolean isConsistent() throws JavaModelException {
+public boolean isConsistent() {
 	return true;
 }
 /**
@@ -319,9 +348,7 @@
  * @see IOpenable
  */
 public boolean isOpen() {
-	synchronized(JavaModelManager.getJavaModelManager()){
-		return JavaModelManager.getJavaModelManager().getInfo(this) != null;
-	}
+	return JavaModelManager.getJavaModelManager().getInfo(this) != null;
 }
 /**
  * Returns true if this represents a source element.
@@ -334,20 +361,42 @@
 /**
  * @see IOpenable
  */
-public void makeConsistent(IProgressMonitor pm) throws JavaModelException {
-	if (!isConsistent()) {
-		buildStructure((OpenableElementInfo)getElementInfo(), pm);
+public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
+	if (isConsistent()) return;
+	
+	// close
+	JavaModelManager manager = JavaModelManager.getJavaModelManager();
+	manager.removeInfoAndChildren(this);
+	
+	boolean hadTemporaryCache = manager.hasTemporaryCache();
+	try {
+		HashMap newElements = manager.getTemporaryCache();
+		openWhenClosed(newElements, monitor);
+		if (newElements.get(this) == null) {
+			// close any buffer that was opened for the new elements
+			Iterator iterator = newElements.keySet().iterator();
+			while (iterator.hasNext()) {
+				IJavaElement element = (IJavaElement)iterator.next();
+				if (element instanceof Openable) {
+					((Openable)element).closeBuffer();
+				}
+			}
+			throw newNotPresentException();
+		}
+		if (!hadTemporaryCache) {
+			manager.putInfos(this, newElements);
+		}
+	} finally {
+		if (!hadTemporaryCache) {
+			manager.resetTemporaryCache();
+		}
 	}
 }
 /**
  * @see IOpenable
  */
 public void open(IProgressMonitor pm) throws JavaModelException {
-	if (!isOpen()) {
-		// TODO: need to synchronize (IOpenable.open(IProgressMonitor) is API
-		// TODO: could use getElementInfo instead
-		this.openWhenClosed(pm);
-	}
+	getElementInfo(pm);
 }
 
 /**
@@ -356,60 +405,18 @@
  * By default, do nothing - subclasses that have buffers
  * must override as required.
  */
-protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException {
+protected IBuffer openBuffer(IProgressMonitor pm, Object info) throws JavaModelException {
 	return null;
 }
 
 /**
- * 	Open the parent element if necessary
- * 
+ * Open the parent element if necessary.
  */
-protected void openParent(IProgressMonitor pm) throws JavaModelException {
+protected void openParent(Object childInfo, HashMap newElements, IProgressMonitor pm) throws JavaModelException {
 
 	Openable openableParent = (Openable)getOpenableParent();
-	if (openableParent != null) {
-		if (!openableParent.isOpen()){
-			openableParent.openWhenClosed(pm);
-		}
-	}
-}
-
-/**
- * Open an <code>Openable</code> that is known to be closed (no check for <code>isOpen()</code>).
- */
-protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
-	try {
-		
-		if (JavaModelManager.VERBOSE){
-			System.out.println("OPENING Element ("+ Thread.currentThread()+"): " + this.toStringWithAncestors()); //$NON-NLS-1$//$NON-NLS-2$
-		}
-		
-		// 1) Parent must be open - open the parent if necessary
-		openParent(pm);
-
-		// 2) create the new element info and open a buffer if needed
-		OpenableElementInfo info = createElementInfo();
-		if (isSourceElement()) {
-			this.openBuffer(pm);
-		} 
-
-		// 3) build the structure of the openable
-		buildStructure(info, pm);
-
-		// 4) anything special
-		opening(info);
-		
-		if (JavaModelManager.VERBOSE) {
-			System.out.println("-> Package cache size = " + JavaModelManager.getJavaModelManager().cache.pkgSize()); //$NON-NLS-1$
-			System.out.println("-> Openable cache filling ratio = " + JavaModelManager.getJavaModelManager().cache.openableFillingRatio() + "%"); //$NON-NLS-1$//$NON-NLS-2$
-		}
-
-		// if any problems occuring openning the element, ensure that it's info
-		// does not remain in the cache	(some elements, pre-cache their info
-		// as they are being opened).
-	} catch (JavaModelException e) {
-		JavaModelManager.getJavaModelManager().removeInfo(this);
-		throw e;
+	if (openableParent != null && !openableParent.isOpen()){
+		openableParent.generateInfos(openableParent.createElementInfo(), newElements, pm);
 	}
 }
 
@@ -419,9 +426,9 @@
  */
 protected boolean parentExists(){
 	
-	IJavaElement parent = this.getParent();
-	if (parent == null) return true;
-	return parent.exists();
+	IJavaElement parentElement = getParent();
+	if (parentElement == null) return true;
+	return parentElement.exists();
 }
 
 /**
@@ -441,7 +448,7 @@
  * @see IOpenable
  */
 public void save(IProgressMonitor pm, boolean force) throws JavaModelException {
-	if (isReadOnly() || this.getResource().isReadOnly()) {
+	if (isReadOnly()) {
 		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
 	}
 	IBuffer buf = getBuffer();
@@ -468,8 +475,8 @@
  */
 protected void codeComplete(org.eclipse.jdt.internal.compiler.env.ICompilationUnit cu, org.eclipse.jdt.internal.compiler.env.ICompilationUnit unitToSkip, int position, final ICodeCompletionRequestor requestor) throws JavaModelException {
 
-	if (requestor == null){
-		codeComplete(cu, unitToSkip, position, (ICompletionRequestor)null);
+	if (requestor == null){ 
+		codeComplete(cu, unitToSkip, position, null, DefaultWorkingCopyOwner.PRIMARY);
 		return;
 	}
 	codeComplete(
@@ -478,6 +485,7 @@
 		position,
 		new ICompletionRequestor(){
 			public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
+				// ignore
 			}
 			public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
 				requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
@@ -495,10 +503,11 @@
 					marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
 					requestor.acceptError(marker);
 				} catch(CoreException e){
+					// could not create marker: ignore
 				}
 			}
-			public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
-				requestor.acceptField(declaringTypePackageName, declaringTypeName, name, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
+			public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
+				requestor.acceptField(declaringTypePackageName, declaringTypeName, fieldName, typePackageName, typeName, completionName, modifiers, completionStart, completionEnd);
 			}
 			public void acceptInterface(char[] packageName,char[] interfaceName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
 				requestor.acceptInterface(packageName, interfaceName, completionName, modifiers, completionStart, completionEnd);
@@ -509,7 +518,7 @@
 			public void acceptLabel(char[] labelName,int completionStart,int completionEnd, int relevance){
 				requestor.acceptLabel(labelName, completionStart, completionEnd);
 			}
-			public void acceptLocalVariable(char[] name,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){
+			public void acceptLocalVariable(char[] localVarName,char[] typePackageName,char[] typeName,int modifiers,int completionStart,int completionEnd, int relevance){
 				// ignore
 			}
 			public void acceptMethod(char[] declaringTypePackageName,char[] declaringTypeName,char[] selector,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] returnTypePackageName,char[] returnTypeName,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance){
@@ -528,9 +537,10 @@
 			public void acceptType(char[] packageName,char[] typeName,char[] completionName,int completionStart,int completionEnd, int relevance){
 				requestor.acceptType(packageName, typeName, completionName, completionStart, completionEnd);
 			}
-			public void acceptVariableName(char[] typePackageName,char[] typeName,char[] name,char[] completionName,int completionStart,int completionEnd, int relevance){
+			public void acceptVariableName(char[] typePackageName,char[] typeName,char[] varName,char[] completionName,int completionStart,int completionEnd, int relevance){
 				// ignore
 			}
-		});
+		},
+		DefaultWorkingCopyOwner.PRIMARY);
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
index b042a54..f402e24 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OpenableElementInfo.java
@@ -11,7 +11,6 @@
 package org.eclipse.jdt.internal.core;
 
 /** Element info for IOpenable elements. */
-/* package */ class OpenableElementInfo extends JavaElementInfo {
-	
-
+public class OpenableElementInfo extends JavaElementInfo {
+	// root of all openable element infos
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java
index 43e7aef..7c784c4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java
@@ -10,10 +10,12 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.text.NumberFormat;
 import java.util.Enumeration;
 import java.util.Iterator;
 
 import org.eclipse.jdt.internal.core.util.LRUCache;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  *	The <code>OverflowingLRUCache</code> is an LRUCache which attempts
@@ -172,9 +174,17 @@
 		spaceNeeded = (spaceNeeded > space) ? spaceNeeded : space;
 		LRUCacheEntry entry = fEntryQueueTail;
 	
-		while (fCurrentSpace + spaceNeeded > limit && entry != null) {
-			this.privateRemoveEntry(entry, false, false);
-			entry = entry._fPrevious;
+		try {
+			// disable timestamps update while making space so that the previous and next links are not changed
+			// (by a call to get(Object) for example)
+			fTimestampsOn = false;
+			
+			while (fCurrentSpace + spaceNeeded > limit && entry != null) {
+				this.privateRemoveEntry(entry, false, false);
+				entry = entry._fPrevious;
+			}
+		} finally {
+			fTimestampsOn = true;
 		}
 	
 		/* check again, since we may have aquired enough space */
@@ -324,7 +334,7 @@
 			shrink();
 			
 		/* Check whether there's an entry in the cache */
-		int newSpace = spaceFor (key, value);
+		int newSpace = spaceFor(value);
 		LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get (key);
 		
 		if (entry != null) {
@@ -405,7 +415,7 @@
  */
 public String toString() {
 	return 
-		"OverflowingLRUCache " + this.fillingRatio() + "% full\n" + //$NON-NLS-1$ //$NON-NLS-2$
+		"OverflowingLRUCache " + NumberFormat.getInstance().format(this.fillingRatio()) + "% full\n" + //$NON-NLS-1$ //$NON-NLS-2$
 		this.toStringContents();
 }
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageDeclaration.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageDeclaration.java
index 5214c02..9b1b439 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageDeclaration.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageDeclaration.java
@@ -10,9 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IPackageDeclaration;
-import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.jdom.IDOMNode;
 
 /**
@@ -20,21 +19,39 @@
  */
 
 /* package */ class PackageDeclaration extends SourceRefElement implements IPackageDeclaration {
-protected PackageDeclaration(ICompilationUnit parent, String name) {
-	super(PACKAGE_DECLARATION, parent, name);
+protected PackageDeclaration(CompilationUnit parent, String name) {
+	super(parent, name);
+}
+public boolean equals(Object o) {
+	if (!(o instanceof PackageDeclaration)) return false;
+	return super.equals(o);
 }
 /**
  * @see JavaElement#equalsDOMNode
  */
-protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
+protected boolean equalsDOMNode(IDOMNode node) {
 	return (node.getNodeType() == IDOMNode.PACKAGE) && getElementName().equals(node.getName());
 }
 /**
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return PACKAGE_DECLARATION;
+}
+/**
  * @see JavaElement#getHandleMemento()
  */
 protected char getHandleMementoDelimiter() {
 	return JavaElement.JEM_PACKAGEDECLARATION;
 }
+/*
+ * @see JavaElement#getPrimaryElement(boolean)
+ */
+public IJavaElement getPrimaryElement(boolean checkOwner) {
+	CompilationUnit cu = (CompilationUnit)getAncestor(COMPILATION_UNIT);
+	if (checkOwner && cu.isPrimary()) return this;
+	return cu.getPackageDeclaration(this.name);
+}
 /**
  * @private Debugging purposes
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
index 8151768..b77aa49 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
@@ -10,8 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.util.*;
 import java.util.ArrayList;
 import java.util.Map;
+import java.util.StringTokenizer;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFolder;
@@ -20,55 +22,58 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * @see IPackageFragment
  */
-public class PackageFragment extends Openable implements IPackageFragment {
+public class PackageFragment extends Openable implements IPackageFragment, SuffixConstants {
 	/**
 	 * Constant empty list of class files
 	 */
-	protected static IClassFile[] fgEmptyClassFileList= new IClassFile[] {};
+	protected static final IClassFile[] NO_CLASSFILES = new IClassFile[] {};
 	/**
 	 * Constant empty list of compilation units
 	 */
-	protected static ICompilationUnit[] fgEmptyCompilationUnitList= new ICompilationUnit[] {};
+	protected static final ICompilationUnit[] NO_COMPILATION_UNITS = new ICompilationUnit[] {};
 /**
  * Constructs a handle for a package fragment
  *
  * @see IPackageFragment
  */
-protected PackageFragment(IPackageFragmentRoot root, String name) {
-	super(PACKAGE_FRAGMENT, root, name);
+protected PackageFragment(PackageFragmentRoot root, String name) {
+	super(root, name);
 }
 /**
- * Compute the children of this package fragment.
- *
- * <p>Package fragments which are folders recognize files based on the
- * type of the fragment
- * <p>Package fragments which are in a jar only recognize .class files (
- * @see JarPackageFragment).
+ * @see Openable
  */
-protected boolean computeChildren(OpenableElementInfo info, IResource resource) throws JavaModelException {
-	ArrayList vChildren = new ArrayList();
+protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
+
+	// check whether this pkg can be opened
+	if (!underlyingResource.isAccessible()) throw newNotPresentException();
+
 	int kind = getKind();
 	String extType;
 	if (kind == IPackageFragmentRoot.K_SOURCE) {
-		extType = "java"; //$NON-NLS-1$
+		extType = EXTENSION_java;
 	} else {
-		extType = "class"; //$NON-NLS-1$
+		extType = EXTENSION_class;
 	}
+
+	// add compilation units/class files from resources
+	HashSet vChildren = new HashSet();
 	try {
-		char[][] exclusionPatterns = ((PackageFragmentRoot)getPackageFragmentRoot()).fullExclusionPatternChars();
-		IResource[] members = ((IContainer) resource).members();
+		char[][] exclusionPatterns = getPackageFragmentRoot().fullExclusionPatternChars();
+		IResource[] members = ((IContainer) underlyingResource).members();
 		for (int i = 0, max = members.length; i < max; i++) {
 			IResource child = members[i];
 			if (child.getType() != IResource.FOLDER
@@ -78,7 +83,7 @@
 					if (extension.equalsIgnoreCase(extType)) {
 						IJavaElement childElement;
 						if (kind == IPackageFragmentRoot.K_SOURCE && Util.isValidCompilationUnitName(child.getName())) {
-							childElement = getCompilationUnit(child.getName());
+							childElement = new CompilationUnit(this, child.getName(), DefaultWorkingCopyOwner.PRIMARY);
 							vChildren.add(childElement);
 						} else if (Util.isValidClassFileName(child.getName())) {
 							childElement = getClassFile(child.getName());
@@ -91,6 +96,16 @@
 	} catch (CoreException e) {
 		throw new JavaModelException(e);
 	}
+	
+	if (kind == IPackageFragmentRoot.K_SOURCE) {
+		// add primary compilation units
+		ICompilationUnit[] primaryCompilationUnits = getCompilationUnits(DefaultWorkingCopyOwner.PRIMARY);
+		for (int i = 0, length = primaryCompilationUnits.length; i < length; i++) {
+			ICompilationUnit primary = primaryCompilationUnits[i];
+			vChildren.add(primary);
+		}
+	}
+	
 	IJavaElement[] children = new IJavaElement[vChildren.size()];
 	vChildren.toArray(children);
 	info.setChildren(children);
@@ -125,15 +140,15 @@
 /**
  * @see IPackageFragment
  */
-public ICompilationUnit createCompilationUnit(String name, String contents, boolean force, IProgressMonitor monitor) throws JavaModelException {
-	CreateCompilationUnitOperation op= new CreateCompilationUnitOperation(this, name, contents, force);
+public ICompilationUnit createCompilationUnit(String cuName, String contents, boolean force, IProgressMonitor monitor) throws JavaModelException {
+	CreateCompilationUnitOperation op= new CreateCompilationUnitOperation(this, cuName, contents, force);
 	runOperation(op, monitor);
-	return getCompilationUnit(name);
+	return new CompilationUnit(this, cuName, DefaultWorkingCopyOwner.PRIMARY);
 }
 /**
  * @see JavaElement
  */
-protected OpenableElementInfo createElementInfo() {
+protected Object createElementInfo() {
 	return new PackageFragmentInfo();
 }
 /**
@@ -143,18 +158,19 @@
 	IJavaElement[] elements = new IJavaElement[] {this};
 	getJavaModel().delete(elements, force, monitor);
 }
-/**
- * @see Openable
- */
-protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
-	
-	return computeChildren(info, underlyingResource);
+public boolean equals(Object o) {
+	if (!(o instanceof PackageFragment)) return false;
+	return super.equals(o);
 }
 /**
  * @see IPackageFragment#getClassFile(String)
+ * @exception IllegalArgumentExcpetion if the name does not end with ".class"
  */
-public IClassFile getClassFile(String name) {
-	return new ClassFile(this, name);
+public IClassFile getClassFile(String classFileName) {
+	if (!org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(classFileName)) {
+		throw new IllegalArgumentException(Util.bind("element.invalidClassFileName")); //$NON-NLS-1$
+	}
+	return new ClassFile(this, classFileName);
 }
 /**
  * Returns a the collection of class files in this - a folder package fragment which has a root
@@ -165,7 +181,7 @@
  */
 public IClassFile[] getClassFiles() throws JavaModelException {
 	if (getKind() == IPackageFragmentRoot.K_SOURCE) {
-		return fgEmptyClassFileList;
+		return NO_CLASSFILES;
 	}
 	
 	ArrayList list = getChildrenOfType(CLASS_FILE);
@@ -175,16 +191,20 @@
 }
 /**
  * @see IPackageFragment#getCompilationUnit(String)
+ * @exception IllegalArgumentExcpetion if the name does not end with ".java"
  */
-public ICompilationUnit getCompilationUnit(String name) {
-	return new CompilationUnit(this, name);
+public ICompilationUnit getCompilationUnit(String cuName) {
+	if (!org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(cuName)) {
+		throw new IllegalArgumentException(Util.bind("convention.unit.notJavaName")); //$NON-NLS-1$
+	}
+	return new CompilationUnit(this, cuName, DefaultWorkingCopyOwner.PRIMARY);
 }
 /**
  * @see IPackageFragment#getCompilationUnits()
  */
 public ICompilationUnit[] getCompilationUnits() throws JavaModelException {
 	if (getKind() == IPackageFragmentRoot.K_BINARY) {
-		return fgEmptyCompilationUnitList;
+		return NO_COMPILATION_UNITS;
 	}
 	
 	ArrayList list = getChildrenOfType(COMPILATION_UNIT);
@@ -193,6 +213,50 @@
 	return array;
 }
 /**
+ * @see IPackageFragment#getCompilationUnits(WorkingCopyOwner)
+ */
+public ICompilationUnit[] getCompilationUnits(WorkingCopyOwner owner) {
+	ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, false/*don't add primary*/);
+	if (workingCopies == null) return JavaModelManager.NoWorkingCopy;
+	int length = workingCopies.length;
+	ICompilationUnit[] result = new ICompilationUnit[length];
+	int index = 0;
+	for (int i = 0; i < length; i++) {
+		ICompilationUnit wc = workingCopies[i];
+		if (equals(wc.getParent())) {
+			result[index++] = wc;
+		}
+	}
+	if (index != length) {
+		System.arraycopy(result, 0, result = new ICompilationUnit[index], 0, index);
+	}
+	return result;
+}
+/**
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return PACKAGE_FRAGMENT;
+}
+/*
+ * @see JavaElement
+ */
+public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner owner) {
+	switch (token.charAt(0)) {
+		case JEM_COUNT:
+			return getHandleUpdatingCountFromMemento(memento, owner);
+		case JEM_CLASSFILE:
+			String classFileName = memento.nextToken();
+			JavaElement classFile = (JavaElement)getClassFile(classFileName);
+			return classFile.getHandleFromMemento(memento, owner);
+		case JEM_COMPILATIONUNIT:
+			String cuName = memento.nextToken();
+			JavaElement cu = new CompilationUnit(this, cuName, owner);
+			return cu.getHandleFromMemento(memento, owner);
+	}
+	return null;
+}
+/**
  * @see JavaElement#getHandleMementoDelimiter()
  */
 protected char getHandleMementoDelimiter() {
@@ -212,7 +276,7 @@
 		// We don't want to show non java resources of the default package (see PR #1G58NB8)
 		return JavaElementInfo.NO_NON_JAVA_RESOURCES;
 	} else {
-		return ((PackageFragmentInfo) getElementInfo()).getNonJavaResources(getResource(), (PackageFragmentRoot)getPackageFragmentRoot());
+		return ((PackageFragmentInfo) getElementInfo()).getNonJavaResources(getResource(), getPackageFragmentRoot());
 	}
 }
 /**
@@ -246,7 +310,7 @@
  * @see IJavaElement#getUnderlyingResource()
  */
 public IResource getUnderlyingResource() throws JavaModelException {
-	IResource rootResource = fParent.getUnderlyingResource();
+	IResource rootResource = this.parent.getUnderlyingResource();
 	if (rootResource == null) {
 		//jar package fragment root that has no associated resource
 		return null;
@@ -255,7 +319,7 @@
 	// is atually the package fragment root)
 	if (rootResource.getType() == IResource.FOLDER || rootResource.getType() == IResource.PROJECT) {
 		IContainer folder = (IContainer) rootResource;
-		String[] segs = Signature.getSimpleNames(fName);
+		String[] segs = Signature.getSimpleNames(this.name);
 		for (int i = 0; i < segs.length; ++i) {
 			IResource child = folder.findMember(segs[i]);
 			if (child == null || child.getType() != IResource.FOLDER) {
@@ -273,9 +337,9 @@
  */
 public boolean hasSubpackages() throws JavaModelException {
 	IJavaElement[] packages= ((IPackageFragmentRoot)getParent()).getChildren();
-	String name = getElementName();
-	int nameLength = name.length();
-	String packageName = isDefaultPackage() ? name : name+"."; //$NON-NLS-1$
+	String elementName = getElementName();
+	int nameLength = elementName.length();
+	String packageName = isDefaultPackage() ? elementName : elementName+"."; //$NON-NLS-1$
 	for (int i= 0; i < packages.length; i++) {
 		String otherName = packages[i].getElementName();
 		if (otherName.length() > nameLength && otherName.startsWith(packageName)) {
@@ -309,43 +373,18 @@
 	}
 	getJavaModel().move(elements, containers, siblings, renamings, force, monitor);
 }
-protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
-	if (!this.resourceExists()) throw newNotPresentException();
-	super.openWhenClosed(pm);
-}
-/**
- * Recomputes the children of this element, based on the current state
- * of the workbench.
- */
-public void refreshChildren() {
-	try {
-		OpenableElementInfo info= (OpenableElementInfo)getElementInfo();
-		computeChildren(info, getResource());
-	} catch (JavaModelException e) {
-		// do nothing.
-	}
-}
 /**
  * @see ISourceManipulation#rename(String, boolean, IProgressMonitor)
  */
-public void rename(String name, boolean force, IProgressMonitor monitor) throws JavaModelException {
-	if (name == null) {
+public void rename(String newName, boolean force, IProgressMonitor monitor) throws JavaModelException {
+	if (newName == null) {
 		throw new IllegalArgumentException(Util.bind("element.nullName")); //$NON-NLS-1$
 	}
 	IJavaElement[] elements= new IJavaElement[] {this};
 	IJavaElement[] dests= new IJavaElement[] {this.getParent()};
-	String[] renamings= new String[] {name};
+	String[] renamings= new String[] {newName};
 	getJavaModel().rename(elements, dests, renamings, force, monitor);
 }
-/*
- * @see JavaElement#rootedAt(IJavaProject)
- */
-public IJavaElement rootedAt(IJavaProject project) {
-	return
-		new PackageFragment(
-			(IPackageFragmentRoot)((JavaElement)fParent).rootedAt(project), 
-			fName);
-}
 /**
  * Debugging purposes
  */
@@ -360,7 +399,7 @@
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
 	buffer.append(this.tabString(tab));
 	if (getElementName().length() == 0) {
-		buffer.append("[default]"); //$NON-NLS-1$
+		buffer.append("<default>"); //$NON-NLS-1$
 	} else {
 		buffer.append(getElementName());
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentInfo.java
index 0add393..b3fd72e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentInfo.java
@@ -22,41 +22,41 @@
 	/**
 	 * A array with all the non-java resources contained by this PackageFragment
 	 */
-	protected Object[] fNonJavaResources;
+	protected Object[] nonJavaResources;
 
 /**
  * Create and initialize a new instance of the receiver
  */
 public PackageFragmentInfo() {
-	fNonJavaResources = null;
+	this.nonJavaResources = null;
 }
 /**
  */
 boolean containsJavaResources() {
-	return fChildren.length != 0;
+	return this.children.length != 0;
 }
 /**
  * Returns an array of non-java resources contained in the receiver.
  */
 Object[] getNonJavaResources(IResource underlyingResource, PackageFragmentRoot rootHandle) {
-	Object[] nonJavaResources = fNonJavaResources;
-	if (nonJavaResources == null) {
+	if (this.nonJavaResources == null) {
 		try {
-			nonJavaResources = 
+			this.nonJavaResources = 
 				PackageFragmentRootInfo.computeFolderNonJavaResources(
 					(JavaProject)rootHandle.getJavaProject(), 
 					(IContainer)underlyingResource, 
 					rootHandle.fullExclusionPatternChars());
 		} catch (JavaModelException e) {
+			// root doesn't exist: consider package has no nonJavaResources
+			this.nonJavaResources = NO_NON_JAVA_RESOURCES;
 		}
-		fNonJavaResources = nonJavaResources;
 	}
-	return nonJavaResources;
+	return this.nonJavaResources;
 }
 /**
- * Set the fNonJavaResources to res value
+ * Set the nonJavaResources to res value
  */
-synchronized void setNonJavaResources(Object[] resources) {
-	fNonJavaResources = resources;
+void setNonJavaResources(Object[] resources) {
+	this.nonJavaResources = resources;
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
index b083b03..d5c2c53 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.util.*;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Map;
@@ -24,6 +25,7 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * @see IPackageFragmentRoot
@@ -54,8 +56,8 @@
  * Constructs a package fragment root which is the root of the java package
  * directory hierarchy.
  */
-protected PackageFragmentRoot(IResource resource, IJavaProject project, String name) {
-	super(PACKAGE_FRAGMENT_ROOT, project, name);
+protected PackageFragmentRoot(IResource resource, JavaProject project, String name) {
+	super(project, name);
 	this.resource = resource;
 }
 
@@ -157,6 +159,20 @@
 	}
 }
 
+/**
+ * @see Openable
+ */
+protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
+	
+	// check whether this pkg fragment root can be opened
+	if (!resourceExists() || !isOnClasspath()) {
+		throw newNotPresentException();
+	}
+
+	((PackageFragmentRootInfo) info).setRootKind(determineKind(underlyingResource));
+	return computeChildren(info, newElements);
+}
+
 SourceMapper createSourceMapper(IPath sourcePath, IPath rootPath) {
 	SourceMapper mapper = new SourceMapper(
 		sourcePath, 
@@ -178,29 +194,21 @@
 }
 
 /**
- * This root is being closed.  If this root has an associated source attachment, 
- * close it too.
- *
- * @see JavaElement
- */
-//protected void closing(Object info) throws JavaModelException { TODO remove after 2.1
-//	((PackageFragmentRootInfo) info).sourceMapper = null;
-//	super.closing(info);
-//}
-/**
  * Compute the package fragment children of this package fragment root.
  * 
  * @exception JavaModelException  The resource associated with this package fragment root does not exist
  */
-protected boolean computeChildren(OpenableElementInfo info) throws JavaModelException {
+protected boolean computeChildren(OpenableElementInfo info, Map newElements) throws JavaModelException {
+	// Note the children are not opened (so not added to newElements) for a regular package fragment root
+	// Howver they are opened for a Jar package fragment root (see JarPackageFragmentRoot#computeChildren)
 	try {
 		// the underlying resource may be a folder or a project (in the case that the project folder
 		// is actually the package fragment root)
-		IResource resource = getResource();
-		if (resource.getType() == IResource.FOLDER || resource.getType() == IResource.PROJECT) {
+		IResource underlyingResource = getResource();
+		if (underlyingResource.getType() == IResource.FOLDER || underlyingResource.getType() == IResource.PROJECT) {
 			ArrayList vChildren = new ArrayList(5);
 			char[][] exclusionPatterns = fullExclusionPatternChars();
-			computeFolderChildren((IContainer) resource, "", vChildren, exclusionPatterns); //$NON-NLS-1$
+			computeFolderChildren((IContainer) underlyingResource, "", vChildren, exclusionPatterns); //$NON-NLS-1$
 			IJavaElement[] children = new IJavaElement[vChildren.size()];
 			vChildren.toArray(children);
 			info.setChildren(children);
@@ -250,26 +258,7 @@
 		throw new JavaModelException(e);
 	}
 }
-/*
- * Computes and returns the source attachment root path for the given source attachment path.
- * Returns <code>null</code> if none could be found.
- * 
- * @param sourceAttachmentPath the given absolute path to the source archive or folder
- * @return the computed source attachment root path or <code>null</cde> if none could be found
- * @throws JavaModelException
- */
-public IPath computeSourceAttachmentRootPath(IPath sourceAttachmentPath) throws JavaModelException {
-	IPath sourcePath = this.getSourceAttachmentPath();
-	if (sourcePath == null) return null;
-	SourceMapper mapper = 
-		new SourceMapper(
-		sourcePath, 
-		null, // detect root path
-		this.isExternal() ? JavaCore.getOptions() : this.getJavaProject().getOptions(true) // only project options if associated with resource
-	);
-	if (mapper.rootPath == null) return null;
-	return new Path(mapper.rootPath);
-}
+
 /*
  * @see org.eclipse.jdt.core.IPackageFragmentRoot#copy
  */
@@ -286,22 +275,20 @@
 	runOperation(op, monitor);
 }
 
-
-
 /**
  * Returns a new element info for this element.
  */
-protected OpenableElementInfo createElementInfo() {
+protected Object createElementInfo() {
 	return new PackageFragmentRootInfo();
 }
 
 /**
  * @see IPackageFragmentRoot
  */
-public IPackageFragment createPackageFragment(String name, boolean force, IProgressMonitor monitor) throws JavaModelException {
-	CreatePackageFragmentOperation op = new CreatePackageFragmentOperation(this, name, force);
+public IPackageFragment createPackageFragment(String pkgName, boolean force, IProgressMonitor monitor) throws JavaModelException {
+	CreatePackageFragmentOperation op = new CreatePackageFragmentOperation(this, pkgName, force);
 	runOperation(op, monitor);
-	return getPackageFragment(name);
+	return getPackageFragment(pkgName);
 }
 
 /**
@@ -334,17 +321,18 @@
 	if (!(o instanceof PackageFragmentRoot))
 		return false;
 	PackageFragmentRoot other = (PackageFragmentRoot) o;
-	return getJavaModel().equals(other.getJavaModel()) && 
-			this.resource.equals(other.resource) &&
-			fOccurrenceCount == other.fOccurrenceCount;
+	return this.resource.equals(other.resource) &&
+			this.occurrenceCount == other.occurrenceCount;
 }
 
 /**
  * @see IJavaElement
  */
 public boolean exists() {
-	return super.exists() 
-				&& isOnClasspath();
+	return 
+		parentExists() 
+			&& resourceExists() 
+			&& isOnClasspath();
 }
 
 public IClasspathEntry findSourceAttachmentRecommendation() {
@@ -361,7 +349,7 @@
 				Object target = JavaModel.getTarget(workspaceRoot, entry.getSourceAttachmentPath(), true);
 				if (target instanceof IFile){
 					IFile file = (IFile) target;
-					if (Util.isArchiveFileName(file.getName())){
+					if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(file.getName())){
 						return entry;
 					}
 				} else if (target instanceof IFolder) {
@@ -370,7 +358,7 @@
 				if (target instanceof java.io.File){
 					java.io.File file = (java.io.File) target;
 					if (file.isFile()) {
-						if (Util.isArchiveFileName(file.getName())){
+						if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(file.getName())){
 							return entry;
 						}
 					} else {
@@ -380,6 +368,7 @@
 				}
 			}
 		} catch(JavaModelException e){
+			// ignore
 		}
 		
 		// iterate over all projects
@@ -394,7 +383,7 @@
 					Object target = JavaModel.getTarget(workspaceRoot, entry.getSourceAttachmentPath(), true);
 					if (target instanceof IFile){
 						IFile file = (IFile) target;
-						if (Util.isArchiveFileName(file.getName())){
+						if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(file.getName())){
 							return entry;
 						}
 					} else if (target instanceof IFolder) {
@@ -403,7 +392,7 @@
 					if (target instanceof java.io.File){
 						java.io.File file = (java.io.File) target;
 						if (file.isFile()) {
-							if (Util.isArchiveFileName(file.getName())){
+							if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(file.getName())){
 								return entry;
 							}
 						} else {
@@ -413,9 +402,11 @@
 					}
 				}
 			} catch(JavaModelException e){
+				// ignore
 			}
 		}
 	} catch(JavaModelException e){
+		// ignore
 	}
 
 	return null;
@@ -424,7 +415,7 @@
 /*
  * Returns the exclusion patterns from the classpath entry associated with this root.
  */
-char[][] fullExclusionPatternChars() {
+public char[][] fullExclusionPatternChars() {
 	try {
 		if (this.isOpen() && this.getKind() != IPackageFragmentRoot.K_SOURCE) return null;
 		ClasspathEntry entry = (ClasspathEntry)getRawClasspathEntry();
@@ -437,34 +428,61 @@
 		return null;
 	}
 }		
-
 /**
- * @see Openable
+ * @see IJavaElement
  */
-protected boolean generateInfos(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException {
-	
-	((PackageFragmentRootInfo) info).setRootKind(determineKind(underlyingResource));
-	return computeChildren(info);
+public int getElementType() {
+	return PACKAGE_FRAGMENT_ROOT;
 }
-
 /**
  * @see JavaElement#getHandleMemento()
  */
 protected char getHandleMementoDelimiter() {
 	return JavaElement.JEM_PACKAGEFRAGMENTROOT;
 }
+/*
+ * @see JavaElement
+ */
+public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner owner) {
+	switch (token.charAt(0)) {
+		case JEM_COUNT:
+			return getHandleUpdatingCountFromMemento(memento, owner);
+		case JEM_PACKAGEFRAGMENT:
+			String pkgName;
+			if (memento.hasMoreTokens()) {
+				pkgName = memento.nextToken();
+				char firstChar = pkgName.charAt(0);
+				if (firstChar == JEM_CLASSFILE || firstChar == JEM_COMPILATIONUNIT || firstChar == JEM_COUNT) {
+					token = pkgName;
+					pkgName = IPackageFragment.DEFAULT_PACKAGE_NAME;
+				} else {
+					token = null;
+				}
+			} else {
+				pkgName = IPackageFragment.DEFAULT_PACKAGE_NAME;
+				token = null;
+			}
+			JavaElement pkg = (JavaElement)getPackageFragment(pkgName);
+			if (token == null) {
+				return pkg.getHandleFromMemento(memento, owner);
+			} else {
+				return pkg.getHandleFromMemento(token, memento, owner);
+			}
+	}
+	return null;
+}
 /**
  * @see JavaElement#getHandleMemento()
  */
 public String getHandleMemento(){
 	IPath path;
-	IResource resource = getResource();
-	if (resource != null) {
+	IResource underlyingResource = getResource();
+	if (underlyingResource != null) {
 		// internal jar or regular root
 		if (getResource().getProject().equals(getJavaProject().getProject())) {
-			path = resource.getProjectRelativePath();
+			path = underlyingResource.getProjectRelativePath();
 		} else {
-			path = resource.getFullPath();
+			path = underlyingResource.getFullPath();
 		}
 	} else {
 		// external jar
@@ -473,6 +491,10 @@
 	StringBuffer buff= new StringBuffer(((JavaElement)getParent()).getHandleMemento());
 	buff.append(getHandleMementoDelimiter());
 	buff.append(path.toString()); 
+	if (this.occurrenceCount > 1) {
+		buff.append(JEM_COUNT);
+		buff.append(this.occurrenceCount);
+	}
 	return buff.toString();
 }
 /**
@@ -511,19 +533,19 @@
  * Returns the package name for the given folder
  * (which is a decendent of this root).
  */
-protected String getPackageName(IFolder folder) throws JavaModelException {
+protected String getPackageName(IFolder folder) {
 	IPath myPath= getPath();
 	IPath pkgPath= folder.getFullPath();
 	int mySegmentCount= myPath.segmentCount();
 	int pkgSegmentCount= pkgPath.segmentCount();
-	StringBuffer name = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
+	StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
 	for (int i= mySegmentCount; i < pkgSegmentCount; i++) {
 		if (i > mySegmentCount) {
-			name.append('.');
+			pkgName.append('.');
 		}
-		name.append(pkgPath.segment(i));
+		pkgName.append(pkgPath.segment(i));
 	}
-	return name.toString();
+	return pkgName.toString();
 }
 
 /**
@@ -539,10 +561,9 @@
 public IClasspathEntry getRawClasspathEntry() throws JavaModelException {
 
 	IClasspathEntry rawEntry = null;
-	IJavaProject project = this.getJavaProject();
+	JavaProject project = (JavaProject)this.getJavaProject();
 	project.getResolvedClasspath(true); // force the reverse rawEntry cache to be populated
-	JavaModelManager.PerProjectInfo perProjectInfo = 
-		JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
+	JavaModelManager.PerProjectInfo perProjectInfo = project.getPerProjectInfo();
 	if (perProjectInfo != null && perProjectInfo.resolvedPathToRawEntries != null) {
 		rawEntry = (IClasspathEntry) perProjectInfo.resolvedPathToRawEntries.get(this.getPath());
 	}
@@ -615,7 +636,7 @@
  * Returns the qualified name for the source attachment property
  * of this root.
  */
-protected QualifiedName getSourceAttachmentPropertyName() throws JavaModelException {
+protected QualifiedName getSourceAttachmentPropertyName() {
 	return new QualifiedName(JavaCore.PLUGIN_ID, "sourceattachment: " + this.getPath().toOSString()); //$NON-NLS-1$
 }
 
@@ -623,6 +644,7 @@
 	try {
 		ResourcesPlugin.getWorkspace().getRoot().setPersistentProperty(this.getSourceAttachmentPropertyName(), property);
 	} catch (CoreException ce) {
+		// ignore
 	}
 }
 
@@ -726,9 +748,6 @@
  * Returns whether this package fragment root is on the classpath of its project.
  */
 protected boolean isOnClasspath() {
-	if (this.getElementType() == IJavaElement.JAVA_PROJECT){
-		return true;
-	}
 	
 	IPath path = this.getPath();
 	try {
@@ -762,46 +781,13 @@
 	runOperation(op, monitor);
 }
 
-
-protected void openWhenClosed(IProgressMonitor pm) throws JavaModelException {
-	if (!this.resourceExists() 
-			|| !this.isOnClasspath()) {
-		throw newNotPresentException();
-	}
-	super.openWhenClosed(pm);
-}
-
-/**
- * Recomputes the children of this element, based on the current state
- * of the workbench.
- */
-public void refreshChildren() {
-	try {
-		OpenableElementInfo info= (OpenableElementInfo)getElementInfo();
-		computeChildren(info);
-	} catch (JavaModelException e) {
-		// do nothing.
-	}
-}
-
-/*
- * @see JavaElement#rootedAt(IJavaProject)
- */
-public IJavaElement rootedAt(IJavaProject project) {
-	return
-		new PackageFragmentRoot(
-			getResource(),
-			project, 
-			fName);
-}
-
 /**
  * @private Debugging purposes
  */
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
 	buffer.append(this.tabString(tab));
 	if (getElementName().length() == 0) {
-		buffer.append("[project root]"); //$NON-NLS-1$
+		buffer.append("<project root>"); //$NON-NLS-1$
 	} else {
 		IPath path = getPath();
 		if (getJavaProject().getElementName().equals(path.segment(0))) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
index 5cdde47..d45bd43 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java
@@ -19,6 +19,7 @@
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * The element info for <code>PackageFragmentRoot</code>s.
@@ -74,7 +75,7 @@
 					if (Util.isValidClassFileName(fileName)) 
 						continue nextResource;
 					// ignore .zip or .jar file on classpath
-					if (Util.isArchiveFileName(fileName) && isClasspathEntry(member.getFullPath(), classpath)) 
+					if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(fileName) && isClasspathEntry(member.getFullPath(), classpath)) 
 						continue nextResource;
 					break;
 
@@ -119,6 +120,7 @@
 					handle.fullExclusionPatternChars());
 		}
 	} catch (JavaModelException e) {
+		// ignore
 	}
 	return nonJavaResources;
 }
@@ -143,7 +145,7 @@
  * Retuns the SourceMapper for this root, or <code>null</code>
  * if this root does not have attached source.
  */
-protected synchronized SourceMapper getSourceMapper() {
+protected SourceMapper getSourceMapper() {
 	return this.sourceMapper;
 }
 private static boolean isClasspathEntry(IPath path, IClasspathEntry[] resolvedClasspath) {
@@ -158,7 +160,7 @@
 /**
  * Set the fNonJavaResources to res value
  */
-synchronized void setNonJavaResources(Object[] resources) {
+void setNonJavaResources(Object[] resources) {
 	fNonJavaResources = resources;
 }
 /**
@@ -170,7 +172,7 @@
 /**
  * Sets the SourceMapper for this root.
  */
-protected synchronized void setSourceMapper(SourceMapper mapper) {
+protected void setSourceMapper(SourceMapper mapper) {
 	this.sourceMapper= mapper;
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
index 2cf66c3..9dad92f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
@@ -13,6 +13,7 @@
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Reconcile a working copy and signal the changes through a delta.
@@ -30,12 +31,12 @@
 	 * 	of the original compilation unit fails
 	 */
 	protected void executeOperation() throws JavaModelException {
-		if (fMonitor != null){
-			if (fMonitor.isCanceled()) return;
-			fMonitor.beginTask(Util.bind("element.reconciling"), 10); //$NON-NLS-1$
+		if (progressMonitor != null){
+			if (progressMonitor.isCanceled()) return;
+			progressMonitor.beginTask(Util.bind("element.reconciling"), 10); //$NON-NLS-1$
 		}
 	
-		WorkingCopy workingCopy = getWorkingCopy();
+		CompilationUnit workingCopy = getWorkingCopy();
 		boolean wasConsistent = workingCopy.isConsistent();
 		JavaElementDeltaBuilder deltaBuilder = null;
 	
@@ -45,40 +46,40 @@
 				deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
 				
 				// update the element infos with the content of the working copy
-				workingCopy.makeConsistent(fMonitor);
+				workingCopy.makeConsistent(progressMonitor);
 				deltaBuilder.buildDeltas();
 		
 			}
 	
-			if (fMonitor != null) fMonitor.worked(2);
+			if (progressMonitor != null) progressMonitor.worked(2);
 			
 			// force problem detection? - if structure was consistent
 			if (forceProblemDetection && wasConsistent){
-				if (fMonitor != null && fMonitor.isCanceled()) return;
+				if (progressMonitor != null && progressMonitor.isCanceled()) return;
 		
-				IProblemRequestor problemRequestor = workingCopy.problemRequestor;
+				IProblemRequestor problemRequestor = workingCopy.getPerWorkingCopyInfo();
 				if (problemRequestor != null && problemRequestor.isActive()){
 					problemRequestor.beginReporting();
-					CompilationUnitProblemFinder.process(workingCopy, problemRequestor, fMonitor);
+					CompilationUnitProblemFinder.process(workingCopy, problemRequestor, progressMonitor);
 					problemRequestor.endReporting();
 				}
 			}
 			
 			// register the deltas
 			if (deltaBuilder != null){
-				if ((deltaBuilder.delta != null) && (deltaBuilder.delta.getAffectedChildren().length > 0)) {
+				if (deltaBuilder.delta != null) {
 					addReconcileDelta(workingCopy, deltaBuilder.delta);
 				}
 			}
 		} finally {
-			if (fMonitor != null) fMonitor.done();
+			if (progressMonitor != null) progressMonitor.done();
 		}
 	}
 	/**
 	 * Returns the working copy this operation is working on.
 	 */
-	protected WorkingCopy getWorkingCopy() {
-		return (WorkingCopy)getElementToProcess();
+	protected CompilationUnit getWorkingCopy() {
+		return (CompilationUnit)getElementToProcess();
 	}
 	/**
 	 * @see JavaModelOperation#isReadOnly
@@ -91,8 +92,8 @@
 		if (!status.isOK()) {
 			return status;
 		}
-		WorkingCopy workingCopy = getWorkingCopy();
-		if (workingCopy.useCount == 0) {
+		CompilationUnit workingCopy = getWorkingCopy();
+		if (!workingCopy.isWorkingCopy()) {
 			return new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, workingCopy); //was destroyed
 		}
 		return status;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameElementsOperation.java
index 037ea14..eca7f3d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameElementsOperation.java
@@ -15,6 +15,7 @@
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.ISourceReference;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This operation renames elements.
@@ -56,7 +57,7 @@
 	IJavaModelStatus status = super.verify();
 	if (! status.isOK())
 		return status;
-	if (fRenamingsList == null || fRenamingsList.length == 0)
+	if (this.renamingsList == null || this.renamingsList.length == 0)
 		return new JavaModelStatus(IJavaModelStatusConstants.NULL_NAME);
 	return JavaModelStatus.VERIFIED_OK;
 }
@@ -78,6 +79,12 @@
 	if (elementType < IJavaElement.TYPE || elementType == IJavaElement.INITIALIZER)
 		error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
 		
+	Member localContext;
+	if (element instanceof Member && (localContext = ((Member)element).getOuterMostLocalContext()) != null && localContext != element) {
+		// JDOM doesn't support source manipulation in local/anonymous types
+		error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
+	}
+
 	verifyRenaming(element);
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameResourceElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameResourceElementsOperation.java
index 67c16cd..e8eab23 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameResourceElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/RenameResourceElementsOperation.java
@@ -10,10 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This operation renames resources (Package fragments and compilation units).
@@ -58,7 +58,8 @@
 		error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
 	}
 	if (elementType == IJavaElement.COMPILATION_UNIT) {
-		if (((ICompilationUnit) element).isWorkingCopy()) {
+		CompilationUnit cu = (CompilationUnit)element;
+		if (cu.isWorkingCopy() && !cu.isPrimary()) {
 			error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element);
 		}
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
index f8c8976..10001e3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironment.java
@@ -47,7 +47,7 @@
 	 */
 	public SearchableEnvironment(IJavaProject project) throws JavaModelException {
 		this.project = project;
-		this.nameLookup = (NameLookup) ((JavaProject) project).getNameLookup();
+		this.nameLookup = ((JavaProject) project).getNameLookup();
 
 		// Create search scope with visible entry on the project's classpath
 		this.searchScope = SearchEngine.createJavaSearchScope(this.project.getAllPackageFragmentRoots());
@@ -186,10 +186,13 @@
 			IProgressMonitor progressMonitor = new IProgressMonitor() {
 				boolean isCanceled = false;
 				public void beginTask(String name, int totalWork) {
+					// implements interface method
 				}
 				public void done() {
+					// implements interface method
 				}
 				public void internalWorked(double work) {
+					// implements interface method
 				}
 				public boolean isCanceled() {
 					return isCanceled;
@@ -198,10 +201,13 @@
 					isCanceled = value;
 				}
 				public void setTaskName(String name) {
+					// implements interface method
 				}
 				public void subTask(String name) {
+					// implements interface method
 				}
 				public void worked(int work) {
+					// implements interface method
 				}
 			};
 			ITypeNameRequestor nameRequestor = new ITypeNameRequestor() {
@@ -322,5 +328,6 @@
 	}
 	
 	public void cleanup() {
+		// nothing to do
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java
index 7b51898..67ec4fa 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SearchableEnvironmentRequestor.java
@@ -56,7 +56,7 @@
  * @see IJavaElementRequestor
  */
 public void acceptInitializer(IInitializer initializer) {
-
+	// implements interface method
 }
 /**
  * @see IJavaElementRequestor
@@ -77,7 +77,8 @@
 		} else {
 			fRequestor.acceptInterface(type.getPackageFragment().getElementName().toCharArray(), type.getElementName().toCharArray(), type.getFlags());
 		}
-	} catch (JavaModelException npe) {
+	} catch (JavaModelException jme) {
+		// ignore
 	}
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
index 0a6bae1..ecfe7b9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
@@ -24,43 +24,44 @@
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.codeassist.ISelectionRequestor;
 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.jdt.internal.core.util.HandleFactory;
 
 /**
  * Implementation of <code>ISelectionRequestor</code> to assist with
  * code resolve in a compilation unit. Translates names to elements.
  */
 public class SelectionRequestor implements ISelectionRequestor {
-	/**
+	/*
 	 * The name lookup facility used to resolve packages
 	 */
-	protected NameLookup fNameLookup= null;
+	protected NameLookup nameLookup;
 
-	/**
-	 * Fix for 1FVXGDK
-	 *
-	 * The compilation unit we are resolving in
+	/*
+	 * The compilation unit or class file we are resolving in
 	 */
-	protected IJavaElement fCodeResolve;
+	protected Openable openable;
 
-	/**
+	/*
 	 * The collection of resolved elements.
 	 */
-	protected IJavaElement[] fElements= fgEmptyElements;
+	protected IJavaElement[] elements = JavaElement.NO_ELEMENTS;
+	protected int elementIndex = -1;
+	
+	protected HandleFactory handleFactory = new HandleFactory();
 
-	/**
-	 * Empty collection used for efficiency.
-	 */
-	protected static IJavaElement[] fgEmptyElements = new IJavaElement[]{};
 /**
  * Creates a selection requestor that uses that given
  * name lookup facility to resolve names.
  *
  * Fix for 1FVXGDK
  */
-public SelectionRequestor(NameLookup nameLookup, IJavaElement codeResolve) {
+public SelectionRequestor(NameLookup nameLookup, Openable openable) {
 	super();
-	fNameLookup = nameLookup;
-	fCodeResolve = codeResolve;
+	this.nameLookup = nameLookup;
+	this.openable = openable;
 }
 /**
  * Resolve the binary method
@@ -86,7 +87,7 @@
 	}
 	IMethod method= type.getMethod(new String(selector), parameterTypes);
 	if (method.exists()) {
-		fElements = growAndAddToArray(fElements, method);
+		addElement(method);
 		if(SelectionEngine.DEBUG){
 			System.out.print("SELECTION - accept method("); //$NON-NLS-1$
 			System.out.print(method.toString());
@@ -101,9 +102,11 @@
 	acceptType(packageName, className, NameLookup.ACCEPT_CLASSES, needQualification);
 }
 /**
- * Do nothing.
+ * @see ISelectionRequestor#acceptError
  */
-public void acceptError(IProblem error) {}
+public void acceptError(IProblem error) {
+	// do nothing
+}
 /**
  * Resolve the field.
  */
@@ -113,7 +116,7 @@
 	if (type != null) {
 		IField field= type.getField(new String(name));
 		if (field.exists()) {
-			fElements= growAndAddToArray(fElements, field);
+			addElement(field);
 			if(SelectionEngine.DEBUG){
 				System.out.print("SELECTION - accept field("); //$NON-NLS-1$
 				System.out.print(field.toString());
@@ -128,6 +131,73 @@
 public void acceptInterface(char[] packageName, char[] interfaceName, boolean needQualification) {
 	acceptType(packageName, interfaceName, NameLookup.ACCEPT_INTERFACES, needQualification);
 }
+public void acceptLocalField(SourceTypeBinding typeBinding, char[] name, CompilationUnitDeclaration parsedUnit) {
+	IType type = (IType)this.handleFactory.createElement(typeBinding.scope.referenceContext, parsedUnit, this.openable);
+	if (type != null) {
+		IField field= type.getField(new String(name));
+		if (field.exists()) {
+			addElement(field);
+			if(SelectionEngine.DEBUG){
+				System.out.print("SELECTION - accept field("); //$NON-NLS-1$
+				System.out.print(field.toString());
+				System.out.println(")"); //$NON-NLS-1$
+			}
+		}
+	}
+}
+public void acceptLocalMethod(SourceTypeBinding typeBinding, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, boolean isConstructor, CompilationUnitDeclaration parsedUnit) {
+	IType type = (IType)this.handleFactory.createElement(typeBinding.scope.referenceContext, parsedUnit, this.openable);
+	// fix for 1FWFT6Q
+	if (type != null) {
+		if (type.isBinary()) {
+			
+			// need to add a paramater for constructor in binary type
+			IType declaringDeclaringType = type.getDeclaringType();
+			
+			boolean isStatic = false;
+			try {
+				isStatic = Flags.isStatic(type.getFlags());
+			} catch (JavaModelException e) {
+				// isStatic == false
+			}
+			
+			if(declaringDeclaringType != null && isConstructor	&& !isStatic) {
+				int length = parameterPackageNames.length;
+				System.arraycopy(parameterPackageNames, 0, parameterPackageNames = new char[length+1][], 1, length);
+				System.arraycopy(parameterTypeNames, 0, parameterTypeNames = new char[length+1][], 1, length);
+				
+				parameterPackageNames[0] = declaringDeclaringType.getPackageFragment().getElementName().toCharArray();
+				parameterTypeNames[0] = declaringDeclaringType.getTypeQualifiedName().toCharArray();
+			}
+			
+			acceptBinaryMethod(type, selector, parameterPackageNames, parameterTypeNames);
+		} else {
+			acceptSourceMethod(type, selector, parameterPackageNames, parameterTypeNames);
+		}
+	}
+}
+public void acceptLocalType(SourceTypeBinding typeBinding, CompilationUnitDeclaration parsedUnit) {
+	IJavaElement type = this.handleFactory.createElement(typeBinding.scope.referenceContext, parsedUnit, this.openable);
+	if (type != null) {
+		addElement(type);
+		if(SelectionEngine.DEBUG){
+			System.out.print("SELECTION - accept local type("); //$NON-NLS-1$
+			System.out.print(type.toString());
+			System.out.println(")"); //$NON-NLS-1$
+		}
+	}
+}
+public void acceptLocalVariable(LocalVariableBinding binding, CompilationUnitDeclaration parsedUnit) {
+	IJavaElement localVar = this.handleFactory.createElement(binding.declaration, parsedUnit, this.openable);
+	if (localVar != null) {
+		addElement(localVar);
+		if(SelectionEngine.DEBUG){
+			System.out.print("SELECTION - accept local variable("); //$NON-NLS-1$
+			System.out.print(localVar.toString());
+			System.out.println(")"); //$NON-NLS-1$
+		}
+	}
+}
 /**
  * Resolve the method
  */
@@ -167,10 +237,10 @@
  * Resolve the package
  */
 public void acceptPackage(char[] packageName) {
-	IPackageFragment[] pkgs = fNameLookup.findPackageFragments(new String(packageName), false);
+	IPackageFragment[] pkgs = this.nameLookup.findPackageFragments(new String(packageName), false);
 	if (pkgs != null) {
 		for (int i = 0, length = pkgs.length; i < length; i++) {
-			fElements = growAndAddToArray(fElements, pkgs[i]);
+			addElement(pkgs[i]);
 			if(SelectionEngine.DEBUG){
 				System.out.print("SELECTION - accept package("); //$NON-NLS-1$
 				System.out.print(pkgs[i].toString());
@@ -187,12 +257,11 @@
 protected void acceptSourceMethod(IType type, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames) {
 	String name = new String(selector);
 	IMethod[] methods = null;
-	IJavaElement[] matches = new IJavaElement[] {};
 	try {
 		methods = type.getMethods();
 		for (int i = 0; i < methods.length; i++) {
 			if (methods[i].getElementName().equals(name) && methods[i].getParameterTypes().length == parameterTypeNames.length) {
-				matches = growAndAddToArray(matches, methods[i]);
+				addElement(methods[i]);
 			}
 		}
 	} catch (JavaModelException e) {
@@ -200,9 +269,9 @@
 	}
 
 	// if no matches, nothing to report
-	if (matches.length == 0) {
+	if (this.elementIndex == -1) {
 		// no match was actually found, but a method was originally given -> default constructor
-		fElements = growAndAddToArray(fElements, type);
+		addElement(type);
 		if(SelectionEngine.DEBUG){
 			System.out.print("SELECTION - accept type("); //$NON-NLS-1$
 			System.out.print(type.toString());
@@ -212,18 +281,21 @@
 	}
 
 	// if there is only one match, we've got it
-	if (matches.length == 1) {
-		fElements = growAndAddToArray(fElements, matches[0]);
+	if (this.elementIndex == 0) {
 		if(SelectionEngine.DEBUG){
 			System.out.print("SELECTION - accept method("); //$NON-NLS-1$
-			System.out.print(matches[0].toString());
+			System.out.print(this.elements[0].toString());
 			System.out.println(")"); //$NON-NLS-1$
 		}
 		return;
 	}
 
 	// more than one match - must match simple parameter types
-	for (int i = 0; i < matches.length; i++) {
+	IJavaElement[] matches = this.elements;
+	int matchesIndex = this.elementIndex;
+	this.elements = JavaElement.NO_ELEMENTS;
+	this.elementIndex = -1;
+	for (int i = 0; i <= matchesIndex; i++) {
 		IMethod method= (IMethod)matches[i];
 		String[] signatures = method.getParameterTypes();
 		boolean match= true;
@@ -236,7 +308,7 @@
 			}
 		}
 		if (match) {
-			fElements = growAndAddToArray(fElements, method);
+			addElement(method);
 			if(SelectionEngine.DEBUG){
 				System.out.print("SELECTION - accept method("); //$NON-NLS-1$
 				System.out.print(method.toString());
@@ -252,7 +324,7 @@
 protected void acceptType(char[] packageName, char[] typeName, int acceptFlags, boolean needQualification) {
 	IType type= resolveType(packageName, typeName, acceptFlags);
 	if (type != null) {
-		fElements= growAndAddToArray(fElements, type);
+		addElement(type);
 		if(SelectionEngine.DEBUG){
 			System.out.print("SELECTION - accept type("); //$NON-NLS-1$
 			System.out.print(type.toString());
@@ -261,22 +333,25 @@
 	} 
 	
 }
+/*
+ * Adds the given element to the list of resolved elements.
+ */
+protected void addElement(IJavaElement element) {
+	int elementLength = this.elementIndex + 1;
+	if (elementLength == this.elements.length) {
+		System.arraycopy(this.elements, 0, this.elements = new IJavaElement[(elementLength*2) + 1], 0, elementLength);
+	}
+	this.elements[++this.elementIndex] = element;
+}
 /**
  * Returns the resolved elements.
  */
 public IJavaElement[] getElements() {
-	return fElements;
-}
-/**
- * Adds the new element to a new array that contains all of the elements of the old array.
- * Returns the new array.
- */
-protected IJavaElement[] growAndAddToArray(IJavaElement[] array, IJavaElement addition) {
-	IJavaElement[] old = array;
-	array = new IJavaElement[old.length + 1];
-	System.arraycopy(old, 0, array, 0, old.length);
-	array[old.length] = addition;
-	return array;
+	int elementLength = this.elementIndex + 1;
+	if (this.elements.length != elementLength) {
+		System.arraycopy(this.elements, 0, this.elements = new IJavaElement[elementLength], 0, elementLength);
+	}
+	return this.elements;
 }
 /**
  * Resolve the type
@@ -285,8 +360,8 @@
 
 	IType type= null;
 	
-	if (fCodeResolve instanceof WorkingCopy) {
-		WorkingCopy wc = (WorkingCopy) fCodeResolve;
+	if (this.openable instanceof CompilationUnit && ((CompilationUnit)this.openable).isWorkingCopy()) {
+		CompilationUnit wc = (CompilationUnit) this.openable;
 		try {
 			if(((packageName == null || packageName.length == 0) && wc.getPackageDeclarations().length == 0) ||
 				(!(packageName == null || packageName.length == 0) && wc.getPackageDeclaration(new String(packageName)).exists())) {
@@ -309,12 +384,12 @@
 	}
 
 	if(type == null) {
-		IPackageFragment[] pkgs = fNameLookup.findPackageFragments(
+		IPackageFragment[] pkgs = this.nameLookup.findPackageFragments(
 			(packageName == null || packageName.length == 0) ? IPackageFragment.DEFAULT_PACKAGE_NAME : new String(packageName), 
 			false);
 		// iterate type lookup in each package fragment
 		for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) {
-			type= fNameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags);
+			type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags);
 			if (type != null) break;	
 		}
 		if (type == null) {
@@ -322,13 +397,13 @@
 			if (packageName != null) {
 				pName = new String(packageName);
 			}
-			if (fCodeResolve != null && fCodeResolve.getParent().getElementName().equals(pName)) {
+			if (this.openable != null && this.openable.getParent().getElementName().equals(pName)) {
 				// look inside the type in which we are resolving in
 				String tName= new String(typeName);
 				tName = tName.replace('.','$');
 				IType[] allTypes= null;
 				try {
-					ArrayList list = ((JavaElement)fCodeResolve).getChildrenOfType(IJavaElement.TYPE);
+					ArrayList list = this.openable.getChildrenOfType(IJavaElement.TYPE);
 					allTypes = new IType[list.size()];
 					list.toArray(allTypes);
 				} catch (JavaModelException e) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
index 4a0e38a..b3845ec 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
@@ -34,11 +34,11 @@
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.JavaConventions;
 import org.eclipse.jdt.core.JavaModelException;
 
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This operation sets an <code>IJavaProject</code>'s classpath.
@@ -49,12 +49,14 @@
 
 	IClasspathEntry[] oldResolvedPath, newResolvedPath;
 	IClasspathEntry[] newRawPath;
-	boolean canChangeResource;
+	boolean canChangeResources;
 	boolean needCycleCheck;
 	boolean needValidation;
 	boolean needSave;
 	IPath newOutputLocation;
-	
+	JavaProject project;
+	boolean identicalRoots;
+
 	public static final IClasspathEntry[] ReuseClasspath = new IClasspathEntry[0];
 	public static final IClasspathEntry[] UpdateClasspath = new IClasspathEntry[0];
 	// if reusing output location, then also reuse clean flag
@@ -64,7 +66,7 @@
 	 * When executed, this operation sets the classpath of the given project.
 	 */
 	public SetClasspathOperation(
-		IJavaProject project,
+		JavaProject project,
 		IClasspathEntry[] oldResolvedPath,
 		IClasspathEntry[] newRawPath,
 		IPath newOutputLocation,
@@ -76,9 +78,10 @@
 		this.oldResolvedPath = oldResolvedPath;
 		this.newRawPath = newRawPath;
 		this.newOutputLocation = newOutputLocation;
-		this.canChangeResource = canChangeResource;
+		this.canChangeResources = canChangeResource;
 		this.needValidation = needValidation;
 		this.needSave = needSave;
+		this.project = project;
 	}
 
 	/**
@@ -99,6 +102,7 @@
 				try {
 					root.close();
 				} catch (JavaModelException e) {
+					// ignore
 				}
 				// force detach source on jar package fragment roots (source will be lazily computed when needed)
 				((PackageFragmentRoot) root).setSourceAttachmentProperty(null);// loose info - will be recomputed
@@ -180,7 +184,6 @@
 	 */
 	protected ArrayList determineAffectedPackageFragments(IPath location) throws JavaModelException {
 		ArrayList fragments = new ArrayList();
-		JavaProject project =getProject();
 	
 		// see if this will cause any package fragments to be affected
 		IWorkspace workspace = ResourcesPlugin.getWorkspace();
@@ -237,12 +240,11 @@
 		JavaModelException originalException = null;
 
 		try {
-			JavaProject project = getProject();
 			if (this.newRawPath == UpdateClasspath) this.newRawPath = project.getRawClasspath();
 			if (this.newRawPath != ReuseClasspath){
 				updateClasspath();
 				project.updatePackageFragmentRoots();
-				JavaModelManager.getJavaModelManager().deltaProcessor.addForRefresh(project);
+				JavaModelManager.getJavaModelManager().getDeltaProcessor().addForRefresh(project);
 			}
 
 		} catch(JavaModelException e){
@@ -257,6 +259,18 @@
 			} catch(JavaModelException e){
 				if (originalException != null) throw originalException; 
 				throw e;
+			} finally {
+				// ensures the project is getting rebuilt if only variable is modified
+				if (!this.identicalRoots && this.canChangeResources) {
+					try {
+						this.project.getProject().touch(this.progressMonitor);
+					} catch (CoreException e) {
+						if (JavaModelManager.CP_RESOLVE_VERBOSE){
+							System.out.println("CPInit - FAILED to touch project: "+ this.project.getElementName()); //$NON-NLS-1$
+							e.printStackTrace();
+						}
+					}
+				}				
 			}
 		}
 		done();
@@ -267,11 +281,8 @@
 	 * Use three deltas in case the same root is removed/added/reordered (for
 	 * instance, if it is changed from K_SOURCE to K_BINARY or vice versa)
 	 */
-	protected void generateClasspathChangeDeltas(
-		IClasspathEntry[] oldResolvedPath,
-		IClasspathEntry[] newResolvedPath,
-		final JavaProject project) {
-	
+	protected void generateClasspathChangeDeltas() {
+
 		JavaModelManager manager = JavaModelManager.getJavaModelManager();
 		boolean needToUpdateDependents = false;
 		JavaElementDelta delta = new JavaElementDelta(getJavaModel());
@@ -286,10 +297,11 @@
 			try {
 				roots = project.getPackageFragmentRoots();
 			} catch (JavaModelException e) {
+				// ignore
 			}
 		} else {
 			Map allRemovedRoots ;
-			if ((allRemovedRoots = manager.deltaProcessor.removedRoots) != null) {
+			if ((allRemovedRoots = manager.getDeltaProcessor().removedRoots) != null) {
 		 		roots = (IPackageFragmentRoot[]) allRemovedRoots.get(project);
 			}
 		}
@@ -310,7 +322,7 @@
 					this.needCycleCheck = true;
 					continue; 
 				}
-	
+
 				IPackageFragmentRoot[] pkgFragmentRoots = null;
 				if (oldRoots != null) {
 					IPackageFragmentRoot oldRoot = (IPackageFragmentRoot)  oldRoots.get(oldResolvedPath[i].getPath());
@@ -340,7 +352,7 @@
 				
 				int changeKind = oldResolvedPath[i].getEntryKind();
 				needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE) || oldResolvedPath[i].isExported();
-	
+
 				// Remove the .java files from the index for a source folder
 				// For a lib folder or a .jar file, remove the corresponding index if not shared.
 				if (indexManager != null) {
@@ -353,23 +365,23 @@
 								public String getID() {
 									return path.toString();
 								}
-								public void run() throws JavaModelException {
+								public void run() /* throws JavaModelException */ {
 									indexManager.removeSourceFolderFromIndex(project, path, exclusionPatterns);
 								}
 							}, 
 							REMOVEALL_APPEND);
 							break;
 						case IClasspathEntry.CPE_LIBRARY:
-							final DeltaProcessor deltaProcessor = manager.deltaProcessor;
+							final DeltaProcessingState deltaState = manager.deltaState;
 							postAction(new IPostAction() {
 								public String getID() {
 									return path.toString();
 								}
-								public void run() throws JavaModelException {
-									if (deltaProcessor.otherRoots.get(path) == null) { // if root was not shared
+								public void run() /* throws JavaModelException */ {
+									if (deltaState.otherRoots.get(path) == null) { // if root was not shared
 										indexManager.discardJobs(path.toString());
 										indexManager.removeIndex(path);
-										// TODO: we could just remove the in-memory index and have the indexing check for timestamps
+										// TODO (kent) we could just remove the in-memory index and have the indexing check for timestamps
 									}
 								}
 							}, 
@@ -378,7 +390,7 @@
 					}		
 				}
 				hasDelta = true;
-	
+
 			} else {
 				// do not notify remote project changes
 				if (oldResolvedPath[i].getEntryKind() == IClasspathEntry.CPE_PROJECT){
@@ -402,26 +414,36 @@
 				int sourceAttachmentFlags = 
 					this.getSourceAttachmentDeltaFlag(
 						oldResolvedPath[i].getSourceAttachmentPath(),
-						newSourcePath,
-						null/*not a source root path*/);
-				int sourceAttachmentRootFlags = 
-					this.getSourceAttachmentDeltaFlag(
-						oldResolvedPath[i].getSourceAttachmentRootPath(),
-						newResolvedPath[index].getSourceAttachmentRootPath(),
-						newSourcePath/*in case both root paths are null*/);
+						newSourcePath);
+				IPath oldRootPath = oldResolvedPath[i].getSourceAttachmentRootPath();
+				IPath newRootPath = newResolvedPath[index].getSourceAttachmentRootPath();
+				int sourceAttachmentRootFlags = getSourceAttachmentDeltaFlag(oldRootPath, newRootPath);
 				int flags = sourceAttachmentFlags | sourceAttachmentRootFlags;
 				if (flags != 0) {
-					addClasspathDeltas(
-						project.computePackageFragmentRoots(oldResolvedPath[i]),
-						flags,
-						delta);
+					addClasspathDeltas(project.computePackageFragmentRoots(oldResolvedPath[i]), flags, delta);
 					hasDelta = true;
+				} else {
+					if (oldRootPath == null && newRootPath == null) {
+						// if source path is specified and no root path, it needs to be recomputed dynamically
+						// force detach source on jar package fragment roots (source will be lazily computed when needed)
+						IPackageFragmentRoot[] computedRoots = project.computePackageFragmentRoots(oldResolvedPath[i]);
+						for (int j = 0; j < computedRoots.length; j++) {
+							IPackageFragmentRoot root = computedRoots[j];
+							// force detach source on jar package fragment roots (source will be lazily computed when needed)
+							try {
+								root.close();
+							} catch (JavaModelException e) {
+								// ignore
+							}
+							((PackageFragmentRoot) root).setSourceAttachmentProperty(null);// loose info - will be recomputed
+						}
+					}
 				}
 			}
 		}
-	
+
 		for (int i = 0; i < newLength; i++) {
-	
+
 			int index = classpathContains(oldResolvedPath, newResolvedPath[i]);
 			if (index == -1) {
 				// do not notify remote project changes
@@ -454,7 +476,7 @@
 									public String getID() {
 										return newPath.toString();
 									}
-									public void run() throws JavaModelException {
+									public void run() /* throws JavaModelException */ {
 										indexManager.indexLibrary(newPath, project.getProject());
 									}
 								}, 
@@ -469,7 +491,7 @@
 								public String getID() {
 									return path.toString();
 								}
-								public void run() throws JavaModelException {
+								public void run() /* throws JavaModelException */ {
 									indexManager.indexSourceFolder(project, path, exclusionPatterns);
 								}
 							}, 
@@ -480,38 +502,31 @@
 				
 				needToUpdateDependents |= (changeKind == IClasspathEntry.CPE_SOURCE) || newResolvedPath[i].isExported();
 				hasDelta = true;
-	
+
 			} // classpath reordering has already been generated in previous loop
 		}
-	
+
 		if (hasDelta) {
 			this.addDelta(delta);
+		} else {
+			this.identicalRoots = true;
 		}
 		if (needToUpdateDependents){
 			updateAffectedProjects(project.getProject().getFullPath());
 		}
 	}
 
-	protected JavaProject getProject() {
-		return ((JavaProject) getElementsToProcess()[0]);
-	}
-
 	/*
 	 * Returns the source attachment flag for the delta between the 2 give source paths.
 	 * Returns either F_SOURCEATTACHED, F_SOURCEDETACHED, F_SOURCEATTACHED | F_SOURCEDETACHED
 	 * or 0 if there is no difference.
 	 */
-	private int getSourceAttachmentDeltaFlag(IPath oldPath, IPath newPath, IPath sourcePath) {
+	private int getSourceAttachmentDeltaFlag(IPath oldPath, IPath newPath) {
 		if (oldPath == null) {
 			if (newPath != null) {
 				return IJavaElementDelta.F_SOURCEATTACHED;
 			} else {
-				if (sourcePath != null) {
-					// if source path is specified and no root path, it needs to be recomputed dynamically
-					return IJavaElementDelta.F_SOURCEATTACHED | IJavaElementDelta.F_SOURCEDETACHED;
-				} else {
-					return 0;
-				}
+				return 0;
 			}
 		} else if (newPath == null) {
 			return IJavaElementDelta.F_SOURCEDETACHED;
@@ -527,15 +542,14 @@
 	 * otherwise <code>false</code>. Subclasses must override.
 	 */
 	public boolean isReadOnly() {
-		return !this.canChangeResource;
+		return !this.canChangeResources;
 	}
 
 	protected void saveClasspathIfNecessary() throws JavaModelException {
 		
-		if (!this.canChangeResource || !this.needSave) return;
+		if (!this.canChangeResources || !this.needSave) return;
 				
 		IClasspathEntry[] classpathForSave;
-		JavaProject project = getProject();
 		if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath){
 			classpathForSave = project.getRawClasspath();
 		} else {
@@ -578,69 +592,78 @@
 
 	private void updateClasspath() throws JavaModelException {
 
-		JavaProject project = ((JavaProject) getElementsToProcess()[0]);
-
 		beginTask(Util.bind("classpath.settingProgress", project.getElementName()), 2); //$NON-NLS-1$
 
 		// SIDE-EFFECT: from thereon, the classpath got modified
-		project.setRawClasspath0(this.newRawPath);
+		project.getPerProjectInfo().updateClasspathInformation(this.newRawPath);
 
 		// resolve new path (asking for marker creation if problems)
 		if (this.newResolvedPath == null) {
-			this.newResolvedPath = project.getResolvedClasspath(true, this.canChangeResource);
+			this.newResolvedPath = project.getResolvedClasspath(true, this.canChangeResources);
 		}
 		
 		if (this.oldResolvedPath != null) {
-			generateClasspathChangeDeltas(
-				this.oldResolvedPath,
-				this.newResolvedPath,
-				project);
+			generateClasspathChangeDeltas();
 		} else {
 			this.needCycleCheck = true;
 			updateAffectedProjects(project.getProject().getFullPath());
 		}
 		
-		updateCycleMarkersIfNecessary(newResolvedPath);
+		updateCycleMarkersIfNecessary();
 	}
 
 	/**
 	 * Update projects which are affected by this classpath change:
-	 * those which refers to the current project as source
+	 * those which refers to the current project as source (indirectly)
 	 */
 	protected void updateAffectedProjects(IPath prerequisiteProjectPath) {
 
+		// remove all update classpath post actions for this project
+		removeAllPostAction(prerequisiteProjectPath.toString());
+		
 		try {
 			IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
-			IJavaProject originatingProject = getProject();
+			IJavaProject initialProject = this.project;
 			IJavaProject[] projects = model.getJavaProjects();
 			for (int i = 0, projectCount = projects.length; i < projectCount; i++) {
 				try {
-					JavaProject project = (JavaProject) projects[i];
-					if (project.equals(originatingProject)) continue; // skip itself
+					final JavaProject affectedProject = (JavaProject) projects[i];
+					if (affectedProject.equals(initialProject)) continue; // skip itself
 					
 					// consider ALL dependents (even indirect ones), since they may need to
 					// flush their respective namelookup caches (all pkg fragment roots).
 
-					IClasspathEntry[] classpath = project.getExpandedClasspath(true);
+					IClasspathEntry[] classpath = affectedProject.getExpandedClasspath(true);
 					for (int j = 0, entryCount = classpath.length; j < entryCount; j++) {
 						IClasspathEntry entry = classpath[j];
 						if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT
 							&& entry.getPath().equals(prerequisiteProjectPath)) {
-							project.setRawClasspath(
-								UpdateClasspath, 
-								SetClasspathOperation.ReuseOutputLocation, 
-								this.fMonitor, 
-								this.canChangeResource,  
-								project.getResolvedClasspath(true), 
-								false, // updating only - no validation
-								false); // updating only - no need to save
+								
+							postAction(new IPostAction() {
+									public String getID() {
+										return affectedProject.getPath().toString();
+									}
+									public void run() throws JavaModelException {
+										affectedProject.setRawClasspath(
+											UpdateClasspath, 
+											SetClasspathOperation.ReuseOutputLocation, 
+											SetClasspathOperation.this.progressMonitor, 
+											SetClasspathOperation.this.canChangeResources,  
+											affectedProject.getResolvedClasspath(true), 
+											false, // updating only - no validation
+											false); // updating only - no need to save
+									}
+								},
+								REMOVEALL_APPEND);
 							break;
 						}
 					}
 				} catch (JavaModelException e) {
+					// ignore
 				}
 			}
 		} catch (JavaModelException e) {
+			// ignore
 		}
 		
 	}
@@ -648,29 +671,25 @@
 	/**
 	 * Update cycle markers
 	 */
-	protected void updateCycleMarkersIfNecessary(IClasspathEntry[] newResolvedPath) {
+	protected void updateCycleMarkersIfNecessary() {
 
 		if (!this.needCycleCheck) return;
-		if (!this.canChangeResource) return;
+		if (!this.canChangeResources) return;
 		 
-		try {
-			JavaProject project = getProject();
-			if (!project.hasCycleMarker() && !project.hasClasspathCycle(project.getResolvedClasspath(true))){
-				return;
-			}
-		
-			postAction(
-				new IPostAction() {
-					public String getID() {
-						return "updateCycleMarkers";  //$NON-NLS-1$
-					}
-					public void run() throws JavaModelException {
-						JavaProject.updateAllCycleMarkers();
-					}
-				},
-				REMOVEALL_APPEND);
-		} catch(JavaModelException e){
+		if (!project.hasCycleMarker() && !project.hasClasspathCycle(newResolvedPath)){
+			return;
 		}
+	
+		postAction(
+			new IPostAction() {
+				public String getID() {
+					return "updateCycleMarkers";  //$NON-NLS-1$
+				}
+				public void run() throws JavaModelException {
+					JavaProject.updateAllCycleMarkers(null);
+				}
+			},
+			REMOVEALL_APPEND);
 	}
 
 	/**
@@ -681,8 +700,6 @@
 	 */
 	protected void updateOutputLocation() throws JavaModelException {
 		
-		JavaProject project= ((JavaProject) getElementsToProcess()[0]);
-
 		beginTask(Util.bind("classpath.settingOutputLocationProgress", project.getElementName()), 2); //$NON-NLS-1$
 		
 		IPath oldLocation= project.getOutputLocation();
@@ -713,7 +730,7 @@
 			}
 		}
 
-		JavaModelManager.PerProjectInfo perProjectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(project.getProject());
+		JavaModelManager.PerProjectInfo perProjectInfo = project.getPerProjectInfo();
 		synchronized (perProjectInfo) {
 			perProjectInfo.outputLocation = this.newOutputLocation;
 		}
@@ -729,20 +746,19 @@
 	 */
 	protected void updateProjectReferencesIfNecessary() throws JavaModelException {
 		
-		if (!this.canChangeResource) return;
+		if (!this.canChangeResources) return;
 		if (this.newRawPath == ReuseClasspath || this.newRawPath == UpdateClasspath) return;
 	
-		JavaProject jproject = getProject();
-		String[] oldRequired = jproject.projectPrerequisites(this.oldResolvedPath);
+		String[] oldRequired = this.project.projectPrerequisites(this.oldResolvedPath);
 
 		if (this.newResolvedPath == null) {
-			this.newResolvedPath = jproject.getResolvedClasspath(this.newRawPath, null, true, this.needValidation, null /*no reverse map*/);
+			this.newResolvedPath = this.project.getResolvedClasspath(this.newRawPath, null, true, true, null/*no reverse map*/);
 		}
-		String[] newRequired = jproject.projectPrerequisites(this.newResolvedPath);
+		String[] newRequired = this.project.projectPrerequisites(this.newResolvedPath);
 	
 		try {		
-			IProject project = jproject.getProject();
-			IProjectDescription description = project.getDescription();
+			IProject projectResource = this.project.getProject();
+			IProjectDescription description = projectResource.getDescription();
 			 
 			IProject[] projectReferences = description.getReferencedProjects();
 			
@@ -785,13 +801,13 @@
 			Util.sort(requiredProjectNames); // ensure that if changed, the order is consistent
 			
 			IProject[] requiredProjectArray = new IProject[newSize];
-			IWorkspaceRoot wksRoot = project.getWorkspace().getRoot();
+			IWorkspaceRoot wksRoot = projectResource.getWorkspace().getRoot();
 			for (int i = 0; i < newSize; i++){
 				requiredProjectArray[i] = wksRoot.getProject(requiredProjectNames[i]);
 			}
 	
 			description.setReferencedProjects(requiredProjectArray);
-			project.setDescription(description, this.fMonitor);
+			projectResource.setDescription(description, this.progressMonitor);
 	
 		} catch(CoreException e){
 			throw new JavaModelException(e);
@@ -806,7 +822,6 @@
 		}
 
 		if (needValidation) {
-			IJavaProject project = (IJavaProject) getElementToProcess();
 			// retrieve classpath 
 			IClasspathEntry[] entries = this.newRawPath;
 			if (entries == ReuseClasspath){
@@ -827,7 +842,7 @@
 			}
 					
 			// perform validation
-			return JavaConventions.validateClasspath(
+			return ClasspathEntry.validateClasspath(
 				project,
 				entries,
 				outputLocation);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SimpleDelta.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SimpleDelta.java
new file mode 100644
index 0000000..522589c
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SimpleDelta.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.IJavaElementDelta;
+
+/**
+ * A simple Java element delta that remembers the kind of changes only.
+ */
+public class SimpleDelta {
+
+	/*
+	 * @see IJavaElementDelta#getKind()
+	 */
+	protected int kind = 0;
+	
+	/*
+	 * @see IJavaElementDelta#getFlags()
+	 */
+	protected int changeFlags = 0;
+	
+	/*
+	 * Marks this delta as added
+	 */
+	public void added() {
+		this.kind = IJavaElementDelta.ADDED;
+	}
+	
+	/*
+	 * Marks this delta as changed with the given change flag
+	 */
+	public void changed(int flags) {
+		this.kind = IJavaElementDelta.CHANGED;
+		this.changeFlags |= flags;
+	}
+	
+	/*
+	 * @see IJavaElementDelta#getFlags()
+	 */
+	public int getFlags() {
+		return this.changeFlags;
+	}
+	
+	/*
+	 * @see IJavaElementDelta#getKind()
+	 */
+	public int getKind() {
+		return this.kind;
+	}
+
+	/*
+	 * Mark this delta has a having a modifiers change
+	 */
+	public void modifiers() {
+		changed(IJavaElementDelta.F_MODIFIERS);
+	}
+
+	/*
+	 * Marks this delta as removed
+	 */
+	public void removed() {
+		this.kind = IJavaElementDelta.REMOVED;
+		this.changeFlags = 0;
+	}
+	
+	/*
+	 * Mark this delta has a having a super type change
+	 */
+	public void superTypes() {
+		changed(IJavaElementDelta.F_SUPER_TYPES);
+	}
+
+	protected void toDebugString(StringBuffer buffer) {
+		buffer.append("["); //$NON-NLS-1$
+		switch (getKind()) {
+			case IJavaElementDelta.ADDED :
+				buffer.append('+');
+				break;
+			case IJavaElementDelta.REMOVED :
+				buffer.append('-');
+				break;
+			case IJavaElementDelta.CHANGED :
+				buffer.append('*');
+				break;
+			default :
+				buffer.append('?');
+				break;
+		}
+		buffer.append("]: {"); //$NON-NLS-1$
+		toDebugString(buffer, getFlags());
+		buffer.append("}"); //$NON-NLS-1$
+	}
+
+	protected boolean toDebugString(StringBuffer buffer, int flags) {
+		boolean prev = false;
+		if ((flags & IJavaElementDelta.F_MODIFIERS) != 0) {
+			if (prev)
+				buffer.append(" | "); //$NON-NLS-1$
+			buffer.append("MODIFIERS CHANGED"); //$NON-NLS-1$
+			prev = true;
+		}
+		if ((flags & IJavaElementDelta.F_SUPER_TYPES) != 0) {
+			if (prev)
+				buffer.append(" | "); //$NON-NLS-1$
+			buffer.append("SUPER TYPES CHANGED"); //$NON-NLS-1$
+			prev = true;
+		}
+		return prev;
+	}
+
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		toDebugString(buffer);
+		return buffer.toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java
index dc3fd9f..1908d03 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SingleTypeRequestor.java
@@ -29,11 +29,13 @@
  * @see IJavaElementRequestor
  */
 public void acceptField(IField field) {
+	// implements interface method
 }
 /**
  * @see IJavaElementRequestor
  */
 public void acceptInitializer(IInitializer initializer) {
+	// implements interface method
 }
 /**
  * @see IJavaElementRequestor
@@ -45,11 +47,13 @@
  * @see IJavaElementRequestor
  */
 public void acceptMethod(IMethod method) {
+	// implements interface method
 }
 /**
  * @see IJavaElementRequestor
  */
 public void acceptPackageFragment(IPackageFragment packageFragment) {
+	// implements interface method
 }
 /**
  * @see IJavaElementRequestor
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementBuilder.java
index 10d6406..92f17b3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementBuilder.java
@@ -27,6 +27,9 @@
 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
 import org.eclipse.jdt.core.util.CompilationUnitSorter;
 import org.eclipse.jdt.internal.compiler.SourceElementRequestorAdapter;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
 
@@ -40,20 +43,20 @@
 		SortElement(int sourceStart, int modifiers) {
 			super(SortElementBuilder.this);
 			this.sourceStart = normalizeSourceStart(sourceStart);
-			modifiers &= ~org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers.AccInterface; // remove AccInterface flags
-			modifiers &= org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers.AccJustFlag;
+			modifiers &= ~IConstants.AccInterface; // remove AccInterface flags
+			modifiers &= CompilerModifiers.AccJustFlag;
 			this.modifiers = modifiers;
 			this.children_count = 0;
 		}
 
 		protected void setParameters(MethodDeclaration methodDeclaration, String[] parameterNames, String[] parameterTypes) {
 			for (int i = 0, max = parameterNames.length; i < max; i++) {
-				String type = parameterTypes[i];
+				String paramType = parameterTypes[i];
 				SingleVariableDeclaration singleVariableDeclaration = ast.newSingleVariableDeclaration();
 				singleVariableDeclaration.setName(ast.newSimpleName(parameterNames[i]));
 				int indexOfArrayBrace;
-				if (type.indexOf('.') != -1) {
-					String[] typeParts = splitOn('.', type);
+				if (paramType.indexOf('.') != -1) {
+					String[] typeParts = splitOn('.', paramType);
 					int length = typeParts.length;
 					indexOfArrayBrace = typeParts[length - 1].indexOf('[');
 					if (indexOfArrayBrace != -1) {
@@ -61,7 +64,7 @@
 						typeParts[length - 1] = typeParts[length - 1].substring(0, indexOfArrayBrace);
 						String[] typeSubstrings = new String[length];
 						for (int j = 0; j < length; j++) {
-							typeSubstrings[j] = new String(typeParts[j]);
+							typeSubstrings[j] = typeParts[j];
 						}
 						singleVariableDeclaration.setType(ast.newArrayType(ast.newSimpleType(ast.newName(typeSubstrings)), dimensions));
 					} else {
@@ -71,12 +74,12 @@
 						}
 						singleVariableDeclaration.setType(ast.newSimpleType(ast.newName(typeSubstrings)));
 					}
-				} else if ((indexOfArrayBrace = type.indexOf('[')) != -1) {
-					int dimensions = occurencesOf('[', type);
-					type = type.substring(0, indexOfArrayBrace);
-					singleVariableDeclaration.setType(ast.newArrayType(newType(type), dimensions));
+				} else if ((indexOfArrayBrace = paramType.indexOf('[')) != -1) {
+					int dimensions = occurencesOf('[', paramType);
+					paramType = paramType.substring(0, indexOfArrayBrace);
+					singleVariableDeclaration.setType(ast.newArrayType(newType(paramType), dimensions));
 				} else {
-					singleVariableDeclaration.setType(newType(type));
+					singleVariableDeclaration.setType(newType(paramType));
 				}
 				methodDeclaration.parameters().add(singleVariableDeclaration);
 			}
@@ -112,10 +115,10 @@
 			return count;
 		}
 		
-		protected Type newType(String type) {
+		protected Type newType(String typeSource) {
 			// check if type is a primitive type
-			scanner.setSource(type.toCharArray());
-			scanner.resetTo(0, type.length());
+			scanner.setSource(typeSource.toCharArray());
+			scanner.resetTo(0, typeSource.length());
 			int token = 0;
 			try {
 				token = scanner.getNextToken();
@@ -123,7 +126,7 @@
 				return null;
 			}
 			if (token == TerminalTokens.TokenNameIdentifier) {
-				return ast.newSimpleType(ast.newSimpleName(new String(type)));
+				return ast.newSimpleType(ast.newSimpleName(typeSource));
 			} else {
 				switch(token) {
 					case TerminalTokens.TokenNameint :
@@ -250,7 +253,9 @@
 		SortMethodDeclaration(int sourceStart, int modifiers, char[] name, char[][] parametersNames, char[][] parametersTypes, char[][] thrownExceptions, char[] returnType) {			
 			super(sourceStart, modifiers, name, parametersNames, parametersTypes, thrownExceptions);
 			this.id = METHOD;
-			this.returnType = new String(returnType);
+			if (returnType != null) {
+				this.returnType = new String(returnType);
+			}
 		}
 		
 		void display(StringBuffer buffer, int tab) {
@@ -258,15 +263,19 @@
 				.append(tab(tab))
 				.append("method ") //$NON-NLS-1$
 				.append(name)
-				.append(decodeSignature())
-				.append(" " + returnType + LINE_SEPARATOR); //$NON-NLS-1$
+				.append(decodeSignature());
+			if (returnType != null) {
+				buffer.append(" " + returnType + LINE_SEPARATOR); //$NON-NLS-1$
+			} else {
+				buffer.append(LINE_SEPARATOR); //$NON-NLS-1$
+			}
 		}
 		
 		ASTNode convert() {
 			MethodDeclaration methodDeclaration = ast.newMethodDeclaration();
 			methodDeclaration.setConstructor(false);
 			methodDeclaration.setModifiers(this.modifiers);
-			methodDeclaration.setName(ast.newSimpleName(new String(this.name)));
+			methodDeclaration.setName(ast.newSimpleName(this.name));
 			methodDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(this.sourceStart));
 			// set parameter names and types
 			if (this.parametersNames != null) {
@@ -288,23 +297,25 @@
 			// set return type
 			int indexOfArrayBrace;
 			String currentReturnType = this.returnType;
-			if (currentReturnType.indexOf('.') != -1) {
-				String[] returnTypeSubstrings = splitOn('.', currentReturnType);
-				int length = returnTypeSubstrings.length;
-				indexOfArrayBrace = returnTypeSubstrings[length - 1].indexOf('[');
-				if (indexOfArrayBrace != -1) {
-					int dimensions = occurencesOf('[', returnTypeSubstrings[length - 1]);
-					returnTypeSubstrings[length - 1] = returnTypeSubstrings[length - 1].substring(0, indexOfArrayBrace);
-					methodDeclaration.setReturnType(ast.newArrayType(ast.newSimpleType(ast.newName(returnTypeSubstrings)), dimensions));
+			if (currentReturnType != null) {
+				if (currentReturnType.indexOf('.') != -1) {
+					String[] returnTypeSubstrings = splitOn('.', currentReturnType);
+					int length = returnTypeSubstrings.length;
+					indexOfArrayBrace = returnTypeSubstrings[length - 1].indexOf('[');
+					if (indexOfArrayBrace != -1) {
+						int dimensions = occurencesOf('[', returnTypeSubstrings[length - 1]);
+						returnTypeSubstrings[length - 1] = returnTypeSubstrings[length - 1].substring(0, indexOfArrayBrace);
+						methodDeclaration.setReturnType(ast.newArrayType(ast.newSimpleType(ast.newName(returnTypeSubstrings)), dimensions));
+					} else {
+						methodDeclaration.setReturnType(ast.newSimpleType(ast.newName(returnTypeSubstrings)));
+					}
+				} else if ((indexOfArrayBrace = currentReturnType.indexOf('[')) != -1) {
+					int dimensions = occurencesOf('[', currentReturnType);
+					currentReturnType = currentReturnType.substring(0, indexOfArrayBrace);
+					methodDeclaration.setReturnType(ast.newArrayType(newType(currentReturnType), dimensions));
 				} else {
-					methodDeclaration.setReturnType(ast.newSimpleType(ast.newName(returnTypeSubstrings)));
+					methodDeclaration.setReturnType(newType(currentReturnType));
 				}
-			} else if ((indexOfArrayBrace = currentReturnType.indexOf('[')) != -1) {
-				int dimensions = occurencesOf('[', currentReturnType);
-				currentReturnType = currentReturnType.substring(0, indexOfArrayBrace);
-				methodDeclaration.setReturnType(ast.newArrayType(newType(currentReturnType), dimensions));
-			} else {
-				methodDeclaration.setReturnType(newType(currentReturnType));
 			}
 			return methodDeclaration;				
 		}
@@ -327,7 +338,7 @@
 			MethodDeclaration methodDeclaration = ast.newMethodDeclaration();
 			methodDeclaration.setConstructor(true);
 			methodDeclaration.setModifiers(this.modifiers);
-			methodDeclaration.setName(ast.newSimpleName(new String(this.name)));
+			methodDeclaration.setName(ast.newSimpleName(this.name));
 			methodDeclaration.setProperty(CompilationUnitSorter.RELATIVE_ORDER, new Integer(this.sourceStart));
 			// set parameter names and types
 			if (this.parametersNames != null) {
@@ -371,7 +382,7 @@
 		
 		ASTNode convert() {
 			VariableDeclarationFragment variableDeclarationFragment = ast.newVariableDeclarationFragment();
-			variableDeclarationFragment.setName(ast.newSimpleName(new String(this.name)));
+			variableDeclarationFragment.setName(ast.newSimpleName(this.name));
 			FieldDeclaration fieldDeclaration = ast.newFieldDeclaration(variableDeclarationFragment);
 
 			String currentFieldType = this.type;
@@ -506,8 +517,6 @@
 	}
 	
 	class SortMultipleFieldDeclaration extends SortElement {
-		int declarationStart;
-		
 		SortMultipleFieldDeclaration(SortFieldDeclaration fieldDeclaration) {
 			super(fieldDeclaration.declarationStart, fieldDeclaration.modifiers);
 			this.declarationStart = fieldDeclaration.declarationStart;
@@ -544,7 +553,7 @@
 
 		ASTNode convert() {
 			VariableDeclarationFragment variableDeclarationFragment = ast.newVariableDeclarationFragment();
-			variableDeclarationFragment.setName(ast.newSimpleName(new String(this.innerFields[0].name)));
+			variableDeclarationFragment.setName(ast.newSimpleName(this.innerFields[0].name));
 			FieldDeclaration fieldDeclaration = ast.newFieldDeclaration(variableDeclarationFragment);
 
 			for (int j = 1, max2 = this.innerFields.length; j < max2; j++) {
@@ -867,6 +876,7 @@
 			this.id = COMPILATION_UNIT;
 		}
 		void display(StringBuffer buffer, int tab) {
+			// nothing to do
 		}
 		
 		ASTNode convert() {
@@ -921,7 +931,7 @@
 		this.source = source;
 		this.comparator = comparator;
 		this.positionsToMap = positionsToMap;
-		this.scanner = new Scanner(false, false, false, false, null, null);
+		this.scanner = new Scanner(false, false, false, ClassFileConstants.JDK1_3/*sourceLevel*/, null, null);
 		this.ast = new AST();
 	}
 	
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java
index c8222ad..a5996d2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortElementsOperation.java
@@ -19,13 +19,13 @@
 import org.eclipse.jdt.core.IJavaModelStatus;
 import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IWorkingCopy;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.SourceElementParser;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.core.builder.ProblemFactory;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This operation is used to sort elements in a compilation unit according to
@@ -36,7 +36,6 @@
 public class SortElementsOperation extends JavaModelOperation {
 	
 	Comparator comparator;
-	boolean hasChanged;
 	int[] positions;
 	
 	/**
@@ -54,7 +53,7 @@
 	 * progress reporting.
 	 */
 	protected int getMainAmountOfWork(){
-		return fElementsToProcess.length;
+		return elementsToProcess.length;
 	}
 	
 	/**
@@ -63,8 +62,8 @@
 	protected void executeOperation() throws JavaModelException {
 		try {
 			beginTask(Util.bind("operation.sortelements"), getMainAmountOfWork()); //$NON-NLS-1$
-			WorkingCopy copy = (WorkingCopy) fElementsToProcess[0];
-			ICompilationUnit unit = (ICompilationUnit) copy.getOriginalElement();
+			CompilationUnit copy = (CompilationUnit) elementsToProcess[0];
+			ICompilationUnit unit = copy.getPrimary();
 			IBuffer buffer = copy.getBuffer();
 			if (buffer  == null) { 
 				return;
@@ -85,8 +84,7 @@
 	 * @param unit
 	 * @param bufferContents
 	 */
-	private String processElement(ICompilationUnit unit, int[] positionsToMap, char[] source) throws JavaModelException {
-		this.hasChanged = false;
+	private String processElement(ICompilationUnit unit, int[] positionsToMap, char[] source) {
 		SortElementBuilder builder = new SortElementBuilder(source, positionsToMap, comparator);
 		SourceElementParser parser = new SourceElementParser(builder,
 			ProblemFactory.getProblemFactory(Locale.getDefault()), new CompilerOptions(JavaCore.getOptions()), true);
@@ -103,7 +101,7 @@
 					expectedPackageName,
 					unit.getElementName(),
 					null),
-				false);
+				false/*diet parse*/);
 		} else {
 			parser.parseCompilationUnit(
 				new BasicCompilationUnit(
@@ -111,7 +109,7 @@
 					null,
 					"",//$NON-NLS-1$
 					null),
-				false);
+				false/*diet parse*/);
 		}
 		return builder.getSource();
 	}
@@ -126,14 +124,14 @@
 	 * @see JavaConventions
 	 */
 	public IJavaModelStatus verify() {
-		if (fElementsToProcess.length != 1) {
+		if (elementsToProcess.length != 1) {
 			return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
 		}
-		if (fElementsToProcess[0] == null) {
+		if (elementsToProcess[0] == null) {
 			return new JavaModelStatus(IJavaModelStatusConstants.NO_ELEMENTS_TO_PROCESS);
 		}
-		if (!(fElementsToProcess[0] instanceof IWorkingCopy) || !((IWorkingCopy) fElementsToProcess[0]).isWorkingCopy()) {
-			return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, fElementsToProcess[0]);
+		if (!(elementsToProcess[0] instanceof ICompilationUnit) || !((ICompilationUnit) elementsToProcess[0]).isWorkingCopy()) {
+			return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, elementsToProcess[0]);
 		}
 		return JavaModelStatus.VERIFIED_OK;
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortJavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortJavaElement.java
index d04faef..e7dc5f4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortJavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SortJavaElement.java
@@ -144,13 +144,13 @@
 	}
 	
 	private ASTNode[] convertChildren() {
-		ASTNode[] astNodes = new ASTNode[this.children_count];
+		ASTNode[] convertedNodes = new ASTNode[this.children_count];
 		for (int i = 0, max = this.children_count; i < max; i++) {
 			SortElementBuilder.SortElement currentElement = this.children[i];
 			ASTNode newNode = currentElement.convert();
 			newNode.setProperty(CORRESPONDING_ELEMENT, currentElement);
-			astNodes[i] = newNode;
+			convertedNodes[i] = newNode;
 		}
-		return astNodes;
+		return convertedNodes;
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
index e280fe6..d04ee34 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceField.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
@@ -25,21 +26,66 @@
 /**
  * Constructs a handle to the field with the given name in the specified type. 
  */
-protected SourceField(IType parent, String name) {
-	super(FIELD, parent, name);
+protected SourceField(JavaElement parent, String name) {
+	super(parent, name);
+}
+public boolean equals(Object o) {
+	if (!(o instanceof SourceField)) return false;
+	return super.equals(o);
 }
 /**
  * @see JavaElement#equalsDOMNode
  */
-protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
+protected boolean equalsDOMNode(IDOMNode node) {
 	return (node.getNodeType() == IDOMNode.FIELD) && super.equalsDOMNode(node);
 }
 /**
  * @see IField
  */
 public Object getConstant() throws JavaModelException {
+	Object constant = null;	
 	SourceFieldElementInfo info = (SourceFieldElementInfo) getElementInfo();
-	return info.initializationSource;
+	if (info.initializationSource == null) {
+		return null;
+	}
+			
+	String constantSource = new String(info.initializationSource);
+	String signature = info.getTypeSignature();
+	if (signature.equals(Signature.SIG_INT)) {
+		constant = new Integer(constantSource);
+	} else if (signature.equals(Signature.SIG_SHORT)) {
+		constant = new Short(constantSource);
+	} else if (signature.equals(Signature.SIG_BYTE)) {
+		constant = new Byte(constantSource);
+	} else if (signature.equals(Signature.SIG_BOOLEAN)) {
+		constant = Boolean.valueOf(constantSource);
+	} else if (signature.equals(Signature.SIG_CHAR)) {
+		constant = new Character(constantSource.charAt(0));
+	} else if (signature.equals(Signature.SIG_DOUBLE)) {
+		constant = new Double(constantSource);
+	} else if (signature.equals(Signature.SIG_FLOAT)) {
+		constant = new Float(constantSource);
+	} else if (signature.equals(Signature.SIG_LONG)) {
+		if (constantSource.endsWith("L") || constantSource.endsWith("l")) { //$NON-NLS-1$ //$NON-NLS-2$
+			int index = constantSource.lastIndexOf("L");//$NON-NLS-1$
+			if (index != -1) {
+				constant = new Long(constantSource.substring(0, index));
+			} else {
+				constant = new Long(constantSource.substring(0, constantSource.lastIndexOf("l")));//$NON-NLS-1$
+			}
+		} else {
+			constant = new Long(constantSource);
+		}
+	} else if (signature.equals("QString;")) {//$NON-NLS-1$
+		constant = constantSource;
+	}
+	return constant;
+}
+/**
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return FIELD;
 }
 /**
  * @see JavaElement#getHandleMemento()
@@ -47,6 +93,17 @@
 protected char getHandleMementoDelimiter() {
 	return JavaElement.JEM_FIELD;
 }
+/*
+ * @see JavaElement#getPrimaryElement(boolean)
+ */
+public IJavaElement getPrimaryElement(boolean checkOwner) {
+	if (checkOwner) {
+		CompilationUnit cu = (CompilationUnit)getAncestor(COMPILATION_UNIT);
+		if (cu.isPrimary()) return this;
+	}
+	IJavaElement primaryParent =this.parent.getPrimaryElement(false);
+	return ((IType)primaryParent).getField(this.name);
+}
 /**
  * @see IField
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
index 9082311..4d9dd85 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceFieldElementInfo.java
@@ -17,7 +17,7 @@
  * Element info for IField elements.
  */
 
-/* package */ class SourceFieldElementInfo extends MemberElementInfo implements ISourceField {
+public class SourceFieldElementInfo extends MemberElementInfo implements ISourceField {
 
 	/**
 	 * The type name of this field.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
index 51f1f05..a53a21c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java
@@ -38,6 +38,7 @@
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.util.ReferenceInfoAdapter;
 
@@ -52,22 +53,17 @@
  */
 public class SourceMapper
 	extends ReferenceInfoAdapter
-	implements ISourceElementRequestor {
+	implements ISourceElementRequestor, SuffixConstants {
 		
 	public static boolean VERBOSE = false;
-
-	private final static String SUFFIX_JAVA = ".JAVA"; //$NON-NLS-1$
-	private final static String SUFFIX_java = ".java"; //$NON-NLS-1$
-
 	/**
 	 * Specifies the file name filter use to compute the root paths.
 	 */
 	private static final FilenameFilter FILENAME_FILTER = new FilenameFilter() {
 		public boolean accept(File dir, String name) {
-			return name.endsWith(SUFFIX_JAVA) || name.endsWith(SUFFIX_java); //$NON-NLS-1$
+			return name.endsWith(SUFFIX_STRING_JAVA) || name.endsWith(SUFFIX_STRING_java); //$NON-NLS-1$
 		}
 	};
-	
 	/**
 	 * Specifies the location of the package fragment roots within
 	 * the zip (empty specifies the default root). <code>null</code> is
@@ -204,10 +200,11 @@
 	 * @see ISourceElementRequestor
 	 */
 	public void acceptImport(
-		int declarationStart,
-		int declarationEnd,
-		char[] name,
-		boolean onDemand) {
+			int declarationStart,
+			int declarationEnd,
+			char[] name,
+			boolean onDemand,
+			int modifiers) {
 		char[][] imports = (char[][]) this.importsTable.get(fType);
 		int importsCounter;
 		if (imports == null) {
@@ -263,7 +260,7 @@
 	 * Closes this <code>SourceMapper</code>'s zip file. Once this is done, this
 	 * <code>SourceMapper</code> cannot be used again.
 	 */
-	public void close() throws JavaModelException {
+	public void close() {
 		fSourceRanges = null;
 		fParameterNames = null;
 	}
@@ -331,6 +328,7 @@
 					}
 				}
 			} catch (CoreException e) {
+				// ignore
 			} finally {
 				manager.closeZipFile(zip); // handle null case
 			}
@@ -350,6 +348,7 @@
 							}
 						}
 					} catch (CoreException e) {
+						// ignore
 					}
 				}
 			} else if (target instanceof File) {
@@ -394,6 +393,7 @@
 					}
 				}
 			} catch (CoreException e) {
+				// ignore
 			} finally {
 				manager.closeZipFile(zip); // handle null case
 			}
@@ -477,6 +477,7 @@
 				}
 			}
 		} catch (CoreException e) {
+			// ignore
 		}
 	}	
 
@@ -708,6 +709,7 @@
 	 * @see ISourceElementRequestor
 	 */
 	public void exitInitializer(int declarationEnd) {
+		// implements abstract method
 	}
 	
 	/**
@@ -837,17 +839,19 @@
 			try {
 				if (type.isMember()) {
 					IType enclosingType = type.getDeclaringType();
+					if (enclosingType == null) return null; // play it safe
 					while (enclosingType.getDeclaringType() != null) {
 						enclosingType = enclosingType.getDeclaringType();
 					}
-					return enclosingType.getElementName() + ".java"; //$NON-NLS-1$
+					return enclosingType.getElementName() + SUFFIX_STRING_java;
 				} else if (type.isLocal() || type.isAnonymous()){
 					String typeQualifiedName = type.getTypeQualifiedName();
-					return typeQualifiedName.substring(0, typeQualifiedName.indexOf('$')) + ".java"; //$NON-NLS-1$
+					return typeQualifiedName.substring(0, typeQualifiedName.indexOf('$')) + SUFFIX_STRING_java;
 				} else {
-					return type.getElementName() + ".java"; //$NON-NLS-1$
+					return type.getElementName() + SUFFIX_STRING_java;
 				}
 			} catch (JavaModelException e) {
+				// ignore
 			}
 		} else {
 			return  new String(sourceFileName);
@@ -895,8 +899,9 @@
 				IResource res = folder.findMember(fullName);
 				if (res instanceof IFile) {
 					try {
-						source = org.eclipse.jdt.internal.core.Util.getResourceContentsAsCharArray((IFile)res, this.encoding);
+						source = org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray((IFile)res, this.encoding);
 					} catch (JavaModelException e) {
+						// ignore
 					}
 				}
 			} else if (target instanceof File) {
@@ -906,6 +911,7 @@
 					try {
 						source = Util.getFileCharContent(sourceFile, this.encoding);
 					} catch (IOException e) {
+						// ignore
 					}
 				}
 			}
@@ -942,7 +948,7 @@
 	 * null if no parameter names are known for the method.
 	 */
 	public char[][] getMethodParameterNames(IMethod method) {
-		if (((IMember) method).isBinary()) {
+		if (method.isBinary()) {
 			IJavaElement[] el = getUnqualifiedMethodHandle(method, false);
 			if(el[1] != null && fParameterNames.get(el[0]) == null) {
 				method = (IMethod) getUnqualifiedMethodHandle(method, true)[0];
@@ -1049,16 +1055,16 @@
 	public synchronized ISourceRange mapSource(
 		IType type,
 		char[] contents,
-		IJavaElement searchedElement) {
+		IJavaElement elementToFind) {
 			
 		fType = (BinaryType) type;
 		
 		// check whether it is already mapped
-		if (this.fSourceRanges.get(type) != null) return (searchedElement != null) ? this.getNameRange(searchedElement) : null;
+		if (this.fSourceRanges.get(type) != null) return (elementToFind != null) ? this.getNameRange(elementToFind) : null;
 		
 		this.importsTable.remove(fType);
 		this.importsCounterTable.remove(fType);
-		this.searchedElement = searchedElement;
+		this.searchedElement = elementToFind;
 		this.types = new IType[1];
 		this.typeDeclarationStarts = new int[1];
 		this.typeNameRanges = new SourceRange[1];
@@ -1082,6 +1088,7 @@
 				isAnonymousClass = binType.isAnonymous();
 				fullName = binType.getName();
 			} catch(JavaModelException e) {
+				// ignore
 			}
 			if (isAnonymousClass) {
 				String eltName = fType.getElementName();
@@ -1089,21 +1096,22 @@
 				try {
 					this.anonymousClassName = Integer.parseInt(eltName);
 				} catch(NumberFormatException e) {
+					// ignore
 				}
 			}
 			boolean doFullParse = hasToRetrieveSourceRangesForLocalClass(fullName);
 			parser = new SourceElementParser(this, factory, new CompilerOptions(this.options), doFullParse);
 			parser.parseCompilationUnit(
-				new BasicCompilationUnit(contents, null, type.getElementName() + ".java", encoding), //$NON-NLS-1$
+				new BasicCompilationUnit(contents, null, type.getElementName() + SUFFIX_STRING_java, encoding),
 				doFullParse);
-			if (searchedElement != null) {
-				ISourceRange range = this.getNameRange(searchedElement);
+			if (elementToFind != null) {
+				ISourceRange range = this.getNameRange(elementToFind);
 				return range;
 			} else {
 				return null;
 			}
 		} finally {
-			if (searchedElement != null) {
+			if (elementToFind != null) {
 				fSourceRanges = oldSourceRanges;
 			}
 			fType = null;
@@ -1121,6 +1129,7 @@
 				return Util.bytesToChar(bytes, this.encoding);
 			}
 		} catch (IOException e) {
+			// ignore
 		}
 		return null;
 	}	
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java
index 8d60b42..40eadd1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethod.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.IType;
@@ -17,6 +18,7 @@
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.jdom.IDOMMethod;
 import org.eclipse.jdt.core.jdom.IDOMNode;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * @see IMethod
@@ -35,8 +37,8 @@
 	 * An empty list of Strings
 	 */
 	protected static final String[] fgEmptyList= new String[] {};
-protected SourceMethod(IType parent, String name, String[] parameterTypes) {
-	super(METHOD, parent, name);
+protected SourceMethod(JavaElement parent, String name, String[] parameterTypes) {
+	super(parent, name);
 	Assert.isTrue(name.indexOf('.') == -1);
 	if (parameterTypes == null) {
 		fParameterTypes= fgEmptyList;
@@ -45,20 +47,25 @@
 	}
 }
 public boolean equals(Object o) {
+	if (!(o instanceof SourceMethod)) return false;
 	return super.equals(o) && Util.equalArraysOrNull(fParameterTypes, ((SourceMethod)o).fParameterTypes);
 }
 /**
  * @see JavaElement#equalsDOMNode
  */
-protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
+protected boolean equalsDOMNode(IDOMNode node) {
 	if (node.getNodeType() == IDOMNode.METHOD) {
-		IDOMMethod m = (IDOMMethod)node;
-		if (isConstructor()) {
-			return 
-				(m.isConstructor() || m.getName().equals(this.getElementName()) /* case of a constructor that is being renamed */) 
-					&& signatureEquals(m);
-		} else {
-			return super.equalsDOMNode(node) && signatureEquals(m);
+		try {
+			IDOMMethod m = (IDOMMethod)node;
+			if (isConstructor()) {
+				return 
+					(m.isConstructor() || m.getName().equals(this.getElementName()) /* case of a constructor that is being renamed */) 
+						&& signatureEquals(m);
+			} else {
+				return super.equalsDOMNode(node) && signatureEquals(m);
+			}
+		} catch (JavaModelException e) {
+			return false;
 		}
 	} else {
 		return false;
@@ -66,6 +73,12 @@
 
 }
 /**
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return METHOD;
+}
+/**
  * @see IMethod
  */
 public String[] getExceptionTypes() throws JavaModelException {
@@ -84,6 +97,10 @@
 		buff.append(getHandleMementoDelimiter());
 		buff.append(fParameterTypes[i]);
 	}
+	if (this.occurrenceCount > 1) {
+		buff.append(JEM_COUNT);
+		buff.append(this.occurrenceCount);
+	}
 	return buff.toString();
 }
 /**
@@ -119,6 +136,17 @@
 public String[] getParameterTypes() {
 	return fParameterTypes;
 }
+/*
+ * @see JavaElement#getPrimaryElement(boolean)
+ */
+public IJavaElement getPrimaryElement(boolean checkOwner) {
+	if (checkOwner) {
+		CompilationUnit cu = (CompilationUnit)getAncestor(COMPILATION_UNIT);
+		if (cu.isPrimary()) return this;
+	}
+	IJavaElement primaryParent = this.parent.getPrimaryElement(false);
+	return ((IType)primaryParent).getMethod(this.name, fParameterTypes);
+}
 /**
  * @see IMethod
  */
@@ -181,7 +209,7 @@
  * Returns <code>true</code> if the signature of this <code>SourceMethod</code> matches that of the given
  * <code>IDOMMethod</code>, otherwise <code>false</code>. 
  */
-protected boolean signatureEquals(IDOMMethod method) throws JavaModelException {
+protected boolean signatureEquals(IDOMMethod method) {
 	String[] otherTypes= method.getParameterTypes();
 	String[] types= getParameterTypes();
 	boolean ok= true;
@@ -218,9 +246,11 @@
 	buffer.append(this.tabString(tab));
 	if (info == null) {
 		buffer.append(getElementName());
+			toStringParameters(buffer);
 		buffer.append(" (not open)"); //$NON-NLS-1$
 	} else if (info == NO_INFO) {
 		buffer.append(getElementName());
+			toStringParameters(buffer);
 	} else {
 		try {
 			if (Flags.isStatic(this.getFlags())) {
@@ -231,21 +261,24 @@
 				buffer.append(' ');
 			}
 			buffer.append(this.getElementName());
-			buffer.append('(');
-			String[] parameterTypes = this.getParameterTypes();
-			int length;
-			if (parameterTypes != null && (length = parameterTypes.length) > 0) {
-				for (int i = 0; i < length; i++) {
-					buffer.append(Signature.toString(parameterTypes[i]));
-					if (i < length - 1) {
-						buffer.append(", "); //$NON-NLS-1$
-					}
-				}
-			}
-			buffer.append(')');
+			toStringParameters(buffer);
 		} catch (JavaModelException e) {
 			buffer.append("<JavaModelException in toString of " + getElementName()); //$NON-NLS-1$
 		}
 	}
 }
+private void toStringParameters(StringBuffer buffer) {
+	buffer.append('(');
+	String[] parameterTypes = this.getParameterTypes();
+	int length;
+	if (parameterTypes != null && (length = parameterTypes.length) > 0) {
+		for (int i = 0; i < length; i++) {
+			buffer.append(Signature.toString(parameterTypes[i]));
+			if (i < length - 1) {
+				buffer.append(", "); //$NON-NLS-1$
+			}
+		}
+	}
+	buffer.append(')');
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java
index 3cfd14c..a76fa2b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMethodElementInfo.java
@@ -16,7 +16,7 @@
 /** 
  * Element info for IMethod elements. 
  */
-/* package */ class SourceMethodElementInfo extends MemberElementInfo implements ISourceMethod {
+public class SourceMethodElementInfo extends MemberElementInfo implements ISourceMethod {
 
 	/**
 	 * For a source method (that is, a method contained in a compilation unit)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRange.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRange.java
index 4b8bca0..6d2513e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRange.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRange.java
@@ -15,11 +15,11 @@
 /**
  * @see ISourceRange
  */
-/* package */ class SourceRange implements ISourceRange {
+public class SourceRange implements ISourceRange {
 
 protected int offset, length;
 
-protected SourceRange(int offset, int length) {
+public SourceRange(int offset, int length) {
 	this.offset = offset;
 	this.length = length;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java
index 67b8cf6..775e6f7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java
@@ -10,24 +10,40 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IBuffer;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IOpenable;
 import org.eclipse.jdt.core.ISourceRange;
 import org.eclipse.jdt.core.ISourceReference;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Abstract class for Java elements which implement ISourceReference.
  */
 /* package */ abstract class SourceRefElement extends JavaElement implements ISourceReference {
-protected SourceRefElement(int type, IJavaElement parent, String name) {
-	super(type, parent, name);
+protected SourceRefElement(JavaElement parent, String name) {
+	super(parent, name);
+}
+/**
+ * This element is being closed.  Do any necessary cleanup.
+ */
+protected void closing(Object info) throws JavaModelException {
+	// Do any necessary cleanup
+}
+/**
+ * Returns a new element info for this element.
+ */
+protected Object createElementInfo() {
+	return null; // not used for source ref elements
 }
 /**
  * @see ISourceManipulation
@@ -55,6 +71,18 @@
 	IJavaElement[] elements = new IJavaElement[] {this};
 	getJavaModel().delete(elements, force, monitor);
 }
+/*
+ * @see JavaElement#generateInfos
+ */
+protected void generateInfos(Object info, HashMap newElements, IProgressMonitor pm) throws JavaModelException {
+	Openable openableParent = (Openable)getOpenableParent();
+	if (openableParent == null) return;
+
+	JavaElementInfo openableParentInfo = (JavaElementInfo) JavaModelManager.getJavaModelManager().getInfo(openableParent);
+	if (openableParentInfo == null) {
+		openableParent.generateInfos(openableParent.createElementInfo(), newElements, pm);
+	}
+}
 /**
  * @see IMember
  */
@@ -71,6 +99,16 @@
 	if (!exists()) throw newNotPresentException();
 	return null;
 }
+/*
+ * @see JavaElement
+ */
+public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner workingCopyOwner) {
+	switch (token.charAt(0)) {
+		case JEM_COUNT:
+			return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
+	}
+	return this;
+}
 /**
  * Return the first instance of IOpenable in the hierarchy of this
  * type (going up the hierarchy from this type);
@@ -112,7 +150,11 @@
 	if (offset == -1 || length == 0 ) {
 		return null;
 	}
-	return buffer.getText(offset, length);
+	try {
+		return buffer.getText(offset, length);
+	} catch(RuntimeException e) {
+		return null;
+	}
 }
 /**
  * @see ISourceReference
@@ -150,20 +192,13 @@
 /**
  * @see ISourceManipulation
  */
-public void rename(String name, boolean force, IProgressMonitor monitor) throws JavaModelException {
-	if (name == null) {
+public void rename(String newName, boolean force, IProgressMonitor monitor) throws JavaModelException {
+	if (newName == null) {
 		throw new IllegalArgumentException(Util.bind("element.nullName")); //$NON-NLS-1$
 	}
 	IJavaElement[] elements= new IJavaElement[] {this};
 	IJavaElement[] dests= new IJavaElement[] {this.getParent()};
-	String[] renamings= new String[] {name};
+	String[] renamings= new String[] {newName};
 	getJavaModel().rename(elements, dests, renamings, force, monitor);
 }
-/*
- * @see JavaElement#rootedAt(IJavaProject)
- */
-public IJavaElement rootedAt(IJavaProject project) {
-	// not needed
-	return null;
-}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
index 92debd8..5e3e11e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
@@ -12,6 +12,7 @@
 
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.StringTokenizer;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.*;
@@ -25,6 +26,7 @@
 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
 import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Handle for a source type. Info object is a SourceTypeElementInfo.
@@ -39,39 +41,59 @@
 	 * An empty list of Strings
 	 */
 	protected static final String[] fgEmptyList= new String[] {};
-protected SourceType(IJavaElement parent, String name) {
-	super(TYPE, parent, name);
-	Assert.isTrue(name.indexOf('.') == -1);
+protected SourceType(JavaElement parent, String name) {
+	super(parent, name);
+	Assert.isTrue(name.indexOf('.') == -1, Util.bind("sourcetype.invalidName", name)); //$NON-NLS-1$
 }
 /**
  * @see IType
  */
 public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor) throws JavaModelException {
+	codeComplete(snippet, insertion, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic, requestor, DefaultWorkingCopyOwner.PRIMARY);
+}
+/**
+ * @see IType
+ */
+public void codeComplete(char[] snippet,int insertion,int position,char[][] localVariableTypeNames,char[][] localVariableNames,int[] localVariableModifiers,boolean isStatic,ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
 	if (requestor == null) {
-		throw new IllegalArgumentException(Util.bind("codeAssist.nullRequestor")); //$NON-NLS-1$
+		throw new IllegalArgumentException("Completion requestor cannot be null"); //$NON-NLS-1$
 	}
 	
 	JavaProject project = (JavaProject) getJavaProject();
 	SearchableEnvironment environment = (SearchableEnvironment) project.getSearchableNameEnvironment();
 	NameLookup nameLookup = project.getNameLookup();
-	CompletionEngine engine = new CompletionEngine(environment, new CompletionRequestorWrapper(requestor,nameLookup), project.getOptions(true), project);
+	CompletionRequestorWrapper requestorWrapper = new CompletionRequestorWrapper(requestor,nameLookup);
+	CompletionEngine engine = new CompletionEngine(environment, requestorWrapper, project.getOptions(true), project);
+	requestorWrapper.completionEngine = engine;
 	
 	String source = getCompilationUnit().getSource();
 	if (source != null && insertion > -1 && insertion < source.length()) {
-		String encoding = project.getOption(JavaCore.CORE_ENCODING, true);
-		
-		char[] prefix = CharOperation.concat(source.substring(0, insertion).toCharArray(), new char[]{'{'});
-		char[] suffix = CharOperation.concat(new char[]{'}'}, source.substring(insertion).toCharArray());
-		char[] fakeSource = CharOperation.concat(prefix, snippet, suffix);
-		
-		BasicCompilationUnit cu = 
-			new BasicCompilationUnit(
-				fakeSource, 
-				null,
-				getElementName(),
-				encoding); 
-
-		engine.complete(cu, prefix.length + position, prefix.length);
+		try {
+			// set the units to look inside
+			JavaModelManager manager = JavaModelManager.getJavaModelManager();
+			ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+			nameLookup.setUnitsToLookInside(workingCopies);
+	
+			// code complete
+			String encoding = project.getOption(JavaCore.CORE_ENCODING, true);
+			
+			char[] prefix = CharOperation.concat(source.substring(0, insertion).toCharArray(), new char[]{'{'});
+			char[] suffix = CharOperation.concat(new char[]{'}'}, source.substring(insertion).toCharArray());
+			char[] fakeSource = CharOperation.concat(prefix, snippet, suffix);
+			
+			BasicCompilationUnit cu = 
+				new BasicCompilationUnit(
+					fakeSource, 
+					null,
+					getElementName(),
+					encoding); 
+	
+			engine.complete(cu, prefix.length + position, prefix.length);
+		} finally {
+			if (nameLookup != null) {
+				nameLookup.setUnitsToLookInside(null);
+			}
+		}
 	} else {
 		engine.complete(this, snippet, position, localVariableTypeNames, localVariableNames, localVariableModifiers, isStatic);
 	}
@@ -120,10 +142,14 @@
 	runOperation(op, monitor);
 	return (IType) op.getResultElements()[0];
 }
+public boolean equals(Object o) {
+	if (!(o instanceof SourceType)) return false;
+	return super.equals(o);
+}
 /**
  * @see JavaElement#equalsDOMNode
  */
-protected boolean equalsDOMNode(IDOMNode node) throws JavaModelException {
+protected boolean equalsDOMNode(IDOMNode node) {
 	return (node.getNodeType() == IDOMNode.TYPE) && super.equalsDOMNode(node);
 }
 /*
@@ -141,13 +167,13 @@
  * @see IMember
  */
 public IType getDeclaringType() {
-	IJavaElement parent = getParent();
-	while (parent != null) {
-		if (parent.getElementType() == IJavaElement.TYPE) {
-			return (IType) parent;
+	IJavaElement parentElement = getParent();
+	while (parentElement != null) {
+		if (parentElement.getElementType() == IJavaElement.TYPE) {
+			return (IType) parentElement;
 		} else
-			if (parent instanceof IMember) {
-				parent = parent.getParent();
+			if (parentElement instanceof IMember) {
+				parentElement = parentElement.getParent();
 			} else {
 				return null;
 			}
@@ -155,10 +181,16 @@
 	return null;
 }
 /**
+ * @see IJavaElement
+ */
+public int getElementType() {
+	return TYPE;
+}
+/**
  * @see IType#getField
  */
-public IField getField(String name) {
-	return new SourceField(this, name);
+public IField getField(String fieldName) {
+	return new SourceField(this, fieldName);
 }
 /**
  * @see IType
@@ -185,12 +217,85 @@
 	}
 	return packageName + '.' + getTypeQualifiedName(enclosingTypeSeparator);
 }
-
+/*
+ * @see JavaElement
+ */
+public IJavaElement getHandleFromMemento(String token, StringTokenizer memento, WorkingCopyOwner workingCopyOwner) {
+	switch (token.charAt(0)) {
+		case JEM_COUNT:
+			return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
+		case JEM_FIELD:
+			String fieldName = memento.nextToken();
+			JavaElement field = (JavaElement)getField(fieldName);
+			return field.getHandleFromMemento(memento, workingCopyOwner);
+		case JEM_INITIALIZER:
+			String count = memento.nextToken();
+			JavaElement initializer = (JavaElement)getInitializer(Integer.parseInt(count));
+			return initializer.getHandleFromMemento(memento, workingCopyOwner);
+		case JEM_METHOD:
+			String selector = memento.nextToken();
+			ArrayList params = new ArrayList();
+			nextParam: while (memento.hasMoreTokens()) {
+				token = memento.nextToken();
+				switch (token.charAt(0)) {
+					case JEM_TYPE:
+						break nextParam;
+					case JEM_METHOD:
+						String param = memento.nextToken();
+						StringBuffer buffer = new StringBuffer();
+						while (Signature.C_ARRAY == param.charAt(0)) {
+							buffer.append(Signature.C_ARRAY);
+							param = memento.nextToken();
+						}
+						params.add(buffer.toString() + param);
+						break;
+					default:
+						break nextParam;
+				}
+			}
+			String[] parameters = new String[params.size()];
+			params.toArray(parameters);
+			JavaElement method = (JavaElement)getMethod(selector, parameters);
+			if (token != null) {
+				switch (token.charAt(0)) {
+					case JEM_TYPE:
+					case JEM_LOCALVARIABLE:
+						return method.getHandleFromMemento(token, memento, workingCopyOwner);
+					default:
+						return method;
+				}
+			} else {
+				return method;
+			}
+		case JEM_TYPE:
+			String typeName;
+			if (memento.hasMoreTokens()) {
+				typeName = memento.nextToken();
+				char firstChar = typeName.charAt(0);
+				if (firstChar == JEM_FIELD || firstChar == JEM_INITIALIZER || firstChar == JEM_METHOD || firstChar == JEM_TYPE || firstChar == JEM_COUNT) {
+					token = typeName;
+					typeName = ""; //$NON-NLS-1$
+				} else {
+					token = null;
+				}
+			} else {
+				typeName = ""; //$NON-NLS-1$
+				token = null;
+			}
+			JavaElement type = (JavaElement)getType(typeName);
+			if (token == null) {
+				return type.getHandleFromMemento(memento, workingCopyOwner);
+			} else {
+				return type.getHandleFromMemento(token, memento, workingCopyOwner);
+			}
+	}
+	return null;
+}
 /**
  * @see IType
  */
-public IInitializer getInitializer(int occurrenceCount) {
-	return new Initializer(this, occurrenceCount);
+public IInitializer getInitializer(int count) {
+	return new Initializer(this, count);
 }
 /**
  * @see IType
@@ -204,8 +309,8 @@
 /**
  * @see IType#getMethod
  */
-public IMethod getMethod(String name, String[] parameterTypeSignatures) {
-	return new SourceMethod(this, name, parameterTypeSignatures);
+public IMethod getMethod(String selector, String[] parameterTypeSignatures) {
+	return new SourceMethod(this, selector, parameterTypeSignatures);
 }
 /**
  * @see IType
@@ -220,18 +325,39 @@
  * @see IType
  */
 public IPackageFragment getPackageFragment() {
-	IJavaElement parent = fParent;
-	while (parent != null) {
-		if (parent.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
-			return (IPackageFragment) parent;
+	IJavaElement parentElement = this.parent;
+	while (parentElement != null) {
+		if (parentElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) {
+			return (IPackageFragment)parentElement;
 		}
 		else {
-			parent = parent.getParent();
+			parentElement = parentElement.getParent();
 		}
 	}
 	Assert.isTrue(false);  // should not happen
 	return null;
 }
+/*
+ * @see JavaElement#getPrimaryElement(boolean)
+ */
+public IJavaElement getPrimaryElement(boolean checkOwner) {
+	if (checkOwner) {
+		CompilationUnit cu = (CompilationUnit)getAncestor(COMPILATION_UNIT);
+		if (cu.isPrimary()) return this;
+	}
+	IJavaElement primaryParent = this.parent.getPrimaryElement(false);
+	switch (primaryParent.getElementType()) {
+		case IJavaElement.COMPILATION_UNIT:
+			return ((ICompilationUnit)primaryParent).getType(this.name);
+		case IJavaElement.TYPE:
+			return ((IType)primaryParent).getType(this.name);
+		case IJavaElement.FIELD:
+		case IJavaElement.INITIALIZER:
+		case IJavaElement.METHOD:
+			return ((IMember)primaryParent).getType(this.name, this.occurrenceCount);
+	}
+	return this;
+}
 /**
  * @see IType
  */
@@ -261,8 +387,8 @@
 /**
  * @see IType
  */
-public IType getType(String name) {
-	return new SourceType(this, name);
+public IType getType(String typeName) {
+	return new SourceType(this, typeName);
 }
 /**
  * @see IType#getTypeQualifiedName
@@ -274,11 +400,19 @@
  * @see IType#getTypeQualifiedName(char)
  */
 public String getTypeQualifiedName(char enclosingTypeSeparator) {
-	if (fParent.getElementType() == IJavaElement.COMPILATION_UNIT) {
-		return fName;
-	} else {
-		return ((IType) fParent).getTypeQualifiedName(enclosingTypeSeparator) + enclosingTypeSeparator + fName;
+	switch (this.parent.getElementType()) {
+		case IJavaElement.COMPILATION_UNIT:
+			return this.name;
+		case IJavaElement.TYPE:
+			return ((IType) this.parent).getTypeQualifiedName(enclosingTypeSeparator) + enclosingTypeSeparator + this.name;
+		case IJavaElement.FIELD:
+		case IJavaElement.INITIALIZER:
+		case IJavaElement.METHOD:
+			return 
+				((IMember) this.parent).getDeclaringType().getTypeQualifiedName(enclosingTypeSeparator) 
+				+ enclosingTypeSeparator + this.name;
 	}
+	return null;
 }
 
 /**
@@ -291,16 +425,10 @@
 	return array;
 }
 /**
- * @see IParent 
- */
-public boolean hasChildren() throws JavaModelException {
-	return getChildren().length > 0;
-}
-/**
  * @see IType#isAnonymous()
  */
-public boolean isAnonymous() throws JavaModelException {
-	return false; // cannot create source handle onto anonymous types
+public boolean isAnonymous() {
+	return this.name.length() == 0;
 }
 /**
  * @see IType
@@ -318,32 +446,66 @@
 /**
  * @see IType#isLocal()
  */
-public boolean isLocal() throws JavaModelException {
-	return false; // cannot create source handle onto local types
+public boolean isLocal() {
+	return this.parent instanceof IMethod || this.parent instanceof IInitializer;
 }
 /**
  * @see IType#isMember()
  */
-public boolean isMember() throws JavaModelException {
+public boolean isMember() {
 	return getDeclaringType() != null;
 }
 /**
  * @see IType
  */
 public ITypeHierarchy loadTypeHierachy(InputStream input, IProgressMonitor monitor) throws JavaModelException {
-	return TypeHierarchy.load(this, input);
+	return loadTypeHierachy(input, DefaultWorkingCopyOwner.PRIMARY, monitor);
+}
+/**
+ * NOTE: This method is not part of the API has it is not clear clients would easily use it: they would need to
+ * first make sure all working copies for the given owner exist before calling it. This is especially har at startup 
+ * time.
+ * In case clients want this API, here is how it should be specified:
+ * <p>
+ * Loads a previously saved ITypeHierarchy from an input stream. A type hierarchy can
+ * be stored using ITypeHierachy#store(OutputStream). A compilation unit of a
+ * loaded type has the given owner if such a working copy exists, otherwise the type's 
+ * compilation unit is a primary compilation unit.
+ * 
+ * Only hierarchies originally created by the following methods can be loaded:
+ * <ul>
+ * <li>IType#newSupertypeHierarchy(IProgressMonitor)</li>
+ * <li>IType#newSupertypeHierarchy(WorkingCopyOwner, IProgressMonitor)</li>
+ * <li>IType#newTypeHierarchy(IJavaProject, IProgressMonitor)</li>
+ * <li>IType#newTypeHierarchy(IJavaProject, WorkingCopyOwner, IProgressMonitor)</li>
+ * <li>IType#newTypeHierarchy(IProgressMonitor)</li>
+ * <li>IType#newTypeHierarchy(WorkingCopyOwner, IProgressMonitor)</li>
+ * </u>
+ * 
+ * @param input stream where hierarchy will be read
+ * @param monitor the given progress monitor
+ * @return the stored hierarchy
+ * @exception JavaModelException if the hierarchy could not be restored, reasons include:
+ *      - type is not the focus of the hierarchy or 
+ *		- unable to read the input stream (wrong format, IOException during reading, ...)
+ * @see ITypeHierarchy#store(OutputStream, IProgressMonitor)
+ * @since 3.0
+ */
+public ITypeHierarchy loadTypeHierachy(InputStream input, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
+	// TODO monitor should be passed to TypeHierarchy.load(...)
+	return TypeHierarchy.load(this, input, owner);
 }
 /**
  * @see IType
  */
 public ITypeHierarchy newSupertypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
-	return this.newSupertypeHierarchy(null, monitor);
+	return this.newSupertypeHierarchy(DefaultWorkingCopyOwner.PRIMARY, monitor);
 }
-/**
- * @see IType#newSupertypeHierarchy(IWorkingCopy[], IProgressMonitor)
+/*
+ * @see IType#newSupertypeHierarchy(ICompilationUnit[], IProgressMonitor)
  */
 public ITypeHierarchy newSupertypeHierarchy(
-	IWorkingCopy[] workingCopies,
+	ICompilationUnit[] workingCopies,
 	IProgressMonitor monitor)
 	throws JavaModelException {
 
@@ -351,18 +513,93 @@
 	runOperation(op, monitor);
 	return op.getResult();
 }
+/**
+ * @param workingCopies the working copies that take precedence over their original compilation units
+ * @param monitor the given progress monitor
+ * @return a type hierarchy for this type containing this type and all of its supertypes
+ * @exception JavaModelException if this element does not exist or if an
+ *		exception occurs while accessing its corresponding resource.
+ *
+ * @see IType#newSupertypeHierarchy(IWorkingCopy[], IProgressMonitor)
+ * @deprecated
+ */
+public ITypeHierarchy newSupertypeHierarchy(
+	IWorkingCopy[] workingCopies,
+	IProgressMonitor monitor)
+	throws JavaModelException {
 
+	ICompilationUnit[] copies;
+	if (workingCopies == null) {
+		copies = null;
+	} else {
+		int length = workingCopies.length;
+		System.arraycopy(workingCopies, 0, copies = new ICompilationUnit[length], 0, length);
+	}
+	return newSupertypeHierarchy(copies, monitor);
+}
+/**
+ * @see IType#newSupertypeHierarchy(WorkingCopyOwner, IProgressMonitor)
+ */
+public ITypeHierarchy newSupertypeHierarchy(
+	WorkingCopyOwner owner,
+	IProgressMonitor monitor)
+	throws JavaModelException {
+
+	ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
+	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), false);
+	runOperation(op, monitor);
+	return op.getResult();
+}
+/**
+ * @see IType
+ */
+public ITypeHierarchy newTypeHierarchy(IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
+	return newTypeHierarchy(project, DefaultWorkingCopyOwner.PRIMARY, monitor);
+}
+/**
+ * @see IType#newTypeHierarchy(IJavaProject, WorkingCopyOwner, IProgressMonitor)
+ */
+public ITypeHierarchy newTypeHierarchy(IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor) throws JavaModelException {
+	if (project == null) {
+		throw new IllegalArgumentException(Util.bind("hierarchy.nullProject")); //$NON-NLS-1$
+	}
+	ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
+	ICompilationUnit[] projectWCs = null;
+	if (workingCopies != null) {
+		int length = workingCopies.length;
+		projectWCs = new ICompilationUnit[length];
+		int index = 0;
+		for (int i = 0; i < length; i++) {
+			ICompilationUnit wc = workingCopies[i];
+			if (project.equals(wc.getJavaProject())) {
+				projectWCs[index++] = wc;
+			}
+		}
+		if (index != length) {
+			System.arraycopy(projectWCs, 0, projectWCs = new ICompilationUnit[index], 0, index);
+		}
+	}
+	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(
+		this, 
+		projectWCs,
+		project, 
+		true);
+	runOperation(op, monitor);
+	return op.getResult();
+}
 /**
  * @see IType
  */
 public ITypeHierarchy newTypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
-	return this.newTypeHierarchy((IWorkingCopy[])null, monitor);
+	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, null, SearchEngine.createWorkspaceScope(), true);
+	runOperation(op, monitor);
+	return op.getResult();
 }
-/**
- * @see IType#newTypeHierarchy(IWorkingCopy[], IProgressMonitor)
+/*
+ * @see IType#newTypeHierarchy(ICompilationUnit[], IProgressMonitor)
  */
 public ITypeHierarchy newTypeHierarchy(
-	IWorkingCopy[] workingCopies,
+	ICompilationUnit[] workingCopies,
 	IProgressMonitor monitor)
 	throws JavaModelException {
 		
@@ -370,70 +607,112 @@
 	runOperation(op, monitor);
 	return op.getResult();
 }
-
 /**
- * @see IType
+ * @see IType#newTypeHierarchy(IWorkingCopy[], IProgressMonitor)
+ * @deprecated
  */
-public ITypeHierarchy newTypeHierarchy(IJavaProject project, IProgressMonitor monitor) throws JavaModelException {
-	if (project == null) {
-		throw new IllegalArgumentException(Util.bind("hierarchy.nullProject")); //$NON-NLS-1$
+public ITypeHierarchy newTypeHierarchy(
+	IWorkingCopy[] workingCopies,
+	IProgressMonitor monitor)
+	throws JavaModelException {
+		
+	ICompilationUnit[] copies;
+	if (workingCopies == null) {
+		copies = null;
+	} else {
+		int length = workingCopies.length;
+		System.arraycopy(workingCopies, 0, copies = new ICompilationUnit[length], 0, length);
 	}
-	
-	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(
-		this, 
-		(IWorkingCopy[])null, // no working copies
-		project,
-		true);
-	runOperation(op, monitor);
-	return op.getResult();
+	return newTypeHierarchy(copies, monitor);
 }
 /**
- * See ISourceType.resolveType(...)
+ * @see IType#newTypeHierarchy(WorkingCopyOwner, IProgressMonitor)
  */
-
- public String[][] resolveType(String typeName) throws JavaModelException {
-	ISourceType info = (ISourceType) this.getElementInfo();
-	ISearchableNameEnvironment environment = ((JavaProject)getJavaProject()).getSearchableNameEnvironment();
-
-	class TypeResolveRequestor implements ISelectionRequestor {
-		String[][] answers = null;
-		void acceptType(String[] answer){
-			if (answers == null) {
-				answers = new String[][]{ answer };
-			} else {
-				// grow
-				int length = answers.length;
-				System.arraycopy(answers, 0, answers = new String[length+1][], 0, length);
-				answers[length] = answer;
+public ITypeHierarchy newTypeHierarchy(
+	WorkingCopyOwner owner,
+	IProgressMonitor monitor)
+	throws JavaModelException {
+		
+	ICompilationUnit[] workingCopies = JavaModelManager.getJavaModelManager().getWorkingCopies(owner, true/*add primary working copies*/);
+	CreateTypeHierarchyOperation op= new CreateTypeHierarchyOperation(this, workingCopies, SearchEngine.createWorkspaceScope(), true);
+	runOperation(op, monitor);
+	return op.getResult();	
+}
+/**
+ * @see IType#resolveType(String)
+ */
+public String[][] resolveType(String typeName) throws JavaModelException {
+	return resolveType(typeName, DefaultWorkingCopyOwner.PRIMARY);
+}
+/**
+ * @see IType#resolveType(String, WorkingCopyOwner)
+ */
+public String[][] resolveType(String typeName, WorkingCopyOwner owner) throws JavaModelException {
+	JavaProject project = (JavaProject)getJavaProject();
+	NameLookup lookup = null;
+	try {
+		// set the units to look inside
+		lookup = project.getNameLookup();
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+		lookup.setUnitsToLookInside(workingCopies);
+			
+		// resolve
+		ISourceType info = (ISourceType) this.getElementInfo();
+		ISearchableNameEnvironment environment = project.getSearchableNameEnvironment();
+	
+		class TypeResolveRequestor implements ISelectionRequestor {
+			String[][] answers = null;
+			void acceptType(String[] answer){
+				if (answers == null) {
+					answers = new String[][]{ answer };
+				} else {
+					// grow
+					int length = answers.length;
+					System.arraycopy(answers, 0, answers = new String[length+1][], 0, length);
+					answers[length] = answer;
+				}
 			}
+			public void acceptClass(char[] packageName, char[] className, boolean needQualification) {
+				acceptType(new String[]  { new String(packageName), new String(className) });
+			}
+			
+			public void acceptInterface(char[] packageName, char[] interfaceName, boolean needQualification) {
+				acceptType(new String[]  { new String(packageName), new String(interfaceName) });
+			}
+	
+			public void acceptError(IProblem error) {
+				// ignore
+			}
+			public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName) {
+				// ignore
+			}
+			public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, boolean isConstructor) {
+				// ignore
+			}
+			public void acceptPackage(char[] packageName){
+				// ignore
+			}
+	
 		}
-		public void acceptClass(char[] packageName, char[] className, boolean needQualification) {
-			acceptType(new String[]  { new String(packageName), new String(className) });
+		TypeResolveRequestor requestor = new TypeResolveRequestor();
+		SelectionEngine engine = 
+			new SelectionEngine(environment, requestor, this.getJavaProject().getOptions(true));
+			
+	 	IType[] topLevelTypes = this.getCompilationUnit().getTypes();
+	 	int length = topLevelTypes.length;
+	 	ISourceType[] topLevelInfos = new ISourceType[length];
+	 	for (int i = 0; i < length; i++) {
+			topLevelInfos[i] = (ISourceType)((SourceType)topLevelTypes[i]).getElementInfo();
 		}
-		
-		public void acceptInterface(char[] packageName, char[] interfaceName, boolean needQualification) {
-			acceptType(new String[]  { new String(packageName), new String(interfaceName) });
+			
+		engine.selectType(info, typeName.toCharArray(), topLevelInfos, false);
+		return requestor.answers;
+	} finally {
+		if (lookup != null) {
+			lookup.setUnitsToLookInside(null);
 		}
-
-		public void acceptError(IProblem error) {}
-		public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name) {}
-		public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, boolean isConstructor) {}
-		public void acceptPackage(char[] packageName){}
-
 	}
-	TypeResolveRequestor requestor = new TypeResolveRequestor();
-	SelectionEngine engine = 
-		new SelectionEngine(environment, requestor, this.getJavaProject().getOptions(true));
-		
- 	IType[] topLevelTypes = this.getCompilationUnit().getTypes();
- 	int length = topLevelTypes.length;
- 	ISourceType[] topLevelInfos = new ISourceType[length];
- 	for (int i = 0; i < length; i++) {
-		topLevelInfos[i] = (ISourceType)((SourceType)topLevelTypes[i]).getElementInfo();
-	}
-		
-	engine.selectType(info, typeName.toCharArray(), topLevelInfos, false);
-	return requestor.answers;
 }
 /**
  * @private Debugging purposes
@@ -441,10 +720,24 @@
 protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
 	buffer.append(this.tabString(tab));
 	if (info == null) {
-		buffer.append(this.getElementName());
+		String elementName = this.getElementName();
+		if (elementName.length() == 0) {
+			buffer.append("<anonymous #"); //$NON-NLS-1$
+			buffer.append(this.occurrenceCount);
+			buffer.append(">"); //$NON-NLS-1$
+		} else {
+			buffer.append(elementName);
+		}
 		buffer.append(" (not open)"); //$NON-NLS-1$
 	} else if (info == NO_INFO) {
-		buffer.append(getElementName());
+		String elementName = this.getElementName();
+		if (elementName.length() == 0) {
+			buffer.append("<anonymous #"); //$NON-NLS-1$
+			buffer.append(this.occurrenceCount);
+			buffer.append(">"); //$NON-NLS-1$
+		} else {
+			buffer.append(elementName);
+		}
 	} else {
 		try {
 			if (this.isInterface()) {
@@ -452,7 +745,14 @@
 			} else {
 				buffer.append("class "); //$NON-NLS-1$
 			}
-			buffer.append(this.getElementName());
+			String elementName = this.getElementName();
+			if (elementName.length() == 0) {
+				buffer.append("<anonymous #"); //$NON-NLS-1$
+				buffer.append(this.occurrenceCount);
+				buffer.append(">"); //$NON-NLS-1$
+			} else {
+				buffer.append(elementName);
+			}
 		} catch (JavaModelException e) {
 			buffer.append("<JavaModelException in toString of " + getElementName()); //$NON-NLS-1$
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
index 5f4e0ce..cb44dbb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
@@ -10,11 +10,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import org.eclipse.jdt.core.IImportDeclaration;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.internal.compiler.env.IConstants;
 import org.eclipse.jdt.internal.compiler.env.ISourceField;
+import org.eclipse.jdt.internal.compiler.env.ISourceImport;
 import org.eclipse.jdt.internal.compiler.env.ISourceMethod;
 import org.eclipse.jdt.internal.compiler.env.ISourceType;
 
@@ -22,6 +24,9 @@
  * Element info for an IType element that originated from source. 
  */
 public class SourceTypeElementInfo extends MemberElementInfo implements ISourceType {
+
+	protected static final ISourceImport[] NO_IMPORTS = new ISourceImport[0];
+	protected static final InitializerElementInfo[] NO_INITIALIZERS = new InitializerElementInfo[0];
 	protected static final ISourceField[] NO_FIELDS = new ISourceField[0];
 	protected static final ISourceMethod[] NO_METHODS = new ISourceMethod[0];
 	protected static final ISourceType[] NO_TYPES = new ISourceType[0];
@@ -30,7 +35,7 @@
 	 * is fully qualified for binary types and is NOT
 	 * fully qualified for source types.
 	 */
-	protected char[] fSuperclassName;
+	protected char[] superclassName;
 	
 	/**
 	 * The names of the interfaces this type implements or
@@ -38,76 +43,35 @@
 	 * of a binary type, and are NOT fully qualified in the
 	 * case of a source type
 	 */
-	protected char[][] fSuperInterfaceNames;
+	protected char[][] superInterfaceNames;
 	
 	/**
-	 * The enclosing type name for this type.
-	 *
-	 * @see getEnclosingTypeName
-	 */
-	protected char[] fEnclosingTypeName = null;
-
-	/**
 	 * The name of the source file this type is declared in.
 	 */
-	protected char[] fSourceFileName= null;
+	protected char[] sourceFileName;
 
 	/**
 	 * The name of the package this type is contained in.
 	 */
-	protected char[] fPackageName= null;
+	protected char[] packageName;
 
 	/**
-	 * The qualified name of this type.
+	 * The infos of the imports in this type's compilation unit
 	 */
-	protected char[] fQualifiedName= null;
-
-
-
-
-
-
-
-	/**
-	 * The imports in this type's compilation unit
-	 */
-	protected char[][] fImports= null;
-
+	private ISourceImport[] imports;
+	
 	/**
 	 * Backpointer to my type handle - useful for translation
 	 * from info to handle.
 	 */
-	protected IType fHandle= null;
-	 
-
-
-
-
-
-
-
-
-/**
- * Adds the given import to this type's collection of imports
- */
-protected void addImport(char[] i) {
-	if (fImports == null) {
-		fImports = new char[][] {i};
-	} else {
-		char[][] copy = new char[fImports.length + 1][];
-		System.arraycopy(fImports, 0, copy, 0, fImports.length);
-		copy[fImports.length] = i;
-		fImports = copy;
-	}
-}
-
+	protected IType handle = null;
 
 /**
  * Returns the ISourceType that is the enclosing type for this
  * type, or <code>null</code> if this type is a top level type.
  */
 public ISourceType getEnclosingType() {
-	IJavaElement parent= fHandle.getParent();
+	IJavaElement parent= this.handle.getParent();
 	if (parent != null && parent.getElementType() == IJavaElement.TYPE) {
 		try {
 			return (ISourceType)((JavaElement)parent).getElementInfo();
@@ -121,24 +85,19 @@
 /**
  * @see ISourceType
  */
-public char[] getEnclosingTypeName() {
-	return fEnclosingTypeName;
-}
-/**
- * @see ISourceType
- */
 public ISourceField[] getFields() {
-	int length = fChildren.length;
+	int length = this.children.length;
 	if (length == 0) return NO_FIELDS;
 	ISourceField[] fields = new ISourceField[length];
 	int fieldIndex = 0;
 	for (int i = 0; i < length; i++) {
-		IJavaElement child = fChildren[i];
+		IJavaElement child = this.children[i];
 		if (child instanceof SourceField) {
 			try {
 				ISourceField field = (ISourceField)((SourceField)child).getElementInfo();
 				fields[fieldIndex++] = field;
 			} catch (JavaModelException e) {
+				// ignore
 			}
 		}
 	}
@@ -150,41 +109,86 @@
  * @see ISourceType
  */
 public char[] getFileName() {
-	return fSourceFileName;
+	return this.sourceFileName;
 }
 /**
  * Returns the handle for this type info
  */
 public IType getHandle() {
-	return fHandle;
+	return this.handle;
 }
 /**
  * @see ISourceType
  */
-public char[][] getImports() {
-	return fImports;
+public ISourceImport[] getImports() {
+	if (this.imports == null) {
+		try {
+			IImportDeclaration[] importDeclarations = this.handle.getCompilationUnit().getImports();
+			int length = importDeclarations.length;
+			if (length == 0) {
+				this.imports = NO_IMPORTS;
+			} else {
+				ISourceImport[] sourceImports = new ISourceImport[length];
+				for (int i = 0; i < length; i++) {
+					sourceImports[i] = (ImportDeclarationElementInfo)((ImportDeclaration)importDeclarations[i]).getElementInfo();
+				}
+				this.imports = sourceImports; // only commit at the end, once completed (bug 36854)
+			}
+		} catch (JavaModelException e) {
+			this.imports = NO_IMPORTS;
+		}
+	}
+	return this.imports;
+}
+/*
+ * Returns the InitializerElementInfos for this type.
+ * Returns an empty array if none.
+ */
+public InitializerElementInfo[] getInitializers() {
+	int length = this.children.length;
+	if (length == 0) return NO_INITIALIZERS;
+	InitializerElementInfo[] initializers = new InitializerElementInfo[length];
+	int initializerIndex = 0;
+	for (int i = 0; i < length; i++) {
+		IJavaElement child = this.children[i];
+		if (child instanceof Initializer) {
+			try {
+				InitializerElementInfo initializer = (InitializerElementInfo)((Initializer)child).getElementInfo();
+				initializers[initializerIndex++] = initializer;
+			} catch (JavaModelException e) {
+				// ignore
+			}
+		}
+	}
+	if (initializerIndex == 0) return NO_INITIALIZERS;
+	System.arraycopy(initializers, 0, initializers = new InitializerElementInfo[initializerIndex], 0, initializerIndex);
+	return initializers;
 }
 /**
  * @see ISourceType
  */
 public char[][] getInterfaceNames() {
-	return fSuperInterfaceNames;
+	if (this.handle.getElementName().length() == 0) { // if anonymous type
+		return null;
+	}
+	return this.superInterfaceNames;
 }
 /**
  * @see ISourceType
  */
 public ISourceType[] getMemberTypes() {
-	int length = fChildren.length;
+	int length = this.children.length;
 	if (length == 0) return NO_TYPES;
 	ISourceType[] memberTypes = new ISourceType[length];
 	int typeIndex = 0;
 	for (int i = 0; i < length; i++) {
-		IJavaElement child = fChildren[i];
+		IJavaElement child = this.children[i];
 		if (child instanceof SourceType) {
 			try {
 				ISourceType type = (ISourceType)((SourceType)child).getElementInfo();
 				memberTypes[typeIndex++] = type;
 			} catch (JavaModelException e) {
+				// ignore
 			}
 		}
 	}
@@ -196,17 +200,18 @@
  * @see ISourceType
  */
 public ISourceMethod[] getMethods() {
-	int length = fChildren.length;
+	int length = this.children.length;
 	if (length == 0) return NO_METHODS;
 	ISourceMethod[] methods = new ISourceMethod[length];
 	int methodIndex = 0;
 	for (int i = 0; i < length; i++) {
-		IJavaElement child = fChildren[i];
+		IJavaElement child = this.children[i];
 		if (child instanceof SourceMethod) {
 			try {
 				ISourceMethod method = (ISourceMethod)((SourceMethod)child).getElementInfo();
 				methods[methodIndex++] = method;
 			} catch (JavaModelException e) {
+				// ignore
 			}
 		}
 	}
@@ -218,19 +223,19 @@
  * @see ISourceType
  */
 public char[] getPackageName() {
-	return fPackageName;
-}
-/**
- * @see ISourceType
- */
-public char[] getQualifiedName() {
-	return fQualifiedName;
+	return this.packageName;
 }
 /**
  * @see ISourceType
  */
 public char[] getSuperclassName() {
-	return fSuperclassName;
+	if (this.handle.getElementName().length() == 0) { // if anonymous type
+		char[][] interfaceNames = this.superInterfaceNames;	
+		if (interfaceNames != null && interfaceNames.length > 0) {
+			return interfaceNames[0];
+		}
+	} 
+	return this.superclassName;
 }
 /**
  * @see ISourceType
@@ -251,48 +256,36 @@
 	return (this.flags & IConstants.AccInterface) != 0;
 }
 /**
- * Sets the (unqualified) name of the type that encloses this type.
- */
-protected void setEnclosingTypeName(char[] enclosingTypeName) {
-	fEnclosingTypeName = enclosingTypeName;
-}
-/**
  * Sets the handle for this type info
  */
 protected void setHandle(IType handle) {
-	fHandle= handle;
+	this.handle = handle;
 }
 /**
  * Sets the name of the package this type is declared in.
  */
 protected void setPackageName(char[] name) {
-	fPackageName= name;
-}
-/**
- * Sets this type's qualified name.
- */
-protected void setQualifiedName(char[] name) {
-	fQualifiedName= name;
+	this.packageName= name;
 }
 /**
  * Sets the name of the source file this type is declared in.
  */
 protected void setSourceFileName(char[] name) {
-	fSourceFileName= name;
+	this.sourceFileName= name;
 }
 /**
  * Sets the (unqualified) name of this type's superclass
  */
 protected void setSuperclassName(char[] superclassName) {
-	fSuperclassName = superclassName;
+	this.superclassName = superclassName;
 }
 /**
  * Sets the (unqualified) names of the interfaces this type implements or extends
  */
 protected void setSuperInterfaceNames(char[][] superInterfaceNames) {
-	fSuperInterfaceNames = superInterfaceNames;
+	this.superInterfaceNames = superInterfaceNames;
 }
 public String toString() {
-	return "Info for " + fHandle.toString(); //$NON-NLS-1$
+	return "Info for " + this.handle.toString(); //$NON-NLS-1$
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeConverter.java
index ed023d8..79abc76 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeConverter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeConverter.java
@@ -17,6 +17,7 @@
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
 import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
@@ -25,7 +26,6 @@
 import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.MemberTypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
@@ -45,7 +45,7 @@
 		char[] packageName = type.getPackageFragment().getElementName().toCharArray();
 		
 		if (packageName != null && packageName.length > 0) { 
-			compilationUnit.currentPackage = new ImportReference(CharOperation.splitOn('.', packageName), new long[]{0}, false);
+			compilationUnit.currentPackage = new ImportReference(CharOperation.splitOn('.', packageName), new long[]{0}, false, CompilerModifiers.AccDefault);
 		}
 	
 		/* convert type */
@@ -55,7 +55,7 @@
 		IType parent = type.getDeclaringType();
 		TypeDeclaration previousDeclaration = typeDeclaration;
 		while(parent != null) {
-			TypeDeclaration declaration = convert(parent, alreadyComputedMember, (MemberTypeDeclaration)previousDeclaration, compilationResult);
+			TypeDeclaration declaration = convert(parent, alreadyComputedMember, previousDeclaration, compilationResult);
 			
 			alreadyComputedMember = parent;
 			previousDeclaration = declaration;
@@ -122,13 +122,12 @@
 		return methodDeclaration;
 	}
 	
-	private static TypeDeclaration convert(IType type, IType alreadyComputedMember,MemberTypeDeclaration alreadyComputedMemberDeclaration, CompilationResult compilationResult) throws JavaModelException {
+	private static TypeDeclaration convert(IType type, IType alreadyComputedMember,TypeDeclaration alreadyComputedMemberDeclaration, CompilationResult compilationResult) throws JavaModelException {
 		/* create type declaration - can be member type */
-		TypeDeclaration typeDeclaration;
-		if (type.getDeclaringType() == null) {
-			typeDeclaration = new TypeDeclaration(compilationResult);
-		} else {
-			typeDeclaration = new MemberTypeDeclaration(compilationResult);
+		TypeDeclaration typeDeclaration = new TypeDeclaration(compilationResult);
+
+		if (type.getDeclaringType() != null) {
+			typeDeclaration.bits |= ASTNode.IsMemberTypeMASK;
 		}
 		typeDeclaration.name = type.getElementName().toCharArray();
 		typeDeclaration.modifiers = type.getFlags();
@@ -148,13 +147,12 @@
 		/* convert member types */
 		IType[] memberTypes = type.getTypes();
 		int memberTypeCount =	memberTypes == null ? 0 : memberTypes.length;
-		typeDeclaration.memberTypes = new MemberTypeDeclaration[memberTypeCount];
+		typeDeclaration.memberTypes = new TypeDeclaration[memberTypeCount];
 		for (int i = 0; i < memberTypeCount; i++) {
 			if(alreadyComputedMember != null && alreadyComputedMember.getFullyQualifiedName().equals(memberTypes[i].getFullyQualifiedName())) {
 				typeDeclaration.memberTypes[i] = alreadyComputedMemberDeclaration;
 			} else {
-				typeDeclaration.memberTypes[i] =
-					(MemberTypeDeclaration) convert(memberTypes[i], null, null, compilationResult);
+				typeDeclaration.memberTypes[i] = convert(memberTypes[i], null, null, compilationResult);
 			}
 		}
 
@@ -180,11 +178,11 @@
 				break;
 			}
 		}
+		boolean isInterface = type.isInterface();
 		typeDeclaration.methods = new AbstractMethodDeclaration[methodCount + neededCount];
-		if (neededCount != 0) { // add default constructor in first position
+		if (neededCount != 0 && !isInterface) { // add default constructor in first position
 			typeDeclaration.methods[0] = typeDeclaration.createsInternalConstructor(false, false);
 		}
-		boolean isInterface = type.isInterface();
 		for (int i = 0; i < methodCount; i++) {
 			AbstractMethodDeclaration method =convert(methods[i], type, compilationResult);
 			if (isInterface || method.isAbstract()) { // fix-up flag 
@@ -202,7 +200,7 @@
 				type= CharOperation.concat(resolvedName[0][0].toCharArray(), resolvedName[0][1].toCharArray(), '.');
 			}
 		} catch (JavaModelException e) {
-			
+			// ignore
 		}
 		
 		/* count identifiers and dimensions */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Util.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Util.java
deleted file mode 100644
index 2fa59bc..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Util.java
+++ /dev/null
@@ -1,1359 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.StringTokenizer;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IJavaModelStatusConstants;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.JavaConventions;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.core.util.CharArrayBuffer;
-
-/**
- * Provides convenient utility methods to other types in this package.
- */
-public class Util {
-
-	private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
-	private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
-	private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$
-	private static final String EMPTY_ARGUMENT = "   "; //$NON-NLS-1$
-
-	public interface Comparable {
-		/**
-		 * Returns 0 if this and c are equal, >0 if this is greater than c,
-		 * or <0 if this is less than c.
-		 */
-		int compareTo(Comparable c);
-	}
-
-	public interface Comparer {
-		/**
-		 * Returns 0 if a and b are equal, >0 if a is greater than b,
-		 * or <0 if a is less than b.
-		 */
-		int compare(Object a, Object b);
-	}
-	
-	public interface Displayable {
-		String displayString(Object o);
-	}
-	
-	public static final String[] fgEmptyStringArray = new String[0];
-
-	/**
-	 * Are we running JDK 1.1?
-	 */
-	private static boolean JDK1_1 = false;
-
-	/* Bundle containing messages */
-	protected static ResourceBundle bundle;
-	private final static String bundleName = "org.eclipse.jdt.internal.core.messages"; //$NON-NLS-1$
-
-	public final static char[] SUFFIX_class = ".class".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_CLASS = ".CLASS".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_java = ".java".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_JAVA = ".JAVA".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_jar = ".jar".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_JAR = ".JAR".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_zip = ".zip".toCharArray(); //$NON-NLS-1$
-	public final static char[] SUFFIX_ZIP = ".ZIP".toCharArray(); //$NON-NLS-1$
-
-	static {
-		String ver = System.getProperty("java.version"); //$NON-NLS-1$
-		JDK1_1 = ((ver != null) && ver.startsWith("1.1")); //$NON-NLS-1$
-		relocalize();
-	}	
-	
-	/**
-	 * Lookup the message with the given ID in this catalog 
-	 */
-	public static String bind(String id) {
-		return bind(id, (String[])null);
-	}
-	
-	/**
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given string values.
-	 */
-	public static String bind(String id, String[] bindings) {
-		if (id == null)
-			return "No message available"; //$NON-NLS-1$
-		String message = null;
-		try {
-			message = bundle.getString(id);
-		} catch (MissingResourceException e) {
-			// If we got an exception looking for the message, fail gracefully by just returning
-			// the id we were looking for.  In most cases this is semi-informative so is not too bad.
-			return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
-		}
-		// for compatibility with MessageFormat which eliminates double quotes in original message
-		char[] messageWithNoDoubleQuotes =
-		CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
-		message = new String(messageWithNoDoubleQuotes);
-	
-		if (bindings == null)
-			return message;
-	
-		int length = message.length();
-		int start = -1;
-		int end = length;
-		StringBuffer output = new StringBuffer(80);
-		while (true) {
-			if ((end = message.indexOf('{', start)) > -1) {
-				output.append(message.substring(start + 1, end));
-				if ((start = message.indexOf('}', end)) > -1) {
-					int index = -1;
-					try {
-						index = Integer.parseInt(message.substring(end + 1, start));
-						output.append(bindings[index]);
-					} catch (NumberFormatException nfe) {
-						output.append(message.substring(end + 1, start + 1));
-					} catch (ArrayIndexOutOfBoundsException e) {
-						output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
-					}
-				} else {
-					output.append(message.substring(end, length));
-					break;
-				}
-			} else {
-				output.append(message.substring(start + 1, length));
-				break;
-			}
-		}
-		return output.toString();
-	}
-
-	/**
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given string.
-	 */
-	public static String bind(String id, String binding) {
-		return bind(id, new String[] {binding});
-	}
-	
-	/**
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given strings.
-	 */
-	public static String bind(String id, String binding1, String binding2) {
-		return bind(id, new String[] {binding1, binding2});
-	}
-
-	/**
-	 * Checks the type signature in String sig, 
-	 * starting at start and ending before end (end is not included).
-	 * Returns the index of the character immediately after the signature if valid,
-	 * or -1 if not valid.
-	 */
-	private static int checkTypeSignature(String sig, int start, int end, boolean allowVoid) {
-		if (start >= end) return -1;
-		int i = start;
-		char c = sig.charAt(i++);
-		int nestingDepth = 0;
-		while (c == '[') {
-			++nestingDepth;
-			if (i >= end) return -1;
-			c = sig.charAt(i++);
-		}
-		switch (c) {
-			case 'B':
-			case 'C': 
-			case 'D':
-			case 'F':
-			case 'I':
-			case 'J':
-			case 'S': 
-			case 'Z':
-				break;
-			case 'V':
-				if (!allowVoid) return -1;
-				// array of void is not allowed
-				if (nestingDepth != 0) return -1;
-				break;
-			case 'L':
-				int semicolon = sig.indexOf(';', i);
-				// Must have at least one character between L and ;
-				if (semicolon <= i || semicolon >= end) return -1;
-				i = semicolon + 1;
-				break;
-			default:
-				return -1;
-		}
-		return i;
-	}
-	
-	/**
-	 * Combines two hash codes to make a new one.
-	 */
-	public static int combineHashCodes(int hashCode1, int hashCode2) {
-		return hashCode1 * 17 + hashCode2;
-	}
-	
-	/**
-	 * Compares two byte arrays.  
-	 * Returns <0 if a byte in a is less than the corresponding byte in b, or if a is shorter, or if a is null.
-	 * Returns >0 if a byte in a is greater than the corresponding byte in b, or if a is longer, or if b is null.
-	 * Returns 0 if they are equal or both null.
-	 */
-	public static int compare(byte[] a, byte[] b) {
-		if (a == b)
-			return 0;
-		if (a == null)
-			return -1;
-		if (b == null)
-			return 1;
-		int len = Math.min(a.length, b.length);
-		for (int i = 0; i < len; ++i) {
-			int diff = a[i] - b[i];
-			if (diff != 0)
-				return diff;
-		}
-		if (a.length > len)
-			return 1;
-		if (b.length > len)
-			return -1;
-		return 0;
-	}
-
-	/**
-	 * Compares two char arrays lexicographically. 
-	 * The comparison is based on the Unicode value of each character in
-	 * the char arrays. 
-	 * @return  the value <code>0</code> if a is equal to
-	 *          b; a value less than <code>0</code> if a
-	 *          is lexicographically less than b; and a
-	 *          value greater than <code>0</code> if a is
-	 *          lexicographically greater than b.
-	 */
-	public static int compare(char[] v1, char[] v2) {
-		int len1 = v1.length;
-		int len2 = v2.length;
-		int n = Math.min(len1, len2);
-		int i = 0;
-		while (n-- != 0) {
-			if (v1[i] != v2[i]) {
-				return v1[i] - v2[i];
-			}
-			++i;
-		}
-		return len1 - len2;
-	}
-
-	/**
-	 * Concatenate two strings with a char in between.
-	 * @see #concat(String, String)
-	 */
-	public static String concat(String s1, char c, String s2) {
-		if (s1 == null) s1 = "null"; //$NON-NLS-1$
-		if (s2 == null) s2 = "null"; //$NON-NLS-1$
-		int l1 = s1.length();
-		int l2 = s2.length();
-		char[] buf = new char[l1 + 1 + l2];
-		s1.getChars(0, l1, buf, 0);
-		buf[l1] = c;
-		s2.getChars(0, l2, buf, l1 + 1);
-		return new String(buf);
-	}
-	
-	/**
-	 * Concatenate two strings.
-	 * Much faster than using +, which:
-	 * 		- creates a StringBuffer,
-	 * 		- which is synchronized,
-	 * 		- of default size, so the resulting char array is
-	 *        often larger than needed.
-	 * This implementation creates an extra char array, since the
-	 * String constructor copies its argument, but there's no way around this.
-	 */
-	public static String concat(String s1, String s2) {
-		if (s1 == null) s1 = "null"; //$NON-NLS-1$
-		if (s2 == null) s2 = "null"; //$NON-NLS-1$
-		int l1 = s1.length();
-		int l2 = s2.length();
-		char[] buf = new char[l1 + l2];
-		s1.getChars(0, l1, buf, 0);
-		s2.getChars(0, l2, buf, l1);
-		return new String(buf);
-	}
-
-	/**
-	 * Concatenate three strings.
-	 * @see #concat(String, String)
-	 */
-	public static String concat(String s1, String s2, String s3) {
-		if (s1 == null) s1 = "null"; //$NON-NLS-1$
-		if (s2 == null) s2 = "null"; //$NON-NLS-1$
-		if (s3 == null) s3 = "null"; //$NON-NLS-1$
-		int l1 = s1.length();
-		int l2 = s2.length();
-		int l3 = s3.length();
-		char[] buf = new char[l1 + l2 + l3];
-		s1.getChars(0, l1, buf, 0);
-		s2.getChars(0, l2, buf, l1);
-		s3.getChars(0, l3, buf, l1 + l2);
-		return new String(buf);
-	}
-	
-	/**
-	 * Converts a type signature from the IBinaryType representation to the DC representation.
-	 */
-	public static String convertTypeSignature(char[] sig) {
-		return new String(sig).replace('/', '.');
-	}
-
-	/**
-	 * Returns true iff str.toLowerCase().endsWith(end.toLowerCase())
-	 * implementation is not creating extra strings.
-	 */
-	public final static boolean endsWithIgnoreCase(String str, String end) {
-		
-		int strLength = str == null ? 0 : str.length();
-		int endLength = end == null ? 0 : end.length();
-		
-		// return false if the string is smaller than the end.
-		if(endLength > strLength)
-			return false;
-			
-		// return false if any character of the end are
-		// not the same in lower case.
-		for(int i = 1 ; i <= endLength; i++){
-			if(Character.toLowerCase(end.charAt(endLength - i)) != Character.toLowerCase(str.charAt(strLength - i)))
-				return false;
-		}
-		
-		return true;
-	}
-
-	/**
-	 * Compares two arrays using equals() on the elements.
-	 * Either or both arrays may be null.
-	 * Returns true if both are null.
-	 * Returns false if only one is null.
-	 * If both are arrays, returns true iff they have the same length and
-	 * all elements are equal.
-	 */
-	public static boolean equalArraysOrNull(int[] a, int[] b) {
-		if (a == b)
-			return true;
-		if (a == null || b == null)
-			return false;
-		int len = a.length;
-		if (len != b.length)
-			return false;
-		for (int i = 0; i < len; ++i) {
-			if (a[i] != b[i])
-				return false;
-		}
-		return true;
-	}
-
-	/**
-	 * Compares two arrays using equals() on the elements.
-	 * Either or both arrays may be null.
-	 * Returns true if both are null.
-	 * Returns false if only one is null.
-	 * If both are arrays, returns true iff they have the same length and
-	 * all elements compare true with equals.
-	 */
-	public static boolean equalArraysOrNull(Object[] a, Object[] b) {
-		if (a == b)	return true;
-		if (a == null || b == null) return false;
-
-		int len = a.length;
-		if (len != b.length) return false;
-		for (int i = 0; i < len; ++i) {
-			if (a[i] == null) {
-				if (b[i] != null) return false;
-			} else {
-				if (!a[i].equals(b[i])) return false;
-			}
-		}
-		return true;
-	}
-	
-	/**
-	 * Compares two String arrays using equals() on the elements.
-	 * The arrays are first sorted.
-	 * Either or both arrays may be null.
-	 * Returns true if both are null.
-	 * Returns false if only one is null.
-	 * If both are arrays, returns true iff they have the same length and
-	 * iff, after sorting both arrays, all elements compare true with equals.
-	 * The original arrays are left untouched.
-	 */
-	public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) {
-		if (a == b)	return true;
-		if (a == null || b == null) return false;
-		int len = a.length;
-		if (len != b.length) return false;
-		if (len >= 2) {  // only need to sort if more than two items
-			a = sortCopy(a);
-			b = sortCopy(b);
-		}
-		for (int i = 0; i < len; ++i) {
-			if (!a[i].equals(b[i])) return false;
-		}
-		return true;
-	}
-	
-	/**
-	 * Compares two arrays using equals() on the elements.
-	 * The arrays are first sorted.
-	 * Either or both arrays may be null.
-	 * Returns true if both are null.
-	 * Returns false if only one is null.
-	 * If both are arrays, returns true iff they have the same length and
-	 * iff, after sorting both arrays, all elements compare true with equals.
-	 * The original arrays are left untouched.
-	 */
-	public static boolean equalArraysOrNullSortFirst(Comparable[] a, Comparable[] b) {
-		if (a == b)	return true;
-		if (a == null || b == null) return false;
-		int len = a.length;
-		if (len != b.length) return false;
-		if (len >= 2) {  // only need to sort if more than two items
-			a = sortCopy(a);
-			b = sortCopy(b);
-		}
-		for (int i = 0; i < len; ++i) {
-			if (!a[i].equals(b[i])) return false;
-		}
-		return true;
-	}
-	
-	/**
-	 * Compares two objects using equals().
-	 * Either or both array may be null.
-	 * Returns true if both are null.
-	 * Returns false if only one is null.
-	 * Otherwise, return the result of comparing with equals().
-	 */
-	public static boolean equalOrNull(Object a, Object b) {
-		if (a == b) {
-			return true;
-		}
-		if (a == null || b == null) {
-			return false;
-		}
-		return a.equals(b);
-	}
-	
-	/**
-	 * Given a qualified name, extract the last component.
-	 * If the input is not qualified, the same string is answered.
-	 */
-	public static String extractLastName(String qualifiedName) {
-		int i = qualifiedName.lastIndexOf('.');
-		if (i == -1) return qualifiedName;
-		return qualifiedName.substring(i+1);
-	}
-	
-	/**
-	 * Extracts the parameter types from a method signature.
-	 */
-	public static String[] extractParameterTypes(char[] sig) {
-		int count = getParameterCount(sig);
-		String[] result = new String[count];
-		if (count == 0)
-			return result;
-		int i = CharOperation.indexOf('(', sig) + 1;
-		count = 0;
-		int len = sig.length;
-		int start = i;
-		for (;;) {
-			if (i == len)
-				break;
-			char c = sig[i];
-			if (c == ')')
-				break;
-			if (c == '[') {
-				++i;
-			} else
-				if (c == 'L') {
-					i = CharOperation.indexOf(';', sig, i + 1) + 1;
-					Assert.isTrue(i != 0);
-					result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
-					start = i;
-				} else {
-					++i;
-					result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
-					start = i;
-				}
-		}
-		return result;
-	}
-
-	/**
-	 * Extracts the return type from a method signature.
-	 */
-	public static String extractReturnType(String sig) {
-		int i = sig.lastIndexOf(')');
-		Assert.isTrue(i != -1);
-		return sig.substring(i+1);	
-	}
-	
-	/**
-	 * Finds the first line separator used by the given text.
-	 *
-	 * @return </code>"\n"</code> or </code>"\r"</code> or  </code>"\r\n"</code>,
-	 *			or <code>null</code> if none found
-	 */
-	public static String findLineSeparator(char[] text) {
-		// find the first line separator
-		int length = text.length;
-		if (length > 0) {
-			char nextChar = text[0];
-			for (int i = 0; i < length; i++) {
-				char currentChar = nextChar;
-				nextChar = i < length-1 ? text[i+1] : ' ';
-				switch (currentChar) {
-					case '\n': return "\n"; //$NON-NLS-1$
-					case '\r': return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$
-				}
-			}
-		}
-		// not found
-		return null;
-	}
-	
-	/**
-	 * Returns the line separator used by the given buffer.
-	 * Uses the given text if none found.
-	 *
-	 * @return </code>"\n"</code> or </code>"\r"</code> or  </code>"\r\n"</code>
-	 */
-	private static String getLineSeparator(char[] text, char[] buffer) {
-		// search in this buffer's contents first
-		String lineSeparator = findLineSeparator(buffer);
-		if (lineSeparator == null) {
-			// search in the given text
-			lineSeparator = findLineSeparator(text);
-			if (lineSeparator == null) {
-				// default to system line separator
-				return org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR;
-			}
-		}
-		return lineSeparator;
-	}
-		
-	/**
-	 * Returns the number of parameter types in a method signature.
-	 */
-	public static int getParameterCount(char[] sig) {
-		int i = CharOperation.indexOf('(', sig) + 1;
-		Assert.isTrue(i != 0);
-		int count = 0;
-		int len = sig.length;
-		for (;;) {
-			if (i == len)
-				break;
-			char c = sig[i];
-			if (c == ')')
-				break;
-			if (c == '[') {
-				++i;
-			} else
-				if (c == 'L') {
-					++count;
-					i = CharOperation.indexOf(';', sig, i + 1) + 1;
-					Assert.isTrue(i != 0);
-				} else {
-					++count;
-					++i;
-				}
-		}
-		return count;
-	}
-	
-	/**
-	 * Returns the given file's contents as a byte array.
-	 */
-	public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException {
-		InputStream stream= null;
-		try {
-			stream = new BufferedInputStream(file.getContents(true));
-		} catch (CoreException e) {
-			throw new JavaModelException(e);
-		}
-		try {
-			return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1);
-		} catch (IOException e) {
-			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
-		} finally {
-			try {
-				stream.close();
-			} catch (IOException e) {
-			}
-		}
-	}
-	
-	/**
-	 * Returns the given file's contents as a character array.
-	 */
-	public static char[] getResourceContentsAsCharArray(IFile file) throws JavaModelException {
-		String encoding = JavaCore.create(file.getProject()).getOption(JavaCore.CORE_ENCODING, true);
-		return getResourceContentsAsCharArray(file, encoding);
-	}
-
-	public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException {
-		InputStream stream= null;
-		try {
-			stream = new BufferedInputStream(file.getContents(true));
-		} catch (CoreException e) {
-			throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST);
-		}
-		try {
-			return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, -1, encoding);
-		} catch (IOException e) {
-			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
-		} finally {
-			try {
-				stream.close();
-			} catch (IOException e) {
-			}
-		}
-	}
-	
-	/**
-	 * Returns a trimmed version the simples names returned by Signature.
-	 */
-	public static String[] getTrimmedSimpleNames(String name) {
-		String[] result = Signature.getSimpleNames(name);
-		if (result == null) return null;
-		for (int i = 0, length = result.length; i < length; i++) {
-			result[i] = result[i].trim();
-		}
-		return result;
-	}
-	
-	/**
-	 * Returns true iff str.toLowerCase().endsWith(".class")
-	 * implementation is not creating extra strings.
-	 */
-	public final static boolean isClassFileName(String name) {
-		int nameLength = name == null ? 0 : name.length();
-		int suffixLength = SUFFIX_CLASS.length;
-		if (nameLength < suffixLength) return false;
-
-		for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
-			char c = name.charAt(offset + i);
-			if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false;
-		}
-		return true;		
-	}
-	
-	/*
-	 * Returns whether the given java element is exluded from its root's classpath.
-	 */
-	public static final boolean isExcluded(IJavaElement element) {
-		int elementType = element.getElementType();
-		switch (elementType) {
-			case IJavaElement.PACKAGE_FRAGMENT:
-				PackageFragmentRoot root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
-				IResource resource = element.getResource();
-				return resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars());
-			case IJavaElement.COMPILATION_UNIT:
-				root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
-				resource = element.getResource();
-				if (resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars()))
-					return true;
-				return isExcluded(element.getParent());
-			default:
-				IJavaElement cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
-				return cu != null && isExcluded(cu);
-		}
-	}
-	/*
-	 * Returns whether the given resource path matches one of the exclusion
-	 * patterns.
-	 * 
-	 * @see IClasspathEntry#getExclusionPatterns
-	 */
-	public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) {
-		if (exclusionPatterns == null) return false;
-		char[] path = resourcePath.toString().toCharArray();
-		for (int i = 0, length = exclusionPatterns.length; i < length; i++)
-			if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/'))
-				return true;
-		return false;
-	}	
-	
-	/*
-	 * Returns whether the given resource matches one of the exclusion patterns.
-	 * 
-	 * @see IClasspathEntry#getExclusionPatterns
-	 */
-	public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) {
-		IPath path = resource.getFullPath();
-		// ensure that folders are only excluded if all of their children are excluded
-		if (resource.getType() == IResource.FOLDER)
-			path = path.append("*"); //$NON-NLS-1$
-		return isExcluded(path, exclusionPatterns);
-	}
-
-	/**
-	 * Returns true iff str.toLowerCase().endsWith(".jar" or ".zip")
-	 * implementation is not creating extra strings.
-	 */
-	public final static boolean isArchiveFileName(String name) {
-		int nameLength = name == null ? 0 : name.length();
-		int suffixLength = SUFFIX_JAR.length;
-		if (nameLength < suffixLength) return false;
-
-		int i, offset;
-		for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
-			char c = name.charAt(offset + i);
-			if (c != SUFFIX_jar[i] && c != SUFFIX_JAR[i]) break;
-		}
-		if (i == suffixLength) return true;		
-		for ( i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
-			char c = name.charAt(offset + i);
-			if (c != SUFFIX_zip[i] && c != SUFFIX_ZIP[i]) return false;
-		}
-		return true;
-	}
-	
-	/**
-	 * Validate the given compilation unit name.
-	 * A compilation unit name must obey the following rules:
-	 * <ul>
-	 * <li> it must not be null
-	 * <li> it must include the <code>".java"</code> suffix
-	 * <li> its prefix must be a valid identifier
-	 * </ul>
-	 * </p>
-	 * @param name the name of a compilation unit
-	 * @return a status object with code <code>IStatus.OK</code> if
-	 *		the given name is valid as a compilation unit name, otherwise a status 
-	 *		object indicating what is wrong with the name
-	 */
-	public static boolean isValidCompilationUnitName(String name) {
-		return JavaConventions.validateCompilationUnitName(name).getSeverity() != IStatus.ERROR;
-	}
-
-	/**
-	 * Validate the given .class file name.
-	 * A .class file name must obey the following rules:
-	 * <ul>
-	 * <li> it must not be null
-	 * <li> it must include the <code>".class"</code> suffix
-	 * <li> its prefix must be a valid identifier
-	 * </ul>
-	 * </p>
-	 * @param name the name of a .class file
-	 * @return a status object with code <code>IStatus.OK</code> if
-	 *		the given name is valid as a .class file name, otherwise a status 
-	 *		object indicating what is wrong with the name
-	 */
-	public static boolean isValidClassFileName(String name) {
-		return JavaConventions.validateClassFileName(name).getSeverity() != IStatus.ERROR;
-	}
-
-	/**
-	 * Returns true iff str.toLowerCase().endsWith(".java")
-	 * implementation is not creating extra strings.
-	 */
-	public final static boolean isJavaFileName(String name) {
-		int nameLength = name == null ? 0 : name.length();
-		int suffixLength = SUFFIX_JAVA.length;
-		if (nameLength < suffixLength) return false;
-
-		for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
-			char c = name.charAt(offset + i);
-			if (c != SUFFIX_java[i] && c != SUFFIX_JAVA[i]) return false;
-		}
-		return true;		
-	}
-
-	/**
-	 * Returns true if the given method signature is valid,
-	 * false if it is not.
-	 */
-	public static boolean isValidMethodSignature(String sig) {
-		int len = sig.length();
-		if (len == 0) return false;
-		int i = 0;
-		char c = sig.charAt(i++);
-		if (c != '(') return false;
-		if (i >= len) return false;
-		while (sig.charAt(i) != ')') {
-			// Void is not allowed as a parameter type.
-			i = checkTypeSignature(sig, i, len, false);
-			if (i == -1) return false;
-			if (i >= len) return false;
-		}
-		++i;
-		i = checkTypeSignature(sig, i, len, true);
-		return i == len;
-	}
-	
-	/**
-	 * Returns true if the given type signature is valid,
-	 * false if it is not.
-	 */
-	public static boolean isValidTypeSignature(String sig, boolean allowVoid) {
-		int len = sig.length();
-		return checkTypeSignature(sig, 0, len, allowVoid) == len;
-	}
-	
-	/**
-	 * Returns true if the given folder name is valid for a package,
-	 * false if it is not.
-	 */
-	public static boolean isValidFolderNameForPackage(String folderName) {
-		return JavaConventions.validateIdentifier(folderName).getSeverity() != IStatus.ERROR;
-	}	
-
-	/*
-	 * Add a log entry
-	 */
-	public static void log(Throwable e, String message) {
-		Throwable nestedException;
-		if (e instanceof JavaModelException 
-				&& (nestedException = ((JavaModelException)e).getException()) != null) {
-			e = nestedException;
-		}
-		IStatus status= new Status(
-			IStatus.ERROR, 
-			JavaCore.getPlugin().getDescriptor().getUniqueIdentifier(), 
-			IStatus.ERROR, 
-			message, 
-			e); 
-		JavaCore.getPlugin().getLog().log(status);
-	}	
-	
-	/**
-	 * Normalizes the cariage returns in the given text.
-	 * They are all changed  to use the given buffer's line separator.
-	 */
-	public static char[] normalizeCRs(char[] text, char[] buffer) {
-		CharArrayBuffer result = new CharArrayBuffer();
-		int lineStart = 0;
-		int length = text.length;
-		if (length == 0) return text;
-		String lineSeparator = getLineSeparator(text, buffer);
-		char nextChar = text[0];
-		for (int i = 0; i < length; i++) {
-			char currentChar = nextChar;
-			nextChar = i < length-1 ? text[i+1] : ' ';
-			switch (currentChar) {
-				case '\n':
-					int lineLength = i-lineStart;
-					char[] line = new char[lineLength];
-					System.arraycopy(text, lineStart, line, 0, lineLength);
-					result.append(line);
-					result.append(lineSeparator);
-					lineStart = i+1;
-					break;
-				case '\r':
-					lineLength = i-lineStart;
-					if (lineLength >= 0) {
-						line = new char[lineLength];
-						System.arraycopy(text, lineStart, line, 0, lineLength);
-						result.append(line);
-						result.append(lineSeparator);
-						if (nextChar == '\n') {
-							nextChar = ' ';
-							lineStart = i+2;
-						} else {
-							// when line separator are mixed in the same file
-							// \r might not be followed by a \n. If not, we should increment
-							// lineStart by one and not by two.
-							lineStart = i+1;
-						}
-					} else {
-						// when line separator are mixed in the same file
-						// we need to prevent NegativeArraySizeException
-						lineStart = i+1;
-					}
-					break;
-			}
-		}
-		char[] lastLine;
-		if (lineStart > 0) {
-			int lastLineLength = length-lineStart;
-			if (lastLineLength > 0) {
-				lastLine = new char[lastLineLength];
-				System.arraycopy(text, lineStart, lastLine, 0, lastLineLength);
-				result.append(lastLine);
-			}
-			return result.getContents();
-		} else {
-			return text;
-		}
-	}
-
-	/**
-	 * Normalizes the cariage returns in the given text.
-	 * They are all changed  to use given buffer's line sepatator.
-	 */
-	public static String normalizeCRs(String text, String buffer) {
-		return new String(normalizeCRs(text.toCharArray(), buffer.toCharArray()));
-	}
-
-	/**
-	 * Sort the objects in the given collection using the given sort order.
-	 */
-	private static void quickSort(Object[] sortedCollection, int left, int right, int[] sortOrder) {
-		int original_left = left;
-		int original_right = right;
-		int mid = sortOrder[ (left + right) / 2];
-		do {
-			while (sortOrder[left] < mid) {
-				left++;
-			}
-			while (mid < sortOrder[right]) {
-				right--;
-			}
-			if (left <= right) {
-				Object tmp = sortedCollection[left];
-				sortedCollection[left] = sortedCollection[right];
-				sortedCollection[right] = tmp;
-				int tmp2 = sortOrder[left];
-				sortOrder[left] = sortOrder[right];
-				sortOrder[right] = tmp2;
-				left++;
-				right--;
-			}
-		} while (left <= right);
-		if (original_left < right) {
-			quickSort(sortedCollection, original_left, right, sortOrder);
-		}
-		if (left < original_right) {
-			quickSort(sortedCollection, left, original_right, sortOrder);
-		}
-	}
-
-	/**
-	 * Sort the objects in the given collection using the given comparer.
-	 */
-	private static void quickSort(Object[] sortedCollection, int left, int right, Comparer comparer) {
-		int original_left = left;
-		int original_right = right;
-		Object mid = sortedCollection[ (left + right) / 2];
-		do {
-			while (comparer.compare(sortedCollection[left], mid) < 0) {
-				left++;
-			}
-			while (comparer.compare(mid, sortedCollection[right]) < 0) {
-				right--;
-			}
-			if (left <= right) {
-				Object tmp = sortedCollection[left];
-				sortedCollection[left] = sortedCollection[right];
-				sortedCollection[right] = tmp;
-				left++;
-				right--;
-			}
-		} while (left <= right);
-		if (original_left < right) {
-			quickSort(sortedCollection, original_left, right, comparer);
-		}
-		if (left < original_right) {
-			quickSort(sortedCollection, left, original_right, comparer);
-		}
-	}
-
-	/**
-	 * Sort the strings in the given collection.
-	 */
-	private static void quickSort(String[] sortedCollection, int left, int right) {
-		int original_left = left;
-		int original_right = right;
-		String mid = sortedCollection[ (left + right) / 2];
-		do {
-			while (sortedCollection[left].compareTo(mid) < 0) {
-				left++;
-			}
-			while (mid.compareTo(sortedCollection[right]) < 0) {
-				right--;
-			}
-			if (left <= right) {
-				String tmp = sortedCollection[left];
-				sortedCollection[left] = sortedCollection[right];
-				sortedCollection[right] = tmp;
-				left++;
-				right--;
-			}
-		} while (left <= right);
-		if (original_left < right) {
-			quickSort(sortedCollection, original_left, right);
-		}
-		if (left < original_right) {
-			quickSort(sortedCollection, left, original_right);
-		}
-	}
-
-	/**
-	 * Converts the given relative path into a package name.
-	 * Returns null if the path is not a valid package name.
-	 */
-	public static String packageName(IPath pkgPath) {
-		StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
-		for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) {
-			String segment = pkgPath.segment(j);
-			if (!isValidFolderNameForPackage(segment)) {
-				return null;
-			}
-			pkgName.append(segment);
-			if (j < pkgPath.segmentCount() - 1) {
-				pkgName.append("." ); //$NON-NLS-1$
-			}
-		}
-		return pkgName.toString();
-	}
-
-	/**
-	 * Sort the comparable objects in the given collection.
-	 */
-	private static void quickSort(Comparable[] sortedCollection, int left, int right) {
-		int original_left = left;
-		int original_right = right;
-		Comparable mid = sortedCollection[ (left + right) / 2];
-		do {
-			while (sortedCollection[left].compareTo(mid) < 0) {
-				left++;
-			}
-			while (mid.compareTo(sortedCollection[right]) < 0) {
-				right--;
-			}
-			if (left <= right) {
-				Comparable tmp = sortedCollection[left];
-				sortedCollection[left] = sortedCollection[right];
-				sortedCollection[right] = tmp;
-				left++;
-				right--;
-			}
-		} while (left <= right);
-		if (original_left < right) {
-			quickSort(sortedCollection, original_left, right);
-		}
-		if (left < original_right) {
-			quickSort(sortedCollection, left, original_right);
-		}
-	}
-
-	/**
-	 * Sort the strings in the given collection in reverse alphabetical order.
-	 */
-	private static void quickSortReverse(String[] sortedCollection, int left, int right) {
-		int original_left = left;
-		int original_right = right;
-		String mid = sortedCollection[ (left + right) / 2];
-		do {
-			while (sortedCollection[left].compareTo(mid) > 0) {
-				left++;
-			}
-			while (mid.compareTo(sortedCollection[right]) > 0) {
-				right--;
-			}
-			if (left <= right) {
-				String tmp = sortedCollection[left];
-				sortedCollection[left] = sortedCollection[right];
-				sortedCollection[right] = tmp;
-				left++;
-				right--;
-			}
-		} while (left <= right);
-		if (original_left < right) {
-			quickSortReverse(sortedCollection, original_left, right);
-		}
-		if (left < original_right) {
-			quickSortReverse(sortedCollection, left, original_right);
-		}
-	}
-
-	/**
-	 * Sorts an array of objects in place, using the sort order given for each item.
-	 */
-	public static void sort(Object[] objects, int[] sortOrder) {
-		if (objects.length > 1)
-			quickSort(objects, 0, objects.length - 1, sortOrder);
-	}
-
-	/**
-	 * Sorts an array of objects in place.
-	 * The given comparer compares pairs of items.
-	 */
-	public static void sort(Object[] objects, Comparer comparer) {
-		if (objects.length > 1)
-			quickSort(objects, 0, objects.length - 1, comparer);
-	}
-
-	/**
-	 * Sorts an array of strings in place using quicksort.
-	 */
-	public static void sort(String[] strings) {
-		if (strings.length > 1)
-			quickSort(strings, 0, strings.length - 1);
-	}
-
-	/**
-	 * Sorts an array of Comparable objects in place.
-	 */
-	public static void sort(Comparable[] objects) {
-		if (objects.length > 1)
-			quickSort(objects, 0, objects.length - 1);
-	}
-
-	/**
-	 * Sorts an array of Strings, returning a new array
-	 * with the sorted items.  The original array is left untouched.
-	 */
-	public static Object[] sortCopy(Object[] objects, Comparer comparer) {
-		int len = objects.length;
-		Object[] copy = new Object[len];
-		System.arraycopy(objects, 0, copy, 0, len);
-		sort(copy, comparer);
-		return copy;
-	}
-
-	/**
-	 * Sorts an array of Strings, returning a new array
-	 * with the sorted items.  The original array is left untouched.
-	 */
-	public static String[] sortCopy(String[] objects) {
-		int len = objects.length;
-		String[] copy = new String[len];
-		System.arraycopy(objects, 0, copy, 0, len);
-		sort(copy);
-		return copy;
-	}
-
-	/**
-	 * Sorts an array of Comparable objects, returning a new array
-	 * with the sorted items.  The original array is left untouched.
-	 */
-	public static Comparable[] sortCopy(Comparable[] objects) {
-		int len = objects.length;
-		Comparable[] copy = new Comparable[len];
-		System.arraycopy(objects, 0, copy, 0, len);
-		sort(copy);
-		return copy;
-	}
-
-	/**
-	 * Sorts an array of strings in place using quicksort
-	 * in reverse alphabetical order.
-	 */
-	public static void sortReverseOrder(String[] strings) {
-		if (strings.length > 1)
-			quickSortReverse(strings, 0, strings.length - 1);
-	}
-
-	/**
-	 * Converts a String[] to char[][].
-	 */
-	public static char[][] toCharArrays(String[] a) {
-		int len = a.length;
-		char[][] result = new char[len][];
-		for (int i = 0; i < len; ++i) {
-			result[i] = toChars(a[i]);
-		}
-		return result;
-	}
-
-	/**
-	 * Converts a String to char[].
-	 */
-	public static char[] toChars(String s) {
-		int len = s.length();
-		char[] chars = new char[len];
-		s.getChars(0, len, chars, 0);
-		return chars;
-	}
-
-	/**
-	 * Converts a String to char[][], where segments are separate by '.'.
-	 */
-	public static char[][] toCompoundChars(String s) {
-		int len = s.length();
-		if (len == 0) {
-			return CharOperation.NO_CHAR_CHAR;
-		}
-		int segCount = 1;
-		for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) {
-			++segCount;
-		}
-		char[][] segs = new char[segCount][];
-		int start = 0;
-		for (int i = 0; i < segCount; ++i) {
-			int dot = s.indexOf('.', start);
-			int end = (dot == -1 ? s.length() : dot);
-			segs[i] = new char[end - start];
-			s.getChars(start, end, segs[i], 0);
-			start = end + 1;
-		}
-		return segs;
-	}
-
-	/**
-	 * Converts a char[][] to String, where segments are separated by '.'.
-	 */
-	public static String toString(char[][] c) {
-		StringBuffer sb = new StringBuffer();
-		for (int i = 0, max = c.length; i < max; ++i) {
-			if (i != 0) sb.append('.');
-			sb.append(c[i]);
-		}
-		return sb.toString();
-	}
-
-	/**
-	 * Converts a char[][] and a char[] to String, where segments are separated by '.'.
-	 */
-	public static String toString(char[][] c, char[] d) {
-		if (c == null) return new String(d);
-		StringBuffer sb = new StringBuffer();
-		for (int i = 0, max = c.length; i < max; ++i) {
-			sb.append(c[i]);
-			sb.append('.');
-		}
-		sb.append(d);
-		return sb.toString();
-	}
-
-	/**
-	 * Converts a char[] to String.
-	 */
-	public static String toString(char[] c) {
-		return new String(c);
-	}
-
-	/**
-	 * Converts an array of Objects into String.
-	 */
-	public static String toString(Object[] objects) {
-		return toString(objects, 
-			new Displayable(){ 
-				public String displayString(Object o) { 
-					if (o == null) return "null"; //$NON-NLS-1$
-					return o.toString(); 
-				}
-			});
-	}
-
-	/**
-	 * Converts an array of Objects into String.
-	 */
-	public static String toString(Object[] objects, Displayable renderer) {
-		if (objects == null) return ""; //$NON-NLS-1$
-		StringBuffer buffer = new StringBuffer(10);
-		for (int i = 0; i < objects.length; i++){
-			if (i > 0) buffer.append(", "); //$NON-NLS-1$
-			buffer.append(renderer.displayString(objects[i]));
-		}
-		return buffer.toString();
-	}
-	
-	/**
-	 * Asserts that the given method signature is valid.
-	 */
-	public static void validateMethodSignature(String sig) {
-		Assert.isTrue(isValidMethodSignature(sig));
-	}
-
-	/**
-	 * Asserts that the given type signature is valid.
-	 */
-	public static void validateTypeSignature(String sig, boolean allowVoid) {
-		Assert.isTrue(isValidTypeSignature(sig, allowVoid));
-	}
-
-	/**
-	 * Creates a NLS catalog for the given locale.
-	 */
-	public static void relocalize() {
-		try {
-			bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
-		} catch(MissingResourceException e) {
-			System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
-			throw e;
-		}
-	}
-	
-	/**
-	 * Put all the arguments in one String.
-	 */
-	public static String getProblemArgumentsForMarker(String[] arguments){
-		StringBuffer args = new StringBuffer(10);
-		
-		args.append(arguments.length);
-		args.append(':');
-		
-			
-		for (int j = 0; j < arguments.length; j++) {
-			if(j != 0)
-				args.append(ARGUMENTS_DELIMITER);
-			
-			if(arguments[j].length() == 0) {
-				args.append(EMPTY_ARGUMENT);
-			} else {			
-				args.append(arguments[j]);
-			}
-		}
-		
-		return args.toString();
-	}
-	
-	/**
-	 * Separate all the arguments of a String made by getProblemArgumentsForMarker
-	 */
-	public static String[] getProblemArgumentsFromMarker(String argumentsString){
-		if (argumentsString == null) return null;
-		int index = argumentsString.indexOf(':');
-		if(index == -1)
-			return null;
-		
-		int length = argumentsString.length();
-		int numberOfArg;
-		try{
-			numberOfArg = Integer.parseInt(argumentsString.substring(0 , index));
-		} catch (NumberFormatException e) {
-			return null;
-		}
-		argumentsString = argumentsString.substring(index + 1, length);
-		
-		String[] args = new String[length];
-		int count = 0;
-		
-		StringTokenizer tokenizer = new StringTokenizer(argumentsString, ARGUMENTS_DELIMITER);
-		while(tokenizer.hasMoreTokens()) {
-			String argument = tokenizer.nextToken();
-			if(argument.equals(EMPTY_ARGUMENT))
-				argument = "";  //$NON-NLS-1$
-			args[count++] = argument;
-		}
-		
-		if(count != numberOfArg)
-			return null;
-		
-		System.arraycopy(args, 0, args = new String[count], 0, count);
-		return args;
-	}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/WorkingCopy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/WorkingCopy.java
deleted file mode 100644
index d85ca59..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/WorkingCopy.java
+++ /dev/null
@@ -1,500 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core;
-
-import java.io.*;
-import java.io.ByteArrayInputStream;
-import java.util.ArrayList;
-import org.eclipse.core.resources.IFile;
-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.jdt.core.*;
-import org.eclipse.jdt.core.compiler.CharOperation;
-
-/**
- * Implementation of a working copy compilation unit. A working
- * copy maintains the timestamp of the resource it was created
- * from.
- */
-
-public class WorkingCopy extends CompilationUnit {
-
-	/**
-	 * If set, this is the factory that will be used to create the buffer.
-	 */
-	protected IBufferFactory bufferFactory;
-
-	/**
-	 * If set, this is the problem requestor which will be used to notify problems
-	 * detected during reconciling.
-	 */
-	protected IProblemRequestor problemRequestor;
-		
-	/**
-	 * A counter of the number of time clients have asked for this 
-	 * working copy. It is set to 1, if the working
-	 * copy is not managed. When destroyed, this counter is
-	 * set to 0. Once destroyed, this working copy cannot be opened
-	 * and non-handle info can not be accessed. This is
-	 * never true if this compilation unit is not a working
-	 * copy.
-	 */
-	protected int useCount = 1;
-	
-/**
- */
-protected WorkingCopy(IPackageFragment parent, String name, IBufferFactory bufferFactory) {
-	this(parent, name, bufferFactory, null);
-}
-/**
- */
-protected WorkingCopy(IPackageFragment parent, String name, IBufferFactory bufferFactory, IProblemRequestor problemRequestor) {
-	super(parent, name);
-	this.bufferFactory = 
-		bufferFactory == null ? 
-			this.getBufferManager().getDefaultBufferFactory() :
-			bufferFactory;
-	this.problemRequestor = problemRequestor;
-}
-/**
- * @see IWorkingCopy
- */
-public void commit(boolean force, IProgressMonitor monitor) throws JavaModelException {
-	ICompilationUnit original = (ICompilationUnit)this.getOriginalElement();
-	if (original.exists()) {
-		CommitWorkingCopyOperation op= new CommitWorkingCopyOperation(this, force);
-		runOperation(op, monitor);
-	} else {
-		String encoding = this.getJavaProject().getOption(JavaCore.CORE_ENCODING, true);
-		String contents = this.getSource();
-		if (contents == null) return;
-		try {
-			byte[] bytes = encoding == null 
-				? contents.getBytes() 
-				: contents.getBytes(encoding);
-			ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
-			IFile originalRes = (IFile)original.getResource();
-			if (originalRes.exists()) {
-				originalRes.setContents(
-					stream, 
-					force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, 
-					null);
-			} else {
-				originalRes.create(
-					stream,
-					force,
-					monitor);
-			}
-		} catch (CoreException e) {
-			throw new JavaModelException(e);
-		} catch (UnsupportedEncodingException e) {
-			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
-		}
-	}
-}
-/**
- * Returns a new element info for this element.
- */
-protected OpenableElementInfo createElementInfo() {
-	return new WorkingCopyElementInfo();
-}
-/**
- * @see IWorkingCopy
- */
-public void destroy() {
-	if (--this.useCount > 0) {
-		if (SHARED_WC_VERBOSE) {
-			System.out.println("Decrementing use count of shared working copy " + this.toStringWithAncestors());//$NON-NLS-1$
-		}
-		return;
-	}
-	try {
-		DestroyWorkingCopyOperation op = new DestroyWorkingCopyOperation(this);
-		runOperation(op, null);
-	} catch (JavaModelException e) {
-		// do nothing
-	}
-}
-
-public boolean exists() {
-	// working copy always exists in the model until it is detroyed
-	return this.useCount != 0;
-}
-
-
-/**
- * Answers custom buffer factory
- */
-public IBufferFactory getBufferFactory(){
-
-	return this.bufferFactory;
-}
-
-/**
- * Working copies must be identical to be equal.
- *
- * @see Object#equals
- */
-public boolean equals(Object o) {
-	return this == o; 
-}
-
-	/**
-	 * Returns the info for this handle.  
-	 * If this element is not already open, it and all of its parents are opened.
-	 * Does not return null.
-	 * NOTE: BinaryType infos are NJOT rooted under JavaElementInfo.
-	 * @exception JavaModelException if the element is not present or not accessible
-	 */
-	public Object getElementInfo() throws JavaModelException {
-
-		JavaModelManager manager = JavaModelManager.getJavaModelManager();
-		boolean shouldPerformProblemDetection = false;
-		synchronized(manager){
-			Object info = manager.getInfo(this);
-			if (info == null) {
-				shouldPerformProblemDetection = true;
-			}
-		}
-		Object info = super.getElementInfo(); // will populate if necessary
-
-		// perform problem detection outside the JavaModelManager lock
-		if (this.problemRequestor != null && shouldPerformProblemDetection && this.problemRequestor.isActive()){
-			this.problemRequestor.beginReporting();
-			CompilationUnitProblemFinder.process(this, this.problemRequestor, null); 
-			this.problemRequestor.endReporting();
-		}		
-		return info;
-	}
-/**
- * @see IWorkingCopy
- */
-public IJavaElement getOriginal(IJavaElement workingCopyElement) {
-	//not a element contained in a compilation unit
-	int javaElementType = workingCopyElement.getElementType();
-	if (javaElementType < COMPILATION_UNIT || javaElementType == CLASS_FILE) {
-		return null;
-	}
-	if (workingCopyElement instanceof BinaryMember) {
-		return null;
-	}
-	IJavaElement parent = workingCopyElement.getParent();
-	ArrayList hierarchy = new ArrayList(4);
-	
-	while (parent.getElementType() > COMPILATION_UNIT) {
-		hierarchy.add(parent);
-		parent = parent.getParent();
-	}
-	if (parent.getElementType() == COMPILATION_UNIT) {
-		hierarchy.add(((ICompilationUnit)parent).getOriginalElement());
-	}
-	
-	ICompilationUnit cu = (ICompilationUnit) getOriginalElement();
-	if (javaElementType == COMPILATION_UNIT) {
-		parent = workingCopyElement;
-	}
-	if (((ICompilationUnit) parent).isWorkingCopy() && !((ICompilationUnit) parent).getOriginalElement().equals(cu)) {
-		return null;
-	}
-	switch (javaElementType) {
-		case PACKAGE_DECLARATION :
-			return cu.getPackageDeclaration(workingCopyElement.getElementName());
-		case IMPORT_CONTAINER :
-			return cu.getImportContainer();
-		case IMPORT_DECLARATION :
-			return cu.getImport(workingCopyElement.getElementName());
-		case TYPE :
-			if (hierarchy.size() == 1) {
-				return cu.getType(workingCopyElement.getElementName());
-			} else {
-				//inner type
-				return getOriginalType(hierarchy).getType(workingCopyElement.getElementName());
-			}
-		case METHOD :
-			IType type;
-			if (hierarchy.size() == 2) {
-				String typeName = ((IJavaElement) hierarchy.get(0)).getElementName();
-				type = cu.getType(typeName);
-			} else {
-				//inner type
-				type = getOriginalType(hierarchy);
-			}
-			return type.getMethod(workingCopyElement.getElementName(), ((IMethod) workingCopyElement).getParameterTypes());
-		case FIELD :
-			if (hierarchy.size() == 2) {
-				String typeName = ((IJavaElement) hierarchy.get(0)).getElementName();
-				type = cu.getType(typeName);
-			} else {
-				//inner type
-				type = getOriginalType(hierarchy);
-			}
-			return type.getField(workingCopyElement.getElementName());
-		case INITIALIZER :
-			if (hierarchy.size() == 2) {
-				String typeName = ((IJavaElement) hierarchy.get(0)).getElementName();
-				type = cu.getType(typeName);
-			} else {
-				//inner type
-				type = getOriginalType(hierarchy);
-			}
-			return type.getInitializer(((Initializer) workingCopyElement).getOccurrenceCount());
-		case COMPILATION_UNIT :
-			return cu;
-		default :
-			return null;
-	}
-}
-/**
- * @see IWorkingCopy
- */
-public IJavaElement getOriginalElement() {
-	return new CompilationUnit((IPackageFragment)getParent(), getElementName());
-}
-protected IType getOriginalType(ArrayList hierarchy) {
-	int size = hierarchy.size() - 1;
-	ICompilationUnit typeCU = (ICompilationUnit) hierarchy.get(size);
-	String typeName = ((IJavaElement) hierarchy.get(size - 1)).getElementName();
-	IType type = typeCU.getType(typeName);
-	size= size - 2;
-	while (size > -1) {
-		typeName = ((IJavaElement) hierarchy.get(size)).getElementName();
-		type = ((IType) type).getType(typeName);
-		size--;
-	}
-	return type;
-}
-
-/*
- * @see IJavaElement
- */
-public IResource getResource() {
-	return null;
-}
-
-/**
- * @see IWorkingCopy
- */
-public IJavaElement getSharedWorkingCopy(IProgressMonitor monitor, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException {
-	return this;
-}
-/**
- * Returns <code>null<code> - a working copy does not have an underlying resource.
- *
- * @see IJavaElement
- */
-public IResource getUnderlyingResource() throws JavaModelException {
-	return null;
-}
-/**
- * @see IWorkingCopy
- */
-public IJavaElement getWorkingCopy() throws JavaModelException {
-	return this;
-}
-/**
- * @see IWorkingCopy
- */
-public IJavaElement getWorkingCopy(IProgressMonitor monitor, IBufferFactory factory, IProblemRequestor problemRequestor) throws JavaModelException {
-	return this;
-}
-/**
- * @see IWorkingCopy
- */
-public boolean isBasedOn(IResource resource) {
-	if (resource.getType() != IResource.FILE) {
-		return false;
-	}
-	if (this.useCount == 0) {
-		return false;
-	}
-	try {
-		// if resource got deleted, then #getModificationStamp() will answer IResource.NULL_STAMP, which is always different from the cached
-		// timestamp
-		return ((CompilationUnitElementInfo) getElementInfo()).fTimestamp == ((IFile) resource).getModificationStamp();
-	} catch (JavaModelException e) {
-		return false;
-	}
-}
-/**
- * @see IWorkingCopy
- */
-public boolean isWorkingCopy() {
-	return true;
-}
-
-/**
- * @see IOpenable#makeConsistent(IProgressMonitor)
- */
-public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
-	if (!isConsistent()) { // TODO: this code isn't synchronized with regular opening of a working copy (should use getElementInfo)
-		super.makeConsistent(monitor);
-
-		if (monitor != null && monitor.isCanceled()) return;
-		if (this.problemRequestor != null && this.problemRequestor.isActive()){
-			this.problemRequestor.beginReporting();
-			CompilationUnitProblemFinder.process(this, this.problemRequestor, monitor); 
-			this.problemRequestor.endReporting();
-		}		
-	}
-}
-
-/**
- * @see IOpenable
- * @see IWorkingCopy
- *
- * @exception JavaModelException attempting to open a read only element for something other than navigation
- * 	or if this is a working copy being opened after it has been destroyed.
- */
-public void open(IProgressMonitor monitor) throws JavaModelException {
-	if (this.useCount == 0) { // was destroyed
-		throw newNotPresentException();
-	} else {
-		super.open(monitor);
-		
-		if (monitor != null && monitor.isCanceled()) return;
-		if (this.problemRequestor != null && this.problemRequestor.isActive()){
-			this.problemRequestor.beginReporting();
-			CompilationUnitProblemFinder.process(this, this.problemRequestor, monitor); 
-			this.problemRequestor.endReporting();
-		}		
-	}
-}
-/**
- * @see Openable
- */
-protected IBuffer openBuffer(IProgressMonitor pm) throws JavaModelException {
-
-	if (this.useCount == 0) throw newNotPresentException(); // was destroyed
-	
-	// create buffer - working copies may use custom buffer factory
-	IBuffer buffer = getBufferFactory().createBuffer(this);
-	if (buffer == null) return null;
-
-	// set the buffer source if needed
-	if (buffer.getCharacters() == null) {
-		ICompilationUnit original = (ICompilationUnit)this.getOriginalElement();
-		if (original.isOpen()) {
-			buffer.setContents(original.getSource());
-		} else {
-			IFile file = (IFile)original.getResource();
-			if (file == null || !file.exists()) {
-				// initialize buffer with empty contents
-				buffer.setContents(CharOperation.NO_CHAR);
-			} else {
-				buffer.setContents(Util.getResourceContentsAsCharArray(file));
-			}
-		}
-	}
-
-	// add buffer to buffer cache
-	this.getBufferManager().addBuffer(buffer);
-
-	// listen to buffer changes
-	buffer.addBufferChangedListener(this);
-
-	return buffer;	
-}
-/*
- * @see Openable#openParent(IProgressMonitor)
- */
-protected void openParent(IProgressMonitor pm) throws JavaModelException {
-	if (FIX_BUG25184) {
-		try {
-			super.openParent(pm);
-		} catch(JavaModelException e){
-			// allow parent to not exist for working copies defined outside classpath
-			if (!e.isDoesNotExist()){ 
-				throw e;
-			}
-		}
-	} else {
-		super.openParent(pm);
-	}
-}
-
-/**
- * @see IWorkingCopy
- */ 
-public IMarker[] reconcile() throws JavaModelException {
-	reconcile(false, null);
-	return null;
-}
-
-/**
- * @see IWorkingCopy
- */ 
-public void reconcile(boolean forceProblemDetection, IProgressMonitor monitor) throws JavaModelException {
-	ReconcileWorkingCopyOperation op = new ReconcileWorkingCopyOperation(this, forceProblemDetection);
-	runOperation(op, monitor);
-}
-
-/**
- * @see IWorkingCopy
- */
-public void restore() throws JavaModelException {
-
-	if (this.useCount == 0) throw newNotPresentException(); //was destroyed
-
-	CompilationUnit original = (CompilationUnit) getOriginalElement();
-	IBuffer buffer = this.getBuffer();
-	if (buffer == null) return;
-	buffer.setContents(original.getContents());
-	updateTimeStamp(original);
-	makeConsistent(null);
-}
-/*
- * @see JavaElement#rootedAt(IJavaProject)
- */
-public IJavaElement rootedAt(IJavaProject project) {
-	return
-		new WorkingCopy(
-			(IPackageFragment)((JavaElement)fParent).rootedAt(project), 
-			fName,
-			this.bufferFactory);
-
-}
-/**
- * @see IOpenable
- */
-public void save(IProgressMonitor pm, boolean force) throws JavaModelException {
-	if (isReadOnly()) {
-		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, this));
-	}
-	// no need to save the buffer for a working copy (this is a noop)
-	//IBuffer buf = getBuffer();
-	//if (buf != null) { // some Openables (like a JavaProject) don't have a buffer
-	//	buf.save(pm, force);
-		this.reconcile();   // not simply makeConsistent, also computes fine-grain deltas
-							// in case the working copy is being reconciled already (if not it would miss
-							// one iteration of deltas).
-	//}
-}
-
-/**
- * @private Debugging purposes
- */
-protected void toStringInfo(int tab, StringBuffer buffer, Object info) {
-	buffer.append(this.tabString(tab));
-	buffer.append("[Working copy] "); //$NON-NLS-1$
-	super.toStringInfo(0, buffer, info);
-}
-protected void updateTimeStamp(CompilationUnit original) throws JavaModelException {
-	long timeStamp =
-		((IFile) original.getResource()).getModificationStamp();
-	if (timeStamp == IResource.NULL_STAMP) {
-		throw new JavaModelException(
-			new JavaModelStatus(IJavaModelStatusConstants.INVALID_RESOURCE));
-	}
-	((CompilationUnitElementInfo) getElementInfo()).fTimestamp = timeStamp;
-}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/WorkingCopyElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/WorkingCopyElementInfo.java
deleted file mode 100644
index ab1ccac..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/WorkingCopyElementInfo.java
+++ /dev/null
@@ -1,17 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core;
-
-import org.eclipse.jdt.core.compiler.IProblem;
-
-public class WorkingCopyElementInfo extends CompilationUnitElementInfo {
-	IProblem[] problems;
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/XMLWriter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/XMLWriter.java
new file mode 100644
index 0000000..92390c7
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/XMLWriter.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+/**
+ * @since 3.0
+ */
+class XMLWriter extends PrintWriter {
+	/* constants */
+	private static final String XML_VERSION= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; //$NON-NLS-1$
+	private static void appendEscapedChar(StringBuffer buffer, char c) {
+		String replacement= getReplacement(c);
+		if (replacement != null) {
+			buffer.append('&');
+			buffer.append(replacement);
+			buffer.append(';');
+		} else {
+			buffer.append(c);
+		}
+	}
+	private static String getEscaped(String s) {
+		StringBuffer result= new StringBuffer(s.length() + 10);
+		for (int i= 0; i < s.length(); ++i)
+			appendEscapedChar(result, s.charAt(i));
+		return result.toString();
+	}
+	private static String getReplacement(char c) {
+		// Encode special XML characters into the equivalent character references.
+		// These five are defined by default for all XML documents.
+		switch (c) {
+			case '<' :
+				return "lt"; //$NON-NLS-1$
+			case '>' :
+				return "gt"; //$NON-NLS-1$
+			case '"' :
+				return "quot"; //$NON-NLS-1$
+			case '\'' :
+				return "apos"; //$NON-NLS-1$
+			case '&' :
+				return "amp"; //$NON-NLS-1$
+		}
+		return null;
+	}
+	private int tab;
+	public XMLWriter(Writer writer) {
+		super(writer);
+		tab= 0;
+		println(XML_VERSION);
+	}
+	public void endTag(String name, boolean insertTab) {
+		tab--;
+		printTag('/' + name, null, insertTab, true, false);
+	}
+	private void printTabulation() {
+		for (int i= 0; i < tab; i++)
+			super.print('\t');
+	}
+	public void printTag(String name, HashMap parameters, boolean insertTab, boolean insertNewLine, boolean closeTag) {
+		StringBuffer sb= new StringBuffer();
+		sb.append("<"); //$NON-NLS-1$
+		sb.append(name);
+		if (parameters != null) {
+			for (Enumeration enum= Collections.enumeration(parameters.keySet()); enum.hasMoreElements();) {
+				sb.append(" "); //$NON-NLS-1$
+				String key= (String) enum.nextElement();
+				sb.append(key);
+				sb.append("=\""); //$NON-NLS-1$
+				sb.append(getEscaped(String.valueOf(parameters.get(key))));
+				sb.append("\""); //$NON-NLS-1$
+			}
+		}
+		if (closeTag) {
+			sb.append("/>"); //$NON-NLS-1$
+		} else {
+			sb.append(">"); //$NON-NLS-1$
+		}
+		if (insertTab) {
+			printTabulation();
+		}
+		if (insertNewLine) {
+			println(sb.toString());
+		} else {
+			print(sb.toString());
+		}
+	}
+	public void startTag(String name, boolean insertTab) {
+		printTag(name, null, insertTab, true, false);
+		tab++;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
index cf56d50..4c2d3d3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
@@ -20,7 +20,8 @@
 import org.eclipse.jdt.internal.compiler.ClassFile;
 import org.eclipse.jdt.internal.compiler.Compiler;
 import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.Util;
 
 import java.io.*;
 import java.util.*;
@@ -76,47 +77,54 @@
 
 	SourceFile compilationUnit = (SourceFile) result.getCompilationUnit(); // go directly back to the sourceFile
 	if (!workQueue.isCompiled(compilationUnit)) {
+		workQueue.finished(compilationUnit);
+
 		try {
-			workQueue.finished(compilationUnit);
 			updateProblemsFor(compilationUnit, result); // record compilation problems before potentially adding duplicate errors
 			updateTasksFor(compilationUnit, result); // record tasks
-
-			String typeLocator = compilationUnit.typeLocator();
-			ClassFile[] classFiles = result.getClassFiles();
-			int length = classFiles.length;
-			ArrayList duplicateTypeNames = null;
-			ArrayList definedTypeNames = new ArrayList(length);
-			for (int i = 0; i < length; i++) {
-				ClassFile classFile = classFiles[i];
-				char[][] compoundName = classFile.getCompoundName();
-				char[] typeName = compoundName[compoundName.length - 1];
-				boolean isNestedType = CharOperation.contains('$', typeName);
-
-				// Look for a possible collision, if one exists, report an error but do not write the class file
-				if (isNestedType) {
-					String qualifiedTypeName = new String(classFile.outerMostEnclosingClassFile().fileName());
-					if (newState.isDuplicateLocator(qualifiedTypeName, typeLocator))
-						continue;
-				} else {
-					String qualifiedTypeName = new String(classFile.fileName()); // the qualified type name "p1/p2/A"
-					if (newState.isDuplicateLocator(qualifiedTypeName, typeLocator)) {
-						if (duplicateTypeNames == null)
-							duplicateTypeNames = new ArrayList();
-						duplicateTypeNames.add(compoundName);
-						createErrorFor(compilationUnit.resource, Util.bind("build.duplicateClassFile", new String(typeName))); //$NON-NLS-1$
-						continue;
-					}
-					newState.recordLocatorForType(qualifiedTypeName, typeLocator);
-				}
-				definedTypeNames.add(writeClassFile(classFile, compilationUnit.sourceLocation.binaryFolder, !isNestedType));
-			}
-
-			finishedWith(typeLocator, result, compilationUnit.getMainTypeName(), definedTypeNames, duplicateTypeNames);
-			notifier.compiled(compilationUnit);
 		} catch (CoreException e) {
-			Util.log(e, "JavaBuilder handling CoreException"); //$NON-NLS-1$
-			createErrorFor(compilationUnit.resource, Util.bind("build.inconsistentClassFile")); //$NON-NLS-1$
+			throw internalException(e);
 		}
+
+		String typeLocator = compilationUnit.typeLocator();
+		ClassFile[] classFiles = result.getClassFiles();
+		int length = classFiles.length;
+		ArrayList duplicateTypeNames = null;
+		ArrayList definedTypeNames = new ArrayList(length);
+		for (int i = 0; i < length; i++) {
+			ClassFile classFile = classFiles[i];
+			char[][] compoundName = classFile.getCompoundName();
+			char[] typeName = compoundName[compoundName.length - 1];
+			boolean isNestedType = CharOperation.contains('$', typeName);
+
+			// Look for a possible collision, if one exists, report an error but do not write the class file
+			if (isNestedType) {
+				String qualifiedTypeName = new String(classFile.outerMostEnclosingClassFile().fileName());
+				if (newState.isDuplicateLocator(qualifiedTypeName, typeLocator))
+					continue;
+			} else {
+				String qualifiedTypeName = new String(classFile.fileName()); // the qualified type name "p1/p2/A"
+				if (newState.isDuplicateLocator(qualifiedTypeName, typeLocator)) {
+					if (duplicateTypeNames == null)
+						duplicateTypeNames = new ArrayList();
+					duplicateTypeNames.add(compoundName);
+					createProblemFor(compilationUnit.resource, Util.bind("build.duplicateClassFile", new String(typeName)), JavaCore.ERROR); //$NON-NLS-1$
+					continue;
+				}
+				newState.recordLocatorForType(qualifiedTypeName, typeLocator);
+			}
+			try {
+				definedTypeNames.add(writeClassFile(classFile, compilationUnit, !isNestedType));
+			} catch (CoreException e) {
+				Util.log(e, "JavaBuilder handling CoreException"); //$NON-NLS-1$
+				if (e.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS)
+					createProblemFor(compilationUnit.resource, Util.bind("build.classFileCollision", e.getMessage()), JavaCore.ERROR); //$NON-NLS-1$
+				else
+					createProblemFor(compilationUnit.resource, Util.bind("build.inconsistentClassFile"), JavaCore.ERROR); //$NON-NLS-1$
+			}
+		}
+		finishedWith(typeLocator, result, compilationUnit.getMainTypeName(), definedTypeNames, duplicateTypeNames);
+		notifier.compiled(compilationUnit);
 	}
 }
 
@@ -136,21 +144,23 @@
 * if they are affected by the changes.
 */
 protected void compile(SourceFile[] units) {
-	int toDo = units.length;
-	if (this.compiledAllAtOnce = toDo <= MAX_AT_ONCE) {
+	int unitsLength = units.length;
+
+	this.compiledAllAtOnce = unitsLength <= MAX_AT_ONCE;
+	if (this.compiledAllAtOnce) {
 		// do them all now
 		if (JavaBuilder.DEBUG)
-			for (int i = 0; i < toDo; i++)
+			for (int i = 0; i < unitsLength; i++)
 				System.out.println("About to compile " + units[i].typeLocator()); //$NON-NLS-1$
 		compile(units, null);
 	} else {
 		int i = 0;
 		boolean compilingFirstGroup = true;
-		while (i < toDo) {
-			int doNow = toDo < MAX_AT_ONCE ? toDo : MAX_AT_ONCE;
+		while (i < unitsLength) {
+			int doNow = unitsLength < MAX_AT_ONCE ? unitsLength : MAX_AT_ONCE;
 			int index = 0;
 			SourceFile[] toCompile = new SourceFile[doNow];
-			while (i < toDo && index < doNow) {
+			while (i < unitsLength && index < doNow) {
 				// Although it needed compiling when this method was called, it may have
 				// already been compiled when it was referenced by another unit.
 				SourceFile unit = units[i++];
@@ -162,7 +172,7 @@
 			}
 			if (index < doNow)
 				System.arraycopy(toCompile, 0, toCompile = new SourceFile[index], 0, index);
-			SourceFile[] additionalUnits = new SourceFile[toDo - i];
+			SourceFile[] additionalUnits = new SourceFile[unitsLength - i];
 			System.arraycopy(units, i, additionalUnits, 0, additionalUnits.length);
 			compilingFirstGroup = false;
 			compile(toCompile, additionalUnits);
@@ -204,13 +214,11 @@
 	notifier.checkCancel();
 }
 
-protected void createErrorFor(IResource resource, String message) {
+protected void createProblemFor(IResource resource, String message, String problemSeverity) {
 	try {
 		IMarker marker = resource.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
-		int severity = IMarker.SEVERITY_ERROR;
-		if (message.equals(Util.bind("build.duplicateResource"))) //$NON-NLS-1$
-			if (JavaCore.WARNING.equals(javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE, true)))
-				severity = IMarker.SEVERITY_WARNING;
+		int severity = problemSeverity.equals(JavaCore.WARNING) ? IMarker.SEVERITY_WARNING : IMarker.SEVERITY_ERROR;
+
 		marker.setAttributes(
 			new String[] {IMarker.MESSAGE, IMarker.SEVERITY, IMarker.CHAR_START, IMarker.CHAR_END},
 			new Object[] {message, new Integer(severity), new Integer(0), new Integer(1)});
@@ -219,7 +227,7 @@
 	}
 }
 
-protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName, ArrayList definedTypeNames, ArrayList duplicateTypeNames) throws CoreException {
+protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName, ArrayList definedTypeNames, ArrayList duplicateTypeNames) {
 	if (duplicateTypeNames == null) {
 		newState.record(sourceLocator, result.qualifiedReferences, result.simpleNameReferences, mainTypeName, definedTypeNames);
 		return;
@@ -398,7 +406,7 @@
 				new Object[] { 
 					task.getMessage(),
 					new Integer(priority),
-					new Boolean(false),
+					org.eclipse.jdt.internal.compiler.util.Util.toBoolean(false),
 					new Integer(task.getSourceStart()),
 					new Integer(task.getSourceEnd() + 1),
 					new Integer(task.getSourceLineNumber()),
@@ -423,22 +431,23 @@
 	storeTasksFor(sourceFile, tasks);
 }
 
-protected char[] writeClassFile(ClassFile classFile, IContainer outputFolder, boolean isSecondaryType) throws CoreException {
+protected char[] writeClassFile(ClassFile classFile, SourceFile compilationUnit, boolean isSecondaryType) throws CoreException {
 	String fileName = new String(classFile.fileName()); // the qualified type name "p1/p2/A"
 	IPath filePath = new Path(fileName);
+	IContainer outputFolder = compilationUnit.sourceLocation.binaryFolder; 
 	IContainer container = outputFolder;
 	if (filePath.segmentCount() > 1) {
 		container = createFolder(filePath.removeLastSegments(1), outputFolder);
 		filePath = new Path(filePath.lastSegment());
 	}
 
-	IFile file = container.getFile(filePath.addFileExtension(JavaBuilder.CLASS_EXTENSION));
-	writeClassFileBytes(classFile.getBytes(), file, fileName, isSecondaryType);
+	IFile file = container.getFile(filePath.addFileExtension(SuffixConstants.EXTENSION_class));
+	writeClassFileBytes(classFile.getBytes(), file, fileName, isSecondaryType, compilationUnit.updateClassFile);
 	// answer the name of the class file as in Y or Y$M
 	return filePath.lastSegment().toCharArray();
 }
 
-protected void writeClassFileBytes(byte[] bytes, IFile file, String qualifiedFileName, boolean isSecondaryType) throws CoreException {
+protected void writeClassFileBytes(byte[] bytes, IFile file, String qualifiedFileName, boolean isSecondaryType, boolean updateClassFile) throws CoreException {
 	if (file.exists()) {
 		// Deal with shared output folders... last one wins... no collision cases detected
 		if (JavaBuilder.DEBUG)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
index 8bed0ac..c055344 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
@@ -15,7 +15,7 @@
 
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.internal.core.JavaModelManager;
-import org.eclipse.jdt.internal.core.Util;
+import org.eclipse.jdt.internal.core.util.Util;
 
 import java.util.*;
 
@@ -32,7 +32,7 @@
 
 	try {
 		notifier.subTask(Util.bind("build.cleaningOutput")); //$NON-NLS-1$
-		JavaModelManager.getJavaModelManager().deltaProcessor.addForRefresh(javaBuilder.javaProject);
+		JavaModelManager.getJavaModelManager().getDeltaProcessor().addForRefresh(javaBuilder.javaProject);
 		JavaBuilder.removeProblemsAndTasksFor(javaBuilder.currentProject);
 		cleanOutputFolders();
 		notifier.updateProgressDelta(0.1f);
@@ -75,7 +75,7 @@
 					}
 					switch(proxy.getType()) {
 						case IResource.FILE :
-							if (Util.isJavaFileName(proxy.getName())) {
+							if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(proxy.getName())) {
 								if (resource == null)
 									resource = proxy.requestResource();
 								sourceFiles.add(new SourceFile((IFile) resource, sourceLocation, encoding));
@@ -106,11 +106,23 @@
 				if (!visited.contains(outputFolder)) {
 					visited.add(outputFolder);
 					IResource[] members = outputFolder.members(); 
-					for (int j = 0, m = members.length; j < m; j++)
-						members[j].delete(IResource.FORCE, null);
+					for (int j = 0, m = members.length; j < m; j++) {
+						IResource member = members[j];
+						if (!member.isDerived()) {
+							member.accept(
+								new IResourceVisitor() {
+									public boolean visit(IResource resource) throws CoreException {
+										resource.setDerived(true);
+										return resource.getType() != IResource.FILE;
+									}
+								}
+							);
+						}
+						member.delete(IResource.FORCE, null);
+					}
 				}
 				notifier.checkCancel();
-				copyExtraResourcesBack(sourceLocation, deleteAll);
+				copyExtraResourcesBack(sourceLocation, true);
 			} else {
 				boolean isOutputFolder = sourceLocation.sourceFolder.equals(sourceLocation.binaryFolder);
 				final char[][] exclusionPatterns =
@@ -126,7 +138,7 @@
 								if (Util.isExcluded(resource, exclusionPatterns)) return false;
 							}
 							if (proxy.getType() == IResource.FILE) {
-								if (Util.isClassFileName(proxy.getName())) {
+								if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(proxy.getName())) {
 									if (resource == null)
 										resource = proxy.requestResource();
 									resource.delete(IResource.FORCE, null);
@@ -150,7 +162,7 @@
 		for (int i = 0, l = sourceLocations.length; i < l; i++) {
 			ClasspathMultiDirectory sourceLocation = sourceLocations[i];
 			if (sourceLocation.hasIndependentOutputFolder)
-				copyExtraResourcesBack(sourceLocation, deleteAll);
+				copyExtraResourcesBack(sourceLocation, false);
 			else if (!sourceLocation.sourceFolder.equals(sourceLocation.binaryFolder))
 				copyPackages(sourceLocation); // output folder is different from source folder
 			notifier.checkCancel();
@@ -173,7 +185,8 @@
 				IResource resource = null;
 				switch(proxy.getType()) {
 					case IResource.FILE :
-						if (Util.isJavaFileName(proxy.getName()) || Util.isClassFileName(proxy.getName())) return false;
+						if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(proxy.getName()) ||
+							org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(proxy.getName())) return false;
 
 						resource = proxy.requestResource();
 						if (javaBuilder.filterExtraResource(resource)) return false;
@@ -184,7 +197,12 @@
 						IResource copiedResource = outputFolder.getFile(partialPath);
 						if (copiedResource.exists()) {
 							if (deletedAll) {
-								createErrorFor(resource, Util.bind("build.duplicateResource")); //$NON-NLS-1$
+								IResource originalResource = findOriginalResource(partialPath);
+								String id = originalResource.getFullPath().removeFirstSegments(1).toString();
+								createProblemFor(
+									resource,
+									Util.bind("build.duplicateResource", id), //$NON-NLS-1$
+									javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE, true));
 								return false;
 							}
 							copiedResource.delete(IResource.FORCE, null); // last one wins
@@ -237,6 +255,17 @@
 	);
 }
 
+protected IResource findOriginalResource(IPath partialPath) {
+	for (int i = 0, l = sourceLocations.length; i < l; i++) {
+		ClasspathMultiDirectory sourceLocation = sourceLocations[i];
+		if (sourceLocation.hasIndependentOutputFolder) {
+			IResource originalResource = sourceLocation.sourceFolder.getFile(partialPath);
+			if (originalResource.exists()) return originalResource;
+		}
+	}
+	return null;
+}
+
 public String toString() {
 	return "batch image builder for:\n\tnew state: " + newState; //$NON-NLS-1$
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BuildNotifier.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BuildNotifier.java
index 14f9640..62ebb34 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BuildNotifier.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/BuildNotifier.java
@@ -15,7 +15,7 @@
 
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
-import org.eclipse.jdt.internal.core.Util;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public class BuildNotifier {
 
@@ -256,9 +256,9 @@
 	}
 }
 
-public void updateProgress(float percentComplete) {
-	if (percentComplete > this.percentComplete) {
-		this.percentComplete = Math.min(percentComplete, 1.0f);
+public void updateProgress(float newPercentComplete) {
+	if (newPercentComplete > this.percentComplete) {
+		this.percentComplete = Math.min(newPercentComplete, 1.0f);
 		int work = Math.round(this.percentComplete * this.totalWork);
 		if (work > this.workDone) {
 			if (monitor != null)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
index 4b2242c..155e977 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
@@ -15,7 +15,6 @@
 
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
-import org.eclipse.jdt.internal.core.Util;
 import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
 
 class ClasspathDirectory extends ClasspathLocation {
@@ -46,13 +45,13 @@
 
 	try {
 		IResource container = binaryFolder.findMember(qualifiedPackageName); // this is a case-sensitive check
-		if (container instanceof IContainer) {
+		if (container instanceof IContainer && !isExcluded(container)) {
 			IResource[] members = ((IContainer) container).members();
 			dirList = new String[members.length];
 			int index = 0;
 			for (int i = 0, l = members.length; i < l; i++) {
 				IResource m = members[i];
-				if (m.getType() == IResource.FILE && Util.isClassFileName(m.getName()))
+				if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(m.getName()))
 					// add exclusion pattern check here if we want to hide .class files
 					dirList[index++] = m.getName();
 			}
@@ -62,6 +61,7 @@
 			return dirList;
 		}
 	} catch(CoreException ignored) {
+		// ignore
 	}
 	directoryCache.put(qualifiedPackageName, missingPackageHolder);
 	return null;
@@ -90,7 +90,22 @@
 	try {
 		ClassFileReader reader = ClassFileReader.read(binaryLocation + qualifiedBinaryFileName);
 		if (reader != null) return new NameEnvironmentAnswer(reader);
-	} catch (Exception e) {} // treat as if class file is missing
+	} catch (Exception e) {
+		// handle the case when the project is the output folder and the top-level package is a linked folder
+		if (binaryFolder instanceof IProject) {
+			IResource file = binaryFolder.findMember(qualifiedBinaryFileName);
+			if (file instanceof IFile) {
+				IPath location = file.getLocation();
+				if (location != null) {
+					try {
+						ClassFileReader reader = ClassFileReader.read(location.toString());
+						if (reader != null) return new NameEnvironmentAnswer(reader);
+					} catch (Exception ignored) { // treat as if class file is missing
+					}
+				}
+			}
+		}
+	}
 	return null;
 }
 
@@ -98,6 +113,10 @@
 	return binaryFolder.getProjectRelativePath();
 }
 
+protected boolean isExcluded(IResource resource) {
+	return false;
+}
+
 public boolean isOutputFolder() {
 	return isOutputFolder;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
index 9670171..1ceba9f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
@@ -7,6 +7,7 @@
  * 
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ *     Tal Lev-Ami - added package cache for zip files
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.builder;
 
@@ -16,6 +17,7 @@
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
 import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.core.util.SimpleSet;
 
 import java.io.*;
 import java.util.*;
@@ -23,16 +25,66 @@
 
 public class ClasspathJar extends ClasspathLocation {
 
+static class PackageCacheEntry {
+	long lastModified;
+	long fileSize;
+	SimpleSet packageSet;
+	
+	PackageCacheEntry(long lastModified, long fileSize, SimpleSet packageSet) {
+		this.lastModified = lastModified;
+		this.fileSize = fileSize;
+		this.packageSet = packageSet;
+	}
+}
+
+static SimpleLookupTable PackageCache = new SimpleLookupTable();
+
+/**
+ * Calculate and cache the package list available in the zipFile.
+ * @param zipFile The zip file to use
+ * @return A SimpleSet with the all the package names in the zipFile.
+ */
+static SimpleSet findPackageSet(ZipFile zipFile) {
+	String zipFileName = zipFile.getName();
+	File zipFileObject = new File(zipFileName);
+	long lastModified = zipFileObject.lastModified();
+	long fileSize = zipFileObject.length();
+	PackageCacheEntry cacheEntry = (PackageCacheEntry) PackageCache.get(zipFileName);
+	if (cacheEntry != null && cacheEntry.lastModified == lastModified && cacheEntry.fileSize == fileSize)
+		return cacheEntry.packageSet;
+
+	SimpleSet packageSet = new SimpleSet(41);
+	packageSet.add(""); //$NON-NLS-1$
+	nextEntry : for (Enumeration e = zipFile.entries(); e.hasMoreElements(); ) {
+		String fileName = ((ZipEntry) e.nextElement()).getName();
+
+		// add the package name & all of its parent packages
+		int last = fileName.lastIndexOf('/');
+		while (last > 0) {
+			// extract the package name
+			String packageName = fileName.substring(0, last);
+			if (packageSet.includes(packageName))
+				continue nextEntry;
+			packageSet.add(packageName);
+			last = packageName.lastIndexOf('/');
+		}
+	}
+
+	PackageCache.put(zipFileName, new PackageCacheEntry(lastModified, fileSize, packageSet));
+	return packageSet;
+}
+
+
 String zipFilename; // keep for equals
 IFile resource;
 ZipFile zipFile;
 boolean closeZipFileAtEnd;
-SimpleLookupTable packageCache;
+SimpleSet knownPackageNames;
 
 ClasspathJar(String zipFilename) {
 	this.zipFilename = zipFilename;
 	this.zipFile = null;
-	this.packageCache = null;
+	this.knownPackageNames = null;
 }
 
 ClasspathJar(IFile resource) {
@@ -40,22 +92,25 @@
 	IPath location = resource.getLocation();
 	this.zipFilename = location != null ? location.toString() : ""; //$NON-NLS-1$
 	this.zipFile = null;
-	this.packageCache = null;
+	this.knownPackageNames = null;
 }
 
 public ClasspathJar(ZipFile zipFile) {
 	this.zipFilename = zipFile.getName();
 	this.zipFile = zipFile;
 	this.closeZipFileAtEnd = false;
-	this.packageCache = null;
+	this.knownPackageNames = null;
 }
 
 public void cleanup() {
 	if (zipFile != null && this.closeZipFileAtEnd) {
-		try { zipFile.close(); } catch(IOException e) {}
+		try {
+			zipFile.close();
+		} catch(IOException e) { // ignore it
+		}
 		this.zipFile = null;
 	}
-	this.packageCache = null;
+	this.knownPackageNames = null;
 }
 
 public boolean equals(Object o) {
@@ -71,7 +126,8 @@
 	try {
 		ClassFileReader reader = ClassFileReader.read(zipFile, qualifiedBinaryFileName);
 		if (reader != null) return new NameEnvironmentAnswer(reader);
-	} catch (Exception e) {} // treat as if class file is missing
+	} catch (Exception e) { // treat as if class file is missing
+	}
 	return null;
 }
 
@@ -81,34 +137,19 @@
 }
 
 public boolean isPackage(String qualifiedPackageName) {
-	if (packageCache != null)
-		return packageCache.containsKey(qualifiedPackageName);
+	if (knownPackageNames != null)
+		return knownPackageNames.includes(qualifiedPackageName);
 
-	this.packageCache = new SimpleLookupTable(41);
-	packageCache.put("", ""); //$NON-NLS-1$ //$NON-NLS-2$
 	try {
 		if (this.zipFile == null) {
 			this.zipFile = new ZipFile(zipFilename);
 			this.closeZipFileAtEnd = true;
 		}
-
-		nextEntry : for (Enumeration e = zipFile.entries(); e.hasMoreElements(); ) {
-			String fileName = ((ZipEntry) e.nextElement()).getName();
-	
-			// add the package name & all of its parent packages
-			int last = fileName.lastIndexOf('/');
-			while (last > 0) {
-				// extract the package name
-				String packageName = fileName.substring(0, last);
-				if (packageCache.containsKey(packageName))
-					continue nextEntry;
-				packageCache.put(packageName, packageName);
-				last = packageName.lastIndexOf('/');
-			}
-		}
-		return packageCache.containsKey(qualifiedPackageName);
-	} catch(Exception e) {}
-	return false;
+		this.knownPackageNames = findPackageSet(zipFile);
+	} catch(Exception e) {
+		this.knownPackageNames = new SimpleSet(); // assume for this build the zipFile is empty
+	}
+	return knownPackageNames.includes(qualifiedPackageName);
 }
 
 public String toString() {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
index 7282bbb..cb7cc27 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
@@ -43,10 +43,10 @@
 
 public abstract boolean isPackage(String qualifiedPackageName);
 
-// free anything which is not required when the state is saved
 public void cleanup() {
+	// free anything which is not required when the state is saved
 }
-// reset any internal caches before another compile loop starts
 public void reset() {
+	// reset any internal caches before another compile loop starts
 }
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
index fe66631..ca87205 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiDirectory.java
@@ -10,8 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.builder;
 
-import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.*;
+
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.core.util.Util;
 
 class ClasspathMultiDirectory extends ClasspathDirectory {
 
@@ -40,6 +42,12 @@
 		&& CharOperation.equals(exclusionPatterns, md.exclusionPatterns);
 } 
 
+protected boolean isExcluded(IResource resource) {
+	if (this.exclusionPatterns != null && this.sourceFolder.equals(this.binaryFolder))
+		return Util.isExcluded(resource, this.exclusionPatterns);
+	return false;
+}
+
 public String toString() {
 	return "Source classpath directory " + sourceFolder.getFullPath().toString() + //$NON-NLS-1$
 		" with binary directory " + binaryFolder.getFullPath().toString(); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
index 2ecf5fb..3b87aee 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
@@ -17,8 +17,10 @@
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.classfmt.*;
-import org.eclipse.jdt.internal.core.Util;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.core.util.Util;
 
 import java.io.*;
 import java.util.*;
@@ -30,8 +32,8 @@
 
 protected ArrayList sourceFiles;
 protected ArrayList previousSourceFiles;
-protected ArrayList qualifiedStrings;
-protected ArrayList simpleStrings;
+protected StringSet qualifiedStrings;
+protected StringSet simpleStrings;
 protected SimpleLookupTable secondaryTypesToRemove;
 protected boolean hasStructuralChanges;
 protected int compileLoop;
@@ -45,8 +47,8 @@
 
 	this.sourceFiles = new ArrayList(33);
 	this.previousSourceFiles = null;
-	this.qualifiedStrings = new ArrayList(33);
-	this.simpleStrings = new ArrayList(33);
+	this.qualifiedStrings = new StringSet(3);
+	this.simpleStrings = new StringSet(3);
 	this.hasStructuralChanges = false;
 	this.compileLoop = 0;
 }
@@ -79,9 +81,10 @@
 		for (int i = 0, l = valueTable.length; i < l; i++) {
 			IResourceDelta delta = (IResourceDelta) valueTable[i];
 			if (delta != null) {
-				ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[]) javaBuilder.binaryLocationsPerProject.get(keyTable[i]);
+				IProject p = (IProject) keyTable[i];
+				ClasspathLocation[] classFoldersAndJars = (ClasspathLocation[]) javaBuilder.binaryLocationsPerProject.get(p);
 				if (classFoldersAndJars != null)
-					if (!findAffectedSourceFiles(delta, classFoldersAndJars)) return false;
+					if (!findAffectedSourceFiles(delta, classFoldersAndJars, p)) return false;
 			}
 		}
 		notifier.updateProgressDelta(0.10f);
@@ -116,8 +119,8 @@
 	} catch (AbortIncrementalBuildException e) {
 		// abort the incremental build and let the batch builder handle the problem
 		if (JavaBuilder.DEBUG)
-			System.out.println("ABORTING incremental build... cannot find " + e.qualifiedTypeName + //$NON-NLS-1$
-				". Could have been renamed inside its existing source file."); //$NON-NLS-1$
+			System.out.println("ABORTING incremental build... problem with " + e.qualifiedTypeName + //$NON-NLS-1$
+				". Likely renamed inside its existing source file."); //$NON-NLS-1$
 		return false;
 	} catch (CoreException e) {
 		throw internalException(e);
@@ -128,16 +131,16 @@
 }
 
 protected void addAffectedSourceFiles() {
-	if (qualifiedStrings.isEmpty() && simpleStrings.isEmpty()) return;
+	if (qualifiedStrings.elementSize == 0 && simpleStrings.elementSize == 0) return;
 
 	// the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are just 'X'
 	char[][][] qualifiedNames = ReferenceCollection.internQualifiedNames(qualifiedStrings);
 	// if a well known qualified name was found then we can skip over these
-	if (qualifiedNames.length < qualifiedStrings.size())
+	if (qualifiedNames.length < qualifiedStrings.elementSize)
 		qualifiedNames = null;
 	char[][] simpleNames = ReferenceCollection.internSimpleNames(simpleStrings);
 	// if a well known name was found then we can skip over these
-	if (simpleNames.length < simpleStrings.size())
+	if (simpleNames.length < simpleStrings.elementSize)
 		simpleNames = null;
 
 	Object[] keyTable = newState.references.keyTable;
@@ -172,26 +175,22 @@
 	}
 }
 
-protected void addDependentsOf(IPath path, boolean hasStructuralChanges) {
-	if (hasStructuralChanges) {
+protected void addDependentsOf(IPath path, boolean isStructuralChange) {
+	if (isStructuralChange && !this.hasStructuralChanges) {
 		newState.tagAsStructurallyChanged();
 		this.hasStructuralChanges = true;
 	}
 	// the qualifiedStrings are of the form 'p1/p2' & the simpleStrings are just 'X'
 	path = path.setDevice(null);
 	String packageName = path.removeLastSegments(1).toString();
-	if (!qualifiedStrings.contains(packageName))
-		qualifiedStrings.add(packageName);
+	qualifiedStrings.add(packageName);
 	String typeName = path.lastSegment();
 	int memberIndex = typeName.indexOf('$');
 	if (memberIndex > 0)
 		typeName = typeName.substring(0, memberIndex);
-	if (!simpleStrings.contains(typeName)) {
-		if (JavaBuilder.DEBUG)
-			System.out.println("  will look for dependents of " //$NON-NLS-1$
-				+ typeName + " in " + packageName); //$NON-NLS-1$
-		simpleStrings.add(typeName);
-	}
+	if (simpleStrings.add(typeName) && JavaBuilder.DEBUG)
+		System.out.println("  will look for dependents of " //$NON-NLS-1$
+			+ typeName + " in " + packageName); //$NON-NLS-1$
 }
 
 protected void cleanUp() {
@@ -206,7 +205,7 @@
 	this.compileLoop = 0;
 }
 
-protected boolean findAffectedSourceFiles(IResourceDelta delta, ClasspathLocation[] classFoldersAndJars) {
+protected boolean findAffectedSourceFiles(IResourceDelta delta, ClasspathLocation[] classFoldersAndJars, IProject prereqProject) {
 	for (int i = 0, l = classFoldersAndJars.length; i < l; i++) {
 		ClasspathLocation bLocation = classFoldersAndJars[i];
 		// either a .class file folder or a zip/jar file
@@ -227,8 +226,11 @@
 					}
 					int segmentCount = binaryDelta.getFullPath().segmentCount();
 					IResourceDelta[] children = binaryDelta.getAffectedChildren(); // .class files from class folder
+					StringSet structurallyChangedTypes = null;
+					if (bLocation.isOutputFolder())
+						structurallyChangedTypes = this.newState.getStructurallyChangedTypes(javaBuilder.getLastState(prereqProject));
 					for (int j = 0, m = children.length; j < m; j++)
-						findAffectedSourceFiles(children[j], segmentCount);
+						findAffectedSourceFiles(children[j], segmentCount, structurallyChangedTypes);
 					notifier.checkCancel();
 				}
 			}
@@ -237,7 +239,7 @@
 	return true;
 }
 
-protected void findAffectedSourceFiles(IResourceDelta binaryDelta, int segmentCount) {
+protected void findAffectedSourceFiles(IResourceDelta binaryDelta, int segmentCount, StringSet structurallyChangedTypes) {
 	// When a package becomes a type or vice versa, expect 2 deltas,
 	// one on the folder & one on the class file
 	IResource resource = binaryDelta.getResource();
@@ -273,11 +275,11 @@
 				case IResourceDelta.CHANGED :
 					IResourceDelta[] children = binaryDelta.getAffectedChildren();
 					for (int i = 0, l = children.length; i < l; i++)
-						findAffectedSourceFiles(children[i], segmentCount);
+						findAffectedSourceFiles(children[i], segmentCount, structurallyChangedTypes);
 			}
 			return;
 		case IResource.FILE :
-			if (Util.isClassFileName(resource.getName())) {
+			if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(resource.getName())) {
 				IPath typePath = resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
 				switch (binaryDelta.getKind()) {
 					case IResourceDelta.ADDED :
@@ -289,6 +291,8 @@
 					case IResourceDelta.CHANGED :
 						if ((binaryDelta.getFlags() & IResourceDelta.CONTENT) == 0)
 							return; // skip it since it really isn't changed
+						if (structurallyChangedTypes != null && !structurallyChangedTypes.includes(typePath.toString()))
+							return; // skip since it wasn't a structural change
 						if (JavaBuilder.DEBUG)
 							System.out.println("Found changed class file " + typePath); //$NON-NLS-1$
 						addDependentsOf(typePath, false);
@@ -310,7 +314,6 @@
 					findSourceFiles(children[j], md, segmentCount);
 		} else {
 			IResourceDelta sourceDelta = delta.findMember(md.sourceFolder.getProjectRelativePath());
-
 			if (sourceDelta != null) {
 				if (sourceDelta.getKind() == IResourceDelta.REMOVED) {
 					if (JavaBuilder.DEBUG)
@@ -319,8 +322,18 @@
 				}
 				int segmentCount = sourceDelta.getFullPath().segmentCount();
 				IResourceDelta[] children = sourceDelta.getAffectedChildren();
-				for (int j = 0, m = children.length; j < m; j++)
-					findSourceFiles(children[j], md, segmentCount);
+				try {
+					for (int j = 0, m = children.length; j < m; j++)
+						findSourceFiles(children[j], md, segmentCount);
+				} catch (org.eclipse.core.internal.resources.ResourceException e) {
+					// catch the case that a package has been renamed and collides on disk with an as-yet-to-be-deleted package
+					if (e.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) {
+						if (JavaBuilder.DEBUG)
+							System.out.println("ABORTING incremental build... found renamed package"); //$NON-NLS-1$
+						return false;
+					}
+					throw e; // rethrow
+				}
 			}
 		}
 		notifier.checkCancel();
@@ -375,14 +388,14 @@
 			return;
 		case IResource.FILE :
 			String resourceName = resource.getName();
-			if (Util.isJavaFileName(resourceName)) {
+			if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(resourceName)) {
 				IPath typePath = resource.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
 				String typeLocator = resource.getProjectRelativePath().toString();
 				switch (sourceDelta.getKind()) {
 					case IResourceDelta.ADDED :
 						if (JavaBuilder.DEBUG)
 							System.out.println("Compile this added source file " + typeLocator); //$NON-NLS-1$
-						sourceFiles.add(new SourceFile((IFile) resource, md, encoding));
+						sourceFiles.add(new SourceFile((IFile) resource, md, encoding, true));
 						String typeName = typePath.toString();
 						if (!newState.isDuplicateLocator(typeName, typeLocator)) { // adding dependents results in 2 duplicate errors
 							if (JavaBuilder.DEBUG)
@@ -419,10 +432,10 @@
 							return; // skip it since it really isn't changed
 						if (JavaBuilder.DEBUG)
 							System.out.println("Compile this changed source file " + typeLocator); //$NON-NLS-1$
-						sourceFiles.add(new SourceFile((IFile) resource, md, encoding));
+						sourceFiles.add(new SourceFile((IFile) resource, md, encoding, true));
 				}
 				return;
-			} else if (Util.isClassFileName(resourceName)) {
+			} else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(resourceName)) {
 				return; // skip class files
 			} else if (md.hasIndependentOutputFolder) {
 				if (javaBuilder.filterExtraResource(resource)) return;
@@ -469,7 +482,7 @@
 	}
 }
 
-protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName, ArrayList definedTypeNames, ArrayList duplicateTypeNames) throws CoreException {
+protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName, ArrayList definedTypeNames, ArrayList duplicateTypeNames) {
 	char[][] previousTypeNames = newState.getDefinedTypeNamesFor(sourceLocator);
 	if (previousTypeNames == null)
 		previousTypeNames = new char[][] {mainTypeName};
@@ -504,7 +517,7 @@
 			System.out.println("Found removed type " + typePath); //$NON-NLS-1$
 		addDependentsOf(typePath, true); // when member types are removed, their enclosing type is structurally changed
 	}
-	IFile classFile = outputFolder.getFile(typePath.addFileExtension(JavaBuilder.CLASS_EXTENSION));
+	IFile classFile = outputFolder.getFile(typePath.addFileExtension(SuffixConstants.EXTENSION_class));
 	if (classFile.exists()) {
 		if (JavaBuilder.DEBUG)
 			System.out.println("Deleting class file of removed type " + typePath); //$NON-NLS-1$
@@ -558,11 +571,11 @@
 	storeTasksFor(sourceFile, tasks);
 }
 
-protected void writeClassFileBytes(byte[] bytes, IFile file, String qualifiedFileName, boolean isSecondaryType) throws CoreException {
+protected void writeClassFileBytes(byte[] bytes, IFile file, String qualifiedFileName, boolean isSecondaryType, boolean updateClassFile) throws CoreException {
 	// Before writing out the class file, compare it to the previous file
 	// If structural changes occured then add dependent source files
 	if (file.exists()) {
-		if (writeClassFileCheck(file, qualifiedFileName, bytes)) {
+		if (writeClassFileCheck(file, qualifiedFileName, bytes) || updateClassFile) { // see 46093
 			if (JavaBuilder.DEBUG)
 				System.out.println("Writing changed class file " + file.getName());//$NON-NLS-1$
 			file.setContents(new ByteArrayInputStream(bytes), true, false, null);
@@ -576,7 +589,14 @@
 			addDependentsOf(new Path(qualifiedFileName), true); // new secondary type
 		if (JavaBuilder.DEBUG)
 			System.out.println("Writing new class file " + file.getName());//$NON-NLS-1$
-		file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null);
+		try {
+			file.create(new ByteArrayInputStream(bytes), IResource.FORCE, null);
+		} catch (org.eclipse.core.internal.resources.ResourceException e) {
+			if (e.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS)
+				// catch the case that a nested type has been renamed and collides on disk with an as-yet-to-be-deleted type
+				throw new AbortCompilation(true, new AbortIncrementalBuildException(qualifiedFileName));
+			throw e; // rethrow
+		}
 		file.setDerived(true);
 	}
 }
@@ -584,12 +604,10 @@
 protected boolean writeClassFileCheck(IFile file, String fileName, byte[] newBytes) throws CoreException {
 	try {
 		byte[] oldBytes = Util.getResourceContentsAsByteArray(file);
-		if (this.compileLoop > 1) { // only optimize files which were recompiled during the dependent pass, see 33990
-			notEqual : if (newBytes.length == oldBytes.length) {
-				for (int i = newBytes.length; --i >= 0;)
-					if (newBytes[i] != oldBytes[i]) break notEqual;
-				return false; // bytes are identical so skip them
-			}
+		notEqual : if (newBytes.length == oldBytes.length) {
+			for (int i = newBytes.length; --i >= 0;)
+				if (newBytes[i] != oldBytes[i]) break notEqual;
+			return false; // bytes are identical so skip them
 		}
 		IPath location = file.getLocation();
 		if (location == null) return false; // unable to determine location of this class file
@@ -599,9 +617,11 @@
 			if (JavaBuilder.DEBUG)
 				System.out.println("Type has structural changes " + fileName); //$NON-NLS-1$
 			addDependentsOf(new Path(fileName), true);
+			this.newState.wasStructurallyChanged(fileName);
 		}
 	} catch (ClassFormatException e) {
 		addDependentsOf(new Path(fileName), true);
+		this.newState.wasStructurallyChanged(fileName);
 	}
 	return true;
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
index f39be6a..247ab90 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
@@ -17,6 +17,7 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.core.util.Util;
 
 import java.io.*;
 import java.util.*;
@@ -33,8 +34,6 @@
 char[][] extraResourceFileFilters;
 String[] extraResourceFolderFilters;
 
-public static final String CLASS_EXTENSION = "class"; //$NON-NLS-1$
-
 public static boolean DEBUG = false;
 
 /**
@@ -48,7 +47,9 @@
 	try {
 		if (resource != null && resource.exists())
 			return resource.findMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
-	} catch (CoreException e) {} // assume there are no problems
+	} catch (CoreException e) {
+		// assume there are no problems
+	}
 	return new IMarker[0];
 }
 
@@ -56,11 +57,26 @@
 	try {
 		if (resource != null && resource.exists())
 			return resource.findMarkers(IJavaModelMarker.TASK_MARKER, false, IResource.DEPTH_INFINITE);
-	} catch (CoreException e) {} // assume there are no tasks
+	} catch (CoreException e) {
+		// assume there are no tasks
+	}
 	return new IMarker[0];
 }
 
-public static void finishedBuilding(IResourceChangeEvent event) {
+/**
+ * Hook allowing to initialize some static state before a complete build iteration.
+ * This hook is invoked during PRE_AUTO_BUILD notification
+ */
+public static void buildStarting() {
+	// do nothing
+	// TODO (philippe) is it still needed?
+}
+
+/**
+ * Hook allowing to reset some static state after a complete build iteration.
+ * This hook is invoked during POST_AUTO_BUILD notification
+ */
+public static void buildFinished() {
 	BuildNotifier.resetProblemCounters();
 }
 
@@ -68,14 +84,18 @@
 	try {
 		if (resource != null && resource.exists())
 			resource.deleteMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
-	} catch (CoreException e) {} // assume there were no problems
+	} catch (CoreException e) {
+		// assume there were no problems
+	}
 }
 
 public static void removeTasksFor(IResource resource) {
 	try {
 		if (resource != null && resource.exists())
 			resource.deleteMarkers(IJavaModelMarker.TASK_MARKER, false, IResource.DEPTH_INFINITE);
-	} catch (CoreException e) {} // assume there were no problems
+	} catch (CoreException e) {
+		// assume there were no problems
+	}
 }
 
 public static void removeProblemsAndTasksFor(IResource resource) {
@@ -84,7 +104,9 @@
 			resource.deleteMarkers(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE);
 			resource.deleteMarkers(IJavaModelMarker.TASK_MARKER, false, IResource.DEPTH_INFINITE);
 		}
-	} catch (CoreException e) {} // assume there were no problems
+	} catch (CoreException e) {
+		// assume there were no problems
+	}
 }
 
 public static State readState(IProject project, DataInputStream in) throws IOException {
@@ -95,9 +117,6 @@
 	((State) state).write(out);
 }
 
-public JavaBuilder() {
-}
-
 protected IProject[] build(int kind, Map ignored, IProgressMonitor monitor) throws CoreException {
 	this.currentProject = getProject();
 	if (currentProject == null || !currentProject.isAccessible()) return new IProject[0];
@@ -299,7 +318,7 @@
 	return deltas;
 }
 
-private State getLastState(IProject project) {
+public State getLastState(IProject project) {
 	return (State) JavaModelManager.getJavaModelManager().getLastBuiltState(project, notifier.monitor);
 }
 
@@ -355,7 +374,8 @@
 				o--;
 				continue;
 			}
-		} catch (CoreException ignore) {}
+		} catch (CoreException ignore) { // skip it
+		}
 		if (DEBUG)
 			System.out.println(newSourceLocations[n] + " != " + oldSourceLocations[o]); //$NON-NLS-1$
 		return true;
@@ -366,7 +386,8 @@
 				n++;
 				continue;
 			}
-		} catch (CoreException ignore) {}
+		} catch (CoreException ignore) { // skip it
+		}
 		if (DEBUG)
 			System.out.println("Added non-empty source folder"); //$NON-NLS-1$
 		return true;
@@ -480,7 +501,7 @@
 		if (DEBUG)
 			System.out.println("Aborted build because project has classpath errors (incomplete or involved in cycle)"); //$NON-NLS-1$
 
-		JavaModelManager.getJavaModelManager().deltaProcessor.addForRefresh(javaProject);
+		JavaModelManager.getJavaModelManager().getDeltaProcessor().addForRefresh(javaProject);
 
 		removeProblemsAndTasksFor(currentProject); // remove all compilation problems
 
@@ -523,13 +544,13 @@
  */
 void mustPropagateStructuralChanges() {
 	HashSet cycleParticipants = new HashSet(3);
-	javaProject.updateCycleParticipants(null, new ArrayList(), cycleParticipants, workspaceRoot, new HashSet(3));
+	javaProject.updateCycleParticipants(new ArrayList(), cycleParticipants, workspaceRoot, new HashSet(3), null);
 	IPath currentPath = javaProject.getPath();
 	Iterator i= cycleParticipants.iterator();
 	while (i.hasNext()) {
 		IPath participantPath = (IPath) i.next();
 		if (participantPath != currentPath) {
-			IProject project = this.workspaceRoot.getProject(participantPath.segment(0));
+			IProject project = workspaceRoot.getProject(participantPath.segment(0));
 			if (hasBeenBuilt(project)) {
 				if (DEBUG) 
 					System.out.println("Requesting another build iteration since cycle participant " + project.getName() //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
index d9b7216..7d18d77 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
@@ -17,13 +17,14 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.*;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
 
 import java.io.*;
 import java.util.*;
 
-public class NameEnvironment implements INameEnvironment {
+public class NameEnvironment implements INameEnvironment, SuffixConstants {
 
 boolean isIncrementalBuild;
 ClasspathMultiDirectory[] sourceLocations;
@@ -77,7 +78,7 @@
 	SimpleLookupTable binaryLocationsPerProject) throws CoreException {
 
 	/* Update incomplete classpath marker */
-	IClasspathEntry[] classpathEntries = javaProject.getExpandedClasspath(true, true);
+	IClasspathEntry[] classpathEntries = javaProject.getExpandedClasspath(true/*ignore unresolved variable*/, true/*create markers*/, null/*preferred cp*/, null/*preferred output*/);
 
 	/* Update cycle marker */
 	IMarker cycleMarker = javaProject.getCycleMarker();
@@ -124,7 +125,7 @@
 				IClasspathEntry[] prereqClasspathEntries = prereqJavaProject.getRawClasspath();
 				ArrayList seen = new ArrayList();
 				nextPrereqEntry: for (int j = 0, m = prereqClasspathEntries.length; j < m; j++) {
-					IClasspathEntry prereqEntry = (IClasspathEntry) prereqClasspathEntries[j];
+					IClasspathEntry prereqEntry = prereqClasspathEntries[j];
 					if (prereqEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
 						Object prereqTarget = JavaModel.getTarget(root, prereqEntry.getPath(), true);
 						if (!(prereqTarget instanceof IContainer)) continue nextPrereqEntry;
@@ -159,7 +160,7 @@
 					IResource resource = (IResource) target;
 					ClasspathLocation bLocation = null;
 					if (resource instanceof IFile) {
-						if (!(Util.isArchiveFileName(path.lastSegment())))
+						if (!(org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(path.lastSegment())))
 							continue nextEntry;
 						bLocation = ClasspathLocation.forLibrary((IFile) resource);
 					} else if (resource instanceof IContainer) {
@@ -179,7 +180,7 @@
 						binaryLocationsPerProject.put(p, existingLocations);
 					}
 				} else if (target instanceof File) {
-					if (!(Util.isArchiveFileName(path.lastSegment())))
+					if (!(org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(path.lastSegment())))
 						continue nextEntry;
 					bLocations.add(ClasspathLocation.forLibrary(path.toString()));
 				}
@@ -254,7 +255,7 @@
 		// if an additional source file is waiting to be compiled, answer it BUT not if this is a secondary type search
 		// if we answer X.java & it no longer defines Y then the binary type looking for Y will think the class path is wrong
 		// let the recompile loop fix up dependents when the secondary type Y has been deleted from X.java
-		IPath qSourceFilePath = new Path(qualifiedTypeName + ".java"); //$NON-NLS-1$
+		IPath qSourceFilePath = new Path(qualifiedTypeName + SUFFIX_STRING_java);
 		int qSegmentCount = qSourceFilePath.segmentCount();
 		next : for (int i = 0, l = additionalUnits.length; i < l; i++) {
 			SourceFile additionalUnit = additionalUnits[i];
@@ -269,7 +270,7 @@
 		}
 	}
 
-	String qBinaryFileName = qualifiedTypeName + ".class"; //$NON-NLS-1$
+	String qBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
 	String binaryFileName = qBinaryFileName;
 	String qPackageName =  ""; //$NON-NLS-1$
 	if (qualifiedTypeName.length() > typeName.length) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameSet.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameSet.java
new file mode 100644
index 0000000..82a9eba
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameSet.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.builder;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+public class NameSet {
+
+// to avoid using Enumerations, walk the individual values skipping nulls
+public char[][] names;
+public int elementSize; // number of elements in the table
+public int threshold;
+
+public NameSet(int size) {
+	if (size < 3) size = 3;
+	this.elementSize = 0;
+	this.threshold = size + 1; // size is the expected number of elements
+	this.names = new char[2 * size + 1][];
+}
+
+public char[] add(char[] name) {
+	int length = names.length;
+	int index = CharOperation.hashCode(name) % length;
+	char[] current;
+	while ((current = names[index]) != null) {
+		if (CharOperation.equals(current, name)) return current;
+		if (++index == length) index = 0;
+	}
+	names[index] = name;
+
+	// assumes the threshold is never equal to the size of the table
+	if (++elementSize > threshold) rehash();
+	return name;
+}
+
+private void rehash() {
+	NameSet newSet = new NameSet(elementSize * 2); // double the number of expected elements
+	char[] current;
+	for (int i = names.length; --i >= 0;)
+		if ((current = names[i]) != null)
+			newSet.add(current);
+
+	this.names = newSet.names;
+	this.elementSize = newSet.elementSize;
+	this.threshold = newSet.threshold;
+}
+
+public String toString() {
+	String s = ""; //$NON-NLS-1$
+	char[] name;
+	for (int i = 0, l = names.length; i < l; i++)
+		if ((name = names[i]) != null)
+			s += new String(name) + "\n"; //$NON-NLS-1$
+	return s;
+}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/QualifiedNameSet.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/QualifiedNameSet.java
new file mode 100644
index 0000000..fef6e8a
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/QualifiedNameSet.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.builder;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+public class QualifiedNameSet {
+
+// to avoid using Enumerations, walk the individual values skipping nulls
+public char[][][] qualifiedNames;
+public int elementSize; // number of elements in the table
+public int threshold;
+
+public QualifiedNameSet(int size) {
+	if (size < 3) size = 3;
+	this.elementSize = 0;
+	this.threshold = size + 1; // size is the expected number of elements
+	this.qualifiedNames = new char[2 * size + 1][][];
+}
+
+public char[][] add(char[][] qualifiedName) {
+	int qLength = qualifiedName.length;
+	if (qLength == 0) return CharOperation.NO_CHAR_CHAR;
+
+	int length = qualifiedNames.length;
+	int index = CharOperation.hashCode(qualifiedName[qLength - 1]) % length;
+	char[][] current;
+	while ((current = qualifiedNames[index]) != null) {
+		if (CharOperation.equals(current, qualifiedName)) return current;
+		if (++index == length) index = 0;
+	}
+	qualifiedNames[index] = qualifiedName;
+
+	// assumes the threshold is never equal to the size of the table
+	if (++elementSize > threshold) rehash();
+	return qualifiedName;
+}
+
+private void rehash() {
+	QualifiedNameSet newSet = new QualifiedNameSet(elementSize * 2); // double the number of expected elements
+	char[][] current;
+	for (int i = qualifiedNames.length; --i >= 0;)
+		if ((current = qualifiedNames[i]) != null)
+			newSet.add(current);
+
+	this.qualifiedNames = newSet.qualifiedNames;
+	this.elementSize = newSet.elementSize;
+	this.threshold = newSet.threshold;
+}
+
+public String toString() {
+	String s = ""; //$NON-NLS-1$
+	char[][] qualifiedName;
+	for (int i = 0, l = qualifiedNames.length; i < l; i++)
+		if ((qualifiedName = qualifiedNames[i]) != null)
+			s += CharOperation.toString(qualifiedName) + "\n"; //$NON-NLS-1$
+	return s;
+}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
index 96130e4..f5de9b5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
@@ -13,8 +13,6 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 
-import java.util.*;
-
 public class ReferenceCollection {
 
 char[][][] qualifiedNameReferences; // contains no simple names as in just 'a' which is kept in simpleNameReferences instead
@@ -109,25 +107,27 @@
 
 // each array contains qualified char[][], one for size 2, 3, 4, 5, 6, 7 & the rest
 static final int MaxQualifiedNames = 7;
-static ArrayList[] InternedQualifiedNames = new ArrayList[MaxQualifiedNames];
+static QualifiedNameSet[] InternedQualifiedNames = new QualifiedNameSet[MaxQualifiedNames];
 // each array contains simple char[], one for size 1 to 29 & the rest
 static final int MaxSimpleNames = 30;
-static ArrayList[] InternedSimpleNames = new ArrayList[MaxSimpleNames];
+static NameSet[] InternedSimpleNames = new NameSet[MaxSimpleNames];
 static {
 	for (int i = 0; i < MaxQualifiedNames; i++)
-		InternedQualifiedNames[i] = new ArrayList(37);
+		InternedQualifiedNames[i] = new QualifiedNameSet(37);
 	for (int i = 0; i < MaxSimpleNames; i++)
-		InternedSimpleNames[i] = new ArrayList(11);
+		InternedSimpleNames[i] = new NameSet(37);
 }
 
-static char[][][] internQualifiedNames(ArrayList qualifiedStrings) {
+static char[][][] internQualifiedNames(StringSet qualifiedStrings) {
 	if (qualifiedStrings == null) return EmptyQualifiedNames;
-	int length = qualifiedStrings.size();
+	int length = qualifiedStrings.elementSize;
 	if (length == 0) return EmptyQualifiedNames;
 
 	char[][][] result = new char[length][][];
-	for (int i = 0; i < length; i++)
-		result[i] = CharOperation.splitOn('/', ((String) qualifiedStrings.get(i)).toCharArray());
+	String[] strings = qualifiedStrings.values;
+	for (int i = 0, l = strings.length; i < l; i++)
+		if (strings[i] != null)
+			result[--length] = CharOperation.splitOn('/', strings[i].toCharArray());
 	return internQualifiedNames(result);
 }
 
@@ -152,17 +152,9 @@
 		// InternedQualifiedNames[0] is for the rest (> 7 & 1)
 		// InternedQualifiedNames[1] is for size 2...
 		// InternedQualifiedNames[6] is for size 7
-		ArrayList internedNames = InternedQualifiedNames[qLength <= MaxQualifiedNames ? qLength - 1 : 0];
-		for (int j = 0, m = internedNames.size(); j < m; j++) {
-			char[][] internedName = (char[][]) internedNames.get(j);
-			if (CharOperation.equals(qualifiedName, internedName)) {
-				keepers[index++] = internedName;
-				continue next;
-			}
-		}
+		QualifiedNameSet internedNames = InternedQualifiedNames[qLength <= MaxQualifiedNames ? qLength - 1 : 0];
 		qualifiedName = internSimpleNames(qualifiedName, false);
-		internedNames.add(qualifiedName);
-		keepers[index++] = qualifiedName;
+		keepers[index++] = internedNames.add(qualifiedName);
 	}
 	if (length > index) {
 		if (length == 0) return EmptyQualifiedNames;
@@ -171,14 +163,16 @@
 	return keepers;
 }
 
-static char[][] internSimpleNames(ArrayList simpleStrings) {
+static char[][] internSimpleNames(StringSet simpleStrings) {
 	if (simpleStrings == null) return EmptySimpleNames;
-	int length = simpleStrings.size();
+	int length = simpleStrings.elementSize;
 	if (length == 0) return EmptySimpleNames;
 
 	char[][] result = new char[length][];
-	for (int i = 0; i < length; i++)
-		result[i] = ((String) simpleStrings.get(i)).toCharArray();
+	String[] strings = simpleStrings.values;
+	for (int i = 0, l = strings.length; i < l; i++)
+		if (strings[i] != null)
+			result[--length] = strings[i].toCharArray();
 	return internSimpleNames(result, true);
 }
 
@@ -206,16 +200,8 @@
 		// InternedSimpleNames[0] is for the rest (> 29)
 		// InternedSimpleNames[1] is for size 1...
 		// InternedSimpleNames[29] is for size 29
-		ArrayList internedNames = InternedSimpleNames[sLength < MaxSimpleNames ? sLength : 0];
-		for (int j = 0, m = internedNames.size(); j < m; j++) {
-			char[] internedName = (char[]) internedNames.get(j);
-			if (CharOperation.equals(name, internedName)) {
-				keepers[index++] = internedName;
-				continue next;
-			}
-		}
-		internedNames.add(name);
-		keepers[index++] = name;
+		NameSet internedNames = InternedSimpleNames[sLength < MaxSimpleNames ? sLength : 0];
+		keepers[index++] = internedNames.add(name);
 	}
 	if (length > index) {
 		if (index == 0) return EmptySimpleNames;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
index e4746cd..9f2ad0a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/SourceFile.java
@@ -17,7 +17,7 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
-import org.eclipse.jdt.internal.core.Util;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public class SourceFile implements ICompilationUnit {
 
@@ -25,12 +25,20 @@
 ClasspathMultiDirectory sourceLocation;
 String initialTypeName;
 String encoding;
+boolean updateClassFile;
 
 public SourceFile(IFile resource, ClasspathMultiDirectory sourceLocation, String encoding) {
 	this.resource = resource;
 	this.sourceLocation = sourceLocation;
 	this.initialTypeName = extractTypeName();
 	this.encoding = encoding;
+	this.updateClassFile = false;
+}
+
+public SourceFile(IFile resource, ClasspathMultiDirectory sourceLocation, String encoding, boolean updateClassFile) {
+	this(resource, sourceLocation, encoding);
+
+	this.updateClassFile = updateClassFile;
 }
 
 public boolean equals(Object o) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index 00ab0fc..dfc9e01 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -14,7 +14,6 @@
 import org.eclipse.core.runtime.*;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.core.Util;
 import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
 
 import java.io.*;
@@ -37,6 +36,10 @@
 
 private String[] knownPackageNames; // of the form "p1/p2"
 
+private long previousStructuralBuildTime;
+private StringSet structurallyChangedTypes;
+public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed
+
 static final byte VERSION = 0x0007;
 
 static final byte SOURCE_FOLDER = 1;
@@ -45,10 +48,13 @@
 static final byte INTERNAL_JAR = 4;
 
 State() {
+	// constructor with no argument
 }
 
 protected State(JavaBuilder javaBuilder) {
 	this.knownPackageNames = null;
+	this.previousStructuralBuildTime = -1;
+	this.structurallyChangedTypes = null;
 	this.javaProjectName = javaBuilder.currentProject.getName();
 	this.sourceLocations = javaBuilder.nameEnvironment.sourceLocations;
 	this.binaryLocations = javaBuilder.nameEnvironment.binaryLocations;
@@ -61,10 +67,14 @@
 }
 
 void copyFrom(State lastState) {
+	this.knownPackageNames = null;
+	this.previousStructuralBuildTime = lastState.previousStructuralBuildTime;
+	this.structurallyChangedTypes = lastState.structurallyChangedTypes;
+	this.buildNumber = lastState.buildNumber + 1;
+	this.lastStructuralBuildTime = lastState.lastStructuralBuildTime;
+	this.structuralBuildTimes = lastState.structuralBuildTimes;
+
 	try {
-		this.knownPackageNames = null;
-		this.buildNumber = lastState.buildNumber + 1;
-		this.lastStructuralBuildTime = lastState.lastStructuralBuildTime;
 		this.references = (SimpleLookupTable) lastState.references.clone();
 		this.typeLocators = (SimpleLookupTable) lastState.typeLocators.clone();
 	} catch (CloneNotSupportedException e) {
@@ -91,6 +101,16 @@
 	return null; // means only one type is defined with the same name as the file... saves space
 }
 
+StringSet getStructurallyChangedTypes(State prereqState) {
+	if (prereqState != null && prereqState.previousStructuralBuildTime > 0) {
+		Object o = structuralBuildTimes.get(prereqState.javaProjectName);
+		long previous = o == null ? 0 : ((Long) o).longValue();
+		if (previous == prereqState.previousStructuralBuildTime)
+			return prereqState.structurallyChangedTypes;
+	}
+	return null;
+}
+
 boolean isDuplicateLocator(String qualifiedTypeName, String typeLocator) {
 	String existing = (String) typeLocators.get(qualifiedTypeName);
 	return existing != null && !existing.equals(typeLocator);
@@ -157,7 +177,7 @@
 			return;
 		case IResource.FILE :
 			IPath typeLocatorPath = resource.getProjectRelativePath();
-			if (Util.isJavaFileName(typeLocatorPath.lastSegment()))
+			if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(typeLocatorPath.lastSegment()))
 				removeLocator(typeLocatorPath.toString());
 	}
 }
@@ -299,6 +319,8 @@
 }
 
 void tagAsStructurallyChanged() {
+	this.previousStructuralBuildTime = this.lastStructuralBuildTime;
+	this.structurallyChangedTypes = new StringSet(7);
 	this.lastStructuralBuildTime = System.currentTimeMillis();
 }
 
@@ -311,6 +333,15 @@
 	return true;
 }
 
+void wasStructurallyChanged(String typeName) {
+	if (this.structurallyChangedTypes != null) {
+		if (this.structurallyChangedTypes.elementSize > MaxStructurallyChangedTypes)
+			this.structurallyChangedTypes = null; // too many to keep track of
+		else
+			this.structurallyChangedTypes.add(typeName);
+	}
+}
+
 void write(DataOutputStream out) throws IOException {
 	int length;
 	Object[] keyTable;
@@ -426,7 +457,7 @@
 			if (keyTable[i] != null) {
 				length--;
 				out.writeUTF((String) keyTable[i]);
-				out.writeInt(internedTypeLocators.indexOf((String) valueTable[i]));
+				out.writeInt(internedTypeLocators.indexOf(valueTable[i]));
 			}
 		}
 		if (JavaBuilder.DEBUG && length != 0)
@@ -487,7 +518,7 @@
 		for (int i = 0, l = keyTable.length; i < l; i++) {
 			if (keyTable[i] != null) {
 				length--;
-				out.writeInt(internedTypeLocators.indexOf((String) keyTable[i]));
+				out.writeInt(internedTypeLocators.indexOf(keyTable[i]));
 				ReferenceCollection collection = (ReferenceCollection) valueTable[i];
 				if (collection instanceof AdditionalTypeCollection) {
 					out.writeByte(1);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/StringSet.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/StringSet.java
new file mode 100644
index 0000000..6688a04
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/StringSet.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.builder;
+
+public class StringSet {
+
+// to avoid using Enumerations, walk the individual values skipping nulls
+public String[] values;
+public int elementSize; // number of elements in the table
+public int threshold;
+
+public StringSet(int size) {
+	if (size < 3) size = 3;
+	this.elementSize = 0;
+	this.threshold = size + 1; // size is the expected number of elements
+	this.values = new String[2 * size + 1];
+}
+
+public boolean add(String value) {
+	int length = this.values.length;
+	int index = (value.hashCode() & 0x7FFFFFFF) % length;
+	String current;
+	while ((current = this.values[index]) != null) {
+		if (value.equals(current)) return false; // did not add it since it already existed
+		if (++index == length) index = 0;
+	}
+	this.values[index] = value;
+
+	// assumes the threshold is never equal to the size of the table
+	if (++elementSize > threshold) rehash();
+	return true;
+}
+
+public void clear() {
+	for (int i = this.values.length; --i >= 0;)
+		this.values[i] = null;
+	this.elementSize = 0;
+}
+
+public boolean includes(String value) {
+	int length = values.length;
+	int index = (value.hashCode() & 0x7FFFFFFF) % length;
+	String current;
+	while ((current = this.values[index]) != null) {
+		if (value.equals(current)) return true;
+		if (++index == length) index = 0;
+	}
+	return false;
+}
+
+private void rehash() {
+	StringSet newSet = new StringSet(elementSize * 2); // double the number of expected elements
+	String current;
+	for (int i = this.values.length; --i >= 0;)
+		if ((current = this.values[i]) != null)
+			newSet.add(current);
+
+	this.values = newSet.values;
+	this.elementSize = newSet.elementSize;
+	this.threshold = newSet.threshold;
+}
+
+public String toString() {
+	String s = ""; //$NON-NLS-1$
+	String value;
+	for (int i = 0, l = this.values.length; i < l; i++)
+		if ((value = this.values[i]) != null)
+			s += value + "\n"; //$NON-NLS-1$
+	return s;
+}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
index fb61cf2..70de004 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
@@ -11,11 +11,13 @@
 package org.eclipse.jdt.internal.core.eval;
 
 import java.util.Locale;
+import java.util.Map;
 
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.ICompletionRequestor;
 import org.eclipse.jdt.core.IImportDeclaration;
@@ -31,6 +33,8 @@
 import org.eclipse.jdt.core.eval.IGlobalVariable;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.BinaryType;
 import org.eclipse.jdt.internal.core.ClassFile;
 import org.eclipse.jdt.internal.core.CompletionRequestorWrapper;
@@ -74,7 +78,7 @@
 /**
  * Checks to ensure that there is a previously built state.
  */
-protected void checkBuilderState() throws JavaModelException {
+protected void checkBuilderState() {
 	
 	return;
 }
@@ -82,29 +86,69 @@
  * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeComplete(String, int, ICompletionRequestor)
  */
 public void codeComplete(String codeSnippet, int position, ICompletionRequestor requestor) throws JavaModelException {
-	this.context.complete(
-		codeSnippet.toCharArray(),
-		position,
-		this.project.getSearchableNameEnvironment(),
-		new CompletionRequestorWrapper(requestor,this.project.getNameLookup()),
-		this.project.getOptions(true),
-		this.project
-	);
+	codeComplete(codeSnippet, position, requestor, DefaultWorkingCopyOwner.PRIMARY);
+}
+/**
+ * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeComplete(String, int, ICompletionRequestor, WorkingCopyOwner)
+ */
+public void codeComplete(String codeSnippet, int position, ICompletionRequestor requestor, WorkingCopyOwner owner) throws JavaModelException {
+	NameLookup lookup = null;
+	try {
+		// set the units to look inside
+		lookup = this.project.getNameLookup();
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+		lookup.setUnitsToLookInside(workingCopies);
+
+		// code complete
+		this.context.complete(
+			codeSnippet.toCharArray(),
+			position,
+			this.project.getSearchableNameEnvironment(),
+			new CompletionRequestorWrapper(requestor, lookup),
+			this.project.getOptions(true),
+			this.project
+		);
+	} finally {
+		if (lookup != null) {
+			lookup.setUnitsToLookInside(null);
+		}
+	}
 }
 /**
  * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeSelect(String, int, int)
  */
 public IJavaElement[] codeSelect(String codeSnippet, int offset, int length) throws JavaModelException {
-	SelectionRequestor requestor= new SelectionRequestor(this.project.getNameLookup(), null); // null because there is no need to look inside the code snippet itself
-	this.context.select(
-		codeSnippet.toCharArray(),
-		offset,
-		offset + length - 1,
-		this.project.getSearchableNameEnvironment(),
-		requestor,
-		this.project.getOptions(true)
-	);
-	return requestor.getElements();
+	return codeSelect(codeSnippet, offset, length, DefaultWorkingCopyOwner.PRIMARY);
+}
+/**
+ * @see org.eclipse.jdt.core.eval.IEvaluationContext#codeSelect(String, int, int, WorkingCopyOwner)
+ */
+public IJavaElement[] codeSelect(String codeSnippet, int offset, int length, WorkingCopyOwner owner) throws JavaModelException {
+	NameLookup lookup = null;
+	try {
+		// set the units to look inside
+		lookup = this.project.getNameLookup();
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		ICompilationUnit[] workingCopies = manager.getWorkingCopies(owner, true/*add primary WCs*/);
+		lookup.setUnitsToLookInside(workingCopies);
+
+		// code select
+		SelectionRequestor requestor= new SelectionRequestor(lookup, null); // null because there is no need to look inside the code snippet itself
+		this.context.select(
+			codeSnippet.toCharArray(),
+			offset,
+			offset + length - 1,
+			this.project.getSearchableNameEnvironment(),
+			requestor,
+			this.project.getOptions(true)
+		);
+		return requestor.getElements();
+	} finally {
+		if (lookup != null) {
+			lookup.setUnitsToLookInside(null);
+		}
+	}
 }
 /**
  * @see org.eclipse.jdt.core.eval.IEvaluationContext#deleteVariable(IGlobalVariable)
@@ -145,6 +189,7 @@
 		varNames[i] = localVariableNames[i].toCharArray();
 	}
 
+	Map options = this.project.getOptions(true);
 	// transfer the imports of the IType to the evaluation context
 	if (declaringType != null) {
 		// retrieves the package statement 
@@ -160,6 +205,8 @@
 					importsNames[i] = imports[i].getElementName().toCharArray();
 				}
 				this.context.setImports(importsNames);
+				// turn off import complaints for implicitly added ones
+				options.put(CompilerOptions.OPTION_ReportUnusedImport, CompilerOptions.IGNORE);
 			}
 		} else {
 			// try to retrieve imports from the source
@@ -168,6 +215,8 @@
 				char[][] imports = sourceMapper.getImports((BinaryType) declaringType);
 				if (imports != null) {
 					this.context.setImports(imports);
+					// turn off import complaints for implicitly added ones
+					options.put(CompilerOptions.OPTION_ReportUnusedImport, CompilerOptions.IGNORE);
 				}
 			}
 		}
@@ -183,7 +232,7 @@
 			isStatic,
 			isConstructorCall,
 			environment = getBuildNameEnvironment(), 
-			this.project.getOptions(true), 
+			options, 
 			getInfrastructureEvaluationRequestor(requestor), 
 			getProblemFactory());
 	} catch (InstallException e) {
@@ -235,7 +284,7 @@
 /**
  * Returns a name environment for the last built state.
  */
-protected INameEnvironment getBuildNameEnvironment() throws JavaModelException {
+protected INameEnvironment getBuildNameEnvironment() {
 	return new NameEnvironment(getProject());
 }
 
@@ -272,7 +321,7 @@
 /**
  * Returns the problem factory to be used during evaluation.
  */
-protected IProblemFactory getProblemFactory() throws JavaModelException {
+protected IProblemFactory getProblemFactory() {
 	return ProblemFactory.getProblemFactory(Locale.getDefault());
 }
 /**
@@ -320,7 +369,7 @@
 /**
  * @see IEvaluationContext#validateImports(ICodeSnippetRequestor)
  */
-public void validateImports(ICodeSnippetRequestor requestor) throws JavaModelException {
+public void validateImports(ICodeSnippetRequestor requestor) {
 	
 	checkBuilderState();
 	INameEnvironment environment = null;
@@ -348,6 +397,7 @@
 		position,
 		new ICompletionRequestor(){
 			public void acceptAnonymousType(char[] superTypePackageName,char[] superTypeName,char[][] parameterPackageNames,char[][] parameterTypeNames,char[][] parameterNames,char[] completionName,int modifiers,int completionStart,int completionEnd, int relevance) {
+				// implements interface method
 			}
 			public void acceptClass(char[] packageName, char[] className, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
 				requestor.acceptClass(packageName, className, completionName, modifiers, completionStart, completionEnd);
@@ -365,6 +415,7 @@
 					marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
 					requestor.acceptError(marker);
 				} catch(CoreException e){
+					// ignore
 				}
 			}
 			public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] name, char[] typePackageName, char[] typeName, char[] completionName, int modifiers, int completionStart, int completionEnd, int relevance) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/ChangeCollector.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/ChangeCollector.java
new file mode 100644
index 0000000..256c18b
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/ChangeCollector.java
@@ -0,0 +1,442 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.hierarchy;
+
+import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.SimpleDelta;
+
+/*
+ * Collects changes (reported through fine-grained deltas) that can affect a type hierarchy.
+ */
+public class ChangeCollector {
+	
+	/*
+	 * A table from ITypes to TypeDeltas
+	 */
+	HashMap changes = new HashMap();
+	
+	TypeHierarchy hierarchy;
+	
+	public ChangeCollector(TypeHierarchy hierarchy) {
+		this.hierarchy = hierarchy;
+	}
+	
+	/*
+	 * Adds the children of the given delta to the list of changes.
+	 */
+	private void addAffectedChildren(IJavaElementDelta delta) throws JavaModelException {
+		IJavaElementDelta[] children = delta.getAffectedChildren();
+		for (int i = 0, length = children.length; i < length; i++) {
+			IJavaElementDelta child = children[i];
+			IJavaElement childElement = child.getElement();
+			switch (childElement.getElementType()) {
+				case IJavaElement.IMPORT_CONTAINER:
+					addChange((IImportContainer)childElement, child);
+					break;
+				case IJavaElement.IMPORT_DECLARATION:
+					addChange((IImportDeclaration)childElement, child);
+					break;
+				case IJavaElement.TYPE:
+					addChange((IType)childElement, child);
+					break;
+				case IJavaElement.INITIALIZER:
+				case IJavaElement.FIELD:
+				case IJavaElement.METHOD:
+					addChange((IMember)childElement, child);
+					break;
+			}
+		}
+	}
+	
+	/*
+	 * Adds the given delta on a compilation unit to the list of changes.
+	 */
+	public void addChange(ICompilationUnit cu, IJavaElementDelta newDelta) throws JavaModelException {
+		int newKind = newDelta.getKind();
+		switch (newKind) {
+			case IJavaElementDelta.ADDED:
+				ArrayList allTypes = new ArrayList();
+				getAllTypesFromElement(cu, allTypes);
+				for (int i = 0, length = allTypes.size(); i < length; i++) {
+					IType type = (IType)allTypes.get(i);
+					addTypeAddition(type, (SimpleDelta)this.changes.get(type));
+				}
+				break;
+			case IJavaElementDelta.REMOVED:
+				allTypes = new ArrayList();
+				getAllTypesFromHierarchy((JavaElement)cu, allTypes);
+				for (int i = 0, length = allTypes.size(); i < length; i++) {
+					IType type = (IType)allTypes.get(i);
+					addTypeRemoval(type, (SimpleDelta)this.changes.get(type));
+				}
+				break;
+			case IJavaElementDelta.CHANGED:
+				addAffectedChildren(newDelta);
+				break;
+		}
+	}
+	
+	private void addChange(IImportContainer importContainer, IJavaElementDelta newDelta) throws JavaModelException {
+		int newKind = newDelta.getKind();
+		if (newKind == IJavaElementDelta.CHANGED) {
+			addAffectedChildren(newDelta);
+			return;
+		}
+		SimpleDelta existingDelta = (SimpleDelta)this.changes.get(importContainer);
+		if (existingDelta != null) {
+			switch (newKind) {
+				case IJavaElementDelta.ADDED:
+					if (existingDelta.getKind() == IJavaElementDelta.REMOVED) {
+						// REMOVED then ADDED
+						this.changes.remove(importContainer);
+					}
+					break;
+				case IJavaElementDelta.REMOVED:
+					if (existingDelta.getKind() == IJavaElementDelta.ADDED) {
+						// ADDED then REMOVED
+						this.changes.remove(importContainer);
+					}
+					break;
+					// CHANGED handled above
+			}
+		} else {
+			SimpleDelta delta = new SimpleDelta();
+			switch (newKind) {
+				case IJavaElementDelta.ADDED:
+					delta.added();
+					break;
+				case IJavaElementDelta.REMOVED:
+					delta.removed();
+					break;
+			}
+			this.changes.put(importContainer, delta);
+		}
+	}
+
+	private void addChange(IImportDeclaration importDecl, IJavaElementDelta newDelta) {
+		SimpleDelta existingDelta = (SimpleDelta)this.changes.get(importDecl);
+		int newKind = newDelta.getKind();
+		if (existingDelta != null) {
+			switch (newKind) {
+				case IJavaElementDelta.ADDED:
+					if (existingDelta.getKind() == IJavaElementDelta.REMOVED) {
+						// REMOVED then ADDED
+						this.changes.remove(importDecl);
+					}
+					break;
+				case IJavaElementDelta.REMOVED:
+					if (existingDelta.getKind() == IJavaElementDelta.ADDED) {
+						// ADDED then REMOVED
+						this.changes.remove(importDecl);
+					}
+					break;
+				// CHANGED cannot happen for import declaration
+			}
+		} else {
+			SimpleDelta delta = new SimpleDelta();
+			switch (newKind) {
+				case IJavaElementDelta.ADDED:
+					delta.added();
+					break;
+				case IJavaElementDelta.REMOVED:
+					delta.removed();
+					break;
+			}
+			this.changes.put(importDecl, delta);
+		}
+	}
+	
+	/*
+	 * Adds a change for the given member (a method, a field or an initializer) and the types it defines.
+	 */
+	private void addChange(IMember member, IJavaElementDelta newDelta) throws JavaModelException {
+		int newKind = newDelta.getKind();
+		switch (newKind) {
+			case IJavaElementDelta.ADDED:
+				ArrayList allTypes = new ArrayList();
+				getAllTypesFromElement(member, allTypes);
+				for (int i = 0, length = allTypes.size(); i < length; i++) {
+					IType innerType = (IType)allTypes.get(i);
+					addTypeAddition(innerType, (SimpleDelta)this.changes.get(innerType));
+				}
+				break;
+			case IJavaElementDelta.REMOVED:
+				allTypes = new ArrayList();
+				getAllTypesFromHierarchy((JavaElement)member, allTypes);
+				for (int i = 0, length = allTypes.size(); i < length; i++) {
+					IType type = (IType)allTypes.get(i);
+					addTypeRemoval(type, (SimpleDelta)this.changes.get(type));
+				}
+				break;
+			case IJavaElementDelta.CHANGED:
+				addAffectedChildren(newDelta);
+				break;
+		}
+	}
+	
+	/*
+	 * Adds a change for the given type and the types it defines.
+	 */
+	private void addChange(IType type, IJavaElementDelta newDelta) throws JavaModelException {
+		 int newKind = newDelta.getKind();
+		SimpleDelta existingDelta = (SimpleDelta)this.changes.get(type);
+		switch (newKind) {
+			case IJavaElementDelta.ADDED:
+				addTypeAddition(type, existingDelta);
+				ArrayList allTypes = new ArrayList();
+				getAllTypesFromElement(type, allTypes);
+				for (int i = 0, length = allTypes.size(); i < length; i++) {
+					IType innerType = (IType)allTypes.get(i);
+					addTypeAddition(innerType, (SimpleDelta)this.changes.get(innerType));
+				}
+				break;
+			case IJavaElementDelta.REMOVED:
+				addTypeRemoval(type, existingDelta);
+				allTypes = new ArrayList();
+				getAllTypesFromHierarchy((JavaElement)type, allTypes);
+				for (int i = 0, length = allTypes.size(); i < length; i++) {
+					IType innerType = (IType)allTypes.get(i);
+					addTypeRemoval(innerType, (SimpleDelta)this.changes.get(innerType));
+				}
+				break;
+			case IJavaElementDelta.CHANGED:
+				addTypeChange(type, newDelta.getFlags(), existingDelta);
+				addAffectedChildren(newDelta);
+				break;
+		}
+	}
+
+	private void addTypeAddition(IType type, SimpleDelta existingDelta) throws JavaModelException {
+		if (existingDelta != null) {
+			switch (existingDelta.getKind()) {
+				case IJavaElementDelta.REMOVED:
+					// REMOVED then ADDED
+					boolean hasChange = false;
+					if (hasSuperTypeChange(type)) {
+						existingDelta.superTypes();
+						hasChange = true;
+					} 
+					if (hasVisibilityChange(type)) {
+						existingDelta.modifiers();
+						hasChange = true;
+					}
+					if (!hasChange) {
+						this.changes.remove(type);
+					}
+					break;
+					// CHANGED then ADDED
+					// or ADDED then ADDED: should not happen
+			}
+		} else {
+			// check whether the type addition affects the hierarchy
+			String typeName = type.getElementName();
+			if (this.hierarchy.hasSupertype(typeName) 
+					|| this.hierarchy.subtypesIncludeSupertypeOf(type) 
+					|| this.hierarchy.missingTypes.contains(typeName)) {
+				SimpleDelta delta = new SimpleDelta();
+				delta.added();
+				this.changes.put(type, delta);
+			}
+		}
+	}
+	
+	private void addTypeChange(IType type, int newFlags, SimpleDelta existingDelta) throws JavaModelException {
+		if (existingDelta != null) {
+			switch (existingDelta.getKind()) {
+				case IJavaElementDelta.CHANGED:
+					// CHANGED then CHANGED
+					int existingFlags = existingDelta.getFlags();
+					boolean hasChange = false;
+					if ((existingFlags & IJavaElementDelta.F_SUPER_TYPES) != 0
+							&& hasSuperTypeChange(type)) {
+						existingDelta.superTypes();
+						hasChange = true;
+					} 
+					if ((existingFlags & IJavaElementDelta.F_MODIFIERS) != 0
+							&& hasVisibilityChange(type)) {
+						existingDelta.modifiers();
+						hasChange = true;
+					}
+					if (!hasChange) {
+						// super types and visibility are back to the ones in the existing hierarchy
+						this.changes.remove(type);
+					}
+					break;
+					// ADDED then CHANGED: leave it as ADDED
+					// REMOVED then CHANGED: should not happen
+			}
+		} else {
+			// check whether the type change affects the hierarchy
+			SimpleDelta typeDelta = null;
+			if ((newFlags & IJavaElementDelta.F_SUPER_TYPES) != 0 
+					&& this.hierarchy.includesTypeOrSupertype(type)) {
+				typeDelta = new SimpleDelta();
+				typeDelta.superTypes();
+			}
+			if ((newFlags & IJavaElementDelta.F_MODIFIERS) != 0
+					&& this.hierarchy.hasSupertype(type.getElementName())) {
+				if (typeDelta == null) {
+					typeDelta = new SimpleDelta();
+				}
+				typeDelta.modifiers();
+			}
+			if (typeDelta != null) {
+				this.changes.put(type, typeDelta);
+			}
+		}
+	}
+
+	private void addTypeRemoval(IType type, SimpleDelta existingDelta) {
+		if (existingDelta != null) {
+			switch (existingDelta.getKind()) {
+				case IJavaElementDelta.ADDED:
+					// ADDED then REMOVED
+					this.changes.remove(type);
+					break;
+				case IJavaElementDelta.CHANGED:
+					// CHANGED then REMOVED
+					existingDelta.removed();
+					break;
+					// REMOVED then REMOVED: should not happen
+			}
+		} else {
+			// check whether the type removal affects the hierarchy
+			if (this.hierarchy.contains(type)) {
+				SimpleDelta typeDelta = new SimpleDelta();
+				typeDelta.removed();
+				this.changes.put(type, typeDelta);
+			}
+		}
+	}
+	
+	/*
+	 * Returns all types defined in the given element excluding the given element.
+	 */
+	private void getAllTypesFromElement(IJavaElement element, ArrayList allTypes) throws JavaModelException {
+		switch (element.getElementType()) {
+			case IJavaElement.COMPILATION_UNIT:
+				IType[] types = ((ICompilationUnit)element).getTypes();
+				for (int i = 0, length = types.length; i < length; i++) {
+					IType type = types[i];
+					allTypes.add(type);
+					getAllTypesFromElement(type, allTypes);
+				}
+				break;
+			case IJavaElement.TYPE:
+				types = ((IType)element).getTypes();
+				for (int i = 0, length = types.length; i < length; i++) {
+					IType type = types[i];
+					allTypes.add(type);
+					getAllTypesFromElement(type, allTypes);
+				}
+				break;
+			case IJavaElement.INITIALIZER:
+			case IJavaElement.FIELD:
+			case IJavaElement.METHOD:
+				IJavaElement[] children = ((IMember)element).getChildren();
+				for (int i = 0, length = children.length; i < length; i++) {
+					IType type = (IType)children[i];
+					allTypes.add(type);
+					getAllTypesFromElement(type, allTypes);
+				}
+				break;
+		}
+	}
+	
+	/*
+	 * Returns all types in the existing hierarchy that have the given element as a parent.
+	 */
+	private void getAllTypesFromHierarchy(JavaElement element, ArrayList allTypes) {
+		switch (element.getElementType()) {
+			case IJavaElement.COMPILATION_UNIT:
+				ArrayList types = (ArrayList)this.hierarchy.files.get(element);
+				if (types != null) {
+					allTypes.addAll(types);
+				}
+				break;
+			case IJavaElement.TYPE:
+			case IJavaElement.INITIALIZER:
+			case IJavaElement.FIELD:
+			case IJavaElement.METHOD:
+				types = (ArrayList)this.hierarchy.files.get(((IMember)element).getCompilationUnit());
+				if (types != null) {
+					for (int i = 0, length = types.size(); i < length; i++) {
+						IType type = (IType)types.get(i);
+						if (element.isAncestorOf(type)) {
+							allTypes.add(type);
+						}
+					}
+				}
+				break;
+		}
+	}
+	
+	private boolean hasSuperTypeChange(IType type) throws JavaModelException {
+		// check super class
+		IType superclass = this.hierarchy.getSuperclass(type);
+		String existingSuperclassName = superclass == null ? null : superclass.getElementName();
+		String newSuperclassName = type.getSuperclassName();
+		if (existingSuperclassName != null && !existingSuperclassName.equals(newSuperclassName)) {
+			return true;
+		}
+		
+		// check super interfaces
+		IType[] existingSuperInterfaces = this.hierarchy.getSuperInterfaces(type);
+		String[] newSuperInterfaces = type.getSuperInterfaceNames();
+		if (existingSuperInterfaces.length != newSuperInterfaces.length) {
+			return true;
+		}
+		for (int i = 0, length = newSuperInterfaces.length; i < length; i++) {
+			String superInterfaceName = newSuperInterfaces[i];
+			if (!superInterfaceName.equals(newSuperInterfaces[i])) {
+				return true;
+			}
+		}
+		
+		return false;
+	}
+	
+	private boolean hasVisibilityChange(IType type) throws JavaModelException {
+		int existingFlags = this.hierarchy.getCachedFlags(type);
+		int newFlags = type.getFlags();
+		return existingFlags != newFlags;
+	}
+
+	/*
+	 * Whether the hierarchy needs refresh according to the changes collected so far.
+	 */
+	public boolean needsRefresh() {
+		return changes.size() != 0;
+	}
+	
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		Iterator iterator = this.changes.entrySet().iterator();
+		while (iterator.hasNext()) {
+			Map.Entry entry = (Map.Entry)iterator.next();
+			buffer.append(((JavaElement)entry.getKey()).toDebugString());
+			buffer.append(entry.getValue());
+			if (iterator.hasNext()) {
+				buffer.append('\n');
+			}
+		}
+		return buffer.toString();
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
index 1acff1f..d9cd7dc 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
@@ -10,21 +10,15 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.hierarchy;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.eclipse.core.resources.IFile;
-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.OperationCanceledException;
-import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.IWorkingCopy;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
@@ -32,19 +26,14 @@
 import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
 import org.eclipse.jdt.internal.core.BasicCompilationUnit;
-import org.eclipse.jdt.internal.core.BinaryType;
 import org.eclipse.jdt.internal.core.ClassFile;
-import org.eclipse.jdt.internal.core.CompilationUnit;
-import org.eclipse.jdt.internal.core.CreateTypeHierarchyOperation;
 import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
 import org.eclipse.jdt.internal.core.JavaElement;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.JavaProject;
 import org.eclipse.jdt.internal.core.NameLookup;
 import org.eclipse.jdt.internal.core.Openable;
-import org.eclipse.jdt.internal.core.PackageFragmentRoot;
 import org.eclipse.jdt.internal.core.SearchableEnvironment;
-import org.eclipse.jdt.internal.core.SourceType;
 import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
 
 public abstract class HierarchyBuilder implements IHierarchyRequestor {
@@ -111,28 +100,26 @@
 		//    a sub or super type of the focus type.
 		org.eclipse.jdt.core.ICompilationUnit unitToLookInside = focusType.getCompilationUnit();
 		if (nameLookup != null) {
-			synchronized(nameLookup) { // prevent 2 concurrent accesses to name lookup while the working copies are set
-				IWorkingCopy[] workingCopies = this.getWokingCopies();
-				IWorkingCopy[] unitsToLookInside;
-				if (unitToLookInside != null) {
-					int wcLength = workingCopies == null ? 0 : workingCopies.length;
-					if (wcLength == 0) {
-						unitsToLookInside = new IWorkingCopy[] {unitToLookInside};
-					} else {
-						unitsToLookInside = new IWorkingCopy[wcLength+1];
-						unitsToLookInside[0] = unitToLookInside;
-						System.arraycopy(workingCopies, 0, unitsToLookInside, 1, wcLength);
-					}
+			org.eclipse.jdt.core.ICompilationUnit[] workingCopies = this.hierarchy.workingCopies;
+			org.eclipse.jdt.core.ICompilationUnit[] unitsToLookInside;
+			if (unitToLookInside != null) {
+				int wcLength = workingCopies == null ? 0 : workingCopies.length;
+				if (wcLength == 0) {
+					unitsToLookInside = new org.eclipse.jdt.core.ICompilationUnit[] {unitToLookInside};
 				} else {
-					unitsToLookInside = workingCopies;
+					unitsToLookInside = new org.eclipse.jdt.core.ICompilationUnit[wcLength+1];
+					unitsToLookInside[0] = unitToLookInside;
+					System.arraycopy(workingCopies, 0, unitsToLookInside, 1, wcLength);
 				}
-				try {
-					nameLookup.setUnitsToLookInside(unitsToLookInside);
-					// resolve
-					this.hierarchyResolver.resolve(type);
-				} finally {
-					nameLookup.setUnitsToLookInside(null);
-				}
+			} else {
+				unitsToLookInside = workingCopies;
+			}
+			try {
+				nameLookup.setUnitsToLookInside(unitsToLookInside); // NB: this uses a PerThreadObject, so it is thread safe
+				// resolve
+				this.hierarchyResolver.resolve(type);
+			} finally {
+				nameLookup.setUnitsToLookInside(null);
 			}
 		} else {
 			// resolve
@@ -261,13 +248,6 @@
 	protected IType getType() {
 		return this.hierarchy.getType();
 	}
-protected IWorkingCopy[] getWokingCopies() {
-	if (this.hierarchy.progressMonitor instanceof CreateTypeHierarchyOperation) {
-		return ((CreateTypeHierarchyOperation)this.hierarchy.progressMonitor).workingCopies;
-	} else {
-		return null;
-	}
-}
 	/**
 	 * Looks up and returns a handle for the given binary info.
 	 */
@@ -295,7 +275,7 @@
 /**
  * Create an ICompilationUnit info from the given compilation unit on disk.
  */
-protected ICompilationUnit createCompilationUnitFromPath(Openable handle, String osPath) throws JavaModelException {
+protected ICompilationUnit createCompilationUnitFromPath(Openable handle, String osPath) {
 	String encoding = handle.getJavaProject().getOption(JavaCore.CORE_ENCODING, true);
 	return 
 		new BasicCompilationUnit(
@@ -308,15 +288,19 @@
  * Creates the type info from the given class file on disk and
  * adds it to the given list of infos.
  */
-protected IGenericType createInfoFromClassFile(Openable handle, String osPath) throws JavaModelException {
-	IGenericType info = null;
+protected IBinaryType createInfoFromClassFile(Openable handle, String osPath) {
+	IBinaryType info = null;
 	try {
 		info = org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.read(osPath);
 	} catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException e) {
-		e.printStackTrace();
+		if (TypeHierarchy.DEBUG) {
+			e.printStackTrace();
+		}
 		return null;
 	} catch (java.io.IOException e) {
-		e.printStackTrace();
+		if (TypeHierarchy.DEBUG) {
+			e.printStackTrace();
+		}
 		return null;
 	}						
 	this.infoToHandle.put(info, handle);
@@ -325,10 +309,10 @@
 	/**
  * Create a type info from the given class file in a jar and adds it to the given list of infos.
  */
-protected IGenericType createInfoFromClassFileInJar(Openable classFile) throws JavaModelException {
+protected IBinaryType createInfoFromClassFileInJar(Openable classFile) {
 	IJavaElement pkg = classFile.getParent();
 	String classFilePath = pkg.getElementName().replace('.', '/') + "/" + classFile.getElementName(); //$NON-NLS-1$
-	IGenericType info = null;
+	IBinaryType info = null;
 	java.util.zip.ZipFile zipFile = null;
 	try {
 		zipFile = ((JarPackageFragmentRoot)pkg.getParent()).getJar();
@@ -336,13 +320,19 @@
 			zipFile,
 			classFilePath);
 	} catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException e) {
-		e.printStackTrace();
+		if (TypeHierarchy.DEBUG) {
+			e.printStackTrace();
+		}
 		return null;
 	} catch (java.io.IOException e) {
-		e.printStackTrace();
+		if (TypeHierarchy.DEBUG) {
+			e.printStackTrace();
+		}
 		return null;
 	} catch (CoreException e) {
-		e.printStackTrace();
+		if (TypeHierarchy.DEBUG) {
+			e.printStackTrace();
+		}
 		return null;
 	} finally {
 		JavaModelManager.getJavaModelManager().closeZipFile(zipFile);
@@ -351,91 +341,4 @@
 	return info;
 }
 
-protected void addInfoFromClosedElement(Openable handle, ArrayList infos, ArrayList units, String resourcePath) throws JavaModelException {
-	
-	// create a temporary info
-	IJavaElement pkg = handle.getParent();
-	PackageFragmentRoot root = (PackageFragmentRoot)pkg.getParent();
-	if (root.isArchive()) {
-		// class file in a jar
-		IGenericType info = this.createInfoFromClassFileInJar(handle);
-		if (info != null) {
-			infos.add(info);
-		}
-	} else {
-		// file in a directory
-		IPath path = new Path(resourcePath);
-		IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
-		IPath location = file.getLocation();
-		if (location != null){
-			String osPath = location.toOSString();
-			if (handle instanceof CompilationUnit) {
-				// compilation unit in a directory
-				ICompilationUnit unit = this.createCompilationUnitFromPath(handle, osPath);
-				if (unit != null) {
-					units.add(unit);
-				}
-			} else if (handle instanceof ClassFile) {
-				// class file in a directory
-				IGenericType info = this.createInfoFromClassFile(handle, osPath);
-				if (info != null) {
-					infos.add(info);
-				}
-			}
-		}
-	}
-	
-}
-
-/**
- * Add the type info from the given CU to the given list of infos.
- */
-protected void addInfoFromOpenCU(CompilationUnit cu, ArrayList infos) throws JavaModelException {
-	IType[] types = cu.getTypes();
-	for (int j = 0; j < types.length; j++) {
-		SourceType type = (SourceType)types[j];
-		this.addInfoFromOpenSourceType(type, infos);
-	}
-}
-
-
-/**
- * Add the type info from the given CU to the given list of infos.
- */
-protected void addInfoFromOpenSourceType(SourceType type, ArrayList infos) throws JavaModelException {
-	IGenericType info = (IGenericType)type.getElementInfo();
-	infos.add(info);
-	this.infoToHandle.put(info, type);
-	IType[] members = type.getTypes();
-	for (int i = 0; i < members.length; i++) {
-		this.addInfoFromOpenSourceType((SourceType)members[i], infos);
-	}
-}
-
-/**
- * Add the type info from the given class file to the given list of infos.
- */
-protected void addInfoFromOpenClassFile(ClassFile classFile, ArrayList infos) throws JavaModelException {
-	IType type = classFile.getType();
-	IGenericType info = (IGenericType) ((BinaryType) type).getElementInfo();
-	infos.add(info);
-	this.infoToHandle.put(info, classFile);
-}
-
-protected void addInfoFromElement(Openable handle, ArrayList infos, ArrayList units, String resourcePath) throws JavaModelException {
-	if (handle.isOpen()) {
-		// reuse the info from the java model cache
-		if (handle instanceof CompilationUnit) {
-			this.addInfoFromOpenCU((CompilationUnit)handle, infos);
-		} else if (handle instanceof ClassFile) {
-			this.addInfoFromOpenClassFile((ClassFile)handle, infos);
-		}
-	} else {
-		this.addInfoFromClosedElement(handle, infos, units, resourcePath);
-	}
-}
-
-
-
-
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
index 85f4b3f..fd73dba 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
@@ -23,17 +23,23 @@
  * implements I & J?
  */
 
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MemberTypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
@@ -54,91 +60,98 @@
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.jdt.internal.compiler.util.Util;
+import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.Member;
+import org.eclipse.jdt.internal.core.util.ASTNodeFinder;
+import org.eclipse.jdt.internal.core.util.ElementInfoConverter;
+import org.eclipse.jdt.internal.core.util.HandleFactory;
 
 public class HierarchyResolver implements ITypeRequestor {
-	IHierarchyRequestor requestor;
+	
+	/*
+	 * A wrapper around the simple name of a type that is missing.
+	 */
+	public class MissingType implements IGenericType {
+		public String simpleName;
+		
+		public MissingType(String simpleName) {
+			this.simpleName = simpleName;
+		}
+	
+		/*
+		 * @see IDependent#getFileName()
+		 */
+		public char[] getFileName() {
+			return null;
+		}
+		
+		/*
+		 * @see IGenericType#getModifiers()
+		 */
+		public int getModifiers() {
+			return 0;
+		}
+	
+		/*
+		 * @see IGenericType#isBinaryType()
+		 */
+		public boolean isBinaryType() {
+			return false;
+		}
+	
+		/*
+		 * @see IGenericType#isClass()
+		 */
+		public boolean isClass() {
+			return false;
+		}
+	
+		/*
+		 * @see IGenericType#isInterface()
+		 */
+		public boolean isInterface() {
+			return false;
+		}
+		
+		public String toString() {
+			return "Missing type: " + this.simpleName; //$NON-NLS-1$
+		}
+	
+	}
+	private ReferenceBinding focusType;
+	private boolean superTypesOnly;
+	private boolean hasMissingSuperClass;
 	LookupEnvironment lookupEnvironment;
+	private CompilerOptions options;
+	HierarchyBuilder requestor;
+	private ReferenceBinding[] typeBindings;
 
 	private int typeIndex;
 	private IGenericType[] typeModels;
-	private ReferenceBinding[] typeBindings;
-	private ReferenceBinding focusType;
-	private CompilerOptions options;
-	private boolean hasMissingSuperClass;
 	
-/**
- * A wrapper around the simple name of a type that is missing.
- */
-public class MissingType implements IGenericType {
-	public String simpleName;
-	
-	public MissingType(String simpleName) {
-		this.simpleName = simpleName;
-	}
-	
-	/*
-	 * @see IGenericType#getModifiers()
-	 */
-	public int getModifiers() {
-		return 0;
-	}
-
-	/*
-	 * @see IGenericType#isBinaryType()
-	 */
-	public boolean isBinaryType() {
-		return false;
-	}
-
-	/*
-	 * @see IGenericType#isClass()
-	 */
-	public boolean isClass() {
-		return false;
-	}
-
-	/*
-	 * @see IGenericType#isInterface()
-	 */
-	public boolean isInterface() {
-		return false;
-	}
-
-	/*
-	 * @see IDependent#getFileName()
-	 */
-	public char[] getFileName() {
-		return null;
-	}
-	
-	public String toString() {
-		return "Missing type: " + this.simpleName; //$NON-NLS-1$
-	}
-
-}
-	
-public HierarchyResolver(INameEnvironment nameEnvironment, Map settings, IHierarchyRequestor requestor, IProblemFactory problemFactory) {
+public HierarchyResolver(INameEnvironment nameEnvironment, Map settings, HierarchyBuilder requestor, IProblemFactory problemFactory) {
 	// create a problem handler with the 'exit after all problems' handling policy
-	options = settings == null ? new CompilerOptions() : new CompilerOptions(settings);
+	options = new CompilerOptions(settings);
 	IErrorHandlingPolicy policy = DefaultErrorHandlingPolicies.exitAfterAllProblems();
 	ProblemReporter problemReporter = new ProblemReporter(policy, options, problemFactory);
 
-	this.initialize(
+	this.setEnvironment(
 		new LookupEnvironment(this, options, problemReporter, nameEnvironment),
 		requestor);
 }
-public HierarchyResolver(LookupEnvironment lookupEnvironment, IHierarchyRequestor requestor) {
-	this.initialize(lookupEnvironment, requestor);
+public HierarchyResolver(LookupEnvironment lookupEnvironment, HierarchyBuilder requestor) {
+	this.setEnvironment(lookupEnvironment, requestor);
 }
 /**
  * Add an additional binary type
  */
 
 public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
-	BinaryTypeBinding typeBinding = lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+	BinaryTypeBinding typeBinding = this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
 	try {
 		this.remember(binaryType, typeBinding);
 	} catch (AbortCompilation e) {
+		// ignore
 	}
 }
 /**
@@ -147,7 +160,7 @@
 
 public void accept(ICompilationUnit sourceUnit) {
 	//System.out.println("Cannot accept compilation units inside the HierarchyResolver.");
-	lookupEnvironment.problemReporter.abortDueToInternalError(
+	this.lookupEnvironment.problemReporter.abortDueToInternalError(
 		new StringBuffer(Util.bind("accept.cannot")) //$NON-NLS-1$
 			.append(sourceUnit.getFileName())
 			.toString());
@@ -167,18 +180,20 @@
 	CompilationUnitDeclaration unit =
 		SourceTypeConverter.buildCompilationUnit(
 			new ISourceType[] {sourceType}, // ignore secondary types, to improve laziness
-			false, // no need for field and methods
-			true, // need member types
-			false, // no need for field initialization
+			SourceTypeConverter.MEMBER_TYPE, // need member types
+			// no need for field initialization
 			lookupEnvironment.problemReporter, 
 			result);
 		
 	// build bindings
 	if (unit != null) {
 		try {
-			lookupEnvironment.buildTypeBindings(unit);
-			rememberWithMemberTypes(sourceType, unit.types[0].binding);
-			lookupEnvironment.completeTypeBindings(unit, false);
+			this.lookupEnvironment.buildTypeBindings(unit);
+			
+			org.eclipse.jdt.core.ICompilationUnit cu = ((SourceTypeElementInfo)sourceType).getHandle().getCompilationUnit();
+			rememberAllTypes(unit, cu, false);
+
+			this.lookupEnvironment.completeTypeBindings(unit, true/*build constructor only*/);
 		} catch (AbortCompilation e) {
 			// missing 'java.lang' package: ignore
 		}
@@ -236,10 +251,28 @@
 		superInterfaceNames = ((IBinaryType)type).getInterfaceNames();
 		separator = '/';
 	} else if (type instanceof ISourceType) {
-		superInterfaceNames = ((ISourceType)type).getInterfaceNames();
+		ISourceType sourceType = (ISourceType)type;
+		if (sourceType.getName().length == 0) { // if anonymous type
+			if (typeBinding.superInterfaces() != null && typeBinding.superInterfaces().length > 0) {
+				superInterfaceNames = new char[][] {sourceType.getSuperclassName()};
+			} else {
+				superInterfaceNames = sourceType.getInterfaceNames();
+			}
+		} else {
+			superInterfaceNames = sourceType.getInterfaceNames();
+		}
 		separator = '.';
 	} else if (type instanceof HierarchyType) {
-		superInterfaceNames = ((HierarchyType)type).superInterfaceNames;
+		HierarchyType hierarchyType = (HierarchyType)type;
+		if (hierarchyType.name.length == 0) { // if anonymous type
+			if (typeBinding.superInterfaces() != null && typeBinding.superInterfaces().length > 0) {
+				superInterfaceNames = new char[][] {hierarchyType.superclassName};
+			} else {
+				superInterfaceNames = hierarchyType.superInterfaceNames;
+			}
+		} else {
+			superInterfaceNames = hierarchyType.superInterfaceNames;
+		}
 		separator = '.';
 	} else{
 		return null;
@@ -272,14 +305,6 @@
 	}
 	return superinterfaces;
 }
-private void initialize(LookupEnvironment lookupEnvironment, IHierarchyRequestor requestor) {
-	this.lookupEnvironment = lookupEnvironment;
-	this.requestor = requestor;
-
-	this.typeIndex = -1;
-	this.typeModels = new IGenericType[5];
-	this.typeBindings = new ReferenceBinding[5];
-}
 private void remember(IGenericType suppliedType, ReferenceBinding typeBinding) {
 	if (typeBinding == null) return;
 	
@@ -297,61 +322,118 @@
 	typeModels[typeIndex] = suppliedType;
 	typeBindings[typeIndex] = typeBinding;
 }
-private void rememberWithMemberTypes(TypeDeclaration typeDeclaration, HierarchyType enclosingType, ICompilationUnit unit) {
-
-	if (typeDeclaration.binding == null) return;
-
-	// simple super class name
-	char[] superclassName = null;
-	TypeReference superclass = typeDeclaration.superclass;
-	if (superclass != null) {
-		char[][] typeName = superclass.getTypeName();
-		superclassName = typeName == null ? null : typeName[typeName.length-1];
-	}
+private void remember(IType type, ReferenceBinding typeBinding) {
+	if (((CompilationUnit)type.getCompilationUnit()).isOpen()) {
+		try {
+			IGenericType genericType = (IGenericType)((JavaElement)type).getElementInfo();
+			remember(genericType, typeBinding);
+		} catch (JavaModelException e) {
+			// cannot happen since element is open
+			return;
+		}
+	} else {
+		if (typeBinding == null) return;
+		
+		TypeDeclaration typeDeclaration = ((SourceTypeBinding)typeBinding).scope.referenceType();
 	
-	// simple super interface names
-	char[][] superInterfaceNames = null;
-	TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
-	if (superInterfaces != null) {
-		int length = superInterfaces.length;
-		superInterfaceNames = new char[length][];
-		for (int i = 0; i < length; i++) {
-			TypeReference superInterface = superInterfaces[i];
-			char[][] typeName = superInterface.getTypeName();
-			superInterfaceNames[i] = typeName[typeName.length-1];
+		// simple super class name
+		char[] superclassName = null;
+		TypeReference superclass;
+		if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+			superclass = typeDeclaration.allocation.type;
+		} else {
+			superclass = typeDeclaration.superclass;
+		}
+		if (superclass != null) {
+			char[][] typeName = superclass.getTypeName();
+			superclassName = typeName == null ? null : typeName[typeName.length-1];
+		}
+		
+		// simple super interface names
+		char[][] superInterfaceNames = null;
+		TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+		if (superInterfaces != null) {
+			int length = superInterfaces.length;
+			superInterfaceNames = new char[length][];
+			for (int i = 0; i < length; i++) {
+				TypeReference superInterface = superInterfaces[i];
+				char[][] typeName = superInterface.getTypeName();
+				superInterfaceNames[i] = typeName[typeName.length-1];
+			}
+		}
+	
+		HierarchyType hierarchyType = new HierarchyType(
+			type, 
+			!typeDeclaration.isInterface(),
+			typeDeclaration.name,
+			typeDeclaration.binding.modifiers,
+			superclassName,
+			superInterfaceNames);
+		remember(hierarchyType, typeDeclaration.binding);
+	}
+
+}
+/*
+ * Remembers all type bindings defined in the given parsed unit, adding local/anonymous types if specified.
+ */
+private void rememberAllTypes(CompilationUnitDeclaration parsedUnit, org.eclipse.jdt.core.ICompilationUnit cu, boolean includeLocalTypes) {
+	TypeDeclaration[] types = parsedUnit.types;
+	if (types != null) {
+		for (int i = 0, length = types.length; i < length; i++) {
+			TypeDeclaration type = types[i];
+			rememberWithMemberTypes(type, cu.getType(new String(type.name)));
 		}
 	}
-
-	HierarchyType hierarchyType = new HierarchyType(
-		enclosingType, 
-		!typeDeclaration.isInterface(),
-		typeDeclaration.name,
-		typeDeclaration.binding.modifiers,
-		superclassName,
-		superInterfaceNames,
-		unit);
-	remember(hierarchyType, typeDeclaration.binding);
-
-	// propagate into member types
-	if (typeDeclaration.memberTypes == null) return;
-	MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
-	for (int i = 0, max = memberTypes.length; i < max; i++){
-		rememberWithMemberTypes(memberTypes[i], hierarchyType, unit);
+	if (includeLocalTypes && parsedUnit.localTypes != null) {
+		HandleFactory factory = new HandleFactory();
+		HashSet existingElements = new HashSet(parsedUnit.localTypeCount);
+		HashMap knownScopes = new HashMap(parsedUnit.localTypeCount);
+		for (int i = 0; i < parsedUnit.localTypeCount; i++) {
+			LocalTypeBinding localType = parsedUnit.localTypes[i];
+			ClassScope classScope = localType.scope;
+			TypeDeclaration typeDecl = classScope.referenceType();
+			IType typeHandle = (IType)factory.createElement(classScope, cu, existingElements, knownScopes);
+			rememberWithMemberTypes(typeDecl, typeHandle);
+		}
 	}
 }
-private void rememberWithMemberTypes(ISourceType suppliedType, ReferenceBinding typeBinding) {
-	if (typeBinding == null) return;
-
-	remember(suppliedType, typeBinding);
-
-	ISourceType[] memberTypes = suppliedType.getMemberTypes();
-	if (memberTypes == null) return;
-	for (int m = memberTypes.length; --m >= 0;) {
-		ISourceType memberType = memberTypes[m];
-		rememberWithMemberTypes(memberType, typeBinding.getMemberType(memberType.getName()));
+private void rememberWithMemberTypes(TypeDeclaration typeDecl, IType typeHandle) {
+	remember(typeHandle, typeDecl.binding);
+	
+	TypeDeclaration[] memberTypes = typeDecl.memberTypes;
+	if (memberTypes != null) {
+		for (int i = 0, length = memberTypes.length; i < length; i++) {
+			TypeDeclaration memberType = memberTypes[i];
+			rememberWithMemberTypes(memberType, typeHandle.getType(new String(memberType.name)));
+		}
 	}
 }
-private void reportHierarchy() {
+private void reportHierarchy(IType focus, CompilationUnitDeclaration parsedUnit, BinaryTypeBinding binaryTypeBinding) {
+	
+	// set focus type binding
+	if (focus != null) {
+		if (binaryTypeBinding != null) {
+			// binary type
+			this.focusType = binaryTypeBinding;
+		} else {
+			// source type
+			Member declaringMember = ((Member)focus).getOuterMostLocalContext();
+			if (declaringMember == null) {
+				// top level or member type
+				char[] fullyQualifiedName = focus.getFullyQualifiedName().toCharArray();
+				setFocusType(CharOperation.splitOn('.', fullyQualifiedName));
+			} else {
+				// anonymous or local type
+				if (parsedUnit != null) {
+					TypeDeclaration typeDecl = new ASTNodeFinder(parsedUnit).findType(focus);
+					if (typeDecl != null) {
+						this.focusType = typeDecl.binding;
+					}
+				} 
+			}
+		}
+	}
+	
 	int objectIndex = -1;
 	for (int current = typeIndex; current >= 0; current--) {
 		ReferenceBinding typeBinding = typeBindings[current];
@@ -384,145 +466,15 @@
 	}
 }
 private void reset(){
-	lookupEnvironment.reset();
+	this.lookupEnvironment.reset();
 
+	this.focusType = null;
+	this.superTypesOnly = false;
 	this.typeIndex = -1;
 	this.typeModels = new IGenericType[5];
 	this.typeBindings = new ReferenceBinding[5];
 }
 /**
- * Resolve the supertypes for the supplied source types.
- * Inform the requestor of the resolved supertypes for each
- * supplied source type using:
- *    connect(ISourceType suppliedType, IGenericType superclass, IGenericType[] superinterfaces)
- *
- * Also inform the requestor of the supertypes of each
- * additional requested super type which is also a source type
- * instead of a binary type.
- */
-
-public void resolve(IGenericType[] suppliedTypes, IProgressMonitor monitor) {
-	resolve(suppliedTypes, null, monitor);
-}
-/**
- * Resolve the supertypes for the supplied source types.
- * Inform the requestor of the resolved supertypes for each
- * supplied source type using:
- *    connect(ISourceType suppliedType, IGenericType superclass, IGenericType[] superinterfaces)
- *
- * Also inform the requestor of the supertypes of each
- * additional requested super type which is also a source type
- * instead of a binary type.
- */
-
-public void resolve(IGenericType[] suppliedTypes, ICompilationUnit[] sourceUnits, IProgressMonitor monitor) {
-	try {
-		int suppliedLength = suppliedTypes == null ? 0 : suppliedTypes.length;
-		int sourceLength = sourceUnits == null ? 0 : sourceUnits.length;
-		CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[suppliedLength + sourceLength];
-		
-		// cache binary type bidings
-		BinaryTypeBinding[] binaryBindings = new BinaryTypeBinding[suppliedLength];
-		for (int i = 0; i < suppliedLength; i++) {
-			if (suppliedTypes[i].isBinaryType()) {
-				IBinaryType binaryType = (IBinaryType) suppliedTypes[i];
-				try {
-					binaryBindings[i] = lookupEnvironment.cacheBinaryType(binaryType, false);
-				} catch (AbortCompilation e) {
-					// classpath problem for this type: ignore
-				}
-			}
-		}
-		
-		// build type bindings
-		for (int i = 0; i < suppliedLength; i++) {
-			if (suppliedTypes[i].isBinaryType()) {
-				if (binaryBindings[i] != null) {
-					try {
-						remember((IBinaryType) suppliedTypes[i], binaryBindings[i]);
-					} catch (AbortCompilation e) {
-						// classpath problem for this type: ignore
-					}
-				}
-			} else {
-				// must start with the top level type
-				ISourceType topLevelType = (ISourceType) suppliedTypes[i];
-				while (topLevelType.getEnclosingType() != null)
-					topLevelType = topLevelType.getEnclosingType();
-				CompilationResult result = new CompilationResult(topLevelType.getFileName(), i, suppliedLength, this.options.maxProblemsPerUnit);
-				units[i] = 
-					SourceTypeConverter.buildCompilationUnit(
-						new ISourceType[]{topLevelType}, 
-						false, // no need for field and methods
-						true, // need member types
-						false, // no need for field initialization
-						lookupEnvironment.problemReporter, 
-						result);
-				if (units[i] != null) {
-					try {
-						lookupEnvironment.buildTypeBindings(units[i]);
-					} catch (AbortCompilation e) {
-						// classpath problem for this type: ignore
-					}
-				}
-			}
-			worked(monitor, 1);
-		}
-		Parser parser = new Parser(lookupEnvironment.problemReporter, true, options.sourceLevel >= CompilerOptions.JDK1_4);
-		for (int i = 0; i < sourceLength; i++){
-			ICompilationUnit sourceUnit = sourceUnits[i];
-			CompilationResult unitResult = new CompilationResult(sourceUnit, suppliedLength+i, suppliedLength+sourceLength, this.options.maxProblemsPerUnit); 
-			CompilationUnitDeclaration parsedUnit = parser.dietParse(sourceUnit, unitResult);
-			if (parsedUnit != null) {
-				units[suppliedLength+i] = parsedUnit;
-				lookupEnvironment.buildTypeBindings(parsedUnit);
-			}
-			worked(monitor, 1);
-		}
-		
-		// complete type bindings (ie. connect super types) and remember them
-		for (int i = 0; i < suppliedLength; i++) {
-			if (!suppliedTypes[i].isBinaryType()) { // note that binary types have already been remembered above
-				CompilationUnitDeclaration parsedUnit = units[i];
-				if (parsedUnit != null) {
-					// must start with the top level type
-					ISourceType topLevelType = (ISourceType) suppliedTypes[i];
-					suppliedTypes[i] = null; // no longer needed pass this point				
-					while (topLevelType.getEnclosingType() != null)
-						topLevelType = topLevelType.getEnclosingType();
-					try {
-						lookupEnvironment.completeTypeBindings(parsedUnit, false);
-						rememberWithMemberTypes(topLevelType, parsedUnit.types[0].binding);
-					} catch (AbortCompilation e) {
-						// classpath problem for this type: ignore
-					}
-				}
-			}
-			worked(monitor, 1);
-		}
-		for (int i = 0; i < sourceLength; i++) {
-			CompilationUnitDeclaration parsedUnit = units[suppliedLength+i];
-			if (parsedUnit != null) {
-				lookupEnvironment.completeTypeBindings(parsedUnit, false);
-				int typeCount = parsedUnit.types == null ? 0 : parsedUnit.types.length;
-				ICompilationUnit sourceUnit = sourceUnits[i];
-				sourceUnits[i] = null; // no longer needed pass this point
-				for (int j = 0; j < typeCount; j++){
-					rememberWithMemberTypes(parsedUnit.types[j], null, sourceUnit);
-				}
-			}
-			worked(monitor, 1);
-		}
-
-		reportHierarchy();
-		
-	} catch (ClassCastException e){ // work-around for 1GF5W1S - can happen in case duplicates are fed to the hierarchy with binaries hiding sources
-	} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
-	} finally {
-		reset();
-	}
-}
-/**
  * Resolve the supertypes for the supplied source type.
  * Inform the requestor of the resolved supertypes using:
  *    connect(ISourceType suppliedType, IGenericType superclass, IGenericType[] superinterfaces)
@@ -531,36 +483,212 @@
 public void resolve(IGenericType suppliedType) {
 	try {
 		if (suppliedType.isBinaryType()) {
-			remember(suppliedType, lookupEnvironment.cacheBinaryType((IBinaryType) suppliedType));
+			BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType((IBinaryType) suppliedType);
+			remember(suppliedType, binaryTypeBinding);
+			this.superTypesOnly = true;
+			reportHierarchy(this.requestor.getType(), null, binaryTypeBinding);
 		} else {
-			// must start with the top level type
-			ISourceType topLevelType = (ISourceType) suppliedType;
-			while (topLevelType.getEnclosingType() != null)
-				topLevelType = topLevelType.getEnclosingType();
-			CompilationResult result = new CompilationResult(topLevelType.getFileName(), 1, 1, this.options.maxProblemsPerUnit);
-			CompilationUnitDeclaration unit =
-				SourceTypeConverter.buildCompilationUnit(
-					new ISourceType[]{topLevelType}, 
-					false, // no need for field and methods
-					true, // need member types
-					false, // no need for field initialization
-					lookupEnvironment.problemReporter, 
-					result);
-
-			if (unit != null) {
-				lookupEnvironment.buildTypeBindings(unit);
-				rememberWithMemberTypes(topLevelType, unit.types[0].binding);
-
-				lookupEnvironment.completeTypeBindings(unit, false);
-			}
+			org.eclipse.jdt.core.ICompilationUnit cu = ((SourceTypeElementInfo)suppliedType).getHandle().getCompilationUnit();
+			HashSet localTypes = new HashSet();
+			localTypes.add(cu.getPath().toString());
+			this.superTypesOnly = true;
+			resolve(new Openable[] {(Openable)cu}, localTypes, null);
 		}
-		reportHierarchy();
 	} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
 	} finally {
 		reset();
 	}
 }
 /**
+ * Resolve the supertypes for the types contained in the given openables (ICompilationUnits and/or IClassFiles).
+ * Inform the requestor of the resolved supertypes for each
+ * supplied source type using:
+ *    connect(ISourceType suppliedType, IGenericType superclass, IGenericType[] superinterfaces)
+ *
+ * Also inform the requestor of the supertypes of each
+ * additional requested super type which is also a source type
+ * instead of a binary type.
+ */
+
+public void resolve(Openable[] openables, HashSet localTypes, IProgressMonitor monitor) {
+	try {
+		int openablesLength = openables.length;
+		CompilationUnitDeclaration[] parsedUnits = new CompilationUnitDeclaration[openablesLength];
+		boolean[] hasLocalType = new boolean[openablesLength];
+		org.eclipse.jdt.core.ICompilationUnit[] cus = new org.eclipse.jdt.core.ICompilationUnit[openablesLength];
+		int unitsIndex = 0;
+		
+		CompilationUnitDeclaration focusUnit = null;
+		BinaryTypeBinding focusBinaryBinding = null;
+		IType focus = this.requestor.getType();
+		Openable focusOpenable = null;
+		if (focus != null) {
+			if (focus.isBinary()) {
+				focusOpenable = (Openable)focus.getClassFile();
+			} else {
+				focusOpenable = (Openable)focus.getCompilationUnit();
+			}
+		}
+		
+		// build type bindings
+		Parser parser = new Parser(this.lookupEnvironment.problemReporter, true);
+		for (int i = 0; i < openablesLength; i++) {
+			Openable openable = openables[i];
+			if (openable instanceof org.eclipse.jdt.core.ICompilationUnit) {
+				org.eclipse.jdt.core.ICompilationUnit cu = (org.eclipse.jdt.core.ICompilationUnit)openable;
+
+				// contains a potential subtype as a local or anonymous type?
+				boolean containsLocalType = false;
+				if (localTypes == null) { // case of hierarchy on region
+					containsLocalType = false;
+				} else {
+					IPath path = cu.getPath();
+					containsLocalType = localTypes.contains(path.toString());
+				}
+				
+				// build parsed unit
+				CompilationUnitDeclaration parsedUnit = null;
+				if (cu.isOpen()) {
+					// create parsed unit from source element infos
+					CompilationResult result = new CompilationResult(((ICompilationUnit)cu).getFileName(), i, openablesLength, this.options.maxProblemsPerUnit);
+					SourceTypeElementInfo[] typeInfos = null;
+					try {
+						IType[] topLevelTypes = cu.getTypes();
+						int topLevelLength = topLevelTypes.length;
+						typeInfos = new SourceTypeElementInfo[topLevelLength];
+						for (int j = 0; j < topLevelLength; j++) {
+							IType topLevelType = topLevelTypes[j];
+							typeInfos[j] = (SourceTypeElementInfo)((JavaElement)topLevelType).getElementInfo();
+						}
+					} catch (JavaModelException e) {
+						// types/cu exist since cu is opened
+					}
+					if (!containsLocalType) {
+						parsedUnit = 
+							SourceTypeConverter.buildCompilationUnit(
+								typeInfos, 
+								SourceTypeConverter.MEMBER_TYPE, // need member types
+								// no need for field initialization
+								this.lookupEnvironment.problemReporter, 
+								result);
+					} else {
+						parsedUnit =
+							ElementInfoConverter.buildCompilationUnit(
+								typeInfos, 
+								true, // need local types
+								this.lookupEnvironment.problemReporter, 
+								result);
+						parsedUnit.bits |= ASTNode.HasAllMethodBodies;
+					}
+				} else {
+					// create parsed unit from file
+					IResource file = cu.getResource();
+					String osPath = file.getLocation().toOSString();
+					ICompilationUnit sourceUnit = this.requestor.createCompilationUnitFromPath(openable, osPath);
+					
+					CompilationResult unitResult = new CompilationResult(sourceUnit, i, openablesLength, this.options.maxProblemsPerUnit); 
+					parsedUnit = parser.dietParse(sourceUnit, unitResult);
+				}
+
+				if (parsedUnit != null) {
+					hasLocalType[unitsIndex] = containsLocalType;
+					cus[unitsIndex] = cu;
+					parsedUnits[unitsIndex++] = parsedUnit;
+					try {
+						this.lookupEnvironment.buildTypeBindings(parsedUnit);
+						if (openable.equals(focusOpenable)) {
+							focusUnit = parsedUnit;
+						}
+					} catch (AbortCompilation e) {
+						// classpath problem for this type: ignore
+					}
+				}
+			} else {
+				// cache binary type binding
+				ClassFile classFile = (ClassFile)openable;
+				IBinaryType binaryType = null;
+				if (classFile.isOpen()) {
+					// create binary type from info
+					IType type = classFile.getType();
+					try {
+						binaryType = (IBinaryType)((JavaElement)type).getElementInfo();
+					} catch (JavaModelException e) {
+						// type exists since class file is opened
+					}
+				} else {
+					// create binary type from file
+					if (classFile.getPackageFragmentRoot().isArchive()) {
+						binaryType = this.requestor.createInfoFromClassFileInJar(classFile);
+					} else {
+						IResource file = classFile.getResource();
+						String osPath = file.getLocation().toOSString();
+						binaryType = this.requestor.createInfoFromClassFile(classFile, osPath);
+					}
+				}
+				if (binaryType != null) {
+					try {
+						BinaryTypeBinding binaryTypeBinding = this.lookupEnvironment.cacheBinaryType(binaryType, false);
+						remember(binaryType, binaryTypeBinding);
+						if (openable.equals(focusOpenable)) {
+							focusBinaryBinding = binaryTypeBinding;
+						}
+					} catch (AbortCompilation e) {
+						// classpath problem for this type: ignore
+					}
+				}
+			}
+		}
+				
+		
+		// complete type bindings (ie. connect super types)
+		for (int i = 0; i < unitsIndex; i++) {
+			CompilationUnitDeclaration parsedUnit = parsedUnits[i];
+			if (parsedUnit != null) {
+				try {
+					boolean containsLocalType = hasLocalType[i];
+					if (containsLocalType) { // NB: no-op if method bodies have been already parsed
+						parser.getMethodBodies(parsedUnit);
+					}
+					this.lookupEnvironment.completeTypeBindings(parsedUnit, true/*build constructor only*/);
+				} catch (AbortCompilation e) {
+					// classpath problem for this type: ignore
+				}
+			}
+			worked(monitor, 1);
+		}
+		
+		// remember type bindings
+		for (int i = 0; i < unitsIndex; i++) {
+			CompilationUnitDeclaration parsedUnit = parsedUnits[i];
+			if (parsedUnit != null) {
+				boolean containsLocalType = hasLocalType[i];
+				if (containsLocalType) {
+					parsedUnit.scope.faultInTypes();
+					parsedUnit.scope.verifyMethods(this.lookupEnvironment.methodVerifier());
+					parsedUnit.resolve();
+				}
+					
+				rememberAllTypes(parsedUnit, cus[i], containsLocalType);
+			}
+		}
+
+		reportHierarchy(focus, focusUnit, focusBinaryBinding);
+		
+	} catch (ClassCastException e){ // work-around for 1GF5W1S - can happen in case duplicates are fed to the hierarchy with binaries hiding sources
+	} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
+	} finally {
+		reset();
+	}
+}
+private void setEnvironment(LookupEnvironment lookupEnvironment, HierarchyBuilder requestor) {
+	this.lookupEnvironment = lookupEnvironment;
+	this.requestor = requestor;
+
+	this.typeIndex = -1;
+	this.typeModels = new IGenericType[5];
+	this.typeBindings = new ReferenceBinding[5];
+}
+/**
  * Set the focus type (ie. the type that this resolver is computing the hierarch for.
  * Returns the binding of this focus type or null if it could not be found.
  */
@@ -575,7 +703,7 @@
 public boolean subOrSuperOfFocus(ReferenceBinding typeBinding) {
 	if (this.focusType == null) return true; // accept all types (case of hierarchy in a region)
 	if (this.subTypeOfType(this.focusType, typeBinding)) return true;
-	if (this.subTypeOfType(typeBinding, this.focusType)) return true;
+	if (!this.superTypesOnly && this.subTypeOfType(typeBinding, this.focusType)) return true;
 	return false;
 }
 private boolean subTypeOfType(ReferenceBinding subType, ReferenceBinding typeBinding) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
index fb21984..c7e0cd6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.hierarchy;
 
-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.internal.compiler.env.IGenericType;
 
 /**
@@ -20,30 +20,27 @@
  */
 public class HierarchyType implements IGenericType {
 
-	public HierarchyType enclosingType;
+	public IType typeHandle;
 	public boolean isClass;
 	public char[] name;
 	public int modifiers;
 	public char[] superclassName;
 	public char[][] superInterfaceNames;
-	public ICompilationUnit originatingUnit;
 	
 public HierarchyType(
-	HierarchyType enclosingType, 
+	IType typeHandle, 
 	boolean isClass, 
 	char[] name, 
 	int modifiers, 
 	char[] superclassName,
-	char[][] superInterfaceNames,
-	ICompilationUnit originatingUnit) {
+	char[][] superInterfaceNames) {
 		
-	this.enclosingType = enclosingType;
+	this.typeHandle = typeHandle;
 	this.isClass = isClass;
 	this.name = name;
 	this.modifiers = modifiers;
 	this.superclassName = superclassName;
 	this.superInterfaceNames = superInterfaceNames;
-	this.originatingUnit = originatingUnit;
 }
 /**
  * Answer the file name which defines the type.
@@ -56,7 +53,7 @@
  * e.g. "c:/com/ibm/compiler/java/api/Compiler.java" 
  */
 public char[] getFileName() {
-	return originatingUnit.getFileName();
+	return this.typeHandle.getCompilationUnit().getElementName().toCharArray();
 }
 /**
  * Answer an int whose bits are set according the access constants
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
index a6d7af2..be926b8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
@@ -10,42 +10,30 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.hierarchy;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.*;
 
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.SubProgressMonitor;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.IWorkingCopy;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchConstants;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.*;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.env.IGenericType;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TagBits;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.IInfoConstants;
-import org.eclipse.jdt.internal.core.search.IndexSearchAdapter;
+import org.eclipse.jdt.internal.core.search.IndexQueryRequestor;
+import org.eclipse.jdt.internal.core.search.JavaSearchParticipant;
 import org.eclipse.jdt.internal.core.search.SubTypeSearchJob;
-import org.eclipse.jdt.internal.core.search.indexing.AbstractIndexer;
 import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
 import org.eclipse.jdt.internal.core.search.matching.SuperTypeReferencePattern;
+import org.eclipse.jdt.internal.core.util.HandleFactory;
 
-public class IndexBasedHierarchyBuilder extends HierarchyBuilder {
+public class IndexBasedHierarchyBuilder extends HierarchyBuilder implements SuffixConstants {
 	public static final int MAXTICKS = 800; // heuristic so that there still progress for deep hierachies
 	/**
 	 * A temporary cache of compilation units to handles to speed info
@@ -108,40 +96,7 @@
 	this.binariesFromIndexMatches = new HashMap(10);
 	this.scope = scope;
 }
-/**
- * Add the type info from the given hierarchy binary type to the given list of infos.
- */
-private void addInfoFromBinaryIndexMatch(Openable handle, HierarchyBinaryType binaryType, ArrayList infos) throws JavaModelException {
-	infos.add(binaryType);
-	this.infoToHandle.put(binaryType, handle);
-}
-protected void addInfoFromClosedElement(Openable handle,ArrayList infos,ArrayList units,String resourcePath) throws JavaModelException {
-	HierarchyBinaryType binaryType = (HierarchyBinaryType) binariesFromIndexMatches.get(resourcePath);
-	if (binaryType != null) {
-		this.addInfoFromBinaryIndexMatch(handle, binaryType, infos);
-	} else {
-		super.addInfoFromClosedElement(handle, infos, units, resourcePath);
-	}
-}
-/**
- * Add the type info (and its sibblings type infos) to the given list of infos.
- */
-private void addInfosFromType(IType type, ArrayList infos) throws JavaModelException {
-	if (type.isBinary()) {
-		// add class file
-		ClassFile classFile = (ClassFile)type.getClassFile();
-		if (classFile != null) {
-			this.addInfoFromOpenClassFile(classFile, infos);
-		}
-	} else {
-		// add whole cu (if it is a working copy, it's types can be potential subtypes)
-		CompilationUnit unit = (CompilationUnit)type.getCompilationUnit();
-		if (unit != null) {
-			this.addInfoFromOpenCU(unit, infos);
-		}
-	}
-}
-public void build(boolean computeSubtypes) throws JavaModelException, CoreException {
+public void build(boolean computeSubtypes) {
 	JavaModelManager manager = JavaModelManager.getJavaModelManager();
 	try {
 		// optimize access to zip files while building hierarchy
@@ -149,20 +104,29 @@
 				
 		if (computeSubtypes) {
 			// Note by construction there always is a focus type here
-			boolean focusIsObject = getType().getElementName().equals(new String(IIndexConstants.OBJECT));
+			IType focusType = getType();
+			boolean focusIsObject = focusType.getElementName().equals(new String(IIndexConstants.OBJECT));
 			int amountOfWorkForSubtypes = focusIsObject ? 5 : 80; // percentage of work needed to get possible subtypes
 			IProgressMonitor possibleSubtypesMonitor = 
 				this.hierarchy.progressMonitor == null ? 
 					null : 
 					new SubProgressMonitor(this.hierarchy.progressMonitor, amountOfWorkForSubtypes);
-			String[] allPossibleSubtypes = this.determinePossibleSubTypes(possibleSubtypesMonitor);
+			HashSet localTypes = new HashSet(10); // contains the paths that have potential subtypes that are local/anonymous types
+			String[] allPossibleSubtypes;
+			if (((Member)focusType).getOuterMostLocalContext() == null) {
+				// top level or member type
+				allPossibleSubtypes = this.determinePossibleSubTypes(localTypes, possibleSubtypesMonitor);
+			} else {
+				// local or anonymous type
+				allPossibleSubtypes = new String[0];
+			}
 			if (allPossibleSubtypes != null) {
 				IProgressMonitor buildMonitor = 
 					this.hierarchy.progressMonitor == null ? 
 						null : 
 						new SubProgressMonitor(this.hierarchy.progressMonitor, 100 - amountOfWorkForSubtypes);
 				this.hierarchy.initialize(allPossibleSubtypes.length);
-				buildFromPotentialSubtypes(allPossibleSubtypes, buildMonitor);
+				buildFromPotentialSubtypes(allPossibleSubtypes, localTypes, buildMonitor);
 			}
 		} else {
 			this.hierarchy.initialize(1);
@@ -172,66 +136,65 @@
 		manager.flushZipFiles();
 	}
 }
-private void buildForProject(JavaProject project, ArrayList infos, ArrayList units, IWorkingCopy[] workingCopies, IProgressMonitor monitor) throws JavaModelException {
+private void buildForProject(JavaProject project, ArrayList potentialSubtypes, org.eclipse.jdt.core.ICompilationUnit[] workingCopies, HashSet localTypes, IProgressMonitor monitor) throws JavaModelException {
 	// copy vectors into arrays
-	IGenericType[] genericTypes;
-	int infosSize = infos.size();
-	if (infosSize > 0) {
-		genericTypes = new IGenericType[infosSize];
-		infos.toArray(genericTypes);
-	} else {
-		genericTypes = new IGenericType[0];
-	}
-	ICompilationUnit[] compilationUnits;
-	int unitsSize = units.size();
-	if (unitsSize > 0) {
-		compilationUnits = new ICompilationUnit[unitsSize];
-		units.toArray(compilationUnits);
-	} else {
-		compilationUnits = new ICompilationUnit[0];
-	}
+	int openablesLength = potentialSubtypes.size();
+	Openable[] openables = new Openable[openablesLength];
+	potentialSubtypes.toArray(openables);
 
 	// resolve
-	if (infosSize > 0 || unitsSize > 0) {
+	if (openablesLength > 0) {
 		this.searchableEnvironment = (SearchableEnvironment)project.getSearchableNameEnvironment();
 		IType focusType = this.getType();
 		this.nameLookup = project.getNameLookup();
 		boolean inProjectOfFocusType = focusType != null && focusType.getJavaProject().equals(project);
-		synchronized(this.nameLookup) { // prevent 2 concurrent accesses to name lookup while the units to look inside are set
-			if (inProjectOfFocusType) {
-				org.eclipse.jdt.core.ICompilationUnit unitToLookInside = focusType.getCompilationUnit();
-				IWorkingCopy[] unitsToLookInside;
-				if (unitToLookInside != null) {
-					int wcLength = workingCopies == null ? 0 : workingCopies.length;
-					if (wcLength == 0) {
-						unitsToLookInside = new IWorkingCopy[] {unitToLookInside};
-					} else {
-						unitsToLookInside = new IWorkingCopy[wcLength+1];
-						unitsToLookInside[0] = unitToLookInside;
-						System.arraycopy(workingCopies, 0, unitsToLookInside, 1, wcLength);
-					}
+		if (inProjectOfFocusType) {
+			org.eclipse.jdt.core.ICompilationUnit unitToLookInside = focusType.getCompilationUnit();
+			org.eclipse.jdt.core.ICompilationUnit[] unitsToLookInside;
+			if (unitToLookInside != null) {
+				int wcLength = workingCopies == null ? 0 : workingCopies.length;
+				if (wcLength == 0) {
+					unitsToLookInside = new org.eclipse.jdt.core.ICompilationUnit[] {unitToLookInside};
 				} else {
-					unitsToLookInside = workingCopies;
+					unitsToLookInside = new org.eclipse.jdt.core.ICompilationUnit[wcLength+1];
+					unitsToLookInside[0] = unitToLookInside;
+					System.arraycopy(workingCopies, 0, unitsToLookInside, 1, wcLength);
 				}
-				this.nameLookup.setUnitsToLookInside(unitsToLookInside);
+			} else {
+				unitsToLookInside = workingCopies;
 			}
-			try {
-				this.hierarchyResolver = 
-					new HierarchyResolver(this.searchableEnvironment, project.getOptions(true), this, new DefaultProblemFactory());
-				if (focusType != null) {
+			this.nameLookup.setUnitsToLookInside(unitsToLookInside); // NB: this uses a PerThreadObject, so it is thread safe
+		}
+		try {
+			this.hierarchyResolver = 
+				new HierarchyResolver(this.searchableEnvironment, project.getOptions(true), this, new DefaultProblemFactory());
+			if (focusType != null) {
+				Member declaringMember = ((Member)focusType).getOuterMostLocalContext();
+				if (declaringMember == null) {
+					// top level or member type
 					char[] fullyQualifiedName = focusType.getFullyQualifiedName().toCharArray();
-					ReferenceBinding focusTypeBinding = this.hierarchyResolver.setFocusType(CharOperation.splitOn('.', fullyQualifiedName));
-					if (focusTypeBinding == null 
-						|| (!inProjectOfFocusType && (focusTypeBinding.tagBits & TagBits.HierarchyHasProblems) > 0)) {
+					if (!inProjectOfFocusType && project.getSearchableNameEnvironment().findType(CharOperation.splitOn('.', fullyQualifiedName)) == null) {
 						// focus type is not visible in this project: no need to go further
 						return;
 					}
+				} else {
+					// local or anonymous type
+					Openable openable;
+					if (declaringMember.isBinary()) {
+						openable = (Openable)declaringMember.getClassFile();
+					} else {
+						openable = (Openable)declaringMember.getCompilationUnit();
+					}
+					localTypes = new HashSet();
+					localTypes.add(openable.getPath().toString());
+					this.hierarchyResolver.resolve(new Openable[] {openable}, localTypes, monitor);
+					return;
 				}
-				this.hierarchyResolver.resolve(genericTypes, compilationUnits, monitor);
-			} finally {
-				if (inProjectOfFocusType) {
-					this.nameLookup.setUnitsToLookInside(null);
-				}
+			}
+			this.hierarchyResolver.resolve(openables, localTypes, monitor);
+		} finally {
+			if (inProjectOfFocusType) {
+				this.nameLookup.setUnitsToLookInside(null);
 			}
 		}
 	}
@@ -239,18 +202,18 @@
 /**
  * Configure this type hierarchy based on the given potential subtypes.
  */
-private void buildFromPotentialSubtypes(String[] allPotentialSubTypes, IProgressMonitor monitor) {
+private void buildFromPotentialSubtypes(String[] allPotentialSubTypes, HashSet localTypes, IProgressMonitor monitor) {
 	IType focusType = this.getType();
 		
 	// substitute compilation units with working copies
 	HashMap wcPaths = new HashMap(); // a map from path to working copies
 	int wcLength;
-	IWorkingCopy[] workingCopies = this.getWokingCopies();
+	org.eclipse.jdt.core.ICompilationUnit[] workingCopies = this.hierarchy.workingCopies;
 	if (workingCopies != null && (wcLength = workingCopies.length) > 0) {
 		String[] newPaths = new String[wcLength];
 		for (int i = 0; i < wcLength; i++) {
-			IWorkingCopy workingCopy = workingCopies[i];
-			String path = workingCopy.getOriginalElement().getPath().toString();
+			org.eclipse.jdt.core.ICompilationUnit workingCopy = workingCopies[i];
+			String path = workingCopy.getPath().toString();
 			wcPaths.put(path, workingCopy);
 			newPaths[i] = path;
 		}
@@ -284,14 +247,13 @@
 	 * be sorted in reverse alphabetical order so that top level types are cached
 	 * before their inner types.
 	 */
-	Util.sortReverseOrder(allPotentialSubTypes);
+	org.eclipse.jdt.internal.core.util.Util.sortReverseOrder(allPotentialSubTypes);
 	
-	ArrayList infos = new ArrayList();
-	ArrayList units = new ArrayList();
+	ArrayList potentialSubtypes = new ArrayList();
 
 	try {
 		// create element infos for subtypes
-		HandleFactory factory = new HandleFactory(ResourcesPlugin.getWorkspace());
+		HandleFactory factory = new HandleFactory();
 		IJavaProject currentProject = null;
 		if (monitor != null) monitor.beginTask("", length*2 /* 1 for build binding, 1 for connect hierarchy*/); //$NON-NLS-1$
 		for (int i = 0; i < length; i++) {
@@ -302,7 +264,7 @@
 				if (i > 0 && resourcePath.equals(allPotentialSubTypes[i-1])) continue;
 				
 				Openable handle;
-				IWorkingCopy workingCopy = (IWorkingCopy)wcPaths.get(resourcePath);
+				org.eclipse.jdt.core.ICompilationUnit workingCopy = (org.eclipse.jdt.core.ICompilationUnit)wcPaths.get(resourcePath);
 				if (workingCopy != null) {
 					handle = (Openable)workingCopy;
 				} else {
@@ -316,17 +278,15 @@
 				IJavaProject project = handle.getJavaProject();
 				if (currentProject == null) {
 					currentProject = project;
-					infos = new ArrayList(5);
-					units = new ArrayList(5);
+					potentialSubtypes = new ArrayList(5);
 				} else if (!currentProject.equals(project)) {
 					// build current project
-					this.buildForProject((JavaProject)currentProject, infos, units, workingCopies, monitor);
+					this.buildForProject((JavaProject)currentProject, potentialSubtypes, workingCopies, localTypes, monitor);
 					currentProject = project;
-					infos = new ArrayList(5);
-					units = new ArrayList(5);
+					potentialSubtypes = new ArrayList(5);
 				}
 				
-				this.addInfoFromElement(handle, infos, units, resourcePath);
+				potentialSubtypes.add(handle);
 			} catch (JavaModelException e) {
 				continue;
 			}
@@ -337,21 +297,30 @@
 			if (currentProject == null) {
 				// case of no potential subtypes
 				currentProject = focusType.getJavaProject();
-				this.addInfosFromType(focusType, infos);
+				if (focusType.isBinary()) {
+					potentialSubtypes.add(focusType.getClassFile());
+				} else {
+					potentialSubtypes.add(focusType.getCompilationUnit());
+				}
 			}
-			this.buildForProject((JavaProject)currentProject, infos, units, workingCopies, monitor);
+			this.buildForProject((JavaProject)currentProject, potentialSubtypes, workingCopies, localTypes, monitor);
 		} catch (JavaModelException e) {
+			// ignore
 		}
 		
 		// Compute hierarchy of focus type if not already done (case of a type with potential subtypes that are not real subtypes)
 		if (!this.hierarchy.contains(focusType)) {
 			try {
 				currentProject = focusType.getJavaProject();
-				infos = new ArrayList();
-				units = new ArrayList();
-				this.addInfosFromType(focusType, infos);
-				this.buildForProject((JavaProject)currentProject, infos, units, workingCopies, monitor);
+				potentialSubtypes = new ArrayList();
+				if (focusType.isBinary()) {
+					potentialSubtypes.add(focusType.getClassFile());
+				} else {
+					potentialSubtypes.add(focusType.getCompilationUnit());
+				}
+				this.buildForProject((JavaProject)currentProject, potentialSubtypes, workingCopies, localTypes, monitor);
 			} catch (JavaModelException e) {
+				// ignore
 			}
 		}
 		
@@ -363,7 +332,7 @@
 		if (monitor != null) monitor.done();
 	}
 }
-protected ICompilationUnit createCompilationUnitFromPath(Openable handle,String osPath) throws JavaModelException {
+protected ICompilationUnit createCompilationUnitFromPath(Openable handle,String osPath) {
 	ICompilationUnit unit = super.createCompilationUnitFromPath(handle, osPath);
 	this.cuToHandle.put(unit, handle);
 	return unit;
@@ -372,21 +341,22 @@
  * Returns all of the possible subtypes of this type hierarchy.
  * Returns null if they could not be determine.
  */
-private String[] determinePossibleSubTypes(IProgressMonitor monitor) throws JavaModelException, CoreException {
+private String[] determinePossibleSubTypes(final HashSet localTypes, IProgressMonitor monitor) {
 
 	class PathCollector implements IPathRequestor {
 		HashSet paths = new HashSet(10);
-		public void acceptPath(String path) {
+		public void acceptPath(String path, boolean containsLocalTypes) {
 			paths.add(path);
+			if (containsLocalTypes) {
+				localTypes.add(path);
+			}
 		}
 	}
 	PathCollector collector = new PathCollector();
-	IProject project = this.hierarchy.javaProject().getProject();
 	
 	try {
 		if (monitor != null) monitor.beginTask("", MAXTICKS); //$NON-NLS-1$
 		searchAllPossibleSubTypes(
-			project.getWorkspace(),
 			this.getType(),
 			this.scope,
 			this.binariesFromIndexMatches,
@@ -413,32 +383,13 @@
 	if (genericType instanceof HierarchyType) {
 		IType type = (IType)this.infoToHandle.get(genericType);
 		if (type == null) {
-			HierarchyType hierarchyType = (HierarchyType)genericType;
-			CompilationUnit unit = (CompilationUnit)this.cuToHandle.get(hierarchyType.originatingUnit);
-
-			// collect enclosing type names
-			ArrayList enclosingTypeNames = new ArrayList();
-			HierarchyType enclosingType = hierarchyType;
-			do {
-				enclosingTypeNames.add(enclosingType.name);
-				enclosingType = enclosingType.enclosingType;
-			} while (enclosingType != null);
-			int length = enclosingTypeNames.size();
-			char[][] simpleTypeNames = new char[length][];
-			enclosingTypeNames.toArray(simpleTypeNames);
-
-			// build handle
-			type = unit.getType(new String(simpleTypeNames[length-1]));
-			for (int i = length-2; i >= 0; i--) {
-				type = type.getType(new String(simpleTypeNames[i]));
-			}
+			type = ((HierarchyType)genericType).typeHandle;
 			this.infoToHandle.put(genericType, type);
 		}
 		return type;
 	} else
 		return super.getHandle(genericType);
 }
-
 /**
  * Find the set of candidate subtypes of a given type.
  *
@@ -450,56 +401,58 @@
  */
 
 public static void searchAllPossibleSubTypes(
-	IWorkspace workbench,
 	IType type,
 	IJavaSearchScope scope,
 	final Map binariesFromIndexMatches,
 	final IPathRequestor pathRequestor,
 	int waitingPolicy,	// WaitUntilReadyToSearch | ForceImmediateSearch | CancelIfNotReadyToSearch
-	IProgressMonitor progressMonitor)  throws JavaModelException, CoreException {
+	IProgressMonitor progressMonitor) {
 
 	/* embed constructs inside arrays so as to pass them to (inner) collector */
 	final Queue awaitings = new Queue();
 	final HashtableOfObject foundSuperNames = new HashtableOfObject(5);
 
-	IndexManager indexManager = ((JavaModelManager)JavaModelManager.getJavaModelManager()).getIndexManager();
+	IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
 
 	/* use a special collector to collect paths and queue new subtype names */
-	IIndexSearchRequestor searchRequestor = new IndexSearchAdapter(){
-		public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char[] enclosingTypeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers) {
-			pathRequestor.acceptPath(resourcePath);
-			int suffix = resourcePath.toLowerCase().indexOf(".class"); //$NON-NLS-1$
+	IndexQueryRequestor searchRequestor = new IndexQueryRequestor() {
+		public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant) {
+			SuperTypeReferencePattern record = (SuperTypeReferencePattern)indexRecord;
+			pathRequestor.acceptPath(documentPath, record.enclosingTypeName == IIndexConstants.ONE_ZERO);
+			char[] typeName = record.simpleName;
+			int suffix = documentPath.toLowerCase().indexOf(SUFFIX_STRING_class);
 			if (suffix != -1){ 
-				HierarchyBinaryType binaryType = (HierarchyBinaryType)binariesFromIndexMatches.get(resourcePath);
+				HierarchyBinaryType binaryType = (HierarchyBinaryType)binariesFromIndexMatches.get(documentPath);
 				if (binaryType == null){
+					char[] enclosingTypeName = record.enclosingTypeName;
 					if (enclosingTypeName == IIndexConstants.ONE_ZERO) { // local or anonymous type
-						int lastSlash = resourcePath.lastIndexOf('/');
-						if (lastSlash == -1) return;
-						int lastDollar = resourcePath.lastIndexOf('$');
-						if (lastDollar == -1) return;
-						enclosingTypeName = resourcePath.substring(lastSlash+1, lastDollar).toCharArray();
-						typeName = resourcePath.substring(lastDollar+1, suffix).toCharArray();
+						int lastSlash = documentPath.lastIndexOf('/');
+						if (lastSlash == -1) return true;
+						int lastDollar = documentPath.lastIndexOf('$');
+						if (lastDollar == -1) return true;
+						enclosingTypeName = documentPath.substring(lastSlash+1, lastDollar).toCharArray();
+						typeName = documentPath.substring(lastDollar+1, suffix).toCharArray();
 					}
-					binaryType = new HierarchyBinaryType(modifiers, qualification, typeName, enclosingTypeName, classOrInterface);
-					binariesFromIndexMatches.put(resourcePath, binaryType);
+					binaryType = new HierarchyBinaryType(record.modifiers, record.pkgName, typeName, enclosingTypeName, record.classOrInterface);
+					binariesFromIndexMatches.put(documentPath, binaryType);
 				}
-				binaryType.recordSuperType(superTypeName, superQualification, superClassOrInterface);
+				binaryType.recordSuperType(record.superSimpleName, record.superQualification, record.superClassOrInterface);
 			}
 			if (!foundSuperNames.containsKey(typeName)){
 				foundSuperNames.put(typeName, typeName);
 				awaitings.add(typeName);
 			}
+			return true;
 		}		
 	};
 	
-	SuperTypeReferencePattern pattern = new SuperTypeReferencePattern(null, null, IJavaSearchConstants.EXACT_MATCH, IJavaSearchConstants.CASE_SENSITIVE);
+	SuperTypeReferencePattern pattern = new SuperTypeReferencePattern(null, null, SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);
+	pattern.focus = type;
 	SubTypeSearchJob job = new SubTypeSearchJob(
-				pattern, 
-				scope,
-				type, 
-				IInfoConstants.PathInfo, 
-				searchRequestor, 
-				indexManager);
+		pattern, 
+		new JavaSearchParticipant(null), // java search only
+		scope, 
+		searchRequestor);
 	
 	/* initialize entry result cache */
 	pattern.entryResults = new HashMap();
@@ -512,7 +465,7 @@
 		char[] currentTypeName = awaitings.retrieve();
 
 		/* all subclasses of OBJECT are actually all types */
-		if (CharOperation.equals(currentTypeName, AbstractIndexer.OBJECT)){
+		if (CharOperation.equals(currentTypeName, IIndexConstants.OBJECT)){
 			currentTypeName = null;
 		}			
 		/* search all index references to a given supertype */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java
index 0c743d5..1819f25 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedHierarchyBuilder.java
@@ -12,6 +12,7 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.SubProgressMonitor;
@@ -22,14 +23,11 @@
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.IWorkingCopy;
 import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.internal.compiler.env.IGenericType;
 import org.eclipse.jdt.internal.core.CompilationUnit;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.JavaProject;
 import org.eclipse.jdt.internal.core.Openable;
-import org.eclipse.jdt.internal.core.Util;
 
 public class RegionBasedHierarchyBuilder extends HierarchyBuilder {
 	
@@ -46,7 +44,7 @@
 		// optimize access to zip files while building hierarchy
 		manager.cacheZipFiles();
 				
-		if (this.hierarchy.type == null || computeSubtypes) {
+		if (this.hierarchy.focusType == null || computeSubtypes) {
 			IProgressMonitor typeInRegionMonitor = 
 				this.hierarchy.progressMonitor == null ? 
 					null : 
@@ -76,77 +74,43 @@
 	if (size != 0) {
 		this.infoToHandle = new HashMap(size);
 	}
-	IType[] types = new IType[size];
-	allTypesInRegion.toArray(types);
-
-	/*
-	 * NOTE: To workaround pb with hierarchy resolver that requests top  
-	 * level types in the process of caching an enclosing type, this needs to
-	 * be sorted in reverse alphabetical order so that top level types are cached
-	 * before their inner types.
-	 */
-	Util.sort(
-		types,
-		new Util.Comparer() {
-			/**
-			 * @see Comparer#compare(Object, Object)
-			 */
-			public int compare(Object a, Object b) {
-				return - ((IJavaElement)a).getParent().getElementName().compareTo(((IJavaElement)b).getParent().getElementName());
-			}
+	HashSet existingOpenables = new HashSet(size);
+	Openable[] openables = new Openable[size];
+	int openableIndex = 0;
+	for (int i = 0; i < size; i++) {
+		IType type = (IType)allTypesInRegion.get(i);
+		Openable openable;
+		if (type.isBinary()) {
+			openable = (Openable)type.getClassFile();
+		} else {
+			openable = (Openable)type.getCompilationUnit();
 		}
-	);
-
-	// collect infos and compilation units
-	ArrayList infos = new ArrayList();
-	ArrayList units = new ArrayList();
-	types : for (int i = 0; i < size; i++) {
-		try {
-			IType type = types[i];
-			this.addInfoFromElement((Openable)type.getOpenable(), infos, units, type.getPath().toString());
-		} catch (JavaModelException npe) {
-			continue types;
+		if (existingOpenables.add(openable)) {
+			openables[openableIndex++] = openable;
 		}
 	}
-
-	// copy vectors into arrays
-	IGenericType[] genericTypes;
-	int infosSize = infos.size();
-	if (infosSize > 0) {
-		genericTypes = new IGenericType[infosSize];
-		infos.toArray(genericTypes);
-	} else {
-		genericTypes = new IGenericType[0];
-	}
-	org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] compilationUnits;
-	int unitsSize = units.size();
-	if (unitsSize > 0) {
-		compilationUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[unitsSize];
-		units.toArray(compilationUnits);
-	} else {
-		compilationUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[0];
+	if (openableIndex < size) {
+		System.arraycopy(openables, 0, openables = new Openable[openableIndex], 0, openableIndex);
 	}
 
 	try {
 		// resolve
-		if (monitor != null) monitor.beginTask("", (infosSize+unitsSize) * 2/* 1 for build binding, 1 for connect hierarchy*/); //$NON-NLS-1$
-		if (infosSize > 0 || unitsSize > 0) {
+		if (monitor != null) monitor.beginTask("", openableIndex * 2/* 1 for build binding, 1 for connect hierarchy*/); //$NON-NLS-1$
+		if (openableIndex > 0) {
 			IType focusType = this.getType();
 			CompilationUnit unitToLookInside = null;
 			if (focusType != null) {
 				unitToLookInside = (CompilationUnit)focusType.getCompilationUnit();
 			}
 			if (this.nameLookup != null && unitToLookInside != null) {
-				synchronized(this.nameLookup) { // prevent 2 concurrent accesses to name lookup while the working copies are set
-					try {
-						nameLookup.setUnitsToLookInside(new IWorkingCopy[] {unitToLookInside});
-						this.hierarchyResolver.resolve(genericTypes, compilationUnits, monitor);
-					} finally {
-						nameLookup.setUnitsToLookInside(null);
-					}
+				try {
+					nameLookup.setUnitsToLookInside(new ICompilationUnit[] {unitToLookInside}); // NB: this uses a PerThreadObject, so it is thread safe
+					this.hierarchyResolver.resolve(openables, null, monitor);
+				} finally {
+					nameLookup.setUnitsToLookInside(null);
 				}
 			} else {
-				this.hierarchyResolver.resolve(genericTypes, compilationUnits, monitor);
+				this.hierarchyResolver.resolve(openables, null, monitor);
 			}
 		}
 	} finally {
@@ -162,7 +126,7 @@
 		try {
 			ArrayList types = new ArrayList();
 			IJavaElement[] roots =
-				((RegionBasedTypeHierarchy) this.hierarchy).fRegion.getElements();
+				((RegionBasedTypeHierarchy) this.hierarchy).region.getElements();
 			int length = roots.length;
 			if (monitor != null) monitor.beginTask("", length); //$NON-NLS-1$
 			for (int i = 0; i <length; i++) {
@@ -222,6 +186,7 @@
 				injectAllTypesForPackageFragmentRoot(root, types);
 			}
 		} catch (JavaModelException e) {
+			// ignore
 		}
 	}
 	
@@ -247,6 +212,7 @@
 				}
 			}
 		} catch (JavaModelException e) {
+			// ignore
 		}
 	}
 	
@@ -281,6 +247,7 @@
 				types.add(cf.getType());
 			}
 		} catch (JavaModelException e) {
+			// ignore
 		}
 	}
 	
@@ -300,6 +267,7 @@
 				}
 			}
 		} catch (JavaModelException e) {
+			// ignore
 		}
 	}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
index f7d9b83..42039c9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/RegionBasedTypeHierarchy.java
@@ -10,7 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.hierarchy;
 
+import java.util.ArrayList;
+
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaElementDelta;
 import org.eclipse.jdt.core.IJavaProject;
@@ -22,45 +25,40 @@
 import org.eclipse.jdt.internal.core.CompilationUnit;
 import org.eclipse.jdt.internal.core.JavaElement;
 import org.eclipse.jdt.internal.core.Openable;
-import org.eclipse.jdt.internal.core.Region;
 import org.eclipse.jdt.internal.core.TypeVector;
 
 public class RegionBasedTypeHierarchy extends TypeHierarchy {
 	/**
 	 * The region of types for which to build the hierarchy
 	 */
-	protected IRegion fRegion;
+	protected IRegion region;
 
-	/**
-	 * The Java Project in which the hierarchy is being built - this
-	 * provides the context for determining a classpath and namelookup rules/
-	 */
-	protected IJavaProject fProject;
 /**
  * Creates a TypeHierarchy on the types in the specified region,
+ * considering first the given working copies,
  * using the given project for a name lookup contenxt. If a specific
  * type is also specified, the type hierarchy is pruned to only
  * contain the branch including the specified type.
  */
-public RegionBasedTypeHierarchy(IRegion region, IJavaProject project, IType type, boolean computeSubtypes) throws JavaModelException {
-	super(type, (IJavaSearchScope)null, computeSubtypes);
-	fRegion = region;
-	fProject = project;
+public RegionBasedTypeHierarchy(IRegion region, IJavaProject project, ICompilationUnit[] workingCopies, IType type, boolean computeSubtypes) {
+	super(type, workingCopies, (IJavaSearchScope)null, computeSubtypes);
+	this.region = region;
+	this.project = project;
 }
-/**
- * Activates this hierarchy for change listeners
+/*
+ * @see TypeHierarchy#initializeRegions
  */
-protected void activate() {
-	super.activate();
-	IJavaElement[] roots = fRegion.getElements();
+protected void initializeRegions() {
+	super.initializeRegions();
+	IJavaElement[] roots = this.region.getElements();
 	for (int i = 0; i < roots.length; i++) {
 		IJavaElement root = roots[i];
 		if (root instanceof IOpenable) {
-			this.files.put(root, root);
+			this.files.put(root, new ArrayList());
 		} else {
 			Openable o = (Openable) ((JavaElement) root).getOpenableParent();
 			if (o != null) {
-				this.files.put(o, o);
+				this.files.put(o, new ArrayList());
 			}
 		}
 		checkCanceled();
@@ -73,19 +71,15 @@
 	HierarchyBuilder builder = new RegionBasedHierarchyBuilder(this);
 	builder.build(this.computeSubtypes);
 }
-protected void destroy() {
-	fRegion = new Region();
-	super.destroy();	
-}
 protected boolean isAffectedByOpenable(IJavaElementDelta delta, IJavaElement element) {
-	// ignore changes to working copies
+	// change to working copy
 	if (element instanceof CompilationUnit && ((CompilationUnit)element).isWorkingCopy()) {
-		return false;
+		return super.isAffectedByOpenable(delta, element);
 	}
 
 	// if no focus, hierarchy is affected if the element is part of the region
-	if (this.type == null) {
-		return fRegion.contains(element);
+	if (this.focusType == null) {
+		return this.region.contains(element);
 	} else {
 		return super.isAffectedByOpenable(delta, element);
 	}
@@ -94,7 +88,7 @@
  * Returns the java project this hierarchy was created in.
  */
 public IJavaProject javaProject() {
-	return fProject;
+	return this.project;
 }
 public void pruneDeadBranches() {
 	this.pruneDeadBranches(this.getRootClasses(), false);
@@ -102,7 +96,7 @@
 private void pruneDeadBranches(IType[] types, boolean superInRegion) {
 	for (int i = 0, length = types.length; i < length; i++) {
 		IType type = types[i];
-		if (fRegion.contains(type)) {
+		if (this.region.contains(type)) {
 			TypeVector subtypes = (TypeVector)this.typeToSubtypes.get(type);
 			if (subtypes != null) {
 				this.pruneDeadBranches(subtypes.copy().elements(), true);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
index eba759f..cefc9b9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/TypeHierarchy.java
@@ -23,6 +23,7 @@
 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.OperationCanceledException;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.jdt.core.*;
@@ -41,21 +42,21 @@
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
 import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.CompilationUnit;
-import org.eclipse.jdt.internal.core.ImportContainer;
 import org.eclipse.jdt.internal.core.JavaElement;
-import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.JavaModelStatus;
 import org.eclipse.jdt.internal.core.JavaProject;
 import org.eclipse.jdt.internal.core.Openable;
 import org.eclipse.jdt.internal.core.Region;
 import org.eclipse.jdt.internal.core.TypeVector;
-import org.eclipse.jdt.internal.core.Util;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * @see ITypeHierarchy
  */
 public class TypeHierarchy implements ITypeHierarchy, IElementChangedListener {
+
 	public static boolean DEBUG = false;
 	
 	static final byte VERSION = 0x0000;
@@ -87,7 +88,12 @@
 	 * The type the hierarchy was specifically computed for,
 	 * possibly null.
 	 */
-	protected IType type;
+	protected IType focusType;
+	
+	/*
+	 * The working copies that take precedence over original compilation units
+	 */
+	protected ICompilationUnit[] workingCopies;
 
 	protected Map classToSuperclass;
 	protected Map typeToSuperInterfaces;
@@ -109,12 +115,10 @@
 	 */
 	protected ArrayList changeListeners = null;
 
-	/**
-	 * A set of the compilation units and class
-	 * files that are considered in this hierarchy. Null if
-	 * not activated.
+	/*
+	 * A map from Openables to ArrayLists of ITypes
 	 */
-	protected Map files = null;
+	public Map files = null;
 
 	/**
 	 * A region describing the packages considered by this
@@ -123,29 +127,10 @@
 	protected Region packageRegion = null;
 
 	/**
-	 * A region describing the package fragment roots considered by this
-	 * hierarchy. Null if not activated.
-	 */
-	protected Region rootRegion = null;
-	
-	/**
 	 * A region describing the projects considered by this
 	 * hierarchy. Null if not activated.
 	 */
 	protected Region projectRegion = null;
-
-	/**
-	 * A boolean indicating if this hierarchy is actively tracking changes
-	 * in the Java Model.
-	 */
-	protected boolean isActivated = false;
-
-	/**
-	 * A boolean indicating if the hierarchy exists
-	 *
-	 * fix for 1FW67PA
-	 */
-	protected boolean exists = true;
 	
 	/**
 	 * Whether this hierarchy should contains subtypes.
@@ -156,55 +141,64 @@
 	 * The scope this hierarchy should restrain itsef in.
 	 */
 	IJavaSearchScope scope;
+	
+	/*
+	 * Whether this hierarchy needs refresh
+	 */
+	public boolean needsRefresh = true;
+	
+	/*
+	 * Collects changes to types
+	 */
+	protected ChangeCollector changeCollector;
 
 /**
  * Creates an empty TypeHierarchy
  */
-public TypeHierarchy() throws JavaModelException {
+public TypeHierarchy() {
+	// Creates an empty TypeHierarchy
 }
 /**
  * Creates a TypeHierarchy on the given type.
  */
-public TypeHierarchy(IType type, IJavaProject project, boolean computeSubtypes) throws JavaModelException {
-	this(type, SearchEngine.createJavaSearchScope(new IJavaElement[] {project}), computeSubtypes);
+public TypeHierarchy(IType type, ICompilationUnit[] workingCopies, IJavaProject project, boolean computeSubtypes) {
+	this(type, workingCopies, SearchEngine.createJavaSearchScope(new IJavaElement[] {project}), computeSubtypes);
 	this.project = project;
 }
 /**
  * Creates a TypeHierarchy on the given type.
  */
-public TypeHierarchy(IType type, IJavaSearchScope scope, boolean computeSubtypes) throws JavaModelException {
-	this.type = type;
+public TypeHierarchy(IType type, ICompilationUnit[] workingCopies, IJavaSearchScope scope, boolean computeSubtypes) {
+	this.focusType = type;
+	this.workingCopies = workingCopies;
 	this.computeSubtypes = computeSubtypes;
 	this.scope = scope;
 }
 /**
- * Activates this hierarchy for change listeners
+ * Initializes the file, package and project regions
  */
-protected void activate() {
+protected void initializeRegions() {
 
-	// determine my file, package, root, & project regions.
-	this.files = new HashMap(5);
-	this.projectRegion = new Region();
-	this.packageRegion = new Region();
-	this.rootRegion = new Region();
-	IType[] types = getAllTypes();
-	for (int i = 0; i < types.length; i++) {
-		IType type = types[i];
+	IType[] allTypes = getAllTypes();
+	for (int i = 0; i < allTypes.length; i++) {
+		IType type = allTypes[i];
 		Openable o = (Openable) ((JavaElement) type).getOpenableParent();
 		if (o != null) {
-			this.files.put(o, o);
+			ArrayList types = (ArrayList)this.files.get(o);
+			if (types == null) {
+				types = new ArrayList();
+				this.files.put(o, types);
+			}
+			types.add(type);
 		}
 		IPackageFragment pkg = type.getPackageFragment();
 		this.packageRegion.add(pkg);
-		this.rootRegion.add(pkg.getParent());
-		IJavaProject project = type.getJavaProject();
-		if (project != null) {
-			this.projectRegion.add(project);
+		IJavaProject declaringProject = type.getJavaProject();
+		if (declaringProject != null) {
+			this.projectRegion.add(declaringProject);
 		}
 		checkCanceled();
 	}
-	JavaCore.addElementChangedListener(this);
-	this.isActivated = true;
 }
 /**
  * Adds all of the elements in the collection to the list if the
@@ -248,17 +242,20 @@
 /**
  * @see ITypeHierarchy
  */
-public void addTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener) {
-	if (this.changeListeners == null) {
-		this.changeListeners = new ArrayList();
-		// fix for 1FW67PA
-		if (this.exists) {
-			activate();
-		}
+public synchronized void addTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener) {
+	ArrayList listeners = this.changeListeners;
+	if (listeners == null) {
+		this.changeListeners = listeners = new ArrayList();
 	}
+	
+	// register with JavaCore to get Java element delta on first listener added
+	if (listeners.size() == 0) {
+		JavaCore.addElementChangedListener(this);
+	}
+	
 	// add listener only if it is not already present
-	if (this.changeListeners.indexOf(listener) == -1) {
-		this.changeListeners.add(listener);
+	if (listeners.indexOf(listener) == -1) {
+		listeners.add(listener);
 	}
 }
 private static Integer bytesToFlags(byte[] bytes){
@@ -314,7 +311,7 @@
  * Compute this type hierarchy.
  */
 protected void compute() throws JavaModelException, CoreException {
-	if (this.type != null) {
+	if (this.focusType != null) {
 		HierarchyBuilder builder = 
 			new IndexBasedHierarchyBuilder(
 				this, 
@@ -340,98 +337,54 @@
 	return false;
 }
 /**
- * Deactivates this hierarchy for change listeners
- */
-protected void deactivate() {
-	JavaModelManager.getJavaModelManager().removeElementChangedListener(this);
-	this.files= null;
-	this.packageRegion= null;
-	this.rootRegion= null;
-	this.projectRegion= null;
-	this.changeListeners= null;
-	this.isActivated= false;
-}
-/**
- * Empties this hierarchy.
- *
- * fix for 1FW67PA
- */
-protected void destroy() {
-	this.exists = false;
-	this.classToSuperclass = new HashMap(1);
-	this.files = new HashMap(5);
-	this.interfaces = new ArrayList(0);
-	this.packageRegion = new Region();
-	this.projectRegion = new Region();
-	this.rootClasses = new TypeVector();
-	this.rootRegion = new Region();
-	this.typeToSubtypes = new HashMap(1);
-	this.typeFlags = new HashMap(1);
-	this.typeToSuperInterfaces = new HashMap(1);
-	this.missingTypes = new ArrayList(4);
-	JavaModelManager.getJavaModelManager().removeElementChangedListener(this);
-}
-/**
  * Determines if the change effects this hierarchy, and fires
  * change notification if required.
  */
 public void elementChanged(ElementChangedEvent event) {
-	// fix for 1FW67PA
-	if (this.exists && this.isActivated()) {
-		if (exists()) {
-			if (isAffected(event.getDelta())) {
-				fireChange();
-			}
-		} else {
-			destroy();
-			fireChange();
-		}
+	// type hierarchy change has already been fired
+	if (this.needsRefresh) return;
+	
+	if (isAffected(event.getDelta())) {
+		this.needsRefresh = true;
+		fireChange();
 	}
-
 }
 /**
  * @see ITypeHierarchy
- *
- * fix for 1FW67PA
  */
 public boolean exists() {
-	if (this.exists) {
-		this.exists = (this.type == null || (this.type != null && this.type.exists())) && this.javaProject().exists();
-		if (!this.exists) {
-			destroy();
-		}
-	}
-	return this.exists;
+	if (!this.needsRefresh) return true;
+	
+	return (this.focusType == null || this.focusType.exists()) && this.javaProject().exists();
 }
 /**
  * Notifies listeners that this hierarchy has changed and needs
  * refreshing. Note that listeners can be removed as we iterate
  * through the list.
  */
-protected void fireChange() {
-	if (this.changeListeners == null) {
+public void fireChange() {
+	ArrayList listeners = this.changeListeners;
+	if (listeners == null) {
 		return;
 	}
 	if (DEBUG) {
 		System.out.println("FIRING hierarchy change ["+Thread.currentThread()+"]"); //$NON-NLS-1$ //$NON-NLS-2$
-		if (this.type != null) {
-			System.out.println("    for hierarchy focused on " + ((JavaElement)this.type).toStringWithAncestors()); //$NON-NLS-1$
+		if (this.focusType != null) {
+			System.out.println("    for hierarchy focused on " + ((JavaElement)this.focusType).toStringWithAncestors()); //$NON-NLS-1$
 		}
 	}
-	ArrayList listeners= (ArrayList)this.changeListeners.clone();
+	// clone so that a listener cannot have a side-effect on this list when being notified
+	listeners = (ArrayList)listeners.clone();
 	for (int i= 0; i < listeners.size(); i++) {
 		final ITypeHierarchyChangedListener listener= (ITypeHierarchyChangedListener)listeners.get(i);
-		// ensure the listener is still a listener
-		if (this.changeListeners != null  && this.changeListeners.indexOf(listener) >= 0) {
-			Platform.run(new ISafeRunnable() {
-				public void handleException(Throwable exception) {
-					Util.log(exception, "Exception occurred in listener of Type hierarchy change notification"); //$NON-NLS-1$
-				}
-				public void run() throws Exception {
-					listener.typeHierarchyChanged(TypeHierarchy.this);
-				}
-			});
-		}
+		Platform.run(new ISafeRunnable() {
+			public void handleException(Throwable exception) {
+				Util.log(exception, "Exception occurred in listener of Type hierarchy change notification"); //$NON-NLS-1$
+			}
+			public void run() throws Exception {
+				listener.typeHierarchyChanged(TypeHierarchy.this);
+			}
+		});
 	}
 }
 private static byte[] flagsToBytes(Integer flags){
@@ -559,11 +512,11 @@
 public IType[] getAllTypes() {
 	IType[] classes = getAllClasses();
 	int classesLength = classes.length;
-	IType[] interfaces = getAllInterfaces();
-	int interfacesLength = interfaces.length;
+	IType[] allInterfaces = getAllInterfaces();
+	int interfacesLength = allInterfaces.length;
 	IType[] all = new IType[classesLength + interfacesLength];
 	System.arraycopy(classes, 0, all, 0, classesLength);
-	System.arraycopy(interfaces, 0, all, classesLength, interfacesLength);
+	System.arraycopy(allInterfaces, 0, all, classesLength, interfacesLength);
 	return all;
 }
 
@@ -582,54 +535,40 @@
  * @see ITypeHierarchy
  */
 public IType[] getExtendingInterfaces(IType type) {
-	try {
-		if (!this.isInterface(type)) {
-			return new IType[] {};
-		}
-	} catch (JavaModelException npe) {
-		return new IType[] {};
-	}
+	if (!this.isInterface(type)) return NO_TYPE;
 	return getExtendingInterfaces0(type);
 }
 /**
  * Assumes that the type is an interface
  * @see getExtendingInterfaces
  */
-private IType[] getExtendingInterfaces0(IType interfce) {
+private IType[] getExtendingInterfaces0(IType extendedInterface) {
 	Iterator iter = this.typeToSuperInterfaces.keySet().iterator();
-	ArrayList xers = new ArrayList();
+	ArrayList interfaceList = new ArrayList();
 	while (iter.hasNext()) {
 		IType type = (IType) iter.next();
-		try {
-			if (!this.isInterface(type)) {
-				continue;
-			}
-		} catch (JavaModelException npe) {
+		if (!this.isInterface(type)) {
 			continue;
 		}
-		IType[] interfaces = (IType[]) this.typeToSuperInterfaces.get(type);
-		if (interfaces != null) {
-			for (int i = 0; i < interfaces.length; i++) {
-				IType iFace = interfaces[i];
-				if (iFace.equals(interfce)) {
-					xers.add(type);
+		IType[] superInterfaces = (IType[]) this.typeToSuperInterfaces.get(type);
+		if (superInterfaces != null) {
+			for (int i = 0; i < superInterfaces.length; i++) {
+				IType superInterface = superInterfaces[i];
+				if (superInterface.equals(extendedInterface)) {
+					interfaceList.add(type);
 				}
 			}
 		}
 	}
-	IType[] extenders = new IType[xers.size()];
-	xers.toArray(extenders);
-	return extenders;
+	IType[] extendingInterfaces = new IType[interfaceList.size()];
+	interfaceList.toArray(extendingInterfaces);
+	return extendingInterfaces;
 }
 /**
  * @see ITypeHierarchy
  */
 public IType[] getImplementingClasses(IType type) {
-	try {
-		if (!this.isInterface(type)) {
-			return NO_TYPE;
-		}
-	} catch (JavaModelException npe) {
+	if (!this.isInterface(type)) {
 		return NO_TYPE;
 	}
 	return getImplementingClasses0(type);
@@ -644,16 +583,12 @@
 	ArrayList iMenters = new ArrayList();
 	while (iter.hasNext()) {
 		IType type = (IType) iter.next();
-		try {
-			if (this.isInterface(type)) {
-				continue;
-			}
-		} catch (JavaModelException npe) {
+		if (this.isInterface(type)) {
 			continue;
 		}
-		IType[] interfaces = (IType[]) this.typeToSuperInterfaces.get(type);
-		for (int i = 0; i < interfaces.length; i++) {
-			IType iFace = interfaces[i];
+		IType[] types = (IType[]) this.typeToSuperInterfaces.get(type);
+		for (int i = 0; i < types.length; i++) {
+			IType iFace = types[i];
 			if (iFace.equals(interfce)) {
 				iMenters.add(type);
 			}
@@ -692,12 +627,8 @@
  * @see ITypeHierarchy
  */
 public IType[] getSubclasses(IType type) {
-	try {
-		if (this.isInterface(type)) {
-			return NO_TYPE;
-		}
-	} catch (JavaModelException npe) {
-		return new IType[] {};
+	if (this.isInterface(type)) {
+		return NO_TYPE;
 	}
 	TypeVector vector = (TypeVector)this.typeToSubtypes.get(type);
 	if (vector == null)
@@ -725,25 +656,20 @@
  * @see ITypeHierarchy
  */
 public IType getSuperclass(IType type) {
-	try {
-		if (this.isInterface(type)) {
-			return null;
-		}
-		return (IType) this.classToSuperclass.get(type);
-
-	} catch (JavaModelException npe) {
+	if (this.isInterface(type)) {
 		return null;
 	}
+	return (IType) this.classToSuperclass.get(type);
 }
 /**
  * @see ITypeHierarchy
  */
 public IType[] getSuperInterfaces(IType type) {
-	IType[] interfaces = (IType[]) this.typeToSuperInterfaces.get(type);
-	if (interfaces == null) {
+	IType[] types = (IType[]) this.typeToSuperInterfaces.get(type);
+	if (types == null) {
 		return NO_TYPE;
 	}
-	return interfaces;
+	return types;
 }
 /**
  * @see ITypeHierarchy
@@ -762,7 +688,7 @@
  * @see ITypeHierarchy
  */
 public IType getType() {
-	return this.type;
+	return this.focusType;
 }
 /**
  * Adds the new elements to a new array that contains all of the elements of the old array.
@@ -792,15 +718,22 @@
 	array[old.length] = addition;
 	return array;
 }
+/*
+ * Whether fine-grained deltas where collected and affects this hierarchy.
+ */
+public boolean hasFineGrainChanges() {
+    ChangeCollector collector = this.changeCollector;
+	return collector != null && collector.needsRefresh();
+}
 /**
  * Returns whether one of the subtypes in this hierarchy has the given simple name
  * or this type has the given simple name.
  */
 private boolean hasSubtypeNamed(String simpleName) {
-	if (this.type.getElementName().equals(simpleName)) {
+	if (this.focusType != null && this.focusType.getElementName().equals(simpleName)) {
 		return true;
 	}
-	IType[] types = this.getAllSubtypes(this.type);
+	IType[] types = this.getAllSubtypes(this.focusType);
 	for (int i = 0, length = types.length; i < length; i++) {
 		if (types[i].getElementName().equals(simpleName)) {
 			return true;
@@ -826,7 +759,7 @@
  * Returns whether the simple name of the given type or one of its supertypes is 
  * the simple name of one of the types in this hierarchy.
  */
-private boolean includesTypeOrSupertype(IType type) {
+boolean includesTypeOrSupertype(IType type) {
 	try {
 		// check type
 		if (hasTypeNamed(type.getElementName())) return true;
@@ -850,6 +783,7 @@
 			}
 		}
 	} catch (JavaModelException e) {
+		// ignore
 	}
 	return false;
 }
@@ -868,18 +802,15 @@
 	this.typeToSubtypes = new HashMap(smallSize);
 	this.typeToSuperInterfaces = new HashMap(smallSize);
 	this.typeFlags = new HashMap(smallSize);
-}
-/**
- * Returns true if this hierarchy is actively tracking changes
- * in the Java Model.
- */
-protected boolean isActivated() {
-	return this.isActivated;
+	
+	this.projectRegion = new Region();
+	this.packageRegion = new Region();
+	this.files = new HashMap(5);
 }
 /**
  * Returns true if the given delta could change this type hierarchy
  */
-public boolean isAffected(IJavaElementDelta delta) {
+public synchronized boolean isAffected(IJavaElementDelta delta) {
 	IJavaElement element= delta.getElement();
 	switch (element.getElementType()) {
 		case IJavaElement.JAVA_MODEL:
@@ -949,8 +880,8 @@
 			// then the type hierarchy has changed
 			IJavaElement[] pkgs = this.packageRegion.getElements();
 			for (int i = 0; i < pkgs.length; i++) {
-				IJavaProject project = pkgs[i].getJavaProject();
-				if (project != null && project.equals(element)) {
+				IJavaProject javaProject = pkgs[i].getJavaProject();
+				if (javaProject != null && javaProject.equals(element)) {
 					return true;
 				}
 			}
@@ -995,9 +926,9 @@
 					IPath rootPath = root.getPath();
 					IJavaElement[] elements = this.projectRegion.getElements();
 					for (int i = 0; i < elements.length; i++) {
-						IJavaProject project = (IJavaProject)elements[i];
+						IJavaProject javaProject = (IJavaProject)elements[i];
 						try {
-							IClasspathEntry[] classpath = project.getResolvedClasspath(true);
+							IClasspathEntry[] classpath = javaProject.getResolvedClasspath(true);
 							for (int j = 0; j < classpath.length; j++) {
 								IClasspathEntry entry = classpath[j];
 								if (entry.getPath().equals(rootPath)) {
@@ -1031,129 +962,66 @@
  * could affect this type hierarchy.
  */
 protected boolean isAffectedByOpenable(IJavaElementDelta delta, IJavaElement element) {
-	// ignore changes to working copies
-	if (element instanceof CompilationUnit && ((CompilationUnit)element).isWorkingCopy()) {
-		return false;
-	}
-		
-	int kind = delta.getKind();
-	switch (kind) {
-		case IJavaElementDelta.REMOVED:
-			return this.files.get(element) != null;
-		case IJavaElementDelta.ADDED:
-			IType[] types = null;
-			try {
-				types = (element instanceof CompilationUnit) ?
-					((CompilationUnit)element).getAllTypes() :
-					new IType[] {((org.eclipse.jdt.internal.core.ClassFile)element).getType()};
-			} catch (JavaModelException e) {
-				e.printStackTrace();
-				return false;
-			}
-			for (int i = 0, length = types.length; i < length; i++) {
-				IType type = types[i];
-				if (typeHasSupertype(type) 
+	if (element instanceof CompilationUnit) {
+		CompilationUnit cu = (CompilationUnit)element;
+		ChangeCollector collector = this.changeCollector;
+		if (collector == null) {
+		    collector = new ChangeCollector(this);
+		}
+		try {
+			collector.addChange(cu, delta);
+		} catch (JavaModelException e) {
+			e.printStackTrace();
+		}
+		if (cu.isWorkingCopy()) {
+			// changes to working copies are batched
+			this.changeCollector = collector;
+			return false;
+		} else {
+			return collector.needsRefresh();
+		}
+	} else if (element instanceof ClassFile) {
+		switch (delta.getKind()) {
+			case IJavaElementDelta.REMOVED:
+				return this.files.get(element) != null;
+			case IJavaElementDelta.ADDED:
+				IType type = ((ClassFile)element).getType();
+				String typeName = type.getElementName();
+				if (hasSupertype(typeName) 
 					|| subtypesIncludeSupertypeOf(type)
-					|| this.missingTypes.contains(type.getElementName())) {
+					|| this.missingTypes.contains(typeName)) {
 						
 					return true;
 				}
-			}
-			break;
-		case IJavaElementDelta.CHANGED:
-			boolean hasImportChange = false;
-			IJavaElementDelta[] children = delta.getAffectedChildren();
-			for (int i = 0, length = children.length; i < length; i++) {
-				IJavaElementDelta child = children[i];
-				IJavaElement childElement = child.getElement();
-				if (childElement instanceof IType) {
-					// NB: rely on the fact that import statements are before type declarations
-					if (this.isAffectedByType(child, (IType)childElement, hasImportChange)) {
-						return true;
-					}
-				} else if (childElement instanceof ImportContainer) {
-					if (!hasImportChange) {
-						hasImportChange = true;
-						types = null;
-						try {
-							types = (element instanceof CompilationUnit) ?
-								((CompilationUnit)element).getAllTypes() :
-								new IType[] {((org.eclipse.jdt.internal.core.ClassFile)element).getType()};
-						} catch (JavaModelException e) {
-							e.printStackTrace();
-							return false;
-						}
-						for (int j = 0, typesLength = types.length; j < typesLength; j++) {
-							if (includesTypeOrSupertype(types[j])) {
-								return true;
-							}
+				break;
+			case IJavaElementDelta.CHANGED:
+				IJavaElementDelta[] children = delta.getAffectedChildren();
+				for (int i = 0, length = children.length; i < length; i++) {
+					IJavaElementDelta child = children[i];
+					IJavaElement childElement = child.getElement();
+					if (childElement instanceof IType) {
+						type = (IType)childElement;
+						boolean hasVisibilityChange = (delta.getFlags() & IJavaElementDelta.F_MODIFIERS) > 0;
+						boolean hasSupertypeChange = (delta.getFlags() & IJavaElementDelta.F_SUPER_TYPES) > 0;
+						if ((hasVisibilityChange && hasSupertype(type.getElementName()))
+								|| (hasSupertypeChange && includesTypeOrSupertype(type))) {
+							return true;
 						}
 					}
 				}
-			}
-			break;
-		
-	}
-	return false;
-}
-/*
- * The rules are:
- * - if the delta is an added type X, then the hierarchy is changed 
- *   . if one of the types in this hierarchy has a supertype whose simple name is the
- *     simple name of X
- *   . if the simple name of a supertype of X is the simple name of one of
- *     the subtypes in this hierarchy (X will be added as one of the subtypes)
- * - if the delta is a changed type X, then the hierarchy is changed
- *   . if the visibility of X has changed and if one of the types in this hierarchy has a 
- *	   supertype whose simple name is the simple name of X
- *   . if one of the supertypes of X has changed or one of the imports has changed,
- *     and if the simple name of a supertype of X is the simple name of one of 
- *     the types in this hierarchy
- * - if the delta is a removed type X, then the hierarchy is changed
- *   . if the given element is part of this hierarchy (note we cannot acces the types 
- *     because the element has been removed)
- */
-protected boolean isAffectedByType(IJavaElementDelta delta, IType type, boolean hasImportChange) {
-	switch (delta.getKind()) {
-		case IJavaElementDelta.ADDED:
-			if (typeHasSupertype(type) 
-				|| subtypesIncludeSupertypeOf(type) 
-				|| this.missingTypes.contains(type.getElementName())) {
-				
-				return true;
-			}
-			break;
-		case IJavaElementDelta.CHANGED:
-			boolean hasVisibilityChange = (delta.getFlags() & IJavaElementDelta.F_MODIFIERS) > 0;
-			boolean hasSupertypeChange = (delta.getFlags() & IJavaElementDelta.F_SUPER_TYPES) > 0;
-			if ((hasVisibilityChange && typeHasSupertype(type))
-					|| ((hasImportChange || hasSupertypeChange) 
-						&& includesTypeOrSupertype(type))) {
-				return true;
-			}
-			break;
-		case IJavaElementDelta.REMOVED:
-			if (this.contains(type)) {
-				return true;
-			}
-			break;
-	}
-	IJavaElementDelta[] children = delta.getAffectedChildren();
-	for (int i = 0, length = children.length; i < length; i++) {
-		IJavaElementDelta child = children[i];
-		IJavaElement childElement = child.getElement();
-		if (childElement instanceof IType) {
-			if (this.isAffectedByType(child, (IType)childElement, hasImportChange)) {
-				return true;
-			}
+				break;
 		}
 	}
 	return false;
-} 
-private boolean isInterface(IType type) throws JavaModelException {
+}
+private boolean isInterface(IType type) {
 	int flags = this.getCachedFlags(type);
 	if (flags == -1) {
-		return type.isInterface();
+		try {
+			return type.isInterface();
+		} catch (JavaModelException e) {
+			return false;
+		}
 	} else {
 		return Flags.isInterface(flags);
 	}
@@ -1162,7 +1030,7 @@
  * Returns the java project this hierarchy was created in.
  */
 public IJavaProject javaProject() {
-	return this.type.getJavaProject();
+	return this.focusType.getJavaProject();
 }
 protected static byte[] readUntil(InputStream input, byte separator) throws JavaModelException, IOException{
 	return readUntil(input, separator, 0);
@@ -1173,17 +1041,17 @@
 	byte b;
 	while((b = (byte)input.read()) != separator && b != -1) {
 		if(bytes.length == length) {
-			System.arraycopy(bytes, 0, bytes = new byte[length*2], 0, length);;
+			System.arraycopy(bytes, 0, bytes = new byte[length*2], 0, length);
 		}
-		bytes[length++]=(byte)b;
+		bytes[length++] = b;
 	}
 	if(b == -1) {
-		throw new JavaModelException(new JavaModelStatus(IJavaModelStatus.ERROR));
+		throw new JavaModelException(new JavaModelStatus(IStatus.ERROR));
 	}
 	System.arraycopy(bytes, 0, bytes = new byte[length + offset], offset, length);
 	return bytes;
 }
-public static ITypeHierarchy load(IType type, InputStream input) throws JavaModelException {
+public static ITypeHierarchy load(IType type, InputStream input, WorkingCopyOwner owner) throws JavaModelException {
 	try {
 		TypeHierarchy typeHierarchy = new TypeHierarchy();
 		typeHierarchy.initialize(1);
@@ -1194,7 +1062,7 @@
 		byte version = (byte)input.read();
 	
 		if(version != VERSION) {
-			throw new JavaModelException(new JavaModelStatus(IJavaModelStatus.ERROR));
+			throw new JavaModelException(new JavaModelStatus(IStatus.ERROR));
 		}
 		byte generalInfo = (byte)input.read();
 		if((generalInfo & COMPUTE_SUBTYPES) != 0) {
@@ -1237,7 +1105,7 @@
 		while((b = (byte)input.read()) != SEPARATOR1 && b != -1) {
 			bytes = readUntil(input, SEPARATOR4, 1);
 			bytes[0] = b;
-			IType element = (IType)JavaCore.create(new String(bytes));
+			IType element = (IType)JavaCore.create(new String(bytes), owner);
 			
 			if(types.length == typeCount) {
 				System.arraycopy(types, 0, types = new IType[typeCount * 2], 0, typeCount);
@@ -1259,9 +1127,9 @@
 			}
 			if((info & COMPUTED_FOR) != 0) {
 				if(!element.equals(type)) {
-					throw new JavaModelException(new JavaModelStatus(IJavaModelStatus.ERROR)); 
+					throw new JavaModelException(new JavaModelStatus(IStatus.ERROR)); 
 				}
-				typeHierarchy.type = element;
+				typeHierarchy.focusType = element;
 			}
 			if((info & ROOT) != 0) {
 				typeHierarchy.addRootClass(element);
@@ -1314,7 +1182,7 @@
 				superInterfaces);
 		}
 		if(b == -1) {
-			throw new JavaModelException(new JavaModelStatus(IJavaModelStatus.ERROR));
+			throw new JavaModelException(new JavaModelStatus(IStatus.ERROR));
 		}
 		return typeHierarchy;
 	} catch(IOException e){
@@ -1337,18 +1205,15 @@
 
 /**
  * @see ITypeHierarchy
+ * TODO (jerome) should use a PerThreadObject to build the hierarchy instead of synchronizing
+ * (see also isAffected(IJavaElementDelta))
  */
-public void refresh(IProgressMonitor monitor) throws JavaModelException {
+public synchronized void refresh(IProgressMonitor monitor) throws JavaModelException {
 	try {
-		boolean reactivate = isActivated();
-		ArrayList listeners = this.changeListeners;
-		if (reactivate) {
-			deactivate();
-		}
 		this.progressMonitor = monitor;
 		if (monitor != null) {
-			if (this.type != null) {
-				monitor.beginTask(Util.bind("hierarchy.creatingOnType", type.getFullyQualifiedName()), 100); //$NON-NLS-1$
+			if (this.focusType != null) {
+				monitor.beginTask(Util.bind("hierarchy.creatingOnType", focusType.getFullyQualifiedName()), 100); //$NON-NLS-1$
 			} else {
 				monitor.beginTask(Util.bind("hierarchy.creating"), 100); //$NON-NLS-1$
 			}
@@ -1361,15 +1226,16 @@
 			} else {
 				System.out.println("CREATING SUPER TYPE HIERARCHY [" + Thread.currentThread() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
 			}
-			if (this.type != null) {
-				System.out.println("  on type " + ((JavaElement)this.type).toStringWithAncestors()); //$NON-NLS-1$
+			if (this.focusType != null) {
+				System.out.println("  on type " + ((JavaElement)this.focusType).toStringWithAncestors()); //$NON-NLS-1$
 			}
 		}
+
 		compute();
-		if (reactivate) {
-			activate();
-			this.changeListeners = listeners;
-		}
+		initializeRegions();
+		this.needsRefresh = false;
+		this.changeCollector = null;
+
 		if (DEBUG) {
 			if (this.computeSubtypes) {
 				System.out.println("CREATED TYPE HIERARCHY in " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
@@ -1379,13 +1245,9 @@
 			System.out.println(this.toString());
 		}
 	} catch (JavaModelException e) {
-		this.progressMonitor = null;
 		throw e;
 	} catch (CoreException e) {
-		this.progressMonitor = null;
 		throw new JavaModelException(e);
-	} catch (OperationCanceledException oce) {
-		refreshCancelled(oce);
 	} finally {
 		if (monitor != null) {
 			monitor.done();
@@ -1393,26 +1255,20 @@
 		this.progressMonitor = null;
 	}
 }
-/**
- * The refresh of this type hierarchy has been cancelled.
- * Cleanup the state of this now invalid type hierarchy.
- */
-protected void refreshCancelled(OperationCanceledException oce) throws JavaModelException {
-	destroy();
-	this.progressMonitor = null;
-	throw oce;
-}
 
 /**
  * @see ITypeHierarchy
  */
-public void removeTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener) {
-	if (this.changeListeners == null) {
+public synchronized void removeTypeHierarchyChangedListener(ITypeHierarchyChangedListener listener) {
+	ArrayList listeners = this.changeListeners;
+	if (listeners == null) {
 		return;
 	}
-	this.changeListeners.remove(listener);
-	if (this.changeListeners.isEmpty()) {
-		deactivate();
+	listeners.remove(listener);
+
+	// deregister from JavaCore on last listener removed
+	if (listeners.isEmpty()) {
+		JavaCore.removeElementChangedListener(this);
 	}
 }
 /**
@@ -1425,10 +1281,10 @@
 		Hashtable hashtable2 = new Hashtable();
 		int count = 0;
 		
-		if(type != null) {
+		if(focusType != null) {
 			Integer index = new Integer(count++);
-			hashtable.put(type, index);
-			hashtable2.put(index, type);
+			hashtable.put(focusType, index);
+			hashtable2.put(index, focusType);
 		}
 		Object[] types = classToSuperclass.keySet().toArray();
 		for (int i = 0; i < types.length; i++) {
@@ -1501,7 +1357,7 @@
 			output.write(flagsToBytes((Integer)typeFlags.get(t)));
 			output.write(SEPARATOR4);
 			byte info = CLASS;
-			if(type != null && type.equals(t)) {
+			if(focusType != null && focusType.equals(t)) {
 				info |= COMPUTED_FOR;
 			}
 			if(interfaces.contains(t)) {
@@ -1554,13 +1410,15 @@
  * the simple name of one of the subtypes in this hierarchy or the
  * simple name of this type.
  */
-private boolean subtypesIncludeSupertypeOf(IType type) {
+boolean subtypesIncludeSupertypeOf(IType type) {
 	// look for superclass
 	String superclassName = null;
 	try {
 		superclassName = type.getSuperclassName();
 	} catch (JavaModelException e) {
-		e.printStackTrace();
+		if (DEBUG) {
+			e.printStackTrace();
+		}
 		return false;
 	}
 	if (superclassName == null) {
@@ -1601,14 +1459,14 @@
 public String toString() {
 	StringBuffer buffer = new StringBuffer();
 	buffer.append("Focus: "); //$NON-NLS-1$
-	buffer.append(this.type == null ? "<NONE>" : this.type.getFullyQualifiedName()); //$NON-NLS-1$
+	buffer.append(this.focusType == null ? "<NONE>" : ((JavaElement)this.focusType).toStringWithAncestors()); //$NON-NLS-1$
 	buffer.append("\n"); //$NON-NLS-1$
 	if (exists()) {
-		if (this.type != null) {
+		if (this.focusType != null) {
 			buffer.append("Super types:\n"); //$NON-NLS-1$
-			toString(buffer, this.type, 1, true);
+			toString(buffer, this.focusType, 1, true);
 			buffer.append("Sub types:\n"); //$NON-NLS-1$
-			toString(buffer, this.type, 1, false);
+			toString(buffer, this.focusType, 1, false);
 		} else {
 			buffer.append("Sub types of root classes:\n"); //$NON-NLS-1$
 			IType[] roots= getRootClasses();
@@ -1638,25 +1496,22 @@
  * If ascendant, shows the super types, otherwise show the sub types.
  */
 private void toString(StringBuffer buffer, IType type, int indent, boolean ascendant) {
-	for (int i= 0; i < indent; i++) {
-		buffer.append("  "); //$NON-NLS-1$
-	}
-	JavaElement element = (JavaElement)type;
-	buffer.append(element.toStringWithAncestors());
-	buffer.append('\n');
-
 	IType[] types= ascendant ? getSupertypes(type) : getSubtypes(type);
 	for (int i= 0; i < types.length; i++) {
+		for (int j= 0; j < indent; j++) {
+			buffer.append("  "); //$NON-NLS-1$
+		}
+		JavaElement element = (JavaElement)types[i];
+		buffer.append(element.toStringWithAncestors());
+		buffer.append('\n');
 		toString(buffer, types[i], indent + 1, ascendant);
 	}
-
 }
 /**
  * Returns whether one of the types in this hierarchy has a supertype whose simple 
- * name is the simple name of the given type.
+ * name is the given simple name.
  */
-private boolean typeHasSupertype(IType type) {
-	String simpleName = type.getElementName();
+boolean hasSupertype(String simpleName) {
 	for(Iterator iter = this.classToSuperclass.values().iterator(); iter.hasNext();){
 		IType superType = (IType)iter.next();
 		if (superType.getElementName().equals(simpleName)) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/AbstractDOMBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/AbstractDOMBuilder.java
index b3fbba5..99d2ed0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/AbstractDOMBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/AbstractDOMBuilder.java
@@ -12,7 +12,6 @@
 
 import java.util.Stack;
 
-import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.jdom.IDOMCompilationUnit;
 import org.eclipse.jdt.core.jdom.IDOMNode;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
@@ -114,10 +113,6 @@
 	}
 }
 /**
- * Does nothing.
- */
-public void acceptProblem(IProblem problem) {} //TODO: (olivier) unused?
-/**
  * Adds the given node to the current enclosing scope, building the JDOM
  * tree. Nodes are only added to an enclosing scope when a compilation unit or type
  * is being built (since those are the only nodes that have children).
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java
index 53ce617..319fe36 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMBuilder.java
@@ -14,6 +14,7 @@
 import java.util.Map;
 
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.jdom.*;
 import org.eclipse.jdt.internal.compiler.DocumentElementParser;
@@ -21,8 +22,6 @@
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
-import org.eclipse.jdt.internal.core.util.CharArrayOps;
-
 /**
  * The DOMBuilder constructs each type of JDOM document fragment,
  * for the DOMFactory. The DOMBuilder has been separated from the
@@ -55,7 +54,9 @@
 /**
  * Creates a new DOMBuilder
  */
-public DOMBuilder() {}
+public DOMBuilder() {
+	// Creates a new DOMBuilder
+}
 /**
  * @see IDocumentElementRequestor#acceptImport(int declarationStart, int declarationEnd, int[] javaDocPositions, char[] name, int nameStartPosition, boolean onDemand)
  */
@@ -65,7 +66,7 @@
 	int[] nameRange = {nameStart, declarationEnd - 1};
 	
 	/* See 1FVII1P */
-	String importName = CharArrayOps.substring(fDocument, nameRange[0], nameRange[1] + 1 - nameRange[0]);
+	String importName = new String(CharOperation.subarray(fDocument, nameRange[0], nameRange[1] + 1));
 
 	fNode= new DOMImport(fDocument, sourceRange, importName, nameRange, onDemand);
 	addChild(fNode);
@@ -87,7 +88,7 @@
 	}
 
 	int[] modifiersRange = {-1, -1};
-	if (modifiersStart > declarationStart) {
+	if (modifiersStart >= declarationStart) {
 		modifiersRange[0] = modifiersStart;
 		modifiersRange[1] = bodyStart - 1;
 	}
@@ -105,7 +106,7 @@
 	int nameStartPosition) {
 	int[] sourceRange = {declarationStart, declarationEnd};
 	int[] nameRange = {nameStartPosition, declarationEnd - 1};
-	fNode= new DOMPackage(fDocument, sourceRange, CharArrayOps.charToString(name), nameRange);
+	fNode= new DOMPackage(fDocument, sourceRange, CharOperation.charToString(name), nameRange);
 	addChild(fNode);
 	if (fBuildingSingleMember) {
 		fFinishedSingleMember= true;
@@ -349,11 +350,11 @@
 	} else {
 		bodyRange = new int[] {parametersEnd + 1, -1};
 	}
-	fNode = new DOMMethod(fDocument, sourceRange, CharArrayOps.charToString(name), nameRange, commentRange, modifiers, 
-		modifiersRange, isConstructor, CharArrayOps.charToString(returnType), returnTypeRange,
-		CharArrayOps.charcharToString(parameterTypes),
-		CharArrayOps.charcharToString(parameterNames), 
-		parameterRange, CharArrayOps.charcharToString(exceptionTypes), exceptionRange, bodyRange);
+	fNode = new DOMMethod(fDocument, sourceRange, CharOperation.charToString(name), nameRange, commentRange, modifiers, 
+		modifiersRange, isConstructor, CharOperation.charToString(returnType), returnTypeRange,
+		CharOperation.charArrayToStringArray(parameterTypes),
+		CharOperation.charArrayToStringArray(parameterNames), 
+		parameterRange, CharOperation.charArrayToStringArray(exceptionTypes), exceptionRange, bodyRange);
 	addChild(fNode);
 	fStack.push(fNode);
 }
@@ -470,8 +471,8 @@
 		if (field.fTypeRange[0] == typeStart)
 			isVariableDeclarator = true;
 	}	
-	fNode = new DOMField(fDocument, sourceRange, CharArrayOps.charToString(name), nameRange, commentRange, 
-		modifiers, modifiersRange, typeRange, CharArrayOps.charToString(type), hasInitializer, 
+	fNode = new DOMField(fDocument, sourceRange, CharOperation.charToString(name), nameRange, commentRange, 
+		modifiers, modifiersRange, typeRange, CharOperation.charToString(type), hasInitializer, 
 		initializerRange, isVariableDeclarator);
 	addChild(fNode);
 	fStack.push(fNode);
@@ -571,7 +572,7 @@
 				extendsKeywordRange[0] = nameEnd + 1;
 				extendsKeywordRange[1] = superclassStart - 1;
 				superclassRange[0] = superclassStart;
-				superclassRange[1] = bodyStart - 1;
+				superclassRange[1] = superclassEnd;
 			}
 			if (superinterfaces != null && superinterfaces.length > 0) {
 				superclassRange[1] = superclassEnd;
@@ -596,7 +597,7 @@
 		int[] closeBodyRange = {-1, -1}; // will be fixed in exit		
 		fNode = new DOMType(fDocument, sourceRange, new String(name), nameRange, commentRange, 
 			modifiers, modifiersRange, typeKeywordRange, superclassRange, extendsKeywordRange, 
-			CharArrayOps.charcharToString(superinterfaces), interfacesRange,
+			CharOperation.charArrayToStringArray(superinterfaces), interfacesRange,
 			implementsKeywordRange, openBodyRange, 
 			closeBodyRange, isClass);
 		addChild(fNode);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java
index 45653cd..f5c2316 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMCompilationUnit.java
@@ -13,20 +13,20 @@
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.jdom.IDOMCompilationUnit;
 import org.eclipse.jdt.core.jdom.IDOMNode;
 import org.eclipse.jdt.core.jdom.IDOMType;
-import org.eclipse.jdt.internal.core.Util;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.util.CharArrayBuffer;
-import org.eclipse.jdt.internal.core.util.CharArrayOps;
-
+import org.eclipse.jdt.internal.core.util.Util;
 /**
  * DOMCompilation unit provides an implementation of IDOMCompilationUnit.
  *
  * @see IDOMCompilationUnit
  * @see DOMNode
  */
-class DOMCompilationUnit extends DOMNode implements IDOMCompilationUnit {
+class DOMCompilationUnit extends DOMNode implements IDOMCompilationUnit, SuffixConstants {
 
 	/**
 	 * The comment and/or whitespace preceding the
@@ -107,7 +107,7 @@
 		topLevelType= firstType;
 	}
 	if (topLevelType != null) {
-		return topLevelType.getName() + ".java";  //$NON-NLS-1$
+		return topLevelType.getName() + SUFFIX_STRING_java;
 	} else {
 		return null;
 	}
@@ -126,7 +126,7 @@
 	if (child != null) {
 		int childStart = child.getStartPosition();
 		if (childStart > 1) {
-			setHeader(CharArrayOps.substring(fDocument, 0, childStart));
+			setHeader(new String(CharOperation.subarray(fDocument, 0, childStart)));
 		}
 	}
 }
@@ -167,7 +167,9 @@
 /**
  * @see IDOMCompilationUnit#setName(String)
  */
-public void setName(String name) {}
+public void setName(String name) {
+	// nothing to do
+}
 /**
  * @see DOMNode#shareContents(DOMNode)
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java
index a0641a7..b77e7a7 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMField.java
@@ -14,13 +14,12 @@
 
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.jdom.DOMException;
 import org.eclipse.jdt.core.jdom.IDOMField;
 import org.eclipse.jdt.core.jdom.IDOMNode;
 import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.util.CharArrayBuffer;
-import org.eclipse.jdt.internal.core.util.CharArrayOps;
-
 /**
  * DOMField provides an implementation of IDOMField.
  *
@@ -60,6 +59,7 @@
  * Constructs an empty field node.
  */
 DOMField() {
+	// Constructs an empty field node
 }
 /**
  * Creates a new detailed FIELD document fragment on the given range of the document.
@@ -150,7 +150,9 @@
  *
  * @see DOMMember#appendMemberBodyContents(CharArrayBuffer)
  */
-protected void appendMemberBodyContents(CharArrayBuffer buffer) {}
+protected void appendMemberBodyContents(CharArrayBuffer buffer) {
+	// nothing to do
+}
 /**
  * @see DOMMember#appendMemberDeclarationContents(CharArrayBuffer)
  */
@@ -308,7 +310,7 @@
 		if (fInitializer != null) {
 			return fInitializer;
 		} else {
-			return CharArrayOps.substring(fDocument, fInitializerRange[0], fInitializerRange[1] + 1 - fInitializerRange[0]);
+			return new String(CharOperation.subarray(fDocument, fInitializerRange[0], fInitializerRange[1] + 1));
 		}
 	} else {
 		return null;
@@ -405,7 +407,7 @@
 	if (isTypeAltered()) {
 		return fType.toCharArray();
 	} else {
-		return CharArrayOps.subarray(fDocument, fTypeRange[0], fTypeRange[1] + 1 - fTypeRange[0]); 
+		return CharOperation.subarray(fDocument, fTypeRange[0], fTypeRange[1] + 1);
 	}
 }
 /**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMInitializer.java
index 76d1a0d..6f79e53 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMInitializer.java
@@ -12,12 +12,11 @@
 
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.jdom.IDOMInitializer;
 import org.eclipse.jdt.core.jdom.IDOMNode;
 import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.util.CharArrayBuffer;
-import org.eclipse.jdt.internal.core.util.CharArrayOps;
-
 /**
  * DOMInitializer provides an implementation of IDOMInitializer.
  *
@@ -43,7 +42,7 @@
  * Constructs an empty initializer node.
  */
 DOMInitializer() {
-
+	// Constructs an empty initializer node
 }
 /**
  * Creates a new detailed INITIALIZER document fragment on the given range of the document.
@@ -113,7 +112,9 @@
 /**
  * @see DOMMember#appendMemberDeclarationContents(CharArrayBuffer)
  */
-protected void appendMemberDeclarationContents(CharArrayBuffer buffer) {}
+protected void appendMemberDeclarationContents(CharArrayBuffer buffer) {
+	// nothing to do
+}
 /**
  * @see DOMNode#appendSimpleContents(CharArrayBuffer)
  */
@@ -134,7 +135,7 @@
 		if (fBody != null) {
 			return fBody;
 		} else {
-			return CharArrayOps.substring(fDocument, fBodyRange[0], fBodyRange[1] + 1 - fBodyRange[0]);
+			return new String(CharOperation.subarray(fDocument, fBodyRange[0], fBodyRange[1] + 1));
 		}
 	} else {
 		return null;
@@ -210,7 +211,9 @@
 /**
  * @see IDOMInitializer#setName(String)
  */
-public void setName(String name) {}
+public void setName(String name) {
+	// initializers have no name
+}
 /**
  * @see DOMNode#shareContents(DOMNode)
  */
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMember.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMember.java
index 2d05295..9a1611f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMember.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMember.java
@@ -11,11 +11,10 @@
 package org.eclipse.jdt.internal.core.jdom;
 
 import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.jdom.IDOMMember;
 import org.eclipse.jdt.internal.compiler.env.IConstants;
 import org.eclipse.jdt.internal.core.util.CharArrayBuffer;
-import org.eclipse.jdt.internal.core.util.CharArrayOps;
-
 /**
  * DOMMember provides an implementation of IDOMMember.
  *
@@ -65,7 +64,7 @@
  * Constructs an empty member node.
  */
 DOMMember() {
-
+	// Constructs an empty member node
 }
 /**
  * Creates a new member document fragment on the given range of the document.
@@ -207,7 +206,7 @@
 	if (flags.length == 0) {
 		return flags;
 	} else {
-		return CharArrayOps.concat(flags, new char[] {' '});
+		return CharOperation.concat(flags, new char[] {' '});
 	}
 }
 /**
@@ -219,7 +218,7 @@
 		if (fComment != null) {
 			return fComment;
 		} else {
-			return CharArrayOps.substring(fDocument, fCommentRange[0], fCommentRange[1] + 1 - fCommentRange[0]);
+			return new String(CharOperation.subarray(fDocument, fCommentRange[0], fCommentRange[1] + 1));
 		}
 	} else {
 		return null;
@@ -249,7 +248,7 @@
 		if (fModifierRange[0] < 0) {
 			return null;
 		} else {
-			return CharArrayOps.subarray(fDocument, fModifierRange[0], fModifierRange[1] + 1 - fModifierRange[0]);
+			return CharOperation.subarray(fDocument, fModifierRange[0], fModifierRange[1] + 1);
 		}
 	} else {
 		return fModifiers;
@@ -284,16 +283,11 @@
 	fragment();
 	setHasComment(comment != null);
 	/* see 1FVIJAH */
-	if (comment != null) {
-		String commentString = new String(comment);
-		if (commentString.indexOf("@deprecated") >= 0) { //$NON-NLS-1$
-			fFlags= fFlags | IConstants.AccDeprecated;
-			return;
-		}
-
+	if (comment != null && comment.indexOf("@deprecated") >= 0) { //$NON-NLS-1$
+		fFlags= fFlags | IConstants.AccDeprecated;
+		return;
 	}
 	fFlags= fFlags & (~IConstants.AccDeprecated);
-
 }
 /**
  * @see IDOMMember#setFlags(int)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java
index fd88639..7ac184f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMMethod.java
@@ -13,12 +13,11 @@
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.jdom.IDOMMethod;
 import org.eclipse.jdt.core.jdom.IDOMNode;
 import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.util.CharArrayBuffer;
-import org.eclipse.jdt.internal.core.util.CharArrayOps;
-
 /**
  * DOMMethod provides an implementation of IDOMMethod.
  *
@@ -116,7 +115,7 @@
  * Constructs an empty method node.
  */
 DOMMethod() {
-
+	// Constructs an empty method node
 }
 /**
  * Creates a new detailed METHOD document fragment on the given range of the document.
@@ -360,7 +359,7 @@
 		if (fBody != null) {
 			return fBody;
 		} else {
-			return CharArrayOps.substring(fDocument, fBodyRange[0], fBodyRange[1] + 1 - fBodyRange[0]);
+			return new String(CharOperation.subarray(fDocument, fBodyRange[0], fBodyRange[1] + 1));
 		}
 	} else {
 		return null;
@@ -480,7 +479,7 @@
 		if (isReturnTypeAltered()) {
 			return fReturnType.toCharArray();
 		} else {
-			return CharArrayOps.subarray(fDocument, fReturnTypeRange[0], fReturnTypeRange[1] + 1 - fReturnTypeRange[0]);
+			return CharOperation.subarray(fDocument, fReturnTypeRange[0], fReturnTypeRange[1] + 1);
 		}
 
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMNode.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMNode.java
index 90b0a00..05e58a9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMNode.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMNode.java
@@ -18,8 +18,8 @@
 import org.eclipse.jdt.core.jdom.IDOMFactory;
 import org.eclipse.jdt.core.jdom.IDOMMethod;
 import org.eclipse.jdt.core.jdom.IDOMNode;
-import org.eclipse.jdt.internal.core.Util;
 import org.eclipse.jdt.internal.core.util.CharArrayBuffer;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * DOMNode provides an implementation for <code>IDOMNode</code>.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java
index 5a195e6..565278f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/DOMType.java
@@ -15,16 +15,15 @@
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.core.jdom.IDOMMethod;
 import org.eclipse.jdt.core.jdom.IDOMNode;
 import org.eclipse.jdt.core.jdom.IDOMType;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
-import org.eclipse.jdt.internal.core.Util;
 import org.eclipse.jdt.internal.core.util.CharArrayBuffer;
-import org.eclipse.jdt.internal.core.util.CharArrayOps;
-
+import org.eclipse.jdt.internal.core.util.Util;
 /**
  * DOMType provides an implementation of IDOMType.
  *
@@ -34,6 +33,7 @@
  
 /* package */ class DOMType extends DOMMember implements IDOMType {
 
+	private static final String[] EMPTY_SUPERINTERFACES = new String[] {};
 	/**
 	 * The 'class' or 'interface' keyword if altered
 	 * from the documents contents, otherwise <code>null</code>.
@@ -126,7 +126,7 @@
  * Constructs an empty type node.
  */
 DOMType() {
-
+	// Constructs an empty type node
 }
 /**
  * Creates a new detailed TYPE document fragment on the given range of the document.
@@ -272,9 +272,8 @@
 	buffer.append(getName());
 
 	if (isClass()) {
-		boolean hasSuperclass = false, hasInterfaces = false;
+		boolean hasInterfaces = false;
 		if (getMask(MASK_TYPE_HAS_SUPERCLASS)) {
-			hasSuperclass = true;
 			if (fExtendsRange[0] < 0) {
 				buffer.append(" extends "); //$NON-NLS-1$
 			} else {
@@ -306,14 +305,10 @@
 				buffer.append(fDocument, fInterfacesRange[1] + 1, fOpenBodyRange[0] - fInterfacesRange[1] - 1);
 			}
 		} else {
-			if (hasSuperclass) {
-				if (fSuperclassRange[0] < 0) {
-					buffer.append(' ');
-				} else {
-					buffer.append(fDocument, fSuperclassRange[1] + 1, fOpenBodyRange[0] - fSuperclassRange[1] - 1);
-				}
+			if (fSuperclassRange[0] < 0) {
+				buffer.append(' ');
 			} else {
-				buffer.append(fDocument, fNameRange[1] + 1, fOpenBodyRange[0] - fNameRange[1] - 1);
+				buffer.append(fDocument, fSuperclassRange[1] + 1, fOpenBodyRange[0] - fSuperclassRange[1] - 1);
 			}
 		}
 	} else {
@@ -386,12 +381,14 @@
  * @see IDOMNode#getJavaElement
  */
 public IJavaElement getJavaElement(IJavaElement parent) throws IllegalArgumentException {
-	if (parent.getElementType() == IJavaElement.TYPE) {
-		return ((IType)parent).getType(getName());
-	} else if (parent.getElementType() == IJavaElement.COMPILATION_UNIT) {
-		return ((ICompilationUnit)parent).getType(getName());
-	} else {
-		throw new IllegalArgumentException(Util.bind("element.illegalParent")); //$NON-NLS-1$
+	switch (parent.getElementType()) {
+		case IJavaElement.COMPILATION_UNIT:
+			return ((ICompilationUnit)parent).getType(getName());
+		case IJavaElement.TYPE:
+			return ((IType)parent).getType(getName());
+		// Note: creating local/anonymous type is not supported 
+		default:
+			throw new IllegalArgumentException(Util.bind("element.illegalParent")); //$NON-NLS-1$
 	}
 }
 /**
@@ -421,7 +418,7 @@
 		if (fSuperclass != null) {
 			return fSuperclass;
 		} else {
-			return CharArrayOps.substring(fDocument, fSuperclassRange[0], fSuperclassRange[1] + 1 - fSuperclassRange[0]);
+			return new String(CharOperation.subarray(fDocument, fSuperclassRange[0], fSuperclassRange[1] + 1));
 		}
 	} else {
 		return null;
@@ -672,9 +669,9 @@
 	}
 	fragment();
 	fSuperInterfaces= names;
-	if (names == null || names.length == 0) {
+	if (names.length == 0) {
 		fInterfaces= null;
-		fSuperInterfaces= null;
+		fSuperInterfaces= EMPTY_SUPERINTERFACES;
 		setMask(MASK_TYPE_HAS_INTERFACES, false);
 	} else {
 		setMask(MASK_TYPE_HAS_INTERFACES, true);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
index 8fe0627..957f0a1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/jdom/SimpleDOMBuilder.java
@@ -13,20 +13,27 @@
 import java.util.Map;
 
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.jdom.IDOMCompilationUnit;
 import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
 import org.eclipse.jdt.internal.compiler.SourceElementParser;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
-import org.eclipse.jdt.internal.core.util.CharArrayOps;
-
 /**
  * A DOM builder that uses the SourceElementParser
  */
 public class SimpleDOMBuilder extends AbstractDOMBuilder implements ISourceElementRequestor {
 
-public void acceptImport(int declarationStart, int declarationEnd, char[] name, boolean onDemand) {
+/**
+ * Does nothing.
+ */
+public void acceptProblem(IProblem problem) {
+	// nothing to do
+}
+
+public void acceptImport(int declarationStart, int declarationEnd, char[] name, boolean onDemand, int modifiers) {
 	int[] sourceRange = {declarationStart, declarationEnd};
 	String importName = new String(name);
 	/** name is set to contain the '*' */
@@ -38,7 +45,7 @@
 }
 public void acceptPackage(int declarationStart, int declarationEnd, char[] name) {
 	int[] sourceRange= new int[] {declarationStart, declarationEnd};
-	fNode= new DOMPackage(fDocument, sourceRange, CharArrayOps.charToString(name));
+	fNode= new DOMPackage(fDocument, sourceRange, CharOperation.charToString(name));
 	addChild(fNode);	
 }
 /**
@@ -52,7 +59,7 @@
  */
 public IDOMCompilationUnit createCompilationUnit(ICompilationUnit compilationUnit) {
 	initializeBuild(compilationUnit.getContents(), true, true);
-	getParser(JavaCore.getOptions()).parseCompilationUnit(compilationUnit, false);
+	getParser(JavaCore.getOptions()).parseCompilationUnit(compilationUnit, false/*diet parse*/);
 	return super.createCompilationUnit(compilationUnit);
 }
 /**
@@ -75,11 +82,11 @@
 		
 	int[] sourceRange = {declarationStart, -1}; // will be fixed up on exit
 	int[] nameRange = {nameStart, nameEnd};
-	fNode = new DOMMethod(fDocument, sourceRange, CharArrayOps.charToString(name), nameRange, modifiers, 
-		isConstructor, CharArrayOps.charToString(returnType),
-		CharArrayOps.charcharToString(parameterTypes),
-		CharArrayOps.charcharToString(parameterNames), 
-		CharArrayOps.charcharToString(exceptionTypes));
+	fNode = new DOMMethod(fDocument, sourceRange, CharOperation.charToString(name), nameRange, modifiers, 
+		isConstructor, CharOperation.charToString(returnType),
+		CharOperation.charArrayToStringArray(parameterTypes),
+		CharOperation.charArrayToStringArray(parameterNames), 
+		CharOperation.charArrayToStringArray(exceptionTypes));
 	addChild(fNode);
 	fStack.push(fNode);
 }
@@ -112,8 +119,8 @@
 	if (fNode instanceof DOMField) {
 		isSecondary = declarationStart == fNode.fSourceRange[0];
 	}
-	fNode = new DOMField(fDocument, sourceRange, CharArrayOps.charToString(name), nameRange, 
-		modifiers, CharArrayOps.charToString(type), isSecondary);
+	fNode = new DOMField(fDocument, sourceRange, CharOperation.charToString(name), nameRange, 
+		modifiers, CharOperation.charToString(type), isSecondary);
 	addChild(fNode);
 	fStack.push(fNode);
 }
@@ -147,7 +154,7 @@
 		int[] sourceRange = {declarationStart, -1}; // will be fixed in the exit
 		int[] nameRange = new int[] {nameStart, nameEnd};
 		fNode = new DOMType(fDocument, sourceRange, new String(name), nameRange,
-			modifiers, CharArrayOps.charcharToString(superinterfaces), isClass);
+			modifiers, CharOperation.charArrayToStringArray(superinterfaces), isClass);
 		addChild(fNode);
 		fStack.push(fNode);
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/messages.properties b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/messages.properties
deleted file mode 100644
index 347a008..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/messages.properties
+++ /dev/null
@@ -1,232 +0,0 @@
-###############################################################################
-# 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
-###############################################################################
-### JavaModel messages.
-
-### hierarchy
-hierarchy.nullProject = Project argument cannot be null.
-hierarchy.nullRegion = Region cannot be null.
-hierarchy.nullFocusType = Type focus cannot be null.
-hierarchy.creating = Creating type hierarchy...
-hierarchy.creatingOnType = Creating type hierarchy on {0}...
-
-### java element
-element.doesNotExist = {0} does not exist.
-element.invalidClassFileName = Class file name must end with .class.
-element.cannotReconcile = Must create reconciler on a working copy.
-element.reconciling = Reconciling...
-element.attachingSource = Attaching source...
-element.invalidType = Type is not one of the defined constants.
-element.classpathCycle = A cycle was detected in the project''s classpath.
-element.onlyOneJavaModel = Cannot instantiate more than one Java Model.
-element.projectDoesNotExist = Project {0} not present
-element.invalidResourceForProject = Illegal argument - must be one of IProject, IFolder, or IFile
-element.nullName = Name cannot be null.
-element.nullType = Type cannot be null.
-element.illegalParent = Illegal parent argument.
-element.notPresent = Not present
-
-### java model operations
-operation.needElements = Operation requires one or more elements.
-operation.needName = Operation requires a name.
-operation.needPath = Operation requires a path.
-operation.needAbsolutePath = Operation requires an absolute path. Relative path specified was: ''{0}''
-operation.needString = Operation requires a String.
-operation.notSupported = Operation not supported for specified element type(s):
-operation.cancelled = Operation cancelled.
-operation.nullContainer = Container cannot be null.
-operation.nullName = Name cannot be null.
-operation.copyElementProgress = Copying elements...
-operation.moveElementProgress = Moving elements...
-operation.renameElementProgress = Renaming elements...
-operation.copyResourceProgress = Copying resources...
-operation.moveResourceProgress = Moving resources...
-operation.renameResourceProgress = Renaming resources...
-operation.createUnitProgress = Creating a compilation unit...
-operation.createFieldProgress = Creating a field...
-operation.createImportsProgress = Creating imports...
-operation.createInitializerProgress = Creating an initializer...
-operation.createMethodProgress = Creating a method...
-operation.createPackageProgress = Creating a package declaration...
-operation.createPackageFragmentProgress = Creating package fragment(s)...
-operation.createTypeProgress = Creating a type...
-operation.deleteElementProgress = Deleting elements...
-operation.deleteResourceProgress = Deleting resources...
-operation.cannotRenameDefaultPackage = Default package cannot be renamed.
-operation.pathOutsideProject = Path ''{0}'' must denote location inside project {1}
-operation.sortelements = Sorting elements...
-
-### working copy
-workingCopy.commit = Committing working copy...
-
-### build status messages
-build.preparingBuild = Preparing for build
-build.readStateProgress = Reading saved built state for project {0}
-build.saveStateProgress = Saving built state for project {0}
-build.saveStateComplete = Saved in {0} ms
-build.readingDelta = Reading resource change information for {0}
-build.analyzingDeltas = Analyzing deltas
-build.analyzingSources = Analyzing sources
-build.cleaningOutput = Cleaning output folder
-build.copyingResources = Copying resources to the output folder
-build.compiling = Compiling {0}
-build.foundHeader = Found
-build.fixedHeader = Fixed
-build.oneError = 1 error
-build.oneWarning = 1 warning
-build.multipleErrors = {0} errors
-build.multipleWarnings = {0} warnings
-build.done = Build done
-
-### build errors
-build.wrongFileFormat = Wrong file format.
-build.cannotSaveState = Error saving last build state for project {0}.
-build.cannotSaveStates = Error saving build states.
-build.initializationError = Builder initialization error.
-build.serializationError = Builder serialization error.
-
-### build inconsistencies
-build.duplicateClassFile = The type {0} is already defined.
-build.duplicateResource = The resource is a duplicate and was not copied to the output folder.
-build.inconsistentClassFile = A class file was not written. The project may be inconsistent, if so try refreshing this project and rebuilding it.
-build.inconsistentProject = The project was not built due to "{0}". Fix the problem, then try refreshing this project and rebuilding it since it may be inconsistent.
-build.incompleteClassPath = The project was not built since its classpath is incomplete. Cannot find the class file for {0}. Fix the classpath then try rebuilding this project.
-build.missingSourceFile = The project was not built since the source file {0} could not be read.
-build.prereqProjectHasClasspathProblems = The project was not built since it depends on {0}, which has classpath problems.
-build.prereqProjectMustBeRebuilt = The project cannot be built until {0} is rebuilt. Rebuilding all projects is recommended.
-build.abortDueToClasspathProblems = The project was not built due to classpath errors (incomplete or involved in cycle).
-
-### status
-status.cannotUseDeviceOnPath = Operation requires a path with no device. Path specified was: {0}
-status.coreException = Core exception.
-status.defaultPackeReadOnly = Default package is read-only.
-status.evaluationError = Evaluation error: {0}.
-status.JDOMError = JDOM error.
-status.IOException = I/O exception.
-status.indexOutOfBounds = Index out of bounds.
-status.invalidContents = Invalid contents specified.
-status.invalidDestination = Invalid destination: ''{0}''.
-status.invalidName = Invalid name specified: {0}.
-status.invalidPackage = Invalid package: {0}.
-status.invalidPath = Invalid path: ''{0}''.
-status.invalidProject = Invalid project: {0}.
-status.invalidResource = Invalid resource: {0}.
-status.invalidResourceType = Invalid resource type for {0}.
-status.invalidSibling = Invalid sibling: {0}.
-status.nameCollision = {0} already exists in target.
-status.noLocalContents = Cannot find local contents for resource: {0}
-status.OK = OK
-status.readOnly = {0} is read-only.
-status.targetException = Target exception.
-status.updateConflict = Update conflict.
-
-### classpath
-classpath.buildPath = Build path
-classpath.cannotNestEntryInEntry = Cannot nest ''{0}'' inside ''{1}''. To enable the nesting exclude ''{2}'' from ''{1}''.
-classpath.cannotNestEntryInLibrary = Cannot nest ''{0}'' inside library ''{1}''.
-classpath.cannotNestEntryInOutput = Cannot nest ''{0}'' inside output folder ''{1}''.
-classpath.cannotNestOutputInEntry = Cannot nest output folder ''{0}'' inside ''{1}''.
-classpath.cannotNestOutputInOutput = Cannot nest output folder ''{0}'' inside output folder ''{1}''.
-classpath.cannotReadClasspathFile = Unable to read ''{0}/.classpath'' file.
-classpath.cannotReferToItself = Project cannot reference itself: {0}
-classpath.cannotUseDistinctSourceFolderAsOutput = Source folder ''{0}'' cannot output to distinct source folder ''{1}''.
-classpath.cannotUseLibraryAsOutput = Source folder ''{0}'' cannot output to library ''{1}''.
-classpath.closedProject = Required project: {0} needs to be open.
-classpath.couldNotWriteClasspathFile = Could not write ''{0}/.classpath'': {1}
-classpath.cycle = A cycle was detected in the classpath of project: {0}
-classpath.duplicateEntryPath = Classpath contains duplicate entry: {0}
-classpath.illegalContainerPath = Illegal classpath container path: ''{0}'', must have at least one segment (containerID+hints).
-classpath.illegalEntryInClasspathFile = Illegal entry in ''{0}/.classpath'' file: {1}
-classpath.illegalLibraryPath = Illegal path for required library: ''{0}''.
-classpath.illegalProjectPath = Illegal path for required project: ''{0}''.
-classpath.illegalSourceFolderPath = Illegal path for required source folder: ''{0}''.
-classpath.illegalVariablePath = Illegal classpath variable path: ''{0}'', must have at least one segment.
-classpath.invalidClasspathInClasspathFile = Invalid classpath in ''{0}/.classpath'' file: {1}
-classpath.invalidContainer = Invalid classpath container: {0}
-classpath.mustEndWithSlash = End exclusion filter ''{0}'' with / to fully exclude ''{1}''.
-classpath.unboundContainerPath = Unbound classpath container: ''{0}''.
-classpath.unboundLibrary = Missing required library: ''{0}''.
-classpath.unboundProject = Missing required Java project: {0}.
-classpath.settingOutputLocationProgress = Setting output location for: ''{0}''
-classpath.settingProgress = Setting classpath for: {0}
-classpath.unboundSourceAttachment = Invalid source attachment: ''{0}'' for required library ''{1}''.
-classpath.unboundSourceFolder = Missing required source folder: ''{0}''.
-classpath.unboundVariablePath = Unbound classpath variable: ''{0}''.
-classpath.unknownKind = Unknown kind: {0}
-classpath.xmlFormatError = XML format error in ''{0}/.classpath'' file: {1}
-classpath.disabledExclusionPatterns = Exclusion patterns are disabled, cannot exclude from entry: ''{0}''.
-classpath.disabledMultipleOutputLocations = Multiple output locations are disabled, cannot associate entry: ''{0}'' with a specific output.
-
-### miscellaneous
-file.notFound = File not found: ''{0}''.
-file.badFormat = Bad format.
-variable.badFormat = Bad format for variables.
-option.badFormat = Bad format for options.
-path.nullPath = Path cannot be null.
-path.mustBeAbsolute = Path must be absolute.
-cache.invalidLoadFactor = Incorrect load factor
-
-### code assist
-codeAssist.nullRequestor = Requestor cannot be null.
-
-### java conventions
-convention.unit.nullName = Compilation unit name must not be null.
-convention.unit.notJavaName = Compilation unit name must end with .java.
-convention.classFile.nullName = .class file name must not be null.
-convention.classFile.notJavaName = .class file name must end with .class.
-convention.illegalIdentifier = ''{0}'' is not a valid Java identifier.
-convention.import.nullImport = An import declaration must not be null.
-convention.import.unqualifiedImport = An import declaration must not end with an unqualified *.
-convention.type.nullName = A Java type name must not be null.
-convention.type.nameWithBlanks = A Java type name must not start or end with a blank.
-convention.type.dollarName = By convention, Java type names usually don''t contain the $ character.
-convention.type.lowercaseName = By convention, Java type names usually start with an uppercase letter.
-convention.type.invalidName = The type name ''{0}'' is not a valid identifier.
-convention.package.nullName = A package name must not be null.
-convention.package.emptyName = A package name must not be empty.
-convention.package.dotName = A package name cannot start or end with a dot.
-convention.package.nameWithBlanks = A package name must not start or end with a blank.
-convention.package.consecutiveDotsName = A package name must not contain two consecutive dots.
-convention.package.uppercaseName = By convention, package names usually start with a lowercase letter.
-
-### DOM
-dom.cannotDetail = Unable to generate detailed source indexes.
-dom.nullTypeParameter = Cannot add parameter with null type
-dom.nullNameParameter = Cannot add parameter with null name
-dom.nullReturnType = Return type cannot be null
-dom.nullExceptionType = Cannot add null exception
-dom.mismatchArgNamesAndTypes = Types and names must have identical length
-dom.addNullChild = Attempt to add null child
-dom.addIncompatibleChild = Attempt to add child of incompatible type
-dom.addChildWithParent = Attempt to add child that is already parented
-dom.unableAddChild = Attempt to add child to node that cannot have children
-dom.addAncestorAsChild = Attempt to add ancestor as child
-dom.addNullSibling = Attempt to insert null sibling
-dom.addSiblingBeforeRoot = Attempt to insert sibling before root node
-dom.addIncompatibleSibling = Attempt to insert sibling of incompatible type
-dom.addSiblingWithParent = Attempt to insert sibling that is already parented
-dom.addAncestorAsSibling = Attempt to insert ancestor as sibling
-dom.addNullInterface = Cannot add null interface
-dom.nullInterfaces = Illegal to set super interfaces to null
-
-### eval
-eval.needBuiltState = Cannot evaluate if the project has not been built once
-
-### correction
-correction.nullRequestor = Requestor cannot be null.
-correction.nullUnit = Compilation unit cannot be null.
-
-### JDT Adapter
-ant.jdtadapter.info.usingJdtCompiler = Using JDT compiler
-ant.jdtadapter.error.missingJDTCompiler = Cannot find the JDT compiler
-ant.jdtadapter.error.missingJRELIB = Cannot bind the JRE_LIB variable. To solve this problem, you can either set the JRE_LIB variable or use the bootclasspath parameter in your ant javac task
-ant.jdtadapter.error.ignoringMemoryInitialSize= Since fork is false, ignoring memoryInitialSize setting
-ant.jdtadapter.error.ignoringMemoryMaximumSize= Since fork is false, ignoring memoryMaximumSize setting
-ant.jdtadapter.error.compilationFailed = Compilation failed. Compiler errors are available in {0}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ASTNodeFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ASTNodeFinder.java
new file mode 100644
index 0000000..a109a51
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ASTNodeFinder.java
@@ -0,0 +1,182 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.SourceType;
+
+/**
+ * Finds an ASTNode given an IJavaElement in a CompilationUnitDeclaration
+ */
+public class ASTNodeFinder {
+	private CompilationUnitDeclaration unit;
+
+	public ASTNodeFinder(CompilationUnitDeclaration unit) {
+		this.unit = unit;
+	}
+
+	/*
+	 * Finds the FieldDeclaration in the given ast corresponding to the given field handle.
+	 * Returns null if not found.
+	 */
+	public FieldDeclaration findField(IField fieldHandle) {
+		TypeDeclaration typeDecl = findType((IType)fieldHandle.getParent());
+		if (typeDecl == null) return null;
+		FieldDeclaration[] fields = typeDecl.fields;
+		if (fields != null) {
+			char[] fieldName = fieldHandle.getElementName().toCharArray();
+			for (int i = 0, length = fields.length; i < length; i++) {
+				FieldDeclaration field = fields[i];
+				if (CharOperation.equals(fieldName, field.name)) {
+					return field;
+				}
+			}
+		}
+		return null;
+	}
+
+	/*
+	 * Finds the Initializer in the given ast corresponding to the given initializer handle.
+	 * Returns null if not found.
+	 */
+	public Initializer findInitializer(IInitializer initializerHandle) {
+		TypeDeclaration typeDecl = findType((IType)initializerHandle.getParent());
+		if (typeDecl == null) return null;
+		FieldDeclaration[] fields = typeDecl.fields;
+		if (fields != null) {
+			int occurenceCount = ((JavaElement)initializerHandle).occurrenceCount;
+			for (int i = 0, length = fields.length; i < length; i++) {
+				FieldDeclaration field = fields[i];
+				if (field instanceof Initializer && --occurenceCount == 0) {
+					return (Initializer)field;
+				}
+			}
+		}
+		return null;
+	}
+
+	/*
+	 * Finds the AbstractMethodDeclaration in the given ast corresponding to the given method handle.
+	 * Returns null if not found.
+	 */
+	public AbstractMethodDeclaration findMethod(IMethod methodHandle) {
+		TypeDeclaration typeDecl = findType((IType)methodHandle.getParent());
+		if (typeDecl == null) return null;
+		AbstractMethodDeclaration[] methods = typeDecl.methods;
+		if (methods != null) {
+			char[] selector = methodHandle.getElementName().toCharArray();
+			String[] parameterTypeSignatures = methodHandle.getParameterTypes();
+			int parameterCount = parameterTypeSignatures.length;
+			nextMethod: for (int i = 0, length = methods.length; i < length; i++) {
+				AbstractMethodDeclaration method = methods[i];
+				if (CharOperation.equals(selector, method.selector)) {
+					Argument[] args = method.arguments;
+					if (args != null && args.length == parameterCount) {
+						for (int j = 0; j < parameterCount; j++) {
+							TypeReference type = args[j].type;
+							String signature = Util.typeSignature(type);
+							if (!signature.equals(parameterTypeSignatures[j])) {
+								continue nextMethod;
+							}
+						}
+						return method;
+					}
+				}
+					
+			}
+		}
+		return null;
+	}
+
+	/*
+	 * Finds the TypeDeclaration in the given ast corresponding to the given type handle.
+	 * Returns null if not found.
+	 */
+	public TypeDeclaration findType(IType typeHandle) {
+		IJavaElement parent = typeHandle.getParent();
+		final char[] typeName = typeHandle.getElementName().toCharArray();
+		final int occurenceCount = ((SourceType)typeHandle).occurrenceCount;
+		final boolean findAnonymous = typeName.length == 0;
+		class Visitor extends ASTVisitor {
+			TypeDeclaration result;
+			int count = 0;
+			public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
+				if (result != null) return false;
+				if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+					if (findAnonymous && ++count == occurenceCount) {
+						result = typeDeclaration;
+					}
+				} else {
+					if (!findAnonymous && CharOperation.equals(typeName, typeDeclaration.name)) {
+						result = typeDeclaration;
+					}
+				}
+				return false; // visit only one level
+			}
+		}
+		switch (parent.getElementType()) {
+			case IJavaElement.COMPILATION_UNIT:
+				TypeDeclaration[] types = this.unit.types;
+				if (types != null) {
+					for (int i = 0, length = types.length; i < length; i++) {
+						TypeDeclaration type = types[i];
+						if (CharOperation.equals(typeName, type.name)) {
+							return type;
+						}
+					}
+				}
+				break;
+			case IJavaElement.TYPE:
+				TypeDeclaration parentDecl = findType((IType)parent);
+				if (parentDecl == null) return null;
+				types = parentDecl.memberTypes;
+				if (types != null) {
+					for (int i = 0, length = types.length; i < length; i++) {
+						TypeDeclaration type = types[i];
+						if (CharOperation.equals(typeName, type.name)) {
+							return type;
+						}
+					}
+				}
+				break;
+			case IJavaElement.FIELD:
+				FieldDeclaration fieldDecl = findField((IField)parent);
+				if (fieldDecl == null) return null;
+				Visitor visitor = new Visitor();
+				fieldDecl.traverse(visitor, null);
+				return visitor.result;
+			case IJavaElement.INITIALIZER:
+				Initializer initializer = findInitializer((IInitializer)parent);
+				if (initializer == null) return null;
+				visitor = new Visitor();
+				initializer.traverse(visitor, null);
+				return visitor.result;
+			case IJavaElement.METHOD:
+				AbstractMethodDeclaration methodDecl = findMethod((IMethod)parent);
+				if (methodDecl == null) return null;
+				visitor = new Visitor();
+				methodDecl.traverse(visitor, (ClassScope)null);
+				return visitor.result;
+		}
+		return null;
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnonymousFileSource.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnonymousFileSource.java
index f65fdf5..3775071 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnonymousFileSource.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/AnonymousFileSource.java
@@ -49,8 +49,8 @@
 		byte hasharray[] = java.security.MessageDigest.getInstance("SHA").digest(bytes); //$NON-NLS-1$
 		StringBuffer sb = new StringBuffer();
 		for (int i = 0; i < hasharray.length; i++) {
-			sb.append(Character.forDigit((int)((hasharray[i] >> 4) & 0x0F), 16));
-			sb.append(Character.forDigit((int)(hasharray[i] & 0x0F), 16));
+			sb.append(Character.forDigit((hasharray[i] >> 4) & 0x0F, 16));
+			sb.append(Character.forDigit(hasharray[i] & 0x0F, 16));
 		}
 		sb.append(".jnk"); //$NON-NLS-1$
 		String fileName = sb.toString();
@@ -104,6 +104,7 @@
 			Thread.sleep(1);
 		} 
 		catch (InterruptedException e) {
+			// ignore
 		}
 		file = fileForName(getAnonymousFileName());
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CharArrayOps.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CharArrayOps.java
deleted file mode 100644
index 1bdf70c..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CharArrayOps.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.util;
-
-/**
- * A class to do characters operations so that we can use
- * char arrays more effectively.
- */
-public class CharArrayOps { // TODO: should promote to CharOperation
-/**
- * Returns the char arrays as an array of Strings
- */
-public static String[] charcharToString(char[][] charchar) {
-	if (charchar == null) {
-		return null;
-	}
-	String[] strings= new String[charchar.length];
-	for (int i= 0; i < charchar.length; i++) {
-		strings[i]= new String(charchar[i]);
-	}
-	return strings;
-}
-/**
- * Returns the char array as a String
- */
-public static String charToString(char[] chars) {
-	if (chars == null) {
-		return null;
-	} else {
-		return new String(chars);
-	}
-}
-/**
- * Concatinates the two arrays into one big array.
- * If the first array is null, returns the second array.
- * If the second array is null, returns the first array.
- *
- * @param first - the array which the other array is concatinated onto
- * @param second - the array which is to be concatinated onto the first array
- */
-public static char[] concat(char[] first, char[] second) {
-	if (first == null)
-		return second;
-	if (second == null)
-		return first;
-
-	int length1 = first.length;
-	int length2 = second.length;
-	char[] result = new char[length1 + length2];
-	System.arraycopy(first, 0, result, 0, length1);
-	System.arraycopy(second, 0, result, length1, length2);
-	return result;
-}
-/**
- * Checks the two character arrays for equality.
- *
- * @param first - one of the arrays to be compared
- * @param second - the other array which is to be compared
- */
-public static boolean equals(char[] first, char[] second) {
-	if (first == second)
-		return true;
-	if (first == null || second == null)
-		return false;
-	if (first.length != second.length)
-		return false;
-
-	for (int i = 0, length = first.length; i < length; i++)
-		if (first[i] != second[i])
-			return false;
-	return true;
-}
-/**
- * Returns the index of the first occurrence of character in buffer,
- * starting from offset, or -1 if not found.
- */
-public static int indexOf(char character, char[] buffer, int offset) {
-	for (int i= offset; i < buffer.length; i++) {
-		if (buffer[i] == character) {
-			return i;
-		}
-	}
-	return -1;
-}
-/**
- * Extracts a sub-array from the given array, starting
- * at the given startIndex and proceeding for length characters.
- * Returns null if:
- *  1. the src array is null
- *  2. the start index is out of bounds
- *  3. the length parameter specifies a end point which is out of bounds
- * Does not return a copy of the array if possible, in other words, if start is zero
- * and length equals the length of the src array.
- *
- * @param src - the array from which elements need to be copied
- * @param start - the start index in the src array
- * @param length - the number of characters to copy
- */
-public static char[] subarray(char[] src, int start, int length) {
-	if (src == null)
-		return null;
-	int srcLength = src.length;
-	if (start < 0 || start >= srcLength)
-		return null;
-	if (length < 0 || start + length > srcLength)
-		return null;
-	if (srcLength == length && start == 0)
-		return src;
-		
-	char[] result = new char[length];
-	if (length > 0)
-		System.arraycopy(src, start, result, 0, length);
-	return result;
-}
-/**
- * Extracts a substring from the given array, starting
- * at the given startIndex and proceeding for length characters.
- * Returns null if:
- *  1. the src array is null
- *  2. the start index is out of bounds
- *  3. the length parameter specifies a end point which is out of bounds
- * Does not return a copy of the array if possible (if start is zero
- * and length equals the length of the src array).
- *
- * @param src - the array from which elements need to be copied
- * @param start - the start index in the src array
- * @param length - the number of characters to copy
- */
-public static String substring(char[] src, int start, int length) {
-	char[] chars= subarray(src, start, length);
-	if (chars != null) {
-		return new String(chars);
-	} else {
-		return null;
-	}
-}
-}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
index ca800ef..5b5ca48 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileReader.java
@@ -47,8 +47,6 @@
 	private IInnerClassesAttribute innerClassesAttribute;
 	private ISourceAttribute sourceFileAttribute;
 	private int classNameIndex;
-	private boolean isDeprecated;
-	private boolean isSynthetic;
 	private int majorVersion;
 	private int minorVersion;
 	private int superclassNameIndex;
@@ -243,7 +241,6 @@
 						int utf8Offset = constantPoolOffsets[u2At(classFileBytes, readOffset, 0)];
 						char[] attributeName = utf8At(classFileBytes, utf8Offset + 3, 0, u2At(classFileBytes, utf8Offset + 1, 0));
 						if (equals(attributeName, IAttributeNamesConstants.DEPRECATED)) {
-							this.isDeprecated = true;
 							this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, this.constantPool, readOffset);
 						} else if (equals(attributeName, IAttributeNamesConstants.INNER_CLASSES)) {
 							this.innerClassesAttribute = new InnerClassesAttribute(classFileBytes, this.constantPool, readOffset);
@@ -252,7 +249,6 @@
 								this.sourceFileAttribute = new SourceFileAttribute(classFileBytes, this.constantPool, readOffset);
 								this.attributes[attributesIndex++] = this.sourceFileAttribute;
 						} else if (equals(attributeName, IAttributeNamesConstants.SYNTHETIC)) {
-								this.isSynthetic = true;
 								this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, this.constantPool, readOffset);
 						} else {
 							this.attributes[attributesIndex++] = new ClassFileAttribute(classFileBytes, this.constantPool, readOffset);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileStruct.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileStruct.java
index 2ce66b4..eccbf1d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileStruct.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ClassFileStruct.java
@@ -39,13 +39,13 @@
 	protected long i8At(byte[] reference, int relativeOffset, int structOffset) {
 		int position = relativeOffset + structOffset;
 		return (((long) (reference[position++] & 0xFF)) << 56)
-			+ (((long) (reference[position++] & 0xFF)) << 48)
-			+ (((long) (reference[position++] & 0xFF)) << 40)
-			+ (((long) (reference[position++] & 0xFF)) << 32)
-			+ (((long) (reference[position++] & 0xFF)) << 24)
-			+ (((long) (reference[position++] & 0xFF)) << 16)
-			+ (((long) (reference[position++] & 0xFF)) << 8)
-			+ ((long) (reference[position++] & 0xFF));
+						+ (((long) (reference[position++] & 0xFF)) << 48)
+						+ (((long) (reference[position++] & 0xFF)) << 40)
+						+ (((long) (reference[position++] & 0xFF)) << 32)
+						+ (((long) (reference[position++] & 0xFF)) << 24)
+						+ (((long) (reference[position++] & 0xFF)) << 16)
+						+ (((long) (reference[position++] & 0xFF)) << 8)
+						+ (reference[position++] & 0xFF);
 	}
 
 	protected int u1At(byte[] reference, int relativeOffset, int structOffset) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
index 6bdd9b7..4d05b56 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/CodeAttribute.java
@@ -224,7 +224,8 @@
 					constantPoolEntry = this.constantPool.decodeEntry(index);
 					if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Float
 						&& constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Integer
-						&& constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_String) {
+						&& constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_String
+						&& constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Class) {
 							throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
 					}
 					visitor._ldc_w(pc - this.codeOffset, index, constantPoolEntry);
@@ -1096,12 +1097,12 @@
 					pc+=3;
 					break;
 				case IOpcodeMnemonics.GOTO_W :
-					branchOffset = (int) i4At(this.classFileBytes, 1, pc);
+					branchOffset = i4At(this.classFileBytes, 1, pc);
 					visitor._goto_w(pc - this.codeOffset, branchOffset);
 					pc+=5;
 					break;
 				case IOpcodeMnemonics.JSR_W :
-					branchOffset = (int) i4At(this.classFileBytes, 1, pc);
+					branchOffset = i4At(this.classFileBytes, 1, pc);
 					visitor._jsr_w(pc - this.codeOffset, branchOffset);
 					pc+=5;
 					break;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
index c29fdab..4cfd770 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/DefaultBytecodeVisitor.java
@@ -36,33 +36,41 @@
 	private StringBuffer buffer;
 	private String lineSeparator;
 	private int tabNumber;
+	private int digitNumberForPC;
 	
-	public DefaultBytecodeVisitor(StringBuffer buffer, String lineSeparator, int tabNumber) {
+	public DefaultBytecodeVisitor(long codeLength, StringBuffer buffer, String lineSeparator, int tabNumber) {
 		this.buffer = buffer;
 		this.lineSeparator = lineSeparator;
 		this.tabNumber = tabNumber + 1;
+		this.digitNumberForPC = (int) (Math.log(codeLength) / Math.log(10));
 	}
 	/**
 	 * @see IBytecodeVisitor#_aaload(int)
 	 */
 	public void _aaload(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.AALOAD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.AALOAD]);
 		writeNewLine();
 	}
+	private void dumpPcNumber(int pc) {
+		writeTabs();
+		int digitForPC = 0;
+		if (pc != 0) {
+			digitForPC = (int) (Math.log(pc) / Math.log(10));
+		}
+		for (int i = 0, max = this.digitNumberForPC - digitForPC; i < max; i++) {
+			buffer.append(' ');
+		}
+		buffer.append(pc);
+		buffer.append(Util.bind("disassembler.identation")); //$NON-NLS-1$
+	}
 
 	/**
 	 * @see IBytecodeVisitor#_aastore(int)
 	 */
 	public void _aastore(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.AASTORE]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.AASTORE]);
 		writeNewLine();
 	}
 
@@ -70,11 +78,8 @@
 	 * @see IBytecodeVisitor#_aconst_null(int)
 	 */
 	public void _aconst_null(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ACONST_NULL]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ACONST_NULL]);
 		writeNewLine();
 	}
 
@@ -82,11 +87,8 @@
 	 * @see IBytecodeVisitor#_aload_0(int)
 	 */
 	public void _aload_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ALOAD_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ALOAD_0]);
 		writeNewLine();
 	}
 
@@ -94,11 +96,8 @@
 	 * @see IBytecodeVisitor#_aload_1(int)
 	 */
 	public void _aload_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ALOAD_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ALOAD_1]);
 		writeNewLine();
 	}
 
@@ -106,11 +105,8 @@
 	 * @see IBytecodeVisitor#_aload_2(int)
 	 */
 	public void _aload_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ALOAD_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ALOAD_2]);
 		writeNewLine();
 	}
 
@@ -118,11 +114,8 @@
 	 * @see IBytecodeVisitor#_aload_3(int)
 	 */
 	public void _aload_3(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ALOAD_3]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ALOAD_3]);
 		writeNewLine();
 	}
 
@@ -130,11 +123,8 @@
 	 * @see IBytecodeVisitor#_aload(int, int)
 	 */
 	public void _aload(int pc, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ALOAD])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ALOAD])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index);
 		writeNewLine();
@@ -144,11 +134,8 @@
 	 * @see IBytecodeVisitor#_anewarray(int, int, IConstantPoolEntry)
 	 */
 	public void _anewarray(int pc, int index, IConstantPoolEntry constantClass) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ANEWARRAY])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ANEWARRAY])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
@@ -160,11 +147,8 @@
 	 * @see IBytecodeVisitor#_areturn(int)
 	 */
 	public void _areturn(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ARETURN]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ARETURN]);
 		writeNewLine();
 	}
 
@@ -172,11 +156,8 @@
 	 * @see IBytecodeVisitor#_arraylength(int)
 	 */
 	public void _arraylength(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ARRAYLENGTH]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ARRAYLENGTH]);
 		writeNewLine();
 	}
 
@@ -184,11 +165,8 @@
 	 * @see IBytecodeVisitor#_astore_0(int)
 	 */
 	public void _astore_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ASTORE_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ASTORE_0]);
 		writeNewLine();
 	}
 
@@ -196,11 +174,8 @@
 	 * @see IBytecodeVisitor#_astore_1(int)
 	 */
 	public void _astore_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ASTORE_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ASTORE_1]);
 		writeNewLine();
 	}
 
@@ -208,11 +183,8 @@
 	 * @see IBytecodeVisitor#_astore_2(int)
 	 */
 	public void _astore_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ASTORE_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ASTORE_2]);
 		writeNewLine();
 	}
 
@@ -220,11 +192,8 @@
 	 * @see IBytecodeVisitor#_astore_3(int)
 	 */
 	public void _astore_3(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ASTORE_3]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ASTORE_3]);
 		writeNewLine();
 	}
 
@@ -232,11 +201,8 @@
 	 * @see IBytecodeVisitor#_astore(int, int)
 	 */
 	public void _astore(int pc, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ASTORE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ASTORE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index);
 		writeNewLine();
@@ -246,11 +212,8 @@
 	 * @see IBytecodeVisitor#_athrow(int)
 	 */
 	public void _athrow(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ATHROW]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ATHROW]);
 		writeNewLine();
 	}
 
@@ -258,11 +221,8 @@
 	 * @see IBytecodeVisitor#_baload(int)
 	 */
 	public void _baload(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.BALOAD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.BALOAD]);
 		writeNewLine();
 	}
 
@@ -270,11 +230,8 @@
 	 * @see IBytecodeVisitor#_bastore(int)
 	 */
 	public void _bastore(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.BASTORE]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.BASTORE]);
 		writeNewLine();
 	}
 	
@@ -282,11 +239,8 @@
 	 * @see IBytecodeVisitor#_bipush(int, byte)
 	 */
 	public void _bipush(int pc, byte _byte) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.BIPUSH])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.BIPUSH])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(_byte);
 		writeNewLine();
@@ -296,11 +250,8 @@
 	 * @see IBytecodeVisitor#_caload(int)
 	 */
 	public void _caload(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.CALOAD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.CALOAD]);
 		writeNewLine();
 	}
 
@@ -308,11 +259,8 @@
 	 * @see IBytecodeVisitor#_castore(int)
 	 */
 	public void _castore(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.CASTORE]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.CASTORE]);
 		writeNewLine();
 	}
 
@@ -320,11 +268,8 @@
 	 * @see IBytecodeVisitor#_checkcast(int, int, IConstantPoolEntry)
 	 */
 	public void _checkcast(int pc, int index, IConstantPoolEntry constantClass) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.CHECKCAST])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.CHECKCAST])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
@@ -336,11 +281,8 @@
 	 * @see IBytecodeVisitor#_d2f(int)
 	 */
 	public void _d2f(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.D2F]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.D2F]);
 		writeNewLine();
 	}
 
@@ -348,11 +290,8 @@
 	 * @see IBytecodeVisitor#_d2i(int)
 	 */
 	public void _d2i(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.D2I]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.D2I]);
 		writeNewLine();
 	}
 
@@ -360,11 +299,8 @@
 	 * @see IBytecodeVisitor#_d2l(int)
 	 */
 	public void _d2l(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.D2L]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.D2L]);
 		writeNewLine();
 	}
 
@@ -372,11 +308,8 @@
 	 * @see IBytecodeVisitor#_dadd(int)
 	 */
 	public void _dadd(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DADD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DADD]);
 		writeNewLine();
 	}
 
@@ -384,11 +317,8 @@
 	 * @see IBytecodeVisitor#_daload(int)
 	 */
 	public void _daload(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DALOAD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DALOAD]);
 		writeNewLine();
 	}
 
@@ -396,11 +326,8 @@
 	 * @see IBytecodeVisitor#_dastore(int)
 	 */
 	public void _dastore(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DASTORE]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DASTORE]);
 		writeNewLine();
 	}
 
@@ -408,11 +335,8 @@
 	 * @see IBytecodeVisitor#_dcmpg(int)
 	 */
 	public void _dcmpg(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DCMPG]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DCMPG]);
 		writeNewLine();
 	}
 
@@ -420,11 +344,8 @@
 	 * @see IBytecodeVisitor#_dcmpl(int)
 	 */
 	public void _dcmpl(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DCMPL]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DCMPL]);
 		writeNewLine();
 	}
 
@@ -432,11 +353,8 @@
 	 * @see IBytecodeVisitor#_dconst_0(int)
 	 */
 	public void _dconst_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DCONST_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DCONST_0]);
 		writeNewLine();
 	}
 
@@ -444,11 +362,8 @@
 	 * @see IBytecodeVisitor#_dconst_1(int)
 	 */
 	public void _dconst_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DCONST_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DCONST_1]);
 		writeNewLine();
 	}
 
@@ -456,11 +371,8 @@
 	 * @see IBytecodeVisitor#_ddiv(int)
 	 */
 	public void _ddiv(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DDIV]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DDIV]);
 		writeNewLine();
 	}
 
@@ -468,11 +380,8 @@
 	 * @see IBytecodeVisitor#_dload_0(int)
 	 */
 	public void _dload_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DLOAD_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DLOAD_0]);
 		writeNewLine();
 	}
 
@@ -480,11 +389,8 @@
 	 * @see IBytecodeVisitor#_dload_1(int)
 	 */
 	public void _dload_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DLOAD_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DLOAD_1]);
 		writeNewLine();
 	}
 
@@ -492,11 +398,8 @@
 	 * @see IBytecodeVisitor#_dload_2(int)
 	 */
 	public void _dload_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DLOAD_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DLOAD_2]);
 		writeNewLine();
 	}
 	
@@ -504,11 +407,8 @@
 	 * @see IBytecodeVisitor#_dload_3(int)
 	 */
 	public void _dload_3(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DLOAD_3]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DLOAD_3]);
 		writeNewLine();
 	}
 
@@ -516,11 +416,8 @@
 	 * @see IBytecodeVisitor#_dload(int, int)
 	 */
 	public void _dload(int pc, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DLOAD])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DLOAD])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index);
 		writeNewLine();
@@ -530,11 +427,8 @@
 	 * @see IBytecodeVisitor#_dmul(int)
 	 */
 	public void _dmul(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DMUL]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DMUL]);
 		writeNewLine();
 	}
 
@@ -542,11 +436,8 @@
 	 * @see IBytecodeVisitor#_dneg(int)
 	 */
 	public void _dneg(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DNEG]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DNEG]);
 		writeNewLine();
 	}
 
@@ -554,11 +445,8 @@
 	 * @see IBytecodeVisitor#_drem(int)
 	 */
 	public void _drem(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DREM]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DREM]);
 		writeNewLine();
 	}
 
@@ -566,11 +454,8 @@
 	 * @see IBytecodeVisitor#_dreturn(int)
 	 */
 	public void _dreturn(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DRETURN]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DRETURN]);
 		writeNewLine();
 	}
 
@@ -578,11 +463,8 @@
 	 * @see IBytecodeVisitor#_dstore_0(int)
 	 */
 	public void _dstore_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSTORE_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSTORE_0]);
 		writeNewLine();
 	}
 
@@ -590,11 +472,8 @@
 	 * @see IBytecodeVisitor#_dstore_1(int)
 	 */
 	public void _dstore_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSTORE_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSTORE_1]);
 		writeNewLine();
 	}
 
@@ -602,11 +481,8 @@
 	 * @see IBytecodeVisitor#_dstore_2(int)
 	 */
 	public void _dstore_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSTORE_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSTORE_2]);
 		writeNewLine();
 	}
 
@@ -614,11 +490,8 @@
 	 * @see IBytecodeVisitor#_dstore_3(int)
 	 */
 	public void _dstore_3(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSTORE_3]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSTORE_3]);
 		writeNewLine();
 	}
 
@@ -626,11 +499,8 @@
 	 * @see IBytecodeVisitor#_dstore(int,int)
 	 */
 	public void _dstore(int pc, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSTORE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSTORE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index);
 		writeNewLine();
@@ -640,11 +510,8 @@
 	 * @see IBytecodeVisitor#_dsub(int)
 	 */
 	public void _dsub(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSUB]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DSUB]);
 		writeNewLine();
 	}
 
@@ -652,11 +519,8 @@
 	 * @see IBytecodeVisitor#_dup_x1(int)
 	 */
 	public void _dup_x1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP_X1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP_X1]);
 		writeNewLine();
 	}
 
@@ -664,11 +528,8 @@
 	 * @see IBytecodeVisitor#_dup_x2(int)
 	 */
 	public void _dup_x2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP_X2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP_X2]);
 		writeNewLine();
 	}
 
@@ -676,11 +537,8 @@
 	 * @see IBytecodeVisitor#_dup(int)
 	 */
 	public void _dup(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP]);
 		writeNewLine();
 	}
 
@@ -688,11 +546,8 @@
 	 * @see IBytecodeVisitor#_dup2_x1(int)
 	 */
 	public void _dup2_x1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP2_X1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP2_X1]);
 		writeNewLine();
 	}
 
@@ -700,11 +555,8 @@
 	 * @see IBytecodeVisitor#_dup2_x2(int)
 	 */
 	public void _dup2_x2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP2_X2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP2_X2]);
 		writeNewLine();
 	}
 
@@ -712,11 +564,8 @@
 	 * @see IBytecodeVisitor#_dup2(int)
 	 */
 	public void _dup2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.DUP2]);
 		writeNewLine();
 	}
 
@@ -724,11 +573,8 @@
 	 * @see IBytecodeVisitor#_f2d(int)
 	 */
 	public void _f2d(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.F2D]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.F2D]);
 		writeNewLine();
 	}
 
@@ -736,11 +582,8 @@
 	 * @see IBytecodeVisitor#_f2i(int)
 	 */
 	public void _f2i(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.F2I]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.F2I]);
 		writeNewLine();
 	}
 	
@@ -748,11 +591,8 @@
 	 * @see IBytecodeVisitor#_f2l(int)
 	 */
 	public void _f2l(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.F2L]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.F2L]);
 		writeNewLine();
 	}
 
@@ -760,11 +600,8 @@
 	 * @see IBytecodeVisitor#_fadd(int)
 	 */
 	public void _fadd(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FADD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FADD]);
 		writeNewLine();
 	}
 	
@@ -772,11 +609,8 @@
 	 * @see IBytecodeVisitor#_faload(int)
 	 */
 	public void _faload(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FALOAD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FALOAD]);
 		writeNewLine();
 	}
 
@@ -784,11 +618,8 @@
 	 * @see IBytecodeVisitor#_fastore(int)
 	 */
 	public void _fastore(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FASTORE]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FASTORE]);
 		writeNewLine();
 	}
 
@@ -796,11 +627,8 @@
 	 * @see IBytecodeVisitor#_fcmpg(int)
 	 */
 	public void _fcmpg(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FCMPG]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FCMPG]);
 		writeNewLine();
 	}
 
@@ -808,11 +636,8 @@
 	 * @see IBytecodeVisitor#_fcmpl(int)
 	 */
 	public void _fcmpl(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FCMPL]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FCMPL]);
 		writeNewLine();
 	}
 
@@ -820,11 +645,8 @@
 	 * @see IBytecodeVisitor#_fconst_0(int)
 	 */
 	public void _fconst_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FCONST_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FCONST_0]);
 		writeNewLine();
 	}
 
@@ -832,11 +654,8 @@
 	 * @see IBytecodeVisitor#_fconst_1(int)
 	 */
 	public void _fconst_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FCONST_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FCONST_1]);
 		writeNewLine();
 	}
 
@@ -844,11 +663,8 @@
 	 * @see IBytecodeVisitor#_fconst_2(int)
 	 */
 	public void _fconst_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FCONST_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FCONST_2]);
 		writeNewLine();
 	}
 
@@ -856,11 +672,8 @@
 	 * @see IBytecodeVisitor#_fdiv(int)
 	 */
 	public void _fdiv(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FDIV]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FDIV]);
 		writeNewLine();
 	}
 
@@ -868,11 +681,8 @@
 	 * @see IBytecodeVisitor#_fload_0(int)
 	 */
 	public void _fload_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FLOAD_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FLOAD_0]);
 		writeNewLine();
 	}
 
@@ -880,11 +690,8 @@
 	 * @see IBytecodeVisitor#_fload_1(int)
 	 */
 	public void _fload_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FLOAD_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FLOAD_1]);
 		writeNewLine();
 	}
 
@@ -892,11 +699,8 @@
 	 * @see IBytecodeVisitor#_fload_2(int)
 	 */
 	public void _fload_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FLOAD_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FLOAD_2]);
 		writeNewLine();
 	}
 
@@ -904,11 +708,8 @@
 	 * @see IBytecodeVisitor#_fload_3(int)
 	 */
 	public void _fload_3(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FLOAD_3]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FLOAD_3]);
 		writeNewLine();
 	}
 
@@ -916,11 +717,8 @@
 	 * @see IBytecodeVisitor#_fload(int, int)
 	 */
 	public void _fload(int pc, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FLOAD])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FLOAD])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index);
 		writeNewLine();
@@ -930,11 +728,8 @@
 	 * @see IBytecodeVisitor#_fmul(int)
 	 */
 	public void _fmul(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FMUL]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FMUL]);
 		writeNewLine();
 	}
 
@@ -942,11 +737,8 @@
 	 * @see IBytecodeVisitor#_fneg(int)
 	 */
 	public void _fneg(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FNEG]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FNEG]);
 		writeNewLine();
 	}
 	
@@ -954,11 +746,8 @@
 	 * @see IBytecodeVisitor#_frem(int)
 	 */
 	public void _frem(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FREM]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FREM]);
 		writeNewLine();
 	}
 
@@ -966,11 +755,8 @@
 	 * @see IBytecodeVisitor#_freturn(int)
 	 */
 	public void _freturn(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FRETURN]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FRETURN]);
 		writeNewLine();
 	}
 
@@ -978,11 +764,8 @@
 	 * @see IBytecodeVisitor#_fstore_0(int)
 	 */
 	public void _fstore_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSTORE_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSTORE_0]);
 		writeNewLine();
 	}
 
@@ -990,11 +773,8 @@
 	 * @see IBytecodeVisitor#_fstore_1(int)
 	 */
 	public void _fstore_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSTORE_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSTORE_1]);
 		writeNewLine();
 	}
 
@@ -1002,11 +782,8 @@
 	 * @see IBytecodeVisitor#_fstore_2(int)
 	 */
 	public void _fstore_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSTORE_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSTORE_2]);
 		writeNewLine();
 	}
 
@@ -1014,11 +791,8 @@
 	 * @see IBytecodeVisitor#_fstore_3(int)
 	 */
 	public void _fstore_3(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSTORE_3]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSTORE_3]);
 		writeNewLine();
 	}
 
@@ -1026,11 +800,8 @@
 	 * @see IBytecodeVisitor#_fstore(int, int)
 	 */
 	public void _fstore(int pc, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSTORE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSTORE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index);
 		writeNewLine();
@@ -1040,11 +811,8 @@
 	 * @see IBytecodeVisitor#_fsub(int)
 	 */
 	public void _fsub(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSUB]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.FSUB]);
 		writeNewLine();
 	}
 
@@ -1052,11 +820,8 @@
 	 * @see IBytecodeVisitor#_getfield(int, int, IConstantPoolEntry)
 	 */
 	public void _getfield(int pc, int index, IConstantPoolEntry constantFieldref) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.GETFIELD])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.GETFIELD])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("classformat.getfield")) //$NON-NLS-1$
@@ -1073,11 +838,8 @@
 	 * @see IBytecodeVisitor#_getstatic(int, int, IConstantPoolEntry)
 	 */
 	public void _getstatic(int pc, int index, IConstantPoolEntry constantFieldref) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.GETSTATIC])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.GETSTATIC])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("classformat.getstatic")) //$NON-NLS-1$
@@ -1094,11 +856,8 @@
 	 * @see IBytecodeVisitor#_goto_w(int, int)
 	 */
 	public void _goto_w(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.GOTO_W])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.GOTO_W])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1108,11 +867,8 @@
 	 * @see IBytecodeVisitor#_goto(int, int)
 	 */
 	public void _goto(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.GOTO])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.GOTO])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1122,11 +878,8 @@
 	 * @see IBytecodeVisitor#_i2b(int)
 	 */
 	public void _i2b(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2B]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2B]);
 		writeNewLine();
 	}
 
@@ -1134,11 +887,8 @@
 	 * @see IBytecodeVisitor#_i2c(int)
 	 */
 	public void _i2c(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2C]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2C]);
 		writeNewLine();
 	}
 
@@ -1146,11 +896,8 @@
 	 * @see IBytecodeVisitor#_i2d(int)
 	 */
 	public void _i2d(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2D]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2D]);
 		writeNewLine();
 	}
 
@@ -1158,11 +905,8 @@
 	 * @see IBytecodeVisitor#_i2f(int)
 	 */
 	public void _i2f(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2F]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2F]);
 		writeNewLine();
 	}
 
@@ -1170,11 +914,8 @@
 	 * @see IBytecodeVisitor#_i2l(int)
 	 */
 	public void _i2l(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2L]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2L]);
 		writeNewLine();
 	}
 
@@ -1182,11 +923,8 @@
 	 * @see IBytecodeVisitor#_i2s(int)
 	 */
 	public void _i2s(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2S]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.I2S]);
 		writeNewLine();
 	}
 
@@ -1194,11 +932,8 @@
 	 * @see IBytecodeVisitor#_iadd(int)
 	 */
 	public void _iadd(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IADD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IADD]);
 		writeNewLine();
 	}
 
@@ -1206,11 +941,8 @@
 	 * @see IBytecodeVisitor#_iaload(int)
 	 */
 	public void _iaload(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IALOAD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IALOAD]);
 		writeNewLine();
 	}
 
@@ -1218,11 +950,8 @@
 	 * @see IBytecodeVisitor#_iand(int)
 	 */
 	public void _iand(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IAND]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IAND]);
 		writeNewLine();
 	}
 
@@ -1230,11 +959,8 @@
 	 * @see IBytecodeVisitor#_iastore(int)
 	 */
 	public void _iastore(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IASTORE]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IASTORE]);
 		writeNewLine();
 	}
 
@@ -1242,11 +968,8 @@
 	 * @see IBytecodeVisitor#_if_acmpeq(int, int)
 	 */
 	public void _if_acmpeq(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ACMPEQ])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ACMPEQ])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1256,11 +979,8 @@
 	 * @see IBytecodeVisitor#_if_acmpne(int, int)
 	 */
 	public void _if_acmpne(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ACMPNE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ACMPNE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1270,11 +990,8 @@
 	 * @see IBytecodeVisitor#_if_icmpeq(int, int)
 	 */
 	public void _if_icmpeq(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPEQ])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPEQ])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1284,11 +1001,8 @@
 	 * @see IBytecodeVisitor#_if_icmpge(int, int)
 	 */
 	public void _if_icmpge(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPGE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPGE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1298,11 +1012,8 @@
 	 * @see IBytecodeVisitor#_if_icmpgt(int, int)
 	 */
 	public void _if_icmpgt(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPGT])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPGT])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1312,11 +1023,8 @@
 	 * @see IBytecodeVisitor#_if_icmple(int, int)
 	 */
 	public void _if_icmple(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPLE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPLE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1326,11 +1034,8 @@
 	 * @see IBytecodeVisitor#_if_icmplt(int, int)
 	 */
 	public void _if_icmplt(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPLT])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPLT])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1340,11 +1045,8 @@
 	 * @see IBytecodeVisitor#_if_icmpne(int, int)
 	 */
 	public void _if_icmpne(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPNE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IF_ICMPNE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1354,11 +1056,8 @@
 	 * @see IBytecodeVisitor#_iconst_0(int)
 	 */
 	public void _iconst_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_0]);
 		writeNewLine();
 	}
 
@@ -1366,11 +1065,8 @@
 	 * @see IBytecodeVisitor#_iconst_1(int)
 	 */
 	public void _iconst_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_1]);
 		writeNewLine();
 	}
 
@@ -1378,11 +1074,8 @@
 	 * @see IBytecodeVisitor#_iconst_2(int)
 	 */
 	public void _iconst_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_2]);
 		writeNewLine();
 	}
 
@@ -1390,11 +1083,8 @@
 	 * @see IBytecodeVisitor#_iconst_3(int)
 	 */
 	public void _iconst_3(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_3]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_3]);
 		writeNewLine();
 	}
 
@@ -1402,11 +1092,8 @@
 	 * @see IBytecodeVisitor#_iconst_4(int)
 	 */
 	public void _iconst_4(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_4]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_4]);
 		writeNewLine();
 	}
 
@@ -1414,11 +1101,8 @@
 	 * @see IBytecodeVisitor#_iconst_5(int)
 	 */
 	public void _iconst_5(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_5]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_5]);
 		writeNewLine();
 	}
 
@@ -1426,11 +1110,8 @@
 	 * @see IBytecodeVisitor#_iconst_m1(int)
 	 */
 	public void _iconst_m1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_M1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ICONST_M1]);
 		writeNewLine();
 	}
 
@@ -1438,11 +1119,8 @@
 	 * @see IBytecodeVisitor#_idiv(int)
 	 */
 	public void _idiv(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IDIV]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IDIV]);
 		writeNewLine();
 	}
 
@@ -1450,11 +1128,8 @@
 	 * @see IBytecodeVisitor#_ifeq(int, int)
 	 */
 	public void _ifeq(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFEQ])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFEQ])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1464,11 +1139,8 @@
 	 * @see IBytecodeVisitor#_ifge(int, int)
 	 */
 	public void _ifge(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFGE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFGE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1478,11 +1150,8 @@
 	 * @see IBytecodeVisitor#_ifgt(int, int)
 	 */
 	public void _ifgt(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFGT])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFGT])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1492,11 +1161,8 @@
 	 * @see IBytecodeVisitor#_ifle(int, int)
 	 */
 	public void _ifle(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFLE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFLE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1506,11 +1172,8 @@
 	 * @see IBytecodeVisitor#_iflt(int, int)
 	 */
 	public void _iflt(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFLT])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFLT])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1520,11 +1183,8 @@
 	 * @see IBytecodeVisitor#_ifne(int, int)
 	 */
 	public void _ifne(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFNE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFNE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1534,11 +1194,8 @@
 	 * @see IBytecodeVisitor#_ifnonnull(int, int)
 	 */
 	public void _ifnonnull(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFNONNULL])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFNONNULL])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1548,11 +1205,8 @@
 	 * @see IBytecodeVisitor#_ifnull(int, int)
 	 */
 	public void _ifnull(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFNULL])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IFNULL])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -1562,11 +1216,8 @@
 	 * @see IBytecodeVisitor#_iinc(int, int, int)
 	 */
 	public void _iinc(int pc, int index, int _const) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IINC])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IINC])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
@@ -1578,11 +1229,8 @@
 	 * @see IBytecodeVisitor#_iload_0(int)
 	 */
 	public void _iload_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ILOAD_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ILOAD_0]);
 		writeNewLine();
 	}
 
@@ -1590,11 +1238,8 @@
 	 * @see IBytecodeVisitor#_iload_1(int)
 	 */
 	public void _iload_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ILOAD_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ILOAD_1]);
 		writeNewLine();
 	}
 
@@ -1602,11 +1247,8 @@
 	 * @see IBytecodeVisitor#_iload_2(int)
 	 */
 	public void _iload_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ILOAD_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ILOAD_2]);
 		writeNewLine();
 	}
 
@@ -1614,11 +1256,8 @@
 	 * @see IBytecodeVisitor#_iload_3(int)
 	 */
 	public void _iload_3(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ILOAD_3]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ILOAD_3]);
 		writeNewLine();
 	}
 
@@ -1626,11 +1265,8 @@
 	 * @see IBytecodeVisitor#_iload(int, int)
 	 */
 	public void _iload(int pc, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ILOAD])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ILOAD])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index);
 		writeNewLine();
@@ -1640,11 +1276,8 @@
 	 * @see IBytecodeVisitor#_imul(int)
 	 */
 	public void _imul(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IMUL]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IMUL]);
 		writeNewLine();
 	}
 
@@ -1652,11 +1285,8 @@
 	 * @see IBytecodeVisitor#_ineg(int)
 	 */
 	public void _ineg(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INEG]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INEG]);
 		writeNewLine();
 	}
 
@@ -1664,11 +1294,8 @@
 	 * @see IBytecodeVisitor#_instanceof(int, int, IConstantPoolEntry)
 	 */
 	public void _instanceof(int pc, int index, IConstantPoolEntry constantClass) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INSTANCEOF])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INSTANCEOF])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
@@ -1690,11 +1317,8 @@
 		char[] returnType = Signature.getReturnType(methodDescriptor);
 		CharOperation.replace(returnType, '/', '.');
 		
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKEINTERFACE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKEINTERFACE])
 			.append(Util.bind("classformat.nargs")) //$NON-NLS-1$
 			.append(nargs)
 			.append(Util.bind("classformat.interfacemethodrefindex")) //$NON-NLS-1$
@@ -1728,11 +1352,8 @@
 		
 		if (CharOperation.equals(INIT, methodName)) {
 			methodName = EMPTY_NAME;
-			writeTabs();
-			buffer
-				.append(pc)
-				.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-				.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKESPECIAL])
+			dumpPcNumber(pc);
+			buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKESPECIAL])
 				.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 				.append(index)
 				.append(Util.bind("classformat.invokespecialconstructor")) //$NON-NLS-1$
@@ -1747,11 +1368,8 @@
 				.append(Util.bind("classformat.invokespecialconstructorclose")); //$NON-NLS-1$
 			writeNewLine();
 		} else {
-			writeTabs();
-			buffer
-				.append(pc)
-				.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-				.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKESPECIAL])
+			dumpPcNumber(pc);
+			buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKESPECIAL])
 				.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 				.append(index)
 				.append(Util.bind("classformat.invokespecialmethod")) //$NON-NLS-1$
@@ -1781,11 +1399,8 @@
 		char[] returnType = Signature.getReturnType(methodDescriptor);
 		CharOperation.replace(returnType, '/', '.');
 		
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKESTATIC])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKESTATIC])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("classformat.invokestaticmethod")) //$NON-NLS-1$
@@ -1814,11 +1429,8 @@
 		char[] returnType = Signature.getReturnType(methodDescriptor);
 		CharOperation.replace(returnType, '/', '.');
 		
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKEVIRTUAL])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.INVOKEVIRTUAL])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("classformat.invokevirtualmethod")) //$NON-NLS-1$
@@ -1841,11 +1453,8 @@
 	 * @see IBytecodeVisitor#_ior(int)
 	 */
 	public void _ior(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IOR]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IOR]);
 		writeNewLine();
 	}
 
@@ -1853,11 +1462,8 @@
 	 * @see IBytecodeVisitor#_irem(int)
 	 */
 	public void _irem(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IREM]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IREM]);
 		writeNewLine();
 	}
 
@@ -1865,11 +1471,8 @@
 	 * @see IBytecodeVisitor#_ireturn(int)
 	 */
 	public void _ireturn(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IRETURN]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IRETURN]);
 		writeNewLine();
 	}
 
@@ -1877,11 +1480,8 @@
 	 * @see IBytecodeVisitor#_ishl(int)
 	 */
 	public void _ishl(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISHL]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISHL]);
 		writeNewLine();
 	}
 
@@ -1889,11 +1489,8 @@
 	 * @see IBytecodeVisitor#_ishr(int)
 	 */
 	public void _ishr(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISHR]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISHR]);
 		writeNewLine();
 	}
 
@@ -1901,11 +1498,8 @@
 	 * @see IBytecodeVisitor#_istore_0(int)
 	 */
 	public void _istore_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISTORE_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISTORE_0]);
 		writeNewLine();
 	}
 
@@ -1913,11 +1507,8 @@
 	 * @see IBytecodeVisitor#_istore_1(int)
 	 */
 	public void _istore_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISTORE_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISTORE_1]);
 		writeNewLine();
 	}
 
@@ -1925,11 +1516,8 @@
 	 * @see IBytecodeVisitor#_istore_2(int)
 	 */
 	public void _istore_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISTORE_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISTORE_2]);
 		writeNewLine();
 	}
 
@@ -1937,11 +1525,8 @@
 	 * @see IBytecodeVisitor#_istore_3(int)
 	 */
 	public void _istore_3(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISTORE_3]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISTORE_3]);
 		writeNewLine();
 	}
 
@@ -1949,11 +1534,8 @@
 	 * @see IBytecodeVisitor#_istore(int, int)
 	 */
 	public void _istore(int pc, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISTORE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISTORE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index);
 		writeNewLine();
@@ -1963,11 +1545,8 @@
 	 * @see IBytecodeVisitor#_isub(int)
 	 */
 	public void _isub(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISUB]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.ISUB]);
 		writeNewLine();
 	}
 
@@ -1975,11 +1554,8 @@
 	 * @see IBytecodeVisitor#_iushr(int)
 	 */
 	public void _iushr(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IUSHR]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IUSHR]);
 		writeNewLine();
 	}
 
@@ -1987,11 +1563,8 @@
 	 * @see IBytecodeVisitor#_ixor(int)
 	 */
 	public void _ixor(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IXOR]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IXOR]);
 		writeNewLine();
 	}
 
@@ -1999,11 +1572,8 @@
 	 * @see IBytecodeVisitor#_jsr_w(int, int)
 	 */
 	public void _jsr_w(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.JSR_W])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.JSR_W])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -2013,11 +1583,8 @@
 	 * @see IBytecodeVisitor#_jsr(int, int)
 	 */
 	public void _jsr(int pc, int branchOffset) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.JSR])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.JSR])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(branchOffset + pc);
 		writeNewLine();
@@ -2027,11 +1594,8 @@
 	 * @see IBytecodeVisitor#_l2d(int)
 	 */
 	public void _l2d(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.L2D]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.L2D]);
 		writeNewLine();
 	}
 
@@ -2039,11 +1603,8 @@
 	 * @see IBytecodeVisitor#_l2f(int)
 	 */
 	public void _l2f(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.L2F]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.L2F]);
 		writeNewLine();
 	}
 
@@ -2051,11 +1612,8 @@
 	 * @see IBytecodeVisitor#_l2i(int)
 	 */
 	public void _l2i(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.L2I]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.L2I]);
 		writeNewLine();
 	}
 
@@ -2063,11 +1621,8 @@
 	 * @see IBytecodeVisitor#_ladd(int)
 	 */
 	public void _ladd(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LADD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LADD]);
 		writeNewLine();
 	}
 
@@ -2075,11 +1630,8 @@
 	 * @see IBytecodeVisitor#_laload(int)
 	 */
 	public void _laload(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LALOAD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LALOAD]);
 		writeNewLine();
 	}
 
@@ -2087,11 +1639,8 @@
 	 * @see IBytecodeVisitor#_land(int)
 	 */
 	public void _land(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LAND]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LAND]);
 		writeNewLine();
 	}
 
@@ -2099,11 +1648,8 @@
 	 * @see IBytecodeVisitor#_lastore(int)
 	 */
 	public void _lastore(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LASTORE]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LASTORE]);
 		writeNewLine();
 	}
 
@@ -2111,11 +1657,8 @@
 	 * @see IBytecodeVisitor#_lcmp(int)
 	 */
 	public void _lcmp(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LCMP]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LCMP]);
 		writeNewLine();
 	}
 
@@ -2123,11 +1666,8 @@
 	 * @see IBytecodeVisitor#_lconst_0(int)
 	 */
 	public void _lconst_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LCONST_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LCONST_0]);
 		writeNewLine();
 	}
 
@@ -2135,11 +1675,8 @@
 	 * @see IBytecodeVisitor#_lconst_1(int)
 	 */
 	public void _lconst_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LCONST_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LCONST_1]);
 		writeNewLine();
 	}
 
@@ -2147,11 +1684,8 @@
 	 * @see IBytecodeVisitor#_ldc_w(int, int, IConstantPoolEntry)
 	 */
 	public void _ldc_w(int pc, int index, IConstantPoolEntry constantPoolEntry) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LDC_W])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LDC_W])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("disassembler.space")); //$NON-NLS-1$
@@ -2164,6 +1698,8 @@
 				break;
 			case IConstantPoolConstant.CONSTANT_String :
 				appendOutputForConstantString(constantPoolEntry);
+			case IConstantPoolConstant.CONSTANT_Class :
+				appendOutputForConstantClass(constantPoolEntry);
 		}
 		writeNewLine();
 	}
@@ -2172,11 +1708,8 @@
 	 * @see IBytecodeVisitor#_ldc(int, int, IConstantPoolEntry)
 	 */
 	public void _ldc(int pc, int index, IConstantPoolEntry constantPoolEntry) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LDC])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LDC])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("disassembler.space")); //$NON-NLS-1$
@@ -2197,11 +1730,8 @@
 	 * @see IBytecodeVisitor#_ldc2_w(int, int, IConstantPoolEntry)
 	 */
 	public void _ldc2_w(int pc, int index, IConstantPoolEntry constantPoolEntry) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LDC2_W])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LDC2_W])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("disassembler.space")); //$NON-NLS-1$
@@ -2219,11 +1749,8 @@
 	 * @see IBytecodeVisitor#_ldiv(int)
 	 */
 	public void _ldiv(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LDIV]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LDIV]);
 		writeNewLine();
 	}
 
@@ -2231,11 +1758,8 @@
 	 * @see IBytecodeVisitor#_lload_0(int)
 	 */
 	public void _lload_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LLOAD_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LLOAD_0]);
 		writeNewLine();
 	}
 
@@ -2243,11 +1767,8 @@
 	 * @see IBytecodeVisitor#_lload_1(int)
 	 */
 	public void _lload_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LLOAD_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LLOAD_1]);
 		writeNewLine();
 	}
 
@@ -2255,11 +1776,8 @@
 	 * @see IBytecodeVisitor#_lload_2(int)
 	 */
 	public void _lload_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LLOAD_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LLOAD_2]);
 		writeNewLine();
 	}
 
@@ -2267,11 +1785,8 @@
 	 * @see IBytecodeVisitor#_lload_3(int)
 	 */
 	public void _lload_3(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LLOAD_3]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LLOAD_3]);
 		writeNewLine();
 	}
 
@@ -2279,11 +1794,8 @@
 	 * @see IBytecodeVisitor#_lload(int, int)
 	 */
 	public void _lload(int pc, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LLOAD])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LLOAD])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index);
 		writeNewLine();
@@ -2293,11 +1805,8 @@
 	 * @see IBytecodeVisitor#_lmul(int)
 	 */
 	public void _lmul(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LMUL]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LMUL]);
 		writeNewLine();
 	}
 
@@ -2305,11 +1814,8 @@
 	 * @see IBytecodeVisitor#_lneg(int)
 	 */
 	public void _lneg(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LNEG]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LNEG]);
 		writeNewLine();
 	}
 
@@ -2317,20 +1823,17 @@
 	 * @see IBytecodeVisitor#_lookupswitch(int, int, int, int[][])
 	 */
 	public void _lookupswitch(int pc, int defaultoffset, int npairs, int[][] offset_pairs) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LOOKUPSWITCH])
-			.append("default:") //$NON-NLS-1$
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LOOKUPSWITCH])
+			.append(" default: ") //$NON-NLS-1$
 			.append(defaultoffset + pc);
 		writeNewLine();
 		for (int i = 0; i < npairs; i++) {
-			writeExtraTabs(1);
+			writeExtraTabs(3);
 			buffer
-				.append("case") //$NON-NLS-1$
+				.append("case ") //$NON-NLS-1$
 				.append(offset_pairs[i][0])
-				.append(":") //$NON-NLS-1$
+				.append(": ") //$NON-NLS-1$
 				.append(offset_pairs[i][1] + pc);
 			writeNewLine();
 		}
@@ -2340,11 +1843,8 @@
 	 * @see IBytecodeVisitor#_lor(int)
 	 */
 	public void _lor(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LOR]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LOR]);
 		writeNewLine();
 	}
 
@@ -2352,11 +1852,8 @@
 	 * @see IBytecodeVisitor#_lrem(int)
 	 */
 	public void _lrem(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LREM]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LREM]);
 		writeNewLine();
 	}
 
@@ -2364,11 +1861,8 @@
 	 * @see IBytecodeVisitor#_lreturn(int)
 	 */
 	public void _lreturn(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LRETURN]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LRETURN]);
 		writeNewLine();
 	}
 
@@ -2376,11 +1870,8 @@
 	 * @see IBytecodeVisitor#_lshl(int)
 	 */
 	public void _lshl(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSHL]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSHL]);
 		writeNewLine();
 	}
 
@@ -2388,11 +1879,8 @@
 	 * @see IBytecodeVisitor#_lshr(int)
 	 */
 	public void _lshr(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSHR]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSHR]);
 		writeNewLine();
 	}
 
@@ -2400,11 +1888,8 @@
 	 * @see IBytecodeVisitor#_lstore_0(int)
 	 */
 	public void _lstore_0(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSTORE_0]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSTORE_0]);
 		writeNewLine();
 	}
 
@@ -2412,11 +1897,8 @@
 	 * @see IBytecodeVisitor#_lstore_1(int)
 	 */
 	public void _lstore_1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSTORE_1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSTORE_1]);
 		writeNewLine();
 	}
 
@@ -2424,11 +1906,8 @@
 	 * @see IBytecodeVisitor#_lstore_2(int)
 	 */
 	public void _lstore_2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSTORE_2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSTORE_2]);
 		writeNewLine();
 	}
 
@@ -2436,11 +1915,8 @@
 	 * @see IBytecodeVisitor#_lstore_3(int)
 	 */
 	public void _lstore_3(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSTORE_3]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSTORE_3]);
 		writeNewLine();
 	}
 
@@ -2448,11 +1924,8 @@
 	 * @see IBytecodeVisitor#_lstore(int, int)
 	 */
 	public void _lstore(int pc, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSTORE])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSTORE])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index);
 		writeNewLine();
@@ -2462,11 +1935,8 @@
 	 * @see IBytecodeVisitor#_lsub(int)
 	 */
 	public void _lsub(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSUB]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LSUB]);
 		writeNewLine();
 	}
 
@@ -2474,11 +1944,8 @@
 	 * @see IBytecodeVisitor#_lushr(int)
 	 */
 	public void _lushr(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LUSHR]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LUSHR]);
 		writeNewLine();
 	}
 
@@ -2486,11 +1953,8 @@
 	 * @see IBytecodeVisitor#_lxor(int)
 	 */
 	public void _lxor(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LXOR]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.LXOR]);
 		writeNewLine();
 	}
 
@@ -2498,11 +1962,8 @@
 	 * @see IBytecodeVisitor#_monitorenter(int)
 	 */
 	public void _monitorenter(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.MONITORENTER]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.MONITORENTER]);
 		writeNewLine();
 	}
 
@@ -2510,11 +1971,8 @@
 	 * @see IBytecodeVisitor#_monitorexit(int)
 	 */
 	public void _monitorexit(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.MONITOREXIT]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.MONITOREXIT]);
 		writeNewLine();
 	}
 
@@ -2526,11 +1984,8 @@
 		int index,
 		int dimensions,
 		IConstantPoolEntry constantClass) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.MULTIANEWARRAY])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.MULTIANEWARRAY])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
@@ -2543,11 +1998,8 @@
 	 * @see IBytecodeVisitor#_new(int, int, IConstantPoolEntry)
 	 */
 	public void _new(int pc, int index, IConstantPoolEntry constantClass) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.NEW])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.NEW])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
@@ -2559,11 +2011,8 @@
 	 * @see IBytecodeVisitor#_newarray(int, int)
 	 */
 	public void _newarray(int pc, int atype) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.NEWARRAY])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.NEWARRAY])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(atype)
 			.append(Util.bind("disassembler.space")); //$NON-NLS-1$
@@ -2575,11 +2024,8 @@
 	 * @see IBytecodeVisitor#_nop(int)
 	 */
 	public void _nop(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.NOP]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.NOP]);
 		writeNewLine();
 	}
 
@@ -2587,11 +2033,8 @@
 	 * @see IBytecodeVisitor#_pop(int)
 	 */
 	public void _pop(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.POP]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.POP]);
 		writeNewLine();
 	}
 
@@ -2599,11 +2042,8 @@
 	 * @see IBytecodeVisitor#_pop2(int)
 	 */
 	public void _pop2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.POP2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.POP2]);
 		writeNewLine();
 	}
 
@@ -2611,11 +2051,8 @@
 	 * @see IBytecodeVisitor#_putfield(int, int, IConstantPoolEntry)
 	 */
 	public void _putfield(int pc, int index, IConstantPoolEntry constantFieldref) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.PUTFIELD])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.PUTFIELD])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("classformat.putfield"))			 //$NON-NLS-1$
@@ -2632,11 +2069,8 @@
 	 * @see IBytecodeVisitor#_putstatic(int, int, IConstantPoolEntry)
 	 */
 	public void _putstatic(int pc, int index, IConstantPoolEntry constantFieldref) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.PUTSTATIC])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.PUTSTATIC])
 			.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
 			.append(index)
 			.append(Util.bind("classformat.putstatic")) //$NON-NLS-1$
@@ -2659,11 +2093,8 @@
 	 * @see IBytecodeVisitor#_ret(int, int)
 	 */
 	public void _ret(int pc, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.RET])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.RET])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(index);
 		writeNewLine();
@@ -2673,11 +2104,8 @@
 	 * @see IBytecodeVisitor#_return(int)
 	 */
 	public void _return(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.RETURN]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.RETURN]);
 		writeNewLine();
 	}
 
@@ -2685,11 +2113,8 @@
 	 * @see IBytecodeVisitor#_saload(int)
 	 */
 	public void _saload(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.SALOAD]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.SALOAD]);
 		writeNewLine();
 	}
 
@@ -2697,11 +2122,8 @@
 	 * @see IBytecodeVisitor#_sastore(int)
 	 */
 	public void _sastore(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.SASTORE]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.SASTORE]);
 		writeNewLine();
 	}
 
@@ -2709,11 +2131,8 @@
 	 * @see IBytecodeVisitor#_sipush(int, short)
 	 */
 	public void _sipush(int pc, short value) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.SIPUSH])
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.SIPUSH])
 			.append(Util.bind("disassembler.space")) //$NON-NLS-1$
 			.append(value);
 		writeNewLine();
@@ -2723,11 +2142,8 @@
 	 * @see IBytecodeVisitor#_swap(int)
 	 */
 	public void _swap(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.SWAP]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.SWAP]);
 		writeNewLine();
 	}
 
@@ -2741,20 +2157,17 @@
 		int high,
 		int[] jump_offsets) {
 
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.TABLESWITCH])
-			.append("default:") //$NON-NLS-1$
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.TABLESWITCH])
+			.append(" default: ") //$NON-NLS-1$
 			.append(defaultoffset + pc);
 		writeNewLine();
 		for (int i = low; i < high + 1; i++) {
-			writeExtraTabs(1);
+			writeExtraTabs(3);
 			buffer
-				.append("case") //$NON-NLS-1$
+				.append("case ") //$NON-NLS-1$
 				.append(i)
-				.append(":") //$NON-NLS-1$
+				.append(": ") //$NON-NLS-1$
 				.append(jump_offsets[i - low] + pc);
 			writeNewLine();
 		}
@@ -2764,11 +2177,8 @@
 	 * @see IBytecodeVisitor#_wide(int, int, int)
 	 */
 	public void _wide(int pc, int iincopcode, int index, int _const) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.WIDE]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.WIDE]);
 		writeNewLine();
 		_iinc(pc + 1, index, _const);
 	}
@@ -2777,11 +2187,8 @@
 	 * @see IBytecodeVisitor#_wide(int, int, int)
 	 */
 	public void _wide(int pc, int opcode, int index) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.WIDE]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.WIDE]);
 		writeNewLine();
 		switch(opcode) {
 			case IOpcodeMnemonics.ILOAD :
@@ -2823,11 +2230,8 @@
 	 * @see IBytecodeVisitor#_breakpoint(int)
 	 */
 	public void _breakpoint(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.BREAKPOINT]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.BREAKPOINT]);
 		writeNewLine();
 	}
 
@@ -2835,11 +2239,8 @@
 	 * @see IBytecodeVisitor#_impdep1(int)
 	 */
 	public void _impdep1(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IMPDEP1]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IMPDEP1]);
 		writeNewLine();
 	}
 
@@ -2847,11 +2248,8 @@
 	 * @see IBytecodeVisitor#_impdep2(int)
 	 */
 	public void _impdep2(int pc) {
-		writeTabs();
-		buffer
-			.append(pc)
-			.append(Util.bind("disassembler.tab")) //$NON-NLS-1$
-			.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IMPDEP2]);
+		dumpPcNumber(pc);
+		buffer.append(OpcodeStringValues.BYTECODE_NAMES[IOpcodeMnemonics.IMPDEP2]);
 		writeNewLine();
 	}
 
@@ -2940,6 +2338,13 @@
 			.append(constantPoolEntry.getFloatValue())
 			.append(">"); //$NON-NLS-1$
 	}
+	
+	private void appendOutputForConstantClass(IConstantPoolEntry constantPoolEntry) {
+		this.buffer
+			.append("<Class ") //$NON-NLS-1$
+			.append(returnConstantClassName(constantPoolEntry))
+			.append(">"); //$NON-NLS-1$
+	}
 
 	private void writeNewLine() {
 		this.buffer.append(lineSeparator);
@@ -2947,13 +2352,13 @@
 
 	private void writeTabs() {
 		for (int i = 0, max = this.tabNumber; i < max; i++) {
-			this.buffer.append(Util.bind("disassembler.tab")); //$NON-NLS-1$
+			this.buffer.append(Util.bind("disassembler.identation")); //$NON-NLS-1$
 		}
 	}	
 
 	private void writeExtraTabs(int extraTabs) {
 		for (int i = 0, max = this.tabNumber + extraTabs; i < max; i++) {
-			this.buffer.append(Util.bind("disassembler.tab")); //$NON-NLS-1$
+			this.buffer.append(Util.bind("disassembler.identation")); //$NON-NLS-1$
 		}
 	}	
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
index af7e0c0..e587fe8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
@@ -41,14 +41,15 @@
 	private static final char[] ANY_EXCEPTION = Util.bind("classfileformat.anyexceptionhandler").toCharArray();	 //$NON-NLS-1$
 	private static final String EMPTY_OUTPUT = ""; //$NON-NLS-1$
 	
-	private void checkSuperFlags(StringBuffer buffer, int accessFlags, String lineSeparator, int tabNumber ) {
-		if ((accessFlags & IModifierConstants.ACC_SUPER) == 0) {
-			writeNewLine(buffer, lineSeparator, tabNumber);
-			buffer
-				.append(Util.bind("disassembler.commentstart")) //$NON-NLS-1$
-				.append(Util.bind("classfileformat.superflagnotset")) //$NON-NLS-1$
-				.append(Util.bind("disassembler.commentend")); //$NON-NLS-1$
+	private void checkSuperFlags(StringBuffer buffer, int accessFlags, String lineSeparator, int tabNumber) {
+		buffer.append(Util.bind("disassembler.commentstart")); //$NON-NLS-1$
+		if ((accessFlags & IModifierConstants.ACC_SUPER) != 0) {
+			buffer.append(Util.bind("classfileformat.superflagisset")); //$NON-NLS-1$
+		} else {
+			buffer.append(Util.bind("classfileformat.superflagisnotset")); //$NON-NLS-1$
 		}
+		buffer.append(Util.bind("disassembler.commentend")); //$NON-NLS-1$
+		writeNewLine(buffer, lineSeparator, tabNumber);
 	}
 
 	private void decodeModifiersForField(StringBuffer buffer, int accessFlags) {
@@ -408,6 +409,8 @@
 				buffer.append(Util.bind("classfileformat.targetoption", "1.3"));//$NON-NLS-1$//$NON-NLS-2$
 			} else if (minorVersion == 0 && majorVersion == 48) {
 				buffer.append(Util.bind("classfileformat.targetoption", "1.4"));//$NON-NLS-1$//$NON-NLS-2$
+			} else if (minorVersion == 0 && majorVersion == 49) {
+				buffer.append(Util.bind("classfileformat.targetoption", "1.5"));//$NON-NLS-1$//$NON-NLS-2$
 			}
 			writeNewLine(buffer, lineSeparator, 0);
 			buffer.append(Util.bind("disassembler.begincommentline"));			 //$NON-NLS-1$
@@ -484,6 +487,7 @@
 			buffer.append(superinterface);
 		}
 		buffer.append(Util.bind("disassembler.opentypedeclaration")); //$NON-NLS-1$
+		writeNewLine(buffer, lineSeparator, 1);
 		checkSuperFlags(buffer, classFileReader.getAccessFlags(), lineSeparator, 1);
 		disassembleTypeMembers(classFileReader, buffer, lineSeparator, 1, mode);
 		if (mode == ClassFileBytesDisassembler.DETAILED) {
@@ -651,10 +655,10 @@
 							buffer.append(constantPoolEntry.getIntegerValue() == 1 ? "true" : "false");//$NON-NLS-1$//$NON-NLS-2$
 							break;
 						case 'B' :
-							buffer.append((byte) constantPoolEntry.getIntegerValue());
+							buffer.append(constantPoolEntry.getIntegerValue());
 							break;
 						case 'S' :
-							buffer.append((short) constantPoolEntry.getIntegerValue());
+							buffer.append(constantPoolEntry.getIntegerValue());
 							break;
 						case 'I' :
 							buffer.append(constantPoolEntry.getIntegerValue());
@@ -695,11 +699,22 @@
 	 */
 	private void disassemble(IClassFileReader classFileReader, IMethodInfo methodInfo, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
 		ICodeAttribute codeAttribute = methodInfo.getCodeAttribute();
-		
+		writeNewLine(buffer, lineSeparator, tabNumber);
+		char[] methodDescriptor = methodInfo.getDescriptor();
+		if (mode == ClassFileBytesDisassembler.DETAILED) {
+			CharOperation.replace(methodDescriptor, '.', '/');
+			buffer
+				.append(Util.bind("disassembler.commentstart")) //$NON-NLS-1$
+				.append(Util.bind("classfileformat.methoddescriptor")) //$NON-NLS-1$
+				.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
+				.append(methodInfo.getDescriptorIndex())
+				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
+				.append(methodDescriptor)
+				.append(Util.bind("disassembler.commentend")); //$NON-NLS-1$
+		}		
 		writeNewLine(buffer, lineSeparator, tabNumber);
 		int accessFlags = methodInfo.getAccessFlags();
 		decodeModifiersForMethod(buffer, accessFlags);
-		char[] methodDescriptor = methodInfo.getDescriptor();
 		CharOperation.replace(methodDescriptor, '/', '.');
 		char[] methodName = null;
 		if (methodInfo.isConstructor()) {
@@ -727,22 +742,9 @@
 			char[] exceptionName = exceptionNames[length - 1];
 			CharOperation.replace(exceptionName, '/', '.');
 			buffer.append(exceptionName);
-			buffer.append(Util.bind("disassembler.space")); //$NON-NLS-1$
 		}
 		buffer.append(Util.bind("disassembler.endofmethodheader")); //$NON-NLS-1$
-		writeNewLine(buffer, lineSeparator, tabNumber);
-		if (mode == ClassFileBytesDisassembler.DETAILED) {
-			CharOperation.replace(methodDescriptor, '.', '/');
-			buffer
-				.append(Util.bind("disassembler.commentstart")) //$NON-NLS-1$
-				.append(Util.bind("classfileformat.methoddescriptor")) //$NON-NLS-1$
-				.append(Util.bind("disassembler.constantpoolindex")) //$NON-NLS-1$
-				.append(methodInfo.getDescriptorIndex())
-				.append(Util.bind("disassembler.space")) //$NON-NLS-1$
-				.append(methodDescriptor)
-				.append(Util.bind("disassembler.commentend")); //$NON-NLS-1$
-			writeNewLine(buffer, lineSeparator, tabNumber);
-		}
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
 		IClassFileAttribute[] attributes = methodInfo.getAttributes();
 		int length = attributes.length;
 		if (length != 0) {
@@ -772,8 +774,6 @@
 	}
 	
 	private void disassemble(ICodeAttribute codeAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
-		buffer.append(Util.bind("disassembler.codeattributeheader")); //$NON-NLS-1$
-		writeNewLine(buffer, lineSeparator, tabNumber + 1);
 		buffer
 			.append(Util.bind("disassembler.commentstart")) //$NON-NLS-1$
 			.append(Util.bind("classfileformat.maxStack")) //$NON-NLS-1$
@@ -782,11 +782,16 @@
 			.append(Util.bind("classfileformat.maxLocals")) //$NON-NLS-1$
 			.append(codeAttribute.getMaxLocals())
 			.append(Util.bind("disassembler.commentend")); //$NON-NLS-1$
+		writeNewLine(buffer, lineSeparator, tabNumber + 1);
+		buffer.append(Util.bind("disassembler.codeattributeheader")); //$NON-NLS-1$
 		writeNewLine(buffer, lineSeparator, tabNumber - 1);
-		DefaultBytecodeVisitor visitor = new DefaultBytecodeVisitor(buffer, lineSeparator, tabNumber);
+		DefaultBytecodeVisitor visitor = new DefaultBytecodeVisitor(codeAttribute.getCodeLength(), buffer, lineSeparator, tabNumber + 1);
 		try {
 			codeAttribute.traverse(visitor);
 		} catch(ClassFormatException e) {
+			dumpTab(tabNumber + 2, buffer);
+			buffer.append("Class format Exception");//$NON-NLS-1$
+			writeNewLine(buffer, lineSeparator, tabNumber + 1);
 		}
 		int exceptionTableLength = codeAttribute.getExceptionTableLength();
 		if (exceptionTableLength != 0) {
@@ -879,7 +884,6 @@
 	}
 	
 	private void disassembleTypeMembers(IClassFileReader classFileReader, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
-		writeNewLine(buffer, lineSeparator, tabNumber);
 		IFieldInfo[] fields = classFileReader.getFieldInfos();
 		for (int i = 0, max = fields.length; i < max; i++) {
 			disassemble(fields[i], buffer, lineSeparator, tabNumber, mode);
@@ -892,7 +896,7 @@
 	
 	private final void dumpTab(int tabNumber, StringBuffer buffer) {
 		for (int i = 0; i < tabNumber; i++) {
-			buffer.append(Util.bind("disassembler.tab")); //$NON-NLS-1$
+			buffer.append(Util.bind("disassembler.identation")); //$NON-NLS-1$
 		}
 	} 
 	
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ElementInfoConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ElementInfoConverter.java
new file mode 100644
index 0000000..62b36eb
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ElementInfoConverter.java
@@ -0,0 +1,482 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.util;
+
+/**
+ * Converter from element info to parsed compilation unit.
+ *
+ */
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.env.*;
+import org.eclipse.jdt.internal.compiler.env.ISourceField;
+import org.eclipse.jdt.internal.compiler.env.ISourceImport;
+import org.eclipse.jdt.internal.compiler.env.ISourceMethod;
+import org.eclipse.jdt.internal.compiler.env.ISourceType;
+
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.SourceFieldElementInfo;
+import org.eclipse.jdt.internal.core.SourceMethodElementInfo;
+
+public class ElementInfoConverter implements CompilerModifiers {
+
+	/*
+	 * Convert a set of source type infos into a parsed compilation unit declaration
+	 * The argument types are then all grouped in the same unit. The argument types must 
+	 * at least contain one type.
+	 * Can optionally add local and anonymous types
+	 */
+	public static CompilationUnitDeclaration buildCompilationUnit(
+		SourceTypeElementInfo[] sourceTypes,
+		boolean needLocalTypes,
+		ProblemReporter problemReporter,
+		CompilationResult compilationResult) {
+
+		return 
+			new ElementInfoConverter(needLocalTypes, problemReporter).convert(
+				sourceTypes, 
+				compilationResult);
+	}
+	
+	private boolean needLocalTypes; // local and anoymous types
+	private ProblemReporter problemReporter;
+	private CompilationUnitDeclaration unit;
+	
+	private ElementInfoConverter(boolean needLocalTypes, ProblemReporter problemReporter) {
+		this.needLocalTypes = needLocalTypes;
+		this.problemReporter = problemReporter;
+	}
+	
+	/*
+	 * Convert an initializerinfo into a parsed initializer declaration
+	 */
+	private Initializer convert(InitializerElementInfo initializerInfo, CompilationResult compilationResult) {
+
+		Block block = new Block(0);
+		Initializer initializer = new Initializer(block, IConstants.AccDefault);
+
+		int start = initializerInfo.getDeclarationSourceStart();
+		int end = initializerInfo.getDeclarationSourceEnd();
+
+		initializer.name = initializerInfo.getName();
+		initializer.sourceStart = initializer.declarationSourceStart = start;
+		initializer.sourceEnd = initializer.declarationSourceEnd = end;
+		initializer.modifiers = initializerInfo.getModifiers();
+
+		/* convert local and anonymous types */
+		IJavaElement[] children = initializerInfo.getChildren();
+		int typesLength = children.length;
+		if (typesLength > 0) {
+			Statement[] statements = new Statement[typesLength];
+			for (int i = 0; i < typesLength; i++) {
+				JavaElement type = (JavaElement)children[i];
+				try {
+					TypeDeclaration localType = convert((SourceTypeElementInfo)type.getElementInfo(), compilationResult);
+					if ((localType.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+						QualifiedAllocationExpression expression = new QualifiedAllocationExpression(localType);
+						expression.type = localType.superclass;
+						localType.superclass = null;
+						localType.superInterfaces = null;
+						localType.allocation = expression;
+						statements[i] = expression;
+					} else {
+						statements[i] = localType;
+					}
+				} catch (JavaModelException e) {
+					// ignore
+				}
+			}
+			block.statements = statements;
+		}
+		
+		return initializer;
+	}
+
+	/*
+	 * Convert a source field info into a parsed field declaration
+	 */
+	private FieldDeclaration convert(SourceFieldElementInfo sourceField, CompilationResult compilationResult) {
+
+		FieldDeclaration field = new FieldDeclaration();
+
+		int start = sourceField.getNameSourceStart();
+		int end = sourceField.getNameSourceEnd();
+
+		field.name = sourceField.getName();
+		field.sourceStart = start;
+		field.sourceEnd = end;
+		field.type = createTypeReference(sourceField.getTypeName(), start, end);
+		field.declarationSourceStart = sourceField.getDeclarationSourceStart();
+		field.declarationSourceEnd = sourceField.getDeclarationSourceEnd();
+		field.modifiers = sourceField.getModifiers();
+
+		/* convert local and anonymous types */
+		if (this.needLocalTypes) {
+			IJavaElement[] children = sourceField.getChildren();
+			int typesLength = children.length;
+			if (typesLength > 0) {
+				ArrayInitializer initializer = new ArrayInitializer();
+				field.initialization = initializer;
+				Expression[] expressions = new Expression[typesLength];
+				initializer.expressions = expressions;
+				for (int i = 0; i < typesLength; i++) {
+					IJavaElement localType = children[i];
+					try {
+						TypeDeclaration anonymousLocalTypeDeclaration = convert((SourceTypeElementInfo)((JavaElement)localType).getElementInfo(),compilationResult);
+						QualifiedAllocationExpression expression = new QualifiedAllocationExpression(anonymousLocalTypeDeclaration);
+						expression.type = anonymousLocalTypeDeclaration.superclass;
+						anonymousLocalTypeDeclaration.superclass = null;
+						anonymousLocalTypeDeclaration.superInterfaces = null;
+						anonymousLocalTypeDeclaration.allocation = expression;
+						expressions[i] = expression;
+					} catch (JavaModelException e) {
+						// ignore
+					}
+				}
+			}
+		}
+		
+		return field;
+	}
+
+	/*
+	 * Convert a source method info into a parsed method/constructor declaration 
+	 */
+	private AbstractMethodDeclaration convert(SourceMethodElementInfo sourceMethod, CompilationResult compilationResult) {
+
+		AbstractMethodDeclaration method;
+
+		/* only source positions available */
+		int start = sourceMethod.getNameSourceStart();
+		int end = sourceMethod.getNameSourceEnd();
+
+		if (sourceMethod.isConstructor()) {
+			ConstructorDeclaration decl = new ConstructorDeclaration(compilationResult);
+			decl.isDefaultConstructor = false;
+			method = decl;
+		} else {
+			MethodDeclaration decl = new MethodDeclaration(compilationResult);
+			/* convert return type */
+			decl.returnType =
+				createTypeReference(sourceMethod.getReturnTypeName(), start, end);
+			method = decl;
+		}
+		method.selector = sourceMethod.getSelector();
+		method.modifiers = sourceMethod.getModifiers();
+		method.sourceStart = start;
+		method.sourceEnd = end;
+		method.declarationSourceStart = sourceMethod.getDeclarationSourceStart();
+		method.declarationSourceEnd = sourceMethod.getDeclarationSourceEnd();
+
+		/* convert arguments */
+		char[][] argumentTypeNames = sourceMethod.getArgumentTypeNames();
+		char[][] argumentNames = sourceMethod.getArgumentNames();
+		int argumentCount = argumentTypeNames == null ? 0 : argumentTypeNames.length;
+		long position = (long) start << 32 + end;
+		method.arguments = new Argument[argumentCount];
+		for (int i = 0; i < argumentCount; i++) {
+			method.arguments[i] =
+				new Argument(
+					argumentNames[i],
+					position,
+					createTypeReference(argumentTypeNames[i], start, end),
+					AccDefault);
+			// do not care whether was final or not
+		}
+
+		/* convert thrown exceptions */
+		char[][] exceptionTypeNames = sourceMethod.getExceptionTypeNames();
+		int exceptionCount = exceptionTypeNames == null ? 0 : exceptionTypeNames.length;
+		method.thrownExceptions = new TypeReference[exceptionCount];
+		for (int i = 0; i < exceptionCount; i++) {
+			method.thrownExceptions[i] =
+				createTypeReference(exceptionTypeNames[i], start, end);
+		}
+		
+		/* convert local and anonymous types */
+		if (this.needLocalTypes) {
+			IJavaElement[] children = sourceMethod.getChildren();
+			int typesLength = children.length;
+			if (typesLength != 0) {
+				Statement[] statements = new Statement[typesLength];
+				for (int i = 0; i < typesLength; i++) {
+					JavaElement type = (JavaElement)children[i];
+					try {
+						TypeDeclaration localType = convert((SourceTypeElementInfo)type.getElementInfo(), compilationResult);
+						if ((localType.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+							QualifiedAllocationExpression expression = new QualifiedAllocationExpression(localType);
+							expression.type = localType.superclass;
+							localType.superclass = null;
+							localType.superInterfaces = null;
+							localType.allocation = expression;
+							statements[i] = expression;
+						} else {
+							statements[i] = localType;
+						}
+					} catch (JavaModelException e) {
+						// ignore
+					}
+				}
+				method.statements = statements;
+			}
+		}
+		
+		return method;
+	}
+
+	/*
+	 * Convert a source type info into a parsed type declaration
+	 */
+	private TypeDeclaration convert(SourceTypeElementInfo sourceType, CompilationResult compilationResult) {
+		
+		/* create type declaration - can be member type, local type or anonymous type */
+		TypeDeclaration type = new TypeDeclaration(compilationResult);
+		if (sourceType.getEnclosingType() == null) {
+			IType typeHandle = sourceType.getHandle();
+			try {
+				if (typeHandle.isAnonymous()) {
+					type.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+					type.bits |= ASTNode.AnonymousAndLocalMask;
+				} else {
+					if (typeHandle.isLocal()) {
+						type.bits |= ASTNode.IsLocalTypeMASK;
+					}
+				}
+			} catch (JavaModelException e) {
+				// could not figure, assume toplevel
+			}
+		}  else {
+			type.bits |= ASTNode.IsMemberTypeMASK;
+		}
+		if ((type.bits & ASTNode.IsAnonymousTypeMASK) == 0) {
+			type.name = sourceType.getName();
+		}
+		int start, end; // only positions available
+		type.sourceStart = start = sourceType.getNameSourceStart();
+		type.sourceEnd = end = sourceType.getNameSourceEnd();
+		type.modifiers = sourceType.getModifiers();
+		type.declarationSourceStart = sourceType.getDeclarationSourceStart();
+		type.declarationSourceEnd = sourceType.getDeclarationSourceEnd();
+		type.bodyEnd = type.declarationSourceEnd;
+
+		/* set superclass and superinterfaces */
+		if (sourceType.getSuperclassName() != null)
+			type.superclass =
+				createTypeReference(sourceType.getSuperclassName(), start, end);
+		char[][] interfaceNames = sourceType.getInterfaceNames();
+		int interfaceCount = interfaceNames == null ? 0 : interfaceNames.length;
+		type.superInterfaces = new TypeReference[interfaceCount];
+		for (int i = 0; i < interfaceCount; i++) {
+			type.superInterfaces[i] = createTypeReference(interfaceNames[i], start, end);
+		}
+		
+		/* convert member types */
+		ISourceType[] sourceMemberTypes = sourceType.getMemberTypes();
+		int sourceMemberTypeCount =
+			sourceMemberTypes == null ? 0 : sourceMemberTypes.length;
+		type.memberTypes = new TypeDeclaration[sourceMemberTypeCount];
+		for (int i = 0; i < sourceMemberTypeCount; i++) {
+			type.memberTypes[i] = convert((SourceTypeElementInfo)sourceMemberTypes[i], compilationResult);
+		}
+		
+		/* convert fields and initializers */
+		ISourceField[] sourceFields = sourceType.getFields();
+		int sourceFieldCount = sourceFields == null ? 0 : sourceFields.length;
+		InitializerElementInfo[] initializers = null;
+		int initializerCount = 0;
+		if (this.needLocalTypes) {
+			initializers = sourceType.getInitializers();
+			initializerCount = initializers.length;
+			type.fields = new FieldDeclaration[initializerCount + sourceFieldCount];
+			for (int i = 0; i < initializerCount; i++) {
+				type.fields[i] = convert(initializers[i], compilationResult);
+			}
+		} else {
+			type.fields = new FieldDeclaration[sourceFieldCount];
+		}
+		int length = initializerCount + sourceFieldCount;
+		int index = 0;
+		for (int i = initializerCount; i < length; i++) {
+			type.fields[i] = convert((SourceFieldElementInfo)sourceFields[index++], compilationResult);
+		}
+
+		/* convert methods - need to add default constructor if necessary */
+		ISourceMethod[] sourceMethods = sourceType.getMethods();
+		int sourceMethodCount = sourceMethods == null ? 0 : sourceMethods.length;
+
+		/* source type has a constructor ?           */
+		/* by default, we assume that one is needed. */
+		int neededCount = 0;
+		if (!type.isInterface()) {
+			neededCount = 1;
+			for (int i = 0; i < sourceMethodCount; i++) {
+				if (sourceMethods[i].isConstructor()) {
+					neededCount = 0;
+					// Does not need the extra constructor since one constructor already exists.
+					break;
+				}
+			}
+		}
+		type.methods = new AbstractMethodDeclaration[sourceMethodCount + neededCount];
+		if (neededCount != 0) { // add default constructor in first position
+			type.methods[0] = type.createsInternalConstructor(false, false);
+		}
+		boolean isInterface = type.isInterface();
+		for (int i = 0; i < sourceMethodCount; i++) {
+			AbstractMethodDeclaration method =convert((SourceMethodElementInfo)sourceMethods[i], compilationResult);
+			if (isInterface || method.isAbstract()) { // fix-up flag 
+				method.modifiers |= AccSemicolonBody;
+			}
+			type.methods[neededCount + i] = method;
+		}
+
+		return type;
+	}
+
+	/*
+	 * Convert a set of source element types into a parsed compilation unit declaration
+	 * The argument types are then all grouped in the same unit. The argument types must 
+	 * at least contain one type.
+	 */
+	private CompilationUnitDeclaration convert(SourceTypeElementInfo[] sourceTypes, CompilationResult compilationResult) {
+		
+		SourceTypeElementInfo sourceType = sourceTypes[0];
+		if (sourceType.getName() == null)
+			return null; // do a basic test that the sourceType is valid
+
+		this.unit = new CompilationUnitDeclaration(this.problemReporter, compilationResult, 0);
+		// not filled at this point
+
+		/* only positions available */
+		int start = sourceType.getNameSourceStart();
+		int end = sourceType.getNameSourceEnd();
+
+		/* convert package and imports */
+		if (sourceType.getPackageName() != null
+			&& sourceType.getPackageName().length > 0)
+			// if its null then it is defined in the default package
+			this.unit.currentPackage =
+				createImportReference(sourceType.getPackageName(), start, end, false, AccDefault);
+		ISourceImport[]  sourceImports = sourceType.getImports();
+		int importCount = sourceImports == null ? 0 : sourceImports.length;
+		this.unit.imports = new ImportReference[importCount];
+		for (int i = 0; i < importCount; i++) {
+			ISourceImport sourceImport = sourceImports[i];
+			this.unit.imports[i] = createImportReference(
+				sourceImport.getName(), 
+				sourceImport.getDeclarationSourceStart(),
+				sourceImport.getDeclarationSourceEnd(),
+				sourceImport.onDemand(),
+				sourceImport.getModifiers());
+		}
+		/* convert type(s) */
+		int typeCount = sourceTypes.length;
+		this.unit.types = new TypeDeclaration[typeCount];
+		for (int i = 0; i < typeCount; i++) {
+			this.unit.types[i] = convert(sourceTypes[i], compilationResult);
+		}
+		return this.unit;
+	}
+
+	/*
+	 * Build an import reference from an import name, e.g. java.lang.*
+	 */
+	private ImportReference createImportReference(
+		char[] importName,
+		int start,
+		int end, 
+		boolean onDemand,
+		int modifiers) {
+	
+		char[][] qImportName = CharOperation.splitOn('.', importName);
+		long[] positions = new long[qImportName.length];
+		long position = (long) start << 32 + end;
+		for (int i = 0; i < qImportName.length; i++) {
+			positions[i] = position; // dummy positions
+		}
+		return new ImportReference(
+			qImportName,
+			positions,
+			onDemand,
+			modifiers);
+	}
+
+	/*
+	 * Build a type reference from a readable name, e.g. java.lang.Object[][]
+	 */
+	private TypeReference createTypeReference(
+		char[] typeSignature,
+		int start,
+		int end) {
+
+		/* count identifiers and dimensions */
+		int max = typeSignature.length;
+		int dimStart = max;
+		int dim = 0;
+		int identCount = 1;
+		for (int i = 0; i < max; i++) {
+			switch (typeSignature[i]) {
+				case '[' :
+					if (dim == 0)
+						dimStart = i;
+					dim++;
+					break;
+				case '.' :
+					identCount++;
+					break;
+			}
+		}
+		/* rebuild identifiers and dimensions */
+		if (identCount == 1) { // simple type reference
+			if (dim == 0) {
+				return new SingleTypeReference(typeSignature, (((long) start )<< 32) + end);
+			} else {
+				char[] identifier = new char[dimStart];
+				System.arraycopy(typeSignature, 0, identifier, 0, dimStart);
+				return new ArrayTypeReference(identifier, dim, (((long) start) << 32) + end);
+			}
+		} else { // qualified type reference
+			long[] positions = new long[identCount];
+			long pos = (((long) start) << 32) + end;
+			for (int i = 0; i < identCount; i++) {
+				positions[i] = pos;
+			}
+			char[][] identifiers =
+				CharOperation.splitOn('.', typeSignature, 0, dimStart);
+			if (dim == 0) {
+				return new QualifiedTypeReference(identifiers, positions);
+			} else {
+				return new ArrayQualifiedTypeReference(identifiers, dim, positions);
+			}
+		}
+	}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
new file mode 100644
index 0000000..ac570e0
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
@@ -0,0 +1,622 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+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.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.JavaElement;
+import org.eclipse.jdt.internal.core.JavaModel;
+import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.Openable;
+import org.eclipse.jdt.internal.core.PackageFragmentRoot;
+import org.eclipse.jdt.internal.core.util.Util;
+
+/**
+ * Creates java element handles.
+ */
+public class HandleFactory {
+
+	/**
+	 * Cache package fragment root information to optimize speed performance.
+	 */
+	private String lastPkgFragmentRootPath;
+	private IPackageFragmentRoot lastPkgFragmentRoot;
+
+	/**
+	 * Cache package handles to optimize memory.
+	 */
+	private Map packageHandles;
+
+	private JavaModel javaModel;
+
+	public HandleFactory() {
+		this.javaModel = JavaModelManager.getJavaModelManager().getJavaModel();
+	}
+	
+	/**
+	 * Creates an Openable handle from the given resource path.
+	 * The resource path can be a path to a file in the workbench (eg. /Proj/com/ibm/jdt/core/HandleFactory.java)
+	 * or a path to a file in a jar file - it then contains the path to the jar file and the path to the file in the jar
+	 * (eg. c:/jdk1.2.2/jre/lib/rt.jar|java/lang/Object.class or /Proj/rt.jar|java/lang/Object.class)
+	 * NOTE: This assumes that the resource path is the toString() of an IPath, 
+	 *       in other words, it uses the IPath.SEPARATOR for file path
+	 *            and it uses '/' for entries in a zip file.
+	 * If not null, uses the given scope as a hint for getting Java project handles.
+	 */
+	public Openable createOpenable(String resourcePath, IJavaSearchScope scope) {
+		int separatorIndex;
+		if ((separatorIndex= resourcePath.indexOf(IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR)) > -1) {
+			// path to a class file inside a jar
+			String jarPath= resourcePath.substring(0, separatorIndex);
+			// Optimization: cache package fragment root handle and package handles
+			if (!jarPath.equals(this.lastPkgFragmentRootPath)) {
+				IPackageFragmentRoot root= this.getJarPkgFragmentRoot(jarPath, scope);
+				if (root == null)
+					return null; // match is outside classpath
+				this.lastPkgFragmentRootPath= jarPath;
+				this.lastPkgFragmentRoot= root;
+				this.packageHandles= new HashMap(5);
+			}
+			// create handle
+			String classFilePath= resourcePath.substring(separatorIndex + 1);
+			int lastSlash= classFilePath.lastIndexOf('/');
+			String packageName= lastSlash > -1 ? classFilePath.substring(0, lastSlash).replace('/', '.') : IPackageFragment.DEFAULT_PACKAGE_NAME;
+			IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(packageName);
+			if (pkgFragment == null) {
+				pkgFragment= this.lastPkgFragmentRoot.getPackageFragment(packageName);
+				this.packageHandles.put(packageName, pkgFragment);
+			}
+			IClassFile classFile= pkgFragment.getClassFile(classFilePath.substring(lastSlash + 1));
+			return (Openable) classFile;
+		} else {
+			// path to a file in a directory
+			// Optimization: cache package fragment root handle and package handles
+			int length = -1;
+			if (this.lastPkgFragmentRootPath == null 
+				|| !(resourcePath.startsWith(this.lastPkgFragmentRootPath) 
+					&& (length = this.lastPkgFragmentRootPath.length()) > 0
+					&& resourcePath.charAt(length) == '/')) {
+				IPackageFragmentRoot root= this.getPkgFragmentRoot(resourcePath);
+				if (root == null)
+					return null; // match is outside classpath
+				this.lastPkgFragmentRoot= root;
+				this.lastPkgFragmentRootPath= this.lastPkgFragmentRoot.getPath().toString();
+				this.packageHandles= new HashMap(5);
+			}
+			// create handle
+			int lastSlash= resourcePath.lastIndexOf(IPath.SEPARATOR);
+			String packageName= lastSlash > (length= this.lastPkgFragmentRootPath.length()) ? resourcePath.substring(length + 1, lastSlash).replace(IPath.SEPARATOR, '.') : IPackageFragment.DEFAULT_PACKAGE_NAME;
+			IPackageFragment pkgFragment= (IPackageFragment) this.packageHandles.get(packageName);
+			if (pkgFragment == null) {
+				pkgFragment= this.lastPkgFragmentRoot.getPackageFragment(packageName);
+				this.packageHandles.put(packageName, pkgFragment);
+			}
+			String simpleName= resourcePath.substring(lastSlash + 1);
+			if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(simpleName)) {
+				ICompilationUnit unit= pkgFragment.getCompilationUnit(simpleName);
+				return (Openable) unit;
+			} else {
+				IClassFile classFile= pkgFragment.getClassFile(simpleName);
+				return (Openable) classFile;
+			}
+		}
+	}
+	
+	/*
+	 * Returns an element handle corresponding to the given ASTNode in the given parsed unit.
+	 * Returns null if the given ASTNode could not be found.
+	 */
+	public IJavaElement createElement(final ASTNode toBeFound, CompilationUnitDeclaration parsedUnit, Openable openable) {
+		class EndVisit extends RuntimeException {
+			// marker to stop traversing ast
+		}
+		class Visitor extends ASTVisitor {
+		    ASTNode[] nodeStack = new ASTNode[10];
+		    int nodeIndex = -1;
+			
+		    public void push(ASTNode node) {
+		        try {
+		            this.nodeStack[++this.nodeIndex] = node;
+		        } catch (IndexOutOfBoundsException e) {
+		            System.arraycopy(this.nodeStack, 0, this.nodeStack = new ASTNode[this.nodeStack.length*2], 0, this.nodeIndex-1);
+		            this.nodeStack[this.nodeIndex] = node;
+		        }
+		    }
+		    
+		    public void pop(ASTNode node) {
+		    	while (this.nodeIndex >= 0 && this.nodeStack[this.nodeIndex--] != node);
+		    }
+		    
+			public boolean visit(Argument node, BlockScope scope) {
+			    push(node);
+				if (node == toBeFound) throw new EndVisit();
+				return true;
+			}
+			public void endVisit(Argument node, BlockScope scope) {
+			    pop(node);
+            }
+
+			public boolean visit(ConstructorDeclaration node, ClassScope scope) {
+			    push(node);
+				if (node == toBeFound) throw new EndVisit();
+				return true;
+			}
+			public void endVisit(ConstructorDeclaration node, ClassScope scope) {
+				pop(node);
+			}
+
+			public boolean visit(FieldDeclaration node, MethodScope scope) {
+			    push(node);
+				if (node == toBeFound) throw new EndVisit();
+				return true;
+			}
+			public void endVisit(FieldDeclaration node, MethodScope scope) {
+			    pop(node);
+			}
+
+			public boolean visit(Initializer node, MethodScope scope) {
+			    push(node);
+				if (node == toBeFound) throw new EndVisit();
+				return true;
+			}
+			// don't pop initializers (used to count how many occurrences are in the type)
+
+			public boolean visit(LocalDeclaration node, BlockScope scope) {
+			    push(node);
+				if (node == toBeFound) throw new EndVisit();
+				return true;
+			}
+			public void endVisit(LocalDeclaration node, BlockScope scope) {
+			    pop(node);
+            }
+
+			public boolean visit(TypeDeclaration node, BlockScope scope) {
+			    push(node);
+				if (node == toBeFound) throw new EndVisit();
+				return true;
+			}
+			public void endVisit(TypeDeclaration node, BlockScope scope) {
+				if ((node.bits & ASTNode.IsMemberTypeMASK) != 0) {
+				    pop(node);
+				}
+				// don't pop local/anonymous types (used to count how many occurrences are in the method)
+			}
+
+			public boolean visit(TypeDeclaration node, ClassScope scope) {
+			    push(node);
+				if (node == toBeFound) throw new EndVisit();
+				return true;
+			}
+			public void endVisit(TypeDeclaration node, ClassScope scope) {
+				if ((node.bits & ASTNode.IsMemberTypeMASK) != 0) {
+				    pop(node);
+				}
+				// don't pop local/anonymous types (used to count how many occurrences are in the initializer)
+			}
+
+			public boolean visit(MethodDeclaration node, ClassScope scope) {
+			    push(node);
+				if (node == toBeFound) throw new EndVisit();
+				return true;
+			}
+			public void endVisit(MethodDeclaration node, ClassScope scope) {
+				pop(node);
+			}
+
+			public boolean visit(TypeDeclaration node, CompilationUnitScope scope) {
+			    push(node);
+				if (node == toBeFound) throw new EndVisit();
+				return true;
+			}
+			public void endVisit(TypeDeclaration node, CompilationUnitScope scope) {
+				pop(node);
+			}
+
+		}
+		Visitor visitor = new Visitor();
+		try {
+			parsedUnit.traverse(visitor, parsedUnit.scope);
+		} catch (EndVisit e) {
+		    ASTNode[] nodeStack = visitor.nodeStack;
+		    int end = visitor.nodeIndex;
+		    int start = 0;
+		    
+		    // find the inner most type declaration if binary type
+		    ASTNode typeDecl = null;
+		    if (openable instanceof ClassFile) {
+				for (int i = end; i >= 0; i--) {
+				    if (nodeStack[i] instanceof TypeDeclaration) {
+				        typeDecl = nodeStack[i];
+				        start = i;
+				        break;
+				    }
+				}
+		    }
+			
+			// find the openable corresponding to this type declaration
+			if (typeDecl != null) {
+			    openable = getOpenable(typeDecl, openable);
+			}
+			
+			return createElement(nodeStack, start, end, openable);
+		}
+		return null;
+	}
+	private IJavaElement createElement(ASTNode[] nodeStack, int start, int end, IJavaElement parent) {
+		if (start > end) return parent;
+        ASTNode node = nodeStack[start];
+        IJavaElement element = parent;
+		switch(parent.getElementType()) {
+	        case IJavaElement.COMPILATION_UNIT:
+	            String typeName = new String(((TypeDeclaration)node).name);
+	        	element = ((ICompilationUnit)parent).getType(typeName);
+	        	break;
+	        case IJavaElement.CLASS_FILE:
+	            try {
+                    element = ((IClassFile)parent).getType();
+                } catch (JavaModelException e) {
+					// class file doesn't exist: ignore
+                }
+                break;
+            case IJavaElement.TYPE:
+                IType type = (IType)parent;
+                if (node instanceof ConstructorDeclaration) {
+	 				element = type.getMethod(
+						parent.getElementName(), 
+						Util.typeParameterSignatures((ConstructorDeclaration)node));
+				} else if (node instanceof MethodDeclaration) {
+				    MethodDeclaration method = (MethodDeclaration)node;
+					element = type.getMethod(
+						new String(method.selector), 
+						Util.typeParameterSignatures(method));
+				} else if (node instanceof Initializer) {
+				    int occurrenceCount = 1;
+				    while (start < end) {
+				        if (nodeStack[start+1] instanceof Initializer) {
+				            start++;
+				        	occurrenceCount++;
+				    	} else {
+				            break;
+				    	}
+				    }
+				    element = type.getInitializer(occurrenceCount);
+                } else if (node instanceof FieldDeclaration) {
+                    String fieldName = new String(((FieldDeclaration)node).name);
+                    element = type.getField(fieldName);
+                } else if (node instanceof TypeDeclaration) {
+					typeName = new String(((TypeDeclaration)node).name);
+                    element = type.getType(typeName);
+                }
+                break;
+			case IJavaElement.FIELD:
+			    IField field = (IField)parent;
+			    if (field.isBinary()) {
+			        return null;
+			    } else {
+					// child of a field can only be anonymous type
+					element = field.getType("", 1); //$NON-NLS-1$
+			    }
+				break;
+			case IJavaElement.METHOD:
+			case IJavaElement.INITIALIZER:
+				IMember member = (IMember)parent;
+				if (node instanceof TypeDeclaration) {
+				    if (member.isBinary()) {
+				        return null;
+				    } else {
+					    int typeIndex = start;
+					    while (typeIndex <= end) {
+					        ASTNode typeDecl = nodeStack[typeIndex+1];
+					        if (typeDecl instanceof TypeDeclaration && (typeDecl.bits & ASTNode.AnonymousAndLocalMask) != 0) {
+					            typeIndex++;
+					    	} else {
+					            break;
+					    	}
+					    }
+					    char[] name = ((TypeDeclaration)nodeStack[typeIndex]).name;
+					    int occurrenceCount = 1;
+						for (int i = start; i < typeIndex; i++) {
+						    if (CharOperation.equals(name, ((TypeDeclaration)nodeStack[i]).name)) {
+						        occurrenceCount++;
+						    }
+						}
+						start = typeIndex;
+						typeName = (node.bits & ASTNode.IsAnonymousTypeMASK) != 0 ? "" : new String(name); //$NON-NLS-1$
+						element = member.getType(typeName, occurrenceCount);
+				    }
+				} else if (node instanceof LocalDeclaration) {
+				    if (start == end) {
+					    LocalDeclaration local = (LocalDeclaration)node;
+						element = new LocalVariable(
+								(JavaElement)parent, 
+								new String(local.name), 
+								local.declarationSourceStart,
+								local.declarationSourceEnd,
+								local.sourceStart,
+								local.sourceEnd,
+								Util.typeSignature(local.type));
+				    } // else the next node is an anonymous (initializer of the local variable)
+				}
+				break;
+ 	    }
+	   return createElement(nodeStack, start+1, end, element);
+	}
+	/**
+	 * Returns a handle denoting the class member identified by its scope.
+	 */
+	public IJavaElement createElement(ClassScope scope, ICompilationUnit unit, HashSet existingElements, HashMap knownScopes) {
+		return createElement(scope, scope.referenceContext.sourceStart, unit, existingElements, knownScopes);
+	}
+	/**
+	 * Create handle by adding child to parent obtained by recursing into parent scopes.
+	 */
+	private IJavaElement createElement(Scope scope, int elementPosition, ICompilationUnit unit, HashSet existingElements, HashMap knownScopes) {
+		IJavaElement newElement = (IJavaElement)knownScopes.get(scope);
+		if (newElement != null) return newElement;
+	
+		switch(scope.kind) {
+			case Scope.COMPILATION_UNIT_SCOPE :
+				newElement = unit;
+				break;			
+			case Scope.CLASS_SCOPE :
+				IJavaElement parentElement = createElement(scope.parent, elementPosition, unit, existingElements, knownScopes);
+				switch (parentElement.getElementType()) {
+					case IJavaElement.COMPILATION_UNIT :
+						newElement = ((ICompilationUnit)parentElement).getType(new String(scope.enclosingSourceType().sourceName));
+						break;						
+					case IJavaElement.TYPE :
+						newElement = ((IType)parentElement).getType(new String(scope.enclosingSourceType().sourceName));
+						break;
+					case IJavaElement.FIELD :
+					case IJavaElement.INITIALIZER :
+					case IJavaElement.METHOD :
+					    IMember member = (IMember)parentElement;
+					    if (member.isBinary()) {
+					        return null;
+					    } else {
+							newElement = member.getType(new String(scope.enclosingSourceType().sourceName), 1);
+							// increment occurrence count if collision is detected
+							if (newElement != null) {
+								while (!existingElements.add(newElement)) ((JavaElement)newElement).occurrenceCount++;
+							}
+					    }
+						break;						
+				}
+				if (newElement != null) {
+					knownScopes.put(scope, newElement);
+				}
+				break;
+			case Scope.METHOD_SCOPE :
+				IType parentType = (IType) createElement(scope.parent, elementPosition, unit, existingElements, knownScopes);
+				MethodScope methodScope = (MethodScope) scope;
+				if (methodScope.isInsideInitializer()) {
+					// inside field or initializer, must find proper one
+					TypeDeclaration type = methodScope.referenceType();
+					int occurenceCount = 1;
+					for (int i = 0, length = type.fields.length; i < length; i++) {
+						FieldDeclaration field = type.fields[i];
+						if (field.declarationSourceStart < elementPosition && field.declarationSourceEnd > elementPosition) {
+							if (field.isField()) {
+								newElement = parentType.getField(new String(field.name));
+							} else {
+								newElement = parentType.getInitializer(occurenceCount);
+							}
+							break;
+						} else if (!field.isField()) {
+							occurenceCount++;
+						}
+					}
+				} else {
+					// method element
+					AbstractMethodDeclaration method = methodScope.referenceMethod();
+					newElement = parentType.getMethod(new String(method.selector), Util.typeParameterSignatures(method));
+					if (newElement != null) {
+						knownScopes.put(scope, newElement);
+					}
+				}
+				break;				
+			case Scope.BLOCK_SCOPE :
+				// standard block, no element per se
+				newElement = createElement(scope.parent, elementPosition, unit, existingElements, knownScopes);
+				break;
+		}
+		return newElement;
+	}
+	/**
+	 * Returns the package fragment root that corresponds to the given jar path.
+	 * See createOpenable(...) for the format of the jar path string.
+	 * If not null, uses the given scope as a hint for getting Java project handles.
+	 */
+	private IPackageFragmentRoot getJarPkgFragmentRoot(String jarPathString, IJavaSearchScope scope) {
+
+		IPath jarPath= new Path(jarPathString);
+		
+		Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), jarPath, false);
+		if (target instanceof IFile) {
+			// internal jar: is it on the classpath of its project?
+			//  e.g. org.eclipse.swt.win32/ws/win32/swt.jar 
+			//        is NOT on the classpath of org.eclipse.swt.win32
+			IFile jarFile = (IFile)target;
+			IJavaProject javaProject = this.javaModel.getJavaProject(jarFile);
+			IClasspathEntry[] classpathEntries;
+			try {
+				classpathEntries = javaProject.getResolvedClasspath(true);
+				for (int j= 0, entryCount= classpathEntries.length; j < entryCount; j++) {
+					if (classpathEntries[j].getPath().equals(jarPath)) {
+						return javaProject.getPackageFragmentRoot(jarFile);
+					}
+				}
+			} catch (JavaModelException e) {
+				// ignore and try to find another project
+			}
+		}
+		
+		// walk projects in the scope and find the first one that has the given jar path in its classpath
+		IJavaProject[] projects;
+		if (scope != null) {
+			IPath[] enclosingProjectsAndJars = scope.enclosingProjectsAndJars();
+			int length = enclosingProjectsAndJars.length;
+			projects = new IJavaProject[length];
+			int index = 0;
+			for (int i = 0; i < length; i++) {
+				IPath path = enclosingProjectsAndJars[i];
+				if (!org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(path.lastSegment())) {
+					projects[index++] = this.javaModel.getJavaProject(path.segment(0));
+				}
+			}
+			if (index < length) {
+				System.arraycopy(projects, 0, projects = new IJavaProject[index], 0, index);
+			}
+			IPackageFragmentRoot root = getJarPkgFragmentRoot(jarPath, target, projects);
+			if (root != null) {
+				return root;
+			}
+		} 
+		
+		// not found in the scope, walk all projects
+		try {
+			projects = this.javaModel.getJavaProjects();
+		} catch (JavaModelException e) {
+			// java model is not accessible
+			return null;
+		}
+		return getJarPkgFragmentRoot(jarPath, target, projects);
+	}
+	
+	private IPackageFragmentRoot getJarPkgFragmentRoot(
+		IPath jarPath,
+		Object target,
+		IJavaProject[] projects) {
+		for (int i= 0, projectCount= projects.length; i < projectCount; i++) {
+			try {
+				JavaProject javaProject= (JavaProject)projects[i];
+				IClasspathEntry[] classpathEntries= javaProject.getResolvedClasspath(true);
+				for (int j= 0, entryCount= classpathEntries.length; j < entryCount; j++) {
+					if (classpathEntries[j].getPath().equals(jarPath)) {
+						if (target instanceof IFile) {
+							// internal jar
+							return javaProject.getPackageFragmentRoot((IFile)target);
+						} else {
+							// external jar
+							return javaProject.getPackageFragmentRoot0(jarPath);
+						}
+					}
+				}
+			} catch (JavaModelException e) {
+				// JavaModelException from getResolvedClasspath - a problem occured while accessing project: nothing we can do, ignore
+			}
+		}
+		return null;
+	}
+
+	/*
+	 * Returns the openable that contains the given AST node.
+	 */
+	private Openable getOpenable(ASTNode toBeFound, Openable openable) {
+	    if (openable instanceof ClassFile) {
+	        try {
+	            int sourceStart = toBeFound.sourceStart;
+	            int sourceEnd = toBeFound.sourceEnd;
+	            ClassFile classFile = (ClassFile)openable;
+                ISourceRange sourceRange = classFile.getType().getSourceRange();
+                int offset = sourceRange.getOffset();
+                if (offset == sourceStart && offset + sourceRange.getLength() != sourceEnd) {
+                    return openable;
+                } else {
+                    String prefix = classFile.getTopLevelTypeName() + '$';
+                    IPackageFragment pkg = (IPackageFragment)classFile.getParent();
+                    IClassFile[] children = pkg.getClassFiles();
+                    for (int i = 0, length = children.length; i < length; i++) {
+                        IClassFile child = children[i];
+                        if (child.getElementName().startsWith(prefix)) {
+			                sourceRange = child.getType().getSourceRange();
+			                offset = sourceRange.getOffset();
+                        	if (offset == sourceStart && offset + sourceRange.getLength() != sourceEnd) {
+                        	    return (Openable)child;
+                        	}
+                        }
+                    }
+                }
+            } catch (JavaModelException e) {
+                // class file doesn't exist: ignore
+            }
+	    }
+	    return openable;
+	}
+	
+	/**
+	 * Returns the package fragment root that contains the given resource path.
+	 */
+	private IPackageFragmentRoot getPkgFragmentRoot(String pathString) {
+
+		IPath path= new Path(pathString);
+		IProject[] projects= ResourcesPlugin.getWorkspace().getRoot().getProjects();
+		for (int i= 0, max= projects.length; i < max; i++) {
+			try {
+				IProject project = projects[i];
+				if (!project.isAccessible() 
+					|| !project.hasNature(JavaCore.NATURE_ID)) continue;
+				IJavaProject javaProject= this.javaModel.getJavaProject(project);
+				IPackageFragmentRoot[] roots= javaProject.getPackageFragmentRoots();
+				for (int j= 0, rootCount= roots.length; j < rootCount; j++) {
+					PackageFragmentRoot root= (PackageFragmentRoot)roots[j];
+					if (root.getPath().isPrefixOf(path) && !Util.isExcluded(path, root.fullExclusionPatternChars())) {
+						return root;
+					}
+				}
+			} catch (CoreException e) {
+				// CoreException from hasNature - should not happen since we check that the project is accessible
+				// JavaModelException from getPackageFragmentRoots - a problem occured while accessing project: nothing we can do, ignore
+			}
+		}
+		return null;
+	}
+	
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LRUCache.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LRUCache.java
index f8b1b2b..79dfecb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LRUCache.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LRUCache.java
@@ -377,7 +377,7 @@
 		LRUCacheEntry entry;
 		
 		/* Check whether there's an entry in the cache */
-		newSpace = spaceFor (key, value);
+		newSpace = spaceFor(value);
 		entry = (LRUCacheEntry) fEntryTable.get (key);
 		
 		if (entry != null) {
@@ -433,9 +433,9 @@
 		fSpaceLimit = limit;
 	}
 	/**
-	 * Returns the space taken by the given key and value.
+	 * Returns the space taken by the given value.
 	 */
-	protected int spaceFor (Object key, Object value) {
+	protected int spaceFor (Object value) {
 		
 		if (value instanceof ILRUCacheable) {
 			return ((ILRUCacheable) value).getCacheFootprint();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PerThreadObject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PerThreadObject.java
deleted file mode 100644
index 511db25..0000000
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PerThreadObject.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.util;
-
-import java.util.Hashtable;
-
-/**
- * Implementation of data structure remembering an Object value by thread. Its purpose is to ease
- * writing multi-threaded algorithms by providing a per thread data structure.
- */
-public class PerThreadObject {
-
-	private Hashtable internalMap = new Hashtable(3); // synchronized map
-	
-	/**
-	 * Answer the current map for this thread
-	 */
-	public Object getCurrent(){
-		return this.internalMap.get(Thread.currentThread());
-	}
-	
-	/**
-	 * Set the map for this current thread - setting to null is equivalent to removing it
-	 */
-	public void setCurrent(Object current){
-		if (current == null){
-			this.internalMap.remove(Thread.currentThread());			
-		} else {
-			this.internalMap.put(Thread.currentThread(), current);
-		}
-	}
-}
-
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
index c1c6ff8..0641b66 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
@@ -12,10 +12,12 @@
 
 import java.util.Iterator;
 
-import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IScanner;
 import org.eclipse.jdt.core.compiler.ITerminalSymbols;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.parser.NLSLine;
 
 public class PublicScanner implements IScanner, ITerminalSymbols {
@@ -129,8 +131,6 @@
 	public /*static*/ final char[][][][] charArray_length = 
 		new char[OptimizedLength][TableSize][InternalTableSize][]; 
 	// support for detecting non-externalized string literals
-	int currentLineNr= -1;
-	int previousLineNr= -1;
 	NLSLine currentLine= null;
 	public static final String TAG_PREFIX= "//$NON-NLS-"; //$NON-NLS-1$
 	public static final int TAG_PREFIX_LENGTH= TAG_PREFIX.length();
@@ -161,26 +161,26 @@
 	public static final int BracketKinds = 3;
 
 public PublicScanner() {
-	this(false /*comment*/, false /*whitespace*/, false /*nls*/, false /*assert*/, null/*taskTag*/, null/*taskPriorities*/);
+	this(false /*comment*/, false /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/);
 }
+
 public PublicScanner(
 	boolean tokenizeComments, 
 	boolean tokenizeWhiteSpace, 
 	boolean checkNonExternalizedStringLiterals, 
-	boolean assertMode,
+	long sourceLevel,
 	char[][] taskTags,
 	char[][] taskPriorities) {
-		
+
 	this.eofPosition = Integer.MAX_VALUE;
 	this.tokenizeComments = tokenizeComments;
 	this.tokenizeWhiteSpace = tokenizeWhiteSpace;
 	this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
-	this.assertMode = assertMode;
+	this.assertMode = sourceLevel >= ClassFileConstants.JDK1_4;
 	this.taskTags = taskTags;
 	this.taskPriorities = taskPriorities;
 }
 
-
 public  final boolean atEnd() {
 	// This code is not relevant if source is 
 	// Only a part of the real stream input
@@ -188,106 +188,124 @@
 	return source.length == currentPosition;
 }
 
-private void checkNonExternalizeString()  throws InvalidInputException {
-	if (currentLine == null)
+private void checkNonExternalizedString() {
+	if (currentLine == null) 
 		return;
 	parseTags(currentLine);
 }
 
 // chech presence of task: tags
 public void checkTaskTag(int commentStart, int commentEnd) {
-
+	char[] src = this.source;
+	
 	// only look for newer task: tags
-	if (this.foundTaskCount > 0 && this.foundTaskPositions[this.foundTaskCount-1][0] >= commentStart) {
+	if (this.foundTaskCount > 0
+		&& this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) {
 		return;
 	}
 	int foundTaskIndex = this.foundTaskCount;
-	nextChar: for (int i = commentStart; i < commentEnd && i < this.eofPosition; i++) {
-
+	char previous = '/';
+	nextChar : for (
+		int i = commentStart + 1; i < commentEnd && i < this.eofPosition; i++) {
 		char[] tag = null;
 		char[] priority = null;
-		
 		// check for tag occurrence
-		nextTag: for (int itag = 0; itag < this.taskTags.length; itag++){
+		nextTag : for (int itag = 0; itag < this.taskTags.length; itag++) {
 			tag = this.taskTags[itag];
-			priority = 
-				this.taskPriorities != null && itag < this.taskPriorities.length ?
-				this.taskPriorities[itag] :
-				null;
 			int tagLength = tag.length;
-			for (int t = 0; t < tagLength; t++){
-				if (this.source[i+t] != tag[t]) continue nextTag;
+			if (tagLength == 0) continue nextTag;
+
+			// ensure tag is not leaded with letter if tag starts with a letter
+			if (Character.isLetterOrDigit(tag[0])) {
+				if (Character.isLetterOrDigit(previous)) {
+					continue nextTag;
+				}
 			}
 
-			if (this.foundTaskTags == null){
+			for (int t = 0; t < tagLength; t++) {
+				if (src[i + t] != tag[t])
+					continue nextTag;
+			}
+			// ensure tag is not followed with letter if tag finishes with a letter
+			if (i+tagLength < commentEnd && Character.isLetterOrDigit(src[i+tagLength-1])) {
+				if (Character.isLetterOrDigit(src[i + tagLength]))
+					continue nextTag;
+			}
+			if (this.foundTaskTags == null) {
 				this.foundTaskTags = new char[5][];
 				this.foundTaskMessages = new char[5][];
 				this.foundTaskPriorities = new char[5][];
 				this.foundTaskPositions = new int[5][];
 			} else if (this.foundTaskCount == this.foundTaskTags.length) {
-				System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount*2][], 0, this.foundTaskCount);
-				System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount*2][], 0, this.foundTaskCount);
-				System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount*2][], 0, this.foundTaskCount);
-				System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount*2][], 0, this.foundTaskCount);
+				System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
+				System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
+				System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
+				System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, this.foundTaskCount);
 			}
+			
+			priority = this.taskPriorities != null && itag < this.taskPriorities.length
+						? this.taskPriorities[itag]
+						: null;
+			
 			this.foundTaskTags[this.foundTaskCount] = tag;
 			this.foundTaskPriorities[this.foundTaskCount] = priority;
-			this.foundTaskPositions[this.foundTaskCount] = new int[]{ i, i+tagLength-1 };
+			this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 };
 			this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR;
 			this.foundTaskCount++;
-			
-			i += tagLength-1; // will be incremented when looping
+			i += tagLength - 1; // will be incremented when looping
+			break nextTag;
 		}
+		previous = src[i];
 	}
-	
 	for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
 		// retrieve message start and end positions
 		int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length;
-		int max_value = i + 1 < this.foundTaskCount ? this.foundTaskPositions[i + 1][0] - 1 : commentEnd-1; // at most beginning of next task
-		if (max_value < msgStart) max_value = msgStart; // would only occur if tag is before EOF.
+		int max_value = i + 1 < this.foundTaskCount
+				? this.foundTaskPositions[i + 1][0] - 1
+				: commentEnd - 1;
+		// at most beginning of next task
+		if (max_value < msgStart) {
+			max_value = msgStart; // would only occur if tag is before EOF.
+		}
 		int end = -1;
 		char c;
-		
-		for (int j = msgStart; j < max_value; j++){
-			if ((c = this.source[j]) == '\n' || c == '\r'){
-				end = j-1;
+		for (int j = msgStart; j < max_value; j++) {
+			if ((c = src[j]) == '\n' || c == '\r') {
+				end = j - 1;
 				break;
 			}
 		}
-		
-		if (end == -1){
-			for (int j = max_value; j > msgStart; j--){
-				if ((c = this.source[j]) == '*') {
-					end = j-1;
+		if (end == -1) {
+			for (int j = max_value; j > msgStart; j--) {
+				if ((c = src[j]) == '*') {
+					end = j - 1;
 					break;
 				}
 			}
-			if (end == -1) end = max_value;
+			if (end == -1)
+				end = max_value;
 		}
-
-		if (msgStart == end) continue; // empty
-				
+		if (msgStart == end)
+			continue; // empty
 		// trim the message
-		while (CharOperation.isWhitespace(source[end]) && msgStart <= end) end--;
-		while (CharOperation.isWhitespace(source[msgStart]) && msgStart <= end) msgStart++;
-
+		while (CharOperation.isWhitespace(src[end]) && msgStart <= end)
+			end--;
+		while (CharOperation.isWhitespace(src[msgStart]) && msgStart <= end)
+			msgStart++;
 		// update the end position of the task
 		this.foundTaskPositions[i][1] = end;
-		
 		// get the message source
-		final int messageLength = end-msgStart+1;
+		final int messageLength = end - msgStart + 1;
 		char[] message = new char[messageLength];
-
-		System.arraycopy(source, msgStart, message, 0, messageLength);
+		System.arraycopy(src, msgStart, message, 0, messageLength);
 		this.foundTaskMessages[i] = message;
 	}
 }
-
 public char[] getCurrentIdentifierSource() {
 	//return the token REAL source (aka unicodes are precomputed)
 
 	char[] result;
-	if (withoutUnicodePtr != 0)
+	if (withoutUnicodePtr != 0) {
 		//0 is used as a fast test flag so the real first char is in position 1
 		System.arraycopy(
 			withoutUnicodeBuffer, 
@@ -295,8 +313,9 @@
 			result = new char[withoutUnicodePtr], 
 			0, 
 			withoutUnicodePtr); 
-	else {
+	} else {
 		int length = currentPosition - startPosition;
+		if (length == this.source.length) return this.source;
 		switch (length) { // see OptimizedLength
 			case 1 :
 				return optimizedCurrentTokenSource1();
@@ -384,11 +403,14 @@
  */
 public final int getLineEnd(int lineNumber) {
 
-	if (lineEnds == null) return -1;
-	if (lineNumber >= lineEnds.length) return -1;
-	if (lineNumber <= 0) return -1;
-	
-	if (lineNumber == lineEnds.length - 1) return eofPosition;
+	if (lineEnds == null) 
+		return -1;
+	if (lineNumber > lineEnds.length+1) 
+		return -1;
+	if (lineNumber <= 0) 
+		return -1;
+	if (lineNumber == lineEnds.length + 1) 
+		return eofPosition;
 	return lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line
 }
 
@@ -412,13 +434,69 @@
  */
 public final int getLineStart(int lineNumber) {
 
-	if (lineEnds == null) return -1;
-	if (lineNumber >= lineEnds.length) return -1;
-	if (lineNumber <= 0) return -1;
+	if (lineEnds == null) 
+		return -1;
+	if (lineNumber > lineEnds.length + 1) 
+		return -1;
+	if (lineNumber <= 0) 
+		return -1;
 	
-	if (lineNumber == 1) return initialPosition;
+	if (lineNumber == 1) 
+		return initialPosition;
 	return lineEnds[lineNumber-2]+1; // next line start one character behind the lineEnd of the previous line
 }
+public final int getNextChar() {
+	try {
+		if (((currentCharacter = source[currentPosition++]) == '\\')
+			&& (source[currentPosition] == 'u')) {
+			//-------------unicode traitement ------------
+			int c1, c2, c3, c4;
+			int unicodeSize = 6;
+			currentPosition++;
+			while (source[currentPosition] == 'u') {
+				currentPosition++;
+				unicodeSize++;
+			}
+
+			if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+				|| c1 < 0)
+				|| ((c2 = Character.getNumericValue(source[currentPosition++])) > 15 || c2 < 0)
+				|| ((c3 = Character.getNumericValue(source[currentPosition++])) > 15 || c3 < 0)
+				|| ((c4 = Character.getNumericValue(source[currentPosition++])) > 15 || c4 < 0)) {
+				return -1;
+			}
+
+			currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+
+			unicodeAsBackSlash = currentCharacter == '\\';
+
+			//need the unicode buffer
+			if (withoutUnicodePtr == 0) {
+				//buffer all the entries that have been left aside....
+				withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
+				System.arraycopy(
+					source, 
+					startPosition, 
+					withoutUnicodeBuffer, 
+					1, 
+					withoutUnicodePtr); 
+			}
+			//fill the buffer with the char
+			withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+			return currentCharacter;
+
+		} //-------------end unicode traitement--------------
+		else {
+			unicodeAsBackSlash = false;
+			if (withoutUnicodePtr != 0) {
+				withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+			}
+			return currentCharacter;
+		}
+	} catch (IndexOutOfBoundsException e) {
+		return -1;
+	}
+}
 public final boolean getNextChar(char testedChar) {
 	//BOOLEAN
 	//handle the case of unicode.
@@ -778,7 +856,6 @@
 	}
 }
 public int getNextToken() throws InvalidInputException {
-
 	this.wasAcr = false;
 	if (diet) {
 		jumpOverMethodBody();
@@ -817,7 +894,7 @@
 				} else {
 					offset = 1;
 					if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
-						checkNonExternalizeString();
+						checkNonExternalizedString();
 						if (recordLineSeparator) {
 							pushLineSeparator();
 						} else {
@@ -1224,7 +1301,7 @@
 								recordComment(false);
 								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
 								if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
-									checkNonExternalizeString();
+									checkNonExternalizedString();
 									if (recordLineSeparator) {
 										if (isUnicode) {
 											pushUnicodeLineSeparator();
@@ -1239,16 +1316,18 @@
 									return TokenNameCOMMENT_LINE;
 								}
 							} catch (IndexOutOfBoundsException e) {
+								currentPosition--;
 								recordComment(false);
-								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition-1);
+								if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
 								if (tokenizeComments) {
-									this.currentPosition--; // reset one character behind
 									return TokenNameCOMMENT_LINE;
+								} else {
+									this.currentPosition++; 
 								}
 							}
 							break;
 						}
-						if (test > 0) { //traditional and annotation comment
+						if (test > 0) { //traditional and javadoc comment
 							try { //get the next char
 								boolean isJavadoc = false, star = false;
 								boolean isUnicode = false;
@@ -1270,7 +1349,7 @@
 									star = true;
 								}
 								if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
-									checkNonExternalizeString();
+									checkNonExternalizedString();
 									if (recordLineSeparator) {
 										if (!isUnicode) {
 											pushLineSeparator();
@@ -1296,7 +1375,7 @@
 								//loop until end of comment */
 								while ((currentCharacter != '/') || (!star)) {
 									if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
-										checkNonExternalizeString();
+										checkNonExternalizedString();
 										if (recordLineSeparator) {
 											if (!isUnicode) {
 												pushLineSeparator();
@@ -1452,7 +1531,8 @@
 							try {
 								scanEscapeCharacter();
 							} catch (InvalidInputException ex) {
-							};
+								// ignore
+							}
 						} else {
 							try { // consume next character
 								unicodeAsBackSlash = false;
@@ -1465,7 +1545,8 @@
 									}
 								}
 							} catch (InvalidInputException ex) {
-							};
+								// ignore
+							}
 						}
 						getNextChar('\'');
 						break;
@@ -1483,7 +1564,8 @@
 								}
 							}
 						} catch (InvalidInputException ex) {
-						};
+								// ignore
+						}
 						while (currentCharacter != '"') {
 							if (currentCharacter == '\r'){
 								if (source[currentPosition] == '\n') currentPosition++;
@@ -1496,7 +1578,8 @@
 								try {
 									scanEscapeCharacter();
 								} catch (InvalidInputException ex) {
-								};
+									// ignore
+								}
 							}
 							try { // consume next character
 								unicodeAsBackSlash = false;
@@ -1509,7 +1592,8 @@
 									}
 								}
 							} catch (InvalidInputException ex) {
-							};
+								// ignore
+							}
 						}
 					} catch (IndexOutOfBoundsException e) {
 						return;
@@ -1583,10 +1667,11 @@
 										}
 									}
 							} catch (IndexOutOfBoundsException e) {
-							} //an eof will them be generated
+								 //an eof will then be generated
+							}
 							break;
 						}
-						if (test > 0) { //traditional and annotation comment
+						if (test > 0) { //traditional and javadoc comment
 							isUnicode = false;
 							boolean star = false;
 							try { // consume next character
@@ -1600,9 +1685,10 @@
 									if (withoutUnicodePtr != 0) {
 										withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
 									}
-								};
+								}
 							} catch (InvalidInputException ex) {
-							};
+ 								// ignore
+ 							}
 							if (currentCharacter == '*') {
 								star = true;
 							}
@@ -1684,24 +1770,24 @@
 
 				default :
 					if (Character.isJavaIdentifierStart(currentCharacter)) {
-						try {
-							scanIdentifierOrKeyword();
-						} catch (InvalidInputException ex) {
-						};
+						scanIdentifierOrKeyword();
 						break;
 					}
 					if (Character.isDigit(currentCharacter)) {
 						try {
 							scanNumber(false);
 						} catch (InvalidInputException ex) {
-						};
+ 							// ignore
+ 						}
 						break;
 					}
 			}
 		}
 		//-----------------end switch while try--------------------
 	} catch (IndexOutOfBoundsException e) {
+		// ignore
 	} catch (InvalidInputException e) {
+		// ignore
 	}
 	return;
 }
@@ -1990,7 +2076,7 @@
 	newEntry6 = max;
 	return r;	
 }
-private void parseTags(NLSLine line) throws InvalidInputException {
+private void parseTags(NLSLine line) {
 	String s = new String(getCurrentTokenSource());
 	int pos = s.indexOf(TAG_PREFIX);
 	int lineLength = line.size();
@@ -2032,7 +2118,7 @@
 	currentLine = null;
 }
 
-public final void pushLineSeparator() throws InvalidInputException {
+public final void pushLineSeparator() {
 	//see comment on isLineDelimiter(char) for the use of '\n' and '\r'
 	final int INCREMENT = 250;
 	
@@ -2045,7 +2131,8 @@
 	// cr 000D
 	if (currentCharacter == '\r') {
 		int separatorPos = currentPosition - 1;
-		if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos)) return;
+		//TODO (olivier) david - why the following line was "if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos)) return;" ?
+		if ((linePtr >= 0) && (lineEnds[linePtr] >= separatorPos)) return;
 		//System.out.println("CR-" + separatorPos);
 		try {
 			lineEnds[++linePtr] = separatorPos;
@@ -2078,7 +2165,8 @@
 				lineEnds[linePtr] = currentPosition - 1;
 			} else {
 				int separatorPos = currentPosition - 1;
-				if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos)) return;
+				//TODO (olivier) david - why the following line was "if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos)) return;" ?
+				if ((linePtr >= 0) && (lineEnds[linePtr] >= separatorPos)) return;
 				// System.out.println("LF-" + separatorPos);							
 				try {
 					lineEnds[++linePtr] = separatorPos;
@@ -2117,7 +2205,7 @@
 }
 public final void recordComment(boolean isJavadoc) {
 
-	// a new annotation comment is recorded
+	// a new comment is recorded
 	try {
 		this.commentStops[++this.commentPtr] = isJavadoc ? this.currentPosition : -this.currentPosition;
 	} catch (IndexOutOfBoundsException e) {
@@ -2136,6 +2224,13 @@
 	this.commentStarts[this.commentPtr] = this.startPosition;
 }
 
+/**
+ * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position.
+ * Beyond this position, the scanner will answer EOF tokens (<code>ITerminalSymbols.TokenNameEOF</code>).
+ * 
+ * @param startPosition the given start position
+ * @param endPosition the given end position
+ */
 public void resetTo(int begin, int end) {
 	//reset the scanner to a given position where it may rescan again
 
@@ -2144,7 +2239,11 @@
 	eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
 	commentPtr = -1; // reset comment stack
 	foundTaskCount = 0;
-
+	
+//	// if resetTo is used with being > than end.
+//	if (begin > eofPosition) {
+//		begin = eofPosition;
+//	}
 }
 
 public final void scanEscapeCharacter() throws InvalidInputException {
@@ -2228,7 +2327,7 @@
 				throw new InvalidInputException(INVALID_ESCAPE);
 	}
 }
-public int scanIdentifierOrKeyword() throws InvalidInputException {
+public int scanIdentifierOrKeyword() {
 	//test keywords
 
 	//first dispatch on the first char.
@@ -2236,7 +2335,7 @@
 	//keywors with the same length AND the same first char, then do another
 	//dispatch on the second char 
 	useAssertAsAnIndentifier = false;
-	while (getNextCharAsJavaIdentifierPart()) {};
+	while (getNextCharAsJavaIdentifierPart());
 
 	int index, length;
 	char[] data;
@@ -2816,7 +2915,7 @@
 			if (Character.digit(currentCharacter, 16) == -1)
 				throw new InvalidInputException(INVALID_HEXA);
 			//---end forcing--
-			while (getNextCharAsDigit(16)) {};
+			while (getNextCharAsDigit(16));
 			if (getNextChar('l', 'L') >= 0)
 				return TokenNameLongLiteral;
 			else
@@ -2826,7 +2925,7 @@
 		//there is x or X in the number
 		//potential octal ! ... some one may write 000099.0 ! thus 00100 < 00078.0 is true !!!!! crazy language
 		if (getNextCharAsDigit()) { //-------------potential octal-----------------
-			while (getNextCharAsDigit()) {};
+			while (getNextCharAsDigit());
 
 			if (getNextChar('l', 'L') >= 0) {
 				return TokenNameLongLiteral;
@@ -2842,7 +2941,7 @@
 				boolean isInteger = true;
 				if (getNextChar('.')) { 
 					isInteger = false;
-					while (getNextCharAsDigit()) {};
+					while (getNextCharAsDigit());
 				}
 				if (getNextChar('e', 'E') >= 0) { // consume next character
 					isInteger = false;
@@ -2870,7 +2969,7 @@
 					}
 					if (!Character.isDigit(currentCharacter))
 						throw new InvalidInputException(INVALID_FLOAT);
-					while (getNextCharAsDigit()) {};
+					while (getNextCharAsDigit());
 				}
 				if (getNextChar('f', 'F') >= 0)
 					return TokenNameFloatingPointLiteral;
@@ -2883,13 +2982,13 @@
 		}
 	}
 
-	while (getNextCharAsDigit()) {};
+	while (getNextCharAsDigit());
 
 	if ((!dotPrefix) && (getNextChar('l', 'L') >= 0))
 		return TokenNameLongLiteral;
 
 	if ((!dotPrefix) && (getNextChar('.'))) { //decimal part that can be empty
-		while (getNextCharAsDigit()) {};
+		while (getNextCharAsDigit());
 		floating = true;
 	}
 
@@ -2922,7 +3021,7 @@
 		}
 		if (!Character.isDigit(currentCharacter))
 			throw new InvalidInputException(INVALID_FLOAT);
-		while (getNextCharAsDigit()) {};
+		while (getNextCharAsDigit());
 	}
 
 	if (getNextChar('d', 'D') >= 0)
@@ -2962,27 +3061,29 @@
 	}
 	return m+2;
 }
-public final void setSource(char[] source){
+public final void setSource(char[] sourceString){
 	//the source-buffer is set to sourceString
 
-	if (source == null) {
+	int sourceLength;
+	if (sourceString == null) {
 		this.source = CharOperation.NO_CHAR;
+		sourceLength = 0;
 	} else {
-		this.source = source;
+		this.source = sourceString;
+		sourceLength = sourceString.length;
 	}
 	startPosition = -1;
-	eofPosition = source.length;
+	eofPosition = sourceLength;
 	initialPosition = currentPosition = 0;
 	containsAssertKeyword = false;
-	withoutUnicodeBuffer = new char[this.source.length];
-
+	withoutUnicodeBuffer = new char[sourceLength];
 }
 
 public String toString() {
 	if (startPosition == source.length)
 		return "EOF\n\n" + new String(source); //$NON-NLS-1$
 	if (currentPosition > source.length)
-		return "behind the EOF :-( ....\n\n" + new String(source); //$NON-NLS-1$
+		return "behind the EOF\n\n" + new String(source); //$NON-NLS-1$
 
 	char front[] = new char[startPosition];
 	System.arraycopy(source, 0, front, 0, startPosition);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ReferenceInfoAdapter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ReferenceInfoAdapter.java
index 888d238..c1d395d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ReferenceInfoAdapter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/ReferenceInfoAdapter.java
@@ -18,29 +18,43 @@
 /**
  * Does nothing.
  */
-public void acceptConstructorReference(char[] typeName, int argCount, int sourcePosition) {}
+public void acceptConstructorReference(char[] typeName, int argCount, int sourcePosition) {
+	// Does nothing
+}
 /**
  * Does nothing.
  */
-public void acceptFieldReference(char[] fieldName, int sourcePosition) {}
+public void acceptFieldReference(char[] fieldName, int sourcePosition) {
+	// Does nothing
+}
 /**
  * Does nothing.
  */
-public void acceptMethodReference(char[] methodName, int argCount, int sourcePosition) {}
+public void acceptMethodReference(char[] methodName, int argCount, int sourcePosition) {
+	// Does nothing
+}
 /**
  * Does nothing.
  */
-public void acceptTypeReference(char[][] typeName, int sourceStart, int sourceEnd) {}
+public void acceptTypeReference(char[][] typeName, int sourceStart, int sourceEnd) {
+	// Does nothing
+}
 /**
  * Does nothing.
  */
-public void acceptTypeReference(char[] typeName, int sourcePosition) {}
+public void acceptTypeReference(char[] typeName, int sourcePosition) {
+	// Does nothing
+}
 /**
  * Does nothing.
  */
-public void acceptUnknownReference(char[][] name, int sourceStart, int sourceEnd) {}
+public void acceptUnknownReference(char[][] name, int sourceStart, int sourceEnd) {
+	// Does nothing
+}
 /**
  * Does nothing.
  */
-public void acceptUnknownReference(char[] name, int sourcePosition) {}
+public void acceptUnknownReference(char[] name, int sourcePosition) {
+	// Does nothing
+}
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java
new file mode 100644
index 0000000..46e4214
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleDocument.java
@@ -0,0 +1,371 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.IDocumentPartitioningListener;
+import org.eclipse.jface.text.IPositionUpdater;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Position;
+
+/**
+ * Minimal implementation of IDocument to apply text edit onto a string.
+ */
+public class SimpleDocument implements IDocument {
+	
+	private StringBuffer buffer;
+
+	
+	public SimpleDocument(String source) {
+		this.buffer = new StringBuffer(source);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getChar(int)
+	 */
+	public char getChar(int offset) {
+		return 0;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getLength()
+	 */
+	public int getLength() {
+		return this.buffer.length();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#get()
+	 */
+	public String get() {
+		return this.buffer.toString();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#get(int, int)
+	 */
+	public String get(int offset, int length) {
+		return this.buffer.substring(offset, offset + length);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#set(java.lang.String)
+	 */
+	public void set(String text) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#replace(int, int, java.lang.String)
+	 */
+	public void replace(int offset, int length, String text) {
+		
+		this.buffer.replace(offset, offset + length, text);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#addDocumentListener(org.eclipse.jface.text.IDocumentListener)
+	 */
+	public void addDocumentListener(IDocumentListener listener) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#removeDocumentListener(org.eclipse.jface.text.IDocumentListener)
+	 */
+	public void removeDocumentListener(IDocumentListener listener) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#addPrenotifiedDocumentListener(org.eclipse.jface.text.IDocumentListener)
+	 */
+	public void addPrenotifiedDocumentListener(IDocumentListener documentAdapter) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#removePrenotifiedDocumentListener(org.eclipse.jface.text.IDocumentListener)
+	 */
+	public void removePrenotifiedDocumentListener(IDocumentListener documentAdapter) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#addPositionCategory(java.lang.String)
+	 */
+	public void addPositionCategory(String category) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#removePositionCategory(java.lang.String)
+	 */
+	public void removePositionCategory(String category) {
+			// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getPositionCategories()
+	 */
+	public String[] getPositionCategories() {
+		// defining interface method
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#containsPositionCategory(java.lang.String)
+	 */
+	public boolean containsPositionCategory(String category) {
+		// defining interface method
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#addPosition(org.eclipse.jface.text.Position)
+	 */
+	public void addPosition(Position position) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#removePosition(org.eclipse.jface.text.Position)
+	 */
+	public void removePosition(Position position) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#addPosition(java.lang.String, org.eclipse.jface.text.Position)
+	 */
+	public void addPosition(String category, Position position) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#removePosition(java.lang.String, org.eclipse.jface.text.Position)
+	 */
+	public void removePosition(String category, Position position) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getPositions(java.lang.String)
+	 */
+	public Position[] getPositions(String category) {
+		// defining interface method
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#containsPosition(java.lang.String, int, int)
+	 */
+	public boolean containsPosition(String category, int offset, int length) {
+		// defining interface method
+		return false;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#computeIndexInCategory(java.lang.String, int)
+	 */
+	public int computeIndexInCategory(String category, int offset) {
+		// defining interface method
+		return 0;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#addPositionUpdater(org.eclipse.jface.text.IPositionUpdater)
+	 */
+	public void addPositionUpdater(IPositionUpdater updater) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#removePositionUpdater(org.eclipse.jface.text.IPositionUpdater)
+	 */
+	public void removePositionUpdater(IPositionUpdater updater) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#insertPositionUpdater(org.eclipse.jface.text.IPositionUpdater, int)
+	 */
+	public void insertPositionUpdater(IPositionUpdater updater, int index) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getPositionUpdaters()
+	 */
+	public IPositionUpdater[] getPositionUpdaters() {
+		// defining interface method
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getLegalContentTypes()
+	 */
+	public String[] getLegalContentTypes() {
+		// defining interface method
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getContentType(int)
+	 */
+	public String getContentType(int offset) {
+		// defining interface method
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getPartition(int)
+	 */
+	public ITypedRegion getPartition(int offset) {
+		// defining interface method
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#computePartitioning(int, int)
+	 */
+	public ITypedRegion[] computePartitioning(int offset, int length) {
+		// defining interface method
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#addDocumentPartitioningListener(org.eclipse.jface.text.IDocumentPartitioningListener)
+	 */
+	public void addDocumentPartitioningListener(IDocumentPartitioningListener listener) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#removeDocumentPartitioningListener(org.eclipse.jface.text.IDocumentPartitioningListener)
+	 */
+	public void removeDocumentPartitioningListener(IDocumentPartitioningListener listener) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#setDocumentPartitioner(org.eclipse.jface.text.IDocumentPartitioner)
+	 */
+	public void setDocumentPartitioner(IDocumentPartitioner partitioner) {
+		// defining interface method
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getDocumentPartitioner()
+	 */
+	public IDocumentPartitioner getDocumentPartitioner() {
+		// defining interface method
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getLineLength(int)
+	 */
+	public int getLineLength(int line) {
+		// defining interface method
+		return 0;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getLineOfOffset(int)
+	 */
+	public int getLineOfOffset(int offset) {
+		// defining interface method
+		return 0;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getLineOffset(int)
+	 */
+	public int getLineOffset(int line) {
+		// defining interface method
+		return 0;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getLineInformation(int)
+	 */
+	public IRegion getLineInformation(int line) {
+		// defining interface method
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getLineInformationOfOffset(int)
+	 */
+	public IRegion getLineInformationOfOffset(int offset) {
+		// defining interface method
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getNumberOfLines()
+	 */
+	public int getNumberOfLines() {
+		// defining interface method
+		return 0;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getNumberOfLines(int, int)
+	 */
+	public int getNumberOfLines(int offset, int length) {
+		// defining interface method
+		return 0;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#computeNumberOfLines(java.lang.String)
+	 */
+	public int computeNumberOfLines(String text) {
+		// defining interface method
+		return 0;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getLegalLineDelimiters()
+	 */
+	public String[] getLegalLineDelimiters() {
+		// defining interface method
+		return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.text.IDocument#getLineDelimiter(int)
+	 */
+	public String getLineDelimiter(int line) {
+		// defining interface method
+		return null;
+	}
+
+	/**
+	 * @see org.eclipse.jface.text.IDocument#search(int, java.lang.String, boolean, boolean, boolean)
+	 * @deprecated
+	 */
+	public int search(
+		int startOffset,
+		String findString,
+		boolean forwardSearch,
+		boolean caseSensitive,
+		boolean wholeWord) {
+		// defining interface method
+		return 0;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleLookupTable.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleLookupTable.java
index 9ac45d7..554a343 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleLookupTable.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleLookupTable.java
@@ -97,21 +97,23 @@
 	return value;
 }
 
-public void removeKey(Object key) {
+public Object removeKey(Object key) {
 	int length = keyTable.length;
 	int index = (key.hashCode() & 0x7FFFFFFF) % length;
 	Object currentKey;
 	while ((currentKey = keyTable[index]) != null) {
 		if (currentKey.equals(key)) {
 			elementSize--;
+			Object oldValue = valueTable[index];
 			keyTable[index] = null;
 			valueTable[index] = null;
 			if (keyTable[index + 1 == length ? 0 : index + 1] != null)
 				rehash(); // only needed if a possible collision existed
-			return;
+			return oldValue;
 		}
 		if (++index == length) index = 0;
 	}
+	return null;
 }
 
 public void removeValue(Object valueToRemove) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleSet.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleSet.java
new file mode 100644
index 0000000..4f42684
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/SimpleSet.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.util;
+
+/**
+ * A simple lookup table is a non-synchronized Hashtable, whose keys
+ * and values are Objects. It also uses linear probing to resolve collisions
+ * rather than a linked list of hash table entries.
+ */
+public final class SimpleSet implements Cloneable {
+
+// to avoid using Enumerations, walk the individual values skipping nulls
+public Object[] values;
+public int elementSize; // number of elements in the table
+public int threshold;
+
+public SimpleSet() {
+	this(13);
+}
+
+public SimpleSet(int size) {
+	if (size < 3) size = 3;
+	this.elementSize = 0;
+	this.threshold = size + 1; // size is the expected number of elements
+	this.values = new Object[2 * size + 1];
+}
+
+public Object add(Object object) {
+	int length = values.length;
+	int index = (object.hashCode() & 0x7FFFFFFF) % length;
+	Object current;
+	while ((current = values[index]) != null) {
+		if (current.equals(object)) return values[index] = object;
+		if (++index == length) index = 0;
+	}
+	values[index] = object;
+
+	// assumes the threshold is never equal to the size of the table
+	if (++elementSize > threshold) rehash();
+	return object;
+}
+
+public Object clone() throws CloneNotSupportedException {
+	SimpleSet result = (SimpleSet) super.clone();
+	result.elementSize = this.elementSize;
+	result.threshold = this.threshold;
+
+	int length = this.values.length;
+	result.values = new Object[length];
+	System.arraycopy(this.values, 0, result.values, 0, length);
+	return result;
+}
+
+public boolean includes(Object object) {
+	int length = values.length;
+	int index = (object.hashCode() & 0x7FFFFFFF) % length;
+	Object current;
+	while ((current = values[index]) != null) {
+		if (current.equals(object)) return true;
+		if (++index == length) index = 0;
+	}
+	return false;
+}
+
+public Object remove(Object object) {
+	int length = values.length;
+	int index = (object.hashCode() & 0x7FFFFFFF) % length;
+	Object current;
+	while ((current = values[index]) != null) {
+		if (current.equals(object)) {
+			elementSize--;
+			Object oldValue = values[index];
+			values[index] = null;
+			if (values[index + 1 == length ? 0 : index + 1] != null)
+				rehash(); // only needed if a possible collision existed
+			return oldValue;
+		}
+		if (++index == length) index = 0;
+	}
+	return null;
+}
+
+private void rehash() {
+	SimpleSet newSet = new SimpleSet(elementSize * 2); // double the number of expected elements
+	Object current;
+	for (int i = values.length; --i >= 0;)
+		if ((current = values[i]) != null)
+			newSet.add(current);
+
+	this.values = newSet.values;
+	this.elementSize = newSet.elementSize;
+	this.threshold = newSet.threshold;
+}
+
+public String toString() {
+	String s = ""; //$NON-NLS-1$
+	Object object;
+	for (int i = 0, l = values.length; i < l; i++)
+		if ((object = values[i]) != null)
+			s += object.toString() + "\n"; //$NON-NLS-1$
+	return s;
+}
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
index 653ae83..3f9a6d8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java
@@ -10,56 +10,78 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.util;
 
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
+import java.io.*;
+import java.util.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.core.Assert;
+import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.PackageFragmentRoot;
+import org.eclipse.jdt.internal.core.index.impl.IndexedFile;
+import org.eclipse.jdt.internal.core.index.impl.WordEntry;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.TextEdit;
 
 /**
  * Provides convenient utility methods to other types in this package.
  */
 public class Util {
-	private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
-	private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+
+	public interface Comparable {
+		/**
+		 * Returns 0 if this and c are equal, >0 if this is greater than c,
+		 * or <0 if this is less than c.
+		 */
+		int compareTo(Comparable c);
+	}
+
+	public interface Comparer {
+		/**
+		 * Returns 0 if a and b are equal, >0 if a is greater than b,
+		 * or <0 if a is less than b.
+		 */
+		int compare(Object a, Object b);
+	}
+	private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$
 
 	/* Bundle containing messages */
 	protected static ResourceBundle bundle;
-	private final static String bundleName =
-		"org.eclipse.jdt.internal.core.util.messages";	//$NON-NLS-1$
+	private final static String bundleName = "org.eclipse.jdt.internal.core.util.messages"; //$NON-NLS-1$
+
+	private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
+	private static final String EMPTY_ARGUMENT = "   "; //$NON-NLS-1$
+	
+	public static final String[] fgEmptyStringArray = new String[0];
+	private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
 
 	static {
-		/**
-		 * Creates a NLS catalog for the given locale.
-		 */
-		try  {		
-			bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
-		} catch(MissingResourceException e) {
-			System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
-			throw e;
-		}
-	}
+		relocalize();
+	}	
 
+	private Util() {
+		// cannot be instantiated
+	}
+	
 	/**
-	 * Lookup the message with the given ID in this catalog and bind its
-	 * substitution locations with the given string values.
+	 * Lookup the message with the given ID in this catalog 
 	 */
 	public static String bind(String id) {
-		if (id == null)
-			return "No message available"; //$NON-NLS-1$
-		String message = null;
-		try {
-			message = bundle.getString(id);
-		} catch (MissingResourceException e) {
-			// If we got an exception looking for the message, fail gracefully by just returning
-			// the id we were looking for.  In most cases this is semi-informative so is not too bad.
-			return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
-		}
-		// for compatibility with MessageFormat which eliminates double quotes in original message
-		char[] messageWithNoDoubleQuotes =
-			CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
-		return new String(messageWithNoDoubleQuotes);
+		return bind(id, (String[])null);
 	}
+	
 	/**
 	 * Lookup the message with the given ID in this catalog and bind its
 	 * substitution locations with the given string.
@@ -67,6 +89,15 @@
 	public static String bind(String id, String binding) {
 		return bind(id, new String[] {binding});
 	}
+	
+	/**
+	 * Lookup the message with the given ID in this catalog and bind its
+	 * substitution locations with the given strings.
+	 */
+	public static String bind(String id, String binding1, String binding2) {
+		return bind(id, new String[] {binding1, binding2});
+	}
+
 	/**
 	 * Lookup the message with the given ID in this catalog and bind its
 	 * substitution locations with the given string values.
@@ -84,26 +115,37 @@
 		}
 		// for compatibility with MessageFormat which eliminates double quotes in original message
 		char[] messageWithNoDoubleQuotes =
-		CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
+			CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
 		message = new String(messageWithNoDoubleQuotes);
-	
-		if (bindings == null)
-			return message;
-	
+		if (bindings == null) return message;
+
 		int length = message.length();
 		int start = -1;
 		int end = length;
-		StringBuffer output = new StringBuffer(80);
+		StringBuffer output = null;
 		while (true) {
 			if ((end = message.indexOf('{', start)) > -1) {
+				if (output == null) output = new StringBuffer(80);
 				output.append(message.substring(start + 1, end));
 				if ((start = message.indexOf('}', end)) > -1) {
 					int index = -1;
 					try {
 						index = Integer.parseInt(message.substring(end + 1, start));
 						output.append(bindings[index]);
-					} catch (NumberFormatException nfe) {
-						output.append(message.substring(end + 1, start + 1));
+					} catch (NumberFormatException nfe) { // could be nested message ID {compiler.name}
+						String argId = message.substring(end + 1, start);
+						boolean done = false;
+						if (!id.equals(argId)) {
+							String argMessage = null;
+							try {
+								argMessage = bundle.getString(argId);
+								output.append(argMessage);
+								done = true;
+							} catch (MissingResourceException e) {
+								// unable to bind argument, ignore (will leave argument in)
+							}
+						}
+						if (!done) output.append(message.substring(end + 1, start + 1));
 					} catch (ArrayIndexOutOfBoundsException e) {
 						output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
 					}
@@ -112,11 +154,1561 @@
 					break;
 				}
 			} else {
+				if (output == null) return message;
 				output.append(message.substring(start + 1, length));
 				break;
 			}
 		}
 		return output.toString();
 	}
+
+	/**
+	 * Checks the type signature in String sig, 
+	 * starting at start and ending before end (end is not included).
+	 * Returns the index of the character immediately after the signature if valid,
+	 * or -1 if not valid.
+	 */
+	private static int checkTypeSignature(String sig, int start, int end, boolean allowVoid) {
+		if (start >= end) return -1;
+		int i = start;
+		char c = sig.charAt(i++);
+		int nestingDepth = 0;
+		while (c == '[') {
+			++nestingDepth;
+			if (i >= end) return -1;
+			c = sig.charAt(i++);
+		}
+		switch (c) {
+			case 'B':
+			case 'C': 
+			case 'D':
+			case 'F':
+			case 'I':
+			case 'J':
+			case 'S': 
+			case 'Z':
+				break;
+			case 'V':
+				if (!allowVoid) return -1;
+				// array of void is not allowed
+				if (nestingDepth != 0) return -1;
+				break;
+			case 'L':
+				int semicolon = sig.indexOf(';', i);
+				// Must have at least one character between L and ;
+				if (semicolon <= i || semicolon >= end) return -1;
+				i = semicolon + 1;
+				break;
+			default:
+				return -1;
+		}
+		return i;
+	}
 	
+	/**
+	 * Combines two hash codes to make a new one.
+	 */
+	public static int combineHashCodes(int hashCode1, int hashCode2) {
+		return hashCode1 * 17 + hashCode2;
+	}
+	
+	/**
+	 * Compares two byte arrays.  
+	 * Returns <0 if a byte in a is less than the corresponding byte in b, or if a is shorter, or if a is null.
+	 * Returns >0 if a byte in a is greater than the corresponding byte in b, or if a is longer, or if b is null.
+	 * Returns 0 if they are equal or both null.
+	 */
+	public static int compare(byte[] a, byte[] b) {
+		if (a == b)
+			return 0;
+		if (a == null)
+			return -1;
+		if (b == null)
+			return 1;
+		int len = Math.min(a.length, b.length);
+		for (int i = 0; i < len; ++i) {
+			int diff = a[i] - b[i];
+			if (diff != 0)
+				return diff;
+		}
+		if (a.length > len)
+			return 1;
+		if (b.length > len)
+			return -1;
+		return 0;
+	}
+	/**
+	 * Compares two strings lexicographically. 
+	 * The comparison is based on the Unicode value of each character in
+	 * the strings. 
+	 *
+	 * @return  the value <code>0</code> if the str1 is equal to str2;
+	 *          a value less than <code>0</code> if str1
+	 *          is lexicographically less than str2; 
+	 *          and a value greater than <code>0</code> if str1 is
+	 *          lexicographically greater than str2.
+	 */
+	public static int compare(char[] str1, char[] str2) {
+		int len1= str1.length;
+		int len2= str2.length;
+		int n= Math.min(len1, len2);
+		int i= 0;
+		while (n-- != 0) {
+			char c1= str1[i];
+			char c2= str2[i++];
+			if (c1 != c2) {
+				return c1 - c2;
+			}
+		}
+		return len1 - len2;
+	}
+
+	/**
+	 * Concatenate two strings with a char in between.
+	 * @see #concat(String, String)
+	 */
+	public static String concat(String s1, char c, String s2) {
+		if (s1 == null) s1 = "null"; //$NON-NLS-1$
+		if (s2 == null) s2 = "null"; //$NON-NLS-1$
+		int l1 = s1.length();
+		int l2 = s2.length();
+		char[] buf = new char[l1 + 1 + l2];
+		s1.getChars(0, l1, buf, 0);
+		buf[l1] = c;
+		s2.getChars(0, l2, buf, l1 + 1);
+		return new String(buf);
+	}
+	
+	/**
+	 * Concatenate two strings.
+	 * Much faster than using +, which:
+	 * 		- creates a StringBuffer,
+	 * 		- which is synchronized,
+	 * 		- of default size, so the resulting char array is
+	 *        often larger than needed.
+	 * This implementation creates an extra char array, since the
+	 * String constructor copies its argument, but there's no way around this.
+	 */
+	public static String concat(String s1, String s2) {
+		if (s1 == null) s1 = "null"; //$NON-NLS-1$
+		if (s2 == null) s2 = "null"; //$NON-NLS-1$
+		int l1 = s1.length();
+		int l2 = s2.length();
+		char[] buf = new char[l1 + l2];
+		s1.getChars(0, l1, buf, 0);
+		s2.getChars(0, l2, buf, l1);
+		return new String(buf);
+	}
+
+	/**
+	 * Concatenate three strings.
+	 * @see #concat(String, String)
+	 */
+	public static String concat(String s1, String s2, String s3) {
+		if (s1 == null) s1 = "null"; //$NON-NLS-1$
+		if (s2 == null) s2 = "null"; //$NON-NLS-1$
+		if (s3 == null) s3 = "null"; //$NON-NLS-1$
+		int l1 = s1.length();
+		int l2 = s2.length();
+		int l3 = s3.length();
+		char[] buf = new char[l1 + l2 + l3];
+		s1.getChars(0, l1, buf, 0);
+		s2.getChars(0, l2, buf, l1);
+		s3.getChars(0, l3, buf, l1 + l2);
+		return new String(buf);
+	}
+	
+	/**
+	 * Converts a type signature from the IBinaryType representation to the DC representation.
+	 */
+	public static String convertTypeSignature(char[] sig) {
+		return new String(sig).replace('/', '.');
+	}
+
+	/**
+	 * Apply the given edit on the given string and return the updated string.
+	 * Return the given string if anything wrong happen while applying the edit.
+	 * 
+	 * @param original the given string
+	 * @param edit the given edit
+	 * 
+	 * @return the updated string
+	 */
+	public final static String editedString(String original, TextEdit edit) {
+		if (edit == null) {
+			return original;
+		}
+		SimpleDocument document = new SimpleDocument(original);
+		try {
+			edit.apply(document, TextEdit.NONE);
+			return document.get();
+		} catch (MalformedTreeException e) {
+			e.printStackTrace();
+		} catch (BadLocationException e) {
+			e.printStackTrace();
+		}
+		return original;
+	}
+
+	/**
+	 * Returns true iff str.toLowerCase().endsWith(end.toLowerCase())
+	 * implementation is not creating extra strings.
+	 */
+	public final static boolean endsWithIgnoreCase(String str, String end) {
+		
+		int strLength = str == null ? 0 : str.length();
+		int endLength = end == null ? 0 : end.length();
+		
+		// return false if the string is smaller than the end.
+		if(endLength > strLength)
+			return false;
+			
+		// return false if any character of the end are
+		// not the same in lower case.
+		for(int i = 1 ; i <= endLength; i++){
+			if(Character.toLowerCase(end.charAt(endLength - i)) != Character.toLowerCase(str.charAt(strLength - i)))
+				return false;
+		}
+		
+		return true;
+	}
+
+	/**
+	 * Compares two arrays using equals() on the elements.
+	 * Either or both arrays may be null.
+	 * Returns true if both are null.
+	 * Returns false if only one is null.
+	 * If both are arrays, returns true iff they have the same length and
+	 * all elements are equal.
+	 */
+	public static boolean equalArraysOrNull(int[] a, int[] b) {
+		if (a == b)
+			return true;
+		if (a == null || b == null)
+			return false;
+		int len = a.length;
+		if (len != b.length)
+			return false;
+		for (int i = 0; i < len; ++i) {
+			if (a[i] != b[i])
+				return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Compares two arrays using equals() on the elements.
+	 * Either or both arrays may be null.
+	 * Returns true if both are null.
+	 * Returns false if only one is null.
+	 * If both are arrays, returns true iff they have the same length and
+	 * all elements compare true with equals.
+	 */
+	public static boolean equalArraysOrNull(Object[] a, Object[] b) {
+		if (a == b)	return true;
+		if (a == null || b == null) return false;
+
+		int len = a.length;
+		if (len != b.length) return false;
+		for (int i = 0; i < len; ++i) {
+			if (a[i] == null) {
+				if (b[i] != null) return false;
+			} else {
+				if (!a[i].equals(b[i])) return false;
+			}
+		}
+		return true;
+	}
+	
+	/**
+	 * Compares two arrays using equals() on the elements.
+	 * The arrays are first sorted.
+	 * Either or both arrays may be null.
+	 * Returns true if both are null.
+	 * Returns false if only one is null.
+	 * If both are arrays, returns true iff they have the same length and
+	 * iff, after sorting both arrays, all elements compare true with equals.
+	 * The original arrays are left untouched.
+	 */
+	public static boolean equalArraysOrNullSortFirst(Comparable[] a, Comparable[] b) {
+		if (a == b)	return true;
+		if (a == null || b == null) return false;
+		int len = a.length;
+		if (len != b.length) return false;
+		if (len >= 2) {  // only need to sort if more than two items
+			a = sortCopy(a);
+			b = sortCopy(b);
+		}
+		for (int i = 0; i < len; ++i) {
+			if (!a[i].equals(b[i])) return false;
+		}
+		return true;
+	}
+	
+	/**
+	 * Compares two String arrays using equals() on the elements.
+	 * The arrays are first sorted.
+	 * Either or both arrays may be null.
+	 * Returns true if both are null.
+	 * Returns false if only one is null.
+	 * If both are arrays, returns true iff they have the same length and
+	 * iff, after sorting both arrays, all elements compare true with equals.
+	 * The original arrays are left untouched.
+	 */
+	public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) {
+		if (a == b)	return true;
+		if (a == null || b == null) return false;
+		int len = a.length;
+		if (len != b.length) return false;
+		if (len >= 2) {  // only need to sort if more than two items
+			a = sortCopy(a);
+			b = sortCopy(b);
+		}
+		for (int i = 0; i < len; ++i) {
+			if (!a[i].equals(b[i])) return false;
+		}
+		return true;
+	}
+	
+	/**
+	 * Compares two objects using equals().
+	 * Either or both array may be null.
+	 * Returns true if both are null.
+	 * Returns false if only one is null.
+	 * Otherwise, return the result of comparing with equals().
+	 */
+	public static boolean equalOrNull(Object a, Object b) {
+		if (a == b) {
+			return true;
+		}
+		if (a == null || b == null) {
+			return false;
+		}
+		return a.equals(b);
+	}
+	
+	/**
+	 * Given a qualified name, extract the last component.
+	 * If the input is not qualified, the same string is answered.
+	 */
+	public static String extractLastName(String qualifiedName) {
+		int i = qualifiedName.lastIndexOf('.');
+		if (i == -1) return qualifiedName;
+		return qualifiedName.substring(i+1);
+	}
+	
+	/**
+	 * Extracts the parameter types from a method signature.
+	 */
+	public static String[] extractParameterTypes(char[] sig) {
+		int count = getParameterCount(sig);
+		String[] result = new String[count];
+		if (count == 0)
+			return result;
+		int i = CharOperation.indexOf('(', sig) + 1;
+		count = 0;
+		int len = sig.length;
+		int start = i;
+		for (;;) {
+			if (i == len)
+				break;
+			char c = sig[i];
+			if (c == ')')
+				break;
+			if (c == '[') {
+				++i;
+			} else
+				if (c == 'L') {
+					i = CharOperation.indexOf(';', sig, i + 1) + 1;
+					Assert.isTrue(i != 0);
+					result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
+					start = i;
+				} else {
+					++i;
+					result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
+					start = i;
+				}
+		}
+		return result;
+	}
+
+	/**
+	 * Extracts the return type from a method signature.
+	 */
+	public static String extractReturnType(String sig) {
+		int i = sig.lastIndexOf(')');
+		Assert.isTrue(i != -1);
+		return sig.substring(i+1);	
+	}
+	private static IFile findFirstClassFile(IFolder folder) {
+		try {
+			IResource[] members = folder.members();
+			for (int i = 0, max = members.length; i < max; i++) {
+				IResource member = members[i];
+				if (member.getType() == IResource.FOLDER) {
+					return findFirstClassFile((IFolder)member);
+				} else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(member.getName())) {
+					return (IFile) member;
+				}
+			}
+		} catch (CoreException e) {
+			// ignore
+		}
+		return null;
+	}
+	
+	/**
+	 * Finds the first line separator used by the given text.
+	 *
+	 * @return </code>"\n"</code> or </code>"\r"</code> or  </code>"\r\n"</code>,
+	 *			or <code>null</code> if none found
+	 */
+	public static String findLineSeparator(char[] text) {
+		// find the first line separator
+		int length = text.length;
+		if (length > 0) {
+			char nextChar = text[0];
+			for (int i = 0; i < length; i++) {
+				char currentChar = nextChar;
+				nextChar = i < length-1 ? text[i+1] : ' ';
+				switch (currentChar) {
+					case '\n': return "\n"; //$NON-NLS-1$
+					case '\r': return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+		}
+		// not found
+		return null;
+	}
+
+	/**
+	 * Get the jdk level of this root.
+	 * The value can be:
+	 * <ul>
+	 * <li>major<<16 + minor : see predefined constants on ClassFileConstants </li>
+	 * <li><code>0</null> if the root is a source package fragment root or if a Java model exception occured</li>
+	 * </ul>
+	 * Returns the jdk level
+	 */
+	public static long getJdkLevel(Object targetLibrary) {
+		try {
+				ClassFileReader reader = null;
+				if (targetLibrary instanceof IFolder) {
+					IFile classFile = findFirstClassFile((IFolder) targetLibrary); // only internal classfolders are allowed
+					if (classFile != null) {
+						byte[] bytes = Util.getResourceContentsAsByteArray(classFile);
+						IPath location = classFile.getLocation();
+						reader = new ClassFileReader(bytes, location == null ? null : location.toString().toCharArray());
+					}
+				} else {
+					// root is a jar file or a zip file
+					ZipFile jar = null;
+					try {
+						IPath path = null;
+						if (targetLibrary instanceof IResource) {
+							path = ((IResource)targetLibrary).getLocation();
+						} else if (targetLibrary instanceof File){
+							File f = (File) targetLibrary;
+							if (!f.isDirectory()) {
+								path = new Path(((File)targetLibrary).getPath());
+							}
+						}
+						if (path != null) {
+							jar = JavaModelManager.getJavaModelManager().getZipFile(path);
+							for (Enumeration e= jar.entries(); e.hasMoreElements();) {
+								ZipEntry member= (ZipEntry) e.nextElement();
+								String entryName= member.getName();
+								if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(entryName)) {
+									reader = ClassFileReader.read(jar, entryName);
+									break;
+								}
+							}
+						}
+					} catch (CoreException e) {
+						// ignore
+					} finally {
+						JavaModelManager.getJavaModelManager().closeZipFile(jar);
+					}
+				}
+				if (reader != null) {
+					return reader.getVersion();
+				}
+		} catch(JavaModelException e) {
+			// ignore
+		} catch(ClassFormatException e) {
+			// ignore
+		} catch(IOException e) {
+			// ignore
+		}
+		return 0;
+	}
+	
+	/**
+	 * Returns the line separator used by the given buffer.
+	 * Uses the given text if none found.
+	 *
+	 * @return </code>"\n"</code> or </code>"\r"</code> or  </code>"\r\n"</code>
+	 */
+	private static String getLineSeparator(char[] text, char[] buffer) {
+		// search in this buffer's contents first
+		String lineSeparator = findLineSeparator(buffer);
+		if (lineSeparator == null) {
+			// search in the given text
+			lineSeparator = findLineSeparator(text);
+			if (lineSeparator == null) {
+				// default to system line separator
+				return org.eclipse.jdt.internal.compiler.util.Util.LINE_SEPARATOR;
+			}
+		}
+		return lineSeparator;
+	}
+		
+	/**
+	 * Returns the number of parameter types in a method signature.
+	 */
+	public static int getParameterCount(char[] sig) {
+		int i = CharOperation.indexOf('(', sig) + 1;
+		Assert.isTrue(i != 0);
+		int count = 0;
+		int len = sig.length;
+		for (;;) {
+			if (i == len)
+				break;
+			char c = sig[i];
+			if (c == ')')
+				break;
+			if (c == '[') {
+				++i;
+			} else
+				if (c == 'L') {
+					++count;
+					i = CharOperation.indexOf(';', sig, i + 1) + 1;
+					Assert.isTrue(i != 0);
+				} else {
+					++count;
+					++i;
+				}
+		}
+		return count;
+	}
+	
+	/**
+	 * Put all the arguments in one String.
+	 */
+	public static String getProblemArgumentsForMarker(String[] arguments){
+		StringBuffer args = new StringBuffer(10);
+		
+		args.append(arguments.length);
+		args.append(':');
+		
+			
+		for (int j = 0; j < arguments.length; j++) {
+			if(j != 0)
+				args.append(ARGUMENTS_DELIMITER);
+			
+			if(arguments[j].length() == 0) {
+				args.append(EMPTY_ARGUMENT);
+			} else {			
+				args.append(arguments[j]);
+			}
+		}
+		
+		return args.toString();
+	}
+	
+	/**
+	 * Separate all the arguments of a String made by getProblemArgumentsForMarker
+	 */
+	public static String[] getProblemArgumentsFromMarker(String argumentsString){
+		if (argumentsString == null) return null;
+		int index = argumentsString.indexOf(':');
+		if(index == -1)
+			return null;
+		
+		int length = argumentsString.length();
+		int numberOfArg;
+		try{
+			numberOfArg = Integer.parseInt(argumentsString.substring(0 , index));
+		} catch (NumberFormatException e) {
+			return null;
+		}
+		argumentsString = argumentsString.substring(index + 1, length);
+		
+		String[] args = new String[length];
+		int count = 0;
+		
+		StringTokenizer tokenizer = new StringTokenizer(argumentsString, ARGUMENTS_DELIMITER);
+		while(tokenizer.hasMoreTokens()) {
+			String argument = tokenizer.nextToken();
+			if(argument.equals(EMPTY_ARGUMENT))
+				argument = "";  //$NON-NLS-1$
+			args[count++] = argument;
+		}
+		
+		if(count != numberOfArg)
+			return null;
+		
+		System.arraycopy(args, 0, args = new String[count], 0, count);
+		return args;
+	}
+	
+	/**
+	 * Returns the given file's contents as a byte array.
+	 */
+	public static byte[] getResourceContentsAsByteArray(IFile file) throws JavaModelException {
+		InputStream stream= null;
+		try {
+			stream = new BufferedInputStream(file.getContents(true));
+		} catch (CoreException e) {
+			throw new JavaModelException(e);
+		}
+		try {
+			return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsByteArray(stream, -1);
+		} catch (IOException e) {
+			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+		} finally {
+			try {
+				stream.close();
+			} catch (IOException e) {
+				// ignore
+			}
+		}
+	}
+	
+	/**
+	 * Returns the given file's contents as a character array.
+	 */
+	public static char[] getResourceContentsAsCharArray(IFile file) throws JavaModelException {
+		String encoding = JavaCore.create(file.getProject()).getOption(JavaCore.CORE_ENCODING, true);
+		return getResourceContentsAsCharArray(file, encoding);
+	}
+
+	public static char[] getResourceContentsAsCharArray(IFile file, String encoding) throws JavaModelException {
+		InputStream stream= null;
+		try {
+			stream = new BufferedInputStream(file.getContents(true));
+		} catch (CoreException e) {
+			throw new JavaModelException(e, IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST);
+		}
+		try {
+			return org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, -1, encoding);
+		} catch (IOException e) {
+			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+		} finally {
+			try {
+				stream.close();
+			} catch (IOException e) {
+				// ignore
+			}
+		}
+	}
+	
+	/**
+	 * Returns a trimmed version the simples names returned by Signature.
+	 */
+	public static String[] getTrimmedSimpleNames(String name) {
+		String[] result = Signature.getSimpleNames(name);
+		if (result == null) return null;
+		for (int i = 0, length = result.length; i < length; i++) {
+			result[i] = result[i].trim();
+		}
+		return result;
+	}
+	
+		/*
+	 * Returns the index of the first argument paths which is strictly enclosing the path to check
+	 */
+	public static int indexOfEnclosingPath(IPath checkedPath, IPath[] paths, int pathCount) {
+
+		for (int i = 0; i < pathCount; i++){
+			if (paths[i].equals(checkedPath)) continue;
+			if (paths[i].isPrefixOf(checkedPath)) return i;
+		}
+		return -1;
+	}
+	
+	/*
+	 * Returns the index of the first argument paths which is equal to the path to check
+	 */
+	public static int indexOfMatchingPath(IPath checkedPath, IPath[] paths, int pathCount) {
+
+		for (int i = 0; i < pathCount; i++){
+			if (paths[i].equals(checkedPath)) return i;
+		}
+		return -1;
+	}
+
+	/*
+	 * Returns the index of the first argument paths which is strictly nested inside the path to check
+	 */
+	public static int indexOfNestedPath(IPath checkedPath, IPath[] paths, int pathCount) {
+
+		for (int i = 0; i < pathCount; i++){
+			if (checkedPath.equals(paths[i])) continue;
+			if (checkedPath.isPrefixOf(paths[i])) return i;
+		}
+		return -1;
+	}
+
+	/*
+	 * Returns whether the given java element is exluded from its root's classpath.
+	 */
+	public static final boolean isExcluded(IJavaElement element) {
+		int elementType = element.getElementType();
+		switch (elementType) {
+			case IJavaElement.PACKAGE_FRAGMENT:
+				PackageFragmentRoot root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+				IResource resource = element.getResource();
+				return resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars());
+			case IJavaElement.COMPILATION_UNIT:
+				root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+				resource = element.getResource();
+				if (resource != null && Util.isExcluded(resource, root.fullExclusionPatternChars()))
+					return true;
+				return isExcluded(element.getParent());
+			default:
+				IJavaElement cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
+				return cu != null && isExcluded(cu);
+		}
+	}
+	/*
+	 * Returns whether the given resource path matches one of the exclusion
+	 * patterns.
+	 * 
+	 * @see IClasspathEntry#getExclusionPatterns
+	 */
+	public final static boolean isExcluded(IPath resourcePath, char[][] exclusionPatterns) {
+		if (exclusionPatterns == null) return false;
+		char[] path = resourcePath.toString().toCharArray();
+		for (int i = 0, length = exclusionPatterns.length; i < length; i++)
+			if (CharOperation.pathMatch(exclusionPatterns[i], path, true, '/'))
+				return true;
+		return false;
+	}	
+	
+	/*
+	 * Returns whether the given resource matches one of the exclusion patterns.
+	 * 
+	 * @see IClasspathEntry#getExclusionPatterns
+	 */
+	public final static boolean isExcluded(IResource resource, char[][] exclusionPatterns) {
+		IPath path = resource.getFullPath();
+		// ensure that folders are only excluded if all of their children are excluded
+		if (resource.getType() == IResource.FOLDER)
+			path = path.append("*"); //$NON-NLS-1$
+		return isExcluded(path, exclusionPatterns);
+	}
+
+	/**
+	 * Validate the given .class file name.
+	 * A .class file name must obey the following rules:
+	 * <ul>
+	 * <li> it must not be null
+	 * <li> it must include the <code>".class"</code> suffix
+	 * <li> its prefix must be a valid identifier
+	 * </ul>
+	 * </p>
+	 * @param name the name of a .class file
+	 * @return a status object with code <code>IStatus.OK</code> if
+	 *		the given name is valid as a .class file name, otherwise a status 
+	 *		object indicating what is wrong with the name
+	 */
+	public static boolean isValidClassFileName(String name) {
+		return JavaConventions.validateClassFileName(name).getSeverity() != IStatus.ERROR;
+	}
+
+	/**
+	 * Validate the given compilation unit name.
+	 * A compilation unit name must obey the following rules:
+	 * <ul>
+	 * <li> it must not be null
+	 * <li> it must include the <code>".java"</code> suffix
+	 * <li> its prefix must be a valid identifier
+	 * </ul>
+	 * </p>
+	 * @param name the name of a compilation unit
+	 * @return a status object with code <code>IStatus.OK</code> if
+	 *		the given name is valid as a compilation unit name, otherwise a status 
+	 *		object indicating what is wrong with the name
+	 */
+	public static boolean isValidCompilationUnitName(String name) {
+		return JavaConventions.validateCompilationUnitName(name).getSeverity() != IStatus.ERROR;
+	}
+	
+	/**
+	 * Returns true if the given folder name is valid for a package,
+	 * false if it is not.
+	 */
+	public static boolean isValidFolderNameForPackage(String folderName) {
+		return JavaConventions.validateIdentifier(folderName).getSeverity() != IStatus.ERROR;
+	}	
+
+	/**
+	 * Returns true if the given method signature is valid,
+	 * false if it is not.
+	 */
+	public static boolean isValidMethodSignature(String sig) {
+		int len = sig.length();
+		if (len == 0) return false;
+		int i = 0;
+		char c = sig.charAt(i++);
+		if (c != '(') return false;
+		if (i >= len) return false;
+		while (sig.charAt(i) != ')') {
+			// Void is not allowed as a parameter type.
+			i = checkTypeSignature(sig, i, len, false);
+			if (i == -1) return false;
+			if (i >= len) return false;
+		}
+		++i;
+		i = checkTypeSignature(sig, i, len, true);
+		return i == len;
+	}
+	
+	/**
+	 * Returns true if the given type signature is valid,
+	 * false if it is not.
+	 */
+	public static boolean isValidTypeSignature(String sig, boolean allowVoid) {
+		int len = sig.length();
+		return checkTypeSignature(sig, 0, len, allowVoid) == len;
+	}
+
+	/*
+	 * Add a log entry
+	 */
+	public static void log(Throwable e, String message) {
+		Throwable nestedException;
+		if (e instanceof JavaModelException 
+				&& (nestedException = ((JavaModelException)e).getException()) != null) {
+			e = nestedException;
+		}
+		IStatus status= new Status(
+			IStatus.ERROR, 
+			JavaCore.getPlugin().getDescriptor().getUniqueIdentifier(), 
+			IStatus.ERROR, 
+			message, 
+			e); 
+		JavaCore.getPlugin().getLog().log(status);
+	}	
+	
+	/**
+	 * Normalizes the cariage returns in the given text.
+	 * They are all changed  to use the given buffer's line separator.
+	 */
+	public static char[] normalizeCRs(char[] text, char[] buffer) {
+		CharArrayBuffer result = new CharArrayBuffer();
+		int lineStart = 0;
+		int length = text.length;
+		if (length == 0) return text;
+		String lineSeparator = getLineSeparator(text, buffer);
+		char nextChar = text[0];
+		for (int i = 0; i < length; i++) {
+			char currentChar = nextChar;
+			nextChar = i < length-1 ? text[i+1] : ' ';
+			switch (currentChar) {
+				case '\n':
+					int lineLength = i-lineStart;
+					char[] line = new char[lineLength];
+					System.arraycopy(text, lineStart, line, 0, lineLength);
+					result.append(line);
+					result.append(lineSeparator);
+					lineStart = i+1;
+					break;
+				case '\r':
+					lineLength = i-lineStart;
+					if (lineLength >= 0) {
+						line = new char[lineLength];
+						System.arraycopy(text, lineStart, line, 0, lineLength);
+						result.append(line);
+						result.append(lineSeparator);
+						if (nextChar == '\n') {
+							nextChar = ' ';
+							lineStart = i+2;
+						} else {
+							// when line separator are mixed in the same file
+							// \r might not be followed by a \n. If not, we should increment
+							// lineStart by one and not by two.
+							lineStart = i+1;
+						}
+					} else {
+						// when line separator are mixed in the same file
+						// we need to prevent NegativeArraySizeException
+						lineStart = i+1;
+					}
+					break;
+			}
+		}
+		char[] lastLine;
+		if (lineStart > 0) {
+			int lastLineLength = length-lineStart;
+			if (lastLineLength > 0) {
+				lastLine = new char[lastLineLength];
+				System.arraycopy(text, lineStart, lastLine, 0, lastLineLength);
+				result.append(lastLine);
+			}
+			return result.getContents();
+		} else {
+			return text;
+		}
+	}
+
+	/**
+	 * Normalizes the cariage returns in the given text.
+	 * They are all changed  to use given buffer's line sepatator.
+	 */
+	public static String normalizeCRs(String text, String buffer) {
+		return new String(normalizeCRs(text.toCharArray(), buffer.toCharArray()));
+	}
+
+	/**
+	 * Converts the given relative path into a package name.
+	 * Returns null if the path is not a valid package name.
+	 */
+	public static String packageName(IPath pkgPath) {
+		StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
+		for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) {
+			String segment = pkgPath.segment(j);
+			if (!isValidFolderNameForPackage(segment)) {
+				return null;
+			}
+			pkgName.append(segment);
+			if (j < pkgPath.segmentCount() - 1) {
+				pkgName.append("." ); //$NON-NLS-1$
+			}
+		}
+		return pkgName.toString();
+	}
+
+	/**
+	 * Returns the length of the common prefix between s1 and s2.
+	 */
+	public static int prefixLength(char[] s1, char[] s2) {
+		int len= 0;
+		int max= Math.min(s1.length, s2.length);
+		for (int i= 0; i < max && s1[i] == s2[i]; ++i)
+			++len;
+		return len;
+	}
+	/**
+	 * Returns the length of the common prefix between s1 and s2.
+	 */
+	public static int prefixLength(String s1, String s2) {
+		int len= 0;
+		int max= Math.min(s1.length(), s2.length());
+		for (int i= 0; i < max && s1.charAt(i) == s2.charAt(i); ++i)
+			++len;
+		return len;
+	}
+	private static void quickSort(char[][] list, int left, int right) {
+		int original_left= left;
+		int original_right= right;
+		char[] mid= list[(left + right) / 2];
+		do {
+			while (compare(list[left], mid) < 0) {
+				left++;
+			}
+			while (compare(mid, list[right]) < 0) {
+				right--;
+			}
+			if (left <= right) {
+				char[] tmp= list[left];
+				list[left]= list[right];
+				list[right]= tmp;
+				left++;
+				right--;
+			}
+		} while (left <= right);
+		if (original_left < right) {
+			quickSort(list, original_left, right);
+		}
+		if (left < original_right) {
+			quickSort(list, left, original_right);
+		}
+	}
+
+	/**
+	 * Sort the comparable objects in the given collection.
+	 */
+	private static void quickSort(Comparable[] sortedCollection, int left, int right) {
+		int original_left = left;
+		int original_right = right;
+		Comparable mid = sortedCollection[ (left + right) / 2];
+		do {
+			while (sortedCollection[left].compareTo(mid) < 0) {
+				left++;
+			}
+			while (mid.compareTo(sortedCollection[right]) < 0) {
+				right--;
+			}
+			if (left <= right) {
+				Comparable tmp = sortedCollection[left];
+				sortedCollection[left] = sortedCollection[right];
+				sortedCollection[right] = tmp;
+				left++;
+				right--;
+			}
+		} while (left <= right);
+		if (original_left < right) {
+			quickSort(sortedCollection, original_left, right);
+		}
+		if (left < original_right) {
+			quickSort(sortedCollection, left, original_right);
+		}
+	}
+	private static void quickSort(IndexedFile[] list, int left, int right) {
+		int original_left= left;
+		int original_right= right;
+		String mid= list[(left + right) / 2].path;
+		do {
+			while (list[left].path.compareTo(mid) < 0) {
+				left++;
+			}
+			while (mid.compareTo(list[right].path) < 0) {
+				right--;
+			}
+			if (left <= right) {
+				IndexedFile tmp= list[left];
+				list[left]= list[right];
+				list[right]= tmp;
+				left++;
+				right--;
+			}
+		} while (left <= right);
+		if (original_left < right) {
+			quickSort(list, original_left, right);
+		}
+		if (left < original_right) {
+			quickSort(list, left, original_right);
+		}
+	}
+	private static void quickSort(int[] list, int left, int right) {
+		int original_left= left;
+		int original_right= right;
+		int mid= list[(left + right) / 2];
+		do {
+			while (list[left] < mid) {
+				left++;
+			}
+			while (mid < list[right]) {
+				right--;
+			}
+			if (left <= right) {
+				int tmp= list[left];
+				list[left]= list[right];
+				list[right]= tmp;
+				left++;
+				right--;
+			}
+		} while (left <= right);
+		if (original_left < right) {
+			quickSort(list, original_left, right);
+		}
+		if (left < original_right) {
+			quickSort(list, left, original_right);
+		}
+	}
+
+	/**
+	 * Sort the objects in the given collection using the given comparer.
+	 */
+	private static void quickSort(Object[] sortedCollection, int left, int right, Comparer comparer) {
+		int original_left = left;
+		int original_right = right;
+		Object mid = sortedCollection[ (left + right) / 2];
+		do {
+			while (comparer.compare(sortedCollection[left], mid) < 0) {
+				left++;
+			}
+			while (comparer.compare(mid, sortedCollection[right]) < 0) {
+				right--;
+			}
+			if (left <= right) {
+				Object tmp = sortedCollection[left];
+				sortedCollection[left] = sortedCollection[right];
+				sortedCollection[right] = tmp;
+				left++;
+				right--;
+			}
+		} while (left <= right);
+		if (original_left < right) {
+			quickSort(sortedCollection, original_left, right, comparer);
+		}
+		if (left < original_right) {
+			quickSort(sortedCollection, left, original_right, comparer);
+		}
+	}
+
+	/**
+	 * Sort the objects in the given collection using the given sort order.
+	 */
+	private static void quickSort(Object[] sortedCollection, int left, int right, int[] sortOrder) {
+		int original_left = left;
+		int original_right = right;
+		int mid = sortOrder[ (left + right) / 2];
+		do {
+			while (sortOrder[left] < mid) {
+				left++;
+			}
+			while (mid < sortOrder[right]) {
+				right--;
+			}
+			if (left <= right) {
+				Object tmp = sortedCollection[left];
+				sortedCollection[left] = sortedCollection[right];
+				sortedCollection[right] = tmp;
+				int tmp2 = sortOrder[left];
+				sortOrder[left] = sortOrder[right];
+				sortOrder[right] = tmp2;
+				left++;
+				right--;
+			}
+		} while (left <= right);
+		if (original_left < right) {
+			quickSort(sortedCollection, original_left, right, sortOrder);
+		}
+		if (left < original_right) {
+			quickSort(sortedCollection, left, original_right, sortOrder);
+		}
+	}
+
+	/**
+	 * Sort the strings in the given collection.
+	 */
+	private static void quickSort(String[] sortedCollection, int left, int right) {
+		int original_left = left;
+		int original_right = right;
+		String mid = sortedCollection[ (left + right) / 2];
+		do {
+			while (sortedCollection[left].compareTo(mid) < 0) {
+				left++;
+			}
+			while (mid.compareTo(sortedCollection[right]) < 0) {
+				right--;
+			}
+			if (left <= right) {
+				String tmp = sortedCollection[left];
+				sortedCollection[left] = sortedCollection[right];
+				sortedCollection[right] = tmp;
+				left++;
+				right--;
+			}
+		} while (left <= right);
+		if (original_left < right) {
+			quickSort(sortedCollection, original_left, right);
+		}
+		if (left < original_right) {
+			quickSort(sortedCollection, left, original_right);
+		}
+	}
+	private static void quickSort(WordEntry[] list, int left, int right) {
+		int original_left= left;
+		int original_right= right;
+		char[] mid= list[(left + right) / 2].fWord;
+		do {
+			while (compare(list[left].fWord, mid) < 0) {
+				left++;
+			}
+			while (compare(mid, list[right].fWord) < 0) {
+				right--;
+			}
+			if (left <= right) {
+				WordEntry tmp= list[left];
+				list[left]= list[right];
+				list[right]= tmp;
+				left++;
+				right--;
+			}
+		} while (left <= right);
+		if (original_left < right) {
+			quickSort(list, original_left, right);
+		}
+		if (left < original_right) {
+			quickSort(list, left, original_right);
+		}
+	}
+
+	/**
+	 * Sort the strings in the given collection in reverse alphabetical order.
+	 */
+	private static void quickSortReverse(String[] sortedCollection, int left, int right) {
+		int original_left = left;
+		int original_right = right;
+		String mid = sortedCollection[ (left + right) / 2];
+		do {
+			while (sortedCollection[left].compareTo(mid) > 0) {
+				left++;
+			}
+			while (mid.compareTo(sortedCollection[right]) > 0) {
+				right--;
+			}
+			if (left <= right) {
+				String tmp = sortedCollection[left];
+				sortedCollection[left] = sortedCollection[right];
+				sortedCollection[right] = tmp;
+				left++;
+				right--;
+			}
+		} while (left <= right);
+		if (original_left < right) {
+			quickSortReverse(sortedCollection, original_left, right);
+		}
+		if (left < original_right) {
+			quickSortReverse(sortedCollection, left, original_right);
+		}
+	}
+	/**
+	 * Reads in a string from the specified data input stream. The 
+	 * string has been encoded using a modified UTF-8 format. 
+	 * <p>
+	 * The first two bytes are read as if by 
+	 * <code>readUnsignedShort</code>. This value gives the number of 
+	 * following bytes that are in the encoded string, not
+	 * the length of the resulting string. The following bytes are then 
+	 * interpreted as bytes encoding characters in the UTF-8 format 
+	 * and are converted into characters. 
+	 * <p>
+	 * This method blocks until all the bytes are read, the end of the 
+	 * stream is detected, or an exception is thrown. 
+	 *
+	 * @param      in   a data input stream.
+	 * @return     a Unicode string.
+	 * @exception  EOFException            if the input stream reaches the end
+	 *               before all the bytes.
+	 * @exception  IOException             if an I/O error occurs.
+	 * @exception  UTFDataFormatException  if the bytes do not represent a
+	 *               valid UTF-8 encoding of a Unicode string.
+	 * @see        java.io.DataInputStream#readUnsignedShort()
+	 */
+	public final static char[] readUTF(DataInput in) throws IOException {
+		int utflen= in.readUnsignedShort();
+		char str[]= new char[utflen];
+		int count= 0;
+		int strlen= 0;
+		while (count < utflen) {
+			int c= in.readUnsignedByte();
+			int char2, char3;
+			switch (c >> 4) {
+				case 0 :
+				case 1 :
+				case 2 :
+				case 3 :
+				case 4 :
+				case 5 :
+				case 6 :
+				case 7 :
+					// 0xxxxxxx
+					count++;
+					str[strlen++]= (char) c;
+					break;
+				case 12 :
+				case 13 :
+					// 110x xxxx   10xx xxxx
+					count += 2;
+					if (count > utflen)
+						throw new UTFDataFormatException();
+					char2= in.readUnsignedByte();
+					if ((char2 & 0xC0) != 0x80)
+						throw new UTFDataFormatException();
+					str[strlen++]= (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
+					break;
+				case 14 :
+					// 1110 xxxx  10xx xxxx  10xx xxxx
+					count += 3;
+					if (count > utflen)
+						throw new UTFDataFormatException();
+					char2= in.readUnsignedByte();
+					char3= in.readUnsignedByte();
+					if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
+						throw new UTFDataFormatException();
+					str[strlen++]= (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
+					break;
+				default :
+					// 10xx xxxx,  1111 xxxx
+					throw new UTFDataFormatException();
+			}
+		}
+		if (strlen < utflen) {
+			System.arraycopy(str, 0, str= new char[strlen], 0, strlen);
+		}
+		return str;
+	}
+
+	/**
+	 * Creates a NLS catalog for the given locale.
+	 */
+	public static void relocalize() {
+		try {
+			bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
+		} catch(MissingResourceException e) {
+			System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+			throw e;
+		}
+	}
+	public static void sort(char[][] list) {
+		if (list.length > 1)
+			quickSort(list, 0, list.length - 1);
+	}
+
+	/**
+	 * Sorts an array of Comparable objects in place.
+	 */
+	public static void sort(Comparable[] objects) {
+		if (objects.length > 1)
+			quickSort(objects, 0, objects.length - 1);
+	}
+	public static void sort(IndexedFile[] list) {
+		if (list.length > 1)
+			quickSort(list, 0, list.length - 1);
+	}
+	public static void sort(int[] list) {
+		if (list.length > 1)
+			quickSort(list, 0, list.length - 1);
+	}
+
+	/**
+	 * Sorts an array of objects in place.
+	 * The given comparer compares pairs of items.
+	 */
+	public static void sort(Object[] objects, Comparer comparer) {
+		if (objects.length > 1)
+			quickSort(objects, 0, objects.length - 1, comparer);
+	}
+
+	/**
+	 * Sorts an array of objects in place, using the sort order given for each item.
+	 */
+	public static void sort(Object[] objects, int[] sortOrder) {
+		if (objects.length > 1)
+			quickSort(objects, 0, objects.length - 1, sortOrder);
+	}
+
+	/**
+	 * Sorts an array of strings in place using quicksort.
+	 */
+	public static void sort(String[] strings) {
+		if (strings.length > 1)
+			quickSort(strings, 0, strings.length - 1);
+	}
+	public static void sort(WordEntry[] list) {
+		if (list.length > 1)
+			quickSort(list, 0, list.length - 1);
+	}
+
+	/**
+	 * Sorts an array of Comparable objects, returning a new array
+	 * with the sorted items.  The original array is left untouched.
+	 */
+	public static Comparable[] sortCopy(Comparable[] objects) {
+		int len = objects.length;
+		Comparable[] copy = new Comparable[len];
+		System.arraycopy(objects, 0, copy, 0, len);
+		sort(copy);
+		return copy;
+	}
+
+	/**
+	 * Sorts an array of Strings, returning a new array
+	 * with the sorted items.  The original array is left untouched.
+	 */
+	public static Object[] sortCopy(Object[] objects, Comparer comparer) {
+		int len = objects.length;
+		Object[] copy = new Object[len];
+		System.arraycopy(objects, 0, copy, 0, len);
+		sort(copy, comparer);
+		return copy;
+	}
+
+	/**
+	 * Sorts an array of Strings, returning a new array
+	 * with the sorted items.  The original array is left untouched.
+	 */
+	public static String[] sortCopy(String[] objects) {
+		int len = objects.length;
+		String[] copy = new String[len];
+		System.arraycopy(objects, 0, copy, 0, len);
+		sort(copy);
+		return copy;
+	}
+
+	/**
+	 * Sorts an array of strings in place using quicksort
+	 * in reverse alphabetical order.
+	 */
+	public static void sortReverseOrder(String[] strings) {
+		if (strings.length > 1)
+			quickSortReverse(strings, 0, strings.length - 1);
+	}
+
+	/**
+	 * Converts a String[] to char[][].
+	 */
+	public static char[][] toCharArrays(String[] a) {
+		int len = a.length;
+		char[][] result = new char[len][];
+		for (int i = 0; i < len; ++i) {
+			result[i] = toChars(a[i]);
+		}
+		return result;
+	}
+
+	/**
+	 * Converts a String to char[].
+	 */
+	public static char[] toChars(String s) {
+		int len = s.length();
+		char[] chars = new char[len];
+		s.getChars(0, len, chars, 0);
+		return chars;
+	}
+
+	/**
+	 * Converts a String to char[][], where segments are separate by '.'.
+	 */
+	public static char[][] toCompoundChars(String s) {
+		int len = s.length();
+		if (len == 0) {
+			return CharOperation.NO_CHAR_CHAR;
+		}
+		int segCount = 1;
+		for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) {
+			++segCount;
+		}
+		char[][] segs = new char[segCount][];
+		int start = 0;
+		for (int i = 0; i < segCount; ++i) {
+			int dot = s.indexOf('.', start);
+			int end = (dot == -1 ? s.length() : dot);
+			segs[i] = new char[end - start];
+			s.getChars(start, end, segs[i], 0);
+			start = end + 1;
+		}
+		return segs;
+	}
+
+	/**
+	 * Converts a char[] to String.
+	 */
+	public static String toString(char[] c) {
+		return new String(c);
+	}
+
+	/**
+	 * Converts a char[][] to String, where segments are separated by '.'.
+	 */
+	public static String toString(char[][] c) {
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0, max = c.length; i < max; ++i) {
+			if (i != 0) sb.append('.');
+			sb.append(c[i]);
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * Converts a char[][] and a char[] to String, where segments are separated by '.'.
+	 */
+	public static String toString(char[][] c, char[] d) {
+		if (c == null) return new String(d);
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0, max = c.length; i < max; ++i) {
+			sb.append(c[i]);
+			sb.append('.');
+		}
+		sb.append(d);
+		return sb.toString();
+	}
+	
+	/*
+	 * Returns the unresolved type parameter signatures of the given method
+	 * e.g. {"QString;", "[int", "[[Qjava.util.Vector;"}
+	 */
+	public static String[] typeParameterSignatures(AbstractMethodDeclaration method) {
+		Argument[] args = method.arguments;
+		if (args != null) {
+			int length = args.length;
+			String[] signatures = new String[length];
+			for (int i = 0; i < args.length; i++) {
+				Argument arg = args[i];
+				signatures[i] = typeSignature(arg.type);
+			}
+			return signatures;
+		}
+		return new String[0];
+	}
+
+	/*
+	 * Returns the unresolved type signature of the given type reference, 
+	 * e.g. "QString;", "[int", "[[Qjava.util.Vector;"
+	 */
+	public static String typeSignature(TypeReference type) {
+		char[][] compoundName = type.getTypeName();
+		char[] typeName =CharOperation.concatWith(compoundName, '.');
+		String signature = Signature.createTypeSignature(typeName, false/*don't resolve*/);
+		int dimensions = type.dimensions();
+		if (dimensions > 0) {
+			signature =  Signature.createArraySignature(signature, dimensions);
+		}
+		return signature;
+	}
+
+	/**
+	 * Asserts that the given method signature is valid.
+	 */
+	public static void validateMethodSignature(String sig) {
+		Assert.isTrue(isValidMethodSignature(sig));
+	}
+
+	/**
+	 * Asserts that the given type signature is valid.
+	 */
+	public static void validateTypeSignature(String sig, boolean allowVoid) {
+		Assert.isTrue(isValidTypeSignature(sig, allowVoid));
+	}
+	/**
+	 * Writes a string to the given output stream using UTF-8 
+	 * encoding in a machine-independent manner. 
+	 * <p>
+	 * First, two bytes are written to the output stream as if by the 
+	 * <code>writeShort</code> method giving the number of bytes to 
+	 * follow. This value is the number of bytes actually written out, 
+	 * not the length of the string. Following the length, each character 
+	 * of the string is output, in sequence, using the UTF-8 encoding 
+	 * for the character. 
+	 *
+	 * @param      str   a string to be written.
+	 * @exception  IOException  if an I/O error occurs.
+	 * @since      JDK1.0
+	 */
+	public static void writeUTF(OutputStream out, char[] str) throws IOException {
+		int strlen= str.length;
+		int utflen= 0;
+		for (int i= 0; i < strlen; i++) {
+			int c= str[i];
+			if ((c >= 0x0001) && (c <= 0x007F)) {
+				utflen++;
+			} else if (c > 0x07FF) {
+				utflen += 3;
+			} else {
+				utflen += 2;
+			}
+		}
+		if (utflen > 65535)
+			throw new UTFDataFormatException();
+		out.write((utflen >>> 8) & 0xFF);
+		out.write((utflen >>> 0) & 0xFF);
+		for (int i= 0; i < strlen; i++) {
+			int c= str[i];
+			if ((c >= 0x0001) && (c <= 0x007F)) {
+				out.write(c);
+			} else if (c > 0x07FF) {
+				out.write(0xE0 | ((c >> 12) & 0x0F));
+				out.write(0x80 | ((c >> 6) & 0x3F));
+				out.write(0x80 | ((c >> 0) & 0x3F));
+			} else {
+				out.write(0xC0 | ((c >> 6) & 0x1F));
+				out.write(0x80 | ((c >> 0) & 0x3F));
+			}
+		}
+	}	
 }
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
index 6983661..b6021e2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
@@ -8,6 +8,219 @@
 # Contributors:
 #     IBM Corporation - initial API and implementation
 ###############################################################################
+
+### JavaModel messages.
+
+### hierarchy
+hierarchy.nullProject = Project argument cannot be null.
+hierarchy.nullRegion = Region cannot be null.
+hierarchy.nullFocusType = Type focus cannot be null.
+hierarchy.creating = Creating type hierarchy...
+hierarchy.creatingOnType = Creating type hierarchy on {0}...
+
+### java element
+element.doesNotExist = {0} does not exist.
+element.invalidClassFileName = Class file name must end with .class.
+element.reconciling = Reconciling...
+element.attachingSource = Attaching source...
+element.invalidType = Type is not one of the defined constants.
+element.invalidResourceForProject = Illegal argument - must be one of IProject, IFolder, or IFile
+element.nullName = Name cannot be null.
+element.nullType = Type cannot be null.
+element.illegalParent = Illegal parent argument.
+sourcetype.invalidName = The source type has an invalid name: {0}
+
+### java model operations
+operation.needElements = Operation requires one or more elements.
+operation.needName = Operation requires a name.
+operation.needPath = Operation requires a path.
+operation.needAbsolutePath = Operation requires an absolute path. Relative path specified was: ''{0}''
+operation.needString = Operation requires a String.
+operation.notSupported = Operation not supported for specified element type(s):
+operation.cancelled = Operation cancelled.
+operation.nullContainer = Container cannot be null.
+operation.nullName = Name cannot be null.
+operation.copyElementProgress = Copying elements...
+operation.moveElementProgress = Moving elements...
+operation.renameElementProgress = Renaming elements...
+operation.copyResourceProgress = Copying resources...
+operation.moveResourceProgress = Moving resources...
+operation.renameResourceProgress = Renaming resources...
+operation.createUnitProgress = Creating a compilation unit...
+operation.createFieldProgress = Creating a field...
+operation.createImportsProgress = Creating imports...
+operation.createInitializerProgress = Creating an initializer...
+operation.createMethodProgress = Creating a method...
+operation.createPackageProgress = Creating a package declaration...
+operation.createPackageFragmentProgress = Creating package fragment(s)...
+operation.createTypeProgress = Creating a type...
+operation.deleteElementProgress = Deleting elements...
+operation.deleteResourceProgress = Deleting resources...
+operation.cannotRenameDefaultPackage = Default package cannot be renamed.
+operation.pathOutsideProject = Path ''{0}'' must denote location inside project {1}
+operation.sortelements = Sorting elements...
+
+### working copy
+workingCopy.commit = Committing working copy...
+
+### build status messages
+build.preparingBuild = Preparing for build
+build.readStateProgress = Reading saved built state for project {0}
+build.saveStateProgress = Saving built state for project {0}
+build.saveStateComplete = Saved in {0} ms
+build.readingDelta = Reading resource change information for {0}
+build.analyzingDeltas = Analyzing deltas
+build.analyzingSources = Analyzing sources
+build.cleaningOutput = Cleaning output folder
+build.copyingResources = Copying resources to the output folder
+build.compiling = Compiling {0}
+build.foundHeader = Found
+build.fixedHeader = Fixed
+build.oneError = 1 error
+build.oneWarning = 1 warning
+build.multipleErrors = {0} errors
+build.multipleWarnings = {0} warnings
+build.done = Build done
+
+### build errors
+build.wrongFileFormat = Wrong file format.
+build.cannotSaveState = Error saving last build state for project {0}.
+build.cannotSaveStates = Error saving build states.
+build.initializationError = Builder initialization error.
+build.serializationError = Builder serialization error.
+
+### build inconsistencies
+build.classFileCollision = Class file collision. {0}
+build.duplicateClassFile = The type {0} is already defined.
+build.duplicateResource = The resource is a duplicate of {0} and was not copied to the output folder.
+build.inconsistentClassFile = A class file was not written. The project may be inconsistent, if so try refreshing this project and rebuilding it.
+build.inconsistentProject = The project was not built due to "{0}". Fix the problem, then try refreshing this project and rebuilding it since it may be inconsistent.
+build.incompleteClassPath = The project was not built since its build path is incomplete. Cannot find the class file for {0}. Fix the build path then try rebuilding this project.
+build.missingSourceFile = The project was not built since the source file {0} could not be read.
+build.prereqProjectHasClasspathProblems = The project was not built since it depends on {0}, which has build path errors.
+build.prereqProjectMustBeRebuilt = The project cannot be built until its prerequisite {0} is rebuilt. Rebuilding all projects is recommended.
+build.abortDueToClasspathProblems = The project cannot be built until build path errors are resolved.
+
+### status
+status.cannotUseDeviceOnPath = Operation requires a path with no device. Path specified was: {0}
+status.coreException = Core exception.
+status.defaultPackageReadOnly = Default package is read-only.
+status.evaluationError = Evaluation error: {0}.
+status.JDOMError = JDOM error.
+status.IOException = I/O exception.
+status.indexOutOfBounds = Index out of bounds.
+status.invalidContents = Invalid contents specified.
+status.invalidDestination = Invalid destination: ''{0}''.
+status.invalidName = Invalid name specified: {0}.
+status.invalidPackage = Invalid package: {0}.
+status.invalidPath = Invalid path: ''{0}''.
+status.invalidProject = Invalid project: {0}.
+status.invalidResource = Invalid resource: {0}.
+status.invalidResourceType = Invalid resource type for {0}.
+status.invalidSibling = Invalid sibling: {0}.
+status.nameCollision = {0} already exists in target.
+status.noLocalContents = Cannot find local contents for resource: {0}
+status.OK = OK
+status.readOnly = {0} is read-only.
+status.targetException = Target exception.
+status.updateConflict = Update conflict.
+
+### classpath
+classpath.buildPath = Build path
+classpath.cannotNestEntryInEntry = Cannot nest ''{0}'' inside ''{1}''. To enable the nesting exclude ''{2}'' from ''{1}''.
+classpath.cannotNestEntryInLibrary = Cannot nest ''{0}'' inside library ''{1}''.
+classpath.cannotNestEntryInOutput = Cannot nest ''{0}'' inside output folder ''{1}''.
+classpath.cannotNestOutputInEntry = Cannot nest output folder ''{0}'' inside ''{1}''.
+classpath.cannotNestOutputInOutput = Cannot nest output folder ''{0}'' inside output folder ''{1}''.
+classpath.cannotReadClasspathFile = Unable to read ''.classpath'' file of project {0}.
+classpath.cannotReferToItself = Project cannot reference itself: {0}
+classpath.cannotUseDistinctSourceFolderAsOutput = Source folder ''{0}'' in project {2} cannot output to distinct source folder ''{1}''.
+classpath.cannotUseLibraryAsOutput = Source folder ''{0}'' in project {2} cannot output to library ''{1}''.
+classpath.closedProject = Required project: {0} needs to be open.
+classpath.couldNotWriteClasspathFile = Could not write ''.classpath'' file of project {0}: {1}
+classpath.cycle = A cycle was detected in the build path of project: {0}
+classpath.duplicateEntryPath = Build path contains duplicate entry: ''{0}'' for project {1}
+classpath.illegalContainerPath = Illegal classpath container path: ''{0}'' in project {1}, must have at least one segment (containerID+hints).
+classpath.illegalEntryInClasspathFile = Illegal entry in ''.classpath'' of project {0} file: {1}
+classpath.illegalLibraryPath = Illegal path for required library: ''{0}'' in project {1}.
+classpath.illegalProjectPath = Illegal path for required project: ''{0}'' in project {1}.
+classpath.illegalSourceFolderPath = Illegal path for required source folder: ''{0}'' in project {1}.
+classpath.illegalVariablePath = Illegal classpath variable path: ''{0}'' in project {1}, must have at least one segment.
+classpath.invalidClasspathInClasspathFile = Invalid build path in ''.classpath'' file of project {0}: {1}
+classpath.invalidContainer = Invalid classpath container: ''{0}'' in project {1}.
+classpath.mustEndWithSlash = End exclusion filter ''{0}'' with / to fully exclude ''{1}''.
+classpath.unboundContainerPath = Unbound classpath container: ''{0}'' in project {1}.
+classpath.unboundLibrary = Project {1} is missing required library: ''{0}''.
+classpath.unboundProject = Project {1} is missing required Java project: ''{0}''.
+classpath.settingOutputLocationProgress = Setting output location for: ''{0}''
+classpath.settingProgress = Setting classpath for: {0}
+classpath.unboundSourceAttachment = Invalid source attachment: ''{0}'' for required library ''{1}'' in project {1}.
+classpath.unboundSourceFolder = Project {1} is missing required source folder: ''{0}''.
+classpath.unboundVariablePath = Unbound classpath variable: ''{0}'' in project {1}.
+classpath.unknownKind = Unknown kind: ''{0}''
+classpath.xmlFormatError = XML format error in ''.classpath'' file of project {0}: {1}
+classpath.disabledExclusionPatterns = Exclusion patterns are disabled in project {1}, cannot exclude from entry: ''{0}''.
+classpath.disabledMultipleOutputLocations = Multiple output locations are disabled in project {1}, cannot associate entry: ''{0}'' with a specific output.
+classpath.incompatibleLibraryJDKLevel = Incompatible .class files version in required binaries. Project ''{0}'' is targeting a {1} runtime, but is compiled against ''{2}'' which requires a {3} runtime.
+
+### miscellaneous
+file.notFound = File not found: ''{0}''.
+file.badFormat = Bad format.
+path.nullPath = Path cannot be null.
+path.mustBeAbsolute = Path must be absolute.
+cache.invalidLoadFactor = Incorrect load factor
+
+### java conventions
+convention.unit.nullName = Compilation unit name must not be null.
+convention.unit.notJavaName = Compilation unit name must end with .java.
+convention.classFile.nullName = .class file name must not be null.
+convention.classFile.notClassFileName = .class file name must end with .class.
+convention.illegalIdentifier = ''{0}'' is not a valid Java identifier.
+convention.import.nullImport = An import declaration must not be null.
+convention.import.unqualifiedImport = An import declaration must not end with an unqualified *.
+convention.type.nullName = A Java type name must not be null.
+convention.type.nameWithBlanks = A Java type name must not start or end with a blank.
+convention.type.dollarName = By convention, Java type names usually don''t contain the $ character.
+convention.type.lowercaseName = By convention, Java type names usually start with an uppercase letter.
+convention.type.invalidName = The type name ''{0}'' is not a valid identifier.
+convention.package.nullName = A package name must not be null.
+convention.package.emptyName = A package name must not be empty.
+convention.package.dotName = A package name cannot start or end with a dot.
+convention.package.nameWithBlanks = A package name must not start or end with a blank.
+convention.package.consecutiveDotsName = A package name must not contain two consecutive dots.
+convention.package.uppercaseName = By convention, package names usually start with a lowercase letter.
+
+### DOM
+dom.cannotDetail = Unable to generate detailed source indexes.
+dom.nullTypeParameter = Cannot add parameter with null type
+dom.nullNameParameter = Cannot add parameter with null name
+dom.nullReturnType = Return type cannot be null
+dom.nullExceptionType = Cannot add null exception
+dom.mismatchArgNamesAndTypes = Types and names must have identical length
+dom.addNullChild = Attempt to add null child
+dom.addIncompatibleChild = Attempt to add child of incompatible type
+dom.addChildWithParent = Attempt to add child that is already parented
+dom.unableAddChild = Attempt to add child to node that cannot have children
+dom.addAncestorAsChild = Attempt to add ancestor as child
+dom.addNullSibling = Attempt to insert null sibling
+dom.addSiblingBeforeRoot = Attempt to insert sibling before root node
+dom.addIncompatibleSibling = Attempt to insert sibling of incompatible type
+dom.addSiblingWithParent = Attempt to insert sibling that is already parented
+dom.addAncestorAsSibling = Attempt to insert ancestor as sibling
+dom.addNullInterface = Cannot add null interface
+dom.nullInterfaces = Illegal to set super interfaces to null
+
+### correction
+correction.nullRequestor = Requestor cannot be null.
+correction.nullUnit = Compilation unit cannot be null.
+
+### Eclipse Java Core Search messages.
+
+engine.searching = Searching...
+exception.wrongFormat = Wrong format
+process.name = Java indexing
+manager.filesToIndex = {0} files to index
+
 ### Disassembler messages
 
 ### disassembler
@@ -22,13 +235,10 @@
 disassembler.begincommentline = \ *\ 
 disassembler.fieldhasconstant =\ =\ 
 disassembler.endoffieldheader = ;
-disassembler.methodtitle = Method 
 disassembler.exceptiontableheader = Exception Table:
 disassembler.linenumberattributeheader = Line number attribute:
 disassembler.localvariabletableattributeheader = Local variable table attribute:
 disassembler.arraydimensions = []
-disassembler.constructor_method_name =
-disassembler.parameternameinmethodinvocation =
 disassembler.innerattributesheader = Inner classes attributes:
 disassembler.inner_class_info_name = inner class info name:
 disassembler.outer_class_info_name = outer class info name:
@@ -38,7 +248,7 @@
 disassembler.genericattributename = Name: 
 disassembler.genericattributelength =\ Length: 
 disassembler.codeattributeheader = Code attribute:
-disassembler.tab = \t
+disassembler.identation = \  
 disassembler.constantpoolindex =\ #
 disassembler.classmemberseparator = #
 disassembler.space = \ 
@@ -55,7 +265,8 @@
 classfileformat.fieldddescriptor =\ Field descriptor 
 classfileformat.maxStack = Stack: 
 classfileformat.maxLocals = Locals: 
-classfileformat.superflagnotset = The ACC_SUPER bit is not set
+classfileformat.superflagisnotset = The ACC_SUPER bit is not set
+classfileformat.superflagisset = The ACC_SUPER bit is set
 classfileformat.clinitname = {}
 ### string displayed for each opcode
 classformat.invokeinterfacemethod =\ <Interface method 
diff --git a/org.eclipse.jdt.core/notes/API_changes.html b/org.eclipse.jdt.core/notes/API_changes.html
new file mode 100644
index 0000000..333a034
--- /dev/null
+++ b/org.eclipse.jdt.core/notes/API_changes.html
@@ -0,0 +1,566 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="IBM">
+   <title>JDT/Core Breaking API changes</title>
+
+</head>
+<body>
+
+<body text="#000000" bgcolor="#FFFFFF">
+&nbsp;
+
+<table border=0 cellspacing=5 cellpadding=2 width="100%" >
+  <tr> 
+    <td align=left width="72%">
+      <font face="Verdana, Arial, Helvetica" size="+3"><b>jdt core - Breaking API changes from R2.1 to R3.0</b></font>
+      <br><font face="Arial, Helvetica, sans-serif" size="-2" color="#8080ff">java development tooling core</font></td>
+  </tr>
+	<tr><td>&nbsp;</td></tr>
+  <tr>
+  	<td>
+	  <font face="Arial, Helvetica, sans-serif" size="-1">
+	  This document lists all API changes (breaking or not) that occured between R2.1 and R3.0 and how to migrate from the R2.1 API to
+	  the R3.0 API.
+	  </font>
+	</td>
+  </tr>
+</table>
+<hr><h1>New API on <code>org.eclipse.jdt.core.dom.AST</code></h1>
+	(in progress) Last edit: 2003/07/18
+<h2>Problem description</h2>
+	Creating an DOM/AST for a compilation unit costs a lot when the user wants only a subpart
+	of the compilation unit to be populated. For example, only the statements of one method are
+	useful and there is no need to create the statements of the other methods.
+	<p>
+	See also <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=40474 ">bug 40474</a>.
+	</p>
+<h2>Problem resolution</h2>
+	Two new APIs have been added on <code>org.eclipse.jdt.core.dom.AST</code>.<br>
+	<ul>
+	<li><pre><code>public static org.eclipse.jdt.core.dom.CompilationUnit parsePartialCompilationUnit(
+		org.eclipse.jdt.core.ICompilationUnit unit,
+		int position,
+		boolean resolveBindings)</code>
+		</pre>
+	</li>
+	<li><pre><code>public static org.eclipse.jdt.core.dom.CompilationUnit parsePartialCompilationUnit(
+		org.eclipse.jdt.core.ICompilationUnit unit,
+		int position,
+		boolean resolveBindings,
+		org.eclipse.jdt.core.WorkingCopyOwner owner)</code>
+		</pre>
+	</ul>
+<h2>Converting to the new API</h2>
+	None.
+
+<hr><h1>IWorkingCopy is removed</h1>
+	(in progress) Last edit: 2003/07/03
+<h2>Problem description</h2>
+	Historically, <code>IWorkingCopy</code> gathered all working copy concerns, 
+	and <code>ICompilationUnit</code> implement this interface, though only the 
+	factory method makes sense for them; thus their implementation of the working 
+	copy features do nothing relevant to clients. <code>IWorkingCopy</code> also 
+	implements the spec'ed factory method, but it doesn't work for these.
+	<p>
+	See also <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36987 ">bug 36987</a>.
+	</p>
+<h2>Problem resolution</h2>
+	Interface <code>IWorkingCopy</code> is removed and all its functionality is moved to <code>ICompilationUnit</code>.
+<h2>Converting to the new API</h2>
+	Clients using <code>IWorkingCopy</code> and <code>ICompilationUnit</code> can
+	adapt to this change by referencing <code>ICompilationUnit</code> instead of 
+	<code>IWorkingCopy</code> when a working copy is needed.
+
+<hr><h1>Working copy factory methods return ICompilationUnit</h1>
+	(in progress) Last edit: 2003/07/03
+<h2>Problem description</h2>
+	Working copies were initialy designed to be editable elements on any <code>IJavaElement</code>.
+	Pratice showed that they were used only to edit <code>ICompilationUnit</code>. This imposed 
+	downcasting to <code>IWorkingCopy</code> when using the working copy factory methods.
+<h2>Problem resolution</h2>
+	Factory methods that create <code>ICompilationUnits</code> (i.e. 
+	<code>getWorkingCopy</code>) now return an <code>ICompilationUint</code> instead of an 
+	<code>IJavaElement</code>.
+<h2>Converting to the new API</h2>
+	Clients using factory methods to create working copies can now remove the cast from 
+	<code>IJavaElement</code> to <code>IWorkingCopy</code>, <code>ICompilationUint</code>
+	being compatible with <code>IWorkingCopy</code>.
+
+<hr><h1>CharOperation.pathMatch(...) treats non absolute pattern as Ant does</h1>
+	Last edit: 2003/06/11 (->M2)
+<h2>Problem description</h2>
+	<code>CharOperation.pathMatch(...)</code> used to treat non absolute pattern <code>'foo'</code>
+	as <code>'**/foo'</code> for free. This was inconsistent with Ant patternset rules.
+<h2>Problem resolution</h2>
+	<code>CharOperation.pathMatch(...)</code> no longer treat non absolute pattern <code>'foo'</code>
+	as <code>'**/foo'</code> for free. This has no incidence on
+	source folder exclusion patterns which are implicitely concatenating exclusion patterns to source folder
+	paths when using them. Only direct clients to this <code>CharOperation</code> API will be affected.
+<h2>Converting to the new API</h2>
+	TODO
+
+<hr><h1>Change in syntax error message ID</h1>
+	Last edit: 2003/06/11 (->M2)
+<h2>Problem description</h2>
+	TODO
+<h2>Problem resolution</h2>
+	The new diagnose of syntax errors use new error messages.
+	  <p>
+		The following messages ID are added:
+		<ul>
+			<li>IProblem.ParsingErrorInsertTokenBefore</li>
+			<li>IProblem.ParsingErrorInsertTokenAfter</li>
+			<li>IProblem.ParsingErrorDeleteToken</li>
+			<li>IProblem.ParsingErrorDeleteTokens</li>
+			<li>IProblem.ParsingErrorMergeTokens</li>
+			<li>IProblem.ParsingErrorInvalidToken</li>
+			<li>IProblem.ParsingErrorMisplacedConstruct</li>
+			<li>IProblem.ParsingErrorReplaceTokens</li>
+			<li>IProblem.ParsingErrorNoSuggestionForTokens</li>
+			<li>IProblem.ParsingErrorUnexpectedEOF</li>
+			<li>IProblem.ParsingErrorInsertToComplete</li>
+			<li>IProblem.ParsingErrorInsertToCompleteScope</li>
+			<li>IProblem.ParsingErrorInsertToCompletePhrase</li>
+		</ul>
+	  </p>
+	  <p>
+		The following messages ID are removed:
+		<ul>
+			<li>IProblem.ParsingErrorNoSuggestion</li>
+			<li>IProblem.ParsingErrorOnKeyword</li>
+			<li>IProblem.ParsingErrorOnKeywordNoSuggestion</li>
+			<li>IProblem.UnmatchedBracket</li>
+			<li>IProblem.InvalidExpressionAsStatement</li>
+		</ul>
+	  </p>
+<h2>Converting to the new API</h2>
+	TODO
+
+<hr><h1>Force reload of .classpath file</h1>
+	Last edit: 2003/06/12 (->M2)
+<h2>Problem description</h2>
+	TODO
+<h2>Problem resolution</h2>
+	Added API <code>IJavaProject#forceClasspathReload(IProgressMonitor)</code> to force reload of <code>.classpath</code> file
+	before next automatic update occurs.
+	<pre>
+/**
+ * Force the project to reload its <code>.classpath</code> file from disk and update the classpath accordingly.
+ * Usually, a change to the <code>.classpath</code> file is automatically noticed and reconciled at the next 
+ * resource change notification event. If required to consider such a change prior to the next automatic
+ * refresh, then this functionnality should be used to trigger a refresh. In particular, if a change to the file is performed,
+ * during an operation where this change needs to be reflected before the operation ends, then an explicit refresh is
+ * necessary.
+ * 
+ * @param monitor a progress monitor for reporting operation progress
+ * @exception JavaModelException if the classpath could not be updated. Reasons
+ * include:
+ *  - This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ *  - Two or more entries specify source roots with the same or overlapping paths (NAME_COLLISION)
+ *  - A entry of kind <code>CPE_PROJECT</code> refers to this project (INVALID_PATH)
+ *  - This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ *  - The output location path refers to a location not contained in this project (<code>PATH_OUTSIDE_PROJECT</code>)
+ *  - The output location path is not an absolute path (<code>RELATIVE_PATH</code>)
+ *  - The output location path is nested inside a package fragment root of this project (<code>INVALID_PATH</code>)
+ *  - The classpath is being modified during resource change event notification (CORE_EXCEPTION)
+ * @since 3.0
+ */
+	</pre>
+<h2>Converting to the new API</h2>
+	TODO
+
+<hr><h1>Allow empty path to be equivalent to no source attachment</h1>
+	Last edit: 2003/06/13 (->M2)
+<h2>Problem description</h2>
+	<code>JavaCore.newLibraryEntry(...)</code> used to not allow an empty source attachment (
+	<code>new Path("")</code>) to be equivalent to no source attachment (i.e. <code>null</code>). 
+	This adjustment is made necessary for library entries generated from classpath variables which cannot be set to 
+	<code>null</code>. Also see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=38531">38531</a>.
+<h2>Problem resolution</h2>
+	<code>JavaCore.newLibraryEntry(...)</code> will now allow an empty source attachment (
+	<code>new Path("")</code>) to be equivalent to no source attachment (i.e. <code>null</code>). 
+	<pre>
+* @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, 
+*    or <code>null</code> if none. Note, since 3.0, an empty path is allowed to denote no source attachment.
+*   and will be automatically converted to <code>null</code>.
+	</pre>
+<h2>Converting to the new API</h2>
+	TODO
+
+<hr><h1>Close the gap between compilation units and working copies</h1>
+	Last edit: 2003/06/27 (->M2)
+<h2>Problem description</h2>
+	TODO
+	<p>See also <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36888 ">bug 36888</a>.
+	</p>
+<h2>Problem resolution</h2>
+	The following new APIs are added to <code>ICompilationUnit</code>:
+	<ul>
+	<li><pre>
+/**
+ * Changes this compilation unit handle into a working copy. A new IBuffer is
+ * created using this compilation unit handle's owner. Uses the primary owner is none was
+ * specified when this compilation unit handle was created.
+ *
+ * When switching to working copy mode, problems are reported to given 
+ * IProblemRequestor.
+ *
+ * Once in working copy mode, changes to this compilation unit or its children are done in memory.
+ * Only the new buffer is affected. Using commitWorkingCopy(boolean, IProgressMonitor)
+ * will bring the underlying resource in sync with this compilation unit.
+ *
+ * If this compilation unit was already in working copy mode, an internal counter is incremented and no
+ * other action is taken on this compilation unit. To bring this compilation unit back into the original mode 
+ * (where it reflects the underlying resource), discardWorkingCopy must be call as many 
+ * times as becomeWorkingCopy.
+ * 
+ * @param problemRequestor a requestor which will get notified of problems detected during
+ * 	reconciling as they are discovered. The requestor can be set to null indicating
+ * 	that the client is not interested in problems.
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ * 	or null if no progress should be reported 
+ * @exception JavaModelException if this compilation unit could not become a working copy.
+ * @see discardWorkingCopy
+ * @since 3.0
+ */
+void becomeWorkingCopy(IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;	
+	</pre></li>
+	<li><pre>
+/**
+ * Commits the contents of this working copy to its underlying resource.
+ *
+ * It is possible that the contents of the original resource have changed
+ * since this working copy was created, in which case there is an update conflict.
+ * The value of the force parameter effects the resolution of
+ * such a conflict:
+ * - true - in this case the contents of this working copy are applied to
+ * 	the underlying resource even though this working copy was created 
+ * 	before a subsequent change in the resource
+ * - false - in this case a JavaModelException is thrown
+ * 
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * 
+ * @param force a flag to handle the cases when the contents of the original resource have changed
+ * since this working copy was created
+ * @param monitor the given progress monitor
+ * @exception JavaModelException if this working copy could not commit. Reasons include:
+ * - A CoreException occurred while updating an underlying resource
+ * - This element is not a working copy (INVALID_ELEMENT_TYPES)
+ * - A update conflict (described above) (UPDATE_CONFLICT)
+ * @since 3.0
+ */
+void commitWorkingCopy(boolean force, IProgressMonitor monitor) throws JavaModelException;	
+	</pre></li>
+	<li><pre>
+/**
+ * Changes this compilation unit in working copy mode back to its original mode.
+ *
+ * This has no effect if this compilation unit was not in working copy mode.
+ * 
+ * If becomeWorkingCopy was called several times on this
+ * compilation unit, discardWorkingCopy must be called as 
+ * many times before it switches back to the original mode.
+ * 
+ * @see becomeWorkingCopy
+ * @exception JavaModelException if this working copy could not return in its original mode.
+ * @since 3.0
+ */
+void discardWorkingCopy() throws JavaModelException;
+	</pre></li>
+	<li><pre>
+/**
+ * Returns the working copy owner of this working copy.
+ * Returns null if it is not a working copy or if it has no owner.
+ * 
+ * @return WorkingCopyOwner the owner of this working copy or null
+ * @since 3.0
+ */
+WorkingCopyOwner getOwner();
+	</pre></li>	
+	<li><pre>
+/**
+ * Returns a new working copy of this element if this element is not
+ * a working copy, or this element if this element is already a working copy.
+ * 
+ * Note: if intending to share a working copy amongst several clients, then 
+ * getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor) 
+ * should be used instead.
+ * 
+ * When the working copy instance is created, an ADDED IJavaElementDelta is 
+ * reported on this working copy.
+ * 
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * 
+* @param monitor a progress monitor used to report progress while opening this compilation unit
+ * 	or null if no progress should be reported 
+ * @exception JavaModelException if the contents of this element can
+ * 	not be determined. 
+ * @return a new working copy of this element if this element is not
+ * 	a working copy, or this element if this element is already a working copy
+ * @since 3.0
+ */
+ICompilationUnit getWorkingCopy(IProgressMonitor monitor) throws JavaModelException;
+	</pre></li>	
+	<li><pre>
+/**
+ * Returns a shared working copy on this element using the given working copy owner to create
+ * the buffer, or this element if this element is already a working copy.
+ * This API can only answer an already existing working copy if it is based on the same
+ * original compilation unit AND was using the same working copy owner (that is, as defined by Object.equals).	 
+ * 
+ * The life time of a shared working copy is as follows:
+ * - The first call to getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)
+ *   creates a new working copy for this element
+ * - Subsequent calls increment an internal counter.
+ * - A call to discardWorkingCopy() decrements the internal counter.
+ * - When this counter is 0, the working copy is discarded.
+ * 
+ * So users of this method must discard exactly once the working copy.
+ *
+ * Note that the working copy owner will be used for the life time of this working copy, that is if the 
+ * working copy is closed then reopened, this owner will be used.
+ * The buffer will be automatically initialized with the original's compilation unit content
+ * upon creation.
+ * 
+ * When the shared working copy instance is created, an ADDED IJavaElementDelta is reported on this
+ * working copy.
+ * 
+ * Since 2.1, a working copy can be created on a not-yet existing compilation
+ * unit. In particular, such a working copy can then be committed in order to create
+ * the corresponding compilation unit.
+ * 
+ * @param owner the working copy owner that creates a buffer that is used to get the content 
+ *  	of the working copy
+ * @param problemRequestor a requestor which will get notified of problems detected during
+ * 	reconciling as they are discovered. The requestor can be set to null indicating
+ * 	that the client is not interested in problems.
+ * @param monitor a progress monitor used to report progress while opening this compilation unit
+ * 	or null if no progress should be reported 
+ * @exception JavaModelException if the contents of this element can
+ *  	not be determined. 
+ * @return a new working copy of this element using the given factory to create
+ * the buffer, or this element if this element is already a working copy
+ * @since 3.0
+ */
+ICompilationUnit getWorkingCopy(WorkingCopyOwner owner, IProblemRequestor problemRequestor, IProgressMonitor monitor) throws JavaModelException;	
+	</pre></li>
+	</ul>
+And the following abstract class replaces <code>IBufferFactory</code>:
+	<pre>
+/**
+ * The owner of an ICompilationUnit handle in working copy mode. 
+ * An owner is used to identify a working copy and to create its buffer.
+ * 
+ * @see ICompilationUnit#becomeWorkingCopy
+ * @see ICompilationUnit#discardWorkingCopy
+ * @since 3.0
+ */
+public abstract class WorkingCopyOwner {
+	/**
+	 * Creates a buffer for the given working copy.
+	 * The new buffer will be initialized with the contents of the underlying file
+	 * if and only if it was not already initialized by the compilation owner (a buffer is 
+	 * uninitialized if its content is null).
+	 * 
+	 * @param workingCopy the working copy of the buffer
+	 * @return IBuffer the created buffer for the given working copy
+	 * @see IBuffer
+	 */
+	public IBuffer createBuffer(ICompilationUnit workingCopy) {
+		...
+	}
+}
+	</pre>
+	To generalize the usage of a working copy owner (entire JavaModel is now aware of owned working copies), new
+	APIs were added. These new APIs are copies of existing APIs augmented with a <code>WorkingCopyOwner</code> 
+	parameter, that defines the working copies to consider in the operation. 
+	When specifying an owner parameter, all working copies belonging to this owner will implicitly take precedence over primary ones
+	(without requiring the owner to remember all its working copies, as in 2.1 era). Note that when no owned working copy is found, a primary
+	unit will be considered instead, and since primary units have a built-in working copy (see <code>ICompilationUnit.becomeWorkingCopy(...)</code>),
+	the primary unit may already be in working copy mode (very likely since an editor got opened on it). This means that an owner will already 
+	transparently see unsaved editor contents for all units for which it has no better working copy to contribute.
+	The following new APIs were added:
+	<ul>
+		<li><code>AST.parseCompilationUnit(char[] source, String unitName, IJavaProject project, WorkingCopyOwner owner)</code></li>
+		<li><code>AST.parseCompilationUnit(IClassFile classFile, boolean resolveBindings, WorkingCopyOwner owner)</code></li>
+		<li><code>AST.parseCompilationUnit(ICompilationUnit unit, boolean resolveBindings, WorkingCopyOwner owner)</code></li>
+		<li><code>IEvaluationContext.codeComplete(String codeSnippet, int position, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
+		<li><code>IEvaluationContext.codeSelect(String codeSnippet, int offset, int length, WorkingCopyOwner owner)</code></li>
+		<li><code>IDOMCompilationUnit.getCompilationUnit(IPackageFragment parent, WorkingCopyOwner owner)</code></li>
+		<li><code>ICodeAssist.codeComplete(int offset, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
+		<li><code>ICodeAssist.codeSelect(int offset, int length, WorkingCopyOwner owner)</code></li>
+		<li><code>ICompilationUnit.reconcile(boolean forceProblemDetection, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+		<li><code>IJavaProject.findElement(IPath path, WorkingCopyOwner owner)</code></li>
+		<li><code>IJavaProject.findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner)</code></li>
+		<li><code>IJavaProject.findType(String fullyQualifiedName, WorkingCopyOwner owner)</code></li>
+		<li><code>IJavaProject.newTypeHierarchy(IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+		<li><code>IJavaProject.newTypeHierarchy(IType type, IRegion region, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+		<li><code>IPackageFragment.getCompilationUnit(String name, WorkingCopyOwner owner)</code></li>
+		<li><code>IPackageFragment.getCompilationUnits(WorkingCopyOwner owner)</code></li>
+		<li><code>IType.codeComplete(char[] snippet, int insertion, int position, char[][] localVariableTypeNames, char[][] localVariableNames, int[] localVariableModifiers, boolean isStatic, ICompletionRequestor requestor, WorkingCopyOwner owner)</code></li>
+		<li><code>IType.newSupertypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+		<li><code>IType.newTypeHierarchy(IJavaProject project, WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+		<li><code>IType.newTypeHierarchy(WorkingCopyOwner owner, IProgressMonitor monitor)</code></li>
+		<li><code>IType.resolveType(String typeName, WorkingCopyOwner owner)</code></li>
+		<li><code>JavaCore.create(IFile file, WorkingCopyOwner owner)</code></li>
+		<li><code>JavaCore.create(IResource resource, WorkingCopyOwner owner)</code></li>
+		<li><code>JavaCore.create(String handleIdentifier, WorkingCopyOwner owner)</code></li>
+		<li><code>JavaCore.createCompilationUnitFrom(IFile file, WorkingCopyOwner owner)</code></li>
+		<li><code>JavaCore.getWorkingCopies(WorkingCopyOwner owner)</code></li>
+		<li><code>SearchEngine.SearchEngine(WorkingCopyOwner workingCopyOwner)</code></li>
+		<li><code>SearchEngine.createHierarchyScope(IType type, WorkingCopyOwner owner)</code></li>
+	</ul>
+<h2>Converting to the new API</h2>
+	TODO
+
+<hr><h1>IJavaElement.getResource() returns a non null value for working copies</h1>
+	Last edit: 2003/06/18 (->M2)
+<h2>Problem description</h2>
+	<code>IJavaElement.getResource()</code> was specified to return <code>null</code> for working copies. 
+	This didn't make sense as	this is a handle-only operation and an <code>IResource</code> is also a handle. 
+<h2>Problem resolution</h2>
+	This restriction was removed and <code>IJavaElement.getResource()</code> now returns a non-<code>null</code> 
+	value for a working copy.
+<h2>Converting to the new API</h2>
+	TODO
+
+<hr><h1>Rename getOriginalElement() into getPrimaryElement()</h1>
+	Last edit: 2003/06/20 (->M2)
+<h2>Problem description</h2>
+	The 2.1 API <code>IWorkingCopy.getOriginalElement()</code> returns an <code>IJavaElement</code>. In practice 
+	the original element for a working copy is always an <code>ICompilationUnit</code> whose owner is the primary owner. 
+<h2>Problem resolution</h2>
+	<code>getPrimary()</code> was added on <code>ICompilationUnit</code> to return an <code>ICompilationUnit</code>. 
+	This new API replaces <code>getOriginalElement()</code>.
+	<pre>
+/**
+ * Returns the primary compilation unit (whose owner is the primary owner)
+ * this working copy was created from, or this compilation unit if this a primary
+ * compilation unit.
+ * Note that the returned primary compilation unit can be in working copy mode.
+ * 
+ * @return the primary compilation unit this working copy was created from,
+ * or this compilation unit if it is primary
+ * @since 3.0
+ */
+ICompilationUnit getPrimary();
+	</pre>
+	In the same manner, <code>IWorkingCopy.getOriginalElement(IJavaElement)</code> is replaced with
+	<code>IJavaElement.getPrimaryElement()</code>.
+	<pre>
+/**
+ * Returns the primary element (whose compilation unit is the primary compilation unit)
+ * this working copy element was created from, or this element if it is a descendant of a
+ * primary compilation unit or if it is not a descendant of a working copy (e.g. it is a
+ * binary member).
+ * The returned element may or may not exist.
+ * 
+ * @return the primary element this working copy element was created from, or this
+ *		element.
+ * @since 3.0
+ */
+IJavaElement getPrimaryElement();
+	</pre>
+
+<h2>Converting to the new API</h2>
+	TODO
+
+<hr><h1>JavaCore.newLibraryEntry(...) no longer accepts a relative source attachment path</h1>
+	Last edit: 2003/06/30 (->M2)
+<h2>Problem description</h2>
+	The API <code>JavaCore.newLibraryEntry(IPath path, IPath sourceAttachmentPath, IPath sourceAttachmentRootPath, boolean isExported)</code> 
+	for creating a library classpath entry with a source attachment used to accept a relative source attachment path. It was spec'ed as such, 
+	but its implementation was too permissive.
+<h2>Problem resolution</h2>
+	From 3.0 on, an <code>IllegalArgumentException</code> will be raised if a non-relative source attachment path is provided. 
+	Note that the only exception to this rule is an empty path (answering <code>true</code> to <code>IPath.isEmpty()</code>) which is 
+	now automatically translated into <code>null</code> denoting no source attachment.
+	In 3.0, a .classpath file will compact source attachments into project relative ones (as it does with other entry pathes already). During 
+	this process, relative pathes are known to be meaning project relative (internally when reading/writing the .classpath file). Externally, 
+	only absolute pathes are allowed to avoid confusion when reading/writing the .classpath file.
+	The tolerance for empty relative pathes comes from the fact that it is possible for variable classpath entries can be resolved to library entries 
+	with no classpath. Then the variable source attachment needs to be positionned to a value meaning no source (<code>null</code>). 
+	However, assigning a classpath variable to <code>null</code> is not allowed (nullification is used to remove variables),
+	thus an empty relative source path is tolerated to work around this limitation.
+<h2>Converting to the new API</h2>
+	TODO
+
+<hr><h1>Read <code>.classpath</code> file contents even if project has not the java nature yet</h1>
+	Last edit: 2003/09/01 (->M4)
+<h2>Problem description</h2>
+In 2.0 it was allowed to access IJavaProject.getOutputLocation/getRawClasspath on a project where the JavaNature was not set yet. Since 2.1 a
+JavaModelException is thrown if that happens.
+For example, the new Java project wizard does this if a .classpath file is found at the
+location where the project will be created.
+<h2>Problem resolution</h2>
+
+	Added API <code>IJavaProject#readRawClasspath()</code> to allow user to read the raw classpath from <code>.classpath</code> disk file
+	on a java project which java nature has not been set yet.
+	<pre>
+/**
+ * Returns the raw classpath for the project as defined by its <code>.classpath</code> file from disk, or <code>null</code>
+ * if unable to read the file. 
+ * <p>
+ * This classpath may differ from the in-memory classpath returned by <code>getRawClasspath</code>, in case the 
+ * automatic reconciliation mechanism has not been performed yet. Usually, any change to the <code>.classpath</code> file 
+ * is automatically noticed and reconciled at the next resource change notification event. 
+ * However, if the file is modified within an operation, where this change needs to be taken into account before the 
+ * operation ends, then the classpath from disk can be read using this method, and further assigned to the project 
+ * using <code>setRawClasspath(...)</code>.
+ * <p>
+ * A raw classpath may contain classpath variable and/or container entries. Classpath variable entries can be resolved 
+ * individually (see <code>JavaCore#getClasspathVariable</code>), or the full classpath can be resolved at once using the 
+ * helper method <code>getResolvedClasspath</code>.
+ * TODO (jim) please reformulate to include classpath containers in resolution aspects
+ * <p>
+ * Note that no check is performed whether the project has the Java nature set, allowing an existing <code>.classpath</code> 
+ * file to be considered independantly (unlike <code>getRawClasspath</code> which requires the Java nature to be associated 
+ * with the project). 
+ * 
+ * @return the raw classpath from disk for the project, as a list of classpath entries
+ * @see #getRawClassPath
+ * @see IClasspathEntry
+ * @since 3.0
+ */
+	</pre>
+
+	Added API <code>IJavaProject#readOutputLocation()</code> to allow user to read the output location from <code>.classpath</code> disk file
+	on a java project which java nature has not been set yet.
+	<pre>
+/**
+ * Returns the default output location for the project as defined by its <code>.classpath</code> file from disk, or <code>null</code>
+ * if unable to read the file. 
+ * <p>
+ * This output location may differ from the in-memory one returned by <code>getOutputLocation</code>, in case the 
+ * automatic reconciliation mechanism has not been performed yet. Usually, any change to the <code>.classpath</code> file 
+ * is automatically noticed and reconciled at the next resource change notification event. 
+ * However, if the file is modified within an operation, where this change needs to be taken into account before the 
+ * operation ends, then the output location from disk can be read using this method, and further assigned to the project 
+ * using <code>setRawClasspath(...)</code>.
+ * <p>
+ * The default output location is where class files are ordinarily generated
+ * (and resource files, copied). Each source classpath entry can also
+ * specify an output location for the generated class files (and copied
+ * resource files) corresponding to compilation units under that source
+ * folder. This makes it possible to arrange generated class files for
+ * different source folders in different output folders, and not
+ * necessarily the default output folder. This means that the generated
+ * class files for the project may end up scattered across several folders,
+ * rather than all in the default output folder (which is more standard).
+ * 
+ * @return the workspace-relative absolute path of the default output folder
+ * @see #getOutputLocation
+ * @since 3.0
+ */
+	</pre>
+<h2>Converting to the new API</h2>
+	TODO
+
+</body>
+</html>
diff --git a/org.eclipse.jdt.core/notes/R20_buildnotes_jdt-core.html b/org.eclipse.jdt.core/notes/R20_buildnotes_jdt-core.html
index 6f3fab0..d7c6de2 100644
--- a/org.eclipse.jdt.core/notes/R20_buildnotes_jdt-core.html
+++ b/org.eclipse.jdt.core/notes/R20_buildnotes_jdt-core.html
@@ -28,7 +28,7 @@
 	  Most recent information is listed first.
 	  <br>
 	  This present document covers all changes up to Release 2.0, changes which occurred since then in 2.1
-	  stream are described in <a href="../buildnotes_jdt-core.html">build notes 2.1 stream</a>.
+	  stream are described in <a href="http://dev.eclipse.org/viewcvs/index.cgi/%7Echeckout%7E/org.eclipse.jdt.core/notes/R21_buildnotes_jdt-core.html">build notes R2.1</a>.
 	  
 	  </font>
 	</td>
diff --git a/org.eclipse.jdt.core/notes/R21_buildnotes_jdt-core.html b/org.eclipse.jdt.core/notes/R21_buildnotes_jdt-core.html
index 0dd3b2f..88789a4 100644
--- a/org.eclipse.jdt.core/notes/R21_buildnotes_jdt-core.html
+++ b/org.eclipse.jdt.core/notes/R21_buildnotes_jdt-core.html
@@ -35,23 +35,6 @@
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 2.1 Build - 31st March 2003
-<br>Project org.eclipse.jdt.core v_312
-<h2>
-What's new in this drop</h2>
-<ul>
-</ul>
-
-<h3>Problem Reports Fixed</h3>
-<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=35831">35831</a>
-NPE navigating references using links
-
-<h3>Problem Reports Closed</h3>
-
-
-<p><hr><h1>
-Eclipse Platform Build Notes&nbsp;<br>
-Java Development Tooling Core</h1>
 Eclipse SDK 2.1 Build - 27th March 2003
 <br>Project org.eclipse.jdt.core v_311 - 2.1 RELEASE (R2_1)
 <h2>
diff --git a/org.eclipse.jdt.core/notes/porting_guide.html b/org.eclipse.jdt.core/notes/porting_guide.html
new file mode 100644
index 0000000..64ffd06
--- /dev/null
+++ b/org.eclipse.jdt.core/notes/porting_guide.html
@@ -0,0 +1,208 @@
+<html>
+
+<head>
+<title>JDT Core Porting Guide</title>
+</head>
+
+<body>
+
+<h1>JDT Core 3.0 Porting Guide</h1>
+<p>Last modified 19:00 CET November 20, 2003</p>
+
+<a name="bug_36987"></a>
+<h4>Interface IWorkingCopy (package org.eclipse.jdt.core; plug-in org.eclipse.jdt.core)</h4>
+<ul>
+	<li>Prior to 3.0, <code>IWorkingCopy</code> gathered all working copy concerns, and <code>ICompilationUnit</code> 
+  		implemented this interface. However, though only the factory method made sense for compilation units, they still had to implement
+  		the entire working copy contract., which was not relevant to clients (implementation detail).
+        <code>IWorkingCopy</code> also implemented the spec'ed factory method, but it didn't work for these.
+    </li>
+	<li>One possible solution would have been to inverse the hierarchy and make <code>IWorkingCopy</code> implement
+	     <code>ICompilationUnit</code>. However as explained in the next <a href="#bug_36888">section</a>, closing the gap 
+	     between resource based compilation units and working copies required to merge these two interfaces. As a consequence 
+	     the interface <code>IWorkingCopy</code> is removed and all its functionality is merged into <code>ICompilationUnit</code>. 
+	</li>
+	<li>Clients using <code>IWorkingCopy</code> and <code>ICompilationUnit</code> can adapt to this change by referencing 
+	     <code>ICompilationUnit</code> instead of <code>IWorkingCopy</code> when a working copy is needed. For example:
+         <pre>
+         ICompilationUnit compilationUnit = ...;
+         IWorkingCopy workingCopy = (IWorkingCopy)compilationUnit.getWorkingCopy();
+         workingCopy.reconcile(true/*force problem detection*/, null/*no progress monitor*/);
+         </pre>
+         should be converted into:
+         <pre>
+         ICompilationUnit compilationUnit = ...;
+         ICompilationUnit workingCopy = compilationUnit.getWorkingCopy(null/*no progress monitor*/);
+         workingCopy.reconcile(true/*force problem detection*/, null/*no progress monitor*/);
+         </pre>
+	</li>
+	<li>To convert usage of <code>IWorkingCopy</code> functionality into usage of <code>ICompilationUnit</code> use this table:
+		<p>
+		<table BORDER CELLSPACING=2 CELLPADDING=2 >
+		<th>IWorkingCopy</th>
+		<th>ICompilationUnit</th>
+		<th>Note</th>
+		<tr>
+		<td>commit(boolean, IProgressMonitor)</td>
+		<td>commitWorkingCopy(boolean, IProgressMonitor)</td>
+		<td>&nbsp;</td>
+		</tr>
+		<tr>
+		<td>destroy()</td>
+		<td>discardWorkingCopy()</td>
+		<td>&nbsp;</td>
+		</tr>
+		<tr>
+		<td>findElements(IJavaElement)</td>
+		<td>findElements(IJavaElement)</td>
+		<td>&nbsp;</td>
+		</tr>
+		<tr>
+		<td>findPrimaryType()</td>
+		<td>findPrimaryType()</td>
+		<td>&nbsp;</td>
+		</tr>
+		<tr>
+		<td>findSharedWorkingCopy(IBufferFactory)</td>
+		<td>findWorkingCopy(WorkingCopyOwner)</td>
+		<td>See <a href="#bug_36888">next section</a> for details.</td>
+		</tr>
+		<tr>
+		<td>getOriginal(IJavaElement)</td>
+		<td>&nbsp;</td>
+		<td>Use IJavaElement.getPrimaryElement() instead. Note that this no longer returns <code>null</code> if the receiver
+		        is not a working copy but this returns the receiver.</td>
+		</tr>
+		<tr>
+		<td>getOriginalElement()</td>
+		<td>getPrimary()</td>
+		<td>This no longer returns <code>null</code> if the receiver is not a working copy but this returns the receiver.
+				The returned object is no longer an <code>IJavaElement</code> but an <code>ICompilationUnit</code>.</td>
+		</tr>
+		<tr>
+		<td>getSharedWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)</td>
+		<td>getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)</td>
+		<td>See <a href="#bug_36888">next section</a> for details.
+				The returned object is no longer an <code>IJavaElement</code> but an <code>ICompilationUnit</code>.</td>
+		</tr>
+		<tr>
+		<td>getWorkingCopy()</td>
+		<td>getWorkingCopy(IProgressMonitor)</td>
+		<td>The returned object is no longer an <code>IJavaElement</code> but an <code>ICompilationUnit</code>.</td>
+		</tr>
+		<tr>
+		<td>getWorkingCopy(IProgressMonitor, IBufferFactory, IProblemRequestor)</td>
+		<td>getWorkingCopy(WorkingCopyOwner, IProblemRequestor, IProgressMonitor)</td>
+		<td>Working copies are now implicitely shared. See <a href="#bug_36888">next section</a> for details.
+				The returned object is no longer an <code>IJavaElement</code> but an <code>ICompilationUnit</code>.</td>
+		</tr>
+		<tr>
+		<td>isBasedOn(IResource)</td>
+		<td>hasResourceChanged()</td>
+		<td>The IResource was always the working copy's resource. There was no need to pass it in.</td>
+		</tr>
+		<tr>
+		<td>isWorkingCopy()</td>
+		<td>isWorkingCopy()</td>
+		<td>&nbsp;</td>
+		</tr>
+		<tr>
+		<td>reconcile()</td>
+		<td>reconcile(boolean, IProgressMonitor)</td>
+		<td>Pass in <code>false</code> and <code>null</code> to have the equivalent functionality. Note that this method doesn't 
+			    return anything.</td>
+		</tr>
+		<tr>
+		<td>reconcile(boolean, IProgressMonitor)</td>
+		<td>reconcile(boolean, IProgressMonitor)</td>
+		<td>&nbsp;</td>
+		</tr>
+		<tr>
+		<td>restore()</td>
+		<td>restore()</td>
+		<td>&nbsp;</td>
+		</tr>
+		</table>
+		</p>
+	</li>
+</ul>
+
+<a name="bug_36888"></a>
+<h4>Interface IBufferFactory is replaced with class WorkingCopyOwner (package org.eclipse.jdt.core; plug-in org.eclipse.jdt.core)<br>
+        (closing the gap between resource based compilation units and working copies)</h4>
+<ul>
+	<li>Prior to 3.0, going from a resource based compilation unit (i.e. a compilation unit representing a file on disk) to the corresponding 
+		 shared working copy was tedious. For example, the Package Explorer had to fiirst find the children of a package fragment, then for 
+		 each compilation unit it had to find if a shared working copy had been created.
+	</li>
+	<li>Also doing a Java model operation in the context of a set of shared working copies was not possible. For example a refactoring 
+		operation had to save all editors prior to doing any change so as to have a consistent model.
+	</li>
+	<li>The notion of working copy owner got introduced to define a set of shared working copies to work on. This replaces the
+		 notion of buffer factory that was used to share working copies. The name 'owner' being more explicit.
+	</li>
+	<li>A working copy is now created for a given working copy owner. Java model operations that need to work on a set of working 
+		 copies can now be passed a working copy owner and this operation will consider the working copies before the compilation units.
+	</li>
+	<li>A class is used instead of an interface so that a default implementation for <code>createBuffer(...)</code> can be
+		 provided.
+	</li>
+	<li>Clients that used <code>IBufferFactory</code> should now subclass <code>WorkingCopyOwner</code> and pass this working
+		  copy owner to the Java model operation in lieu of the buffer factory. The simplest implementation being: 
+		  <code>new WorkingCopyOwner() {}</code>
+	</li>
+	<li>A Package Explorer like client that used to have such code:
+	<pre>
+	IBufferFactory factory = ...
+	
+	// Create a shared working copy for this buffer factory (to show it in an editor)
+	ICompilationUnit cu = ...
+	IWorkingCopy copy = cu.getSharedWorkingCopy(null/*no progress monitor*/, factory, null/*no problem reporter*/);
+	
+	// Find out the children of a package
+	IPackageFragment pkg = ...
+	ICompilationUnit[] cus = pkg.getCompilationUnits();
+	for (int i = 0; i < cus.length; i++) {
+		ICompilationUnit copy = (ICompilationUnit) cus[i].findSharedWorkingCopy(factory);
+		if (copy != null) {
+			cus[i] = copy;
+		}
+	}
+	</pre>
+	would now convert this code to:
+	<pre>
+	WorkingCopyOwner owner = ...
+	
+	// Create a shared working copy for this working copy owner (to show it in an editor)
+	ICompilationUnit cu = ...
+	ICompilationUnit copy = cu.getWorkingCopy(owner, null/*no problem reporter*/, null/*no progress monitor*/);
+	
+	// Find out the children of a package
+	IPackageFragment pkg = ...
+	ICompilationUnit[] cus = pkg.getCompilationUnits(owner);
+	</pre>
+	</li>
+	<li>A refactoring like client that used to have to save all editors before proceding can now work with working copies:
+	<pre>
+	WorkingCopyOwner owner = ...
+	
+	// Search for references to a method in the working copies of the given owner
+	IMethod method = ....
+	IJavaSearchScope scope = ...
+	IJavaSearchResultCollector resultCollector = ...
+	SearchEngine searchEngine = new SearchEngine(owner);
+	searchEngine.search(ResourcesPlugin.getWorkspace(), method, REFERENCES, scope, resultCollector);
+	
+	// Build AST for a compilation unit that contains a reference to the method
+	// and build its bindings in the context of the working copies of the given owner
+	ICompilationUnit cu = ...;
+	CompilationUnit ast = AST.parseCompilationUnit(cu, true /*resolve bindings*/, owner) ;
+	</pre>
+	</li>
+	<li>[TODO: add a table for conversion of IBufferFactory usage to WorkingCopyOwner usage]
+	</li>
+</ul>
+
+</body>
+
+</html>
diff --git a/org.eclipse.jdt.core/plugin.properties b/org.eclipse.jdt.core/plugin.properties
index c22753d..61f9ac7 100644
--- a/org.eclipse.jdt.core/plugin.properties
+++ b/org.eclipse.jdt.core/plugin.properties
@@ -13,7 +13,7 @@
 javaNatureName=Java
 javaBuilderName=Java Builder
 javaProblemName=Java Problem
-buildPathProblemName=Build path Problem
+buildPathProblemName=Build Path Problem
 transientJavaProblemName=Transient Java Problem
 classpathVariableInitializersName=Classpath Variable Initializers
 classpathContainerInitializersName=Classpath Container Initializers
diff --git a/org.eclipse.jdt.core/plugin.xml b/org.eclipse.jdt.core/plugin.xml
index 57a804c..4a3369a 100644
--- a/org.eclipse.jdt.core/plugin.xml
+++ b/org.eclipse.jdt.core/plugin.xml
@@ -1,13 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
-
+<?eclipse version="3.0"?>
 <!-- =================================================================================== -->
 <!-- JDT/CORE Plug-in Manifest                                                           -->
 <!-- =================================================================================== -->
-
 <plugin
     name = "%pluginName"
     id = "org.eclipse.jdt.core"
-    version = "2.1.1"
+    version = "3.0.0"
     provider-name = "%providerName"
     class="org.eclipse.jdt.core.JavaCore">
 
@@ -17,7 +16,8 @@
 
 <requires>
     <import plugin="org.eclipse.core.resources"/>
-    <import plugin="org.apache.xerces"/>
+    <import plugin="org.eclipse.core.runtime.compatibility" optional="true"/>    
+    <import plugin="org.eclipse.text"/>
     <import plugin="org.eclipse.ant.core" optional="true"/>
     <import plugin="org.eclipse.team.core" optional="true"/>
 </requires>
@@ -35,27 +35,6 @@
 
 <!-- =================================================================================== -->
 <!-- Extension Point: Initializers of Classpath Variables                                -->
-<!--                                                                                     -->
-<!-- <!ELEMENT classpathVariableInitializer>                                             -->
-<!--   <!ATTLIST classpathVariableInitializer                                            -->
-<!--    variable   CDATA #REQUIRED                                                       -->
-<!--    class      CDATA #REQUIRED                                                       -->
-<!--   >                                                                                 -->
-<!-- where:                                                                              -->
-<!--    - variable - the name of the classpath variable                                  -->                                               
-<!--    - class - the class that implements this classpath variable initializer.         --> 
-<!--              The class must implement a public subclass of                          -->
-<!--              org.eclipse.jdt.core.ClasspathVariableInitializer with a public        -->
-<!--              0-argument constructor.                                                -->
-<!--                                                                                     -->
-<!-- Example of an ClasspathVariableInitializer for a classpath variable named "FOO":    -->
-<!-- <extension                                                                          -->
-<!--      point="org.eclipse.jdt.core.classpathVariableInitializer">                     -->
-<!--    <classpathVariableInitializer                                                    -->
-<!--         variable="FOO"                                                              -->
-<!--         class="com.example.CPVInitializer"/>                                        -->
-<!-- </extension>                                                                        -->
-<!--                                                                                     -->
 <!-- =================================================================================== -->
 
 <extension-point name="%classpathVariableInitializersName" 
@@ -64,29 +43,6 @@
   
 <!-- =================================================================================== -->
 <!-- Extension Point: Initializers of Classpath Containers                               -->
-<!--                                                                                     -->
-<!-- <!ELEMENT classpathContainerInitializer>                                            -->
-<!--   <!ATTLIST containerResolver                                                       -->
-<!--    id     CDATA #REQUIRED                                                           -->
-<!--    class  CDATA #REQUIRED                                                           -->
-<!--   >                                                                                 -->
-<!-- where:                                                                              -->
-<!--    - id - a unique name identifying all containers for which this initializer will  -->
-<!--              be activated.                                                          -->
-<!--    - class - the class that implements this container initializer.                  --> 
-<!--              The class must implement a public subclass of                          -->
-<!--              org.eclipse.jdt.core.ClasspathContainerResolver with a public          -->
-<!--              0-argument constructor.                                                -->
-<!--                                                                                     -->
-<!-- Example of an ClasspathContainerInitializer for a classpath container named         -->
-<!-- "JDK/1.2":                                                                          -->
-<!-- <extension                                                                          -->
-<!--      point="org.eclipse.jdt.core.classpathContainerInitializer">                    -->
-<!--    <classpathContainerInitializer                                                   -->
-<!--         id="JDK"                                                                    -->
-<!--         class="com.example.MyInitializer"/>                                         -->
-<!-- </extension>                                                                        -->
-<!--                                                                                     -->
 <!-- =================================================================================== -->
 
 <extension-point name="%classpathContainerInitializersName" 
@@ -95,24 +51,6 @@
 
 <!-- =================================================================================== -->
 <!-- Extension Point: Formatter of Source Code                                           -->
-<!--                                                                                     -->
-<!-- <!ELEMENT codeFormatter>                                                            -->
-<!--   <!ATTLIST codeFormatter                                                           -->
-<!--    class      CDATA #REQUIRED                                                       -->
-<!--   >                                                                                 -->
-<!-- where:                                                                              -->
-<!--    - class - the class that defines the code formatter implementation.              --> 
-<!--              The class must be a public implementatiom of                           -->
-<!--              org.eclipse.jdt.core.ICodeFormatter with a public                      -->
-<!--              0-argument constructor.                                                -->
-<!--                                                                                     -->
-<!-- Example of an ICodeFormatter extension:                                             -->
-<!-- <extension                                                                          -->
-<!--      point="org.eclipse.jdt.core.codeFormatter">                                    -->
-<!--    <codeFormatter                                                                   -->
-<!--         class="com.example.MyCodeFormatter"/>                                       -->
-<!-- </extension>                                                                        -->
-<!--                                                                                     -->
 <!-- =================================================================================== -->
 
 <extension-point name="%codeFormattersName" 
@@ -202,7 +140,16 @@
 		library="jdtCompilerAdapter.jar">
 	</extraClasspathEntry>
 </extension> 
-   
+
+<!-- Tasks -->
+<extension point="org.eclipse.ant.core.antTasks">
+  <antTask
+  	name="eclipse.checkDebugAttributes"
+	class="org.eclipse.jdt.core.CheckDebugAttributes"
+	library="jdtCompilerAdapter.jar">
+  </antTask>
+</extension>
+      
 <!-- =================================================================================== -->
 <!-- Extension: Java file types                                                        -->
 <!-- =================================================================================== -->
diff --git a/org.eclipse.jdt.core/scripts/GenerateBuildScript.class b/org.eclipse.jdt.core/scripts/GenerateBuildScript.class
new file mode 100644
index 0000000..4e5222d
--- /dev/null
+++ b/org.eclipse.jdt.core/scripts/GenerateBuildScript.class
Binary files differ
diff --git a/org.eclipse.jdt.core/scripts/export-ejavac.xml b/org.eclipse.jdt.core/scripts/export-ejavac.xml
new file mode 100644
index 0000000..96faf31
--- /dev/null
+++ b/org.eclipse.jdt.core/scripts/export-ejavac.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="export-executable" default="build" basedir="..">
+
+	<property name="gcc-path" value="d:/gcc/gcc-3.4" />
+	<property name="binaryname" value="ejavac" />
+	<property name="dest" value="../../bingcj/" />
+	<property name="work" value="${dest}tmp/" />
+	<property name="gcj_script_name" value="export-executable.xml"/>
+
+    <target name="build">
+
+		<echo message="target: ${dest}" />
+		<mkdir dir="${dest}" />
+		<delete dir="${dest}" />
+		<mkdir dir="${dest}" />
+	
+		<copy todir="${work}">
+		    <fileset dir="batch/" excludes='**/*.html' />
+		</copy>
+		
+		<copy todir="${work}">
+		    <fileset dir="../GcjHelper/" includes='**/*.java' />
+		</copy>
+		
+		<copy todir="${work}">
+		    <fileset dir="compiler/" excludes='**/*.html' />
+		</copy>
+	
+		<echo message="generate build script" />
+		<java classname="GenerateBuildScript">
+			<sysproperty key="user.dir" value="${basedir}/scripts"/>
+			<arg value="${gcj_script_name}"/>
+			<arg value="${basedir}/${work}"/>
+			<classpath>
+				<pathelement path="${basedir}/scripts"/>
+			</classpath>
+		</java>
+		
+		<echo message="run the new build script" />
+		<ant antfile="${basedir}/scripts/export-executable.xml"/>
+		<delete file="${basedir}/scripts/export-executable.xml"/>
+	</target>
+</project>
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/scripts/exportplugin.xml b/org.eclipse.jdt.core/scripts/exportplugin.xml
index 2cf7dcf..67612f9 100644
--- a/org.eclipse.jdt.core/scripts/exportplugin.xml
+++ b/org.eclipse.jdt.core/scripts/exportplugin.xml
@@ -1,48 +1,48 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- build script to create a plugin from ${plugin} -->
-<project name="${plugin}" default="export plug-in [_2.1.1]" basedir="..">
+<project name="${plugin}" default="export plug-in [_3.0.0]" basedir="..">
 
 
-<target name="export plug-in [_2.2.0]">
+<target name="export plug-in [_3.0.0]">
 	<antcall target="zz_internal_export">
-		<param name="version" value="2.2.0"/>
+		<param name="jdt_core_version" value="3.0.0"/>
 	</antcall>
 </target>
 
 <target name="export plug-in [_2.1.1]">
 	<antcall target="zz_internal_export">
-		<param name="version" value="2.1.1"/>
+		<param name="jdt_core_version" value="2.1.1"/>
 	</antcall>
 </target>
 
 <target name="export plug-in [_2.1.0]">
 	<antcall target="zz_internal_export">
-		<param name="version" value="2.1.0"/>
+		<param name="jdt_core_version" value="2.1.0"/>
 	</antcall>
 </target>
 
 <target name="export plug-in [_2.1.0] (directory structure)">
 	<antcall target="zz_internal_export_structure">
-		<param name="version" value="2.1.0"/>
+		<param name="jdt_core_version" value="2.1.0"/>
 	</antcall>
 </target>
 
 <target name="export plug-in [_2.0.1]">
 	<antcall target="zz_internal_export">
-		<param name="version" value="2.0.1"/>
+		<param name="jdt_core_version" value="2.0.1"/>
 	</antcall>
 </target>
 
 <target name="export plug-in [_2.0.0]">
 	<antcall target="zz_internal_export">
-		<param name="version" value="2.0.0"/>
+		<param name="jdt_core_version" value="2.0.0"/>
 	</antcall>
 </target>
 
 <target name="export plug-in [_1.9.0]">
 	<antcall target="zz_internal_export">
-		<param name="version" value="1.9.0"/>
+		<param name="jdt_core_version" value="1.9.0"/>
 	</antcall>
 </target>
 
@@ -51,7 +51,7 @@
 	<tstamp/>
 	<property name="export-dir" value="../../plugin-export" />
 	<property name="plugin" value="org.eclipse.jdt.core" />
-	<property name="plugin-dir" value="${export-dir}/${plugin}_${version}"/>
+	<property name="plugin-dir" value="${export-dir}/${plugin}_${jdt_core_version}"/>
 
 	<echo message="TARGET: ${export-dir}" />
 	<mkdir dir="${export-dir}" />
@@ -61,14 +61,12 @@
 	<echo message="UPDATE jdtcore.jar" />
 	<jar 
 		jarfile="${plugin-dir}/jdtcore.jar"
-		basedir="bin" 
-		excludes="**/JDTCompilerAdapter.class"/>
+		basedir="bin"/>
 		
 	<echo message="UPDATE jdtCompilerAdapter.jar" />
 	<jar 
 		jarfile="${plugin-dir}/jdtCompilerAdapter.jar"
-		basedir="bin" 
-		includes="**/JDTCompilerAdapter.class"/>
+		basedir="antbin"/>
 
 	<echo message="UPDATE plugin.xml" />
 	<copy file="plugin.xml" todir="${plugin-dir}" />
@@ -98,10 +96,10 @@
 		<fileset dir="antadapter" />
 	</zip>	    
 
-	<echo message="UPDATE ${export-dir}/../${plugin}_${version}.zip" />
-	<zip zipfile="${export-dir}/../${plugin}_${version}.zip"
+	<echo message="UPDATE ${export-dir}/../${plugin}_${jdt_core_version}.zip" />
+	<zip zipfile="${export-dir}/../${plugin}_${jdt_core_version}.zip"
 	    basedir="${export-dir}" 
-	    includes="${plugin}_${version}/**"	/>		
+	    includes="${plugin}_${jdt_core_version}/**"	/>		
 </target>
 
 <target name="zz_internal_export_structure">
@@ -109,8 +107,8 @@
 	<tstamp/>
 	<property name="export-dir" value="../../plugin-export" />
 	<property name="plugin" value="org.eclipse.jdt.core" />
-	<property name="bin_dest" value="${export-dir}/eclipse/plugins/${plugin}_${version}"/>
-	<property name="src_dest" value="${export-dir}/eclipse/plugins/org.eclipse.jdt.source_${version}/src/${plugin}_${version}"/>
+	<property name="bin_dest" value="${export-dir}/eclipse/plugins/${plugin}_${jdt_core_version}"/>
+	<property name="src_dest" value="${export-dir}/eclipse/plugins/org.eclipse.jdt.source_${jdt_core_version}/src/${plugin}_${jdt_core_version}"/>
 
 	<echo message="TARGET: ${export-dir}" />
 	<mkdir dir="${export-dir}" />
@@ -123,13 +121,13 @@
 	<jar 
 		jarfile="${bin_dest}/jdtcore.jar"
 		basedir="bin" 
-		excludes="**/JDTCompilerAdapter.class"/>
+		excludes="**/JDTCompilerAdapter.class,**/antadapter/*"/>
 		
 	<echo message="UPDATE jdtCompilerAdapter.jar" />
 	<jar 
 		jarfile="${bin_dest}/jdtCompilerAdapter.jar"
 		basedir="bin" 
-		includes="**/JDTCompilerAdapter.class"/>
+		includes="**/JDTCompilerAdapter.class,**/antadapter/*"/>
 
 	<echo message="UPDATE plugin.xml" />
 	<copy file="plugin.xml" todir="${bin_dest}" />
@@ -144,7 +142,6 @@
 
 	<echo message="UPDATE jdtcoresrc.zip" />
 	<zip zipfile="${src_dest}/jdtcoresrc.zip">
-	    <fileset dir="antadapter" />
 	    <fileset dir="batch" />
 	    <fileset dir="codeassist" />
 	    <fileset dir="compiler" />
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
index d26ee65..bb12194 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
@@ -159,7 +159,7 @@
 	 * has not finished indexing the workspace. Results will more likely
 	 * not contain all the matches.
 	 */
-	int FORCE_IMMEDIATE_SEARCH = IJob.ForceImmediate;
+	int FORCE_IMMEDIATE_SEARCH = IJob.ForceImmediate; // TODO may discard for 3.0, since it isn't used anyway
 	/**
 	 * The search operation throws an <code>org.eclipse.core.runtime.OperationCanceledException</code>
 	 * if the underlying indexer has not finished indexing the workspace.
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchResultCollector.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchResultCollector.java
index ecc3fa3..ad8d7fb 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchResultCollector.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchResultCollector.java
@@ -39,6 +39,7 @@
  * </p>
  *
  * @see SearchEngine#search
+ * TODO (jerome) deprecate - should use SearchRequestor instead
  */
 public interface IJavaSearchResultCollector {
 	/**
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchScope.java
index 2674e13..475a4ee 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchScope.java
@@ -12,7 +12,6 @@
 
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.internal.core.index.impl.JarFileEntryDocument;
 
 /**
  * An <code>IJavaSearchScope</code> defines where search result should be found by a
@@ -23,12 +22,12 @@
  * clients may choose to implement this interface.
  */
 public interface IJavaSearchScope {
-	/**
-	 * This constant defines the separator of the resourcePath string of the <code>encloses(String)</code>
-	 * method. If present in the string, it separates the path to the jar file from the path
-	 * to the .class file in the jar.
-	 */
-	String JAR_FILE_ENTRY_SEPARATOR = JarFileEntryDocument.JAR_FILE_ENTRY_SEPARATOR;
+/**
+ * This constant defines the separator of the resourcePath string of the <code>encloses(String)</code>
+ * method. If present in the string, it separates the path to the jar file from the path
+ * to the .class file in the jar.
+ */
+String JAR_FILE_ENTRY_SEPARATOR = "|"; //$NON-NLS-1$
 /**
  * Checks whether the resource at the given path is enclosed by this scope.
  *
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/ISearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/ISearchPattern.java
index b63f89f..2314df9 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/ISearchPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/ISearchPattern.java
@@ -16,6 +16,8 @@
  *
  * @see SearchEngine#createSearchPattern(IJavaElement, int)
  * @see SearchEngine#createSearchPattern(String, int, int, boolean)
+ * TODO (jerome) deprecate this interface - should use SearchPattern instead
  */
 public interface ISearchPattern {
+	// used as a marker interface: contains no methods
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchDocument.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchDocument.java
new file mode 100644
index 0000000..0ec14d7
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchDocument.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.core.search;
+
+/**
+ * TODO (jerome) spec
+ * @since 3.0
+ */
+public class SearchDocument {
+	protected String documentPath;
+	protected SearchParticipant participant;
+
+	public SearchDocument(String documentPath, SearchParticipant participant) {
+		this.documentPath = documentPath;
+		this.participant = participant;
+	}
+
+	/**
+	 * Contents may be different from actual resource at corresponding document path,
+	 * in case of preprocessing.
+	 */
+	public byte[] getByteContents() {
+		return null;
+	}
+
+	/**
+	 * Contents may be different from actual resource at corresponding document path,
+	 * in case of preprocessing.
+	 */
+	public char[] getCharContents() {
+		return null;
+	}
+
+	/**
+	 * Returns the encoding for this document
+	 */
+	public String getEncoding() {
+		return null;
+	}
+
+	/**
+	 * Returns the participant that created this document
+	 */
+	public SearchParticipant getParticipant() {
+		return this.participant;
+	}
+	
+	/**
+	 * Path to the original document to publicly mention in index or search results.
+	 */	
+	public String getPath() {
+		return this.documentPath;
+	}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchEngine.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchEngine.java
index da02e62..923a2e0 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchEngine.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchEngine.java
@@ -14,19 +14,28 @@
 import org.eclipse.core.runtime.*;
 
 import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.search.*;
 import org.eclipse.jdt.internal.core.search.HierarchyScope;
-import org.eclipse.jdt.internal.core.search.IndexSearchAdapter;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.IInfoConstants;
 import org.eclipse.jdt.internal.core.search.JavaSearchScope;
 import org.eclipse.jdt.internal.core.search.JavaWorkspaceScope;
 import org.eclipse.jdt.internal.core.search.PatternSearchJob;
-import org.eclipse.jdt.internal.core.search.PathCollector;
-import org.eclipse.jdt.internal.core.search.Util;
 import org.eclipse.jdt.internal.core.search.indexing.*;
 import org.eclipse.jdt.internal.core.search.matching.*;
+import org.eclipse.jdt.internal.core.util.Util;
 
 import java.util.*;
 
@@ -44,729 +53,1045 @@
  * <p>
  * This class may be instantiated; it is not intended to be subclassed.
  * </p>
+ * TODO remove IWorkspace argument on the search methods before 3.0
  */
 public class SearchEngine {
 
-/**
- * A list of working copies that take precedence over their original 
- * compilation units.
- */
-private IWorkingCopy[] workingCopies = null;
-
-/**
- * For tracing purpose.
- */	
-public static boolean VERBOSE = false;	
-
-/**
- * Creates a new search engine.
- */
-public SearchEngine() {
-}
-/**
- * Creates a new search engine with a list of working copies that will take precedence over 
- * their original compilation units in the subsequent search operations.
- * <p>
- * Note that passing an empty working copy will be as if the original compilation
- * unit had been deleted.</p>
- * 
- * @param workingCopies the working copies that take precedence over their original compilation units
- * @since 2.0
- */
-public SearchEngine(IWorkingCopy[] workingCopies) {
-	this.workingCopies = workingCopies;
-}
-/*
- * Removes from the given list of working copies the ones that cannot see the given focus.
- */
-private IWorkingCopy[] filterWorkingCopies(IWorkingCopy[] workingCopies, IJavaElement focus, boolean isPolymorphicSearch) {
-	if (focus == null || workingCopies == null) return workingCopies;
-	while (!(focus instanceof IJavaProject) && !(focus instanceof JarPackageFragmentRoot)) {
-		focus = focus.getParent();
-	}
-	int length = workingCopies.length;
-	IWorkingCopy[] result = null;
-	int index = -1;
-	for (int i=0; i<length; i++) {
-		IWorkingCopy workingCopy = workingCopies[i];
-		IPath projectOrJar = IndexSelector.getProjectOrJar((IJavaElement)workingCopy).getPath();
-		if (!IndexSelector.canSeeFocus(focus, isPolymorphicSearch, projectOrJar)) {
-			if (result == null) {
-				result = new IWorkingCopy[length-1];
-				System.arraycopy(workingCopies, 0, result, 0, i);
-				index = i;
-			}
-		} else if (result != null) {
-			result[index++] = workingCopy;
+	class ResultCollectorAdapter extends SearchRequestor {
+		IJavaSearchResultCollector resultCollector;
+		ResultCollectorAdapter(IJavaSearchResultCollector resultCollector) {
+			this.resultCollector = resultCollector;
+		}
+		public boolean acceptSearchMatch(SearchMatch match) throws CoreException {
+			JavaSearchMatch javaSearchMatch = (JavaSearchMatch) match;
+			this.resultCollector.accept(
+				javaSearchMatch.resource,
+				javaSearchMatch.getSourceStart(),
+				javaSearchMatch.getSourceEnd(),
+				javaSearchMatch.element,
+				javaSearchMatch.getAccuracy()
+			);
+			return true;
+		}
+		public void beginReporting() {
+			this.resultCollector.aboutToStart();
+		}
+		public void endReporting() {
+			this.resultCollector.done();
+		}
+		public void enterParticipant(SearchParticipant participant) {
+			// Nothing to do since only one Java search participant
+		}
+		public void exitParticipant(SearchParticipant participant) {
+			// Nothing to do since only one Java search participant
 		}
 	}
-	if (result != null) {
-		if (result.length != index) {
-			System.arraycopy(result, 0, result = new IWorkingCopy[index], 0, index);
+		
+	/*
+	 * A default parser to parse non-reconciled working copies
+	 */
+	private Parser parser;
+	private CompilerOptions compilerOptions;
+		
+	/*
+	 * A list of working copies that take precedence over their original 
+	 * compilation units.
+	 */
+	private ICompilationUnit[] workingCopies;
+	
+	/*
+	 * A working copy owner whose working copies will take precedent over 
+	 * their original compilation units.
+	 */
+	private WorkingCopyOwner workingCopyOwner;
+	
+	/**
+	 * For tracing purpose.
+	 */	
+	public static boolean VERBOSE = false;	
+	
+	/**
+	 * Creates a new search engine.
+	 */
+	public SearchEngine() {
+		// will use working copies of PRIMARY owner
+	}
+	
+	/**
+	 * Creates a new search engine with a list of working copies that will take precedence over 
+	 * their original compilation units in the subsequent search operations.
+	 * <p>
+	 * Note that passing an empty working copy will be as if the original compilation
+	 * unit had been deleted.</p>
+	 * <p>
+	 * Since 3.0 the given working copies take precedence over primary working copies (if any).
+	 * 
+	 * @param workingCopies the working copies that take precedence over their original compilation units
+	 * @since 3.0
+	 */
+	public SearchEngine(ICompilationUnit[] workingCopies) {
+		this.workingCopies = workingCopies;
+	}
+	/**
+	 * Creates a new search engine with a list of working copies that will take precedence over 
+	 * their original compilation units in the subsequent search operations.
+	 * <p>
+	 * Note that passing an empty working copy will be as if the original compilation
+	 * unit had been deleted.</p>
+	 * <p>
+	 * Since 3.0 the given working copies take precedence over primary working copies (if any).
+	 * 
+	 * @param workingCopies the working copies that take precedence over their original compilation units
+	 * @since 2.0
+	 * @deprecated use #SearchEngine(ICompilationUnit[]) instead
+	 */
+	public SearchEngine(IWorkingCopy[] workingCopies) {
+		int length = workingCopies.length;
+		System.arraycopy(workingCopies, 0, this.workingCopies = new ICompilationUnit[length], 0, length);
+	}
+	
+	/**
+	 * Creates a new search engine with the given working copy owner.
+	 * The working copies owned by this owner will take precedence over 
+	 * the primary compilation units in the subsequent search operations.
+	 * 
+	 * @param workingCopyOwner the owner of the working copies that take precedence over their original compilation units
+	 * @since 3.0
+	 */
+	public SearchEngine(WorkingCopyOwner workingCopyOwner) {
+		this.workingCopyOwner = workingCopyOwner;
+	}
+	
+	/**
+	 * Returns a java search scope limited to the hierarchy of the given type.
+	 * The java elements resulting from a search with this scope will
+	 * be types in this hierarchy, or members of the types in this hierarchy.
+	 *
+	 * @param type the focus of the hierarchy scope
+	 * @return a new hierarchy scope
+	 * @exception JavaModelException if the hierarchy could not be computed on the given type
+	 */
+	public static IJavaSearchScope createHierarchyScope(IType type) throws JavaModelException {
+		return createHierarchyScope(type, DefaultWorkingCopyOwner.PRIMARY);
+	}
+	
+	/**
+	 * Returns a java search scope limited to the hierarchy of the given type.
+	 * When the hierarchy is computed, the types defined in the working copies owned
+	 * by the given owner take precedence over the original compilation units.
+	 * The java elements resulting from a search with this scope will
+	 * be types in this hierarchy, or members of the types in this hierarchy.
+	 *
+	 * @param type the focus of the hierarchy scope
+	 * @param owner the owner of working copies that take precedence over original compilation units
+	 * @return a new hierarchy scope
+	 * @exception JavaModelException if the hierarchy could not be computed on the given type
+	 * @since 3.0
+	 */
+	public static IJavaSearchScope createHierarchyScope(IType type, WorkingCopyOwner owner) throws JavaModelException {
+		return new HierarchyScope(type, owner);
+	}
+
+	/**
+	 * Returns a java search scope limited to the given resources.
+	 * The java elements resulting from a search with this scope will
+	 * have their underlying resource included in or equals to one of the given
+	 * resources.
+	 * <p>
+	 * Resources must not overlap, for example, one cannot include a folder and its children.
+	 * </p>
+	 *
+	 * @param resources the resources the scope is limited to
+	 * @return a new java search scope
+	 * @deprecated Use createJavaSearchScope(IJavaElement[]) instead
+	 */
+	public static IJavaSearchScope createJavaSearchScope(IResource[] resources) {
+		int length = resources.length;
+		IJavaElement[] elements = new IJavaElement[length];
+		for (int i = 0; i < length; i++) {
+			elements[i] = JavaCore.create(resources[i]);
+		}
+		return createJavaSearchScope(elements);
+	}
+
+	/**
+	 * Returns a java search scope limited to the given java elements.
+	 * The java elements resulting from a search with this scope will
+	 * be children of the given elements.
+	 * <p>
+	 * If an element is an IJavaProject, then the project's source folders, 
+	 * its jars (external and internal) and its referenced projects (with their source 
+	 * folders and jars, recursively) will be included.
+	 * If an element is an IPackageFragmentRoot, then only the package fragments of 
+	 * this package fragment root will be included.
+	 * If an element is an IPackageFragment, then only the compilation unit and class 
+	 * files of this package fragment will be included. Subpackages will NOT be 
+	 * included.</p>
+	 * <p>
+	 * In other words, this is equivalent to using SearchEngine.createJavaSearchScope(elements, true).</p>
+	 *
+	 * @param elements the java elements the scope is limited to
+	 * @return a new java search scope
+	 * @since 2.0
+	 */
+	public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements) {
+		return createJavaSearchScope(elements, true);
+	}
+
+	/**
+	 * Returns a java search scope limited to the given java elements.
+	 * The java elements resulting from a search with this scope will
+	 * be children of the given elements.
+	 * 
+	 * If an element is an IJavaProject, then the project's source folders, 
+	 * its jars (external and internal) and - if specified - its referenced projects 
+	 * (with their source folders and jars, recursively) will be included.
+	 * If an element is an IPackageFragmentRoot, then only the package fragments of 
+	 * this package fragment root will be included.
+	 * If an element is an IPackageFragment, then only the compilation unit and class 
+	 * files of this package fragment will be included. Subpackages will NOT be 
+	 * included.
+	 *
+	 * @param elements the java elements the scope is limited to
+	 * @param includeReferencedProjects a flag indicating if referenced projects must be 
+	 * 									 recursively included
+	 * @return a new java search scope
+	 * @since 2.0
+	 */
+	public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements, boolean includeReferencedProjects) {
+		JavaSearchScope scope = new JavaSearchScope();
+		HashSet visitedProjects = new HashSet(2);
+		for (int i = 0, length = elements.length; i < length; i++) {
+			IJavaElement element = elements[i];
+			if (element != null) {
+				try {
+					if (element instanceof IJavaProject) {
+						scope.add((IJavaProject)element, includeReferencedProjects, visitedProjects);
+					} else {
+						scope.add(element);
+					}
+				} catch (JavaModelException e) {
+					// ignore
+				}
+			}
+		}
+		return scope;
+	}
+
+	/**
+	 * Returns a search pattern that combines the given two patterns into a "and" pattern.
+	 * The search result will match both the left pattern and the right pattern.
+	 *
+	 * @param leftPattern the left pattern
+	 * @param rightPattern the right pattern
+	 * @return a "and" pattern
+     * @since 3.0
+	 */
+	public static SearchPattern createAndSearchPattern(final SearchPattern leftPattern, final SearchPattern rightPattern) {
+		return new AndPattern(0/*no kind*/, 0/*no rule*/){
+			SearchPattern current = leftPattern;
+			public void decodeIndexKey(char[] key) {
+				current.decodeIndexKey(key);
+
+			}
+			public char[] encodeIndexKey() {
+				return current.encodeIndexKey();
+			}
+			public SearchPattern getIndexRecord() {
+				return current.getIndexRecord();
+			}
+			public char[][] getMatchCategories() {
+				return current.getMatchCategories();
+			}
+			public int getMatchRule() {
+				return current.getMatchRule();
+			}
+			protected boolean hasNextQuery() {
+				if (current == leftPattern) {
+					current = rightPattern;
+					return true;
+				}
+				return false; 
+			}
+			public boolean isMatchingIndexRecord() {
+				return current.isMatchingIndexRecord();
+			}
+			protected void resetQuery() {
+				current = leftPattern;
+			}
+		};
+	}
+	
+	/**
+	 * Returns a search pattern that combines the given two patterns into a "or" pattern.
+	 * The search result will match either the left pattern or the right pattern.
+	 *
+	 * @param leftPattern the left pattern
+	 * @param rightPattern the right pattern
+	 * @return a "or" pattern
+	 */
+	public static ISearchPattern createOrSearchPattern(ISearchPattern leftPattern, ISearchPattern rightPattern) {
+		return new OrPattern((SearchPattern)leftPattern, (SearchPattern)rightPattern);
+	}
+	
+	/**
+	 * Returns a search pattern based on a given string pattern. The string patterns support '*' wild-cards.
+	 * The remaining parameters are used to narrow down the type of expected results.
+	 *
+	 * <br>
+	 *	Examples:
+	 *	<ul>
+	 * 		<li>search for case insensitive references to <code>Object</code>:
+	 *			<code>createSearchPattern("Object", TYPE, REFERENCES, false);</code></li>
+	 *  	<li>search for case sensitive references to exact <code>Object()</code> constructor:
+	 *			<code>createSearchPattern("java.lang.Object()", CONSTRUCTOR, REFERENCES, true);</code></li>
+	 *  	<li>search for implementers of <code>java.lang.Runnable</code>:
+	 *			<code>createSearchPattern("java.lang.Runnable", TYPE, IMPLEMENTORS, true);</code></li>
+	 *  </ul>
+	 * @param stringPattern the given pattern
+	 * @param searchFor determines the nature of the searched elements
+	 *	<ul>
+	 * 	<li><code>IJavaSearchConstants.CLASS</code>: only look for classes</li>
+	 *		<li><code>IJavaSearchConstants.INTERFACE</code>: only look for interfaces</li>
+	 * 	<li><code>IJavaSearchConstants.TYPE</code>: look for both classes and interfaces</li>
+	 *		<li><code>IJavaSearchConstants.FIELD</code>: look for fields</li>
+	 *		<li><code>IJavaSearchConstants.METHOD</code>: look for methods</li>
+	 *		<li><code>IJavaSearchConstants.CONSTRUCTOR</code>: look for constructors</li>
+	 *		<li><code>IJavaSearchConstants.PACKAGE</code>: look for packages</li>
+	 *	</ul>
+	 * @param limitTo determines the nature of the expected matches
+	 *	<ul>
+	 * 		<li><code>IJavaSearchConstants.DECLARATIONS</code>: will search declarations matching with the corresponding
+	 * 			element. In case the element is a method, declarations of matching methods in subtypes will also
+	 *  		be found, allowing to find declarations of abstract methods, etc.</li>
+	 *
+	 *		 <li><code>IJavaSearchConstants.REFERENCES</code>: will search references to the given element.</li>
+	 *
+	 *		 <li><code>IJavaSearchConstants.ALL_OCCURRENCES</code>: will search for either declarations or references as specified
+	 *  		above.</li>
+	 *
+	 *		 <li><code>IJavaSearchConstants.IMPLEMENTORS</code>: for interface, will find all types which implements a given interface.</li>
+	 *	</ul>
+	 *
+	 * @param isCaseSensitive indicates whether the search is case sensitive or not.
+	 * @return a search pattern on the given string pattern, or <code>null</code> if the string pattern is ill-formed.
+	 */
+	public static ISearchPattern createSearchPattern(String stringPattern, int searchFor, int limitTo, boolean isCaseSensitive) {
+		int matchMode;
+		if (stringPattern.indexOf('*') != -1 || stringPattern.indexOf('?') != -1) {
+			matchMode = IJavaSearchConstants.PATTERN_MATCH;
+		} else {
+			matchMode = IJavaSearchConstants.EXACT_MATCH;
+		}
+		return SearchPattern.createPattern(stringPattern, searchFor, limitTo, matchMode, isCaseSensitive);
+	}
+	
+	/**
+	 * Returns a search pattern based on a given Java element. 
+	 * The pattern is used to trigger the appropriate search, and can be parameterized as follows:
+	 *
+	 * @param element the java element the search pattern is based on
+	 * @param limitTo determines the nature of the expected matches
+	 * 	<ul>
+	 * 		<li><code>IJavaSearchConstants.DECLARATIONS</code>: will search declarations matching with the corresponding
+	 * 			element. In case the element is a method, declarations of matching methods in subtypes will also
+	 *  		be found, allowing to find declarations of abstract methods, etc.</li>
+	 *
+	 *		 <li><code>IJavaSearchConstants.REFERENCES</code>: will search references to the given element.</li>
+	 *
+	 *		 <li><code>IJavaSearchConstants.ALL_OCCURRENCES</code>: will search for either declarations or references as specified
+	 *  		above.</li>
+	 *
+	 *		 <li><code>IJavaSearchConstants.IMPLEMENTORS</code>: for interface, will find all types which implements a given interface.</li>
+	 *	</ul>
+	 * @return a search pattern for a java element or <code>null</code> if the given element is ill-formed
+	 */
+	public static ISearchPattern createSearchPattern(IJavaElement element, int limitTo) {
+	
+		return SearchPattern.createPattern(element, limitTo);
+	}
+	
+	/**
+	 * Returns a java search scope with the workspace as the only limit.
+	 *
+	 * @return a new workspace scope
+	 */
+	public static IJavaSearchScope createWorkspaceScope() {
+		return new JavaWorkspaceScope();
+	}
+	
+	/**
+	 * Returns default Java search participant
+	 * TODO add spec
+	 * @since 3.0
+	 */
+	public static SearchParticipant getDefaultSearchParticipant() {
+		
+		return new JavaSearchParticipant(null);
+	}
+
+	/**
+	 * Returns all registered search participants
+	 * TODO add spec
+	 * @since 3.0
+	 */
+	public static SearchParticipant[] getSearchParticipants() {
+		
+		Plugin plugin = JavaCore.getPlugin();
+		if (plugin == null) return SearchParticipant.NO_PARTICIPANT;
+	
+		IExtensionPoint extension = plugin.getDescriptor().getExtensionPoint(JavaModelManager.SEARCH_PARTICIPANT_EXTPOINT_ID);
+		if (extension != null) {
+			IExtension[] extensions =  extension.getExtensions();
+			int length = extensions.length;
+			SearchParticipant[] participants = new SearchParticipant[length+1];
+			// insert first the default Java participant (implicitly registered)
+			participants[0] = getDefaultSearchParticipant();
+			int found = 1;
+			for(int i = 0; i < extensions.length; i++){
+				IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
+				for(int j = 0, configLength = configElements.length; j < configLength; j++){
+					try {
+						Object execExt = configElements[j].createExecutableExtension("class"); //$NON-NLS-1$
+						if (execExt != null && execExt instanceof SearchParticipant){
+							participants[found++] = (SearchParticipant)execExt;
+						}
+					} catch(CoreException e) {
+						// executable extension could not be created: ignore this participant
+						if (SearchEngine.VERBOSE) {
+							System.out.println("Search - failed to instanciate participant: "+ configElements[j].getAttribute("class"));//$NON-NLS-2$//$NON-NLS-1$
+							e.printStackTrace();
+						}						
+					}
+				}
+			}	
+			if (found == 0) return SearchParticipant.NO_PARTICIPANT;
+			if (found < length) {
+				System.arraycopy(participants, 0, participants = new SearchParticipant[found], 0, found);
+			}
+			return participants;
+		}
+		// return default participant (implicitely registered)
+		return new SearchParticipant[] {getDefaultSearchParticipant()};
+	}
+
+	private Parser getParser() {
+		if (this.parser == null) {
+			this.compilerOptions = new CompilerOptions(JavaCore.getOptions());
+			ProblemReporter problemReporter =
+				new ProblemReporter(
+					DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+					this.compilerOptions,
+					new DefaultProblemFactory());
+			this.parser = new Parser(problemReporter, true);
+		}
+		return this.parser;
+	}
+	
+	/**
+	 * Returns the underlying resource of the given element.
+	 * @param element an IJavaElement
+	 * @return an IResource
+	 */
+	private IResource getResource(IJavaElement element) {
+		if (element instanceof IMember) {
+			ICompilationUnit cu = ((IMember)element).getCompilationUnit();
+			if (cu != null) {
+				return cu.getResource();
+			} 
+		} 
+		return element.getResource();
+	}
+	
+	/*
+	 * Returns the list of working copies used by this search engine.
+	 * Returns null if none.
+	 */
+	private ICompilationUnit[] getWorkingCopies() {
+		ICompilationUnit[] copies;
+		if (this.workingCopies != null) {
+			if (this.workingCopyOwner == null) {
+				copies = JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false/*don't add primary WCs a second time*/);
+				if (copies == null) {
+					copies = this.workingCopies;
+				} else {
+					HashMap pathToCUs = new HashMap();
+					for (int i = 0, length = copies.length; i < length; i++) {
+						ICompilationUnit unit = copies[i];
+						pathToCUs.put(unit.getPath(), unit);
+					}
+					for (int i = 0, length = this.workingCopies.length; i < length; i++) {
+						ICompilationUnit unit = this.workingCopies[i];
+						pathToCUs.put(unit.getPath(), unit);
+					}
+					int length = pathToCUs.size();
+					copies = new ICompilationUnit[length];
+					pathToCUs.values().toArray(copies);
+				}
+			} else {
+				copies = this.workingCopies;
+			}
+		} else if (this.workingCopyOwner != null) {
+			copies = JavaModelManager.getJavaModelManager().getWorkingCopies(this.workingCopyOwner, true/*add primary WCs*/);
+		} else {
+			copies = JavaModelManager.getJavaModelManager().getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false/*don't add primary WCs a second time*/);
+		}
+		if (copies == null) return null;
+		
+		// filter out primary working copies that are saved
+		ICompilationUnit[] result = null;
+		int length = copies.length;
+		int index = 0;
+		for (int i = 0; i < length; i++) {
+			CompilationUnit copy = (CompilationUnit)copies[i];
+			try {
+				if (!copy.isPrimary()
+						|| copy.hasUnsavedChanges()
+						|| copy.hasResourceChanged()) {
+					if (result == null) {
+						result = new ICompilationUnit[length];
+					}
+					result[index++] = copy;
+				}
+			}  catch (JavaModelException e) {
+				// copy doesn't exist: ignore
+			}
+		}
+		if (index != length && result != null) {
+			System.arraycopy(result, 0, result = new ICompilationUnit[index], 0, index);
 		}
 		return result;
-	} else {
-		return workingCopies;
 	}
-}
-/**
- * Returns a java search scope limited to the hierarchy of the given type.
- * The java elements resulting from a search with this scope will
- * be types in this hierarchy, or members of the types in this hierarchy.
- *
- * @param type the focus of the hierarchy scope
- * @return a new hierarchy scope
- * @exception JavaModelException if the hierarchy could not be computed on the given type
- */
-public static IJavaSearchScope createHierarchyScope(IType type) throws JavaModelException {
-	return new HierarchyScope(type);
-}
-/**
- * Returns a java search scope limited to the given resources.
- * The java elements resulting from a search with this scope will
- * have their underlying resource included in or equals to one of the given
- * resources.
- * <p>
- * Resources must not overlap, for example, one cannot include a folder and its children.
- * </p>
- *
- * @param resources the resources the scope is limited to
- * @return a new java search scope
- * @deprecated Use createJavaSearchScope(IJavaElement[]) instead
- */
-public static IJavaSearchScope createJavaSearchScope(IResource[] resources) {
-	int length = resources.length;
-	IJavaElement[] elements = new IJavaElement[length];
-	for (int i = 0; i < length; i++) {
-		elements[i] = JavaCore.create(resources[i]);
-	}
-	return createJavaSearchScope(elements);
-}
-/**
- * Returns a java search scope limited to the given java elements.
- * The java elements resulting from a search with this scope will
- * be children of the given elements.
- * <p>
- * If an element is an IJavaProject, then the project's source folders, 
- * its jars (external and internal) and its referenced projects (with their source 
- * folders and jars, recursively) will be included.
- * If an element is an IPackageFragmentRoot, then only the package fragments of 
- * this package fragment root will be included.
- * If an element is an IPackageFragment, then only the compilation unit and class 
- * files of this package fragment will be included. Subpackages will NOT be 
- * included.</p>
- * <p>
- * In other words, this is equivalent to using SearchEngine.createJavaSearchScope(elements, true).</p>
- *
- * @param elements the java elements the scope is limited to
- * @return a new java search scope
- * @since 2.0
- */
-public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements) {
-	return createJavaSearchScope(elements, true);
-}
-/**
- * Returns a java search scope limited to the given java elements.
- * The java elements resulting from a search with this scope will
- * be children of the given elements.
- * 
- * If an element is an IJavaProject, then the project's source folders, 
- * its jars (external and internal) and - if specified - its referenced projects 
- * (with their source folders and jars, recursively) will be included.
- * If an element is an IPackageFragmentRoot, then only the package fragments of 
- * this package fragment root will be included.
- * If an element is an IPackageFragment, then only the compilation unit and class 
- * files of this package fragment will be included. Subpackages will NOT be 
- * included.
- *
- * @param elements the java elements the scope is limited to
- * @param includeReferencedProjects a flag indicating if referenced projects must be 
- * 									 recursively included
- * @return a new java search scope
- * @since 2.0
- */
-public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements, boolean includeReferencedProjects) {
-	JavaSearchScope scope = new JavaSearchScope();
-	HashSet visitedProjects = new HashSet(2);
-	for (int i = 0, length = elements.length; i < length; i++) {
-		IJavaElement element = elements[i];
-		if (element != null) {
-			try {
-				if (element instanceof IJavaProject) {
-					scope.add((IJavaProject)element, includeReferencedProjects, visitedProjects);
+	
+	/**
+	 * Returns the list of working copies used to do the search on the given java element.
+	 * @param element an IJavaElement
+	 * @return an array of ICompilationUnit
+	 */
+	private ICompilationUnit[] getWorkingCopies(IJavaElement element) {
+		if (element instanceof IMember) {
+			ICompilationUnit cu = ((IMember)element).getCompilationUnit();
+			if (cu != null && cu.isWorkingCopy()) {
+				ICompilationUnit[] copies = getWorkingCopies();
+				int length = copies == null ? 0 : copies.length;
+				if (length > 0) {
+					ICompilationUnit[] newWorkingCopies = new ICompilationUnit[length+1];
+					System.arraycopy(copies, 0, newWorkingCopies, 0, length);
+					newWorkingCopies[length] = cu;
+					return newWorkingCopies;
 				} else {
-					scope.add(element);
+					return new ICompilationUnit[] {cu};
 				}
-			} catch (JavaModelException e) {
-				// ignore
 			}
 		}
+		return getWorkingCopies();
 	}
-	return scope;
-}
-/**
- * Returns a search pattern that combines the given two patterns into a "or" pattern.
- * The search result will match either the left pattern or the right pattern.
- *
- * @param leftPattern the left pattern
- * @param rightPattern the right pattern
- * @return a "or" pattern
- */
-public static ISearchPattern createOrSearchPattern(ISearchPattern leftPattern, ISearchPattern rightPattern) {
-	return new OrPattern((SearchPattern)leftPattern, (SearchPattern)rightPattern);
-}
-/**
- * Returns a search pattern based on a given string pattern. The string patterns support '*' wild-cards.
- * The remaining parameters are used to narrow down the type of expected results.
- *
- * <br>
- *	Examples:
- *	<ul>
- * 		<li>search for case insensitive references to <code>Object</code>:
- *			<code>createSearchPattern("Object", TYPE, REFERENCES, false);</code></li>
- *  	<li>search for case sensitive references to exact <code>Object()</code> constructor:
- *			<code>createSearchPattern("java.lang.Object()", CONSTRUCTOR, REFERENCES, true);</code></li>
- *  	<li>search for implementers of <code>java.lang.Runnable</code>:
- *			<code>createSearchPattern("java.lang.Runnable", TYPE, IMPLEMENTORS, true);</code></li>
- *  </ul>
- * @param stringPattern the given pattern
- * @param searchFor determines the nature of the searched elements
- *	<ul>
- * 		<li><code>IJavaSearchConstants.CLASS</code>: only look for classes</li>
- *		<li><code>IJavaSearchConstants.INTERFACE</code>: only look for interfaces</li>
- * 		<li><code>IJavaSearchConstants.TYPE</code>: look for both classes and interfaces</li>
- *		<li><code>IJavaSearchConstants.FIELD</code>: look for fields</li>
- *		<li><code>IJavaSearchConstants.METHOD</code>: look for methods</li>
- *		<li><code>IJavaSearchConstants.CONSTRUCTOR</code>: look for constructors</li>
- *		<li><code>IJavaSearchConstants.PACKAGE</code>: look for packages</li>
- *	</ul>
- * @param limitTo determines the nature of the expected matches
- *	<ul>
- * 		<li><code>IJavaSearchConstants.DECLARATIONS</code>: will search declarations matching with the corresponding
- * 			element. In case the element is a method, declarations of matching methods in subtypes will also
- *  		be found, allowing to find declarations of abstract methods, etc.</li>
- *
- *		 <li><code>IJavaSearchConstants.REFERENCES</code>: will search references to the given element.</li>
- *
- *		 <li><code>IJavaSearchConstants.ALL_OCCURRENCES</code>: will search for either declarations or references as specified
- *  		above.</li>
- *
- *		 <li><code>IJavaSearchConstants.IMPLEMENTORS</code>: for interface, will find all types which implements a given interface.</li>
- *	</ul>
- *
- * @param isCaseSensitive indicates whether the search is case sensitive or not.
- * @return a search pattern on the given string pattern, or <code>null</code> if the string pattern is ill-formed.
- */
-public static ISearchPattern createSearchPattern(String stringPattern, int searchFor, int limitTo, boolean isCaseSensitive) {
-	int matchMode;
-	if (stringPattern.indexOf('*') != -1 || stringPattern.indexOf('?') != -1) {
-		matchMode = IJavaSearchConstants.PATTERN_MATCH;
-	} else {
-		matchMode = IJavaSearchConstants.EXACT_MATCH;
-	}
-	return SearchPattern.createPattern(stringPattern, searchFor, limitTo, matchMode, isCaseSensitive);
-}
-/**
- * Returns a search pattern based on a given Java element. 
- * The pattern is used to trigger the appropriate search, and can be parameterized as follows:
- *
- * @param element the java element the search pattern is based on
- * @param limitTo determines the nature of the expected matches
- * 	<ul>
- * 		<li><code>IJavaSearchConstants.DECLARATIONS</code>: will search declarations matching with the corresponding
- * 			element. In case the element is a method, declarations of matching methods in subtypes will also
- *  		be found, allowing to find declarations of abstract methods, etc.</li>
- *
- *		 <li><code>IJavaSearchConstants.REFERENCES</code>: will search references to the given element.</li>
- *
- *		 <li><code>IJavaSearchConstants.ALL_OCCURRENCES</code>: will search for either declarations or references as specified
- *  		above.</li>
- *
- *		 <li><code>IJavaSearchConstants.IMPLEMENTORS</code>: for interface, will find all types which implements a given interface.</li>
- *	</ul>
- * @return a search pattern for a java element or <code>null</code> if the given element is ill-formed
- */
-public static ISearchPattern createSearchPattern(IJavaElement element, int limitTo) {
 
-	return SearchPattern.createPattern(element, limitTo);
-}
-/**
- * Returns a java search scope with the workspace as the only limit.
- *
- * @return a new workspace scope
- */
-public static IJavaSearchScope createWorkspaceScope() {
-	return new JavaWorkspaceScope();
-}
-/**
- * Returns the underlying resource of the given element.
- */
-private IResource getResource(IJavaElement element) {
-	if (element instanceof IMember) {
-		ICompilationUnit cu = ((IMember)element).getCompilationUnit();
-		if (cu != null) {
-			if (cu.isWorkingCopy()) {
-				return cu.getOriginalElement().getResource();
-			} else {
-				return cu.getResource();
-			}
-		} 
-	} 
-	return element.getResource();
-}
-/**
- * Returns the list of working copies used to do the search on the given java element.
- */
-private IWorkingCopy[] getWorkingCopies(IJavaElement element) {
-	if (element instanceof IMember) {
-		ICompilationUnit cu = ((IMember)element).getCompilationUnit();
-		if (cu != null && cu.isWorkingCopy()) {
-			int length = this.workingCopies == null ? 0 : this.workingCopies.length;
-			if (length > 0) {
-				IWorkingCopy[] newWorkingCopies = new IWorkingCopy[length+1];
-				System.arraycopy(this.workingCopies, 0, newWorkingCopies, 0, length);
-				newWorkingCopies[length] = cu;
-				return newWorkingCopies;
-			} else {
-				return new IWorkingCopy[] {cu};
-			}
+	boolean match(char classOrInterface, char[] patternPkg, char[] patternTypeName, int matchMode, boolean isCaseSensitive, boolean isClass, char[] pkg, char[] typeName) {
+		switch(classOrInterface) {
+			case IIndexConstants.CLASS_SUFFIX :
+				if (!isClass) return false;
+			case IIndexConstants.INTERFACE_SUFFIX :
+				if (isClass) return false;
+			case IIndexConstants.TYPE_SUFFIX : // nothing
 		}
-	}
-	return this.workingCopies;
-}
-/**
- * Searches for the Java element determined by the given signature. The signature
- * can be incomplete. For example, a call like 
- * <code>search(ws, "run()", METHOD,REFERENCES, col)</code>
- * searches for all references to the method <code>run</code>.
- *
- * Note that by default the pattern will be case insensitive. For specifying case s
- * sensitive search, use <code>search(workspace, createSearchPattern(patternString, searchFor, limitTo, true), scope, resultCollector);</code>
- * 
- * @param workspace the workspace
- * @param pattern the pattern to be searched for
- * @param searchFor a hint what kind of Java element the string pattern represents.
- *  Look into <code>IJavaSearchConstants</code> for valid values
- * @param limitTo one of the following values:
- *	<ul>
- *	  <li><code>IJavaSearchConstants.DECLARATIONS</code>: search 
- *		  for declarations only </li>
- *	  <li><code>IJavaSearchConstants.REFERENCES</code>: search 
- *		  for all references </li>
- *	  <li><code>IJavaSearchConstants.ALL_OCCURENCES</code>: search 
- *		  for both declarations and all references </li>
- *	  <li><code>IJavaSearchConstants.IMPLEMENTORS</code>: search for
- *		  all implementors of an interface; the value is only valid if
- *		  the Java element represents an interface</li>
- * 	</ul>
- * @param scope the search result has to be limited to the given scope
- * @param resultCollector a callback object to which each match is reported	 
- * @exception JavaModelException if the search failed. Reasons include:
- *	<ul>
- *		<li>the classpath is incorrectly set</li>
- *	</ul>
- */
-public void search(IWorkspace workspace, String patternString, int searchFor, int limitTo, IJavaSearchScope scope, IJavaSearchResultCollector resultCollector) throws JavaModelException {
-
-	search(workspace, createSearchPattern(patternString, searchFor, limitTo, true), scope, resultCollector);
-}
-/**
- * Searches for the given Java element.
- *
- * @param workspace the workspace
- * @param element the Java element to be searched for
- * @param limitTo one of the following values:
- *	<ul>
- *	  <li><code>IJavaSearchConstants.DECLARATIONS</code>: search 
- *		  for declarations only </li>
- *	  <li><code>IJavaSearchConstants.REFERENCES</code>: search 
- *		  for all references </li>
- *	  <li><code>IJavaSearchConstants.ALL_OCCURENCES</code>: search 
- *		  for both declarations and all references </li>
- *	  <li><code>IJavaSearchConstants.IMPLEMENTORS</code>: search for
- *		  all implementors of an interface; the value is only valid if
- *		  the Java element represents an interface</li>
- * 	</ul>
- * @param scope the search result has to be limited to the given scope
- * @param resultCollector a callback object to which each match is reported
- * @exception JavaModelException if the search failed. Reasons include:
- *	<ul>
- *		<li>the element doesn't exist</li>
- *		<li>the classpath is incorrectly set</li>
- *	</ul>
- */
-public void search(IWorkspace workspace, IJavaElement element, int limitTo, IJavaSearchScope scope, IJavaSearchResultCollector resultCollector) throws JavaModelException {
-
-	search(workspace, createSearchPattern(element, limitTo), scope, resultCollector);
-}
-/**
- * Searches for matches of a given search pattern. Search patterns can be created using helper
- * methods (from a String pattern or a Java element) and encapsulate the description of what is
- * being searched (for example, search method declarations in a case sensitive way).
- *
- * @param workspace the workspace
- * @param searchPattern the pattern to be searched for
- * @param scope the search result has to be limited to the given scope
- * @param resultCollector a callback object to which each match is reported
- * @exception JavaModelException if the search failed. Reasons include:
- *	<ul>
- *		<li>the classpath is incorrectly set</li>
- *	</ul>
- */
-public void search(IWorkspace workspace, ISearchPattern searchPattern, IJavaSearchScope scope, IJavaSearchResultCollector resultCollector) throws JavaModelException {
 	
-	if (VERBOSE) {
-		System.out.println("Searching for " + searchPattern + " in " + scope); //$NON-NLS-1$//$NON-NLS-2$
+		if (patternPkg != null && !CharOperation.equals(patternPkg, pkg, isCaseSensitive))
+			return false;
+	
+		if (patternTypeName != null) {
+			switch(matchMode) {
+				case IJavaSearchConstants.EXACT_MATCH :
+					return CharOperation.equals(patternTypeName, typeName, isCaseSensitive);
+				case IJavaSearchConstants.PREFIX_MATCH :
+					return CharOperation.prefixEquals(patternTypeName, typeName, isCaseSensitive);
+				case IJavaSearchConstants.PATTERN_MATCH :
+					return CharOperation.match(patternTypeName, typeName, isCaseSensitive);
+			}
+		}
+		return true;
+	
+	}	
+
+	/**
+	 * Searches for the Java element determined by the given signature. The signature
+	 * can be incomplete. For example, a call like 
+	 * <code>search(ws, "run()", METHOD,REFERENCES, col)</code>
+	 * searches for all references to the method <code>run</code>.
+	 *
+	 * Note that by default the pattern will be case insensitive. For specifying case s
+	 * sensitive search, use <code>search(workspace, createSearchPattern(patternString, searchFor, limitTo, true), scope, resultCollector);</code>
+	 * 
+	 * @param workspace the workspace
+	 * @param patternString the pattern to be searched for
+	 * @param searchFor a hint what kind of Java element the string pattern represents.
+	 *  Look into <code>IJavaSearchConstants</code> for valid values
+	 * @param limitTo one of the following values:
+	 *	<ul>
+	 *	  <li><code>IJavaSearchConstants.DECLARATIONS</code>: search 
+	 *		  for declarations only </li>
+	 *	  <li><code>IJavaSearchConstants.REFERENCES</code>: search 
+	 *		  for all references </li>
+	 *	  <li><code>IJavaSearchConstants.ALL_OCCURENCES</code>: search 
+	 *		  for both declarations and all references </li>
+	 *	  <li><code>IJavaSearchConstants.IMPLEMENTORS</code>: search for
+	 *		  all implementors of an interface; the value is only valid if
+	 *		  the Java element represents an interface</li>
+	 * 	</ul>
+	 * @param scope the search result has to be limited to the given scope
+	 * @param resultCollector a callback object to which each match is reported	 
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 */
+	public void search(IWorkspace workspace, String patternString, int searchFor, int limitTo, IJavaSearchScope scope, IJavaSearchResultCollector resultCollector) throws JavaModelException {
+		search(workspace, createSearchPattern(patternString, searchFor, limitTo, true), scope, resultCollector);
 	}
 
-	/* search is starting */
-	resultCollector.aboutToStart();
+	/**
+	 * Searches for the given Java element.
+	 *
+	 * @param workspace the workspace
+	 * @param element the Java element to be searched for
+	 * @param limitTo one of the following values:
+	 *	<ul>
+	 *	  <li><code>IJavaSearchConstants.DECLARATIONS</code>: search 
+	 *		  for declarations only </li>
+	 *	  <li><code>IJavaSearchConstants.REFERENCES</code>: search 
+	 *		  for all references </li>
+	 *	  <li><code>IJavaSearchConstants.ALL_OCCURENCES</code>: search 
+	 *		  for both declarations and all references </li>
+	 *	  <li><code>IJavaSearchConstants.IMPLEMENTORS</code>: search for
+	 *		  all implementors of an interface; the value is only valid if
+	 *		  the Java element represents an interface</li>
+	 * 	</ul>
+	 * @param scope the search result has to be limited to the given scope
+	 * @param resultCollector a callback object to which each match is reported
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the element doesn't exist</li>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 */
+	public void search(IWorkspace workspace, IJavaElement element, int limitTo, IJavaSearchScope scope, IJavaSearchResultCollector resultCollector) throws JavaModelException {
+		search(workspace, createSearchPattern(element, limitTo), scope, resultCollector);
+	}
 
-	try {	
-		if (searchPattern == null) return;
-
-		/* initialize progress monitor */
-		IProgressMonitor progressMonitor = resultCollector.getProgressMonitor();
-		if (progressMonitor != null) {
-			progressMonitor.beginTask(Util.bind("engine.searching"), 100); //$NON-NLS-1$
-		}
-
-		/* index search */
-		PathCollector pathCollector = new PathCollector();
-		
-		// In the case of a hierarchy scope make sure that the hierarchy is not computed.
-		// MatchLocator will filter out elements not in the hierarchy
-		SearchPattern pattern = (SearchPattern)searchPattern;
-		if (scope instanceof HierarchyScope) {
-			((HierarchyScope)scope).needsRefresh = false;
-			pattern.needsResolve = true; // force resolve to compute type bindings
-		}
-
-		IndexManager indexManager = ((JavaModelManager)JavaModelManager.getJavaModelManager())
-										.getIndexManager();
-		int detailLevel = IInfoConstants.PathInfo | IInfoConstants.PositionInfo;
-		MatchLocator matchLocator = 
-			new MatchLocator2(
-				pattern, 
-				detailLevel, 
-				resultCollector, 
-				scope,
-				progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 95)
-		);
-
-		indexManager.performConcurrentJob(
-			new PatternSearchJob(
-				pattern, 
+	/**
+	 * Searches for matches of a given search pattern. Search patterns can be created using helper
+	 * methods (from a String pattern or a Java element) and encapsulate the description of what is
+	 * being searched (for example, search method declarations in a case sensitive way).
+	 *
+	 * @param workspace the workspace
+	 * @param searchPattern the pattern to be searched for
+	 * @param scope the search result has to be limited to the given scope
+	 * @param resultCollector a callback object to which each match is reported
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 */
+	public void search(IWorkspace workspace, ISearchPattern searchPattern, IJavaSearchScope scope, IJavaSearchResultCollector resultCollector) throws JavaModelException {
+		try {
+			search(
+				(SearchPattern)searchPattern, 
+				new SearchParticipant[] {new JavaSearchParticipant(getWorkingCopies())}, 
 				scope, 
-				pattern.focus,
-				pattern.isPolymorphicSearch(),
-				detailLevel, 
-				pathCollector, 
-				indexManager),
-			IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
-			progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 5));
-			
-		/* eliminating false matches and locating them */
-		if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
-		matchLocator.locateMatches(
-			pathCollector.getPaths(), 
-			workspace,
-			filterWorkingCopies(this.workingCopies, pattern.focus, pattern.isPolymorphicSearch())
-		);
-		
-
-		if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
-		
-		if (progressMonitor != null) {
-			progressMonitor.done();
+				new ResultCollectorAdapter(resultCollector), 
+				resultCollector.getProgressMonitor());
+		} catch (CoreException e) {
+			if (e instanceof JavaModelException) {
+				throw (JavaModelException) e;
+			} else {
+				throw new JavaModelException(e);
+			}
 		}
-
-		matchLocator.locatePackageDeclarations(workspace);
-	} finally {
-		/* search has ended */
-		resultCollector.done();
 	}
-}
-/**
- * Searches for all top-level types and member types in the given scope.
- * The search can be selecting specific types (given a package or a type name
- * prefix and match modes). 
- * 
- * @param workspace the workspace to search in
- * @param packageName the full name of the package of the searched types, or a prefix for this
- *						package, or a wild-carded string for this package.
- * @param typeName the dot-separated qualified name of the searched type (the qualification include
- *					the enclosing types if the searched type is a member type), or a prefix
- *					for this type, or a wild-carded string for this type.
- * @param matchMode one of
- * <ul>
- *		<li><code>IJavaSearchConstants.EXACT_MATCH</code> if the package name and type name are the full names
- *			of the searched types.</li>
- *		<li><code>IJavaSearchConstants.PREFIX_MATCH</code> if the package name and type name are prefixes of the names
- *			of the searched types.</li>
- *		<li><code>IJavaSearchConstants.PATTERN_MATCH</code> if the package name and type name contain wild-cards.</li>
- * </ul>
- * @param isCaseSensitive whether the search should be case sensitive
- * @param searchFor one of
- * <ul>
- * 		<li><code>IJavaSearchConstants.CLASS</code> if searching for classes only</li>
- * 		<li><code>IJavaSearchConstants.INTERFACE</code> if searching for interfaces only</li>
- * 		<li><code>IJavaSearchConstants.TYPE</code> if searching for both classes and interfaces</li>
- * </ul>
- * @param scope the scope to search in
- * @param nameRequestor the requestor that collects the results of the search
- * @param waitingPolicy one of
- * <ul>
- *		<li><code>IJavaSearchConstants.FORCE_IMMEDIATE_SEARCH</code> if the search should start immediately</li>
- *		<li><code>IJavaSearchConstants.CANCEL_IF_NOT_READY_TO_SEARCH</code> if the search should be cancelled if the
- *			underlying indexer has not finished indexing the workspace</li>
- *		<li><code>IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH</code> if the search should wait for the
- *			underlying indexer to finish indexing the workspace</li>
- * </ul>
- * @param progressMonitor the progress monitor to report progress to, or <code>null</code> if no progress
- *							monitor is provided
- * @exception JavaModelException if the search failed. Reasons include:
- *	<ul>
- *		<li>the classpath is incorrectly set</li>
- *	</ul>
- */
-public void searchAllTypeNames(
-	IWorkspace workspace,
-	char[] packageName, 
-	char[] typeName,
-	int matchMode, 
-	boolean isCaseSensitive,
-	int searchFor, 
-	IJavaSearchScope scope, 
-	final ITypeNameRequestor nameRequestor,
-	int waitingPolicy,
-	IProgressMonitor progressMonitor)  throws JavaModelException {
-
-	IndexManager indexManager = ((JavaModelManager)JavaModelManager.getJavaModelManager()).getIndexManager();
-		
-	char classOrInterface;
-	switch(searchFor){
-		case IJavaSearchConstants.CLASS :
-			classOrInterface = IIndexConstants.CLASS_SUFFIX;
-			break;
-		case IJavaSearchConstants.INTERFACE :
-			classOrInterface = IIndexConstants.INTERFACE_SUFFIX;
-			break;
-		default : 
-			classOrInterface = IIndexConstants.TYPE_SUFFIX;
-			break;
-	}
-	SearchPattern pattern = new TypeDeclarationPattern(
-		packageName,
-		null, // do find member types
-		typeName,
-		classOrInterface,
-		matchMode, 
-		isCaseSensitive);
 	
-	IIndexSearchRequestor searchRequestor = new IndexSearchAdapter(){
-		public void acceptClassDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) {
-			if (enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR) { // filter out local and anonymous classes
-				nameRequestor.acceptClass(packageName, simpleTypeName, enclosingTypeNames, resourcePath);
-			}
-		}		
-		public void acceptInterfaceDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) {
-			if (enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR) { // filter out local and anonymous classes
-				nameRequestor.acceptInterface(packageName, simpleTypeName, enclosingTypeNames, resourcePath);
-			}
-		}		
-	};
+	/**
+	 * Searches for matches of a given search pattern. Search patterns can be created using helper
+	 * methods (from a String pattern or a Java element) and encapsulate the description of what is
+	 * being searched (for example, search method declarations in a case sensitive way).
+	 *
+	 * @param workspace the workspace
+	 * @param searchPattern the pattern to be searched for
+	 * @param scope the search result has to be limited to the given scope
+	 * @param resultCollector a callback object to which each match is reported
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 *@since 3.0
+	 *TODO add spec
+	 */
+	public void search(SearchPattern pattern, SearchParticipant[] participants, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException {
+		pattern.findMatches(participants, scope, requestor, monitor);
+	}
 
-	try {
-		if (progressMonitor != null) {
-			progressMonitor.beginTask(Util.bind("engine.searching"), 100); //$NON-NLS-1$
+	/**
+	 * Searches for all top-level types and member types in the given scope.
+	 * The search can be selecting specific types (given a package or a type name
+	 * prefix and match modes). 
+	 * 
+	 * @param workspace the workspace to search in
+	 * @param packageName the full name of the package of the searched types, or a prefix for this
+	 *						package, or a wild-carded string for this package.
+	 * @param typeName the dot-separated qualified name of the searched type (the qualification include
+	 *					the enclosing types if the searched type is a member type), or a prefix
+	 *					for this type, or a wild-carded string for this type.
+	 * @param matchMode one of
+	 * <ul>
+	 *		<li><code>IJavaSearchConstants.EXACT_MATCH</code> if the package name and type name are the full names
+	 *			of the searched types.</li>
+	 *		<li><code>IJavaSearchConstants.PREFIX_MATCH</code> if the package name and type name are prefixes of the names
+	 *			of the searched types.</li>
+	 *		<li><code>IJavaSearchConstants.PATTERN_MATCH</code> if the package name and type name contain wild-cards.</li>
+	 * </ul>
+	 * @param isCaseSensitive whether the search should be case sensitive
+	 * @param searchFor one of
+	 * <ul>
+	 * 		<li><code>IJavaSearchConstants.CLASS</code> if searching for classes only</li>
+	 * 		<li><code>IJavaSearchConstants.INTERFACE</code> if searching for interfaces only</li>
+	 * 		<li><code>IJavaSearchConstants.TYPE</code> if searching for both classes and interfaces</li>
+	 * </ul>
+	 * @param scope the scope to search in
+	 * @param nameRequestor the requestor that collects the results of the search
+	 * @param waitingPolicy one of
+	 * <ul>
+	 *		<li><code>IJavaSearchConstants.FORCE_IMMEDIATE_SEARCH</code> if the search should start immediately</li>
+	 *		<li><code>IJavaSearchConstants.CANCEL_IF_NOT_READY_TO_SEARCH</code> if the search should be cancelled if the
+	 *			underlying indexer has not finished indexing the workspace</li>
+	 *		<li><code>IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH</code> if the search should wait for the
+	 *			underlying indexer to finish indexing the workspace</li>
+	 * </ul>
+	 * @param progressMonitor the progress monitor to report progress to, or <code>null</code> if no progress
+	 *							monitor is provided
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 */
+	public void searchAllTypeNames(
+		IWorkspace workspace,
+		final char[] packageName, 
+		final char[] typeName,
+		final int matchMode, 
+		final boolean isCaseSensitive,
+		int searchFor, 
+		IJavaSearchScope scope, 
+		final ITypeNameRequestor nameRequestor,
+		int waitingPolicy,
+		IProgressMonitor progressMonitor)  throws JavaModelException {
+	
+		IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
+			
+		final char classOrInterface;
+		switch(searchFor){
+			case IJavaSearchConstants.CLASS :
+				classOrInterface = IIndexConstants.CLASS_SUFFIX;
+				break;
+			case IJavaSearchConstants.INTERFACE :
+				classOrInterface = IIndexConstants.INTERFACE_SUFFIX;
+				break;
+			default : 
+				classOrInterface = IIndexConstants.TYPE_SUFFIX;
+				break;
 		}
-		indexManager.performConcurrentJob(
-			new PatternSearchJob(pattern, scope, IInfoConstants.NameInfo | IInfoConstants.PathInfo, searchRequestor, indexManager),
-			waitingPolicy,
-			progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));	
-	} finally {
-		if (progressMonitor != null) {
-			progressMonitor.done();
+		final TypeDeclarationPattern pattern = new TypeDeclarationPattern(
+			packageName,
+			null, // do find member types
+			typeName,
+			classOrInterface,
+			isCaseSensitive ? matchMode | SearchPattern.R_CASE_SENSITIVE : matchMode);
+		
+		final HashSet workingCopyPaths = new HashSet();
+		ICompilationUnit[] copies = getWorkingCopies();
+		if (copies != null) {
+			for (int i = 0, length = copies.length; i < length; i++) {
+				ICompilationUnit workingCopy = copies[i];
+				workingCopyPaths.add(workingCopy.getPath().toString());
+			}
+		}
+	
+		IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){
+			public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant) {
+				TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord;
+				if (record.enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR  // filter out local and anonymous classes
+						&& !workingCopyPaths.contains(documentPath)) { // filter out working copies
+					boolean isClass = record.classOrInterface != IIndexConstants.INTERFACE_SUFFIX;
+					if (isClass) {
+						nameRequestor.acceptClass(record.pkg, record.simpleName, record.enclosingTypeNames, documentPath);
+					} else {
+						nameRequestor.acceptInterface(record.pkg, record.simpleName, record.enclosingTypeNames, documentPath);
+					}
+				}
+				return true;
+			}
+		};
+	
+		try {
+			if (progressMonitor != null) {
+				progressMonitor.beginTask(Util.bind("engine.searching"), 100); //$NON-NLS-1$
+			}
+			// add type names from indexes
+			indexManager.performConcurrentJob(
+				new PatternSearchJob(
+					pattern, 
+					new JavaSearchParticipant(getWorkingCopies()), // java search only
+					scope, 
+					searchRequestor),
+				waitingPolicy,
+				progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));	
+				
+			// add type names from working copies
+			if (copies != null) {
+				for (int i = 0, length = copies.length; i < length; i++) {
+					ICompilationUnit workingCopy = copies[i];
+					final String path = workingCopy.getPath().toString();
+					if (workingCopy.isConsistent()) {
+						IPackageDeclaration[] packageDeclarations = workingCopy.getPackageDeclarations();
+						char[] packageDeclaration = packageDeclarations.length == 0 ? CharOperation.NO_CHAR : packageDeclarations[0].getElementName().toCharArray();
+						IType[] allTypes = workingCopy.getAllTypes();
+						for (int j = 0, allTypesLength = allTypes.length; j < allTypesLength; j++) {
+							IType type = allTypes[j];
+							IJavaElement parent = type.getParent();
+							char[][] enclosingTypeNames;
+							if (parent instanceof IType) {
+								char[] parentQualifiedName = ((IType)parent).getTypeQualifiedName('.').toCharArray();
+								enclosingTypeNames = CharOperation.splitOn('.', parentQualifiedName);
+							} else {
+								enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
+							}
+							char[] simpleName = type.getElementName().toCharArray();
+							if (match(classOrInterface, packageName, typeName, matchMode, isCaseSensitive, type.isClass(), packageDeclaration, simpleName)) {
+								if (type.isClass()) {
+									nameRequestor.acceptClass(packageDeclaration, simpleName, enclosingTypeNames, path);
+								} else {
+									nameRequestor.acceptInterface(packageDeclaration, simpleName, enclosingTypeNames, path);
+								}
+							}
+						}
+					} else {
+						Parser basicParser = getParser();
+						final char[] contents = workingCopy.getBuffer().getCharacters();
+						org.eclipse.jdt.internal.compiler.env.ICompilationUnit unit = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit() {
+							public char[] getContents() {
+								return contents;
+							}
+							public char[] getMainTypeName() {
+								return null;
+							}
+							public char[][] getPackageName() {
+								return null;
+							}
+							public char[] getFileName() {
+								return null;
+							}
+						};
+						CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.compilerOptions.maxProblemsPerUnit);
+						CompilationUnitDeclaration parsedUnit = basicParser.dietParse(unit, compilationUnitResult);
+						if (parsedUnit != null) {
+							final char[] packageDeclaration = parsedUnit.currentPackage == null ? CharOperation.NO_CHAR : CharOperation.concatWith(parsedUnit.currentPackage.getImportName(), '.');
+							class AllTypeDeclarationsVisitor extends ASTVisitor {
+								public boolean visit(TypeDeclaration typeDeclaration, BlockScope blockScope) {
+									return false; // no local/anonymous type
+								}
+								public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope compilationUnitScope) {
+									if (match(classOrInterface, packageName, typeName, matchMode, isCaseSensitive, !typeDeclaration.isInterface(), packageDeclaration, typeDeclaration.name)) {
+										if (!typeDeclaration.isInterface()) {
+											nameRequestor.acceptClass(packageDeclaration, typeDeclaration.name, CharOperation.NO_CHAR_CHAR, path);
+										} else {
+											nameRequestor.acceptInterface(packageDeclaration, typeDeclaration.name, CharOperation.NO_CHAR_CHAR, path);
+										}
+									}
+									return true;
+								}
+								public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope classScope) {
+									if (match(classOrInterface, packageName, typeName, matchMode, isCaseSensitive, !memberTypeDeclaration.isInterface(), packageDeclaration, memberTypeDeclaration.name)) {
+										// compute encloising type names
+										TypeDeclaration enclosing = memberTypeDeclaration.enclosingType;
+										char[][] enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
+										while (enclosing != null) {
+											enclosingTypeNames = CharOperation.arrayConcat(new char[][] {enclosing.name}, enclosingTypeNames);
+											if ((enclosing.bits & ASTNode.IsMemberTypeMASK) != 0) {
+												enclosing = enclosing.enclosingType;
+											} else {
+												enclosing = null;
+											}
+										}
+										// report
+										if (!memberTypeDeclaration.isInterface()) {
+											nameRequestor.acceptClass(packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames, path);
+										} else {
+											nameRequestor.acceptInterface(packageDeclaration, memberTypeDeclaration.name, enclosingTypeNames, path);
+										}
+									}
+									return true;
+								}
+							}
+							parsedUnit.traverse(new AllTypeDeclarationsVisitor(), parsedUnit.scope);
+						}
+					}
+				}
+			}	
+		} finally {
+			if (progressMonitor != null) {
+				progressMonitor.done();
+			}
+		}
+	}	
+	
+	private void searchDeclarations(IWorkspace workspace, IJavaElement enclosingElement, IJavaSearchResultCollector resultCollector, SearchPattern pattern) throws JavaModelException {
+		IJavaSearchScope scope = createJavaSearchScope(new IJavaElement[] {enclosingElement});
+		IResource resource = this.getResource(enclosingElement);
+		if (resource instanceof IFile) {
+			if (VERBOSE) {
+				System.out.println("Searching for " + pattern + " in " + resource.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$
+			}
+			try {
+				SearchParticipant participant = new JavaSearchParticipant(getWorkingCopies(enclosingElement));
+				participant.locateMatches(
+					new SearchDocument[] {new JavaSearchDocument(enclosingElement.getPath().toString(), participant)}, 
+					pattern, 
+					scope, 
+					new ResultCollectorAdapter(resultCollector), 
+					resultCollector.getProgressMonitor());
+			} catch (CoreException e) {
+				if (e instanceof JavaModelException) {
+					throw (JavaModelException) e;
+				} else {
+					throw new JavaModelException(e);
+				}
+			}
+		} else {
+			search(workspace, pattern, scope, resultCollector);
 		}
 	}
-}
-/**
- * Searches for all declarations of the fields accessed in the given element.
- * The element can be a compilation unit, a type, or a method.
- * Reports the field declarations using the given collector.
- * <p>
- * Consider the following code:
- * <code>
- * <pre>
- *		class A {
- *			int field1;
- *		}
- *		class B extends A {
- *			String value;
- *		}
- *		class X {
- *			void test() {
- *				B b = new B();
- *				System.out.println(b.value + b.field1);
- *			};
- *		}
- * </pre>
- * </code>
- * then searching for declarations of accessed fields in method 
- * <code>X.test()</code> would collect the fields
- * <code>B.value</code> and <code>A.field1</code>.
- * </p>
- *
- * @param workspace the workspace
- * @param enclosingElement the method, type, or compilation unit to be searched in
- * @param resultCollector a callback object to which each match is reported
- * @exception JavaModelException if the search failed. Reasons include:
- *	<ul>
- *		<li>the element doesn't exist</li>
- *		<li>the classpath is incorrectly set</li>
- *	</ul>
- */	
-public void searchDeclarationsOfAccessedFields(IWorkspace workspace, IJavaElement enclosingElement, IJavaSearchResultCollector resultCollector) throws JavaModelException {
-	SearchPattern pattern = new DeclarationOfAccessedFieldsPattern(enclosingElement);
-	IJavaSearchScope scope = createJavaSearchScope(new IJavaElement[] {enclosingElement});
-	IResource resource = this.getResource(enclosingElement);
-	if (resource instanceof IFile) {
-		if (VERBOSE) {
-			System.out.println("Searching for " + pattern + " in " + resource.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$
-		}
-		MatchLocator locator = new MatchLocator2(
-			pattern,
-			IInfoConstants.DeclarationInfo,
-			resultCollector,
-			scope,
-			resultCollector.getProgressMonitor());
-		locator.locateMatches(
-			new String[] {resource.getFullPath().toString()}, 
-			workspace,
-			this.getWorkingCopies(enclosingElement));
-	} else {
-		search(workspace, pattern, scope, resultCollector);
-	}
-}
-/**
- * Searches for all declarations of the types referenced in the given element.
- * The element can be a compilation unit, a type, or a method.
- * Reports the type declarations using the given collector.
- * <p>
- * Consider the following code:
- * <code>
- * <pre>
- *		class A {
- *		}
- *		class B extends A {
- *		}
- *		interface I {
- *		  int VALUE = 0;
- *		}
- *		class X {
- *			void test() {
- *				B b = new B();
- *				this.foo(b, I.VALUE);
- *			};
- *		}
- * </pre>
- * </code>
- * then searching for declarations of referenced types in method <code>X.test()</code>
- * would collect the class <code>B</code> and the interface <code>I</code>.
- * </p>
- *
- * @param workspace the workspace
- * @param enclosingElement the method, type, or compilation unit to be searched in
- * @param resultCollector a callback object to which each match is reported
- * @exception JavaModelException if the search failed. Reasons include:
- *	<ul>
- *		<li>the element doesn't exist</li>
- *		<li>the classpath is incorrectly set</li>
- *	</ul>
- */	
-public void searchDeclarationsOfReferencedTypes(IWorkspace workspace, IJavaElement enclosingElement, IJavaSearchResultCollector resultCollector) throws JavaModelException {
-	SearchPattern pattern = new DeclarationOfReferencedTypesPattern(enclosingElement);
-	IJavaSearchScope scope = createJavaSearchScope(new IJavaElement[] {enclosingElement});
-	IResource resource = this.getResource(enclosingElement);
-	if (resource instanceof IFile) {
-		if (VERBOSE) {
-			System.out.println("Searching for " + pattern + " in " + resource.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$
-		}
-		MatchLocator locator = new MatchLocator2(
-			pattern,
-			IInfoConstants.DeclarationInfo,
-			resultCollector,
-			scope,
-			resultCollector.getProgressMonitor());
-		locator.locateMatches(
-			new String[] {resource.getFullPath().toString()}, 
-			workspace,
-			this.getWorkingCopies(enclosingElement));
-	} else {
-		search(workspace, pattern, scope, resultCollector);
-	}
-}
-/**
- * Searches for all declarations of the methods invoked in the given element.
- * The element can be a compilation unit, a type, or a method.
- * Reports the method declarations using the given collector.
- * <p>
- * Consider the following code:
- * <code>
- * <pre>
- *		class A {
- *			void foo() {};
- *			void bar() {};
- *		}
- *		class B extends A {
- *			void foo() {};
- *		}
- *		class X {
- *			void test() {
- *				A a = new B();
- *				a.foo();
- *				B b = (B)a;
- *				b.bar();
- *			};
- *		}
- * </pre>
- * </code>
- * then searching for declarations of sent messages in method 
- * <code>X.test()</code> would collect the methods
- * <code>A.foo()</code>, <code>B.foo()</code>, and <code>A.bar()</code>.
- * </p>
- *
- * @param workspace the workspace
- * @param enclosingElement the method, type, or compilation unit to be searched in
- * @param resultCollector a callback object to which each match is reported
- * @exception JavaModelException if the search failed. Reasons include:
- *	<ul>
- *		<li>the element doesn't exist</li>
- *		<li>the classpath is incorrectly set</li>
- *	</ul>
- */	
-public void searchDeclarationsOfSentMessages(IWorkspace workspace, IJavaElement enclosingElement, IJavaSearchResultCollector resultCollector) throws JavaModelException {
-	SearchPattern pattern = new DeclarationOfReferencedMethodsPattern(enclosingElement);
-	IJavaSearchScope scope = createJavaSearchScope(new IJavaElement[] {enclosingElement});
-	IResource resource = this.getResource(enclosingElement);
-	if (resource instanceof IFile) {
-		if (VERBOSE) {
-			System.out.println("Searching for " + pattern + " in " + resource.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$
-		}
-		MatchLocator locator = new MatchLocator2(
-			pattern,
-			IInfoConstants.DeclarationInfo,
-			resultCollector,
-			scope,
-			resultCollector.getProgressMonitor());
-		locator.locateMatches(
-			new String[] {resource.getFullPath().toString()}, 
-			workspace,
-			this.getWorkingCopies(enclosingElement));
-	} else {
-		search(workspace, pattern, scope, resultCollector);
-	}
-}
 
+	/**
+	 * Searches for all declarations of the fields accessed in the given element.
+	 * The element can be a compilation unit, a source type, or a source method.
+	 * Reports the field declarations using the given collector.
+	 * <p>
+	 * Consider the following code:
+	 * <code>
+	 * <pre>
+	 *		class A {
+	 *			int field1;
+	 *		}
+	 *		class B extends A {
+	 *			String value;
+	 *		}
+	 *		class X {
+	 *			void test() {
+	 *				B b = new B();
+	 *				System.out.println(b.value + b.field1);
+	 *			};
+	 *		}
+	 * </pre>
+	 * </code>
+	 * then searching for declarations of accessed fields in method 
+	 * <code>X.test()</code> would collect the fields
+	 * <code>B.value</code> and <code>A.field1</code>.
+	 * </p>
+	 *
+	 * @param workspace the workspace
+	 * @param enclosingElement the method, type, or compilation unit to be searched in
+	 * @param resultCollector a callback object to which each match is reported
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the element doesn't exist</li>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 */	
+	public void searchDeclarationsOfAccessedFields(IWorkspace workspace, IJavaElement enclosingElement, IJavaSearchResultCollector resultCollector) throws JavaModelException {
+		SearchPattern pattern = new DeclarationOfAccessedFieldsPattern(enclosingElement);
+		searchDeclarations(workspace, enclosingElement, resultCollector, pattern);
+	}
+	
+	/**
+	 * Searches for all declarations of the types referenced in the given element.
+	 * The element can be a compilation unit, a source type, or a source method.
+	 * Reports the type declarations using the given collector.
+	 * <p>
+	 * Consider the following code:
+	 * <code>
+	 * <pre>
+	 *		class A {
+	 *		}
+	 *		class B extends A {
+	 *		}
+	 *		interface I {
+	 *		  int VALUE = 0;
+	 *		}
+	 *		class X {
+	 *			void test() {
+	 *				B b = new B();
+	 *				this.foo(b, I.VALUE);
+	 *			};
+	 *		}
+	 * </pre>
+	 * </code>
+	 * then searching for declarations of referenced types in method <code>X.test()</code>
+	 * would collect the class <code>B</code> and the interface <code>I</code>.
+	 * </p>
+	 *
+	 * @param workspace the workspace
+	 * @param enclosingElement the method, type, or compilation unit to be searched in
+	 * @param resultCollector a callback object to which each match is reported
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the element doesn't exist</li>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 */	
+	public void searchDeclarationsOfReferencedTypes(IWorkspace workspace, IJavaElement enclosingElement, IJavaSearchResultCollector resultCollector) throws JavaModelException {
+		SearchPattern pattern = new DeclarationOfReferencedTypesPattern(enclosingElement);
+		searchDeclarations(workspace, enclosingElement, resultCollector, pattern);
+	}
+	
+	/**
+	 * Searches for all declarations of the methods invoked in the given element.
+	 * The element can be a compilation unit, a source type, or a source method.
+	 * Reports the method declarations using the given collector.
+	 * <p>
+	 * Consider the following code:
+	 * <code>
+	 * <pre>
+	 *		class A {
+	 *			void foo() {};
+	 *			void bar() {};
+	 *		}
+	 *		class B extends A {
+	 *			void foo() {};
+	 *		}
+	 *		class X {
+	 *			void test() {
+	 *				A a = new B();
+	 *				a.foo();
+	 *				B b = (B)a;
+	 *				b.bar();
+	 *			};
+	 *		}
+	 * </pre>
+	 * </code>
+	 * then searching for declarations of sent messages in method 
+	 * <code>X.test()</code> would collect the methods
+	 * <code>A.foo()</code>, <code>B.foo()</code>, and <code>A.bar()</code>.
+	 * </p>
+	 *
+	 * @param workspace the workspace
+	 * @param enclosingElement the method, type, or compilation unit to be searched in
+	 * @param resultCollector a callback object to which each match is reported
+	 * @exception JavaModelException if the search failed. Reasons include:
+	 *	<ul>
+	 *		<li>the element doesn't exist</li>
+	 *		<li>the classpath is incorrectly set</li>
+	 *	</ul>
+	 */	
+	public void searchDeclarationsOfSentMessages(IWorkspace workspace, IJavaElement enclosingElement, IJavaSearchResultCollector resultCollector) throws JavaModelException {
+		SearchPattern pattern = new DeclarationOfReferencedMethodsPattern(enclosingElement);
+		searchDeclarations(workspace, enclosingElement, resultCollector, pattern);
+	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchMatch.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchMatch.java
new file mode 100644
index 0000000..8666269
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchMatch.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.core.search;
+
+/**
+ * generic result. hierarchy can be extended
+ * TODO add spec
+ * @since 3.0
+ */
+public class SearchMatch {
+	
+	/* match accuracy */
+	public static final int A_ACCURATE = 1;
+	public static final int A_INACCURATE = 2;
+	
+	/* generic information */
+	private final int accuracy;
+	private final  String descriptiveLocation;
+	private final String documentPath;
+	private final String name;
+	private final SearchParticipant participant;	
+	private final int sourceEnd;
+	private final int sourceLineNumber;
+	private final int sourceStart;
+
+	public SearchMatch(
+			String name, 
+			String documentPath, 
+			int accuracy,  
+			SearchParticipant participant, 
+			int sourceStart, 
+			int sourceEnd, 
+			int sourceLineNumber, 
+			String descriptiveLocation) {
+
+		this.name = name;
+		this.documentPath = documentPath;
+		this.accuracy = accuracy;
+		this.participant = participant;
+		this.sourceStart = sourceStart;
+		this.sourceEnd = sourceEnd;
+		this.sourceLineNumber = sourceLineNumber;
+		this.descriptiveLocation = descriptiveLocation;
+	}
+	
+	public int getAccuracy() {
+		return this.accuracy;
+	}
+
+	public String getDescriptiveLocation() {
+		return this.descriptiveLocation;
+	}
+
+	public String getDocumentPath() {
+		return this.documentPath;
+	}
+
+	public String getName() {
+		return this.name;
+	}
+
+	/**
+	 * Returns the participant which issued this match
+	 */
+	public SearchParticipant getParticipant() {
+		return this.participant;
+	}
+	
+	public int getSourceEnd() {
+		return this.sourceEnd;
+	}
+
+	public int getSourceLineNumber() {
+		return this.sourceLineNumber;
+	}
+
+	public int getSourceStart() {
+		return this.sourceStart;
+	}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchParticipant.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchParticipant.java
new file mode 100644
index 0000000..24693ab
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchParticipant.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.core.search;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.internal.core.JavaModelManager;
+
+/**
+ * A search participant describes a particular extension to a generic search mechanism, permitting 
+ * combined search actions which will involve all required participants.
+ * 
+ * A search scope defines which participants are involved. 
+ * 
+ * A search participant is responsible for holding index files, and selecting the appropriate ones to feed to
+ * index queries. It also can map a document path to an actual document (note that documents could live outside
+ * the workspace or not exist yet, and thus aren't just resources).
+ * @since 3.0
+ */
+public abstract class SearchParticipant {
+
+	public static final SearchParticipant[] NO_PARTICIPANT = {};
+
+	// A service provided for participants so that they can delegate between themselves.
+	public static void addIndexEntry(char[] category, char[] key, SearchDocument document, String indexPath) {
+		JavaModelManager.getJavaModelManager().getIndexManager().addIndexEntry(category, key, document, indexPath);
+	}
+
+	public static void removeAllIndexEntries(String documentPath, String indexPath) {
+		// TODO (jerome) implement
+	}
+
+	/**
+	 * Intermediate notification sent when a given participant is getting involved.
+	 */
+	public abstract void beginSearching();
+
+	/**
+	 * Intermediate notification sent when a given participant is finished to be involved.
+	 */
+	public abstract void doneSearching();
+	
+	/**
+	 * Returns a displayable name of this search participant. e.g. "Java".
+	 */
+	public abstract String getDescription();
+
+	/**
+	 * Bind a document path to an actual document. A document path is interpreted by a participant.
+	 */
+	public abstract SearchDocument getDocument(String documentPath);
+
+	/**
+	 * Index the given document.
+	 * Implementation should call addIndexEntry(...)
+	 * TODO (jerome) improve spec
+	 */
+	public abstract void indexDocument(SearchDocument document, String indexPath);
+
+	/**
+	 * Locate the matches in the given documents and report them using the search requestor. 
+	 * Note: allows to combine match locators (e.g. jsp match locator can preprocess jsp unit contents and feed it to Java match locator asking for virtual matches
+	 * by contributing document implementations which do the conversion). It is assumed that virtual matches are rearranged by requestor for adapting line/source 
+	 * positions before submitting final results so the provided searchRequestor should intercept virtual matches and do appropriate conversions.
+	 */
+	public abstract void locateMatches(SearchDocument[] indexMatches, SearchPattern pattern, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException;
+
+	/**
+	 * Schedules the indexing of the given document.
+	 * Once the document is ready to be indexed, indexDocument(SearchDocument) is called.
+	 */
+	public void scheduleDocumentIndexing(SearchDocument document, String containerPath, String indexPath) {
+		JavaModelManager.getJavaModelManager().getIndexManager().scheduleDocumentIndexing(document, containerPath, indexPath, this);
+	}
+	
+	/**
+	 * Returns the collection of index paths to consider when performing a given search query in a given scope.
+	 */
+	public abstract IPath[] selectIndexes(SearchPattern query, IJavaSearchScope scope);
+
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
new file mode 100644
index 0000000..81877cf
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
@@ -0,0 +1,1158 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.core.search;
+
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.core.LocalVariable;
+import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
+import org.eclipse.jdt.internal.core.search.matching.*;
+import org.eclipse.jdt.internal.core.search.pattern.InternalSearchPattern;
+
+/**
+ * TODO (jerome) spec
+ * @since 3.0
+ */
+public abstract class SearchPattern extends InternalSearchPattern implements ISearchPattern, IIndexConstants, IJavaSearchConstants {
+
+	/**
+	 * Rules for pattern matching: (exact, prefix, pattern) [ | case sensitive]
+	 */
+	/**
+	 * Match rule: The search pattern matches exactly the search result,
+	 * that is, the source of the search result equals the search pattern.
+	 */
+	public static final int R_EXACT_MATCH = 0;
+	/**
+	 * Match rule: The search pattern is a prefix of the search result.
+	 */
+	public static final int R_PREFIX_MATCH = 1;
+	/**
+	 * Match rule: The search pattern contains one or more wild cards ('*') where a 
+	 * wild-card can replace 0 or more characters in the search result.
+	 */
+	public static final int R_PATTERN_MATCH = 2;
+	/**
+	 * Match rule: The search pattern contains a regular expression.
+	 */
+	public static final int R_REGEXP_MATCH = 3;
+	/**
+	 * Match rule: The search pattern matches the search result only if cases are the same.
+	 * Can be combined to previous rules, e.g. R_EXACT_MATCH | R_CASE_SENSITIVE
+	 */
+	public static final int R_CASE_SENSITIVE = 4;
+
+
+	public boolean mustResolve = true;
+	
+	public SearchPattern(int patternKind, int matchRule) {
+		super(patternKind, matchRule);
+	}
+	
+	/**
+	 * Constructor pattern are formed by [declaringQualification.]type[(parameterTypes)]
+	 * e.g. java.lang.Object()
+	 *		Main(*)
+	 */
+	private static SearchPattern createConstructorPattern(String patternString, int limitTo, int matchMode, boolean isCaseSensitive) {
+	
+		int matchRule = isCaseSensitive ? matchMode | R_CASE_SENSITIVE : matchMode;
+		
+		Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/);
+		scanner.setSource(patternString.toCharArray());
+		final int InsideName = 1;
+		final int InsideParameter = 2;
+		
+		String declaringQualification = null, typeName = null, parameterType = null;
+		String[] parameterTypes = null;
+		int parameterCount = -1;
+		boolean foundClosingParenthesis = false;
+		int mode = InsideName;
+		int token;
+		try {
+			token = scanner.getNextToken();
+		} catch (InvalidInputException e) {
+			return null;
+		}
+		while (token != TerminalTokens.TokenNameEOF) {
+			switch(mode) {
+				// read declaring type and selector
+				case InsideName :
+					switch (token) {
+						case TerminalTokens.TokenNameDOT:
+							if (declaringQualification == null) {
+								if (typeName == null) return null;
+								declaringQualification = typeName;
+							} else {
+								String tokenSource = new String(scanner.getCurrentTokenSource());
+								declaringQualification += tokenSource + typeName;
+							}
+							typeName = null;
+							break;
+						case TerminalTokens.TokenNameLPAREN:
+							parameterTypes = new String[5];
+							parameterCount = 0;
+							mode = InsideParameter;
+							break;
+						case TerminalTokens.TokenNameWHITESPACE:
+							break;
+						default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
+							if (typeName == null)
+								typeName = new String(scanner.getCurrentTokenSource());
+							else
+								typeName += new String(scanner.getCurrentTokenSource());
+					}
+					break;
+				// read parameter types
+				case InsideParameter :
+					switch (token) {
+						case TerminalTokens.TokenNameWHITESPACE:
+							break;
+						case TerminalTokens.TokenNameCOMMA:
+							if (parameterType == null) return null;
+							if (parameterTypes.length == parameterCount)
+								System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount);
+							parameterTypes[parameterCount++] = parameterType;
+							parameterType = null;
+							break;
+						case TerminalTokens.TokenNameRPAREN:
+							foundClosingParenthesis = true;
+							if (parameterType != null) {
+								if (parameterTypes.length == parameterCount)
+									System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount);
+								parameterTypes[parameterCount++] = parameterType;
+							}
+							break;
+						default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
+							if (parameterType == null)
+								parameterType = new String(scanner.getCurrentTokenSource());
+							else
+								parameterType += new String(scanner.getCurrentTokenSource());
+					}
+					break;
+			}
+			try {
+				token = scanner.getNextToken();
+			} catch (InvalidInputException e) {
+				return null;
+			}
+		}
+		// parenthesis mismatch
+		if (parameterCount>0 && !foundClosingParenthesis) return null;
+		if (typeName == null) return null;
+	
+		char[] typeNameChars = typeName.toCharArray();
+		if (typeNameChars.length == 1 && typeNameChars[0] == '*') typeNameChars = null;
+			
+		char[] declaringQualificationChars = null;
+		if (declaringQualification != null) declaringQualificationChars = declaringQualification.toCharArray();
+		char[][] parameterTypeQualifications = null, parameterTypeSimpleNames = null;
+	
+		// extract parameter types infos
+		if (parameterCount >= 0) {
+			parameterTypeQualifications = new char[parameterCount][];
+			parameterTypeSimpleNames = new char[parameterCount][];
+			for (int i = 0; i < parameterCount; i++) {
+				char[] parameterTypePart = parameterTypes[i].toCharArray();
+				int lastDotPosition = CharOperation.lastIndexOf('.', parameterTypePart);
+				if (lastDotPosition >= 0) {
+					parameterTypeQualifications[i] = CharOperation.subarray(parameterTypePart, 0, lastDotPosition);
+					if (parameterTypeQualifications[i].length == 1 && parameterTypeQualifications[i][0] == '*') {
+						parameterTypeQualifications[i] = null;
+					} else {
+						// prefix with a '*' as the full qualification could be bigger (because of an import)
+						parameterTypeQualifications[i] = CharOperation.concat(ONE_STAR, parameterTypeQualifications[i]);
+					}
+					parameterTypeSimpleNames[i] = CharOperation.subarray(parameterTypePart, lastDotPosition+1, parameterTypePart.length);
+				} else {
+					parameterTypeQualifications[i] = null;
+					parameterTypeSimpleNames[i] = parameterTypePart;
+				}
+				if (parameterTypeSimpleNames[i].length == 1 && parameterTypeSimpleNames[i][0] == '*')
+					parameterTypeSimpleNames[i] = null;
+			}
+		}	
+		switch (limitTo) {
+			case IJavaSearchConstants.DECLARATIONS :
+				return new ConstructorPattern(
+					true,
+					false,
+					typeNameChars, 
+					declaringQualificationChars, 
+					parameterTypeQualifications, 
+					parameterTypeSimpleNames,
+					matchRule);
+			case IJavaSearchConstants.REFERENCES :
+				return new ConstructorPattern(
+					false,
+					true,
+					typeNameChars, 
+					declaringQualificationChars, 
+					parameterTypeQualifications, 
+					parameterTypeSimpleNames,
+					matchRule);
+			case IJavaSearchConstants.ALL_OCCURRENCES :
+				return new ConstructorPattern(
+					true,
+					true,
+					typeNameChars, 
+					declaringQualificationChars, 
+					parameterTypeQualifications, 
+					parameterTypeSimpleNames,
+					matchRule);
+		}
+		return null;
+	}
+	/**
+	 * Field pattern are formed by [declaringType.]name[type]
+	 * e.g. java.lang.String.serialVersionUID long
+	 *		field*
+	 */
+	private static SearchPattern createFieldPattern(String patternString, int limitTo, int matchMode, boolean isCaseSensitive) {
+		
+		int matchRule = isCaseSensitive ? matchMode | R_CASE_SENSITIVE : matchMode;
+	
+		Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/); 
+		scanner.setSource(patternString.toCharArray());
+		final int InsideDeclaringPart = 1;
+		final int InsideType = 2;
+		int lastToken = -1;
+		
+		String declaringType = null, fieldName = null;
+		String type = null;
+		int mode = InsideDeclaringPart;
+		int token;
+		try {
+			token = scanner.getNextToken();
+		} catch (InvalidInputException e) {
+			return null;
+		}
+		while (token != TerminalTokens.TokenNameEOF) {
+			switch(mode) {
+				// read declaring type and fieldName
+				case InsideDeclaringPart :
+					switch (token) {
+						case TerminalTokens.TokenNameDOT:
+							if (declaringType == null) {
+								if (fieldName == null) return null;
+								declaringType = fieldName;
+							} else {
+								String tokenSource = new String(scanner.getCurrentTokenSource());
+								declaringType += tokenSource + fieldName;
+							}
+							fieldName = null;
+							break;
+						case TerminalTokens.TokenNameWHITESPACE:
+							if (!(TerminalTokens.TokenNameWHITESPACE == lastToken || TerminalTokens.TokenNameDOT == lastToken))
+								mode = InsideType;
+							break;
+						default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
+							if (fieldName == null)
+								fieldName = new String(scanner.getCurrentTokenSource());
+							else
+								fieldName += new String(scanner.getCurrentTokenSource());
+					}
+					break;
+				// read type 
+				case InsideType:
+					switch (token) {
+						case TerminalTokens.TokenNameWHITESPACE:
+							break;
+						default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
+							if (type == null)
+								type = new String(scanner.getCurrentTokenSource());
+							else
+								type += new String(scanner.getCurrentTokenSource());
+					}
+					break;
+			}
+			lastToken = token;
+			try {
+				token = scanner.getNextToken();
+			} catch (InvalidInputException e) {
+				return null;
+			}
+		}
+		if (fieldName == null) return null;
+	
+		char[] fieldNameChars = fieldName.toCharArray();
+		if (fieldNameChars.length == 1 && fieldNameChars[0] == '*') fieldNameChars = null;
+			
+		char[] declaringTypeQualification = null, declaringTypeSimpleName = null;
+		char[] typeQualification = null, typeSimpleName = null;
+	
+		// extract declaring type infos
+		if (declaringType != null) {
+			char[] declaringTypePart = declaringType.toCharArray();
+			int lastDotPosition = CharOperation.lastIndexOf('.', declaringTypePart);
+			if (lastDotPosition >= 0) {
+				declaringTypeQualification = CharOperation.subarray(declaringTypePart, 0, lastDotPosition);
+				if (declaringTypeQualification.length == 1 && declaringTypeQualification[0] == '*')
+					declaringTypeQualification = null;
+				declaringTypeSimpleName = CharOperation.subarray(declaringTypePart, lastDotPosition+1, declaringTypePart.length);
+			} else {
+				declaringTypeQualification = null;
+				declaringTypeSimpleName = declaringTypePart;
+			}
+			if (declaringTypeSimpleName.length == 1 && declaringTypeSimpleName[0] == '*')
+				declaringTypeSimpleName = null;
+		}
+		// extract type infos
+		if (type != null) {
+			char[] typePart = type.toCharArray();
+			int lastDotPosition = CharOperation.lastIndexOf('.', typePart);
+			if (lastDotPosition >= 0) {
+				typeQualification = CharOperation.subarray(typePart, 0, lastDotPosition);
+				if (typeQualification.length == 1 && typeQualification[0] == '*') {
+					typeQualification = null;
+				} else {
+					// prefix with a '*' as the full qualification could be bigger (because of an import)
+					typeQualification = CharOperation.concat(ONE_STAR, typeQualification);
+				}
+				typeSimpleName = CharOperation.subarray(typePart, lastDotPosition+1, typePart.length);
+			} else {
+				typeQualification = null;
+				typeSimpleName = typePart;
+			}
+			if (typeSimpleName.length == 1 && typeSimpleName[0] == '*')
+				typeSimpleName = null;
+		}
+		switch (limitTo) {
+			case IJavaSearchConstants.DECLARATIONS :
+				return new FieldPattern(
+					true,
+					false,
+					false,
+					fieldNameChars,
+					declaringTypeQualification,
+					declaringTypeSimpleName,
+					typeQualification,
+					typeSimpleName,
+					matchRule);
+			case IJavaSearchConstants.REFERENCES :
+				return new FieldPattern(
+					false,
+					true, // read access
+					true, // write access
+					fieldNameChars, 
+					declaringTypeQualification, 
+					declaringTypeSimpleName, 
+					typeQualification, 
+					typeSimpleName,
+					matchRule);
+			case IJavaSearchConstants.READ_ACCESSES :
+				return new FieldPattern(
+					false,
+					true, // read access only
+					false,
+					fieldNameChars, 
+					declaringTypeQualification, 
+					declaringTypeSimpleName, 
+					typeQualification, 
+					typeSimpleName,
+					matchRule);
+			case IJavaSearchConstants.WRITE_ACCESSES :
+				return new FieldPattern(
+					false,
+					false,
+					true, // write access only
+					fieldNameChars, 
+					declaringTypeQualification, 
+					declaringTypeSimpleName, 
+					typeQualification, 
+					typeSimpleName,
+					matchRule);
+			case IJavaSearchConstants.ALL_OCCURRENCES :
+				return new FieldPattern(
+					true,
+					true, // read access
+					true, // write access
+					fieldNameChars, 
+					declaringTypeQualification, 
+					declaringTypeSimpleName, 
+					typeQualification, 
+					typeSimpleName,
+					matchRule);
+		}
+		return null;
+	}
+	/**
+	 * Method pattern are formed by [declaringType.]selector[(parameterTypes)][returnType]
+	 * e.g. java.lang.Runnable.run() void
+	 *		main(*)
+	 */
+	private static SearchPattern createMethodPattern(String patternString, int limitTo, int matchMode, boolean isCaseSensitive) {
+		
+		int matchRule = isCaseSensitive ? matchMode | R_CASE_SENSITIVE : matchMode;
+	
+		Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/); 
+		scanner.setSource(patternString.toCharArray());
+		final int InsideSelector = 1;
+		final int InsideParameter = 2;
+		final int InsideReturnType = 3;
+		int lastToken = -1;
+		
+		String declaringType = null, selector = null, parameterType = null;
+		String[] parameterTypes = null;
+		int parameterCount = -1;
+		String returnType = null;
+		boolean foundClosingParenthesis = false;
+		int mode = InsideSelector;
+		int token;
+		try {
+			token = scanner.getNextToken();
+		} catch (InvalidInputException e) {
+			return null;
+		}
+		while (token != TerminalTokens.TokenNameEOF) {
+			switch(mode) {
+				// read declaring type and selector
+				case InsideSelector :
+					switch (token) {
+						case TerminalTokens.TokenNameDOT:
+							if (declaringType == null) {
+								if (selector == null) return null;
+								declaringType = selector;
+							} else {
+								String tokenSource = new String(scanner.getCurrentTokenSource());
+								declaringType += tokenSource + selector;
+							}
+							selector = null;
+							break;
+						case TerminalTokens.TokenNameLPAREN:
+							parameterTypes = new String[5];
+							parameterCount = 0;
+							mode = InsideParameter;
+							break;
+						case TerminalTokens.TokenNameWHITESPACE:
+							if (!(TerminalTokens.TokenNameWHITESPACE == lastToken || TerminalTokens.TokenNameDOT == lastToken))
+								mode = InsideReturnType;
+							break;
+						default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
+							if (selector == null)
+								selector = new String(scanner.getCurrentTokenSource());
+							else
+								selector += new String(scanner.getCurrentTokenSource());
+							break;
+					}
+					break;
+				// read parameter types
+				case InsideParameter :
+					switch (token) {
+						case TerminalTokens.TokenNameWHITESPACE:
+							break;
+						case TerminalTokens.TokenNameCOMMA:
+							if (parameterType == null) return null;
+							if (parameterTypes.length == parameterCount)
+								System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount);
+							parameterTypes[parameterCount++] = parameterType;
+							parameterType = null;
+							break;
+						case TerminalTokens.TokenNameRPAREN:
+							foundClosingParenthesis = true;
+							if (parameterType != null){
+								if (parameterTypes.length == parameterCount)
+									System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount);
+								parameterTypes[parameterCount++] = parameterType;
+							}
+							mode = InsideReturnType;
+							break;
+						default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
+							if (parameterType == null)
+								parameterType = new String(scanner.getCurrentTokenSource());
+							else
+								parameterType += new String(scanner.getCurrentTokenSource());
+					}
+					break;
+				// read return type
+				case InsideReturnType:
+					switch (token) {
+						case TerminalTokens.TokenNameWHITESPACE:
+							break;
+						default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
+							if (returnType == null)
+								returnType = new String(scanner.getCurrentTokenSource());
+							else
+								returnType += new String(scanner.getCurrentTokenSource());
+					}
+					break;
+			}
+			lastToken = token;
+			try {
+				token = scanner.getNextToken();
+			} catch (InvalidInputException e) {
+				return null;
+			}
+		}
+		// parenthesis mismatch
+		if (parameterCount>0 && !foundClosingParenthesis) return null;
+		if (selector == null) return null;
+	
+		char[] selectorChars = selector.toCharArray();
+		if (selectorChars.length == 1 && selectorChars[0] == '*')
+			selectorChars = null;
+			
+		char[] declaringTypeQualification = null, declaringTypeSimpleName = null;
+		char[] returnTypeQualification = null, returnTypeSimpleName = null;
+		char[][] parameterTypeQualifications = null, parameterTypeSimpleNames = null;
+	
+		// extract declaring type infos
+		if (declaringType != null) {
+			char[] declaringTypePart = declaringType.toCharArray();
+			int lastDotPosition = CharOperation.lastIndexOf('.', declaringTypePart);
+			if (lastDotPosition >= 0) {
+				declaringTypeQualification = CharOperation.subarray(declaringTypePart, 0, lastDotPosition);
+				if (declaringTypeQualification.length == 1 && declaringTypeQualification[0] == '*')
+					declaringTypeQualification = null;
+				declaringTypeSimpleName = CharOperation.subarray(declaringTypePart, lastDotPosition+1, declaringTypePart.length);
+			} else {
+				declaringTypeQualification = null;
+				declaringTypeSimpleName = declaringTypePart;
+			}
+			if (declaringTypeSimpleName.length == 1 && declaringTypeSimpleName[0] == '*')
+				declaringTypeSimpleName = null;
+		}
+		// extract parameter types infos
+		if (parameterCount >= 0) {
+			parameterTypeQualifications = new char[parameterCount][];
+			parameterTypeSimpleNames = new char[parameterCount][];
+			for (int i = 0; i < parameterCount; i++) {
+				char[] parameterTypePart = parameterTypes[i].toCharArray();
+				int lastDotPosition = CharOperation.lastIndexOf('.', parameterTypePart);
+				if (lastDotPosition >= 0) {
+					parameterTypeQualifications[i] = CharOperation.subarray(parameterTypePart, 0, lastDotPosition);
+					if (parameterTypeQualifications[i].length == 1 && parameterTypeQualifications[i][0] == '*') {
+						parameterTypeQualifications[i] = null;
+					} else {
+						// prefix with a '*' as the full qualification could be bigger (because of an import)
+						parameterTypeQualifications[i] = CharOperation.concat(ONE_STAR, parameterTypeQualifications[i]);
+					}
+					parameterTypeSimpleNames[i] = CharOperation.subarray(parameterTypePart, lastDotPosition+1, parameterTypePart.length);
+				} else {
+					parameterTypeQualifications[i] = null;
+					parameterTypeSimpleNames[i] = parameterTypePart;
+				}
+				if (parameterTypeSimpleNames[i].length == 1 && parameterTypeSimpleNames[i][0] == '*')
+					parameterTypeSimpleNames[i] = null;
+			}
+		}	
+		// extract return type infos
+		if (returnType != null) {
+			char[] returnTypePart = returnType.toCharArray();
+			int lastDotPosition = CharOperation.lastIndexOf('.', returnTypePart);
+			if (lastDotPosition >= 0) {
+				returnTypeQualification = CharOperation.subarray(returnTypePart, 0, lastDotPosition);
+				if (returnTypeQualification.length == 1 && returnTypeQualification[0] == '*') {
+					returnTypeQualification = null;
+				} else {
+					// because of an import
+					returnTypeQualification = CharOperation.concat(ONE_STAR, returnTypeQualification);
+				}			
+				returnTypeSimpleName = CharOperation.subarray(returnTypePart, lastDotPosition+1, returnTypePart.length);
+			} else {
+				returnTypeQualification = null;
+				returnTypeSimpleName = returnTypePart;
+			}
+			if (returnTypeSimpleName.length == 1 && returnTypeSimpleName[0] == '*')
+				returnTypeSimpleName = null;
+		}
+		switch (limitTo) {
+			case IJavaSearchConstants.DECLARATIONS :
+				return new MethodPattern(
+					true,
+					false,
+					selectorChars, 
+					declaringTypeQualification, 
+					declaringTypeSimpleName, 
+					returnTypeQualification, 
+					returnTypeSimpleName, 
+					parameterTypeQualifications, 
+					parameterTypeSimpleNames,
+					null,
+					matchRule);
+			case IJavaSearchConstants.REFERENCES :
+				return new MethodPattern(
+					false,
+					true,
+					selectorChars, 
+					declaringTypeQualification, 
+					declaringTypeSimpleName, 
+					returnTypeQualification, 
+					returnTypeSimpleName, 
+					parameterTypeQualifications, 
+					parameterTypeSimpleNames,
+					null,
+					matchRule);
+			case IJavaSearchConstants.ALL_OCCURRENCES :
+				return new MethodPattern(
+					true,
+					true,
+					selectorChars, 
+					declaringTypeQualification, 
+					declaringTypeSimpleName, 
+					returnTypeQualification, 
+					returnTypeSimpleName, 
+					parameterTypeQualifications, 
+					parameterTypeSimpleNames,
+					null,
+					matchRule);
+		}
+		return null;
+	}
+	private static SearchPattern createPackagePattern(String patternString, int limitTo, int matchMode, boolean isCaseSensitive) {
+		int matchRule = isCaseSensitive ? matchMode | R_CASE_SENSITIVE : matchMode;
+		switch (limitTo) {
+			case IJavaSearchConstants.DECLARATIONS :
+				return new PackageDeclarationPattern(patternString.toCharArray(), matchRule);
+			case IJavaSearchConstants.REFERENCES :
+				return new PackageReferencePattern(patternString.toCharArray(), matchRule);
+			case IJavaSearchConstants.ALL_OCCURRENCES :
+				return new OrPattern(
+					new PackageDeclarationPattern(patternString.toCharArray(), matchRule),
+					new PackageReferencePattern(patternString.toCharArray(), matchRule)
+				);
+		}
+		return null;
+	}
+	public static SearchPattern createPattern(String patternString, int searchFor, int limitTo, int matchMode, boolean isCaseSensitive) {
+		if (patternString == null || patternString.length() == 0) return null;
+	
+		switch (searchFor) {
+			case IJavaSearchConstants.TYPE:
+				return createTypePattern(patternString, limitTo, matchMode, isCaseSensitive);
+			case IJavaSearchConstants.METHOD:
+				return createMethodPattern(patternString, limitTo, matchMode, isCaseSensitive);
+			case IJavaSearchConstants.CONSTRUCTOR:
+				return createConstructorPattern(patternString, limitTo, matchMode, isCaseSensitive);
+			case IJavaSearchConstants.FIELD:
+				return createFieldPattern(patternString, limitTo, matchMode, isCaseSensitive);
+			case IJavaSearchConstants.PACKAGE:
+				return createPackagePattern(patternString, limitTo, matchMode, isCaseSensitive);
+		}
+		return null;
+	}
+	public static SearchPattern createPattern(IJavaElement element, int limitTo) {
+		SearchPattern searchPattern = null;
+		int lastDot;
+		switch (element.getElementType()) {
+			case IJavaElement.FIELD :
+				IField field = (IField) element; 
+				IType declaringClass = field.getDeclaringType();
+				char[] declaringSimpleName = declaringClass.getElementName().toCharArray();
+				char[] declaringQualification = declaringClass.getPackageFragment().getElementName().toCharArray();
+				char[][] enclosingNames = enclosingTypeNames(declaringClass);
+				if (enclosingNames.length > 0)
+					declaringQualification = CharOperation.concat(declaringQualification, CharOperation.concatWith(enclosingNames, '.'), '.');
+				char[] name = field.getElementName().toCharArray();
+				char[] typeSimpleName;
+				char[] typeQualification;
+				try {
+					String typeSignature = Signature.toString(field.getTypeSignature()).replace('$', '.');
+					if ((lastDot = typeSignature.lastIndexOf('.')) == -1) {
+						typeSimpleName = typeSignature.toCharArray();
+						typeQualification = null;
+					} else {
+						typeSimpleName = typeSignature.substring(lastDot + 1).toCharArray();
+						typeQualification = field.isBinary()
+							? typeSignature.substring(0, lastDot).toCharArray()
+							// prefix with a '*' as the full qualification could be bigger (because of an import)
+							: CharOperation.concat(ONE_STAR, typeSignature.substring(0, lastDot).toCharArray());
+					}
+				} catch (JavaModelException e) {
+					return null;
+				}
+				switch (limitTo) {
+					case IJavaSearchConstants.DECLARATIONS :
+						searchPattern = 
+							new FieldPattern(
+								true,
+								false,
+								false,
+								name, 
+								declaringQualification, 
+								declaringSimpleName, 
+								typeQualification, 
+								typeSimpleName,
+								R_EXACT_MATCH | R_CASE_SENSITIVE);
+						break;
+					case IJavaSearchConstants.REFERENCES :
+						searchPattern = 
+							new FieldPattern(
+								false,
+								true, // read access
+								true, // write access
+								name, 
+								declaringQualification, 
+								declaringSimpleName, 
+								typeQualification, 
+								typeSimpleName,
+								R_EXACT_MATCH | R_CASE_SENSITIVE);
+						break;
+					case IJavaSearchConstants.READ_ACCESSES :
+						searchPattern = 
+							new FieldPattern(
+								false,
+								true, // read access only
+								false,
+								name, 
+								declaringQualification, 
+								declaringSimpleName, 
+								typeQualification, 
+								typeSimpleName,
+								R_EXACT_MATCH | R_CASE_SENSITIVE);
+						break;
+					case IJavaSearchConstants.WRITE_ACCESSES :
+						searchPattern = 
+							new FieldPattern(
+								false,
+								false,
+								true, // write access only
+								name, 
+								declaringQualification, 
+								declaringSimpleName, 
+								typeQualification, 
+								typeSimpleName,
+								R_EXACT_MATCH | R_CASE_SENSITIVE);
+						break;
+					case IJavaSearchConstants.ALL_OCCURRENCES :
+						searchPattern =
+							new FieldPattern(
+								true,
+								true, // read access
+								true, // write access
+								name, 
+								declaringQualification, 
+								declaringSimpleName, 
+								typeQualification, 
+								typeSimpleName,
+								R_EXACT_MATCH | R_CASE_SENSITIVE);
+						break;
+				}
+				break;
+			case IJavaElement.IMPORT_DECLARATION :
+				String elementName = element.getElementName();
+				lastDot = elementName.lastIndexOf('.');
+				if (lastDot == -1) return null; // invalid import declaration
+				IImportDeclaration importDecl = (IImportDeclaration)element;
+				if (importDecl.isOnDemand()) {
+					searchPattern = createPackagePattern(elementName.substring(0, lastDot), limitTo, EXACT_MATCH, CASE_SENSITIVE);
+				} else {
+					searchPattern = 
+						createTypePattern(
+							elementName.substring(lastDot+1).toCharArray(),
+							elementName.substring(0, lastDot).toCharArray(),
+							null,
+							limitTo);
+				}
+				break;
+			case IJavaElement.LOCAL_VARIABLE :
+				LocalVariable localVar = (LocalVariable) element;
+				switch (limitTo) {
+					case IJavaSearchConstants.DECLARATIONS :
+						searchPattern = 
+							new LocalVariablePattern(
+								true, // declarations
+								false, // no read access
+								false, // no write access
+								localVar,
+								R_EXACT_MATCH | R_CASE_SENSITIVE);
+						break;
+					case IJavaSearchConstants.REFERENCES :
+						searchPattern = 
+							new LocalVariablePattern(
+								false,
+								true, // read access
+								true, // write access
+								localVar,
+								R_EXACT_MATCH | R_CASE_SENSITIVE);
+						break;
+					case IJavaSearchConstants.READ_ACCESSES :
+						searchPattern = 
+							new LocalVariablePattern(
+								false,
+								true, // read access only
+								false,
+								localVar,
+								R_EXACT_MATCH | R_CASE_SENSITIVE);
+						break;
+					case IJavaSearchConstants.WRITE_ACCESSES :
+						searchPattern = 
+							new LocalVariablePattern(
+								false,
+								false,
+								true, // write access only
+								localVar,
+								R_EXACT_MATCH | R_CASE_SENSITIVE);
+						break;
+					case IJavaSearchConstants.ALL_OCCURRENCES :
+						searchPattern =
+							new LocalVariablePattern(
+								true,
+								true, // read access
+								true, // write access
+								localVar,
+								R_EXACT_MATCH | R_CASE_SENSITIVE);
+						break;
+				}
+				break;
+			case IJavaElement.METHOD :
+				IMethod method = (IMethod) element;
+				boolean isConstructor;
+				try {
+					isConstructor = method.isConstructor();
+				} catch (JavaModelException e) {
+					return null;
+				}
+				declaringClass = method.getDeclaringType();
+				declaringSimpleName = declaringClass.getElementName().toCharArray();
+				declaringQualification = declaringClass.getPackageFragment().getElementName().toCharArray();
+				enclosingNames = enclosingTypeNames(declaringClass);
+				if (enclosingNames.length > 0)
+					declaringQualification = CharOperation.concat(declaringQualification, CharOperation.concatWith(enclosingNames, '.'), '.');
+				char[] selector = method.getElementName().toCharArray();
+				char[] returnSimpleName;
+				char[] returnQualification;
+				try {
+					String returnType = Signature.toString(method.getReturnType()).replace('$', '.');
+					if ((lastDot = returnType.lastIndexOf('.')) == -1) {
+						returnSimpleName = returnType.toCharArray();
+						returnQualification = null;
+					} else {
+						returnSimpleName = returnType.substring(lastDot + 1).toCharArray();
+						returnQualification = method.isBinary()
+							? returnType.substring(0, lastDot).toCharArray()
+							// prefix with a '*' as the full qualification could be bigger (because of an import)
+							: CharOperation.concat(ONE_STAR, returnType.substring(0, lastDot).toCharArray());
+					}
+				} catch (JavaModelException e) {
+					return null;
+				}
+				String[] parameterTypes = method.getParameterTypes();
+				int paramCount = parameterTypes.length;
+				char[][] parameterSimpleNames = new char[paramCount][];
+				char[][] parameterQualifications = new char[paramCount][];
+				for (int i = 0; i < paramCount; i++) {
+					String signature = Signature.toString(parameterTypes[i]).replace('$', '.');
+					if ((lastDot = signature.lastIndexOf('.')) == -1) {
+						parameterSimpleNames[i] = signature.toCharArray();
+						parameterQualifications[i] = null;
+					} else {
+						parameterSimpleNames[i] = signature.substring(lastDot + 1).toCharArray();
+						parameterQualifications[i] = method.isBinary()
+							? signature.substring(0, lastDot).toCharArray()
+							// prefix with a '*' as the full qualification could be bigger (because of an import)
+							: CharOperation.concat(ONE_STAR, signature.substring(0, lastDot).toCharArray());
+				}
+				}
+				switch (limitTo) {
+					case IJavaSearchConstants.DECLARATIONS :
+						if (isConstructor) {
+							searchPattern = 
+								new ConstructorPattern(
+									true,
+									false,
+									declaringSimpleName, 
+									declaringQualification, 
+									parameterQualifications, 
+									parameterSimpleNames,
+									R_EXACT_MATCH | R_CASE_SENSITIVE);
+						} else {
+							searchPattern = 
+								new MethodPattern(
+									true,
+									false,
+									selector, 
+									declaringQualification, 
+									declaringSimpleName, 
+									returnQualification, 
+									returnSimpleName, 
+									parameterQualifications, 
+									parameterSimpleNames,
+									null,
+									R_EXACT_MATCH | R_CASE_SENSITIVE);
+						}
+						break;
+					case IJavaSearchConstants.REFERENCES :
+						if (isConstructor) {
+							searchPattern = 
+								new ConstructorPattern(
+									false,
+									true,
+									declaringSimpleName, 
+									declaringQualification, 
+									parameterQualifications, 
+									parameterSimpleNames,
+									R_EXACT_MATCH | R_CASE_SENSITIVE);
+						} else {
+							searchPattern = 
+								new MethodPattern(
+									false,
+									true,
+									selector, 
+									declaringQualification, 
+									declaringSimpleName, 
+									returnQualification, 
+									returnSimpleName, 
+									parameterQualifications, 
+									parameterSimpleNames,
+									method.getDeclaringType(),
+									R_EXACT_MATCH | R_CASE_SENSITIVE);
+						}
+						break;
+					case IJavaSearchConstants.ALL_OCCURRENCES :
+						if (isConstructor) {
+							searchPattern =
+								new ConstructorPattern(
+									true,
+									true,
+									declaringSimpleName, 
+									declaringQualification, 
+									parameterQualifications, 
+									parameterSimpleNames,
+									R_EXACT_MATCH | R_CASE_SENSITIVE);
+						} else {
+							searchPattern =
+								new MethodPattern(
+									true,
+									true,
+									selector, 
+									declaringQualification, 
+									declaringSimpleName, 
+									returnQualification, 
+									returnSimpleName, 
+									parameterQualifications, 
+									parameterSimpleNames,
+									method.getDeclaringType(),
+									R_EXACT_MATCH | R_CASE_SENSITIVE);
+						}
+						break;
+				}
+				break;
+			case IJavaElement.TYPE :
+				IType type = (IType)element;
+				searchPattern = 
+					createTypePattern(
+						type.getElementName().toCharArray(), 
+						type.getPackageFragment().getElementName().toCharArray(),
+						enclosingTypeNames(type),
+						limitTo);
+				break;
+			case IJavaElement.PACKAGE_DECLARATION :
+			case IJavaElement.PACKAGE_FRAGMENT :
+				searchPattern = createPackagePattern(element.getElementName(), limitTo, EXACT_MATCH, CASE_SENSITIVE);
+				break;
+		}
+		if (searchPattern != null)
+			searchPattern.focus = element;
+		return searchPattern;
+	}
+	private static SearchPattern createTypePattern(char[] simpleName, char[] packageName, char[][] enclosingTypeNames, int limitTo) {
+		switch (limitTo) {
+			case IJavaSearchConstants.DECLARATIONS :
+				return new TypeDeclarationPattern(
+					packageName, 
+					enclosingTypeNames, 
+					simpleName, 
+					TYPE_SUFFIX,
+					R_EXACT_MATCH | R_CASE_SENSITIVE);
+			case IJavaSearchConstants.REFERENCES :
+				return new TypeReferencePattern(
+					CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
+					simpleName,
+					R_EXACT_MATCH | R_CASE_SENSITIVE);
+			case IJavaSearchConstants.IMPLEMENTORS : 
+				return new SuperTypeReferencePattern(
+					CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
+					simpleName,
+					true,
+					R_EXACT_MATCH | R_CASE_SENSITIVE);
+			case IJavaSearchConstants.ALL_OCCURRENCES :
+				return new OrPattern(
+					new TypeDeclarationPattern(
+						packageName, 
+						enclosingTypeNames, 
+						simpleName, 
+						TYPE_SUFFIX,
+						R_EXACT_MATCH | R_CASE_SENSITIVE), 
+					new TypeReferencePattern(
+						CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
+						simpleName,
+						R_EXACT_MATCH | R_CASE_SENSITIVE));
+		}
+		return null;
+	}
+	/**
+	 * Type pattern are formed by [qualification.]type
+	 * e.g. java.lang.Object
+	 *		Runnable
+	 *
+	 */
+	private static SearchPattern createTypePattern(String patternString, int limitTo, int matchMode, boolean isCaseSensitive) {
+		
+		int matchRule = isCaseSensitive ? matchMode | R_CASE_SENSITIVE : matchMode;
+	
+		Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3/*sourceLevel*/, null /*taskTags*/, null/*taskPriorities*/); 
+		scanner.setSource(patternString.toCharArray());
+		String type = null;
+		int token;
+		try {
+			token = scanner.getNextToken();
+		} catch (InvalidInputException e) {
+			return null;
+		}
+		while (token != TerminalTokens.TokenNameEOF) {
+			switch (token) {
+				case TerminalTokens.TokenNameWHITESPACE:
+					break;
+				default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
+					if (type == null)
+						type = new String(scanner.getCurrentTokenSource());
+					else
+						type += new String(scanner.getCurrentTokenSource());
+			}
+			try {
+				token = scanner.getNextToken();
+			} catch (InvalidInputException e) {
+				return null;
+			}
+		}
+		if (type == null) return null;
+	
+		char[] qualificationChars = null, typeChars = null;
+	
+		// extract declaring type infos
+		if (type != null) {
+			char[] typePart = type.toCharArray();
+			int lastDotPosition = CharOperation.lastIndexOf('.', typePart);
+			if (lastDotPosition >= 0) {
+				qualificationChars = CharOperation.subarray(typePart, 0, lastDotPosition);
+				if (qualificationChars.length == 1 && qualificationChars[0] == '*')
+					qualificationChars = null;
+				typeChars = CharOperation.subarray(typePart, lastDotPosition+1, typePart.length);
+			} else {
+				qualificationChars = null;
+				typeChars = typePart;
+			}
+			if (typeChars.length == 1 && typeChars[0] == '*')
+				typeChars = null;
+		}
+		switch (limitTo) {
+			case IJavaSearchConstants.DECLARATIONS : // cannot search for explicit member types
+				return new QualifiedTypeDeclarationPattern(qualificationChars, typeChars, TYPE_SUFFIX, matchRule);
+			case IJavaSearchConstants.REFERENCES :
+				return new TypeReferencePattern(qualificationChars, typeChars, matchRule);
+			case IJavaSearchConstants.IMPLEMENTORS : 
+				return new SuperTypeReferencePattern(qualificationChars, typeChars, true, matchRule);
+			case IJavaSearchConstants.ALL_OCCURRENCES :
+				return new OrPattern(
+					new QualifiedTypeDeclarationPattern(qualificationChars, typeChars, TYPE_SUFFIX, matchRule),// cannot search for explicit member types
+					new TypeReferencePattern(qualificationChars, typeChars, matchRule));
+		}
+		return null;
+	}
+	/**
+	 * Returns the enclosing type names of the given type.
+	 */
+	private static char[][] enclosingTypeNames(IType type) {
+		IJavaElement parent = type.getParent();
+		switch (parent.getElementType()) {
+			case IJavaElement.CLASS_FILE:
+				// For a binary type, the parent is not the enclosing type, but the declaring type is.
+				// (see bug 20532  Declaration of member binary type not found)
+				IType declaringType = type.getDeclaringType();
+				if (declaringType == null) return CharOperation.NO_CHAR_CHAR;
+				return CharOperation.arrayConcat(
+					enclosingTypeNames(declaringType), 
+					declaringType.getElementName().toCharArray());
+			case IJavaElement.COMPILATION_UNIT:
+				return CharOperation.NO_CHAR_CHAR;
+			case IJavaElement.FIELD:
+			case IJavaElement.INITIALIZER:
+			case IJavaElement.METHOD:
+				IType declaringClass = ((IMember) parent).getDeclaringType();
+				return CharOperation.arrayConcat(
+					enclosingTypeNames(declaringClass),
+					new char[][] {declaringClass.getElementName().toCharArray(), ONE_STAR});
+			case IJavaElement.TYPE:
+				return CharOperation.arrayConcat(
+					enclosingTypeNames((IType)parent), 
+					parent.getElementName().toCharArray());
+			default:
+				return null;
+		}
+	}
+	
+	/**
+	 * Decoded the given index key into the given record.
+	 */
+	public abstract void decodeIndexKey(char[] key);
+
+	/**
+	 * Returns a key to find in relevant index categories. The key will be matched according to some match rule.
+	 * These potential matches will be further narrowed by the match locator, but precise
+	 * match locating can be expensive, and index query should be as accurate as possible
+	 * so as to eliminate obvious false hits.
+	 */
+	public abstract char[] encodeIndexKey();
+	
+	public abstract SearchPattern getIndexRecord();
+	
+	/**
+	 * Returns an array of index categories to consider for this index query.
+	 * These potential matches will be further narrowed by the match locator, but precise
+	 * match locating can be expensive, and index query should be as accurate as possible
+	 * so as to eliminate obvious false hits.
+	 */
+	public abstract char[][] getMatchCategories();
+	
+	/**
+	 * Returns the rule to apply for matching index keys. Can be exact match, prefix match, pattern match or regexp match.
+	 * Rule can also be combined with a case sensitivity flag.
+	 */	
+	public int getMatchRule() {
+		return this.matchRule;
+	}
+	
+	/**
+	 * TODO (jerome) spec
+	 */
+	public abstract boolean isMatchingIndexRecord();
+		
+	/**
+	 * Returns whether the given name matches the given pattern.
+	 */
+	public boolean matchesName(char[] pattern, char[] name) {
+		if (pattern == null) return true; // null is as if it was "*"
+		if (name != null) {
+			switch (matchMode()) {
+				case R_EXACT_MATCH :
+					return CharOperation.equals(pattern, name, isCaseSensitive());
+				case R_PREFIX_MATCH :
+					return CharOperation.prefixEquals(pattern, name, isCaseSensitive());
+				case R_PATTERN_MATCH :
+					if (!isCaseSensitive())
+						pattern = CharOperation.toLowerCase(pattern);
+					return CharOperation.match(pattern, name, isCaseSensitive());
+				case R_REGEXP_MATCH :
+					// TODO (jerome) implement regular expression match
+					return true;
+			}
+		}
+		return false;
+	}
+	
+	public String toString(){
+		return "SearchPattern"; //$NON-NLS-1$
+	}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchRequestor.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchRequestor.java
new file mode 100644
index 0000000..df71d22
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchRequestor.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.core.search;
+
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * TODO add spec
+ */
+/**
+ * A <code>SearchRequestor</code> collects search results from a <code>search</code>
+ * query to a <code>SearchEngine</code>. Clients must implement this interface and pass
+ * an instance to the <code>search(...)</code> methods. When a search starts, the <code>aboutToStart()</code>
+ * method is called, then 0 or more call to <code>accept(...)</code> are done, finally the
+ * <code>done()</code> method is called.
+ * <p>
+ * Results provided to this collector may be accurate - in this case they have an <code>EXACT_MATCH</code> accuracy -
+ * or they might be potential matches only - they have a <code>POTENTIAL_MATCH</code> accuracy. This last
+ * case can occur when a problem prevented the <code>SearchEngine</code> from resolving the match.
+ * </p>
+ * <p>
+ * The order of the results is unspecified. Clients must not rely on this order to display results, 
+ * but they should sort these results (for example, in syntactical order).
+ * <p>
+ * The <code>SearchRequestor</code> is also used to provide a progress monitor to the 
+ * <code>SearchEngine</code>.
+ * </p>
+ * <p>
+ * Clients may implement this interface.
+ * </p>
+ *
+ * @see SearchEngine#search
+ * @since 3.0
+ */
+public abstract class SearchRequestor {
+
+	/**expected detail level */
+	public static final int D_LOCATION = 8;
+	public static final int D_NAME = 1;
+	public static final int D_PATH = 2;
+	public static final int D_POSITION = 4;
+
+	// answer false if requesting to cancel
+	public abstract boolean acceptSearchMatch(SearchMatch match) throws CoreException;
+
+	/**
+	 * Notification sent before starting the search action.
+	 * Typically, this would tell a search requestor to clear previously recorded search results.
+	 */
+	public abstract void beginReporting();
+
+	/**
+	 * Notification sent after having completed the search action.
+	 * Typically, this would tell a search requestor collector that no more results  should be expected in this
+	 * iteration.
+	 */
+	public abstract void endReporting();
+
+	/**
+	 * Intermediate notification sent when a given participant is starting to contribute.
+	 */
+	public abstract void enterParticipant(SearchParticipant participant);
+
+	/**
+	 * Intermediate notification sent when a given participant is finished contributing.
+	 */
+	public abstract void exitParticipant(SearchParticipant participant);
+
+//	/**
+//	 * Client can indicate how much detail is expected
+//	 */
+//	public int getRequestedDetailLevel() {
+//		// by default, request all details
+//		return D_NAME | D_PATH | D_POSITION | D_LOCATION;
+//	}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DocumentFactory.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DocumentFactory.java
deleted file mode 100644
index 06db9c3..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DocumentFactory.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.index;
-
-import java.io.File;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.jdt.internal.core.index.impl.FileDocument;
-import org.eclipse.jdt.internal.core.index.impl.IFileDocument;
-
-public class DocumentFactory {
-
-	public static IDocument newDocument(File file) {
-		return new FileDocument(file);
-	}
-	public static IDocument newDocument(IFile file) {
-		return new IFileDocument(file);
-	}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IDocument.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IDocument.java
deleted file mode 100644
index e167210..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IDocument.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.index;
-
-import java.io.IOException;
-
-/**
- * An <code>IDocument</code> represent a data source, e.g.&nbsp;a <code>File</code> (<code>FileDocument</code>), 
- * an <code>IFile</code> (<code>IFileDocument</code>), 
- * or other kinds of data sources (URL, ...). An <code>IIndexer</code> indexes an<code>IDocument</code>.
- */
-
-public interface IDocument {
-	/**
-	 * Returns the content of the document, in a byte array.
-	 */
-	byte[] getByteContent() throws IOException;
-	/**
-	 * Returns the content of the document, in a char array.
-	 */
-	char[] getCharContent() throws IOException;
-	/**
-	 * Returns the encoding for this document
-	 */
-	String getEncoding();
-	/**
-	 * returns the name of the document (e.g. its path for a <code>File</code>, or its relative path
-	 * in the workbench for an <code>IFile</code>).
-	 */
-	String getName();
-	/**
-	 * Returns the content of the document, as a String.
-	 */
-	public String getStringContent() throws IOException;
-	/**
-	 * Returns the type of the document.
-	 */
-	String getType();
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IEntryResult.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IEntryResult.java
deleted file mode 100644
index 74f405b..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IEntryResult.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.index;
-
-public interface IEntryResult {
-	public int[] getFileReferences();
-	public char[] getWord();
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndex.java
index 8fbba99..b512716 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndex.java
@@ -13,6 +13,9 @@
 import java.io.File;
 import java.io.IOException;
 
+import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jdt.internal.core.index.impl.EntryResult;
+
 /**
  * An IIndex is the interface used to generate an index file, and to make queries on
  * this index.
@@ -22,24 +25,12 @@
 	/**
 	 * Adds the given document to the index.
 	 */
-	void add(IDocument document, IIndexer indexer) throws IOException;
-	/**
-	 * Empties the index.
-	 */
-	void empty() throws IOException;
+	void add(SearchDocument document, IIndexer indexer) throws IOException;
 	/**
 	 * Returns the index file on the disk.
 	 */
 	File getIndexFile();
 	/**
-	 * Returns the number of documents indexed.
-	 */
-	int getNumDocuments() throws IOException;
-	/**
-	 * Returns the number of unique words indexed.
-	 */
-	int getNumWords() throws IOException;
-	/**
 	 * Returns the path corresponding to a given document number
 	 */
 	String getPath(int documentNumber) throws IOException;
@@ -50,19 +41,19 @@
 	/**
 	 * Returns the paths of the documents containing the given word.
 	 */
-	IQueryResult[] query(String word) throws IOException;
+	String[] query(String word) throws IOException;
 	/**
 	 * Returns all entries for a given word.
 	 */
-	IEntryResult[] queryEntries(char[] pattern) throws IOException;
+	EntryResult[] queryEntries(char[] pattern) throws IOException;
 	/**
 	 * Returns the paths of the documents whose names contain the given word.
 	 */
-	IQueryResult[] queryInDocumentNames(String word) throws IOException;
+	String[] queryInDocumentNames(String word) throws IOException;
 	/**
 	 * Returns the paths of the documents containing the given word prefix.
 	 */
-	IQueryResult[] queryPrefix(char[] prefix) throws IOException;
+	String[] queryPrefix(char[] prefix) throws IOException;
 	/**
 	 * Removes the corresponding document from the index.
 	 */
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndexer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndexer.java
index eadc92b..d724b7c 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndexer.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndexer.java
@@ -10,6 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.index;
 
+import org.eclipse.jdt.core.search.SearchDocument;
+
 /**
  * An <code>IIndexer</code> indexes ONE document at each time. It adds the document names and
  * the words references to an IIndex. Each IIndexer can index certain types of document, and should
@@ -17,26 +19,11 @@
  */
 public interface IIndexer {
 	/**
-	 * Returns the file types the <code>IIndexer</code> handles.
-	 */
-
-	String[] getFileTypes();
-	/**
 	 * Indexes the given document, adding the document name and the word references 
 	 * to this document to the given <code>IIndex</code>.The caller should use 
 	 * <code>shouldIndex()</code> first to determine whether this indexer handles 
 	 * the given type of file, and only call this method if so. 
 	 */
 
-	void index(IDocument document, IIndexerOutput output) throws java.io.IOException;
-	/**
-	 * Sets the document types the <code>IIndexer</code> handles.
-	 */
-
-	public void setFileTypes(String[] fileTypes);
-	/**
-	 * Returns whether the <code>IIndexer</code> can index the given document or not.
-	 */
-
-	public boolean shouldIndex(IDocument document);
+	void index(SearchDocument document, IIndexerOutput output) throws java.io.IOException;
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndexerOutput.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndexerOutput.java
index 0c9f152..5121273 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndexerOutput.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IIndexerOutput.java
@@ -9,13 +9,15 @@
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.index;
+
+import org.eclipse.jdt.core.search.SearchDocument;
+
 /**
  * This class represents the output from an indexer to an index 
  * for a single document.
  */
 
 public interface IIndexerOutput {
-	public void addDocument(IDocument document);
+	public void addDocument(SearchDocument document);
 	public void addRef(char[] word);
-	public void addRef(String word);
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IQueryResult.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IQueryResult.java
deleted file mode 100644
index 41d7c4f..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/IQueryResult.java
+++ /dev/null
@@ -1,15 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.index;
-
-public interface IQueryResult {
-	String getPath();
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Block.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Block.java
index ba4c569..7718b6c 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Block.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Block.java
@@ -43,6 +43,7 @@
 	 * Flushes the block
 	 */
 	public void flush() {
+		// ignore
 	}
 	/**
 	 * Loads the block with the given number in memory, reading it from a RandomAccessFile.
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/BlocksIndexInput.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/BlocksIndexInput.java
index f9b995b..e05c4e0 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/BlocksIndexInput.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/BlocksIndexInput.java
@@ -16,10 +16,8 @@
 import java.util.ArrayList;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.core.index.IDocument;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.IQueryResult;
-import org.eclipse.jdt.internal.core.search.Util;
+import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This input is used for reading indexes saved using a BlocksIndexOutput.
@@ -119,9 +117,9 @@
 	/**
 	 * @see IndexInput#getIndexedFile(IDocument)
 	 */
-	public IndexedFile getIndexedFile(IDocument document) throws java.io.IOException {
+	public IndexedFile getIndexedFile(SearchDocument document) throws java.io.IOException {
 		setFirstFile();
-		String name= document.getName();
+		String name= document.getPath();
 		while (hasMoreFiles()) {
 			IndexedFile file= getCurrentFile();
 			String path= file.getPath();
@@ -172,7 +170,7 @@
 	/**
 	 * @see IndexInput#moveToNextFile()
 	 */
-	public void moveToNextFile() throws IOException {
+	public void moveToNextFile() {
 		filePosition++;
 	}
 	/**
@@ -211,21 +209,21 @@
 	/**
 	 * @see IndexInput#query(String)
 	 */
-	public IQueryResult[] query(String word) throws IOException {
+	public String[] query(String word) throws IOException {
 		open();
 		int[] fileNums= getMatchingFileNumbers(word.toCharArray());
 		int size= fileNums.length;
-		IQueryResult[] files= new IQueryResult[size];
+		String[] paths= new String[size];
 		for (int i= 0; i < size; ++i) {
-			files[i]= getIndexedFile(fileNums[i]);
+			paths[i]= getIndexedFile(fileNums[i]).getPath();
 		}
-		return files;
+		return paths;
 	}
 	/**
 	 * If no prefix is provided in the pattern, then this operation will have to walk
 	 * all the entries of the whole index.
 	 */
-	public IEntryResult[] queryEntriesMatching(char[] pattern/*, boolean isCaseSensitive*/) throws IOException {
+	public EntryResult[] queryEntriesMatching(char[] pattern/*, boolean isCaseSensitive*/) throws IOException {
 		open();
 	
 		if (pattern == null || pattern.length == 0) return null;
@@ -235,7 +233,7 @@
 			case -1 :
 				WordEntry entry = getEntry(pattern);
 				if (entry == null) return null;
-				return new IEntryResult[]{ new EntryResult(entry.getWord(), entry.getRefs()) };
+				return new EntryResult[]{ new EntryResult(entry.getWord(), entry.getRefs()) };
 			case 0 :
 				blockNums = summary.getAllBlockNums();
 				break;
@@ -245,7 +243,7 @@
 		}
 		if (blockNums == null || blockNums.length == 0)	return null;
 				
-		IEntryResult[] entries = new IEntryResult[5];
+		EntryResult[] entries = new EntryResult[5];
 		int count = 0;
 		for (int i = 0, max = blockNums.length; i < max; i++) {
 			IndexBlock block = getIndexBlock(blockNums[i]);
@@ -254,9 +252,8 @@
 			WordEntry entry = new WordEntry();
 			while (block.nextEntry(entry)) {
 				if (CharOperation.match(entry.getWord(), pattern, true)) {
-					if (count == entries.length){
-						System.arraycopy(entries, 0, entries = new IEntryResult[count*2], 0, count);
-					}
+					if (count == entries.length)
+						System.arraycopy(entries, 0, entries = new EntryResult[count*2], 0, count);
 					entries[count++] = new EntryResult(entry.getWord(), entry.getRefs());
 					found = true;
 				} else {
@@ -264,18 +261,24 @@
 				}
 			}
 		}
-		if (count != entries.length){
-			System.arraycopy(entries, 0, entries = new IEntryResult[count], 0, count);
-		}
+		if (count != entries.length)
+			System.arraycopy(entries, 0, entries = new EntryResult[count], 0, count);
 		return entries;
 	}
-	public IEntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException {
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.core.index.impl.IndexInput#queryEntries(char[], int)
+	 */
+	public EntryResult[] queryEntries(char[] pattern, int matchRule) throws IOException {
+		// TODO should evolve to provide different flavors of matching
+		return queryEntriesPrefixedBy(pattern);
+	}
+	public EntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException {
 		open();
 		
 		int blockLoc = summary.getFirstBlockLocationForPrefix(prefix);
 		if (blockLoc < 0) return null;
 			
-		IEntryResult[] entries = new IEntryResult[5];
+		EntryResult[] entries = new EntryResult[5];
 		int count = 0;
 		while(blockLoc >= 0){
 			IndexBlock block = getIndexBlock(summary.getBlockNum(blockLoc));
@@ -285,7 +288,7 @@
 			while (block.nextEntry(entry)) {
 				if (CharOperation.prefixEquals(prefix, entry.getWord())) {
 					if (count == entries.length){
-						System.arraycopy(entries, 0, entries = new IEntryResult[count*2], 0, count);
+						System.arraycopy(entries, 0, entries = new EntryResult[count*2], 0, count);
 					}
 					entries[count++] = new EntryResult(entry.getWord(), entry.getRefs());
 					found = true;
@@ -298,11 +301,11 @@
 		}
 		if (count == 0) return null;
 		if (count != entries.length){
-			System.arraycopy(entries, 0, entries = new IEntryResult[count], 0, count);
+			System.arraycopy(entries, 0, entries = new EntryResult[count], 0, count);
 		}
 		return entries;
 	}
-	public IQueryResult[] queryFilesReferringToPrefix(char[] prefix) throws IOException {
+	public String[] queryFilesReferringToPrefix(char[] prefix) throws IOException {
 		open();
 		
 		int blockLoc = summary.getFirstBlockLocationForPrefix(prefix);
@@ -335,30 +338,30 @@
 			blockLoc = summary.getNextBlockLocationForPrefix(prefix, blockLoc);				
 		}
 		/* extract indexed files */
-		IQueryResult[] files = new IQueryResult[count];
+		String[] paths = new String[count];
 		Object[] indexedFiles = fileMatches.valueTable;
 		for (int i = 0, index = 0, max = indexedFiles.length; i < max; i++){
 			IndexedFile indexedFile = (IndexedFile) indexedFiles[i];
 			if (indexedFile != null){
-				files[index++] = indexedFile;
+				paths[index++] = indexedFile.getPath();
 			}
 		}	
-		return files;
+		return paths;
 	}
 	/**
 	 * @see IndexInput#queryInDocumentNames(String)
 	 */
-	public IQueryResult[] queryInDocumentNames(String word) throws IOException {
+	public String[] queryInDocumentNames(String word) throws IOException {
 		open();
 		ArrayList matches= new ArrayList();
 		setFirstFile();
 		while (hasMoreFiles()) {
 			IndexedFile file= getCurrentFile();
 			if (file.getPath().indexOf(word) != -1)
-				matches.add(file);
+				matches.add(file.getPath());
 			moveToNextFile();
 		}
-		IQueryResult[] match= new IQueryResult[matches.size()];
+		String[] match= new String[matches.size()];
 		matches.toArray(match);
 		return match;
 	}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/CodeByteStream.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/CodeByteStream.java
index 54704f4..c6a1d7a 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/CodeByteStream.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/CodeByteStream.java
@@ -198,13 +198,13 @@
 		byteOffset= bitOffset= 0;
 		markByteOffset= markBitOffset= -1;
 	}
-	public void reset(byte[] bytes) {
-		this.bytes= bytes;
+	public void reset(byte[] bytesValue) {
+		this.bytes= bytesValue;
 		reset();
 	}
-	public void reset(byte[] bytes, int byteOffset) {
-		reset(bytes);
-		this.byteOffset= byteOffset;
+	public void reset(byte[] bytesValue, int byteOffsetValue) {
+		reset(bytesValue);
+		this.byteOffset= byteOffsetValue;
 	}
 	public boolean resetToMark() {
 		if (markByteOffset == -1)
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/EntryResult.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/EntryResult.java
index 284a8d7..9435f34 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/EntryResult.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/EntryResult.java
@@ -11,9 +11,8 @@
 package org.eclipse.jdt.internal.core.index.impl;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
 
-public class EntryResult implements IEntryResult {
+public class EntryResult {
 	private char[] word;
 	private int[]  fileRefs;
 	
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Field.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Field.java
index cef7dc6..96111ff 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Field.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Field.java
@@ -52,8 +52,8 @@
 	public byte[] buffer() {
 		return buffer;
 	}
-	public Field buffer(byte[] buffer) {
-		this.buffer= buffer;
+	public Field buffer(byte[] someBuffer) {
+		this.buffer= someBuffer;
 		return this;
 	}
 	public Field clear() {
@@ -67,12 +67,12 @@
 			n++;
 		}
 	}
-	public Field clear(int length) {
-		clear(buffer, offset, length);
+	public Field clear(int someLength) {
+		clear(buffer, offset, someLength);
 		return this;
 	}
-	public Field clear(int offset, int length) {
-		clear(buffer, this.offset + offset, length);
+	public Field clear(int someOffset, int someLength) {
+		clear(buffer, this.offset + someOffset, someLength);
 		return this;
 	}
 	protected static int compare(byte[] buffer1, int offset1, int length1, byte[] buffer2, int offset2, int length2) {
@@ -100,8 +100,8 @@
 		return compare(f1.buffer, f1.offset, f1.length, f2.buffer, f2.offset, f2.length);
 	}
 	// copy bytes from one offset to another within the field
-	public Field copy(int fromOffset, int toOffset, int length) {
-		System.arraycopy(buffer, offset + fromOffset, buffer, offset + toOffset, length);
+	public Field copy(int fromOffset, int toOffset, int someLength) {
+		System.arraycopy(buffer, offset + fromOffset, buffer, offset + toOffset, someLength);
 		return this;
 	}
 	public Field dec(int n) {
@@ -113,19 +113,19 @@
 		System.arraycopy(buffer, offset, result, 0, length);
 		return result;
 	}
-	public byte[] get(int offset, int length) {
-		byte[] result= new byte[length];
-		System.arraycopy(buffer, this.offset + offset, result, 0, length);
+	public byte[] get(int someOffset, int someLength) {
+		byte[] result= new byte[someLength];
+		System.arraycopy(buffer, this.offset + someOffset, result, 0, someLength);
 		return result;
 	}
-	public Field getField(int offset, int length) {
-		return new Field(buffer, this.offset + offset, length);
+	public Field getField(int someOffset, int someLength) {
+		return new Field(buffer, this.offset + someOffset, someLength);
 	}
 	public int getInt1() {
 		return buffer[this.offset];
 	}
-	public int getInt1(int offset) {
-		return buffer[this.offset + offset];
+	public int getInt1(int someOffset) {
+		return buffer[this.offset + someOffset];
 	}
 	public int getInt2() {
 		int i= this.offset;
@@ -133,8 +133,8 @@
 		v= (v << 8) | (buffer[i++] & 255);
 		return v;
 	}
-	public int getInt2(int offset) {
-		int i= this.offset + offset;
+	public int getInt2(int someOffset) {
+		int i= this.offset + someOffset;
 		int v= buffer[i++];
 		v= (v << 8) | (buffer[i++] & 255);
 		return v;
@@ -146,8 +146,8 @@
 		v= (v << 8) | (buffer[i++] & 255);
 		return v;
 	}
-	public int getInt3(int offset) {
-		int i= this.offset + offset;
+	public int getInt3(int someOffset) {
+		int i= this.offset + someOffset;
 		int v= buffer[i++];
 		v= (v << 8) | (buffer[i++] & 255);
 		v= (v << 8) | (buffer[i++] & 255);
@@ -161,8 +161,8 @@
 		v= (v << 8) | (buffer[i++] & 255);
 		return v;
 	}
-	public int getInt4(int offset) {
-		int i= this.offset + offset;
+	public int getInt4(int someOffset) {
+		int i= this.offset + someOffset;
 		int v= buffer[i++];
 		v= (v << 8) | (buffer[i++] & 255);
 		v= (v << 8) | (buffer[i++] & 255);
@@ -172,8 +172,8 @@
 	public int getUInt1() {
 		return buffer[this.offset] & 255;
 	}
-	public int getUInt1(int offset) {
-		return buffer[this.offset + offset] & 255;
+	public int getUInt1(int someOffset) {
+		return buffer[this.offset + someOffset] & 255;
 	}
 	public int getUInt2() {
 		int i= this.offset;
@@ -181,8 +181,8 @@
 		v= (v << 8) | (buffer[i++] & 255);
 		return v;
 	}
-	public int getUInt2(int offset) {
-		int i= this.offset + offset;
+	public int getUInt2(int someOffset) {
+		int i= this.offset + someOffset;
 		int v= (buffer[i++] & 255);
 		v= (v << 8) | (buffer[i++] & 255);
 		return v;
@@ -194,15 +194,15 @@
 		v= (v << 8) | (buffer[i++] & 255);
 		return v;
 	}
-	public int getUInt3(int offset) {
-		int i= this.offset + offset;
+	public int getUInt3(int someOffset) {
+		int i= this.offset + someOffset;
 		int v= (buffer[i++] & 255);
 		v= (v << 8) | (buffer[i++] & 255);
 		v= (v << 8) | (buffer[i++] & 255);
 		return v;
 	}
-	public char[] getUTF(int offset) throws UTFDataFormatException {
-		int pos= this.offset + offset;
+	public char[] getUTF(int someOffset) throws UTFDataFormatException {
+		int pos= this.offset + someOffset;
 		int utflen= getUInt2(pos);
 		pos += 2;
 		char str[]= new char[utflen];
@@ -262,8 +262,8 @@
 	public int length() {
 		return length;
 	}
-	public Field length(int length) {
-		this.length= length;
+	public Field length(int someLength) {
+		this.length= someLength;
 		return this;
 	}
 	/**
@@ -272,22 +272,22 @@
 	public int offset() {
 		return offset;
 	}
-	public Field offset(int offset) {
-		this.offset= offset;
+	public Field offset(int someOffset) {
+		this.offset= someOffset;
 		return this;
 	}
-	public Field pointTo(int offset) {
-		return new Field(buffer, this.offset + offset, 0);
+	public Field pointTo(int someOffset) {
+		return new Field(buffer, this.offset + someOffset, 0);
 	}
 	public Field put(byte[] b) {
 		return put(0, b);
 	}
-	public Field put(int offset, byte[] b) {
-		System.arraycopy(b, 0, buffer, this.offset + offset, b.length);
+	public Field put(int someOffset, byte[] b) {
+		System.arraycopy(b, 0, buffer, this.offset + someOffset, b.length);
 		return this;
 	}
-	public Field put(int offset, Field f) {
-		System.arraycopy(f.buffer, f.offset, buffer, this.offset + offset, f.length);
+	public Field put(int someOffset, Field f) {
+		System.arraycopy(f.buffer, f.offset, buffer, this.offset + someOffset, f.length);
 		return this;
 	}
 	public Field put(Field f) {
@@ -298,8 +298,8 @@
 		buffer[offset]= (byte) (n);
 		return this;
 	}
-	public Field putInt1(int offset, int n) {
-		buffer[this.offset + offset]= (byte) (n);
+	public Field putInt1(int someOffset, int n) {
+		buffer[this.offset + someOffset]= (byte) (n);
 		return this;
 	}
 	public Field putInt2(int n) {
@@ -308,8 +308,8 @@
 		buffer[i++]= (byte) (n >> 0);
 		return this;
 	}
-	public Field putInt2(int offset, int n) {
-		int i= this.offset + offset;
+	public Field putInt2(int someOffset, int n) {
+		int i= this.offset + someOffset;
 		buffer[i++]= (byte) (n >> 8);
 		buffer[i++]= (byte) (n >> 0);
 		return this;
@@ -321,8 +321,8 @@
 		buffer[i++]= (byte) (n >> 0);
 		return this;
 	}
-	public Field putInt3(int offset, int n) {
-		int i= this.offset + offset;
+	public Field putInt3(int someOffset, int n) {
+		int i= this.offset + someOffset;
 		buffer[i++]= (byte) (n >> 16);
 		buffer[i++]= (byte) (n >> 8);
 		buffer[i++]= (byte) (n >> 0);
@@ -336,15 +336,15 @@
 		buffer[i++]= (byte) (n >> 0);
 		return this;
 	}
-	public Field putInt4(int offset, int n) {
-		int i= this.offset + offset;
+	public Field putInt4(int someOffset, int n) {
+		int i= this.offset + someOffset;
 		buffer[i++]= (byte) (n >> 24);
 		buffer[i++]= (byte) (n >> 16);
 		buffer[i++]= (byte) (n >> 8);
 		buffer[i++]= (byte) (n >> 0);
 		return this;
 	}
-	public int putUTF(int offset, char[] str) {
+	public int putUTF(int someOffset, char[] str) {
 		int strlen= str.length;
 		int utflen= 0;
 		for (int i= 0; i < strlen; i++) {
@@ -359,7 +359,7 @@
 		}
 		if (utflen > 65535)
 			throw new IllegalArgumentException();
-		int pos= this.offset + offset;
+		int pos= this.offset + someOffset;
 		buffer[pos++]= (byte) ((utflen >>> 8) & 0xFF);
 		buffer[pos++]= (byte) ((utflen >>> 0) & 0xFF);
 		for (int i= 0; i < strlen; i++) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/FileDocument.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/FileDocument.java
deleted file mode 100644
index f02bd5a..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/FileDocument.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.index.impl;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.eclipse.jdt.core.JavaCore;
-
-/**
- * A <code>FileDocument</code> represents a java.io.File.
- */
-
-public class FileDocument extends PropertyDocument {
-	File file;
-
-	public FileDocument(File file) {
-		super();
-		this.file= file;
-	}
-	/**
-	 * @see IDocument#getByteContent
-	 */
-	public byte[] getByteContent() throws IOException {
-		return org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file);
-	}
-	/**
-	 * @see IDocument#getCharContent
-	 */
-	public char[] getCharContent() throws IOException {
-		return org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(file, null);
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getEncoding()
-	 */
-	public String getEncoding() {
-		return JavaCore.getOption(JavaCore.CORE_ENCODING); // no custom encoding
-	}
-
-	/**
-	 * @see IDocument#getName
-	 */
-	public String getName() {
-		return file.getAbsolutePath().replace(File.separatorChar, IIndexConstants.FILE_SEPARATOR);
-	}
-	/**
-	 * @see IDocument#getStringContent
-	 */
-	public String getStringContent() throws IOException {
-		return new String(getCharContent());
-	}
-	/**
-	 * @see IDocument#getType
-	 */
-	public String getType() {
-		int lastDot= file.getPath().lastIndexOf('.');
-		if (lastDot == -1)
-			return ""; //$NON-NLS-1$
-		return file.getPath().substring(lastDot + 1);
-	}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/FileListBlock.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/FileListBlock.java
index bb16e9c..cf31639 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/FileListBlock.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/FileListBlock.java
@@ -13,6 +13,8 @@
 import java.io.IOException;
 import java.util.ArrayList;
 
+import org.eclipse.jdt.internal.core.util.Util;
+
 public class FileListBlock extends Block {
 
 	protected int offset= 0;
@@ -28,22 +30,22 @@
 	 * difference between its name and the name of the previous indexedfile ...	
 	 */
 	public boolean addFile(IndexedFile indexedFile) {
-		int offset= this.offset;
+		int currentOffset= this.offset;
 		if (isEmpty()) {
-			field.putInt4(offset, indexedFile.getFileNumber());
-			offset += 4;
+			field.putInt4(currentOffset, indexedFile.getFileNumber());
+			currentOffset += 4;
 		}
 		String path= indexedFile.getPath();
 		int prefixLen= prevPath == null ? 0 : Util.prefixLength(prevPath, path);
 		int sizeEstimate= 2 + 2 + (path.length() - prefixLen) * 3;
-		if (offset + sizeEstimate > blockSize - 2)
+		if (currentOffset + sizeEstimate > blockSize - 2)
 			return false;
-		field.putInt2(offset, prefixLen);
-		offset += 2;
+		field.putInt2(currentOffset, prefixLen);
+		currentOffset += 2;
 		char[] chars= new char[path.length() - prefixLen];
 		path.getChars(prefixLen, path.length(), chars, 0);
-		offset += field.putUTF(offset, chars);
-		this.offset= offset;
+		currentOffset += field.putUTF(currentOffset, chars);
+		this.offset= currentOffset;
 		prevPath= path;
 		return true;
 	}
@@ -58,12 +60,12 @@
 			offset= 0;
 		}
 	}
-	public IndexedFile getFile(int fileNum) throws IOException {
+	public IndexedFile getFile(int fileNum) {
 		IndexedFile resp= null;
 		try {
-			String[] paths= getPaths();
+			String[] currentPaths = getPaths();
 			int i= fileNum - field.getInt4(0);
-			resp= new IndexedFile(paths[i], fileNum);
+			resp= new IndexedFile(currentPaths[i], fileNum);
 		} catch (Exception e) {
 			//fileNum too big
 		}
@@ -75,24 +77,24 @@
 	protected String[] getPaths() throws IOException {
 		if (paths == null) {
 			ArrayList v= new ArrayList();
-			int offset= 4;
-			char[] prevPath= null;
+			int currentOffset = 4;
+			char[] previousPath = null;
 			for (;;) {
-				int prefixLen= field.getUInt2(offset);
-				offset += 2;
-				int utfLen= field.getUInt2(offset);
-				char[] path= field.getUTF(offset);
-				offset += 2 + utfLen;
+				int prefixLen= field.getUInt2(currentOffset);
+				currentOffset += 2;
+				int utfLen= field.getUInt2(currentOffset);
+				char[] path= field.getUTF(currentOffset);
+				currentOffset += 2 + utfLen;
 				if (prefixLen != 0) {
 					char[] temp= new char[prefixLen + path.length];
-					System.arraycopy(prevPath, 0, temp, 0, prefixLen);
+					System.arraycopy(previousPath, 0, temp, 0, prefixLen);
 					System.arraycopy(path, 0, temp, prefixLen, path.length);
 					path= temp;
 				}
 				if (path.length == 0)
 					break;
 				v.add(new String(path));
-				prevPath= path;
+				previousPath= path;
 			}
 			paths= new String[v.size()];
 			v.toArray(paths);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/GammaCompressedIndexBlock.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/GammaCompressedIndexBlock.java
index 627b9ca..d2d1183 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/GammaCompressedIndexBlock.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/GammaCompressedIndexBlock.java
@@ -12,6 +12,8 @@
 
 import java.io.UTFDataFormatException;
 
+import org.eclipse.jdt.internal.core.util.Util;
+
 /**
  * Uses prefix coding on words, and gamma coding of document numbers differences.
  */
@@ -30,7 +32,7 @@
 	 */
 	public boolean addEntry(WordEntry entry) {
 		writeCodeStream.reset();
-		encodeEntry(entry, prevWord, writeCodeStream);
+		encodeEntry(entry);
 		if (offset + writeCodeStream.byteLength() > this.blockSize - 2) {
 			return false;
 		}
@@ -40,19 +42,19 @@
 		prevWord= entry.getWord();
 		return true;
 	}
-	protected void encodeEntry(WordEntry entry, char[] prevWord, CodeByteStream codeStream) {
+	private void encodeEntry(WordEntry entry) {
 		char[] word= entry.getWord();
 		int prefixLen= prevWord == null ? 0 : Util.prefixLength(prevWord, word);
-		codeStream.writeByte(prefixLen);
-		codeStream.writeUTF(word, prefixLen, word.length);
+		writeCodeStream.writeByte(prefixLen);
+		writeCodeStream.writeUTF(word, prefixLen, word.length);
 		int n= entry.getNumRefs();
-		codeStream.writeGamma(n);
+		writeCodeStream.writeGamma(n);
 		int prevRef= 0;
 		for (int i= 0; i < n; ++i) {
 			int ref= entry.getRef(i);
 			if (ref <= prevRef)
 				throw new IllegalArgumentException();
-			codeStream.writeGamma(ref - prevRef);
+			writeCodeStream.writeGamma(ref - prevRef);
 			prevRef= ref;
 		}
 	}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IFileDocument.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IFileDocument.java
deleted file mode 100644
index cad1c5c..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IFileDocument.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.index.impl;
-
-import java.io.IOException;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.compiler.CharOperation;
-
-/**
- * An <code>IFileDocument</code> represents an IFile.
- */
-
-public class IFileDocument extends PropertyDocument {
-	protected IFile file;
-
-	// cached contents if needed - only one of them is used at a time
-	protected char[] charContents;
-	protected byte[] byteContents;
-	/**
-	 * IFileDocument constructor comment.
-	 */
-	public IFileDocument(IFile file) {
-		this(file, (char[])null);
-	}
-	/**
-	 * IFileDocument constructor comment.
-	 */
-	public IFileDocument(IFile file, byte[] byteContents) {
-		this.file= file;
-		this.byteContents= byteContents;
-	}
-	/**
-	 * IFileDocument constructor comment.
-	 */
-	public IFileDocument(IFile file, char[] charContents) {
-		this.file= file;
-		this.charContents= charContents;
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getByteContent()
-	 */
-	public byte[] getByteContent() throws IOException {
-		if (byteContents != null) return byteContents;
-		IPath location = file.getLocation();
-		if (location == null) return new byte[0];
-		return byteContents = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(location.toFile());
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getCharContent()
-	 */
-	public char[] getCharContent() throws IOException {
-		if (charContents != null) return charContents;
-		IPath location = file.getLocation();
-		if (location == null) return CharOperation.NO_CHAR;
-		return charContents = org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(
-					location.toFile(), 
-					getEncoding());
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getEncoding()
-	 */
-	public String getEncoding() {
-		return JavaCore.create(file.getProject()).getOption(JavaCore.CORE_ENCODING, true);
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getName()
-	 */
-	public String getName() {
-		return file.getFullPath().toString();
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getStringContent()
-	 */
-	public String getStringContent() throws java.io.IOException {
-		return new String(getCharContent());
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getType()
-	 */
-	public String getType() {
-		String extension= file.getFileExtension();
-		if (extension == null)
-			return ""; //$NON-NLS-1$
-		return extension;
-	}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IIndexConstants.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IIndexConstants.java
index efd0567..182c847 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IIndexConstants.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IIndexConstants.java
@@ -17,7 +17,7 @@
 	/**
 	 * The signature of the index file.
 	 */
-	public static final String SIGNATURE= "INDEX FILE 0.012"; //$NON-NLS-1$
+	public static final String SIGNATURE= "INDEX FILE 0.016"; //$NON-NLS-1$
 	/**
 	 * The separator for files in the index file.
 	 */
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/InMemoryIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/InMemoryIndex.java
index 6e3272f..7b6ee0d 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/InMemoryIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/InMemoryIndex.java
@@ -13,7 +13,8 @@
 import java.io.File;
 import java.io.IOException;
 
-import org.eclipse.jdt.internal.core.index.IDocument;
+import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * This index stores the document names in an <code>ObjectVector</code>, and the words in
@@ -43,7 +44,7 @@
 		init();
 	}
 
-	public IndexedFile addDocument(IDocument document) {
+	public IndexedFile addDocument(SearchDocument document) {
 		IndexedFile indexedFile= this.files.add(document);
 		this.footprint += indexedFile.footprint() + 4;
 		this.sortedFiles = null;
@@ -66,7 +67,7 @@
 	 * If the word does not exist, it adds it in the index.
 	 */
 	protected void addRef(char[] word, int fileNum) {
-		WordEntry entry= (WordEntry) this.words.get(word);
+		WordEntry entry= this.words.get(word);
 		if (entry == null) {
 			entry= new WordEntry(word);
 			entry.addRef(fileNum);
@@ -130,9 +131,9 @@
 	 */
 	protected WordEntry[] getSortedWordEntries() {
 		if (this.sortedWordEntries == null) {
-			WordEntry[] words= this.words.asArray();
-			Util.sort(words);
-			this.sortedWordEntries= words;
+			WordEntry[] wordEntries= this.words.asArray();
+			Util.sort(wordEntries);
+			this.sortedWordEntries= wordEntries;
 		}
 		return this.sortedWordEntries;
 	}
@@ -140,7 +141,7 @@
 	 * Returns the word entry corresponding to the given word.
 	 */
 	protected WordEntry getWordEntry(char[] word) {
-		return (WordEntry) words.get(word);
+		return words.get(word);
 	}
 	/**
 	 * Initialises the fields of the index
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Index.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Index.java
index 74a4675..bf653c5 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Index.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Index.java
@@ -15,11 +15,9 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.eclipse.jdt.internal.core.index.IDocument;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
+import org.eclipse.jdt.core.search.SearchDocument;
 import org.eclipse.jdt.internal.core.index.IIndex;
 import org.eclipse.jdt.internal.core.index.IIndexer;
-import org.eclipse.jdt.internal.core.index.IQueryResult;
 
 /**
  * An Index is used to create an index on the disk, and to make queries. It uses a set of 
@@ -89,11 +87,11 @@
 	 * If the document already exists in the index, it overrides the previous one. The changes will be 
 	 * taken into account after a merge.
 	 */
-	public void add(IDocument document, IIndexer indexer) throws IOException {
+	public void add(SearchDocument document, IIndexer indexer) throws IOException {
 		if (timeToMerge()) {
 			merge();
 		}
-		IndexedFile indexedFile= addsIndex.getIndexedFile(document.getName());
+		IndexedFile indexedFile= addsIndex.getIndexedFile(document.getPath());
 		if (indexedFile != null /*&& removedInAdds.get(document.getName()) == null*/
 			)
 			remove(indexedFile, MergeFactory.ADDS_INDEX);
@@ -112,25 +110,25 @@
 	/**
 	 * Initialises the indexGenerator.
 	 */
-	public void empty() throws IOException {
-
-		if (indexFile.exists()){
-			indexFile.delete();
-			//initialisation of mainIndex
-			InMemoryIndex mainIndex= new InMemoryIndex();
-			IndexOutput mainIndexOutput= new BlocksIndexOutput(indexFile);
-			if (!indexFile.exists())
-				mainIndex.save(mainIndexOutput);
-		}
-
-		//initialisation of addsIndex
-		addsIndex= new InMemoryIndex();
-		addsIndexInput= new SimpleIndexInput(addsIndex);
-
-		//vectors who keep track of the removed Files
-		removedInAdds= new HashMap(11);
-		removedInOld= new HashMap(11);
-	}
+//	public void empty() throws IOException {
+//
+//		if (indexFile.exists()){
+//			indexFile.delete();
+//			//initialisation of mainIndex
+//			InMemoryIndex mainIndex= new InMemoryIndex();
+//			IndexOutput mainIndexOutput= new BlocksIndexOutput(indexFile);
+//			if (!indexFile.exists())
+//				mainIndex.save(mainIndexOutput);
+//		}
+//
+//		//initialisation of addsIndex
+//		addsIndex= new InMemoryIndex();
+//		addsIndexInput= new SimpleIndexInput(addsIndex);
+//
+//		//vectors who keep track of the removed Files
+//		removedInAdds= new HashMap(11);
+//		removedInOld= new HashMap(11);
+//	}
 	/**
 	 * @see IIndex#getIndexFile
 	 */
@@ -138,32 +136,6 @@
 		return indexFile;
 	}
 	/**
-	 * @see IIndex#getNumDocuments
-	 */
-	public int getNumDocuments() throws IOException {
-		//save();
-		IndexInput input= new BlocksIndexInput(indexFile);
-		try {
-			input.open();
-			return input.getNumFiles();
-		} finally {
-			input.close();
-		}		
-	}
-	/**
-	 * @see IIndex#getNumWords
-	 */
-	public int getNumWords() throws IOException {
-		//save();
-		IndexInput input= new BlocksIndexInput(indexFile);
-		try {
-			input.open();
-			return input.getNumWords();
-		} finally {
-			input.close();
-		}		
-	}
-	/**
 	 * Returns the path corresponding to a given document number
 	 */
 	public String getPath(int documentNumber) throws IOException {
@@ -259,7 +231,7 @@
 	/**
 	 * @see IIndex#query
 	 */
-	public IQueryResult[] query(String word) throws IOException {
+	public String[] query(String word) throws IOException {
 		//save();
 		IndexInput input= new BlocksIndexInput(indexFile);
 		try {
@@ -268,7 +240,7 @@
 			input.close();
 		}
 	}
-	public IEntryResult[] queryEntries(char[] prefix) throws IOException {
+	public EntryResult[] queryEntries(char[] prefix) throws IOException {
 		//save();
 		IndexInput input= new BlocksIndexInput(indexFile);
 		try {
@@ -280,7 +252,7 @@
 	/**
 	 * @see IIndex#queryInDocumentNames
 	 */
-	public IQueryResult[] queryInDocumentNames(String word) throws IOException {
+	public String[] queryInDocumentNames(String word) throws IOException {
 		//save();
 		IndexInput input= new BlocksIndexInput(indexFile);
 		try {
@@ -292,7 +264,7 @@
 	/**
 	 * @see IIndex#queryPrefix
 	 */
-	public IQueryResult[] queryPrefix(char[] prefix) throws IOException {
+	public String[] queryPrefix(char[] prefix) throws IOException {
 		//save();
 		IndexInput input= new BlocksIndexInput(indexFile);
 		try {
@@ -304,7 +276,7 @@
 	/**
 	 * @see IIndex#remove
 	 */
-	public void remove(String documentName) throws IOException {
+	public void remove(String documentName) {
 		IndexedFile file= addsIndex.getIndexedFile(documentName);
 		if (file != null) {
 			//the file is in the adds Index, we remove it from this one
@@ -325,7 +297,7 @@
 	 * Removes the given document from the given index (MergeFactory.ADDS_INDEX for the
 	 * in memory index, MergeFactory.OLD_INDEX for the index on the disk).
 	 */
-	protected void remove(IndexedFile file, int index) throws IOException {
+	protected void remove(IndexedFile file, int index) {
 		String name= file.getPath();
 		if (index == MergeFactory.ADDS_INDEX) {
 			Int lastRemoved= (Int) removedInAdds.get(name);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexBlock.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexBlock.java
index 8384ac9..a6665db 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexBlock.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexBlock.java
@@ -74,5 +74,6 @@
 	public abstract boolean nextEntry(WordEntry entry);
 
 	public void reset() {
+		// do nothing
 	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexInput.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexInput.java
index cecdb76..bae3eda 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexInput.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexInput.java
@@ -12,9 +12,7 @@
 
 import java.io.IOException;
 
-import org.eclipse.jdt.internal.core.index.IDocument;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.IQueryResult;
+import org.eclipse.jdt.core.search.SearchDocument;
 
 
 /**
@@ -52,7 +50,7 @@
 	/**
 	 * Returns the current file the indexInput is pointing to in the index.
 	 */
-	public WordEntry getCurrentWordEntry() throws IOException {
+	public WordEntry getCurrentWordEntry() {
 		if (!hasMoreWords())
 			return null;
 		return currentWordEntry;
@@ -73,7 +71,7 @@
 	 * reads in (e.g. the indexedFile with the same path in this index), or null if such 
 	 * indexedFile does not exist.
 	 */
-	public abstract IndexedFile getIndexedFile(IDocument document) throws IOException;
+	public abstract IndexedFile getIndexedFile(SearchDocument document) throws IOException;
 	/**
 	 * Returns the number of files in the index.
 	 */
@@ -102,7 +100,7 @@
 	/**
 	 * Moves the pointer on the current file to the next file in the index.
 	 */
-	public abstract void moveToNextFile() throws IOException;
+	public abstract void moveToNextFile();
 	/**
 	 * Moves the pointer on the current word to the next file in the index.
 	 */
@@ -114,13 +112,14 @@
 	/**
 	 * Returns the list of the files containing the given word in the index.
 	 */
-	public abstract IQueryResult[] query(String word) throws IOException;
-	public abstract IEntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException;
-	public abstract IQueryResult[] queryFilesReferringToPrefix(char[] prefix) throws IOException;
+	public abstract String[] query(String word) throws IOException;
+	public abstract EntryResult[] queryEntries(char[] pattern, int matchRule) throws IOException;
+	public abstract EntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException;
+	public abstract String[] queryFilesReferringToPrefix(char[] prefix) throws IOException;
 	/**
 	 * Returns the list of the files whose name contain the given word in the index.
 	 */
-	public abstract IQueryResult[] queryInDocumentNames(String word) throws IOException;
+	public abstract String[] queryInDocumentNames(String word) throws IOException;
 	/**
 	 * Set the pointer on the current file to the first file of the index.
 	 */
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexSummary.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexSummary.java
index f1db4fe..27c4a02 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexSummary.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexSummary.java
@@ -15,6 +15,7 @@
 import java.util.ArrayList;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * An indexSummary is used when saving an index into a BlocksIndexOuput or 
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexedFile.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexedFile.java
index f12ba7f..7a8b3ab 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexedFile.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexedFile.java
@@ -11,16 +11,16 @@
 package org.eclipse.jdt.internal.core.index.impl;
 
 import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.internal.core.index.IDocument;
-import org.eclipse.jdt.internal.core.index.IQueryResult;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchDocument;
 
 /**
  * An indexedFile associates a number to a document path, and document properties. 
  * It is what we add into an index, and the result of a query.
  */
 
-public class IndexedFile implements IQueryResult {
-	protected String path;
+public class IndexedFile {
+	public String path;
 	protected int fileNumber;
 
 	public IndexedFile(String path, int fileNum) {
@@ -29,10 +29,10 @@
 		this.fileNumber= fileNum;
 		this.path= path;
 	}
-	public IndexedFile(IDocument document, int fileNum) {
+	public IndexedFile(SearchDocument document, int fileNum) {
 		if (fileNum < 1)
 			throw new IllegalArgumentException();
-		this.path= document.getName();
+		this.path= document.getPath();
 		this.fileNumber= fileNum;
 	}
 	/**
@@ -58,7 +58,7 @@
 	 * </ul>
 	 */
 	public static String convertPath(String pathString) {
-		int index = pathString.indexOf(JarFileEntryDocument.JAR_FILE_ENTRY_SEPARATOR);
+		int index = pathString.indexOf(IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR);
 		if (index == -1)
 			return pathString;
 			
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexedFileHashedArray.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexedFileHashedArray.java
index 3cbbba5..6db5bd9 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexedFileHashedArray.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexedFileHashedArray.java
@@ -12,7 +12,7 @@
 
 import java.util.ArrayList;
 
-import org.eclipse.jdt.internal.core.index.IDocument;
+import org.eclipse.jdt.core.search.SearchDocument;
 
 public final class IndexedFileHashedArray {
 
@@ -31,7 +31,7 @@
 	this.replacedElements = null;
 }
 
-public IndexedFile add(IDocument document) {
+public IndexedFile add(SearchDocument document) {
 	return add(new IndexedFile(document, ++lastId));
 }
 
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexerOutput.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexerOutput.java
index 107911b..91150f0 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexerOutput.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/IndexerOutput.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.index.impl;
 
-import org.eclipse.jdt.internal.core.index.IDocument;
+import org.eclipse.jdt.core.search.SearchDocument;
 import org.eclipse.jdt.internal.core.index.IIndexerOutput;
 
 /**
@@ -23,7 +23,6 @@
 public class IndexerOutput implements IIndexerOutput {
 	protected InMemoryIndex index;
 	protected IndexedFile indexedFile;
-	protected IDocument document;
 	/**
 	 * IndexerOutput constructor comment.
 	 */
@@ -34,7 +33,7 @@
 	 * Adds the given document to the inMemoryIndex.
 	 */
 
-	public void addDocument(IDocument document) {
+	public void addDocument(SearchDocument document) {
 		if (indexedFile == null) {
 			indexedFile= index.addDocument(document);
 		} else {
@@ -50,10 +49,4 @@
 		}
 		index.addRef(indexedFile, word);
 	}
-	/**
-	 * Adds a reference to the given word to the inMemoryIndex.
-	 */
-	public void addRef(String word) {
-		addRef(word.toCharArray());
-	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/JarFileDocument.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/JarFileDocument.java
deleted file mode 100644
index 31bd467..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/JarFileDocument.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.index.impl;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.IPath;
-
-/**
- * An <code>JarFileDocument</code> represents an jar file.
- */
-
-public class JarFileDocument extends PropertyDocument {
-	protected IFile file;
-	/**
-	 * JarFileDocument constructor comment.
-	 */
-	public JarFileDocument(IFile file) {
-		this.file = file;
-	}
-	/**
-	 * This API always return null for a JarFileDocument
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getByteContent()
-	 */
-	public byte[] getByteContent() throws IOException {
-		return null;
-	}
-	/**
-	 * This API always return null for a JarFileDocument
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getCharContent()
-	 */
-	public char[] getCharContent() throws IOException {
-		return null;
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getEncoding()
-	 */
-	public String getEncoding() {
-		return null;
-	}
-
-	public File getFile() {
-		IPath location = file.getLocation();
-		if (location == null) {
-			return null;
-		} else {
-			return location.toFile();
-		}
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getName()
-	 */
-	public String getName() {
-		return file.getFullPath().toString();
-	}
-	/**
-	 * This API always return null for a JarFileDocument
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getByteContent()
-	 */
-	public String getStringContent() throws java.io.IOException {
-		return null;
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getType()
-	 */
-	public String getType() {
-		String extension= file.getFileExtension();
-		if (extension == null)
-			return ""; //$NON-NLS-1$
-		return extension;
-	}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/JarFileEntryDocument.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/JarFileEntryDocument.java
deleted file mode 100644
index c83c6db..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/JarFileEntryDocument.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.index.impl;
-
-import java.io.IOException;
-import java.util.zip.ZipEntry;
-
-import org.eclipse.core.runtime.Path;
-
-
-/**
- * An <code>JarFileEntryDocument</code> represents an jar file.
- */
-
-public class JarFileEntryDocument extends PropertyDocument {
-	protected ZipEntry zipEntry;
-	protected byte[] byteContents;
-	protected Path zipFilePath;
-	public static final String JAR_FILE_ENTRY_SEPARATOR = "|"; //$NON-NLS-1$
-/**
- * JarFileEntryDocument constructor comment.
- */
-public JarFileEntryDocument(ZipEntry entry, byte[] contents, Path zipFilePath) {
-	this.zipEntry = entry;
-	this.byteContents = contents;
-	this.zipFilePath = zipFilePath;
-}
-/**
- * This API always return null for a JarFileDocument
- * @see org.eclipse.jdt.internal.core.index.IDocument#getByteContent()
- */
-public byte[] getByteContent() throws IOException {
-	return this.byteContents;
-}
-/**
- * This API always return null for a JarFileDocument
- * @see org.eclipse.jdt.internal.core.index.IDocument#getCharContent()
- */
-public char[] getCharContent() throws IOException {
-	return null;
-}
-/**
- * @see org.eclipse.jdt.internal.core.index.IDocument#getEncoding()
- */
-public String getEncoding() {
-	return null;
-}
-
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getName()
-	 */
-	public String getName() {
-		return zipFilePath + JAR_FILE_ENTRY_SEPARATOR + zipEntry.getName();
-	}
-/**
- * This API always return null for a JarFileDocument
- * @see org.eclipse.jdt.internal.core.index.IDocument#getByteContent()
- */
-public String getStringContent() throws java.io.IOException {
-	return null;
-}
-	/**
-	 * @see org.eclipse.jdt.internal.core.index.IDocument#getType()
-	 */
-	public String getType() {
-		return "class"; //$NON-NLS-1$
-	}
-public void setBytes(byte[] byteContents) {
-	this.byteContents = byteContents;
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/LRUCache.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/LRUCache.java
index c6eb80d..9823815 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/LRUCache.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/LRUCache.java
@@ -383,7 +383,7 @@
 		LRUCacheEntry entry;
 
 		/* Check whether there's an entry in the cache */
-		newSpace= spaceFor(key, value);
+		newSpace= spaceFor(value);
 		entry= (LRUCacheEntry) fEntryTable.get(key);
 
 		if (entry != null) {
@@ -439,9 +439,9 @@
 		fSpaceLimit= limit;
 	}
 	/**
-	 * Returns the space taken by the given key and value.
+	 * Returns the space taken by the given value.
 	 */
-	protected int spaceFor(Object key, Object value) {
+	protected int spaceFor(Object value) {
 
 		if (value instanceof ILRUCacheable) {
 			return ((ILRUCacheable) value).getCacheFootprint();
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/MergeFactory.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/MergeFactory.java
index 5492779..3d0b6ab 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/MergeFactory.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/MergeFactory.java
@@ -13,6 +13,8 @@
 import java.io.IOException;
 import java.util.Map;
 
+import org.eclipse.jdt.internal.core.util.Util;
+
 /**
  * A mergeFactory is used to merge 2 indexes into one. One of the indexes 
  * (oldIndex) is on the disk and the other(addsIndex) is in memory.
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/PropertyDocument.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/PropertyDocument.java
deleted file mode 100644
index 9564c68..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/PropertyDocument.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.index.impl;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import org.eclipse.jdt.internal.core.index.IDocument;
-
-/**
- * The properties of a document are stored into a hashtable.
- * @see IDocument
- */
-
-public abstract class PropertyDocument implements IDocument {
-	protected Hashtable properties;
-	public PropertyDocument() {
-		properties= new Hashtable(5);
-	}
-	/**
-	 * @see IDocument#getProperty
-	 */
-	public String getProperty(String property) {
-		return (String) properties.get(property);
-	}
-	/**
-	 * @see IDocument#getPropertyNames
-	 */
-
-	public Enumeration getPropertyNames() {
-		return properties.keys();
-	}
-	/**
-	 * @see IDocument#setProperty
-	 */
-
-	public void setProperty(String property, String value) {
-		properties.put(property, value);
-	}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/SimpleIndexBlock.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/SimpleIndexBlock.java
index 65dffd7..b1e9b15 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/SimpleIndexBlock.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/SimpleIndexBlock.java
@@ -30,39 +30,39 @@
 		char[] word= entry.getWord();
 		int n= entry.getNumRefs();
 		int sizeEstimate= 2 + word.length * 3 + 4 + n * 4;
-		int offset= this.offset;
-		if (offset + sizeEstimate > this.blockSize - 2)
+		int off= this.offset;
+		if (off + sizeEstimate > this.blockSize - 2)
 			return false;
-		offset += field.putUTF(offset, word);
-		field.putInt4(offset, n);
-		offset += 4;
+		off += field.putUTF(off, word);
+		field.putInt4(off, n);
+		off += 4;
 		for (int i= 0; i < n; ++i) {
-			field.putInt4(offset, entry.getRef(i));
-			offset += 4;
+			field.putInt4(off, entry.getRef(i));
+			off += 4;
 		}
-		this.offset= offset;
+		this.offset= off;
 		return true;
 	}
 	public WordEntry findEntry(char[] word) {
 		try {
-			int offset= 0;
+			int off= 0;
 			int byteLen;
-			while ((byteLen= field.getUInt2(offset)) != 0) {
-				char[] tempWord= field.getUTF(offset);
-				offset += byteLen + 2;
+			while ((byteLen= field.getUInt2(off)) != 0) {
+				char[] tempWord= field.getUTF(off);
+				off += byteLen + 2;
 				if (CharOperation.equals(tempWord, word)) {
 					WordEntry entry= new WordEntry(word);
-					int n= field.getInt4(offset);
-					offset += 4;
+					int n= field.getInt4(off);
+					off += 4;
 					for (int i= 0; i < n; ++i) {
-						int ref= field.getInt4(offset);
-						offset += 4;
+						int ref= field.getInt4(off);
+						off += 4;
 						entry.addRef(ref);
 					}
 					return entry;
 				} else {
-					int n= field.getInt4(offset);
-					offset += 4 + 4 * n;
+					int n= field.getInt4(off);
+					off += 4 + 4 * n;
 				}
 			}
 			return null;
@@ -90,21 +90,21 @@
 	 */
 	public boolean nextEntry(WordEntry entry) {
 		try {
-			int offset= this.offset;
-			int byteLen= field.getUInt2(offset);
+			int off= this.offset;
+			int byteLen= field.getUInt2(off);
 			if (byteLen == 0)
 				return false;
-			char[] word= field.getUTF(offset);
-			offset += byteLen + 2;
+			char[] word= field.getUTF(off);
+			off += byteLen + 2;
 			entry.reset(word);
-			int n= field.getInt4(offset);
-			offset += 4;
+			int n= field.getInt4(off);
+			off += 4;
 			for (int i= 0; i < n; ++i) {
-				int ref= field.getInt4(offset);
-				offset += 4;
+				int ref= field.getInt4(off);
+				off += 4;
 				entry.addRef(ref);
 			}
-			this.offset= offset;
+			this.offset= off;
 			return true;
 		} catch (UTFDataFormatException e) {
 			return false;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/SimpleIndexInput.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/SimpleIndexInput.java
index 0066e09..ea0d2c6 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/SimpleIndexInput.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/SimpleIndexInput.java
@@ -10,12 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.index.impl;
 
-import java.io.IOException;
 import java.util.ArrayList;
 
-import org.eclipse.jdt.internal.core.index.IDocument;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.IQueryResult;
+import org.eclipse.jdt.core.search.SearchDocument;
 
 /**
  * A simpleIndexInput is an input on an in memory Index. 
@@ -35,17 +32,18 @@
 	 * @see IndexInput#clearCache()
 	 */
 	public void clearCache() {
+		// implements abstract method
 	}
 	/**
 	 * @see IndexInput#close()
 	 */
-	public void close() throws IOException {
+	public void close() {
 		sortedFiles= null;
 	}
 	/**
 	 * @see IndexInput#getCurrentFile()
 	 */
-	public IndexedFile getCurrentFile() throws IOException {
+	public IndexedFile getCurrentFile() {
 		if (!hasMoreFiles())
 			return null;
 		return currentFile;
@@ -53,7 +51,7 @@
 	/**
 	 * @see IndexInput#getIndexedFile(int)
 	 */
-	public IndexedFile getIndexedFile(int fileNum) throws IOException {
+	public IndexedFile getIndexedFile(int fileNum) {
 		for (int i= 0; i < sortedFiles.length; i++)
 			if (sortedFiles[i].getFileNumber() == fileNum)
 				return sortedFiles[i];
@@ -62,8 +60,8 @@
 	/**
 	 * @see IndexInput#getIndexedFile(IDocument)
 	 */
-	public IndexedFile getIndexedFile(IDocument document) throws IOException {
-		String name= document.getName();
+	public IndexedFile getIndexedFile(SearchDocument document) {
+		String name= document.getPath();
 		for (int i= index.getNumFiles(); i >= 1; i--) {
 			IndexedFile file= getIndexedFile(i);
 			if (name.equals(file.getPath()))
@@ -96,7 +94,7 @@
 	/**
 	 * @see IndexInput#moveToNextFile()
 	 */
-	public void moveToNextFile() throws IOException {
+	public void moveToNextFile() {
 		filePosition++;
 		if (!hasMoreFiles()) {
 			return;
@@ -106,7 +104,7 @@
 	/**
 	 * @see IndexInput#moveToNextWordEntry()
 	 */
-	public void moveToNextWordEntry() throws IOException {
+	public void moveToNextWordEntry() /* throws IOException */ {
 		wordPosition++;
 		if (hasMoreWords())
 			currentWordEntry= sortedWordEntries[wordPosition - 1];
@@ -114,7 +112,7 @@
 	/**
 	 * @see IndexInput#open()
 	 */
-	public void open() throws IOException {
+	public void open() {
 		sortedWordEntries= index.getSortedWordEntries();
 		sortedFiles= index.getSortedFiles();
 		filePosition= 1;
@@ -125,25 +123,28 @@
 	/**
 	 * @see IndexInput#query(String)
 	 */
-	public IQueryResult[] query(String word) throws IOException {
+	public String[] query(String word) {
 		char[] wordChar= word.toCharArray();
 		WordEntry wordEntry= index.getWordEntry(wordChar);
 		int[] fileNums= wordEntry.getRefs();
-		IQueryResult[] files= new IQueryResult[fileNums.length];
-		for (int i= 0; i < files.length; i++)
-			files[i]= getIndexedFile(fileNums[i]);
-		return files;
+		String[] paths= new String[fileNums.length];
+		for (int i= 0; i < paths.length; i++)
+			paths[i]= getIndexedFile(fileNums[i]).getPath();
+		return paths;
 	}
-	public IEntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException {
+	public EntryResult[] queryEntries(char[] pattern, int matchRule) {
 		return null;
 	}
-	public IQueryResult[] queryFilesReferringToPrefix(char[] prefix) throws IOException {
+	public EntryResult[] queryEntriesPrefixedBy(char[] prefix) {
+		return null;
+	}
+	public String[] queryFilesReferringToPrefix(char[] prefix) {
 			return null;
 	}
 	/**
 	 * @see IndexInput#queryInDocumentNames(String)
 	 */
-	public IQueryResult[] queryInDocumentNames(String word) throws IOException {
+	public String[] queryInDocumentNames(String word) {
 		setFirstFile();
 		ArrayList matches= new ArrayList();
 		while (hasMoreFiles()) {
@@ -152,14 +153,14 @@
 				matches.add(file.getPath());
 			moveToNextFile();
 		}
-		IQueryResult[] match= new IQueryResult[matches.size()];
+		String[] match= new String[matches.size()];
 		matches.toArray(match);
 		return match;
 	}
 	/**
 	 * @see IndexInput#setFirstFile()
 	 */
-	protected void setFirstFile() throws IOException {
+	protected void setFirstFile() {
 		filePosition= 1;
 		if (sortedFiles.length > 0) {
 			currentFile= sortedFiles[0];
@@ -168,7 +169,7 @@
 	/**
 	 * @see IndexInput#setFirstWord()
 	 */
-	protected void setFirstWord() throws IOException {
+	protected void setFirstWord() {
 		wordPosition= 1;
 		if (sortedWordEntries.length > 0)
 			currentWordEntry= sortedWordEntries[0];
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Util.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Util.java
deleted file mode 100644
index 8626007..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/Util.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.index.impl;
-
-import java.io.DataInput;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UTFDataFormatException;
-
-public class Util {
-
-	private Util() {
-	}
-	/**
-	 * Compares two strings lexicographically. 
-	 * The comparison is based on the Unicode value of each character in
-	 * the strings. 
-	 *
-	 * @return  the value <code>0</code> if the str1 is equal to str2;
-	 *          a value less than <code>0</code> if str1
-	 *          is lexicographically less than str2; 
-	 *          and a value greater than <code>0</code> if str1 is
-	 *          lexicographically greater than str2.
-	 */
-	public static int compare(char[] str1, char[] str2) {
-		int len1= str1.length;
-		int len2= str2.length;
-		int n= Math.min(len1, len2);
-		int i= 0;
-		while (n-- != 0) {
-			char c1= str1[i];
-			char c2= str2[i++];
-			if (c1 != c2) {
-				return c1 - c2;
-			}
-		}
-		return len1 - len2;
-	}
-
-	/**
-	 * Returns the length of the common prefix between s1 and s2.
-	 */
-	public static int prefixLength(char[] s1, char[] s2) {
-		int len= 0;
-		int max= Math.min(s1.length, s2.length);
-		for (int i= 0; i < max && s1[i] == s2[i]; ++i)
-			++len;
-		return len;
-	}
-	/**
-	 * Returns the length of the common prefix between s1 and s2.
-	 */
-	public static int prefixLength(String s1, String s2) {
-		int len= 0;
-		int max= Math.min(s1.length(), s2.length());
-		for (int i= 0; i < max && s1.charAt(i) == s2.charAt(i); ++i)
-			++len;
-		return len;
-	}
-	private static void quickSort(char[][] list, int left, int right) {
-		int original_left= left;
-		int original_right= right;
-		char[] mid= list[(left + right) / 2];
-		do {
-			while (compare(list[left], mid) < 0) {
-				left++;
-			}
-			while (compare(mid, list[right]) < 0) {
-				right--;
-			}
-			if (left <= right) {
-				char[] tmp= list[left];
-				list[left]= list[right];
-				list[right]= tmp;
-				left++;
-				right--;
-			}
-		} while (left <= right);
-		if (original_left < right) {
-			quickSort(list, original_left, right);
-		}
-		if (left < original_right) {
-			quickSort(list, left, original_right);
-		}
-	}
-	private static void quickSort(int[] list, int left, int right) {
-		int original_left= left;
-		int original_right= right;
-		int mid= list[(left + right) / 2];
-		do {
-			while (list[left] < mid) {
-				left++;
-			}
-			while (mid < list[right]) {
-				right--;
-			}
-			if (left <= right) {
-				int tmp= list[left];
-				list[left]= list[right];
-				list[right]= tmp;
-				left++;
-				right--;
-			}
-		} while (left <= right);
-		if (original_left < right) {
-			quickSort(list, original_left, right);
-		}
-		if (left < original_right) {
-			quickSort(list, left, original_right);
-		}
-	}
-	private static void quickSort(String[] list, int left, int right) {
-		int original_left= left;
-		int original_right= right;
-		String mid= list[(left + right) / 2];
-		do {
-			while (list[left].compareTo(mid) < 0) {
-				left++;
-			}
-			while (mid.compareTo(list[right]) < 0) {
-				right--;
-			}
-			if (left <= right) {
-				String tmp= list[left];
-				list[left]= list[right];
-				list[right]= tmp;
-				left++;
-				right--;
-			}
-		} while (left <= right);
-		if (original_left < right) {
-			quickSort(list, original_left, right);
-		}
-		if (left < original_right) {
-			quickSort(list, left, original_right);
-		}
-	}
-	private static void quickSort(IndexedFile[] list, int left, int right) {
-		int original_left= left;
-		int original_right= right;
-		String mid= list[(left + right) / 2].path;
-		do {
-			while (list[left].path.compareTo(mid) < 0) {
-				left++;
-			}
-			while (mid.compareTo(list[right].path) < 0) {
-				right--;
-			}
-			if (left <= right) {
-				IndexedFile tmp= list[left];
-				list[left]= list[right];
-				list[right]= tmp;
-				left++;
-				right--;
-			}
-		} while (left <= right);
-		if (original_left < right) {
-			quickSort(list, original_left, right);
-		}
-		if (left < original_right) {
-			quickSort(list, left, original_right);
-		}
-	}
-	private static void quickSort(WordEntry[] list, int left, int right) {
-		int original_left= left;
-		int original_right= right;
-		char[] mid= list[(left + right) / 2].fWord;
-		do {
-			while (compare(list[left].fWord, mid) < 0) {
-				left++;
-			}
-			while (compare(mid, list[right].fWord) < 0) {
-				right--;
-			}
-			if (left <= right) {
-				WordEntry tmp= list[left];
-				list[left]= list[right];
-				list[right]= tmp;
-				left++;
-				right--;
-			}
-		} while (left <= right);
-		if (original_left < right) {
-			quickSort(list, original_left, right);
-		}
-		if (left < original_right) {
-			quickSort(list, left, original_right);
-		}
-	}
-	/**
-	 * Reads in a string from the specified data input stream. The 
-	 * string has been encoded using a modified UTF-8 format. 
-	 * <p>
-	 * The first two bytes are read as if by 
-	 * <code>readUnsignedShort</code>. This value gives the number of 
-	 * following bytes that are in the encoded string, not
-	 * the length of the resulting string. The following bytes are then 
-	 * interpreted as bytes encoding characters in the UTF-8 format 
-	 * and are converted into characters. 
-	 * <p>
-	 * This method blocks until all the bytes are read, the end of the 
-	 * stream is detected, or an exception is thrown. 
-	 *
-	 * @param      in   a data input stream.
-	 * @return     a Unicode string.
-	 * @exception  EOFException            if the input stream reaches the end
-	 *               before all the bytes.
-	 * @exception  IOException             if an I/O error occurs.
-	 * @exception  UTFDataFormatException  if the bytes do not represent a
-	 *               valid UTF-8 encoding of a Unicode string.
-	 * @see        java.io.DataInputStream#readUnsignedShort()
-	 */
-	public final static char[] readUTF(DataInput in) throws IOException {
-		int utflen= in.readUnsignedShort();
-		char str[]= new char[utflen];
-		int count= 0;
-		int strlen= 0;
-		while (count < utflen) {
-			int c= in.readUnsignedByte();
-			int char2, char3;
-			switch (c >> 4) {
-				case 0 :
-				case 1 :
-				case 2 :
-				case 3 :
-				case 4 :
-				case 5 :
-				case 6 :
-				case 7 :
-					// 0xxxxxxx
-					count++;
-					str[strlen++]= (char) c;
-					break;
-				case 12 :
-				case 13 :
-					// 110x xxxx   10xx xxxx
-					count += 2;
-					if (count > utflen)
-						throw new UTFDataFormatException();
-					char2= in.readUnsignedByte();
-					if ((char2 & 0xC0) != 0x80)
-						throw new UTFDataFormatException();
-					str[strlen++]= (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
-					break;
-				case 14 :
-					// 1110 xxxx  10xx xxxx  10xx xxxx
-					count += 3;
-					if (count > utflen)
-						throw new UTFDataFormatException();
-					char2= in.readUnsignedByte();
-					char3= in.readUnsignedByte();
-					if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
-						throw new UTFDataFormatException();
-					str[strlen++]= (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
-					break;
-				default :
-					// 10xx xxxx,  1111 xxxx
-					throw new UTFDataFormatException();
-			}
-		}
-		if (strlen < utflen) {
-			System.arraycopy(str, 0, str= new char[strlen], 0, strlen);
-		}
-		return str;
-	}
-	public static void sort(char[][] list) {
-		if (list.length > 1)
-			quickSort(list, 0, list.length - 1);
-	}
-	public static void sort(int[] list) {
-		if (list.length > 1)
-			quickSort(list, 0, list.length - 1);
-	}
-	public static void sort(String[] list) {
-		if (list.length > 1)
-			quickSort(list, 0, list.length - 1);
-	}
-	public static void sort(IndexedFile[] list) {
-		if (list.length > 1)
-			quickSort(list, 0, list.length - 1);
-	}
-	public static void sort(WordEntry[] list) {
-		if (list.length > 1)
-			quickSort(list, 0, list.length - 1);
-	}
-	/**
-	 * Writes a string to the given output stream using UTF-8 
-	 * encoding in a machine-independent manner. 
-	 * <p>
-	 * First, two bytes are written to the output stream as if by the 
-	 * <code>writeShort</code> method giving the number of bytes to 
-	 * follow. This value is the number of bytes actually written out, 
-	 * not the length of the string. Following the length, each character 
-	 * of the string is output, in sequence, using the UTF-8 encoding 
-	 * for the character. 
-	 *
-	 * @param      str   a string to be written.
-	 * @exception  IOException  if an I/O error occurs.
-	 * @since      JDK1.0
-	 */
-	public static void writeUTF(OutputStream out, char[] str) throws IOException {
-		int strlen= str.length;
-		int utflen= 0;
-		for (int i= 0; i < strlen; i++) {
-			int c= str[i];
-			if ((c >= 0x0001) && (c <= 0x007F)) {
-				utflen++;
-			} else if (c > 0x07FF) {
-				utflen += 3;
-			} else {
-				utflen += 2;
-			}
-		}
-		if (utflen > 65535)
-			throw new UTFDataFormatException();
-		out.write((utflen >>> 8) & 0xFF);
-		out.write((utflen >>> 0) & 0xFF);
-		for (int i= 0; i < strlen; i++) {
-			int c= str[i];
-			if ((c >= 0x0001) && (c <= 0x007F)) {
-				out.write(c);
-			} else if (c > 0x07FF) {
-				out.write(0xE0 | ((c >> 12) & 0x0F));
-				out.write(0x80 | ((c >> 6) & 0x3F));
-				out.write(0x80 | ((c >> 0) & 0x3F));
-			} else {
-				out.write(0xC0 | ((c >> 6) & 0x1F));
-				out.write(0x80 | ((c >> 0) & 0x3F));
-			}
-		}
-	}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/WordEntry.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/WordEntry.java
index 4626a36..7c1e930 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/WordEntry.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/WordEntry.java
@@ -11,9 +11,10 @@
 package org.eclipse.jdt.internal.core.index.impl;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public class WordEntry {
-	protected char[] fWord;
+	public char[] fWord;
 	protected int fNumRefs;
 	protected int[] fRefs;
 	public WordEntry() {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/WordEntryHashedArray.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/WordEntryHashedArray.java
index 7d5887a..c5ab3aa 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/WordEntryHashedArray.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/impl/WordEntryHashedArray.java
@@ -44,10 +44,14 @@
 
 public WordEntry[] asArray() {
 	WordEntry[] array = new WordEntry[elementSize];
-	for (int i = 0, j = 0, length = elements.length; i < length; i++) {
+	int count = 0;
+	for (int i = 0, length = elements.length; i < length; i++) {
 		WordEntry current = elements[i];
-		if (current != null) array[j++] = current;
+		if (current != null)
+			array[count++] = current;
 	}
+	if (count < array.length) // add a little protection because of 40950
+		System.arraycopy(array, 0, array = new WordEntry[count], 0, count);
 	return array;
 }
 
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/AbstractSearchScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/AbstractSearchScope.java
index 3125844..32eb69b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/AbstractSearchScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/AbstractSearchScope.java
@@ -42,6 +42,7 @@
  * @deprecated
  */
 public void setIncludesBinaries(boolean includesBinaries) {
+	// implements interface method
 }
 
 /**
@@ -49,6 +50,7 @@
  * @deprecated
  */
 public void setIncludesClasspaths(boolean includesClasspaths) {
+	// implements interface method
 }
 
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/HierarchyScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/HierarchyScope.java
index c8b0e22..7679f30 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/HierarchyScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/HierarchyScope.java
@@ -18,6 +18,7 @@
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
 import org.eclipse.jdt.internal.core.JavaElement;
@@ -27,10 +28,11 @@
 /**
  * Scope limited to the subtype and supertype hierarchy of a given type.
  */
-public class HierarchyScope extends AbstractSearchScope {
+public class HierarchyScope extends AbstractSearchScope implements SuffixConstants {
 
 	public IType focusType;
 	private String focusPath;
+	private WorkingCopyOwner owner;
 	
 	private ITypeHierarchy hierarchy;
 	private IType[] types;
@@ -60,8 +62,9 @@
 	/* (non-Javadoc)
 	 * Creates a new hiearchy scope for the given type.
 	 */
-	public HierarchyScope(IType type) throws JavaModelException {
+	public HierarchyScope(IType type, WorkingCopyOwner owner) throws JavaModelException {
 		this.focusType = type;
+		this.owner = owner;
 		
 		this.enclosingProjectsAndJars = this.computeProjectsAndJars(type);
 
@@ -84,7 +87,7 @@
 				zipFileName
 					+ JAR_FILE_ENTRY_SEPARATOR
 					+ type.getFullyQualifiedName().replace('.', '/')
-					+ ".class";//$NON-NLS-1$
+					+ SUFFIX_STRING_class;
 		} else {
 			this.focusPath = type.getPath().toString();
 		}
@@ -94,7 +97,7 @@
 		//disabled for now as this could be expensive
 		//JavaModelManager.getJavaModelManager().rememberScope(this);
 	}
-	private void buildResourceVector() throws JavaModelException {
+	private void buildResourceVector() {
 		HashMap resources = new HashMap();
 		HashMap paths = new HashMap();
 		this.types = this.hierarchy.getAllTypes();
@@ -127,7 +130,7 @@
 					zipFileName
 						+ JAR_FILE_ENTRY_SEPARATOR
 						+ type.getFullyQualifiedName().replace('.', '/')
-						+ ".class";//$NON-NLS-1$
+						+ SUFFIX_STRING_class;
 				
 				this.resourcePaths.add(resourcePath);
 				paths.put(jarPath, type);
@@ -298,7 +301,7 @@
 				// be flexible: look at original element (see bug 14106 Declarations in Hierarchy does not find declarations in hierarchy)
 				IType original;
 				if (!type.isBinary() 
-						&& (original = (IType)type.getCompilationUnit().getOriginal(type)) != null) {
+						&& (original = (IType)type.getPrimaryElement()) != null) {
 					return this.hierarchy.contains(original);
 				}
 			}
@@ -325,7 +328,7 @@
 		this.elementCount = 0;
 		this.needsRefresh = false;
 		if (this.hierarchy == null) {
-			this.hierarchy = this.focusType.newTypeHierarchy(null);
+			this.hierarchy = this.focusType.newTypeHierarchy(this.owner, null);
 		} else {
 			this.hierarchy.refresh(null);
 		}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IInfoConstants.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexQueryRequestor.java
similarity index 63%
rename from org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IInfoConstants.java
rename to org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexQueryRequestor.java
index 95c5510..fd2dc74 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IInfoConstants.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexQueryRequestor.java
@@ -10,10 +10,15 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search;
 
-public interface IInfoConstants {
-	/* granularity of search results */
-	int NameInfo = 1;
-	int PathInfo = 2;
-	int PositionInfo = 4;
-	int DeclarationInfo = 8;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.core.search.SearchPattern;
+
+/**
+ * TODO add spec
+ */
+public abstract class IndexQueryRequestor {
+	
+	// answer false if requesting cancel
+	public abstract boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant);
+	
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSearchAdapter.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSearchAdapter.java
index 45b0782..3c9a7d9 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSearchAdapter.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSearchAdapter.java
@@ -15,55 +15,66 @@
  * @see IIndexSearchRequestor
  */
 public void acceptClassDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) {
+	// implements interface method
 }
 /**
  * @see IIndexSearchRequestor
  */
 public void acceptConstructorDeclaration(String resourcePath, char[] typeName, int parameterCount) {
+	// implements interface method
 }
 /**
  * @see IIndexSearchRequestor
  */
 public void acceptConstructorReference(String resourcePath, char[] typeName, int parameterCount) {
+	// implements interface method
 }
 /**
  * @see IIndexSearchRequestor
  */
 public void acceptFieldDeclaration(String resourcePath, char[] fieldName) {
+	// implements interface method
 }
 /**
  * @see IIndexSearchRequestor
  */
 public void acceptFieldReference(String resourcePath, char[] fieldName) {
+	// implements interface method
 }
 /**
  * @see IIndexSearchRequestor
  */
 public void acceptInterfaceDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) {
+	// implements interface method
 }
 /**
  * @see IIndexSearchRequestor
  */
 public void acceptMethodDeclaration(String resourcePath, char[] methodName, int parameterCount) {
+	// implements interface method
 }
 /**
  * @see IIndexSearchRequestor
  */
 public void acceptMethodReference(String resourcePath, char[] methodName, int parameterCount) {
+	// implements interface method
 }
 /**
  * @see IIndexSearchRequestor
  */
 public void acceptPackageReference(String resourcePath, char[] packageName) {
+	// implements interface method
 }
 /**
  * @see IIndexSearchRequestor
  */
 public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char[] enclosingTypeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers){
+	// implements interface method
 }
 /**
  * @see IIndexSearchRequestor
  */
 public void acceptTypeReference(String resourcePath, char[] typeName) {
+	// implements interface method
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSelector.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSelector.java
index b09224c..29a8aa9 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSelector.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSelector.java
@@ -21,10 +21,9 @@
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchPattern;
 import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
 import org.eclipse.jdt.internal.core.JavaProject;
-import org.eclipse.jdt.internal.core.index.IIndex;
-import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
 
 /**
  * Selects the indexes that correspond to projects in a given search scope
@@ -32,19 +31,15 @@
  */
 public class IndexSelector {
 	IJavaSearchScope searchScope;
-	IJavaElement focus;
-	IndexManager indexManager;
+	SearchPattern pattern;
 	IPath[] indexKeys; // cache of the keys for looking index up
-	boolean isPolymorphicSearch;
+	
 public IndexSelector(
-	IJavaSearchScope searchScope,
-	IJavaElement focus,
-	boolean isPolymorphicSearch,
-	IndexManager indexManager) {
+		IJavaSearchScope searchScope,
+		SearchPattern pattern) {
+	
 	this.searchScope = searchScope;
-	this.focus = focus;
-	this.indexManager = indexManager;
-	this.isPolymorphicSearch = isPolymorphicSearch;
+	this.pattern = pattern;
 }
 /**
  * Returns whether elements of the given project or jar can see the given focus (an IJavaProject or
@@ -130,7 +125,8 @@
 	ArrayList requiredIndexKeys = new ArrayList();
 	IPath[] projectsAndJars = this.searchScope.enclosingProjectsAndJars();
 	IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
-	IJavaElement projectOrJarFocus = this.focus == null ? null : getProjectOrJar(this.focus);
+	IJavaElement projectOrJarFocus = this.pattern == null || this.pattern.focus == null ? null : getProjectOrJar(this.pattern.focus);
+	boolean isPolymorphicSearch = this.pattern == null ? false : this.pattern.isPolymorphicSearch();
 	for (int i = 0; i < projectsAndJars.length; i++) {
 		IPath location;
 		IPath path = projectsAndJars[i];
@@ -141,7 +137,7 @@
 			&& !new java.io.File(path.toOSString()).exists()) { // and external jar file does not exist
 				continue;
 		}
-		if (projectOrJarFocus == null || canSeeFocus(projectOrJarFocus, this.isPolymorphicSearch, path)) {
+		if (projectOrJarFocus == null || canSeeFocus(projectOrJarFocus, isPolymorphicSearch, path)) {
 			if (requiredIndexKeys.indexOf(path) == -1) {
 				requiredIndexKeys.add(path);
 			}
@@ -150,24 +146,13 @@
 	this.indexKeys = new IPath[requiredIndexKeys.size()];
 	requiredIndexKeys.toArray(this.indexKeys);
 }
-public IIndex[] getIndexes() {
+public IPath[] getIndexKeys() {
 	if (this.indexKeys == null) {
 		this.initializeIndexKeys(); 
 	}
-	// acquire the in-memory indexes on the fly
-	int length = this.indexKeys.length;
-	IIndex[] indexes = new IIndex[length];
-	int count = 0;
-	for (int i = 0; i < length; i++){
-		// may trigger some index recreation work
-		IIndex index = indexManager.getIndex(indexKeys[i], true /*reuse index file*/, false /*do not create if none*/);
-		if (index != null) indexes[count++] = index; // only consider indexes which are ready yet
-	}
-	if (count != length) {
-		System.arraycopy(indexes, 0, indexes=new IIndex[count], 0, count);
-	}
-	return indexes;
+	return this.indexKeys;
 }
+
 /**
  * Returns the java project that corresponds to the given path.
  * Returns null if the path doesn't correspond to a project.
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java
new file mode 100644
index 0000000..6d139d4
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchDocument.java
@@ -0,0 +1,68 @@
+package org.eclipse.jdt.internal.core.search;
+
+import java.io.IOException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.search.*;
+
+public class JavaSearchDocument extends SearchDocument {
+	
+	private IFile file;
+	protected byte[] byteContents;
+	protected char[] charContents;
+	
+	public JavaSearchDocument(String documentPath, SearchParticipant participant) {
+		super(documentPath, participant);
+	}
+	public JavaSearchDocument(IFile file, SearchParticipant participant) {
+		super(file.getFullPath().toString(), participant);
+		this.file = file;
+	}
+	public JavaSearchDocument(java.util.zip.ZipEntry zipEntry, IPath zipFilePath, byte[] contents, SearchParticipant participant) {
+		super(zipFilePath + IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR + zipEntry.getName(), participant);
+		this.byteContents = contents;
+	}
+
+	public byte[] getByteContents() {
+		if (this.byteContents != null) return this.byteContents;
+		try {
+			return org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(getLocation().toFile());
+		} catch (IOException e) {
+			/// TODO (jerome) log in VERBOSE mode e.printStackTrace();
+			return null;
+		}
+	}
+	public char[] getCharContents() {
+		if (this.charContents != null) return this.charContents;
+		try {
+			return org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(getLocation().toFile(), getEncoding());
+		} catch (IOException e) {
+			/// TODO (jerome) log in VERBOSE mode e.printStackTrace();
+			return null;
+		}
+	}
+	public String getEncoding() {
+		IFile resource = getFile();
+		if (resource != null)
+			return JavaCore.create(resource.getProject()).getOption(JavaCore.CORE_ENCODING, true);
+		return JavaCore.getOption(JavaCore.CORE_ENCODING);
+	}
+	private IFile getFile() {
+		if (this.file == null)
+			this.file = (IFile) ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(this.documentPath));
+		return this.file;
+	}
+	private IPath getLocation() {
+		IFile resource = getFile();
+		if (resource != null)
+			return resource.getLocation();
+		return new Path(this.documentPath); // external file
+	}
+	public String toString() {
+		return "SearchDocument for " + this.documentPath; //$NON-NLS-1$
+	}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java
new file mode 100644
index 0000000..f424482
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchParticipant.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jdt.core.search.SearchRequestor;
+import org.eclipse.jdt.internal.core.CompilationUnit;
+import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
+import org.eclipse.jdt.internal.core.search.indexing.BinaryIndexer;
+import org.eclipse.jdt.internal.core.search.indexing.SourceIndexer;
+import org.eclipse.jdt.internal.core.search.matching.MatchLocator;
+import org.eclipse.jdt.core.search.SearchParticipant;
+
+/**
+ * A search participant describes a particular extension to a generic search mechanism, allowing thus to 
+ * perform combined search actions which will involve all required participants
+ * 
+ * A search scope defines which participants are involved. 
+ * 
+ * A search participant is responsible for holding index files, and selecting the appropriate ones to feed to
+ * index queries. It also can map a document path to an actual document (note that documents could live outside
+ * the workspace or no exist yet, and thus aren't just resources).
+ */
+public class JavaSearchParticipant extends SearchParticipant {
+	
+	public class WorkingCopyDocument extends JavaSearchDocument {
+		public ICompilationUnit workingCopy;
+		WorkingCopyDocument(ICompilationUnit workingCopy) {
+			super(workingCopy.getPath().toString(), JavaSearchParticipant.this);
+			this.charContents = ((CompilationUnit)workingCopy).getContents();
+			this.workingCopy = workingCopy;
+		}
+		public String toString() {
+			return "WorkingCopyDocument for " + getPath(); //$NON-NLS-1$
+		}
+	}
+	
+	IndexSelector indexSelector;
+	
+	/*
+	 * A table from path (String) to working copy document (WorkingCopopyDocument)
+	 */
+	ICompilationUnit[] workingCopies;
+	
+	public JavaSearchParticipant(ICompilationUnit[] workingCopies) {
+		this.workingCopies = workingCopies;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.search.SearchParticipant#beginSearching()
+	 */
+	public void beginSearching() {
+		this.indexSelector = null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.search.SearchParticipant#doneSearching()
+	 */
+	public void doneSearching() {
+		this.indexSelector = null;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.search.SearchParticipant#getName()
+	 */
+	public String getDescription() {
+		return "Java"; //$NON-NLS-1$
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.search.SearchParticipant#getDocument(String)
+	 */
+	public SearchDocument getDocument(String documentPath) {
+		return new JavaSearchDocument(documentPath, this);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.search.SearchParticipant#indexDocument(SearchDocument)
+	 */
+	public void indexDocument(SearchDocument document, String indexPath) {
+		String documentPath = document.getPath();
+		if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(documentPath)) {
+			new SourceIndexer(document, indexPath).indexDocument();
+		} else if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(documentPath)) {
+			new BinaryIndexer(document, indexPath).indexDocument();
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see SearchParticipant#locateMatches(SearchDocument[], SearchPattern, IJavaSearchScope, SearchRequestor, IProgressMonitor)
+	 */
+	public void locateMatches(SearchDocument[] indexMatches, SearchPattern pattern,
+			IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException {
+		
+		MatchLocator matchLocator = 
+			new MatchLocator(
+				pattern, 
+				requestor, 
+				scope,
+				this.workingCopies,
+				monitor == null ? null : new SubProgressMonitor(monitor, 95)
+		);
+
+		// working copies take precedence over corresponding compilation units
+		HashMap workingCopyDocuments = workingCopiesThatCanSeeFocus(pattern.focus, pattern.isPolymorphicSearch());
+		SearchDocument[] matches = null;
+		int length = indexMatches.length;
+		for (int i = 0; i < length; i++) {
+			SearchDocument searchDocument = indexMatches[i];
+			if (searchDocument.getParticipant() == this) {
+				SearchDocument workingCopyDocument = (SearchDocument) workingCopyDocuments.remove(searchDocument.getPath());
+				if (workingCopyDocument != null) {
+					if (matches == null) {
+						System.arraycopy(indexMatches, 0, matches = new SearchDocument[length], 0, length);
+					}
+					matches[i] = workingCopyDocument;
+				}
+			}
+		}
+		if (matches == null) { // no working copy
+			matches = indexMatches;
+		}
+		int remainingWorkingCopiesSize = workingCopyDocuments.size();
+		if (remainingWorkingCopiesSize != 0) {
+			System.arraycopy(matches, 0, matches = new SearchDocument[length+remainingWorkingCopiesSize], 0, length);
+			Iterator iterator = workingCopyDocuments.values().iterator();
+			int index = length;
+			while (iterator.hasNext()) {
+				matches[index++] = (SearchDocument) iterator.next();
+			}
+		}
+
+		/* eliminating false matches and locating them */
+		if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+		matchLocator.locateMatches(matches);
+		
+
+		if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+		
+		matchLocator.locatePackageDeclarations(this);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.core.search.SearchParticipant#selectIndexes(org.eclipse.jdt.core.search.SearchQuery, org.eclipse.jdt.core.search.SearchContext)
+	 */
+	public IPath[] selectIndexes(
+		SearchPattern pattern,
+		IJavaSearchScope scope) {
+		
+		if (this.indexSelector == null) {
+			this.indexSelector = new IndexSelector(scope, pattern);
+		}
+		return this.indexSelector.getIndexKeys();
+	}
+	
+	/*
+	 * Returns the working copies that can see the given focus.
+	 */
+	private HashMap workingCopiesThatCanSeeFocus(IJavaElement focus, boolean isPolymorphicSearch) {
+		if (this.workingCopies == null) return new HashMap();
+		if (focus != null) {
+			while (!(focus instanceof IJavaProject) && !(focus instanceof JarPackageFragmentRoot)) {
+				focus = focus.getParent();
+			}
+		}
+		HashMap result = new HashMap();
+		for (int i=0, length = this.workingCopies.length; i<length; i++) {
+			ICompilationUnit workingCopy = this.workingCopies[i];
+			IPath projectOrJar = IndexSelector.getProjectOrJar(workingCopy).getPath();
+			if (focus == null || IndexSelector.canSeeFocus(focus, isPolymorphicSearch, projectOrJar)) {
+				result.put(
+					workingCopy.getPath().toString(),
+					new WorkingCopyDocument(workingCopy)
+				);
+			}
+		}
+		return result;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java
index b08d41c..9db43aa 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaWorkspaceScope.java
@@ -77,6 +77,7 @@
 		for (int i = 0, length = projects.length; i < length; i++)
 			this.add(projects[i], false, new HashSet(2));
 	} catch (JavaModelException ignored) {
+		// ignore
 	}
 	this.needsInitialize = false;
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PathCollector.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PathCollector.java
index 4e799f1..6ac350e 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PathCollector.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PathCollector.java
@@ -13,119 +13,34 @@
 import java.util.HashSet;
 import java.util.Iterator;
 
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.core.search.SearchPattern;
 
 /**
  * Collects the resource paths reported by a client to this search requestor.
  */
-public class PathCollector implements IIndexSearchRequestor {
+public class PathCollector extends IndexQueryRequestor {
 	
 	/* a set of resource paths */
 	public HashSet paths = new HashSet(5);
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptClassDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) {
-	this.paths.add( resourcePath);
-}
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptConstructorDeclaration(String resourcePath, char[] typeName, int parameterCount) {
-		
-	this.paths.add(resourcePath);
-}
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptConstructorReference(String resourcePath, char[] typeName, int parameterCount) {
-		
-	this.paths.add(resourcePath);
-}
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptFieldDeclaration(String resourcePath, char[] fieldName) {
-	this.paths.add(resourcePath);
-}
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptFieldReference(String resourcePath, char[] fieldName) {
-		
-	this.paths.add(resourcePath);
-}
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptInterfaceDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) {
-		
-	this.paths.add(resourcePath);
-}
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptMethodDeclaration(String resourcePath, char[] methodName, int parameterCount) {
-		
-	this.paths.add(resourcePath);
-}
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptMethodReference(String resourcePath, char[] methodName, int parameterCount) {
-		
-	this.paths.add(resourcePath);
-}
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptPackageReference(String resourcePath, char[] packageName) {
-		
-	this.paths.add(resourcePath);
-}
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char[] enclosingTypeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers) {
-	this.paths.add(resourcePath);
-}
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers) {
-	this.paths.add(resourcePath);
-}
-/**
- * @see IIndexSearchRequestor
- */
-public void acceptTypeReference(String resourcePath, char[] typeName) {
-	this.paths.add(resourcePath);
-}
-/**
- * Returns the files that correspond to the paths that have been collected.
- */
-public IFile[] getFiles(IWorkspace workspace) {
-	IFile[] result = new IFile[this.paths.size()];
-	int i = 0;
-	for (Iterator iter = this.paths.iterator(); iter.hasNext();) {
-		String resourcePath = (String)iter.next();
-		IPath path = new Path(resourcePath);
-		result[i++] = workspace.getRoot().getFile(path);
+	
+	/* (non-Javadoc)
+	 * @seeIndexQueryRequestor#acceptIndexMatch(IndexRecord, SearchParticipant, SearchPattern)
+	 */
+	public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant) {
+		paths.add(documentPath);
+		return true;
 	}
-	return result;
-}
-/**
- * Returns the paths that have been collected.
- */
-public String[] getPaths() {
-	String[] result = new String[this.paths.size()];
-	int i = 0;
-	for (Iterator iter = this.paths.iterator(); iter.hasNext();) {
-		result[i++] = (String)iter.next();
+
+	/**
+	 * Returns the paths that have been collected.
+	 */
+	public String[] getPaths() {
+		String[] result = new String[this.paths.size()];
+		int i = 0;
+		for (Iterator iter = this.paths.iterator(); iter.hasNext();) {
+			result[i++] = (String)iter.next();
+		}
+		return result;
 	}
-	return result;
-}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java
index 696964d..daf5c84 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/PatternSearchJob.java
@@ -12,14 +12,16 @@
 
 import java.io.IOException;
 
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.index.IIndex;
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
 import org.eclipse.jdt.internal.core.search.indexing.ReadWriteMonitor;
-import org.eclipse.jdt.internal.core.search.matching.SearchPattern;
 import org.eclipse.jdt.internal.core.search.processing.IJob;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
 
@@ -27,51 +29,32 @@
 
 	protected SearchPattern pattern;
 	protected IJavaSearchScope scope;
-	protected IJavaElement focus;
-	protected IIndexSearchRequestor requestor;
-	protected IndexManager indexManager;
-	protected int detailLevel;
-	protected IndexSelector indexSelector;
-	protected boolean isPolymorphicSearch;
+	protected SearchParticipant participant;
+	protected IndexQueryRequestor requestor;
+	protected boolean areIndexesReady;
 	protected long executionTime = 0;
 	
 	public PatternSearchJob(
 		SearchPattern pattern,
+		SearchParticipant participant,
 		IJavaSearchScope scope,
-		int detailLevel,
-		IIndexSearchRequestor requestor,
-		IndexManager indexManager) {
-
-		this(
-			pattern,
-			scope,
-			null,
-			false,
-			detailLevel,
-			requestor,
-			indexManager);
-	}
-	public PatternSearchJob(
-		SearchPattern pattern,
-		IJavaSearchScope scope,
-		IJavaElement focus,
-		boolean isPolymorphicSearch,
-		int detailLevel,
-		IIndexSearchRequestor requestor,
-		IndexManager indexManager) {
+		IndexQueryRequestor requestor) {
 
 		this.pattern = pattern;
+		this.participant = participant;
 		this.scope = scope;
-		this.focus = focus;
-		this.isPolymorphicSearch = isPolymorphicSearch;
-		this.detailLevel = detailLevel;
 		this.requestor = requestor;
-		this.indexManager = indexManager;
 	}
 	public boolean belongsTo(String jobFamily) {
 		return true;
 	}
 	public void cancel() {
+		// search job is cancelled through progress 
+	}
+	public void ensureReadyToRun() {
+		if (!this.areIndexesReady) {
+			getIndexes(null/*progress*/); // may trigger some index recreation
+		}
 	}
 	public boolean execute(IProgressMonitor progressMonitor) {
 
@@ -79,18 +62,14 @@
 			throw new OperationCanceledException();
 		boolean isComplete = COMPLETE;
 		executionTime = 0;
-		if (this.indexSelector == null) {
-			this.indexSelector =
-				new IndexSelector(this.scope, this.focus, this.isPolymorphicSearch, this.indexManager);
-		}
-		IIndex[] searchIndexes = this.indexSelector.getIndexes();
+		IIndex[] indexes = getIndexes(progressMonitor);
 		try {
-			int max = searchIndexes.length;
+			int max = indexes.length;
 			if (progressMonitor != null) {
 				progressMonitor.beginTask("", max); //$NON-NLS-1$
 			}
 			for (int i = 0; i < max; i++) {
-				isComplete &= search(searchIndexes[i], progressMonitor);
+				isComplete &= search(indexes[i], progressMonitor);
 				if (progressMonitor != null) {
 					if (progressMonitor.isCanceled()) {
 						throw new OperationCanceledException();
@@ -109,25 +88,37 @@
 			}
 		}
 	}
-	public boolean isReadyToRun() {
-		if (this.indexSelector == null) { // only check once. As long as this job is used, it will keep the same index picture
-			this.indexSelector = new IndexSelector(this.scope, this.focus, this.isPolymorphicSearch, this.indexManager);
-			this.indexSelector.getIndexes(); // will only cache answer if all indexes were available originally
+	public IIndex[] getIndexes(IProgressMonitor progressMonitor) {
+		
+		// acquire the in-memory indexes on the fly
+		IPath[] indexPathes = this.participant.selectIndexes(this.pattern, this.scope);
+		int length = indexPathes.length;
+		IIndex[] indexes = new IIndex[length];
+		int count = 0;
+		IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
+		for (int i = 0; i < length; i++){
+			if (progressMonitor != null && progressMonitor.isCanceled())
+				throw new OperationCanceledException();
+			// may trigger some index recreation work
+			IIndex index = indexManager.getIndex(indexPathes[i], true /*reuse index file*/, false /*do not create if none*/);
+			if (index != null) indexes[count++] = index; // only consider indexes which are ready yet
 		}
-		return true;
-	}
+		if (count != length) {
+			System.arraycopy(indexes, 0, indexes=new IIndex[count], 0, count);
+		}
+		this.areIndexesReady = true;
+		return indexes;
+	}	
+
 	public boolean search(IIndex index, IProgressMonitor progressMonitor) {
 
 		if (progressMonitor != null && progressMonitor.isCanceled())
 			throw new OperationCanceledException();
 
-//		IIndex inMemIndex = indexManager.peekAtIndex(new Path(((Index)index).toString.substring("Index for ".length()).replace('\\','/')));
-//		if (inMemIndex != index) {
 //			System.out.println("SANITY CHECK: search job using obsolete index: ["+index+ "] instead of: ["+inMemIndex+"]");
-//		}
-		
 		if (index == null)
 			return COMPLETE;
+		IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
 		ReadWriteMonitor monitor = indexManager.getMonitorFor(index);
 		if (monitor == null)
 			return COMPLETE; // index got deleted since acquired
@@ -139,7 +130,7 @@
 				try {
 					monitor.exitRead(); // free read lock
 					monitor.enterWrite(); // ask permission to write
-					this.indexManager.saveIndex(index);
+					indexManager.saveIndex(index);
 				} catch (IOException e) {
 					return FAILED;
 				} finally {
@@ -150,9 +141,9 @@
 			pattern.findIndexMatches(
 				index,
 				requestor,
-				detailLevel,
-				progressMonitor,
-				this.scope);
+				this.participant,
+				this.scope,
+				progressMonitor);
 			executionTime += System.currentTimeMillis() - start;
 			return COMPLETE;
 		} catch (IOException e) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java
index f02b353..58f7e14 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/SubTypeSearchJob.java
@@ -17,30 +17,31 @@
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.core.search.SearchPattern;
+import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.index.IIndex;
 import org.eclipse.jdt.internal.core.index.impl.BlocksIndexInput;
 import org.eclipse.jdt.internal.core.index.impl.IndexInput;
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
 import org.eclipse.jdt.internal.core.search.indexing.ReadWriteMonitor;
-import org.eclipse.jdt.internal.core.search.matching.SearchPattern;
 
 public class SubTypeSearchJob extends PatternSearchJob {
 
 	Map inputs = new HashMap(5);
-public SubTypeSearchJob(SearchPattern pattern, IJavaSearchScope scope, int detailLevel, IIndexSearchRequestor requestor, IndexManager indexManager) {
-	super(pattern, scope, detailLevel, requestor, indexManager);
-}
-public SubTypeSearchJob(SearchPattern pattern, IJavaSearchScope scope, IJavaElement focus, int detailLevel, IIndexSearchRequestor requestor, IndexManager indexManager) {
-	super(
-		pattern, 
-		scope, 
-		focus, 
-		false/*not a polymorphic search*/, 
-		detailLevel, 
-		requestor, 
-		indexManager);
+
+public SubTypeSearchJob(
+		SearchPattern pattern,
+		SearchParticipant participant,
+		IJavaSearchScope scope,
+		IndexQueryRequestor requestor) {
+
+		super(
+			pattern,
+			participant,
+			scope,
+			requestor);
 }
 public void closeAll(){
 
@@ -50,6 +51,7 @@
 		try {
 			input.close();
 		} catch(IOException e){
+			// ignore
 		}
 	} 
 }
@@ -61,6 +63,7 @@
 	if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
 
 	if (index == null) return COMPLETE;		
+	IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
 	ReadWriteMonitor monitor = indexManager.getMonitorFor(index);
 	if (monitor == null) return COMPLETE; // index got deleted since acquired
 	try {
@@ -71,7 +74,7 @@
 			try {
 				monitor.exitRead(); // free read lock
 				monitor.enterWrite(); // ask permission to write
-				this.indexManager.saveIndex(index);
+				indexManager.saveIndex(index);
 			} catch(IOException e){
 				return FAILED;
 			} finally {
@@ -87,7 +90,7 @@
 			inputs.put(index, input);
 			//System.out.println("Acquiring INPUT for "+index);
 		}
-		pattern.findIndexMatches(input, requestor, detailLevel, progressMonitor, this.scope);
+		pattern.findIndexMatches(input, requestor, this.participant, this.scope, progressMonitor);
 		executionTime += System.currentTimeMillis() - start;
 		return COMPLETE;
 	} catch(IOException e){
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/Util.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/Util.java
deleted file mode 100644
index b5987ed..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/Util.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search;
-
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-
-public class Util {
-	
-	private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
-	private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
-
-	/* Bundle containing messages */
-	protected static ResourceBundle bundle;
-	private final static String bundleName = "org.eclipse.jdt.internal.core.search.messages"; //$NON-NLS-1$
-	static {
-		relocalize();
-	}
-/**
- * Lookup the message with the given ID in this catalog and bind its
- * substitution locations with the given strings.
- */
-public static String bind(String id, String binding1, String binding2) {
-	return bind(id, new String[] {binding1, binding2});
-}
-/**
- * Lookup the message with the given ID in this catalog and bind its
- * substitution locations with the given string.
- */
-public static String bind(String id, String binding) {
-	return bind(id, new String[] {binding});
-}
-/**
- * Lookup the message with the given ID in this catalog and bind its
- * substitution locations with the given string values.
- */
-public static String bind(String id, String[] bindings) {
-	if (id == null)
-		return "No message available"; //$NON-NLS-1$
-	String message = null;
-	try {
-		message = bundle.getString(id);
-	} catch (MissingResourceException e) {
-		// If we got an exception looking for the message, fail gracefully by just returning
-		// the id we were looking for.  In most cases this is semi-informative so is not too bad.
-		return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
-	}
-	// for compatibility with MessageFormat which eliminates double quotes in original message
-	char[] messageWithNoDoubleQuotes =
-	CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
-	message = new String(messageWithNoDoubleQuotes);
-
-	if (bindings == null)
-		return message;
-	int length = message.length();
-	int start = -1;
-	int end = length;
-	StringBuffer output = new StringBuffer(80);
-	while (true) {
-		if ((end = message.indexOf('{', start)) > -1) {
-			output.append(message.substring(start + 1, end));
-			if ((start = message.indexOf('}', end)) > -1) {
-				int index = -1;
-				try {
-					index = Integer.parseInt(message.substring(end + 1, start));
-					output.append(bindings[index]);
-				} catch (NumberFormatException nfe) {
-					output.append(message.substring(end + 1, start + 1));
-				} catch (ArrayIndexOutOfBoundsException e) {
-					output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
-				}
-			} else {
-				output.append(message.substring(end, length));
-				break;
-			}
-		} else {
-			output.append(message.substring(start + 1, length));
-			break;
-		}
-	}
-	return output.toString();
-}
-/**
- * Lookup the message with the given ID in this catalog 
- */
-public static String bind(String id) {
-	return bind(id, (String[])null);
-}
-/**
- * Creates a NLS catalog for the given locale.
- */
-public static void relocalize() {
-	try  {		
-		bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
-	} catch(MissingResourceException e) {
-		System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
-		throw e;
-	}
-}
-}
-
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
index d44762f..7cafd2b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
@@ -10,564 +10,88 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.indexing;
 
-import java.io.IOException;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchConstants;
-import org.eclipse.jdt.internal.core.index.IDocument;
-import org.eclipse.jdt.internal.core.index.IIndexer;
-import org.eclipse.jdt.internal.core.index.IIndexerOutput;
+import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.internal.core.search.matching.*;
 
-public abstract class AbstractIndexer implements IIndexer, IIndexConstants, IJavaSearchConstants {
-	IIndexerOutput output;
+public abstract class AbstractIndexer implements IIndexConstants {
 
-public AbstractIndexer() {
-	super();
-}
-public void addClassDeclaration(int modifiers, char[] packageName,char[] name,  char[][] enclosingTypeNames, char[] superclass, char[][] superinterfaces){
-
-	this.output.addRef(encodeTypeEntry(packageName, enclosingTypeNames, name, true));
+	SearchDocument document;
+	String indexPath;
 	
-	addSuperTypeReference(modifiers, packageName, name, enclosingTypeNames, CLASS_SUFFIX, superclass, CLASS_SUFFIX);
-	if (superinterfaces != null){
-		for (int i = 0, max = superinterfaces.length; i < max; i++){
-			addSuperTypeReference(modifiers, packageName, name, enclosingTypeNames, CLASS_SUFFIX, superinterfaces[i], INTERFACE_SUFFIX);			
-		}
+	public AbstractIndexer(SearchDocument document, String indexPath) {
+		this.document = document;
+		this.indexPath = indexPath;
 	}
+	public void addClassDeclaration(int modifiers, char[] packageName,char[] name,  char[][] enclosingTypeNames, char[] superclass, char[][] superinterfaces) {
+		addIndexEntry(TYPE_DECL, TypeDeclarationPattern.createIndexKey(packageName, enclosingTypeNames, name, true));
 	
-}
-public void addConstructorDeclaration(char[] typeName, char[][] parameterTypes, char[][] exceptionTypes){
-	// Calculate the number of arguments of the constructor
-	int numberOfArguments = 0;
-	if (parameterTypes != null){
-		numberOfArguments = parameterTypes.length;
-		for (int i = 0; i < numberOfArguments; i++){
-			this.addTypeReference(parameterTypes[i]);
-		}
+		addIndexEntry(
+			SUPER_REF, 
+			SuperTypeReferencePattern.createIndexKey(
+				modifiers, packageName, name, enclosingTypeNames, CLASS_SUFFIX, superclass, CLASS_SUFFIX));
+		if (superinterfaces != null)
+			for (int i = 0, max = superinterfaces.length; i < max; i++)
+				addIndexEntry(
+					SUPER_REF,
+					SuperTypeReferencePattern.createIndexKey(
+						modifiers, packageName, name, enclosingTypeNames, CLASS_SUFFIX, superinterfaces[i], INTERFACE_SUFFIX));
 	}
-	//convert the number of arguments into a char array
-	char[] countChars;
-	if (numberOfArguments < 10) {
-		countChars = COUNTS[numberOfArguments];
-	} else {
-		countChars = String.valueOf(numberOfArguments).toCharArray();
-	}
-	//add the reference
-	this.output.addRef(concat(CONSTRUCTOR_DECL, CharOperation.lastSegment(typeName,'.'), countChars, SEPARATOR));
-
-	if (exceptionTypes != null){
-		for (int i = 0, max = exceptionTypes.length; i < max; i++){
-			this.addTypeReference(exceptionTypes[i]);
-		}
-	}
-}
-public void addConstructorReference(char[] typeName, int argCount){
-
-	char[] countChars;
-	if (argCount < 10) {
-		countChars = COUNTS[argCount];
-	} else {
-		countChars = String.valueOf(argCount).toCharArray();
-	}
-	this.output.addRef(concat(CONSTRUCTOR_REF, CharOperation.lastSegment(typeName, '.'), countChars, SEPARATOR));
+	public void addConstructorDeclaration(char[] typeName, char[][] parameterTypes, char[][] exceptionTypes) {
+		int argCount = parameterTypes == null ? 0 : parameterTypes.length;
+		addIndexEntry(CONSTRUCTOR_DECL, ConstructorPattern.createIndexKey(CharOperation.lastSegment(typeName,'.'), argCount));
 	
-}
-public void addFieldDeclaration(char[] typeName, char[] fieldName){
-	this.output.addRef(CharOperation.concat(FIELD_DECL, fieldName));
-	this.addTypeReference(typeName);
-}
-public void addFieldReference(char[] fieldName){
-	this.output.addRef(CharOperation.concat(FIELD_REF, fieldName));	
-}
-public void addInterfaceDeclaration(int modifiers, char[] packageName, char[] name, char[][] enclosingTypeNames, char[][] superinterfaces){
-
-	this.output.addRef(encodeTypeEntry(packageName, enclosingTypeNames, name, false));
+		for (int i = 0; i < argCount; i++)
+			addTypeReference(parameterTypes[i]);
+		if (exceptionTypes != null)
+			for (int i = 0, max = exceptionTypes.length; i < max; i++)
+				addTypeReference(exceptionTypes[i]);
+	}
+	public void addConstructorReference(char[] typeName, int argCount) {
+		addIndexEntry(CONSTRUCTOR_REF, ConstructorPattern.createIndexKey(CharOperation.lastSegment(typeName,'.'), argCount));
+	}
+	public void addFieldDeclaration(char[] typeName, char[] fieldName) {
+		addIndexEntry(FIELD_DECL, FieldPattern.createIndexKey(fieldName));
+		addTypeReference(typeName);
+	}
+	public void addFieldReference(char[] fieldName) {
+		addIndexEntry(FIELD_REF, FieldPattern.createIndexKey(fieldName));
+	}
+	protected void addIndexEntry(char[] category, char[] key) {
+		SearchParticipant.addIndexEntry(category, key, this.document, this.indexPath);
+	}
+	public void addInterfaceDeclaration(int modifiers, char[] packageName, char[] name, char[][] enclosingTypeNames, char[][] superinterfaces) {
+		addIndexEntry(TYPE_DECL, TypeDeclarationPattern.createIndexKey(packageName, enclosingTypeNames, name, false));
 	
-	if (superinterfaces != null){
-		for (int i = 0, max = superinterfaces.length; i < max; i++){
-			addSuperTypeReference(modifiers, packageName, name, enclosingTypeNames, INTERFACE_SUFFIX, superinterfaces[i], INTERFACE_SUFFIX);			
-		}
+		if (superinterfaces != null)
+			for (int i = 0, max = superinterfaces.length; i < max; i++)
+				addIndexEntry(
+					SUPER_REF,
+					SuperTypeReferencePattern.createIndexKey(
+						modifiers, packageName, name, enclosingTypeNames, INTERFACE_SUFFIX, superinterfaces[i], INTERFACE_SUFFIX));
 	}
-	/* if willing to connect interfaces to Object as a supertype, then uncomment the following 
-	else {
-		addSuperTypeReference(modifiers, packageName, name, INTERFACE_SUFFIX, null, CLASS_SUFFIX); // extends Object by default
-	}
-	*/
-}
-public void addMethodDeclaration(char[] methodName, char[][] parameterTypes, char[] returnType, char[][] exceptionTypes){
-	// Calculate the number of arguments of the method
-	int numberOfArguments = 0;
-	if (parameterTypes != null){
-		numberOfArguments = parameterTypes.length;
-		for (int i = 0; i < numberOfArguments; i++){
-			this.addTypeReference(parameterTypes[i]);
-		}
-	}
-	//convert the number of arguments into a char array
-	char[] countChars;
-	if (numberOfArguments < 10) {
-		countChars = COUNTS[numberOfArguments];
-	} else {
-		countChars = String.valueOf(numberOfArguments).toCharArray();
-	}
-	//add the reference
-	this.output.addRef(concat(METHOD_DECL, methodName, countChars, SEPARATOR));
-
-	if (exceptionTypes != null){
-		for (int i = 0, max = exceptionTypes.length; i < max; i++){
-			this.addTypeReference(exceptionTypes[i]);
-		}
-	}
-	if (returnType != null) this.addTypeReference(returnType);
-}
-public void addMethodReference(char[] methodName, int argCount){
-	char[] countChars;
-	if (argCount < 10) {
-		countChars = COUNTS[argCount];
-	} else {
-		countChars = String.valueOf(argCount).toCharArray();
-	}
-	this.output.addRef(concat(METHOD_REF, methodName, countChars, SEPARATOR));
+	public void addMethodDeclaration(char[] methodName, char[][] parameterTypes, char[] returnType, char[][] exceptionTypes) {
+		int argCount = parameterTypes == null ? 0 : parameterTypes.length;
+		addIndexEntry(METHOD_DECL, MethodPattern.createIndexKey(methodName, argCount));
 	
-}
-public void addNameReference(char[] name){
-	this.output.addRef(CharOperation.concat(REF, name));
-}
-private void addSuperTypeReference(int modifiers, char[] packageName, char[] typeName, char[][] enclosingTypeNames, char classOrInterface, char[] superTypeName, char superClassOrInterface){
-
-	if (superTypeName == null) superTypeName = OBJECT;
-
-	char[] enclosingTypeName = CharOperation.concatWith(enclosingTypeNames, '$');
-	char[] typeSimpleName = CharOperation.lastSegment(typeName, '.');
-	char[] superTypeSimpleName = CharOperation.lastSegment(superTypeName, '.');
-	char[] superQualification;
-	if (superTypeSimpleName == superTypeName){
-		superQualification = null;
-	} else {
-		int length = superTypeName.length - superTypeSimpleName.length - 1;
-		System.arraycopy(superTypeName, 0, superQualification = new char[length], 0, length);
+		for (int i = 0; i < argCount; i++)
+			addTypeReference(parameterTypes[i]);
+		if (exceptionTypes != null)
+			for (int i = 0, max = exceptionTypes.length; i < max; i++)
+				addTypeReference(exceptionTypes[i]);
+		if (returnType != null)
+			addTypeReference(returnType);
 	}
-	// if the supertype name contains a $, then split it into: source name and append the $ prefix to the qualification
-	//	e.g. p.A$B ---> p.A$ + B
-	char[] superTypeSourceName = CharOperation.lastSegment(superTypeSimpleName, '$');
-	if (superTypeSourceName != superTypeSimpleName){
-		int start = superQualification == null ? 0 : superQualification.length+1;
-		int prefixLength = superTypeSimpleName.length - superTypeSourceName.length;
-		char[] mangledQualification = new char[start + prefixLength];
-		if (superQualification != null){
-			System.arraycopy(superQualification, 0, mangledQualification, 0, start-1);
-			mangledQualification[start-1] = '.';
-		}
-		System.arraycopy(superTypeSimpleName, 0, mangledQualification, start, prefixLength);
-		superQualification = mangledQualification;
-		superTypeSimpleName = superTypeSourceName;
-	} 
-	this.output.addRef(concat(SUPER_REF, superTypeSimpleName, superQualification, superClassOrInterface, typeSimpleName, enclosingTypeName, packageName, classOrInterface, (char)modifiers, SEPARATOR));		
-}
-public void addTypeReference(char[] typeName){
-
-	this.output.addRef(CharOperation.concat(TYPE_REF, CharOperation.lastSegment(typeName, '.')));
-}
-/**
- * Constructor declaration entries are encoded as follow: 'constructorDecl/' TypeName '/' Arity:
- * 	e.g. &nbsp;constructorDecl/X/0&nbsp;constructorDecl/Y/1
- *
- */
- public static final char[] bestConstructorDeclarationPrefix(char[] typeName, int arity, int matchMode, boolean isCaseSensitive) {
-
-	if (!isCaseSensitive || typeName == null) return CONSTRUCTOR_DECL;
-	switch(matchMode){
-		case EXACT_MATCH :
-			if (arity >= 0){
-				char[] countChars;
-				if (arity < 10) {
-					countChars = COUNTS[arity];
-				} else {
-					countChars = String.valueOf(arity).toCharArray();
-				}
-				return concat(CONSTRUCTOR_DECL, typeName, countChars, SEPARATOR);
-			}
-		case PREFIX_MATCH :
-			return CharOperation.concat(CONSTRUCTOR_DECL, typeName);
-		case PATTERN_MATCH :
-			int starPos = CharOperation.indexOf('*', typeName);
-			switch(starPos) {
-				case -1 :
-					return CharOperation.concat(CONSTRUCTOR_DECL, typeName);
-				default : 
-					int refLength = CONSTRUCTOR_DECL.length;
-					char[] result = new char[refLength+starPos];
-					System.arraycopy(CONSTRUCTOR_DECL, 0, result, 0, refLength);
-					System.arraycopy(typeName, 0, result, refLength, starPos);
-					return result;
-				case 0 : // fall through
-			}
-		default:
-			return CONSTRUCTOR_DECL;
+	public void addMethodReference(char[] methodName, int argCount) {
+		addIndexEntry(METHOD_REF, MethodPattern.createIndexKey(methodName, argCount));
 	}
-}
-/**
- * Constructor reference entries are encoded as follow: 'constructorRef/' TypeName '/' Arity:
- * 	e.g.&nbsp;constructorRef/X/0&nbsp;constructorRef/Y/1
- *
- */
- public static final char[] bestConstructorReferencePrefix(char[] typeName, int arity, int matchMode, boolean isCaseSensitive) {
-
-	if (!isCaseSensitive || typeName == null) return CONSTRUCTOR_REF;
-	switch(matchMode){
-		case EXACT_MATCH :
-			if (arity >= 0){
-				char[] countChars;
-				if (arity < 10) {
-					countChars = COUNTS[arity];
-				} else {
-					countChars = String.valueOf(arity).toCharArray();
-				}
-				return concat(CONSTRUCTOR_REF, typeName, countChars, SEPARATOR);
-			}
-		case PREFIX_MATCH :
-			return CharOperation.concat(CONSTRUCTOR_REF, typeName);
-		case PATTERN_MATCH :
-			int starPos = CharOperation.indexOf('*', typeName);
-			switch(starPos) {
-				case -1 :
-					return CharOperation.concat(CONSTRUCTOR_REF, typeName);
-				default : 
-					int refLength = CONSTRUCTOR_REF.length;
-					char[] result = new char[refLength+starPos];
-					System.arraycopy(CONSTRUCTOR_REF, 0, result, 0, refLength);
-					System.arraycopy(typeName, 0, result, refLength, starPos);
-					return result;
-				case 0 : // fall through
-			}
-		default:
-			return CONSTRUCTOR_REF;
+	public void addNameReference(char[] name) {
+		addIndexEntry(REF, name);
 	}
-}
-/**
- * Method declaration entries are encoded as follow: 'fieldDecl/' Name
- * 	e.g.&nbsp;fieldDecl/x
- *
- */
- public static final char[] bestFieldDeclarationPrefix(char[] name, int matchMode, boolean isCaseSensitive) {
-
-	if (!isCaseSensitive || name == null) return FIELD_DECL;
-	switch(matchMode){
-		case EXACT_MATCH :
-		case PREFIX_MATCH :
-			return CharOperation.concat(FIELD_DECL, name);
-		case PATTERN_MATCH :
-			int starPos = CharOperation.indexOf('*', name);
-			switch(starPos) {
-				case -1 :
-					return CharOperation.concat(FIELD_DECL, name);
-				default : 
-					int refLength = FIELD_DECL.length;
-					char[] result = new char[refLength+starPos];
-					System.arraycopy(FIELD_DECL, 0, result, 0, refLength);
-					System.arraycopy(name, 0, result, refLength, starPos);
-					return result;
-				case 0 : // fall through
-			}
-		default:
-			return FIELD_DECL;
+	public void addTypeReference(char[] typeName) {
+		addIndexEntry(TYPE_REF, TypeReferencePattern.createIndexKey(CharOperation.lastSegment(typeName, '.')));
 	}
-}
-/**
- * Method declaration entries are encoded as follow: 'methodDecl/' Selector '/' Arity
- * 	e.g.&nbsp;methodDecl/clone/0&nbsp;methodDecl/append/1
- *
- */
- public static final char[] bestMethodDeclarationPrefix(char[] selector, int arity, int matchMode, boolean isCaseSensitive) {
-
-	if (!isCaseSensitive || selector == null) return METHOD_DECL;
-	switch(matchMode){
-		case EXACT_MATCH :
-			if (arity >= 0){
-				char[] countChars;
-				if (arity < 10) {
-					countChars = COUNTS[arity];
-				} else {
-					countChars = String.valueOf(arity).toCharArray();
-				}
-				return concat(METHOD_DECL, selector, countChars, SEPARATOR);
-			}
-		case PREFIX_MATCH :
-			return CharOperation.concat(METHOD_DECL, selector);
-		case PATTERN_MATCH :
-			int starPos = CharOperation.indexOf('*', selector);
-			switch(starPos) {
-				case -1 :
-					return CharOperation.concat(METHOD_DECL, selector);
-				default : 
-					int refLength = METHOD_DECL.length;
-					char[] result = new char[refLength+starPos];
-					System.arraycopy(METHOD_DECL, 0, result, 0, refLength);
-					System.arraycopy(selector, 0, result, refLength, starPos);
-					return result;
-				case 0 : // fall through
-			}
-		default:
-			return METHOD_DECL;
-	}
-}
-/**
- * Method reference entries are encoded as follow: 'methodRef/' Selector '/' Arity
- * 	e.g.&nbsp;methodRef/clone/0&nbsp;methodRef/append/1
- *
- */
- public static final char[] bestMethodReferencePrefix(char[] selector, int arity, int matchMode, boolean isCaseSensitive) {
-
-	if (!isCaseSensitive || selector == null) return METHOD_REF;
-	switch(matchMode){
-		case EXACT_MATCH :
-			if (arity >= 0){
-				char[] countChars;
-				if (arity < 10) {
-					countChars = COUNTS[arity];
-				} else {
-					countChars = String.valueOf(arity).toCharArray();
-				}
-				return concat(METHOD_REF, selector, countChars, SEPARATOR);
-			}
-		case PREFIX_MATCH :
-			return CharOperation.concat(METHOD_REF, selector);
-		case PATTERN_MATCH :
-			int starPos = CharOperation.indexOf('*', selector);
-			switch(starPos) {
-				case -1 :
-					return CharOperation.concat(METHOD_REF, selector);
-				default : 
-					int refLength = METHOD_REF.length;
-					char[] result = new char[refLength+starPos];
-					System.arraycopy(METHOD_REF, 0, result, 0, refLength);
-					System.arraycopy(selector, 0, result, refLength, starPos);
-					return result;
-				case 0 : // fall through
-			}
-		default:
-			return METHOD_REF;
-	}
-}
-/**
- * Type entries are encoded as follow: '<tag>/' Name 
- * 	e.g.&nbsp;ref/Object&nbsp;ref/x
- */
- public static final char[] bestReferencePrefix(char[] tag, char[] name, int matchMode, boolean isCaseSensitive) {
-
-	if (!isCaseSensitive || name == null) return tag;
-	switch(matchMode){
-		case EXACT_MATCH :
-		case PREFIX_MATCH :
-			return CharOperation.concat(tag, name);
-		case PATTERN_MATCH :
-			int starPos = CharOperation.indexOf('*', name);
-			switch(starPos) {
-				case -1 :
-					return CharOperation.concat(tag, name);
-				default : 
-					int refLength = tag.length;
-					char[] result = new char[refLength+starPos];
-					System.arraycopy(tag, 0, result, 0, refLength);
-					System.arraycopy(name, 0, result, refLength, starPos);
-					return result;
-				case 0 : // fall through
-			}
-		default:
-			return tag;
-	}
-}
-/**
- * Type entries are encoded as follow: 'typeDecl/' ('C' | 'I') '/' PackageName '/' TypeName:
- * 	e.g.&nbsp;typeDecl/C/java.lang/Object&nbsp;typeDecl/I/java.lang/Cloneable
- *
- * Current encoding is optimized for queries: all classes/interfaces
- */
- public static final char[] bestTypeDeclarationPrefix(char[] packageName, char[] typeName, char classOrInterface, int matchMode, boolean isCaseSensitive) {
-	// index is case sensitive, thus in case attempting case insensitive search, cannot consider
-	// type name.
-	if (!isCaseSensitive){
-		packageName = null;
-		typeName = null;
-	}
-	switch(classOrInterface){ 
-		default :
-			return TYPE_DECL; // cannot do better given encoding
-		case CLASS_SUFFIX :
-			if (packageName == null) return CLASS_DECL;
-			break;
-		case INTERFACE_SUFFIX :
-			if (packageName == null) return INTERFACE_DECL;
-			break;
-	}
-	switch(matchMode){
-		case EXACT_MATCH :
-		case PREFIX_MATCH :
-			break;
-		case PATTERN_MATCH :
-			if (typeName != null){
-				int starPos = CharOperation.indexOf('*', typeName);
-				switch(starPos) {
-					case -1 :
-						break;
-					case 0 :
-						typeName = null;
-						break;
-					default : 
-						typeName = CharOperation.subarray(typeName, 0, starPos);
-				}
-			}
-	}
-	int packageLength = packageName.length;
-	int typeLength = typeName == null ? 0 : typeName.length;
-	int pos;
-	char[] result = new char[TYPE_DECL_LENGTH + packageLength + typeLength + 3];
-	System.arraycopy(TYPE_DECL, 0, result, 0, pos = TYPE_DECL_LENGTH);
-	result[pos++] = classOrInterface;
-	result[pos++] = SEPARATOR;
-	System.arraycopy(packageName, 0, result, pos, packageLength);
-	pos += packageLength;
-	result[pos++] = SEPARATOR;
-	if (typeLength > 0){
-		System.arraycopy(typeName, 0, result, pos, typeName.length);
-	}
-	return result;
-}
-/**
- * Concat(first, second, third, fourth, fifth, sep) --> [first][second][sep][third][sep][fourth][sep][fifth]
- * in other words, no separator is inserted in between first and second
- */
-protected static final char[] concat(char[] firstWithSeparator, char[] second, char[] third, char[] fourth, char[] fifth, char separator) {
-	int length1= firstWithSeparator.length;
-	int length2= second == null ? 0 : second.length;
-	int length3= third == null ? 0 : third.length;
-	int length4= fourth == null ? 0 : fourth.length;
-	int length5= fifth == null ? 0 : fifth.length;
-	char[] result= new char[length1 + length2 + length3 + length4 + length5 + 3 ];
-	System.arraycopy(firstWithSeparator, 0, result, 0, length1);
-	if (second != null) System.arraycopy(second, 0, result, length1 , length2);
-	int pos = length1 + length2;
-	result[pos]= separator;
-	if (third != null) System.arraycopy(third, 0, result, pos + 1, length3);
-	pos += length3+1;
-	result[pos]= separator;
-	if (fourth != null) System.arraycopy(fourth, 0, result, pos + 1, length4);
-	pos += length4+1;
-	result[pos]= separator;
-	if (fifth != null) System.arraycopy(fifth, 0, result, pos + 1, length5);
-	return result;
-}
-/**
- * Concat(first, second, third, sep) --> [first][second][sep][third]
- * in other words, no separator is inserted in between first and second
- */
-protected static final char[] concat(char[] firstWithSeparator, char[] second, char[] third, char separator) {
-	int length1= firstWithSeparator.length;
-	int length2= second == null ? 0 : second.length;
-	int length3= third == null ? 0 : third.length;
-	char[] result= new char[length1 + length2 + length3 + 1];
-	System.arraycopy(firstWithSeparator, 0, result, 0, length1);
-	if (second != null) System.arraycopy(second, 0, result, length1 , length2);
-	result[length1 + length2]= separator;
-	if (third != null) System.arraycopy(third, 0, result, length1 + length2 + 1, length3);
-	return result;
-}
-/**
- * Concat(first, second, third, charAfterThird, fourth, fifth, sixth, charAfterSixth, last, sep) --> [first][second][sep][third][sep][charAfterThird][sep][fourth][sep][fifth][sep][sixth][sep][charAfterSixth][last]
- * in other words, no separator is inserted in between first and second
- */
-protected static final char[] concat(char[] firstWithSeparator, char[] second, char[] third, char charAfterThird, char[] fourth, char[] fifth, char[] sixth, char charAfterSixth, char last, char separator) {
-	int length1= firstWithSeparator.length;
-	int length2= second == null ? 0 : second.length;
-	int length3= third == null ? 0 : third.length;
-	int length4= fourth == null ? 0 : fourth.length;
-	int length5= fifth == null ? 0 : fifth.length;
-	int length6 = sixth == null ? 0 : sixth.length;
-	char[] result= new char[length1 + length2 + length3 + length4 + length5 + length6 + 9 ];
-	System.arraycopy(firstWithSeparator, 0, result, 0, length1);
-	if (second != null) System.arraycopy(second, 0, result, length1 , length2);
-	int pos = length1 + length2;
-	result[pos]= separator;
-	if (third != null) System.arraycopy(third, 0, result, pos + 1, length3);
-	pos += length3+1;
-	result[pos]= separator;
-	result[++pos] = charAfterThird;
-	result[++pos] = separator;
-	if (fourth != null) System.arraycopy(fourth, 0, result, pos + 1, length4);
-	pos += length4+1;
-	result[pos]= separator;
-	if (fifth != null) System.arraycopy(fifth, 0, result, pos + 1, length5);
-	pos += length5+1;
-	result[pos]= separator;
-	if (sixth != null) System.arraycopy(sixth, 0, result, pos + 1, length6);
-	pos += length6+1;
-	result[pos]= separator;
-	result[++pos] = charAfterSixth;
-	result[++pos]=last;
-	return result;
-}
-/**
- * Type entries are encoded as follow: 'typeDecl/' ('C' | 'I') '/' PackageName '/' TypeName '/' EnclosingTypeName
- * 	e.g.<ul>
- * 	<li>typeDecl/C/java.lang/Object/</li>
- *	<li>typeDecl/I/java.lang/Cloneable/</li>
- *	<li>typeDecl/C/javax.swing/LazyValue/UIDefaults</li>
- * Current encoding is optimized for queries: all classes/interfaces
- */
- protected static final char[] encodeTypeEntry(char[] packageName, char[][] enclosingTypeNames, char[] typeName, boolean isClass) {
-	int packageLength = packageName == null ? 0 : packageName.length;
-	int enclosingTypeNamesLength = 0;
-	if (enclosingTypeNames != null) {
-		for (int i = 0, length = enclosingTypeNames.length; i < length; i++){
-			enclosingTypeNamesLength += enclosingTypeNames[i].length + 1;
-		}
-	}
-	int pos;
-	char[] result = new char[TYPE_DECL_LENGTH + packageLength + typeName.length + enclosingTypeNamesLength + 4];
-	System.arraycopy(TYPE_DECL, 0, result, 0, pos = TYPE_DECL_LENGTH);
-	result[pos++] = isClass ? CLASS_SUFFIX : INTERFACE_SUFFIX;
-	result[pos++] = SEPARATOR;
-	if (packageName != null){
-		System.arraycopy(packageName, 0, result, pos, packageLength);
-		pos += packageLength;
-	}
-	result[pos++] = SEPARATOR;
-	System.arraycopy(typeName, 0, result, pos, typeName.length);
-	pos += typeName.length;
-	result[pos++] = SEPARATOR;
-	if (enclosingTypeNames != null){
-		for (int i = 0, length = enclosingTypeNames.length; i < length; i++){
-			int enclosingTypeNameLength = enclosingTypeNames[i].length;
-			System.arraycopy(enclosingTypeNames[i], 0, result, pos, enclosingTypeNameLength);
-			pos += enclosingTypeNameLength;
-			result[pos++] = SEPARATOR;
-		}
-	}
-	return result;
-}
-/**
- * Returns the file types the <code>IIndexer</code> handles.
- */
-
-public abstract String[] getFileTypes();
-/**
- * @see IIndexer#index(IDocument document, IIndexerOutput output)
- */
-public void index(IDocument document, IIndexerOutput output) throws IOException {
-	this.output = output;
-	if (shouldIndex(document)) indexFile(document);
-}
-protected abstract void indexFile(IDocument document) throws IOException;
-/**
- * @see IIndexer#shouldIndex(IDocument document)
- */
-public boolean shouldIndex(IDocument document) {
-	String type = document.getType();
-	String[] supportedTypes = this.getFileTypes();
-	for (int i = 0; i < supportedTypes.length; ++i) {
-		if (supportedTypes[i].equals(type))
-			return true;
-	}
-	return false;
-}
+	public abstract void indexDocument();
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddClassFileToIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddClassFileToIndex.java
deleted file mode 100644
index 68c0b73..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddClassFileToIndex.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.indexing;
-
-import java.io.IOException;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.jdt.internal.core.index.IIndex;
-import org.eclipse.jdt.internal.core.index.impl.IFileDocument;
-
-class AddClassFileToIndex extends AddFileToIndex {
-	byte[] contents;
-
-	public AddClassFileToIndex(IFile resource, IPath indexedContainer, IndexManager manager) {
-		super(resource, indexedContainer, manager);
-	}
-	protected boolean indexDocument(IIndex index) throws IOException {
-		if (!initializeContents()) return false;
-		index.add(new IFileDocument(resource, this.contents), new BinaryIndexer(true));
-		return true;
-	}
-	public boolean initializeContents() {
-		if (this.contents == null) {
-			try {
-				IPath location = resource.getLocation();
-				if (location != null)
-					this.contents = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(location.toFile());
-			} catch (IOException e) {
-			}
-		}
-		return this.contents != null;
-	}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddCompilationUnitToIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddCompilationUnitToIndex.java
deleted file mode 100644
index 151f257..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddCompilationUnitToIndex.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.indexing;
-
-import java.io.IOException;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.jdt.internal.core.index.IIndex;
-import org.eclipse.jdt.internal.core.index.impl.IFileDocument;
-
-class AddCompilationUnitToIndex extends AddFileToIndex {
-	char[] contents;
-
-	public AddCompilationUnitToIndex(IFile resource, IPath indexedContainer, IndexManager manager) {
-		super(resource, indexedContainer, manager);
-	}
-	protected boolean indexDocument(IIndex index) throws IOException {
-		if (!initializeContents()) return false;
-		index.add(new IFileDocument(resource, this.contents), new SourceIndexer(resource));
-		return true;
-	}
-	public boolean initializeContents() {
-		if (this.contents == null) {
-			try {
-				IPath location = resource.getLocation();
-				if (location != null)
-					this.contents = org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(location.toFile(), null);
-			} catch (IOException e) {
-			}
-		}
-		return this.contents != null;
-	}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddFileToIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddFileToIndex.java
deleted file mode 100644
index 85b3308..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddFileToIndex.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.indexing;
-
-import java.io.IOException;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.internal.core.index.IIndex;
-import org.eclipse.jdt.internal.core.search.processing.JobManager;
-
-abstract class AddFileToIndex extends IndexRequest {
-	IFile resource;
-
-	public AddFileToIndex(IFile resource, IPath indexPath, IndexManager manager) {
-		super(indexPath, manager);
-		this.resource = resource;
-	}
-	public boolean execute(IProgressMonitor progressMonitor) {
-
-		if (progressMonitor != null && progressMonitor.isCanceled()) return true;
-
-		/* ensure no concurrent write access to index */
-		IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ true /*create if none*/);
-		if (index == null) return true;
-		ReadWriteMonitor monitor = manager.getMonitorFor(index);
-		if (monitor == null) return true; // index got deleted since acquired
-
-		try {
-			monitor.enterWrite(); // ask permission to write
-			if (!indexDocument(index)) return false;
-		} catch (IOException e) {
-			if (JobManager.VERBOSE) {
-				JobManager.verbose("-> failed to index " + this.resource + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
-				e.printStackTrace();
-			}
-			return false;
-		} finally {
-			monitor.exitWrite(); // free write lock
-		}
-		return true;
-	}
-	protected abstract boolean indexDocument(IIndex index) throws IOException;
-	public String toString() {
-		return "indexing " + this.resource.getFullPath(); //$NON-NLS-1$
-	}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddFolderToIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddFolderToIndex.java
index 9038772..fa52d9b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddFolderToIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddFolderToIndex.java
@@ -18,9 +18,9 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.internal.core.Util;
 import org.eclipse.jdt.internal.core.index.IIndex;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
+import org.eclipse.jdt.internal.core.util.Util;
 
 class AddFolderToIndex extends IndexRequest {
 	IPath folderPath;
@@ -35,13 +35,13 @@
 	}
 	public boolean execute(IProgressMonitor progressMonitor) {
 
-		if (progressMonitor != null && progressMonitor.isCanceled()) return true;
+		if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
 		if (!project.isAccessible()) return true; // nothing to do
 		IResource folder = this.project.getParent().findMember(this.folderPath);
 		if (folder == null || folder.getType() == IResource.FILE) return true; // nothing to do, source folder was removed
 
 		/* ensure no concurrent write access to index */
-		IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ true /*create if none*/);
+		IIndex index = manager.getIndex(this.containerPath, true, /*reuse index file*/ true /*create if none*/);
 		if (index == null) return true;
 		ReadWriteMonitor monitor = manager.getMonitorFor(index);
 		if (monitor == null) return true; // index got deleted since acquired
@@ -49,15 +49,15 @@
 		try {
 			monitor.enterRead(); // ask permission to read
 
-			final IPath container = this.indexPath;
+			final IPath container = this.containerPath;
 			final IndexManager indexManager = this.manager;
 			final char[][] pattern = exclusionPattern;
 			folder.accept(
 				new IResourceProxyVisitor() {
-					public boolean visit(IResourceProxy proxy) throws CoreException {
+					public boolean visit(IResourceProxy proxy) /* throws CoreException */{
 						switch(proxy.getType()) {
 							case IResource.FILE :
-								if (Util.isJavaFileName(proxy.getName())) {
+								if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(proxy.getName())) {
 									IResource resource = proxy.requestResource();
 									if (pattern == null || !Util.isExcluded(resource, pattern))
 										indexManager.addSource((IFile)resource, container);
@@ -84,6 +84,6 @@
 		return true;
 	}
 	public String toString() {
-		return "adding " + this.folderPath + " to index " + this.indexPath; //$NON-NLS-1$ //$NON-NLS-2$
+		return "adding " + this.folderPath + " to index " + this.containerPath; //$NON-NLS-1$ //$NON-NLS-2$
 	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
index a0228bd..5b9701f 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/AddJarFileToIndex.java
@@ -19,11 +19,12 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.SearchParticipant;
 import org.eclipse.jdt.internal.compiler.util.Util;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.index.IIndex;
-import org.eclipse.jdt.internal.core.index.IQueryResult;
-import org.eclipse.jdt.internal.core.index.impl.JarFileEntryDocument;
+import org.eclipse.jdt.internal.core.search.JavaSearchDocument;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
 import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
 
@@ -34,56 +35,50 @@
 		super(resource.getFullPath(), manager);
 		this.resource = resource;
 	}
-	public AddJarFileToIndex(IPath indexPath, IndexManager manager) {
+	public AddJarFileToIndex(IPath jarPath, IndexManager manager) {
 		// external JAR scenario - no resource
-		super(indexPath, manager);
-	}
-	public boolean belongsTo(String projectNameOrJarPath) {
-		// used to remove pending jobs because the project was deleted... not to delete index files
-		// can be found either by project name or JAR path name
-		return super.belongsTo(projectNameOrJarPath)
-			|| projectNameOrJarPath.equals(this.indexPath.toString());
+		super(jarPath, manager);
 	}
 	public boolean equals(Object o) {
 		if (o instanceof AddJarFileToIndex) {
 			if (this.resource != null)
 				return this.resource.equals(((AddJarFileToIndex) o).resource);
-			if (this.indexPath != null)
-				return this.indexPath.equals(((AddJarFileToIndex) o).indexPath);
+			if (this.containerPath != null)
+				return this.containerPath.equals(((AddJarFileToIndex) o).containerPath);
 		}
 		return false;
 	}
 	public int hashCode() {
 		if (this.resource != null)
 			return this.resource.hashCode();
-		if (this.indexPath != null)
-			return this.indexPath.hashCode();
+		if (this.containerPath != null)
+			return this.containerPath.hashCode();
 		return -1;
 	}
 	public boolean execute(IProgressMonitor progressMonitor) {
 
-		if (progressMonitor != null && progressMonitor.isCanceled()) return true;
+		if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
 
 		try {
 			// if index is already cached, then do not perform any check
 			// MUST reset the IndexManager if a jar file is changed
-			IIndex index = (IIndex) manager.getIndex(this.indexPath, false, /*do not reuse index file*/ false /*do not create if none*/);
+			IIndex index = manager.getIndexForUpdate(this.containerPath, false, /*do not reuse index file*/ false /*do not create if none*/);
 			if (index != null) {
 				if (JobManager.VERBOSE)
-					JobManager.verbose("-> no indexing required (index already exists) for " + this.indexPath); //$NON-NLS-1$
+					JobManager.verbose("-> no indexing required (index already exists) for " + this.containerPath); //$NON-NLS-1$
 				return true;
 			}
 
-			index = manager.getIndex(this.indexPath, true, /*reuse index file*/ true /*create if none*/);
+			index = manager.getIndexForUpdate(this.containerPath, true, /*reuse index file*/ true /*create if none*/);
 			if (index == null) {
 				if (JobManager.VERBOSE)
-					JobManager.verbose("-> index could not be created for " + this.indexPath); //$NON-NLS-1$
+					JobManager.verbose("-> index could not be created for " + this.containerPath); //$NON-NLS-1$
 				return true;
 			}
 			ReadWriteMonitor monitor = manager.getMonitorFor(index);
 			if (monitor == null) {
 				if (JobManager.VERBOSE)
-					JobManager.verbose("-> index for " + this.indexPath + " just got deleted"); //$NON-NLS-1$//$NON-NLS-2$
+					JobManager.verbose("-> index for " + this.containerPath + " just got deleted"); //$NON-NLS-1$//$NON-NLS-2$
 				return true; // index got deleted since acquired
 			}
 			ZipFile zip = null;
@@ -103,18 +98,24 @@
 					// absolute path relative to the workspace
 				} else {
 					if (JavaModelManager.ZIP_ACCESS_VERBOSE)
-						System.out.println("(" + Thread.currentThread() + ") [AddJarFileToIndex.execute()] Creating ZipFile on " + this.indexPath); //$NON-NLS-1$	//$NON-NLS-2$
-					zip = new ZipFile(this.indexPath.toFile());
-					zipFilePath = (Path) this.indexPath;
+						System.out.println("(" + Thread.currentThread() + ") [AddJarFileToIndex.execute()] Creating ZipFile on " + this.containerPath); //$NON-NLS-1$	//$NON-NLS-2$
+					zip = new ZipFile(this.containerPath.toFile());
+					zipFilePath = (Path) this.containerPath;
 					// path is already canonical since coming from a library classpath entry
 				}
 
+				if (this.isCancelled) {
+					if (JobManager.VERBOSE)
+						JobManager.verbose("-> indexing of " + zip.getName() + " has been cancelled"); //$NON-NLS-1$ //$NON-NLS-2$
+					return false;
+				}
+
 				if (JobManager.VERBOSE)
 					JobManager.verbose("-> indexing " + zip.getName()); //$NON-NLS-1$
 				long initialTime = System.currentTimeMillis();
 
-				IQueryResult[] results = index.queryInDocumentNames(""); // all file names //$NON-NLS-1$
-				int max = results == null ? 0 : results.length;
+				String[] paths = index.queryInDocumentNames(""); // all file names //$NON-NLS-1$
+				int max = paths == null ? 0 : paths.length;
 				if (max != 0) {
 					/* check integrity of the existing index file
 					 * if the length is equal to 0, we want to index the whole jar again
@@ -125,13 +126,13 @@
 					String DELETED = "DELETED"; //$NON-NLS-1$
 					SimpleLookupTable indexedFileNames = new SimpleLookupTable(max == 0 ? 33 : max + 11);
 					for (int i = 0; i < max; i++)
-						indexedFileNames.put(results[i].getPath(), DELETED);
+						indexedFileNames.put(paths[i], DELETED);
 					for (Enumeration e = zip.entries(); e.hasMoreElements();) {
 						// iterate each entry to index it
 						ZipEntry ze = (ZipEntry) e.nextElement();
 						if (Util.isClassFileName(ze.getName())) {
-							JarFileEntryDocument entryDocument = new JarFileEntryDocument(ze, null, zipFilePath);
-							indexedFileNames.put(entryDocument.getName(), EXISTS);
+							JavaSearchDocument entryDocument = new JavaSearchDocument(ze, zipFilePath, null, null);
+							indexedFileNames.put(entryDocument.getPath(), EXISTS);
 						}
 					}
 					boolean needToReindex = indexedFileNames.elementSize != max; // a new file was added
@@ -153,11 +154,10 @@
 					}
 				}
 
-				/*
-				 * Index the jar for the first time or reindex the jar in case the previous index file has been corrupted
-				 */
+				// Index the jar for the first time or reindex the jar in case the previous index file has been corrupted
 				// index already existed: recreate it so that we forget about previous entries
-				index = manager.recreateIndex(this.indexPath);
+				SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
+				index = manager.recreateIndex(this.containerPath);
 				for (Enumeration e = zip.entries(); e.hasMoreElements();) {
 					if (this.isCancelled) {
 						if (JobManager.VERBOSE)
@@ -168,11 +168,9 @@
 					// iterate each entry to index it
 					ZipEntry ze = (ZipEntry) e.nextElement();
 					if (Util.isClassFileName(ze.getName())) {
-						byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
-						// Add the name of the file to the index
-						index.add(
-							new JarFileEntryDocument(ze, classFileBytes, zipFilePath),
-							new BinaryIndexer(true));
+						final byte[] classFileBytes = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip);
+						JavaSearchDocument entryDocument = new JavaSearchDocument(ze, zipFilePath, classFileBytes, participant);
+						this.manager.indexDocument(entryDocument, participant, index);
 					}
 				}
 				this.manager.saveIndex(index);
@@ -190,10 +188,10 @@
 			}
 		} catch (IOException e) {
 			if (JobManager.VERBOSE) {
-				JobManager.verbose("-> failed to index " + this.indexPath + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
+				JobManager.verbose("-> failed to index " + this.containerPath + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
 				e.printStackTrace();
 			}
-			manager.removeIndex(this.indexPath);
+			manager.removeIndex(this.containerPath);
 			return false;
 		}
 		return true;
@@ -202,6 +200,6 @@
 		return IndexManager.REBUILDING_STATE;
 	}
 	public String toString() {
-		return "indexing " + this.indexPath.toString(); //$NON-NLS-1$
+		return "indexing " + this.containerPath.toString(); //$NON-NLS-1$
 	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
index e6d8cf5..808412b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
@@ -10,18 +10,16 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.indexing;
 
-import java.io.IOException;
-
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileStruct;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.classfmt.FieldInfo;
 import org.eclipse.jdt.internal.compiler.classfmt.MethodInfo;
-import org.eclipse.jdt.internal.core.index.IDocument;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 
-public class BinaryIndexer extends AbstractIndexer {
-	public static final String[] FILE_TYPES= new String[] {"class"}; //$NON-NLS-1$
+public class BinaryIndexer extends AbstractIndexer implements SuffixConstants {
 	private static final char[] BYTE = "byte".toCharArray(); //$NON-NLS-1$
 	private static final char[] CHAR = "char".toCharArray(); //$NON-NLS-1$
 	private static final char[] DOUBLE = "double".toCharArray(); //$NON-NLS-1$
@@ -32,526 +30,509 @@
 	private static final char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
 	private static final char[] VOID = "void".toCharArray(); //$NON-NLS-1$
 	private static final char[] INIT = "<init>".toCharArray(); //$NON-NLS-1$
+	
+	private static final char[] ONE_DOLLAR = "$".toCharArray(); //$NON-NLS-1$
+	private static final char[] ONE_DOT = ".".toCharArray(); //$NON-NLS-1$
 
-	private boolean needReferences;
-/**
- * BinaryIndexer constructor comment.
- */
-public BinaryIndexer() {
-	needReferences = false;
-}
-/**
- * BinaryIndexer constructor comment.
- */
-public BinaryIndexer(boolean retrieveReferences) {
-	needReferences = retrieveReferences;
-}
-/**
- * For example:
- *   - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
- *   - void foo(int) is (I)V ==> int
- */
-private void convertToArrayType(char[][] parameterTypes, int counter, int arrayDim) {
-	int length = parameterTypes[counter].length;
-	char[] arrayType = new char[length + arrayDim*2];
-	System.arraycopy(parameterTypes[counter], 0, arrayType, 0, length);
-	for (int i = 0; i < arrayDim; i++) {
-		arrayType[length + (i * 2)] = '[';
-		arrayType[length + (i * 2) + 1] = ']';
+	public BinaryIndexer(SearchDocument document, String indexPath) {
+		super(document, indexPath);
 	}
-	parameterTypes[counter] = arrayType;
-}
-/**
- * For example:
- *   - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
- *   - void foo(int) is (I)V ==> int
- */
-private char[] convertToArrayType(char[] typeName, int arrayDim) {
-	int length = typeName.length;
-	char[] arrayType = new char[length + arrayDim*2];
-	System.arraycopy(typeName, 0, arrayType, 0, length);
-	for (int i = 0; i < arrayDim; i++) {
-		arrayType[length + (i * 2)] = '[';
-		arrayType[length + (i * 2) + 1] = ']';
+	public void addTypeReference(char[] typeName){
+	 
+	 	// consider that A$B is a member type: so replace '$' with '.'
+	 	// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=40116)
+	 	typeName = CharOperation.replace(typeName, ONE_DOLLAR, ONE_DOT); // note this doesn't create a new array if no replacement is needed
+	 	super.addTypeReference(typeName);
 	}
-	return arrayType;
-}
-private char[] decodeFieldType(char[] signature) throws ClassFormatException {
-	if (signature == null) return null;
-	int arrayDim = 0;
-	for (int i = 0, max = signature.length; i < max; i++) {
-		switch(signature[i]) {
-			case 'B':
-				if (arrayDim > 0) {
-					return convertToArrayType(BYTE, arrayDim);
-				} else {
-					return BYTE;
-				}
-			case 'C':
-				if (arrayDim > 0) {
-					return convertToArrayType(CHAR, arrayDim);
-				} else {
-					return CHAR;
-				}
-			case 'D':
-				if (arrayDim > 0) {
-					return convertToArrayType(DOUBLE, arrayDim);
-				} else {
-					return DOUBLE;
-				}
-			case 'F':
-				if (arrayDim > 0) {
-					return convertToArrayType(FLOAT, arrayDim);
-				} else {
-					return FLOAT;
-				}
-			case 'I':
-				if (arrayDim > 0) {
-					return convertToArrayType(INT, arrayDim);
-				} else {
-					return INT;
-				}
-			case 'J':
-				if (arrayDim > 0) {
-					return convertToArrayType(LONG, arrayDim);
-				} else {
-					return LONG;
-				}
-			case 'L':
-				int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
-				if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
-				if (arrayDim > 0) {
-					return convertToArrayType(replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon)), arrayDim);
-				} else {
-					return replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
-				}
-			case 'S':
-				if (arrayDim > 0) {
-					return convertToArrayType(SHORT, arrayDim);
-				} else {
-					return SHORT;
-				}
-			case 'Z':
-				if (arrayDim > 0) {
-					return convertToArrayType(BOOLEAN, arrayDim);
-				} else {
-					return BOOLEAN;
-				}
-			case 'V':
-				return VOID;
-			case '[':
-				arrayDim++;
-				break;
-			default:
-				throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+	/**
+	 * For example:
+	 *   - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
+	 *   - void foo(int) is (I)V ==> int
+	 */
+	private void convertToArrayType(char[][] parameterTypes, int counter, int arrayDim) {
+		int length = parameterTypes[counter].length;
+		char[] arrayType = new char[length + arrayDim*2];
+		System.arraycopy(parameterTypes[counter], 0, arrayType, 0, length);
+		for (int i = 0; i < arrayDim; i++) {
+			arrayType[length + (i * 2)] = '[';
+			arrayType[length + (i * 2) + 1] = ']';
 		}
+		parameterTypes[counter] = arrayType;
 	}
-	return null;
-}
-/**
- * For example:
- *   - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
- *   - void foo(int) is (I)V ==> int
- */
-private char[][] decodeParameterTypes(char[] signature) throws ClassFormatException {
-	if (signature == null) return null;
-	int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
-	if (indexOfClosingParen == 1) {
-		// there is no parameter
+	/**
+	 * For example:
+	 *   - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
+	 *   - void foo(int) is (I)V ==> int
+	 */
+	private char[] convertToArrayType(char[] typeName, int arrayDim) {
+		int length = typeName.length;
+		char[] arrayType = new char[length + arrayDim*2];
+		System.arraycopy(typeName, 0, arrayType, 0, length);
+		for (int i = 0; i < arrayDim; i++) {
+			arrayType[length + (i * 2)] = '[';
+			arrayType[length + (i * 2) + 1] = ']';
+		}
+		return arrayType;
+	}
+	private char[] decodeFieldType(char[] signature) throws ClassFormatException {
+		if (signature == null) return null;
+		int arrayDim = 0;
+		for (int i = 0, max = signature.length; i < max; i++) {
+			switch(signature[i]) {
+				case 'B':
+					if (arrayDim > 0) {
+						return convertToArrayType(BYTE, arrayDim);
+					} else {
+						return BYTE;
+					}
+				case 'C':
+					if (arrayDim > 0) {
+						return convertToArrayType(CHAR, arrayDim);
+					} else {
+						return CHAR;
+					}
+				case 'D':
+					if (arrayDim > 0) {
+						return convertToArrayType(DOUBLE, arrayDim);
+					} else {
+						return DOUBLE;
+					}
+				case 'F':
+					if (arrayDim > 0) {
+						return convertToArrayType(FLOAT, arrayDim);
+					} else {
+						return FLOAT;
+					}
+				case 'I':
+					if (arrayDim > 0) {
+						return convertToArrayType(INT, arrayDim);
+					} else {
+						return INT;
+					}
+				case 'J':
+					if (arrayDim > 0) {
+						return convertToArrayType(LONG, arrayDim);
+					} else {
+						return LONG;
+					}
+				case 'L':
+					int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
+					if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+					if (arrayDim > 0) {
+						return convertToArrayType(replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon)), arrayDim);
+					} else {
+						return replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
+					}
+				case 'S':
+					if (arrayDim > 0) {
+						return convertToArrayType(SHORT, arrayDim);
+					} else {
+						return SHORT;
+					}
+				case 'Z':
+					if (arrayDim > 0) {
+						return convertToArrayType(BOOLEAN, arrayDim);
+					} else {
+						return BOOLEAN;
+					}
+				case 'V':
+					return VOID;
+				case '[':
+					arrayDim++;
+					break;
+				default:
+					throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+			}
+		}
 		return null;
 	}
-	if (indexOfClosingParen == -1) {
-		throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
-	}
-	char[][] parameterTypes = new char[3][];
-	int parameterTypesCounter = 0;
-	int arrayDim = 0;
-	for (int i = 1; i < indexOfClosingParen; i++) {
-		if (parameterTypesCounter == parameterTypes.length) {
-			// resize
-			System.arraycopy(parameterTypes, 0, (parameterTypes = new char[parameterTypesCounter * 2][]), 0, parameterTypesCounter);
+	/**
+	 * For example:
+	 *   - int foo(String[]) is ([Ljava/lang/String;)I => java.lang.String[] in a char[][]
+	 *   - void foo(int) is (I)V ==> int
+	 */
+	private char[][] decodeParameterTypes(char[] signature) throws ClassFormatException {
+		if (signature == null) return null;
+		int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
+		if (indexOfClosingParen == 1) {
+			// there is no parameter
+			return null;
 		}
-		switch(signature[i]) {
-			case 'B':
-				parameterTypes[parameterTypesCounter++] = BYTE;
-				if (arrayDim > 0) {
-					convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
-				}
-				arrayDim = 0;
-				break;
-			case 'C':
-				parameterTypes[parameterTypesCounter++] = CHAR;
-				if (arrayDim > 0) {
-					convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
-				}
-				arrayDim = 0;
-				break;
-			case 'D':
-				parameterTypes[parameterTypesCounter++] = DOUBLE;
-				if (arrayDim > 0) {
-					convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
-				}
-				arrayDim = 0;
-				break;
-			case 'F':
-				parameterTypes[parameterTypesCounter++] = FLOAT;
-				if (arrayDim > 0) {
-					convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
-				}
-				arrayDim = 0;
-				break;
-			case 'I':
-				parameterTypes[parameterTypesCounter++] = INT;
-				if (arrayDim > 0) {
-					convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
-				}
-				arrayDim = 0;
-				break;
-			case 'J':
-				parameterTypes[parameterTypesCounter++] = LONG;
-				if (arrayDim > 0) {
-					convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
-				}
-				arrayDim = 0;
-				break;
-			case 'L':
-				int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
-				if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
-				parameterTypes[parameterTypesCounter++] = replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
-				if (arrayDim > 0) {
-					convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
-				}
-				i = indexOfSemiColon;
-				arrayDim = 0;
-				break;
-			case 'S':
-				parameterTypes[parameterTypesCounter++] = SHORT;
-				if (arrayDim > 0) {
-					convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
-				}
-				arrayDim = 0;
-				break;
-			case 'Z':
-				parameterTypes[parameterTypesCounter++] = BOOLEAN;
-				if (arrayDim > 0) {
-					convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
-				}
-				arrayDim = 0;
-				break;
-			case '[':
-				arrayDim++;
-				break;
-			default:
-				throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+		if (indexOfClosingParen == -1) {
+			throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
 		}
-	}
-	if (parameterTypes.length != parameterTypesCounter) {
-		System.arraycopy(parameterTypes, 0, parameterTypes = new char[parameterTypesCounter][], 0, parameterTypesCounter);
-	}
-	return parameterTypes;
-}
-private char[] decodeReturnType(char[] signature) throws ClassFormatException {
-	if (signature == null) return null;
-	int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
-	if (indexOfClosingParen == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
-	int arrayDim = 0;
-	for (int i = indexOfClosingParen + 1, max = signature.length; i < max; i++) {
-		switch(signature[i]) {
-			case 'B':
-				if (arrayDim > 0) {
-					return convertToArrayType(BYTE, arrayDim);
-				} else {
-					return BYTE;
-				}
-			case 'C':
-				if (arrayDim > 0) {
-					return convertToArrayType(CHAR, arrayDim);
-				} else {
-					return CHAR;
-				}
-			case 'D':
-				if (arrayDim > 0) {
-					return convertToArrayType(DOUBLE, arrayDim);
-				} else {
-					return DOUBLE;
-				}
-			case 'F':
-				if (arrayDim > 0) {
-					return convertToArrayType(FLOAT, arrayDim);
-				} else {
-					return FLOAT;
-				}
-			case 'I':
-				if (arrayDim > 0) {
-					return convertToArrayType(INT, arrayDim);
-				} else {
-					return INT;
-				}
-			case 'J':
-				if (arrayDim > 0) {
-					return convertToArrayType(LONG, arrayDim);
-				} else {
-					return LONG;
-				}
-			case 'L':
-				int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
-				if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
-				if (arrayDim > 0) {
-					return convertToArrayType(replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon)), arrayDim);
-				} else {
-					return replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
-				}
-			case 'S':
-				if (arrayDim > 0) {
-					return convertToArrayType(SHORT, arrayDim);
-				} else {
-					return SHORT;
-				}
-			case 'Z':
-				if (arrayDim > 0) {
-					return convertToArrayType(BOOLEAN, arrayDim);
-				} else {
-					return BOOLEAN;
-				}
-			case 'V':
-				return VOID;
-			case '[':
-				arrayDim++;
-				break;
-			default:
-				throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
-		}
-	}
-	return null;
-}
-private int extractArgCount(char[] signature) throws ClassFormatException {
-	int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
-	if (indexOfClosingParen == 1) {
-		// there is no parameter
-		return 0;
-	}
-	if (indexOfClosingParen == -1) {
-		throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
-	}
-	int parameterTypesCounter = 0;
-	for (int i = 1; i < indexOfClosingParen; i++) {
-		switch(signature[i]) {
-			case 'B':
-			case 'C':
-			case 'D':
-			case 'F':
-			case 'I':
-			case 'J':
-			case 'S':
-			case 'Z':
-				parameterTypesCounter++;
-				break;
-			case 'L':
-				int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
-				if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
-				parameterTypesCounter++;
-				i = indexOfSemiColon;
-				break;
-			case '[':
-				break;
-			default:
-				throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
-		}
-	}
-	return parameterTypesCounter;
-}
-private final char[] extractClassName(int[] constantPoolOffsets, ClassFileReader reader, int index) {
-	// the entry at i has to be a field ref or a method/interface method ref.
-	int class_index = reader.u2At(constantPoolOffsets[index] + 1);
-	int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[class_index] + 1)];
-	return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
-}
-private final char[] extractName(int[] constantPoolOffsets, ClassFileReader reader, int index) {
-	int nameAndTypeIndex = reader.u2At(constantPoolOffsets[index] + 3);
-	int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[nameAndTypeIndex] + 1)];
-	return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
-}
-private final char[] extractClassReference(int[] constantPoolOffsets, ClassFileReader reader, int index) {
-	// the entry at i has to be a class ref.
-	int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[index] + 1)];
-	return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
-}
-/**
- * Extract all type, method, field and interface method references from the constant pool
- */
-private void extractReferenceFromConstantPool(byte[] contents, ClassFileReader reader) throws ClassFormatException {
-	int[] constantPoolOffsets = reader.getConstantPoolOffsets();
-	int constantPoolCount = constantPoolOffsets.length;
-	for (int i = 1; i < constantPoolCount; i++) {
-		int tag = reader.u1At(constantPoolOffsets[i]);
-		/**
-		 * u1 tag
-		 * u2 class_index
-		 * u2 name_and_type_index
-		 */
-		char[] name = null;
-		char[] type = null;
-		switch (tag) {
-			case ClassFileStruct.FieldRefTag :
-				// add reference to the class/interface and field name and type
-				name = extractName(constantPoolOffsets, reader, i);
-				addFieldReference(name);
-				break;
-			case ClassFileStruct.MethodRefTag :
-				// add reference to the class and method name and type
-			case ClassFileStruct.InterfaceMethodRefTag :
-				// add reference to the interface and method name and type
-				name = extractName(constantPoolOffsets, reader, i);
-				type = extractType(constantPoolOffsets, reader, i);
-				if (CharOperation.equals(INIT, name)) {
-					// add a constructor reference
-					char[] className = replace('/', '.', extractClassName(constantPoolOffsets, reader, i)); // so that it looks like java.lang.String
-					addConstructorReference(className, extractArgCount(type));
-				} else {
-					// add a method reference
-					addMethodReference(name, extractArgCount(type));
-				}
-				break;
-			case ClassFileStruct.ClassTag :
-				// add a type reference 
-				name = replace('/', '.', extractClassReference(constantPoolOffsets, reader, i)); // so that it looks like java.lang.String
-				addTypeReference(name);
-				
-				// also add a simple reference on each segment of the qualification (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=24741)
-				char[][] qualification = CharOperation.splitOn('.', name);
-				for (int j = 0, length = qualification.length; j < length; j++) {
-					addNameReference(qualification[j]);
-				}
-				break;
-		}
-	}
-}
-private final char[] extractType(int[] constantPoolOffsets, ClassFileReader reader, int index) {
-	int constantPoolIndex = reader.u2At(constantPoolOffsets[index] + 3);
-	int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[constantPoolIndex] + 3)];
-	return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
-}
-/**
- * getFileTypes method comment.
- */
-public String[] getFileTypes() {
-	return FILE_TYPES;
-}
-private void indexClassFile(byte[] contents, char[] documentName) throws IOException {
-	try {
-		ClassFileReader reader = new ClassFileReader(contents, documentName);
-
-		// first add type references
-		char[] className = replace('/', '.', reader.getName()); // looks like java/lang/String
-		// need to extract the package name and the simple name
-		int packageNameIndex = CharOperation.lastIndexOf('.', className);
-		char[] packageName = null;
-		char[] name = null;
-		if (packageNameIndex >= 0) {
-			packageName = CharOperation.subarray(className, 0, packageNameIndex);
-			name = CharOperation.subarray(className, packageNameIndex + 1, className.length);
-		} else {
-			name = className;
-		}
-		char[] enclosingTypeName = null;
-		if (reader.isNestedType()) {
-			if (reader.isAnonymous()) {
-				name = CharOperation.NO_CHAR;
-			} else {
-				name = reader.getInnerSourceName();
+		char[][] parameterTypes = new char[3][];
+		int parameterTypesCounter = 0;
+		int arrayDim = 0;
+		for (int i = 1; i < indexOfClosingParen; i++) {
+			if (parameterTypesCounter == parameterTypes.length) {
+				// resize
+				System.arraycopy(parameterTypes, 0, (parameterTypes = new char[parameterTypesCounter * 2][]), 0, parameterTypesCounter);
 			}
-			if (reader.isLocal() || reader.isAnonymous()) {
-				enclosingTypeName = ONE_ZERO;
-			} else {
-				char[] fullEnclosingName = reader.getEnclosingTypeName();
-				int nameLength = fullEnclosingName.length - packageNameIndex - 1;
-				if (nameLength <= 0) {
-					// See PR 1GIR345: ITPJCORE:ALL - Indexer: NegativeArraySizeException
-					return;
-				}
-				enclosingTypeName = new char[nameLength]; 
-				System.arraycopy(fullEnclosingName, packageNameIndex + 1, enclosingTypeName, 0, nameLength);
+			switch(signature[i]) {
+				case 'B':
+					parameterTypes[parameterTypesCounter++] = BYTE;
+					if (arrayDim > 0) {
+						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
+					}
+					arrayDim = 0;
+					break;
+				case 'C':
+					parameterTypes[parameterTypesCounter++] = CHAR;
+					if (arrayDim > 0) {
+						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
+					}
+					arrayDim = 0;
+					break;
+				case 'D':
+					parameterTypes[parameterTypesCounter++] = DOUBLE;
+					if (arrayDim > 0) {
+						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
+					}
+					arrayDim = 0;
+					break;
+				case 'F':
+					parameterTypes[parameterTypesCounter++] = FLOAT;
+					if (arrayDim > 0) {
+						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
+					}
+					arrayDim = 0;
+					break;
+				case 'I':
+					parameterTypes[parameterTypesCounter++] = INT;
+					if (arrayDim > 0) {
+						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
+					}
+					arrayDim = 0;
+					break;
+				case 'J':
+					parameterTypes[parameterTypesCounter++] = LONG;
+					if (arrayDim > 0) {
+						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
+					}
+					arrayDim = 0;
+					break;
+				case 'L':
+					int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
+					if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+					parameterTypes[parameterTypesCounter++] = replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
+					if (arrayDim > 0) {
+						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
+					}
+					i = indexOfSemiColon;
+					arrayDim = 0;
+					break;
+				case 'S':
+					parameterTypes[parameterTypesCounter++] = SHORT;
+					if (arrayDim > 0) {
+						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
+					}
+					arrayDim = 0;
+					break;
+				case 'Z':
+					parameterTypes[parameterTypesCounter++] = BOOLEAN;
+					if (arrayDim > 0) {
+						convertToArrayType(parameterTypes, parameterTypesCounter-1, arrayDim);
+					}
+					arrayDim = 0;
+					break;
+				case '[':
+					arrayDim++;
+					break;
+				default:
+					throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
 			}
 		}
-		// eliminate invalid innerclasses (1G4KCF7)
-		if (name == null) return;
-		
-		char[][] superinterfaces = replace('/', '.', reader.getInterfaceNames());
-		char[][] enclosingTypeNames = enclosingTypeName == null ? null : new char[][] {enclosingTypeName};
-		if (reader.isInterface()) {
-			addInterfaceDeclaration(reader.getModifiers(), packageName, name, enclosingTypeNames, superinterfaces);
-		} else {
-			char[] superclass = replace('/', '.', reader.getSuperclassName());
-			addClassDeclaration(reader.getModifiers(), packageName, name, enclosingTypeNames, superclass, superinterfaces);
+		if (parameterTypes.length != parameterTypesCounter) {
+			System.arraycopy(parameterTypes, 0, parameterTypes = new char[parameterTypesCounter][], 0, parameterTypesCounter);
 		}
-
-		// first reference all methods declarations and field declarations
-		MethodInfo[] methods = (MethodInfo[]) reader.getMethods();
-		if (methods != null) {
-			for (int i = 0, max = methods.length; i < max; i++) {
-				MethodInfo method = methods[i];
-				char[] descriptor = method.getMethodDescriptor();
-				char[][] parameterTypes = decodeParameterTypes(descriptor);
-				char[] returnType = decodeReturnType(descriptor);
-				char[][] exceptionTypes = replace('/', '.', method.getExceptionTypeNames());
-				if (method.isConstructor()) {
-					addConstructorDeclaration(className, parameterTypes, exceptionTypes);
+		return parameterTypes;
+	}
+	private char[] decodeReturnType(char[] signature) throws ClassFormatException {
+		if (signature == null) return null;
+		int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
+		if (indexOfClosingParen == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+		int arrayDim = 0;
+		for (int i = indexOfClosingParen + 1, max = signature.length; i < max; i++) {
+			switch(signature[i]) {
+				case 'B':
+					if (arrayDim > 0) {
+						return convertToArrayType(BYTE, arrayDim);
+					} else {
+						return BYTE;
+					}
+				case 'C':
+					if (arrayDim > 0) {
+						return convertToArrayType(CHAR, arrayDim);
+					} else {
+						return CHAR;
+					}
+				case 'D':
+					if (arrayDim > 0) {
+						return convertToArrayType(DOUBLE, arrayDim);
+					} else {
+						return DOUBLE;
+					}
+				case 'F':
+					if (arrayDim > 0) {
+						return convertToArrayType(FLOAT, arrayDim);
+					} else {
+						return FLOAT;
+					}
+				case 'I':
+					if (arrayDim > 0) {
+						return convertToArrayType(INT, arrayDim);
+					} else {
+						return INT;
+					}
+				case 'J':
+					if (arrayDim > 0) {
+						return convertToArrayType(LONG, arrayDim);
+					} else {
+						return LONG;
+					}
+				case 'L':
+					int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
+					if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+					if (arrayDim > 0) {
+						return convertToArrayType(replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon)), arrayDim);
+					} else {
+						return replace('/','.',CharOperation.subarray(signature, i + 1, indexOfSemiColon));
+					}
+				case 'S':
+					if (arrayDim > 0) {
+						return convertToArrayType(SHORT, arrayDim);
+					} else {
+						return SHORT;
+					}
+				case 'Z':
+					if (arrayDim > 0) {
+						return convertToArrayType(BOOLEAN, arrayDim);
+					} else {
+						return BOOLEAN;
+					}
+				case 'V':
+					return VOID;
+				case '[':
+					arrayDim++;
+					break;
+				default:
+					throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+			}
+		}
+		return null;
+	}
+	private int extractArgCount(char[] signature) throws ClassFormatException {
+		int indexOfClosingParen = CharOperation.lastIndexOf(')', signature);
+		if (indexOfClosingParen == 1) {
+			// there is no parameter
+			return 0;
+		}
+		if (indexOfClosingParen == -1) {
+			throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+		}
+		int parameterTypesCounter = 0;
+		for (int i = 1; i < indexOfClosingParen; i++) {
+			switch(signature[i]) {
+				case 'B':
+				case 'C':
+				case 'D':
+				case 'F':
+				case 'I':
+				case 'J':
+				case 'S':
+				case 'Z':
+					parameterTypesCounter++;
+					break;
+				case 'L':
+					int indexOfSemiColon = CharOperation.indexOf(';', signature, i+1);
+					if (indexOfSemiColon == -1) throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+					parameterTypesCounter++;
+					i = indexOfSemiColon;
+					break;
+				case '[':
+					break;
+				default:
+					throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+			}
+		}
+		return parameterTypesCounter;
+	}
+	private char[] extractClassName(int[] constantPoolOffsets, ClassFileReader reader, int index) {
+		// the entry at i has to be a field ref or a method/interface method ref.
+		int class_index = reader.u2At(constantPoolOffsets[index] + 1);
+		int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[class_index] + 1)];
+		return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
+	}
+	private char[] extractName(int[] constantPoolOffsets, ClassFileReader reader, int index) {
+		int nameAndTypeIndex = reader.u2At(constantPoolOffsets[index] + 3);
+		int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[nameAndTypeIndex] + 1)];
+		return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
+	}
+	private char[] extractClassReference(int[] constantPoolOffsets, ClassFileReader reader, int index) {
+		// the entry at i has to be a class ref.
+		int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[index] + 1)];
+		return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
+	}
+	/**
+	 * Extract all type, method, field and interface method references from the constant pool
+	 */
+	private void extractReferenceFromConstantPool(byte[] contents, ClassFileReader reader) throws ClassFormatException {
+		int[] constantPoolOffsets = reader.getConstantPoolOffsets();
+		int constantPoolCount = constantPoolOffsets.length;
+		for (int i = 1; i < constantPoolCount; i++) {
+			int tag = reader.u1At(constantPoolOffsets[i]);
+			/**
+			 * u1 tag
+			 * u2 class_index
+			 * u2 name_and_type_index
+			 */
+			char[] name = null;
+			char[] type = null;
+			switch (tag) {
+				case ClassFileConstants.FieldRefTag :
+					// add reference to the class/interface and field name and type
+					name = extractName(constantPoolOffsets, reader, i);
+					addFieldReference(name);
+					break;
+				case ClassFileConstants.MethodRefTag :
+					// add reference to the class and method name and type
+				case ClassFileConstants.InterfaceMethodRefTag :
+					// add reference to the interface and method name and type
+					name = extractName(constantPoolOffsets, reader, i);
+					type = extractType(constantPoolOffsets, reader, i);
+					if (CharOperation.equals(INIT, name)) {
+						// add a constructor reference
+						char[] className = replace('/', '.', extractClassName(constantPoolOffsets, reader, i)); // so that it looks like java.lang.String
+						addConstructorReference(className, extractArgCount(type));
+					} else {
+						// add a method reference
+						addMethodReference(name, extractArgCount(type));
+					}
+					break;
+				case ClassFileConstants.ClassTag :
+					// add a type reference 
+					name = replace('/', '.', extractClassReference(constantPoolOffsets, reader, i)); // so that it looks like java.lang.String
+					addTypeReference(name);
+					
+					// also add a simple reference on each segment of the qualification (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=24741)
+					char[][] qualification = CharOperation.splitOn('.', name);
+					for (int j = 0, length = qualification.length; j < length; j++) {
+						addNameReference(qualification[j]);
+					}
+					break;
+			}
+		}
+	}
+	private char[] extractType(int[] constantPoolOffsets, ClassFileReader reader, int index) {
+		int constantPoolIndex = reader.u2At(constantPoolOffsets[index] + 3);
+		int utf8Offset = constantPoolOffsets[reader.u2At(constantPoolOffsets[constantPoolIndex] + 3)];
+		return reader.utf8At(utf8Offset + 3, reader.u2At(utf8Offset + 1));
+	}
+	public void indexDocument() {
+		try {
+			byte[] contents = this.document.getByteContents();
+			ClassFileReader reader = new ClassFileReader(contents, this.document.getPath().toCharArray());
+	
+			// first add type references
+			char[] className = replace('/', '.', reader.getName()); // looks like java/lang/String
+			// need to extract the package name and the simple name
+			int packageNameIndex = CharOperation.lastIndexOf('.', className);
+			char[] packageName = null;
+			char[] name = null;
+			if (packageNameIndex >= 0) {
+				packageName = CharOperation.subarray(className, 0, packageNameIndex);
+				name = CharOperation.subarray(className, packageNameIndex + 1, className.length);
+			} else {
+				packageName = CharOperation.NO_CHAR;
+				name = className;
+			}
+			char[] enclosingTypeName = null;
+			if (reader.isNestedType()) {
+				if (reader.isAnonymous()) {
+					name = CharOperation.NO_CHAR;
 				} else {
-					if (!method.isClinit()) {
-						addMethodDeclaration(method.getSelector(), parameterTypes, returnType, exceptionTypes);
+					name = reader.getInnerSourceName();
+				}
+				if (reader.isLocal() || reader.isAnonymous()) {
+					enclosingTypeName = ONE_ZERO;
+				} else {
+					char[] fullEnclosingName = reader.getEnclosingTypeName();
+					int nameLength = fullEnclosingName.length - packageNameIndex - 1;
+					if (nameLength <= 0) {
+						// See PR 1GIR345: ITPJCORE:ALL - Indexer: NegativeArraySizeException
+						return;
+					}
+					enclosingTypeName = new char[nameLength]; 
+					System.arraycopy(fullEnclosingName, packageNameIndex + 1, enclosingTypeName, 0, nameLength);
+				}
+			}
+			// eliminate invalid innerclasses (1G4KCF7)
+			if (name == null) return;
+			
+			char[][] superinterfaces = replace('/', '.', reader.getInterfaceNames());
+			char[][] enclosingTypeNames = enclosingTypeName == null ? null : new char[][] {enclosingTypeName};
+			if (reader.isInterface()) {
+				addInterfaceDeclaration(reader.getModifiers(), packageName, name, enclosingTypeNames, superinterfaces);
+			} else {
+				char[] superclass = replace('/', '.', reader.getSuperclassName());
+				addClassDeclaration(reader.getModifiers(), packageName, name, enclosingTypeNames, superclass, superinterfaces);
+			}
+	
+			// first reference all methods declarations and field declarations
+			MethodInfo[] methods = (MethodInfo[]) reader.getMethods();
+			if (methods != null) {
+				for (int i = 0, max = methods.length; i < max; i++) {
+					MethodInfo method = methods[i];
+					char[] descriptor = method.getMethodDescriptor();
+					char[][] parameterTypes = decodeParameterTypes(descriptor);
+					char[] returnType = decodeReturnType(descriptor);
+					char[][] exceptionTypes = replace('/', '.', method.getExceptionTypeNames());
+					if (method.isConstructor()) {
+						addConstructorDeclaration(className, parameterTypes, exceptionTypes);
+					} else {
+						if (!method.isClinit()) {
+							addMethodDeclaration(method.getSelector(), parameterTypes, returnType, exceptionTypes);
+						}
 					}
 				}
 			}
+			FieldInfo[] fields = (FieldInfo[]) reader.getFields();
+			if (fields != null) {
+				for (int i = 0, max = fields.length; i < max; i++) {
+					FieldInfo field = fields[i];
+					char[] fieldName = field.getName();
+					char[] fieldType = decodeFieldType(replace('/', '.', field.getTypeName()));
+					addFieldDeclaration(fieldType, fieldName);
+				}
+			}
+	
+			// record all references found inside the .class file
+			extractReferenceFromConstantPool(contents, reader);
+		} catch (ClassFormatException e) {
+			// ignore
 		}
-		FieldInfo[] fields = (FieldInfo[]) reader.getFields();
-		if (fields != null) {
-			for (int i = 0, max = fields.length; i < max; i++) {
-				FieldInfo field = fields[i];
-				char[] fieldName = field.getName();
-				char[] fieldType = decodeFieldType(replace('/', '.', field.getTypeName()));
-				addFieldDeclaration(fieldType, fieldName);
+	}
+	/*
+	 * Modify the array by replacing all occurences of toBeReplaced with newChar
+	 */
+	private char[][] replace(char toBeReplaced, char newChar, char[][] array) {
+		if (array == null) return null;
+		for (int i = 0, max = array.length; i < max; i++) {
+			replace(toBeReplaced, newChar, array[i]);
+		}
+		return array;
+	}
+	/*
+	 * Modify the array by replacing all occurences of toBeReplaced with newChar
+	 */
+	private char[] replace(char toBeReplaced, char newChar, char[] array) {
+		if (array == null) return null;
+		for (int i = 0, max = array.length; i < max; i++) {
+			if (array[i] == toBeReplaced) {
+				array[i] = newChar;
 			}
 		}
-
-		// record all references found inside the .class file
-		if (needReferences) {
-			extractReferenceFromConstantPool(contents, reader);
-		}
-	} catch (ClassFormatException e) {
+		return array;
 	}
 }
-/**
- * indexFile method comment.
- */
-protected void indexFile(IDocument document) throws IOException {
-	// Add the name of the file to the index
-	output.addDocument(document);
-	indexClassFile(document.getByteContent(), document.getName().toCharArray());
-}
-/**
- * Modify the array by replacing all occurences of toBeReplaced with newChar
- */
-private char[][] replace(char toBeReplaced, char newChar, char[][] array) {
-	if (array == null) return null;
-	for (int i = 0, max = array.length; i < max; i++) {
-		replace(toBeReplaced, newChar, array[i]);
-	}
-	return array;
-}
-/**
- * Modify the array by replacing all occurences of toBeReplaced with newChar
- */
-private char[] replace(char toBeReplaced, char newChar, char[] array) {
-	if (array == null) return null;
-	for (int i = 0, max = array.length; i < max; i++) {
-		if (array[i] == toBeReplaced) {
-			array[i] = newChar;
-		}
-	}
-	return array;
-}
-/**
- * setFileTypes method comment.
- */
-public void setFileTypes(String[] fileTypes) {}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
index 81f1f9d..4b034ae 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
@@ -28,7 +28,8 @@
 	char[] FIELD_DECL= "fieldDecl/".toCharArray(); //$NON-NLS-1$
 	char[] OBJECT = "Object".toCharArray(); //$NON-NLS-1$
 	char[][] COUNTS= 
-		new char[][] { new char[] {'0'}, new char[] {'1'}, new char[] {'2'}, new char[] {'3'}, new char[] {'4'}, new char[] {'5'}, new char[] {'6'}, new char[] {'7'}, new char[] {'8'}, new char[] {'9'}
+		new char[][] { new char[] {'/', '0'}, new char[] {'/', '1'}, new char[] {'/', '2'}, new char[] {'/', '3'}, new char[] {'/', '4'},
+			new char[] {'/', '5'}, new char[] {'/', '6'}, new char[] {'/', '7'}, new char[] {'/', '8'}, new char[] {'/', '9'}
 	};
 	char CLASS_SUFFIX = 'C';
 	char INTERFACE_SUFFIX = 'I';
@@ -41,4 +42,15 @@
 	// used as special marker for enclosing type name of local and anonymous classes
 	char[] ONE_ZERO = new char[] {'0'}; 
 	char[][] ONE_ZERO_CHAR = new char[][] {ONE_ZERO};
+
+	int PKG_REF_PATTERN = 1;
+	int PKG_DECL_PATTERN = 2;
+	int TYPE_REF_PATTERN = 4;
+	int TYPE_DECL_PATTERN = 8;
+	int SUPER_REF_PATTERN = 16;
+	int CONSTRUCTOR_PATTERN = 32;
+	int FIELD_PATTERN = 64;
+	int METHOD_PATTERN = 128;
+	int OR_PATTERN = 256;
+	int LOCAL_VAR_PATTERN = 512;
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
index a9db7f7..529956b 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
@@ -23,15 +23,14 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.IClasspathEntry;
-import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.internal.core.ClasspathEntry;
-import org.eclipse.jdt.internal.core.Util;
+import org.eclipse.jdt.internal.core.JavaProject;
 import org.eclipse.jdt.internal.core.index.IIndex;
-import org.eclipse.jdt.internal.core.index.IQueryResult;
-import org.eclipse.jdt.internal.core.index.impl.IFileDocument;
+import org.eclipse.jdt.internal.core.search.JavaSearchDocument;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
 import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public class IndexAllProject extends IndexRequest {
 	IProject project;
@@ -52,10 +51,10 @@
 	 */
 	public boolean execute(IProgressMonitor progressMonitor) {
 
-		if (progressMonitor != null && progressMonitor.isCanceled()) return true;
+		if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
 		if (!project.isAccessible()) return true; // nothing to do
 
-		IIndex index = this.manager.getIndex(this.indexPath, true, /*reuse index file*/ true /*create if none*/);
+		IIndex index = this.manager.getIndexForUpdate(this.containerPath, true, /*reuse index file*/ true /*create if none*/);
 		if (index == null) return true;
 		ReadWriteMonitor monitor = this.manager.getMonitorFor(index);
 		if (monitor == null) return true; // index got deleted since acquired
@@ -64,17 +63,18 @@
 			monitor.enterRead(); // ask permission to read
 			saveIfNecessary(index, monitor);
 
-			IQueryResult[] results = index.queryInDocumentNames(""); // all file names //$NON-NLS-1$
-			int max = results == null ? 0 : results.length;
+			String[] paths = index.queryInDocumentNames(""); // all file names //$NON-NLS-1$
+			int max = paths == null ? 0 : paths.length;
 			final SimpleLookupTable indexedFileNames = new SimpleLookupTable(max == 0 ? 33 : max + 11);
 			final String OK = "OK"; //$NON-NLS-1$
 			final String DELETED = "DELETED"; //$NON-NLS-1$
 			for (int i = 0; i < max; i++)
-				indexedFileNames.put(results[i].getPath(), DELETED);
+				indexedFileNames.put(paths[i], DELETED);
 			final long indexLastModified = max == 0 ? 0L : index.getIndexFile().lastModified();
 
-			IJavaProject javaProject = JavaCore.create(this.project);
-			IClasspathEntry[] entries = javaProject.getRawClasspath();
+			JavaProject javaProject = (JavaProject)JavaCore.create(this.project);
+			// Do not create marker nor log problems while getting raw classpath (see bug 41859)
+			IClasspathEntry[] entries = javaProject.getRawClasspath(false, false);
 			IWorkspaceRoot root = this.project.getWorkspace().getRoot();
 			for (int i = 0, length = entries.length; i < length; i++) {
 				if (this.isCancelled) return false;
@@ -87,7 +87,8 @@
 						// collect output locations if source is project (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32041)
 						final HashSet outputs = new HashSet();
 						if (sourceFolder.getType() == IResource.PROJECT) {
-							outputs.add(javaProject.getOutputLocation());
+							// Do not create marker nor log problems while getting output location (see bug 41859)
+							outputs.add(javaProject.getOutputLocation(false, false));
 							for (int j = 0; j < length; j++) {
 								IPath output = entries[j].getOutputLocation();
 								if (output != null) {
@@ -105,12 +106,10 @@
 										if (isCancelled) return false;
 										switch(proxy.getType()) {
 											case IResource.FILE :
-												if (Util.isJavaFileName(proxy.getName())) {
-													IResource resource = proxy.requestResource();
-													if (resource.getLocation() != null && (patterns == null || !Util.isExcluded(resource, patterns))) {
-														String name = new IFileDocument((IFile) resource).getName();
-														indexedFileNames.put(name, resource);
-													}
+												if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(proxy.getName())) {
+													IFile file = (IFile) proxy.requestResource();
+													if (file.getLocation() != null && (patterns == null || !Util.isExcluded(file, patterns)))
+														indexedFileNames.put(new JavaSearchDocument(file, null).getPath(), file);
 												}
 												return false;
 											case IResource.FOLDER :
@@ -132,14 +131,14 @@
 										if (isCancelled) return false;
 										switch(proxy.getType()) {
 											case IResource.FILE :
-												if (Util.isJavaFileName(proxy.getName())) {
-													IResource resource = proxy.requestResource();
-													IPath path = resource.getLocation();
-													if (path != null && (patterns == null || !Util.isExcluded(resource, patterns))) {
-														String name = new IFileDocument((IFile) resource).getName();
-														indexedFileNames.put(name,
-															indexedFileNames.get(name) == null || indexLastModified < path.toFile().lastModified()
-																? (Object) resource
+												if (org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(proxy.getName())) {
+													IFile file = (IFile) proxy.requestResource();
+													IPath location = file.getLocation();
+													if (location != null && (patterns == null || !Util.isExcluded(file, patterns))) {
+														String path = new JavaSearchDocument(file, null).getPath();
+														indexedFileNames.put(path,
+															indexedFileNames.get(path) == null || indexLastModified < location.toFile().lastModified()
+																? (Object) file
 																: (Object) OK);
 													}
 												}
@@ -163,7 +162,6 @@
 
 			Object[] names = indexedFileNames.keyTable;
 			Object[] values = indexedFileNames.valueTable;
-			boolean shouldSave = false;
 			for (int i = 0, length = names.length; i < length; i++) {
 				String name = (String) names[i];
 				if (name != null) {
@@ -171,32 +169,29 @@
 
 					Object value = values[i];
 					if (value != OK) {
-						shouldSave = true;
 						if (value == DELETED)
-							this.manager.remove(name, this.indexPath);
+							this.manager.remove(name, this.containerPath);
 						else
-							this.manager.addSource((IFile) value, this.indexPath);
+							this.manager.addSource((IFile) value, this.containerPath);
 					}
 				}
 			}
 
-			// request to save index when all cus have been indexed
-			if (shouldSave)
-				this.manager.request(new SaveIndex(this.indexPath, this.manager));
-
+			// request to save index when all cus have been indexed... also sets state to SAVED_STATE
+			this.manager.request(new SaveIndex(this.containerPath, this.manager));
 		} catch (CoreException e) {
 			if (JobManager.VERBOSE) {
 				JobManager.verbose("-> failed to index " + this.project + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
 				e.printStackTrace();
 			}
-			this.manager.removeIndex(this.indexPath);
+			this.manager.removeIndex(this.containerPath);
 			return false;
 		} catch (IOException e) {
 			if (JobManager.VERBOSE) {
 				JobManager.verbose("-> failed to index " + this.project + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
 				e.printStackTrace();
 			}
-			this.manager.removeIndex(this.indexPath);
+			this.manager.removeIndex(this.containerPath);
 			return false;
 		} finally {
 			monitor.exitRead(); // free read lock
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
index 6585fb3..f647c9e 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
@@ -20,10 +20,8 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.internal.core.Util;
 import org.eclipse.jdt.internal.core.index.IIndex;
-import org.eclipse.jdt.internal.core.index.IQueryResult;
-import org.eclipse.jdt.internal.core.index.impl.IFileDocument;
+import org.eclipse.jdt.internal.core.search.JavaSearchDocument;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
 import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
 
@@ -46,10 +44,10 @@
 	 */
 	public boolean execute(IProgressMonitor progressMonitor) {
 
-		if (progressMonitor != null && progressMonitor.isCanceled()) return true;
+		if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
 		if (!this.folder.isAccessible()) return true; // nothing to do
 
-		IIndex index = this.manager.getIndex(this.indexPath, true, /*reuse index file*/ true /*create if none*/);
+		IIndex index = this.manager.getIndexForUpdate(this.containerPath, true, /*reuse index file*/ true /*create if none*/);
 		if (index == null) return true;
 		ReadWriteMonitor monitor = this.manager.getMonitorFor(index);
 		if (monitor == null) return true; // index got deleted since acquired
@@ -58,8 +56,8 @@
 			monitor.enterRead(); // ask permission to read
 			saveIfNecessary(index, monitor);
 
-			IQueryResult[] results = index.queryInDocumentNames(""); // all file names //$NON-NLS-1$
-			int max = results == null ? 0 : results.length;
+			String[] paths = index.queryInDocumentNames(""); // all file names //$NON-NLS-1$
+			int max = paths == null ? 0 : paths.length;
 			final SimpleLookupTable indexedFileNames = new SimpleLookupTable(max == 0 ? 33 : max + 11);
 			final String OK = "OK"; //$NON-NLS-1$
 			final String DELETED = "DELETED"; //$NON-NLS-1$
@@ -68,12 +66,10 @@
 					public boolean visit(IResourceProxy proxy) {
 						if (isCancelled) return false;
 						if (proxy.getType() == IResource.FILE) {
-							if (Util.isClassFileName(proxy.getName())) {
-								IResource resource = proxy.requestResource();
-								if (resource.getLocation() != null) {
-									String name = new IFileDocument((IFile) resource).getName();
-									indexedFileNames.put(name, resource);
-								}
+							if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(proxy.getName())) {
+								IFile file = (IFile) proxy.requestResource();
+								if (file.getLocation() != null)
+									indexedFileNames.put(new JavaSearchDocument(file, null).getPath(), file);
 							}
 							return false;
 						}
@@ -82,7 +78,7 @@
 				}, IResource.NONE);
 			} else {
 				for (int i = 0; i < max; i++)
-					indexedFileNames.put(results[i].getPath(), DELETED);
+					indexedFileNames.put(paths[i], DELETED);
 
 				final long indexLastModified = index.getIndexFile().lastModified();
 				this.folder.accept(
@@ -90,14 +86,14 @@
 						public boolean visit(IResourceProxy proxy) {
 							if (isCancelled) return false;
 							if (proxy.getType() == IResource.FILE) {
-								if (Util.isClassFileName(proxy.getName())) {
-									IResource resource = proxy.requestResource();
-									IPath path = resource.getLocation();
-									if (path != null) {
-										String name = new IFileDocument((IFile) resource).getName();
-										indexedFileNames.put(name,
-											indexedFileNames.get(name) == null || indexLastModified < path.toFile().lastModified()
-												? (Object) resource
+								if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(proxy.getName())) {
+									IFile file = (IFile) proxy.requestResource();
+									IPath location = file.getLocation();
+									if (location != null) {
+										String path = new JavaSearchDocument(file, null).getPath();
+										indexedFileNames.put(path,
+											indexedFileNames.get(path) == null || indexLastModified < location.toFile().lastModified()
+												? (Object) file
 												: (Object) OK);
 									}
 								}
@@ -112,7 +108,6 @@
 
 			Object[] names = indexedFileNames.keyTable;
 			Object[] values = indexedFileNames.valueTable;
-			boolean shouldSave = false;
 			for (int i = 0, length = names.length; i < length; i++) {
 				String name = (String) names[i];
 				if (name != null) {
@@ -120,32 +115,30 @@
 
 					Object value = values[i];
 					if (value != OK) {
-						shouldSave = true;
 						if (value == DELETED)
-							this.manager.remove(name, this.indexPath);
-						else
-							this.manager.addBinary((IFile) value, this.indexPath);
+							this.manager.remove(name, this.containerPath);
+						else {
+							this.manager.addBinary((IFile) value, this.containerPath);
+						}
 					}
 				}
 			}
 
-			// request to save index when all class files have been indexed
-			if (shouldSave)
-				this.manager.request(new SaveIndex(this.indexPath, this.manager));
-
+			// request to save index when all class files have been indexed... also sets state to SAVED_STATE
+			this.manager.request(new SaveIndex(this.containerPath, this.manager));
 		} catch (CoreException e) {
 			if (JobManager.VERBOSE) {
 				JobManager.verbose("-> failed to index " + this.folder + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
 				e.printStackTrace();
 			}
-			this.manager.removeIndex(this.indexPath);
+			this.manager.removeIndex(this.containerPath);
 			return false;
 		} catch (IOException e) {
 			if (JobManager.VERBOSE) {
 				JobManager.verbose("-> failed to index " + this.folder + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
 				e.printStackTrace();
 			}
-			this.manager.removeIndex(this.indexPath);
+			this.manager.removeIndex(this.containerPath);
 			return false;
 		} finally {
 			monitor.exitRead(); // free read lock
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
index 4f6933a..ed70f8f 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
@@ -14,6 +14,7 @@
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.util.*;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -26,25 +27,33 @@
 import org.eclipse.core.resources.IWorkspace;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.search.SearchParticipant;
 import org.eclipse.jdt.internal.core.JavaModel;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.index.*;
 import org.eclipse.jdt.internal.core.index.IIndex;
+import org.eclipse.jdt.internal.core.index.IIndexer;
 import org.eclipse.jdt.internal.core.index.impl.Index;
-import org.eclipse.jdt.internal.core.search.IndexSelector;
 import org.eclipse.jdt.internal.core.search.JavaWorkspaceScope;
+import org.eclipse.jdt.internal.core.search.PatternSearchJob;
+import org.eclipse.jdt.internal.core.search.matching.TypeDeclarationPattern;
 import org.eclipse.jdt.internal.core.search.processing.IJob;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
 import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public class IndexManager extends JobManager implements IIndexConstants {
-	/* number of file contents in memory */
-	public static int MAX_FILES_IN_MEMORY = 0;
 
 	public IWorkspace workspace;
 	public SimpleLookupTable indexNames = new SimpleLookupTable();
@@ -66,6 +75,11 @@
 	public static Integer UPDATING_STATE = new Integer(1);
 	public static Integer UNKNOWN_STATE = new Integer(2);
 	public static Integer REBUILDING_STATE = new Integer(3);
+	
+	/*
+	 * A table from document path + index path (String) to indexer output (IIndexerOutput)
+	 */
+	static Hashtable indexerOutputs = new Hashtable();
 
 public synchronized void aboutToUpdateIndex(IPath path, Integer newIndexState) {
 	// newIndexState is either UPDATING_STATE or REBUILDING_STATE
@@ -90,12 +104,15 @@
  */
 public void addBinary(IFile resource, IPath indexedContainer){
 	if (JavaCore.getPlugin() == null) return;	
-	AddClassFileToIndex job = new AddClassFileToIndex(resource, indexedContainer, this);
-	if (this.awaitingJobsCount() < MAX_FILES_IN_MEMORY) {
-		// reduces the chance that the file is open later on, preventing it from being deleted
-		if (!job.initializeContents()) return;
-	}
-	request(job);
+	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
+	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
+	String indexPath = computeIndexName(indexedContainer);
+	participant.scheduleDocumentIndexing(document, indexedContainer.toString(), indexPath);
+}
+public void addIndexEntry(char[] category, char[] key, SearchDocument document, String indexPath) {
+	IIndexerOutput output = (IIndexerOutput) indexerOutputs.get(document);
+	if (output == null) return;
+	output.addRef(CharOperation.concat(category, key));
 }
 /**
  * Trigger addition of a resource to an index
@@ -103,12 +120,10 @@
  */
 public void addSource(IFile resource, IPath indexedContainer){
 	if (JavaCore.getPlugin() == null) return;	
-	AddCompilationUnitToIndex job = new AddCompilationUnitToIndex(resource, indexedContainer, this);
-	if (this.awaitingJobsCount() < MAX_FILES_IN_MEMORY) {
-		// reduces the chance that the file is open later on, preventing it from being deleted
-		if (!job.initializeContents()) return;
-	}
-	request(job);
+	SearchParticipant participant = SearchEngine.getDefaultSearchParticipant();
+	SearchDocument document = participant.getDocument(resource.getFullPath().toString());
+	String indexPath = computeIndexName(indexedContainer);
+	participant.scheduleDocumentIndexing(document, indexedContainer.toString(), indexPath);
 }
 String computeIndexName(IPath path) {
 	String name = (String) indexNames.get(path);
@@ -192,6 +207,13 @@
 	//System.out.println(" index name: " + path.toOSString() + " <----> " + index.getIndexFile().getName());	
 	return index;
 }
+public synchronized IIndex getIndexForUpdate(IPath path, boolean reuseExistingFile, boolean createIfMissing) {
+	String indexName = computeIndexName(path);
+	if (getIndexStates().get(indexName) == REBUILDING_STATE)
+		return getIndex(path, reuseExistingFile, createIfMissing);
+
+	return null; // abort the job since the index has been removed from the REBUILDING_STATE
+}
 private SimpleLookupTable getIndexStates() {
 	if (indexStates != null) return indexStates;
 
@@ -220,6 +242,21 @@
 public ReadWriteMonitor getMonitorFor(IIndex index){
 	return (ReadWriteMonitor) monitors.get(index);
 }
+public void indexDocument(final SearchDocument searchDocument, final SearchParticipant searchParticipant, final IIndex index) throws IOException {
+	index.add(searchDocument,
+		new IIndexer() {
+			public void index(SearchDocument document, IIndexerOutput output) throws IOException {
+				output.addDocument(document); // Add the name of the file to the index
+				String indexPath = index.getIndexFile().toString();
+				try {
+					indexerOutputs.put(document, output);
+					searchParticipant.indexDocument(searchDocument, indexPath);
+				} finally {
+					indexerOutputs.remove(document);
+				}
+			}
+		});
+}
 /**
  * Trigger addition of the entire content of a project
  * Note: the actual operation is performed in background 
@@ -230,7 +267,7 @@
 	// Also request indexing of binaries on the classpath
 	// determine the new children
 	try {
-		JavaModel model = (JavaModel) JavaModelManager.getJavaModelManager().getJavaModel();
+		JavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
 		IJavaProject javaProject = model.getJavaProject(project);	
 		// only consider immediate libraries - each project will do the same
 		// NOTE: force to resolve CP variables before calling indexer - 19303, so that initializers
@@ -322,7 +359,7 @@
  * Name of the background process
  */
 public String processName(){
-	return org.eclipse.jdt.internal.core.search.Util.bind("process.name"); //$NON-NLS-1$
+	return Util.bind("process.name"); //$NON-NLS-1$
 }
 private void rebuildIndex(String indexName, IPath path) {
 	Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true);
@@ -459,7 +496,7 @@
 			for (int i = this.jobEnd; i > this.jobStart; i--) { // skip the current job
 				IJob job = this.awaitingJobs[i];
 				if (job instanceof IndexRequest)
-					if (((IndexRequest) job).indexPath.equals(indexPath)) return;
+					if (((IndexRequest) job).containerPath.equals(indexPath)) return;
 			}
 		}
 	}
@@ -500,22 +537,59 @@
 	}
 	needToSave = false;
 }
+public void scheduleDocumentIndexing(final SearchDocument searchDocument, String containerPathString, final String indexPath, final SearchParticipant searchParticipant) {
+	IPath containerPath = new Path(containerPathString);
+	request(new IndexRequest(containerPath, this) {
+		public boolean execute(IProgressMonitor progressMonitor) {
+			if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
+			
+			/* ensure no concurrent write access to index */
+			IIndex index = getIndex(containerPath, true, /*reuse index file*/ true /*create if none*/);
+			if (index == null) return true;
+			ReadWriteMonitor monitor = getMonitorFor(index);
+			if (monitor == null) return true; // index got deleted since acquired
+			
+			try {
+				monitor.enterWrite(); // ask permission to write
+				indexDocument(searchDocument, searchParticipant, index);
+			} catch (IOException e) {
+				if (JobManager.VERBOSE) {
+					JobManager.verbose("-> failed to index " + searchDocument.getPath() + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
+					e.printStackTrace();
+				}
+				return false;
+			} finally {
+				monitor.exitWrite(); // free write lock
+			}
+			return true;
+		}
+		public String toString() {
+			return "indexing " + searchDocument.getPath(); //$NON-NLS-1$
+		}
+	});
+}
 public void shutdown() {
 	if (VERBOSE)
 		JobManager.verbose("Shutdown"); //$NON-NLS-1$
 
-	IndexSelector indexSelector = new IndexSelector(new JavaWorkspaceScope(), null, false, this);
-	IIndex[] selectedIndexes = indexSelector.getIndexes();
 	SimpleLookupTable knownPaths = new SimpleLookupTable();
-	for (int i = 0, max = selectedIndexes.length; i < max; i++) {
-		String path = selectedIndexes[i].getIndexFile().getAbsolutePath();
-		knownPaths.put(path, path);
+	SearchParticipant[] participants = SearchEngine.getSearchParticipants();
+	IJavaSearchScope scope = new JavaWorkspaceScope();
+	for (int i = 0, length = participants.length; i < length; i++) {
+		SearchParticipant participant = participants[i];
+		SearchPattern pattern = new TypeDeclarationPattern(null, null, null, ' ', SearchPattern.R_PATTERN_MATCH);
+		PatternSearchJob job = new PatternSearchJob(pattern, participant, scope, null);
+		IIndex[] selectedIndexes = job.getIndexes(null);
+		for (int j = 0, max = selectedIndexes.length; j < max; j++) {
+			String path = selectedIndexes[j].getIndexFile().getAbsolutePath();
+			knownPaths.put(path, path);
+		}
 	}
 
 	if (indexStates != null) {
-		Object[] indexNames = indexStates.keyTable;
-		for (int i = 0, l = indexNames.length; i < l; i++) {
-			String key = (String) indexNames[i];
+		Object[] keys = indexStates.keyTable;
+		for (int i = 0, l = keys.length; i < l; i++) {
+			String key = (String) keys[i];
 			if (key != null && !knownPaths.containsKey(key))
 				updateIndexState(key, null);
 		}
@@ -572,11 +646,11 @@
 	BufferedWriter writer = null;
 	try {
 		writer = new BufferedWriter(new FileWriter(savedIndexNamesFile));
-		Object[] indexNames = indexStates.keyTable;
+		Object[] keys = indexStates.keyTable;
 		Object[] states = indexStates.valueTable;
 		for (int i = 0, l = states.length; i < l; i++) {
 			if (states[i] == SAVED_STATE) {
-				writer.write((String) indexNames[i]);
+				writer.write((String) keys[i]);
 				writer.write('\n');
 			}
 		}
@@ -587,7 +661,9 @@
 		if (writer != null) {
 			try {
 				writer.close();
-			} catch (IOException e) {}
+			} catch (IOException e) {
+				// ignore
+			}
 		}
 	}
 	if (VERBOSE) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexRequest.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexRequest.java
index b37a50d..153e015 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexRequest.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexRequest.java
@@ -18,24 +18,26 @@
 
 public abstract class IndexRequest implements IJob {
 	protected boolean isCancelled = false;
-	protected IPath indexPath;
+	protected IPath containerPath;
 	protected IndexManager manager;
 
-	public IndexRequest(IPath indexPath, IndexManager manager) {
-		this.indexPath = indexPath;
+	public IndexRequest(IPath containerPath, IndexManager manager) {
+		this.containerPath = containerPath;
 		this.manager = manager;
 	}
-	public boolean belongsTo(String projectName) {
-		return projectName.equals(this.indexPath.segment(0));
+	public boolean belongsTo(String projectNameOrJarPath) {
+		// used to remove pending jobs because the project was deleted... not to delete index files
+		// can be found either by project name or JAR path name
+		return projectNameOrJarPath.equals(this.containerPath.segment(0))
+			|| projectNameOrJarPath.equals(this.containerPath.toString());
 	}
 	public void cancel() {
-		this.manager.jobWasCancelled(this.indexPath);
+		this.manager.jobWasCancelled(this.containerPath);
 		this.isCancelled = true;
 	}
-	public boolean isReadyToRun() {
+	public void ensureReadyToRun() {
 		// tag the index as inconsistent
-		this.manager.aboutToUpdateIndex(indexPath, updatedIndexState());
-		return true;
+		this.manager.aboutToUpdateIndex(this.containerPath, updatedIndexState());
 	}
 	/*
 	 * This code is assumed to be invoked while monitor has read lock
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/ReadWriteMonitor.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/ReadWriteMonitor.java
index 1d7575c..12092dd 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/ReadWriteMonitor.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/ReadWriteMonitor.java
@@ -32,6 +32,7 @@
 		try {
 			wait();
 		} catch(InterruptedException e){
+			// ignore
 		}
 	}
 	status++;
@@ -46,6 +47,7 @@
 		try {
 			wait();
 		} catch(InterruptedException e){
+			// ignore
 		}
 	}
 	status--;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/RemoveFolderFromIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/RemoveFolderFromIndex.java
index eb8ff5d..f650608 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/RemoveFolderFromIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/RemoveFolderFromIndex.java
@@ -16,10 +16,9 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.internal.core.Util;
 import org.eclipse.jdt.internal.core.index.IIndex;
-import org.eclipse.jdt.internal.core.index.IQueryResult;
 import org.eclipse.jdt.internal.core.search.processing.JobManager;
+import org.eclipse.jdt.internal.core.util.Util;
 
 class RemoveFolderFromIndex extends IndexRequest {
 	IPath folderPath;
@@ -34,22 +33,22 @@
 	}
 	public boolean execute(IProgressMonitor progressMonitor) {
 
-		if (progressMonitor != null && progressMonitor.isCanceled()) return true;
+		if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
 
 		/* ensure no concurrent write access to index */
-		IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ false /*create if none*/);
+		IIndex index = manager.getIndex(this.containerPath, true, /*reuse index file*/ false /*create if none*/);
 		if (index == null) return true;
 		ReadWriteMonitor monitor = manager.getMonitorFor(index);
 		if (monitor == null) return true; // index got deleted since acquired
 
 		try {
 			monitor.enterRead(); // ask permission to read
-			IQueryResult[] results = index.queryInDocumentNames(this.folderPath.toString());
+			String[] paths = index.queryInDocumentNames(this.folderPath.toString());
 			// all file names belonging to the folder or its subfolders and that are not excluded (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32607)
-			for (int i = 0, max = results == null ? 0 : results.length; i < max; i++) {
-				String documentPath = results[i].getPath();
+			for (int i = 0, max = paths == null ? 0 : paths.length; i < max; i++) {
+				String documentPath = paths[i];
 				if (this.exclusionPatterns == null || !Util.isExcluded(new Path(documentPath), this.exclusionPatterns)) {
-					manager.remove(documentPath, this.indexPath); // write lock will be acquired by the remove operation
+					manager.remove(documentPath, this.containerPath); // write lock will be acquired by the remove operation
 				}
 			}
 		} catch (IOException e) {
@@ -64,6 +63,6 @@
 		return true;
 	}
 	public String toString() {
-		return "removing " + this.folderPath + " from index " + this.indexPath; //$NON-NLS-1$ //$NON-NLS-2$
+		return "removing " + this.folderPath + " from index " + this.containerPath; //$NON-NLS-1$ //$NON-NLS-2$
 	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/RemoveFromIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/RemoveFromIndex.java
index b4c4e50..d4a1a9d 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/RemoveFromIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/RemoveFromIndex.java
@@ -20,16 +20,16 @@
 class RemoveFromIndex extends IndexRequest {
 	String resourceName;
 
-	public RemoveFromIndex(String resourceName, IPath indexPath, IndexManager manager) {
-		super(indexPath, manager);
+	public RemoveFromIndex(String resourceName, IPath containerPath, IndexManager manager) {
+		super(containerPath, manager);
 		this.resourceName = resourceName;
 	}
 	public boolean execute(IProgressMonitor progressMonitor) {
 
-		if (progressMonitor != null && progressMonitor.isCanceled()) return true;
+		if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
 
 		/* ensure no concurrent write access to index */
-		IIndex index = manager.getIndex(this.indexPath, true, /*reuse index file*/ false /*create if none*/);
+		IIndex index = manager.getIndex(this.containerPath, true, /*reuse index file*/ false /*create if none*/);
 		if (index == null) return true;
 		ReadWriteMonitor monitor = manager.getMonitorFor(index);
 		if (monitor == null) return true; // index got deleted since acquired
@@ -49,6 +49,6 @@
 		return true;
 	}
 	public String toString() {
-		return "removing " + this.resourceName + " from index " + this.indexPath; //$NON-NLS-1$ //$NON-NLS-2$
+		return "removing " + this.resourceName + " from index " + this.containerPath; //$NON-NLS-1$ //$NON-NLS-2$
 	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SaveIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SaveIndex.java
index af6cdad..b53ecf8 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SaveIndex.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SaveIndex.java
@@ -21,15 +21,15 @@
  * Save the index of a project.
  */
 public class SaveIndex extends IndexRequest {
-	public SaveIndex(IPath indexPath, IndexManager manager) {
-		super(indexPath, manager);
+	public SaveIndex(IPath containerPath, IndexManager manager) {
+		super(containerPath, manager);
 	}
 	public boolean execute(IProgressMonitor progressMonitor) {
 
-		if (progressMonitor != null && progressMonitor.isCanceled()) return true;
+		if (this.isCancelled || progressMonitor != null && progressMonitor.isCanceled()) return true;
 
 		/* ensure no concurrent write access to index */
-		IIndex index = this.manager.getIndex(this.indexPath, true /*reuse index file*/, false /*don't create if none*/);
+		IIndex index = this.manager.getIndex(this.containerPath, true /*reuse index file*/, false /*don't create if none*/);
 		if (index == null) return true;
 		ReadWriteMonitor monitor = this.manager.getMonitorFor(index);
 		if (monitor == null) return true; // index got deleted since acquired
@@ -39,7 +39,7 @@
 			this.manager.saveIndex(index);
 		} catch (IOException e) {
 			if (JobManager.VERBOSE) {
-				JobManager.verbose("-> failed to save index " + this.indexPath + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
+				JobManager.verbose("-> failed to save index " + this.containerPath + " because of the following exception:"); //$NON-NLS-1$ //$NON-NLS-2$
 				e.printStackTrace();
 			}
 			return false;
@@ -49,6 +49,6 @@
 		return true;
 	}
 	public String toString() {
-		return "saving index for " + this.indexPath; //$NON-NLS-1$
+		return "saving index for " + this.containerPath; //$NON-NLS-1$
 	}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java
index f7dbaf4..f075013 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java
@@ -10,16 +10,20 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.indexing;
 
-import java.io.IOException;
 import java.util.Locale;
 
-import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.search.SearchDocument;
 import org.eclipse.jdt.internal.compiler.SourceElementParser;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
-import org.eclipse.jdt.internal.core.index.IDocument;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.jdom.CompilationUnit;
+import org.eclipse.jdt.internal.core.search.processing.JobManager;
 
 /**
  * A SourceIndexer indexes java files using a java parser. The following items are indexed:
@@ -34,55 +38,46 @@
  * - Types;<br>
  * - Constructors.
  */
-public class SourceIndexer extends AbstractIndexer {
+public class SourceIndexer extends AbstractIndexer implements SuffixConstants {
 	
-	public static final String[] FILE_TYPES= new String[] {"java"}; //$NON-NLS-1$
 	protected DefaultProblemFactory problemFactory= new DefaultProblemFactory(Locale.getDefault());
-	IFile resourceFile;
 	
-SourceIndexer(IFile resourceFile)	{
-	this.resourceFile = resourceFile;
-}
-
-/**
- * Returns the file types the <code>IIndexer</code> handles.
- */
-
-public String[] getFileTypes(){
-	return FILE_TYPES;
-}
-protected void indexFile(IDocument document) throws IOException {
-
-	// Add the name of the file to the index
-	output.addDocument(document);
-
-	// Create a new Parser
-	SourceIndexerRequestor requestor = new SourceIndexerRequestor(this, document);
-	SourceElementParser parser = new SourceElementParser(
-		requestor, 
-		problemFactory, 
-		new CompilerOptions(JavaCore.create(this.resourceFile.getProject()).getOptions(true)), 
-		true); // index local declarations
-
-	// Launch the parser
-	char[] source = null;
-	char[] name = null;
-	try {
-		source = document.getCharContent();
-		name = document.getName().toCharArray();
-	} catch(Exception e){
+	public SourceIndexer(SearchDocument document, String indexPath)	{
+		super(document, indexPath);
 	}
-	if (source == null || name == null) return; // could not retrieve document info (e.g. resource was discarded)
-	CompilationUnit compilationUnit = new CompilationUnit(source, name);
-	try {
-		parser.parseCompilationUnit(compilationUnit, true);
-	} catch (Exception e) {
-		e.printStackTrace();
+	
+	public void indexDocument() {
+		// Create a new Parser
+		SourceIndexerRequestor requestor = new SourceIndexerRequestor(this);
+		String documentPath = this.document.getPath();
+		IPath path = new Path(documentPath);
+		IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(path.segment(0));
+		SourceElementParser parser = new SourceElementParser(
+			requestor, 
+			this.problemFactory, 
+			new CompilerOptions(JavaCore.create(project).getOptions(true)), 
+			true); // index local declarations
+	
+		// Always check javadoc while indexing
+		parser.javadocParser.checkJavadoc = true;
+		
+		// Launch the parser
+		char[] source = null;
+		char[] name = null;
+		try {
+			source = document.getCharContents();
+			name = documentPath.toCharArray();
+		} catch(Exception e){
+			// ignore
+		}
+		if (source == null || name == null) return; // could not retrieve document info (e.g. resource was discarded)
+		CompilationUnit compilationUnit = new CompilationUnit(source, name);
+		try {
+			parser.parseCompilationUnit(compilationUnit, true/*full parse*/);
+		} catch (Exception e) {
+			if (JobManager.VERBOSE) {
+				e.printStackTrace();
+			}
+		}
 	}
 }
-/**
- * Sets the document types the <code>IIndexer</code> handles.
- */
-
-public void setFileTypes(String[] fileTypes){}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
index 8446d56..29f4afe 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
@@ -13,7 +13,7 @@
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.ISourceElementRequestor;
-import org.eclipse.jdt.internal.core.index.IDocument;
+import org.eclipse.jdt.internal.core.search.processing.JobManager;
 
 /**
  * This class is used by the JavaParserIndexer. When parsing the java file, the requestor
@@ -21,20 +21,17 @@
  */
 public class SourceIndexerRequestor implements ISourceElementRequestor, IIndexConstants {
 	SourceIndexer indexer;
-	IDocument document;
 
-	char[] packageName;
+	char[] packageName = CharOperation.NO_CHAR;
 	char[][] enclosingTypeNames = new char[5][];
 	int depth = 0;
 	int methodDepth = 0;
 	
-public SourceIndexerRequestor(SourceIndexer indexer, IDocument document) {
-	super();
+public SourceIndexerRequestor(SourceIndexer indexer) {
 	this.indexer = indexer;
-	this.document= document;
 }
 /**
- * acceptConstructorReference method comment.
+ * @see ISourceElementRequestor#acceptConstructorReference(char[], int, int)
  */
 public void acceptConstructorReference(char[] typeName, int argCount, int sourcePosition) {
 	this.indexer.addConstructorReference(typeName, argCount);
@@ -47,44 +44,46 @@
 	}
 }
 /**
- * acceptFieldReference method comment.
+ * @see ISourceElementRequestor#acceptFieldReference(char[], int)
  */
 public void acceptFieldReference(char[] fieldName, int sourcePosition) {
 	this.indexer.addFieldReference(fieldName);
 }
 /**
- * acceptImport method comment.
+ * @see ISourceElementRequestor#acceptImport(int, int, char[], boolean, int)
  */
-public void acceptImport(int declarationStart, int declarationEnd, char[] name, boolean onDemand) {
+public void acceptImport(int declarationStart, int declarationEnd, char[] name, boolean onDemand, int modifiers) {
 	char[][] qualification = CharOperation.splitOn('.', CharOperation.subarray(name, 0, CharOperation.lastIndexOf('.', name)));
 	for (int i = 0, length = qualification.length; i < length; i++) {
 		this.indexer.addNameReference(qualification[i]);
 	}
 }
 /**
- * acceptLineSeparatorPositions method comment.
+ * @see ISourceElementRequestor#acceptLineSeparatorPositions(int[])
  */
 public void acceptLineSeparatorPositions(int[] positions) {
+	// implements interface method
 }
 /**
- * acceptMethodReference method comment.
+ * @see ISourceElementRequestor#acceptMethodReference(char[], int, int)
  */
 public void acceptMethodReference(char[] methodName, int argCount, int sourcePosition) {
 	this.indexer.addMethodReference(methodName, argCount);
 }
 /**
- * acceptPackage method comment.
+ * @see ISourceElementRequestor#acceptPackage(int, int, char[])
  */
 public void acceptPackage(int declarationStart, int declarationEnd, char[] name) {
 	this.packageName = name;
 }
 /**
- * acceptProblem method comment.
+ * @see ISourceElementRequestor#acceptProblem(IProblem)
  */
 public void acceptProblem(IProblem problem) {
+	// implements interface method
 }
 /**
- * acceptTypeReference method comment.
+ * @see ISourceElementRequestor#acceptTypeReference(char[][], int, int)
  */
 public void acceptTypeReference(char[][] typeName, int sourceStart, int sourceEnd) {
 	int length = typeName.length;
@@ -93,13 +92,13 @@
 	acceptTypeReference(typeName[length - 1], 0);
 }
 /**
- * acceptTypeReference method comment.
+ * @see ISourceElementRequestor#acceptTypeReference(char[], int)
  */
 public void acceptTypeReference(char[] simpleTypeName, int sourcePosition) {
 	this.indexer.addTypeReference(simpleTypeName);
 }
 /**
- * acceptUnknownReference method comment.
+ * @see ISourceElementRequestor#acceptUnknownReference(char[][], int, int)
  */
 public void acceptUnknownReference(char[][] name, int sourceStart, int sourceEnd) {
 	for (int i = 0; i < name.length; i++) {
@@ -107,7 +106,7 @@
 	}
 }
 /**
- * acceptUnknownReference method comment.
+ * @see ISourceElementRequestor#acceptUnknownReference(char[], int)
  */
 public void acceptUnknownReference(char[] name, int sourcePosition) {
 	this.indexer.addNameReference(name);
@@ -128,7 +127,7 @@
 	return qualification;
 }
 /**
- * enterClass method comment.
+ * @see ISourceElementRequestor#enterClass(int, int, char[], int, int, char[], char[][])
  */
 public void enterClass(int declarationStart, int modifiers, char[] name, int nameSourceStart, int nameSourceEnd, char[] superclass, char[][] superinterfaces) {
 
@@ -144,42 +143,43 @@
 			superinterfaces[i] = CharOperation.lastSegment(superinterfaces[i], '.');
 		}
 	}
-	char[][] enclosingTypeNames;
+	char[][] typeNames;
 	if (this.methodDepth > 0) {
-		enclosingTypeNames = ONE_ZERO_CHAR;
+		typeNames = ONE_ZERO_CHAR;
 	} else {
-		enclosingTypeNames = this.enclosingTypeNames();
+		typeNames = this.enclosingTypeNames();
 	}
-	this.indexer.addClassDeclaration(modifiers, packageName, name, enclosingTypeNames, superclass, superinterfaces);
+	this.indexer.addClassDeclaration(modifiers, this.packageName, name, typeNames, superclass, superinterfaces);
 	this.pushTypeName(name);
 }
 /**
- * enterCompilationUnit method comment.
+ * @see ISourceElementRequestor#enterCompilationUnit()
  */
 public void enterCompilationUnit() {
+	// implements interface method
 }
 /**
- * enterConstructor method comment.
+ * @see ISourceElementRequestor#enterConstructor(int, int, char[], int, int, char[][], char[][], char[][])
  */
 public void enterConstructor(int declarationStart, int modifiers, char[] name, int nameSourceStart, int nameSourceEnd, char[][] parameterTypes, char[][] parameterNames, char[][] exceptionTypes) {
 	this.indexer.addConstructorDeclaration(name, parameterTypes, exceptionTypes);
 	this.methodDepth++;
 }
 /**
- * enterField method comment.
+ * @see ISourceElementRequestor#enterField(int, int, char[], char[], int, int)
  */
 public void enterField(int declarationStart, int modifiers, char[] type, char[] name, int nameSourceStart, int nameSourceEnd) {
 	this.indexer.addFieldDeclaration(type, name);
 	this.methodDepth++;
 }
 /**
- * enterInitializer method comment.
+ * @see ISourceElementRequestor#enterInitializer(int, int)
  */
 public void enterInitializer(int declarationSourceStart, int modifiers) {
 	this.methodDepth++;
 }
 /**
- * enterInterface method comment.
+ * @see ISourceElementRequestor#enterInterface(int, int, char[], int, int, char[][])
  */
 public void enterInterface(int declarationStart, int modifiers, char[] name, int nameSourceStart, int nameSourceEnd, char[][] superinterfaces) {
 	// eliminate possible qualifications, given they need to be fully resolved again
@@ -188,68 +188,71 @@
 			superinterfaces[i] = CharOperation.lastSegment(superinterfaces[i], '.');
 		}
 	}	
-	char[][] enclosingTypeNames;
+	char[][] typeNames;
 	if (this.methodDepth > 0) {
-		enclosingTypeNames = ONE_ZERO_CHAR;
+		typeNames = ONE_ZERO_CHAR;
 	} else {
-		enclosingTypeNames = this.enclosingTypeNames();
+		typeNames = this.enclosingTypeNames();
 	}
-	this.indexer.addInterfaceDeclaration(modifiers, packageName, name, enclosingTypeNames, superinterfaces);
+	this.indexer.addInterfaceDeclaration(modifiers, packageName, name, typeNames, superinterfaces);
 	this.pushTypeName(name);	
 }
 /**
- * enterMethod method comment.
+ * @see ISourceElementRequestor#enterMethod(int, int, char[], char[], int, int, char[][], char[][], char[][])
  */
 public void enterMethod(int declarationStart, int modifiers, char[] returnType, char[] name, int nameSourceStart, int nameSourceEnd, char[][] parameterTypes, char[][] parameterNames, char[][] exceptionTypes) {
 	this.indexer.addMethodDeclaration(name, parameterTypes, returnType, exceptionTypes);
 	this.methodDepth++;
 }
 /**
- * exitClass method comment.
+ * @see ISourceElementRequestor#exitClass(int)
  */
 public void exitClass(int declarationEnd) {
 	popTypeName();
 }
 /**
- * exitCompilationUnit method comment.
+ * @see ISourceElementRequestor#exitCompilationUnit(int)
  */
 public void exitCompilationUnit(int declarationEnd) {
+	// implements interface method
 }
 /**
- * exitConstructor method comment.
+ * @see ISourceElementRequestor#exitConstructor(int)
  */
 public void exitConstructor(int declarationEnd) {
 	this.methodDepth--;
 }
 /**
- * exitField method comment.
+ * @see ISourceElementRequestor#exitField(int, int, int)
  */
 public void exitField(int initializationStart, int declarationEnd, int declarationSourceEnd) {
 	this.methodDepth--;
 }
 /**
- * exitInitializer method comment.
+ * @see ISourceElementRequestor#exitInitializer(int)
  */
 public void exitInitializer(int declarationEnd) {
 	this.methodDepth--;
 }
 /**
- * exitInterface method comment.
+ * @see ISourceElementRequestor#exitInterface(int)
  */
 public void exitInterface(int declarationEnd) {
 	popTypeName();	
 }
 /**
- * exitMethod method comment.
+ * @see ISourceElementRequestor#exitMethod(int)
  */
 public void exitMethod(int declarationEnd) {
 	this.methodDepth--;
 }
 public void popTypeName(){
 	try {
-	enclosingTypeNames[--depth] = null;
+		enclosingTypeNames[--depth] = null;
 	} catch (ArrayIndexOutOfBoundsException e) {
-		e.printStackTrace();
+		if (JobManager.VERBOSE) {
+			e.printStackTrace();
+		}
 	}
 }
 public void pushTypeName(char[] typeName){
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/AndPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/AndPattern.java
index 2ae7193..96ce69d 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/AndPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/AndPattern.java
@@ -14,44 +14,55 @@
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.internal.core.index.impl.EntryResult;
 import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
+import org.eclipse.jdt.internal.core.index.impl.IndexedFile;
+import org.eclipse.jdt.internal.core.search.IndexQueryRequestor;
 
 /**
  * Query the index multiple times and do an 'and' on the results.
  */
-public abstract class AndPattern extends SearchPattern {
-public AndPattern(int matchMode, boolean isCaseSensitive) {
-	super(matchMode, isCaseSensitive);
+public abstract class AndPattern extends SearchPattern { // TODO should rename IntersectingPattern, and make AndPattern a true subclass
+	
+public AndPattern(int patternKind, int matchRule) {
+	super(patternKind, matchRule);
 }
+
 /**
  * Query a given index for matching entries. 
  */
-public void findIndexMatches(IndexInput input, IIndexSearchRequestor requestor, int detailLevel, IProgressMonitor progressMonitor, IJavaSearchScope scope) throws IOException {
+protected void findIndexMatches(IndexInput input, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope, IProgressMonitor progressMonitor, char[] queryKey, char[] category) throws IOException {
 
 	if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
 	
 	/* narrow down a set of entries using prefix criteria */
-	long[] potentialRefs = null;
+	long[] possibleRefs = null;
 	int maxRefs = -1;
 	this.resetQuery();
+	SearchPattern indexRecord = null;
 	do {
-		IEntryResult[] entries = input.queryEntriesPrefixedBy(indexEntryPrefix());
+		queryKey = encodeIndexKey();
+		char[] pattern = CharOperation.concat(category, queryKey);
+		EntryResult[] entries = input.queryEntries(pattern, SearchPattern.R_PREFIX_MATCH);
 		if (entries == null) break;
 
 		int numFiles = input.getNumFiles();
 		long[] references = null;
 		int referencesLength = -1;
-		for (int i = 0, max = entries.length; i < max; i++){
-
+		for (int i = 0, max = entries.length; i < max; i++) {
 			if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
 
 			/* retrieve and decode entry */	
-			IEntryResult entry = entries[i];
-			decodeIndexEntry(entry);
-			if (matchIndexEntry()) {
+			EntryResult entry = entries[i];
+			char[] word = entry.getWord();
+			char[] indexKey = CharOperation.subarray(word, category.length, word.length);
+			indexRecord = getIndexRecord();
+			indexRecord.decodeIndexKey(indexKey);
+			if (isMatchingIndexRecord()) {
 				/* accumulate references in an array of bits : 1 if the reference is present, 0 otherwise */
 				int[] fileReferences = entry.getFileReferences();
 				for (int j = 0, refLength = fileReferences.length; j < refLength; j++) {
@@ -68,40 +79,49 @@
 		}
 		
 		/* only select entries which actually match the entire search pattern */
-		if (references == null) {
-			/* no references */
-			return;
+		if (references == null) return;
+		if (possibleRefs == null) {
+			/* first query : these are the possible references */
+			possibleRefs = references;
+			maxRefs = numFiles;
 		} else {
-			if (potentialRefs == null) {
-				/* first query : these are the potential references */
-				potentialRefs = references;
-				maxRefs = numFiles;
-			} else {
-				/* eliminate potential references that don't match the current references */
-				for (int i = 0, length = references.length; i < length; i++) {
-					if (i < potentialRefs.length) {
-						potentialRefs[i] &= references[i];
-					} else {
-						potentialRefs[i] = 0;
-					}
-				}
-			}				
+			/* eliminate possible references that don't match the current references */
+			int possibleLength = possibleRefs.length;
+			for (int i = 0, length = references.length; i < length; i++) {
+				if (i < possibleLength)
+					possibleRefs[i] &= references[i];
+				else
+					possibleRefs[i] = 0;
+			}
+			// check to see that there are still possible references after the merge
+			while (--possibleLength >= 0 && possibleRefs[possibleLength] == 0);
+			if (possibleLength == -1) return;
 		}
 	} while (this.hasNextQuery());
 
-	/* report potential references that remain */
-	if (potentialRefs != null) {
+	/* report possible references that remain */
+	if (possibleRefs != null) {
 		int[] refs = new int[maxRefs];
 		int refsLength = 0;
 		for (int reference = 1; reference <= maxRefs; reference++) {
 			int vectorIndex = reference / 64; // a long has 64 bits
-			if ((potentialRefs[vectorIndex] & (1L << (reference % 64))) != 0) {
+			if ((possibleRefs[vectorIndex] & (1L << (reference % 64))) != 0)
 				refs[refsLength++] = reference;
-			}
-						
 		}
 		System.arraycopy(refs, 0, refs = new int[refsLength], 0, refsLength);
-		this.feedIndexRequestor(requestor, detailLevel, refs, input, scope);
+		for (int i = 0; i < refsLength; i++) { // TODO (jerome) merge with previous loop
+			int reference = refs[i];
+			if (reference != -1) { // if the reference has not been eliminated
+				IndexedFile file = input.getIndexedFile(reference);
+				if (file != null) {
+					String documentPath = IndexedFile.convertPath(file.getPath());
+					if (scope.encloses(documentPath)) {
+						if (!requestor.acceptIndexMatch(documentPath, indexRecord, participant)) 
+							throw new OperationCanceledException();
+					}
+				}
+			}
+		}
 	}
 }
 /**
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java
new file mode 100644
index 0000000..1c025f3
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java
@@ -0,0 +1,251 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
+import org.eclipse.jdt.internal.compiler.env.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
+
+public class ClassFileMatchLocator implements IIndexConstants {
+
+public static char[] convertClassFileFormat(char[] name) {
+	for (int i = 0, l = name.length; i < l; i++) {
+		if (name[i] == '/') {
+			char[] newName = (char[]) name.clone();
+			CharOperation.replace(newName, '/', '.');
+			return newName;
+		}
+	}
+	return name;
+}
+
+boolean checkDeclaringType(IBinaryType enclosingBinaryType, char[] simpleName, char[] qualification, boolean isCaseSensitive) {
+	if (simpleName == null && qualification == null) return true;
+	if (enclosingBinaryType == null) return true;
+
+	char[] declaringTypeName = convertClassFileFormat(enclosingBinaryType.getName());
+	return checkTypeName(simpleName, qualification, declaringTypeName, isCaseSensitive);
+}
+boolean checkParameters(char[] methodDescriptor, char[][] parameterSimpleNames, char[][] parameterQualifications, boolean isCaseSensitive) {
+	char[][] arguments = Signature.getParameterTypes(methodDescriptor);
+	int parameterCount = parameterSimpleNames.length;
+	if (parameterCount != arguments.length) return false;
+	for (int i = 0; i < parameterCount; i++)
+		if (!checkTypeName(parameterSimpleNames[i], parameterQualifications[i], Signature.toCharArray(arguments[i]), isCaseSensitive))
+			return false;
+	return true;
+}
+boolean checkTypeName(char[] simpleName, char[] qualification, char[] fullyQualifiedTypeName, boolean isCaseSensitive) {
+	// NOTE: if case insensitive then simpleName & qualification are assumed to be lowercase
+	char[] wildcardPattern = PatternLocator.qualifiedPattern(simpleName, qualification);
+	if (wildcardPattern == null) return true;
+	return CharOperation.match(wildcardPattern, fullyQualifiedTypeName, isCaseSensitive);
+}
+/**
+ * Locate declaration in the current class file. This class file is always in a jar.
+ */
+public void locateMatches(MatchLocator locator, ClassFile classFile, IBinaryType info) throws CoreException {
+	// check class definition
+	SearchPattern pattern = locator.pattern;
+	BinaryType binaryType = (BinaryType) classFile.getType();
+	if (matchBinary(pattern, info, null))
+		locator.reportBinaryMatch(null, binaryType, info, IJavaSearchResultCollector.EXACT_MATCH);
+
+	int accuracy = IJavaSearchResultCollector.EXACT_MATCH;
+	if (pattern.mustResolve) {
+		try {
+			BinaryTypeBinding binding = locator.cacheBinaryType(binaryType);
+			if (binding != null) {
+				// filter out element not in hierarchy scope
+				if (!locator.typeInHierarchy(binding)) return;
+
+				MethodBinding[] methods = binding.methods();
+				for (int i = 0, l = methods.length; i < l; i++) {
+					MethodBinding method = methods[i];
+					if (locator.patternLocator.resolveLevel(method) == PatternLocator.ACCURATE_MATCH) {
+						IMethod methodHandle = binaryType.getMethod(
+							new String(method.isConstructor() ? binding.compoundName[binding.compoundName.length-1] : method.selector),
+							CharOperation.toStrings(Signature.getParameterTypes(convertClassFileFormat(method.signature()))));
+						locator.reportBinaryMatch(null, methodHandle, info, IJavaSearchResultCollector.EXACT_MATCH);
+					}
+				}
+
+				FieldBinding[] fields = binding.fields();
+				for (int i = 0, l = fields.length; i < l; i++) {
+					FieldBinding field = fields[i];
+					if (locator.patternLocator.resolveLevel(field) == PatternLocator.ACCURATE_MATCH) {
+						IField fieldHandle = binaryType.getField(new String(field.name));
+						locator.reportBinaryMatch(null, fieldHandle, info, IJavaSearchResultCollector.EXACT_MATCH);
+					}
+				}
+
+				// no need to check binary info since resolve was successful
+				return;
+			}
+		} catch (AbortCompilation e) { // if compilation was aborted it is a problem with the class path
+		}
+		// report as a potential match if binary info matches the pattern		
+		accuracy = IJavaSearchResultCollector.POTENTIAL_MATCH;
+	}
+
+	IBinaryMethod[] methods = info.getMethods();
+	if (methods != null) {
+		for (int i = 0, l = methods.length; i < l; i++) {
+			IBinaryMethod method = methods[i];
+			if (matchBinary(pattern, method, info)) {
+				IMethod methodHandle = binaryType.getMethod(
+					new String(method.isConstructor() ? info.getName() : method.getSelector()),
+					CharOperation.toStrings(Signature.getParameterTypes(convertClassFileFormat(method.getMethodDescriptor()))));
+				locator.reportBinaryMatch(null, methodHandle, info, accuracy);
+			}
+		}
+	}
+
+	IBinaryField[] fields = info.getFields();
+	if (fields != null) {
+		for (int i = 0, l = fields.length; i < l; i++) {
+			IBinaryField field = fields[i];
+			if (matchBinary(pattern, field, info)) {
+				IField fieldHandle = binaryType.getField(new String(field.getName()));
+				locator.reportBinaryMatch(null, fieldHandle, info, accuracy);
+			}
+		}
+	}
+}
+/**
+ * Finds out whether the given binary info matches the search pattern.
+ * Default is to return false.
+ */
+boolean matchBinary(SearchPattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
+	switch (pattern.kind) {
+		case CONSTRUCTOR_PATTERN :
+			return matchConstructor((ConstructorPattern) pattern, binaryInfo, enclosingBinaryType);
+		case FIELD_PATTERN :
+			return matchField((FieldPattern) pattern, binaryInfo, enclosingBinaryType);
+		case METHOD_PATTERN :
+			return matchMethod((MethodPattern) pattern, binaryInfo, enclosingBinaryType);
+		case SUPER_REF_PATTERN :
+			return matchSuperTypeReference((SuperTypeReferencePattern) pattern, binaryInfo, enclosingBinaryType);
+		case TYPE_DECL_PATTERN :
+			return matchTypeDeclaration((TypeDeclarationPattern) pattern, binaryInfo, enclosingBinaryType);
+		case OR_PATTERN :
+			SearchPattern[] patterns = ((OrPattern) pattern).patterns;
+			for (int i = 0, length = patterns.length; i < length; i++)
+				if (matchBinary(patterns[i], binaryInfo, enclosingBinaryType)) return true;
+	}
+	return false;
+}
+boolean matchConstructor(ConstructorPattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
+	if (!pattern.findDeclarations) return false; // only relevant when finding declarations
+	if (!(binaryInfo instanceof IBinaryMethod)) return false;
+
+	IBinaryMethod method = (IBinaryMethod) binaryInfo;
+	if (!method.isConstructor()) return false;
+	if (!checkDeclaringType(enclosingBinaryType, pattern.declaringSimpleName, pattern.declaringQualification, pattern.isCaseSensitive()))
+		return false;
+	if (pattern.parameterSimpleNames != null) {
+		char[] methodDescriptor = convertClassFileFormat(method.getMethodDescriptor());
+		if (!checkParameters(methodDescriptor, pattern.parameterSimpleNames, pattern.parameterQualifications, pattern.isCaseSensitive()))
+			return false;
+	}
+	return true;
+}
+boolean matchField(FieldPattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
+	if (!pattern.findDeclarations) return false; // only relevant when finding declarations
+	if (!(binaryInfo instanceof IBinaryField)) return false;
+
+	IBinaryField field = (IBinaryField) binaryInfo;
+	if (!pattern.matchesName(pattern.name, field.getName())) return false;
+	if (!checkDeclaringType(enclosingBinaryType, pattern.declaringSimpleName, pattern.declaringQualification, pattern.isCaseSensitive()))
+		return false;
+
+	char[] fieldTypeSignature = Signature.toCharArray(convertClassFileFormat(field.getTypeName()));
+	return checkTypeName(pattern.typeSimpleName, pattern.typeQualification, fieldTypeSignature, pattern.isCaseSensitive());
+}
+boolean matchMethod(MethodPattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
+	if (!pattern.findDeclarations) return false; // only relevant when finding declarations
+	if (!(binaryInfo instanceof IBinaryMethod)) return false;
+
+	IBinaryMethod method = (IBinaryMethod) binaryInfo;
+	if (!pattern.matchesName(pattern.selector, method.getSelector())) return false;
+	if (!checkDeclaringType(enclosingBinaryType, pattern.declaringSimpleName, pattern.declaringQualification, pattern.isCaseSensitive()))
+		return false;
+
+	// look at return type only if declaring type is not specified
+	boolean checkReturnType = pattern.declaringSimpleName == null && (pattern.returnSimpleName != null || pattern.returnQualification != null);
+	boolean checkParameters = pattern.parameterSimpleNames != null;
+	if (checkReturnType || checkParameters) {
+		char[] methodDescriptor = convertClassFileFormat(method.getMethodDescriptor());
+		if (checkReturnType) {
+			char[] returnTypeSignature = Signature.toCharArray(Signature.getReturnType(methodDescriptor));
+			if (!checkTypeName(pattern.returnSimpleName, pattern.returnQualification, returnTypeSignature, pattern.isCaseSensitive()))
+				return false;
+		}
+		if (checkParameters &&  !checkParameters(methodDescriptor, pattern.parameterSimpleNames, pattern.parameterQualifications, pattern.isCaseSensitive()))
+			return false;
+	}
+	return true;
+}
+boolean matchSuperTypeReference(SuperTypeReferencePattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
+	if (!(binaryInfo instanceof IBinaryType)) return false;
+
+	IBinaryType type = (IBinaryType) binaryInfo;
+	if (!pattern.checkOnlySuperinterfaces) {
+		char[] vmName = type.getSuperclassName();
+		if (vmName != null) {
+			char[] superclassName = convertClassFileFormat(vmName);
+			if (checkTypeName(pattern.superSimpleName, pattern.superQualification, superclassName, pattern.isCaseSensitive()))
+				return true;
+		}
+	}
+
+	char[][] superInterfaces = type.getInterfaceNames();
+	if (superInterfaces != null) {
+		for (int i = 0, max = superInterfaces.length; i < max; i++) {
+			char[] superInterfaceName = convertClassFileFormat(superInterfaces[i]);
+			if (checkTypeName(pattern.superSimpleName, pattern.superQualification, superInterfaceName, pattern.isCaseSensitive()))
+				return true;
+		}
+	}
+	return false;
+}
+boolean matchTypeDeclaration(TypeDeclarationPattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
+	if (!(binaryInfo instanceof IBinaryType)) return false;
+
+	IBinaryType type = (IBinaryType) binaryInfo;
+	char[] fullyQualifiedTypeName = convertClassFileFormat(type.getName());
+	if (pattern.enclosingTypeNames == null || pattern instanceof QualifiedTypeDeclarationPattern) {
+		if (!checkTypeName(pattern.simpleName, pattern.pkg, fullyQualifiedTypeName, pattern.isCaseSensitive())) return false;
+	} else {
+		char[] enclosingTypeName = CharOperation.concatWith(pattern.enclosingTypeNames, '.');
+		char[] patternString = pattern.pkg == null
+			? enclosingTypeName
+			: CharOperation.concat(pattern.pkg, enclosingTypeName, '.');
+		if (!checkTypeName(pattern.simpleName, patternString, fullyQualifiedTypeName, pattern.isCaseSensitive())) return false;
+	}
+
+	switch (pattern.classOrInterface) {
+		case CLASS_SUFFIX:
+			return !type.isInterface();
+		case INTERFACE_SUFFIX:
+			return type.isInterface();
+		case TYPE_SUFFIX: // nothing
+	}
+	return true;
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
index 82781d1..b43713f 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
@@ -16,7 +16,6 @@
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
-import org.eclipse.jdt.internal.core.Util;
 import org.eclipse.jdt.internal.core.builder.ClasspathLocation;
 import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
 
@@ -54,7 +53,7 @@
 			for (int i = 0, l = members.length; i < l; i++) {
 				IResource m = members[i];
 				String name;
-				if (m.getType() == IResource.FILE && Util.isJavaFileName(name = m.getName()))
+				if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.compiler.util.Util.isJavaFileName(name = m.getName()))
 					dirList[index++] = name;
 			}
 			if (index < dirList.length)
@@ -63,6 +62,7 @@
 			return dirList;
 		}
 	} catch(CoreException ignored) {
+		// treat as if missing
 	}
 	directoryCache.put(qualifiedPackageName, missingPackageHolder);
 	return null;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorDeclarationPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorDeclarationPattern.java
deleted file mode 100644
index ab3b91e..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorDeclarationPattern.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.io.IOException;
-
-import org.eclipse.jdt.core.Signature;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.indexing.AbstractIndexer;
-
-/**
- * The selector is unused, the constructor name is specified by the type simple name.
- */ 
-public class ConstructorDeclarationPattern extends MethodDeclarationPattern {
-
-	private char[] decodedTypeName;	
-public ConstructorDeclarationPattern(char[] declaringSimpleName, int matchMode, boolean isCaseSensitive, char[] declaringQualification, char[][] parameterQualifications, char[][] parameterSimpleNames) {
-	super(null, matchMode, isCaseSensitive, declaringQualification, declaringSimpleName, null, null, parameterQualifications, parameterSimpleNames);
-}
-public void decodeIndexEntry(IEntryResult entryResult){
-
-	char[] word = entryResult.getWord();
-	int size = word.length;
-	int lastSeparatorIndex = CharOperation.lastIndexOf(SEPARATOR, word);	
-
-	decodedParameterCount = Integer.parseInt(new String(word, lastSeparatorIndex + 1, size - lastSeparatorIndex - 1));
-	decodedTypeName = CharOperation.subarray(word, CONSTRUCTOR_DECL.length, lastSeparatorIndex);
-}
-/**
- * see SearchPattern.feedIndexRequestor
- */
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope) throws IOException {
-	for (int i = 0, max = references.length; i < max; i++) {
-		IndexedFile file = input.getIndexedFile(references[i]);
-		String path;
-		if (file != null && scope.encloses(path = IndexedFile.convertPath(file.getPath()))) {
-			requestor.acceptConstructorDeclaration(path, decodedTypeName, decodedParameterCount);
-		}
-	}
-}
-/**
- * @see SearchPattern#indexEntryPrefix
- */
-public char[] indexEntryPrefix() {
-
-	return AbstractIndexer.bestConstructorDeclarationPrefix(
-			declaringSimpleName, 
-			parameterSimpleNames == null ? -1 : parameterSimpleNames.length, 
-			matchMode, 
-			isCaseSensitive);
-}
-/**
- * @see SearchPattern#matchesBinary(Object, Object)
- */
-public boolean matchesBinary(Object binaryInfo, Object enclosingBinaryInfo) {
-	if (!(binaryInfo instanceof IBinaryMethod)) return false;
-
-	IBinaryMethod method = (IBinaryMethod)binaryInfo;
-	
-	// must be a constructor
-	if (!method.isConstructor()) return false;
-
-	// declaring type
-	IBinaryType declaringType = (IBinaryType)enclosingBinaryInfo;
-	if (declaringType != null) {
-		char[] declaringTypeName = (char[])declaringType.getName().clone();
-		CharOperation.replace(declaringTypeName, '/', '.');
-		if (!this.matchesType(this.declaringSimpleName, this.declaringQualification, declaringTypeName)) {
-			return false;
-		}
-	}
-
-	// parameter types
-	int parameterCount = this.parameterSimpleNames == null ? -1 : this.parameterSimpleNames.length;
-	if (parameterCount > -1) {
-		String methodDescriptor = new String(method.getMethodDescriptor()).replace('/', '.');
-		String[] arguments = Signature.getParameterTypes(methodDescriptor);
-		int argumentCount = arguments.length;
-		if (parameterCount != argumentCount)
-			return false;
-		for (int i = 0; i < parameterCount; i++) {
-			char[] qualification = this.parameterQualifications[i];
-			char[] type = this.parameterSimpleNames[i];
-			if (!this.matchesType(type, qualification,  Signature.toString(arguments[i]).toCharArray()))
-				return false;
-		}
-	}
-
-	return true;
-}
-/**
- * @see SearchPattern#matchIndexEntry
- */
-protected boolean matchIndexEntry() {
-
-	/* check selector matches */
-	if (declaringSimpleName != null){
-		switch(matchMode){
-			case EXACT_MATCH :
-				if (!CharOperation.equals(declaringSimpleName, decodedTypeName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PREFIX_MATCH :
-				if (!CharOperation.prefixEquals(declaringSimpleName, decodedTypeName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PATTERN_MATCH :
-				if (!CharOperation.match(declaringSimpleName, decodedTypeName, isCaseSensitive)){
-					return false;
-				}
-		}
-	}
-	if (parameterSimpleNames != null){
-		if (parameterSimpleNames.length != decodedParameterCount) return false;
-	}
-	return true;
-}
-public String toString(){
-
-	StringBuffer buffer = new StringBuffer(20);
-	buffer.append("ConstructorDeclarationPattern: "); //$NON-NLS-1$
-	if (declaringQualification != null) buffer.append(declaringQualification).append('.');
-	if (declaringSimpleName != null) 
-		buffer.append(declaringSimpleName);
-	else if (declaringQualification != null) buffer.append("*"); //$NON-NLS-1$
-
-	buffer.append('(');
-	if (parameterSimpleNames == null) {
-		buffer.append("..."); //$NON-NLS-1$
-	} else {
-		for (int i = 0, max = parameterSimpleNames.length; i < max; i++){
-			if (i > 0) buffer.append(", "); //$NON-NLS-1$
-			if (parameterQualifications[i] != null) buffer.append(parameterQualifications[i]).append('.');
-			if (parameterSimpleNames[i] == null) buffer.append('*'); else buffer.append(parameterSimpleNames[i]);
-		}
-	}
-	buffer.append(')');
-	buffer.append(", "); //$NON-NLS-1$
-	switch(matchMode){
-		case EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	if (isCaseSensitive)
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
-	return buffer.toString();
-}
-
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
- */
-public int matchLevel(AstNode node, boolean resolve) {
-	if (!(node instanceof ConstructorDeclaration)) return IMPOSSIBLE_MATCH;
-
-	ConstructorDeclaration constructor = (ConstructorDeclaration)node;
-
-	if (resolve) {
-		return this.matchLevel(constructor.binding);
-	} else {
-		// constructor name is stored in selector field
-		if (this.declaringSimpleName != null 
-				&& !this.matchesName(this.declaringSimpleName, constructor.selector))
-			return IMPOSSIBLE_MATCH;
-			
-		// parameter types
-		int parameterCount = this.parameterSimpleNames == null ? -1 : this.parameterSimpleNames.length;
-		if (parameterCount > -1) {
-			int argumentCount = constructor.arguments == null ? 0 : constructor.arguments.length;
-			if (parameterCount != argumentCount)
-				return IMPOSSIBLE_MATCH;
-		}
-
-		return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-	}
-}
-
-/**
- * @see SearchPattern#matchLevel(Binding)
- */
-public int matchLevel(Binding binding) {
-	if (binding == null) return INACCURATE_MATCH;
-	if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH;
-	int level;
-
-	MethodBinding constructor = (MethodBinding)binding;
-	
-	// must be a constructor
-	if (!constructor.isConstructor()) return IMPOSSIBLE_MATCH;
-
-	// declaring type
-	ReferenceBinding declaringType = constructor.declaringClass;
-	if (!constructor.isStatic() && !constructor.isPrivate()) {
-		level = this.matchLevelAsSubtype(declaringType, this.declaringSimpleName, this.declaringQualification);
-	} else {
-		level = this.matchLevelForType(this.declaringSimpleName, this.declaringQualification, declaringType);
-	}
-	if (level == IMPOSSIBLE_MATCH) {
-		return IMPOSSIBLE_MATCH;
-	}
-		
-	// parameter types
-	int parameterCount = this.parameterSimpleNames == null ? -1 : this.parameterSimpleNames.length;
-	if (parameterCount > -1) {
-		int argumentCount = constructor.parameters == null ? 0 : constructor.parameters.length;
-		if (parameterCount != argumentCount)
-			return IMPOSSIBLE_MATCH;
-		for (int i = 0; i < parameterCount; i++) {
-			char[] qualification = this.parameterQualifications[i];
-			char[] type = this.parameterSimpleNames[i];
-			int newLevel = this.matchLevelForType(type, qualification, constructor.parameters[i]);
-			switch (newLevel) {
-				case IMPOSSIBLE_MATCH:
-					return IMPOSSIBLE_MATCH;
-				case ACCURATE_MATCH: // keep previous level
-					break;
-				default: // ie. INACCURATE_MATCH
-					level = newLevel;
-					break;
-			}
-		}
-	}
-
-	return level;
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
new file mode 100644
index 0000000..e45244d
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+
+public class ConstructorLocator extends PatternLocator {
+
+protected ConstructorPattern pattern;
+
+public ConstructorLocator(ConstructorPattern pattern) {
+	super(pattern);
+
+	this.pattern = pattern;
+}
+public int match(ASTNode node, MatchingNodeSet nodeSet) { // interested in ExplicitConstructorCall
+	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
+	if (!(node instanceof ExplicitConstructorCall)) return IMPOSSIBLE_MATCH;
+
+	if (this.pattern.parameterSimpleNames != null) {
+		int length = this.pattern.parameterSimpleNames.length;
+		Expression[] args = ((ExplicitConstructorCall) node).arguments;
+		int argsLength = args == null ? 0 : args.length;
+		if (length != argsLength) return IMPOSSIBLE_MATCH;
+	}
+
+	return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+}
+public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) {
+	int referencesLevel = this.pattern.findReferences ? matchLevelForReferences(node) : IMPOSSIBLE_MATCH;
+	int declarationsLevel = this.pattern.findDeclarations ? matchLevelForDeclarations(node) : IMPOSSIBLE_MATCH;
+
+	return nodeSet.addMatch(node, referencesLevel >= declarationsLevel ? referencesLevel : declarationsLevel); // use the stronger match
+}
+public int match(Expression node, MatchingNodeSet nodeSet) { // interested in AllocationExpression
+	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
+	if (!(node instanceof AllocationExpression)) return IMPOSSIBLE_MATCH;
+
+	// constructor name is simple type name
+	AllocationExpression allocation = (AllocationExpression) node;
+	char[][] typeName = allocation.type.getTypeName();
+	if (this.pattern.declaringSimpleName != null && !matchesName(this.pattern.declaringSimpleName, typeName[typeName.length-1]))
+		return IMPOSSIBLE_MATCH;
+
+	if (this.pattern.parameterSimpleNames != null) {
+		int length = this.pattern.parameterSimpleNames.length;
+		Expression[] args = allocation.arguments;
+		int argsLength = args == null ? 0 : args.length;
+		if (length != argsLength) return IMPOSSIBLE_MATCH;
+	}
+
+	return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+}
+//public int match(FieldDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(MethodDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(MessageSend node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(Reference node, MatchingNodeSet nodeSet) - SKIP IT
+public int match(TypeDeclaration node, MatchingNodeSet nodeSet) {
+	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
+
+	// need to look for a generated default constructor
+	return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+}
+//public int match(TypeReference node, MatchingNodeSet nodeSet) - SKIP IT
+
+protected int matchContainer() {
+	if (this.pattern.findReferences) return ALL_CONTAINER; // handles both declarations + references & just references
+	// COMPILATION_UNIT_CONTAINER - implicit constructor call: case of Y extends X and Y doesn't define any constructor
+	// CLASS_CONTAINER - implicit constructor call: case of constructor declaration with no explicit super call
+	// METHOD_CONTAINER - reference in another constructor
+	// FIELD_CONTAINER - anonymous in a field initializer
+
+	// declarations are only found in Class
+	return CLASS_CONTAINER;
+}
+protected int matchLevelForReferences(ConstructorDeclaration constructor) {
+	ExplicitConstructorCall constructorCall = constructor.constructorCall;
+	if (constructorCall == null || constructorCall.accessMode != ExplicitConstructorCall.ImplicitSuper)
+		return IMPOSSIBLE_MATCH;
+
+	if (this.pattern.parameterSimpleNames != null) {
+		int length = this.pattern.parameterSimpleNames.length;
+		Expression[] args = constructorCall.arguments;
+		int argsLength = args == null ? 0 : args.length;
+		if (length != argsLength) return IMPOSSIBLE_MATCH;
+	}
+	return this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
+}
+protected int matchLevelForDeclarations(ConstructorDeclaration constructor) {
+	// constructor name is stored in selector field
+	if (this.pattern.declaringSimpleName != null && !matchesName(this.pattern.declaringSimpleName, constructor.selector))
+		return IMPOSSIBLE_MATCH;
+
+	if (this.pattern.parameterSimpleNames != null) {
+		int length = this.pattern.parameterSimpleNames.length;
+		Argument[] args = constructor.arguments;
+		int argsLength = args == null ? 0 : args.length;
+		if (length != argsLength) return IMPOSSIBLE_MATCH;
+
+		for (int i = 0; i < length; i++)
+			if (!matchesTypeReference(this.pattern.parameterSimpleNames[i], args[i].type))
+				return IMPOSSIBLE_MATCH;
+	}
+
+	return this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
+}
+public int resolveLevel(ASTNode node) {
+	if (this.pattern.findReferences) {
+		if (node instanceof AllocationExpression)
+			return resolveLevel((AllocationExpression) node);
+		if (node instanceof ExplicitConstructorCall)
+			return resolveLevel(((ExplicitConstructorCall) node).binding);
+		if (node instanceof TypeDeclaration)
+			return resolveLevel((TypeDeclaration) node);
+	}
+	if (node instanceof ConstructorDeclaration)
+		return resolveLevel((ConstructorDeclaration) node, true);
+	return IMPOSSIBLE_MATCH;
+}
+protected int resolveLevel(AllocationExpression allocation) {
+	// constructor name is simple type name
+	char[][] typeName = allocation.type.getTypeName();
+	if (this.pattern.declaringSimpleName != null && !matchesName(this.pattern.declaringSimpleName, typeName[typeName.length-1]))
+		return IMPOSSIBLE_MATCH;
+
+	return resolveLevel(allocation.binding);
+}
+public int resolveLevel(Binding binding) {
+	if (binding == null) return INACCURATE_MATCH;
+	if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH;
+
+	MethodBinding method = (MethodBinding) binding;
+	if (!method.isConstructor()) return IMPOSSIBLE_MATCH;
+
+	// declaring type, simple name has already been matched by matchIndexEntry()
+	int level = resolveLevelForType(this.pattern.declaringSimpleName, this.pattern.declaringQualification, method.declaringClass);
+	if (level == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
+
+	// parameter types
+	int parameterCount = this.pattern.parameterSimpleNames == null ? -1 : this.pattern.parameterSimpleNames.length;
+	if (parameterCount > -1) {
+		if (method.parameters == null) return INACCURATE_MATCH;
+		if (parameterCount != method.parameters.length) return IMPOSSIBLE_MATCH;
+		for (int i = 0; i < parameterCount; i++) {
+			int newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], method.parameters[i]);
+			if (level > newLevel) {
+				if (newLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
+				level = newLevel; // can only be downgraded
+			}
+		}
+	}
+	return level;
+}
+protected int resolveLevel(ConstructorDeclaration constructor, boolean checkDeclarations) {
+	int referencesLevel = IMPOSSIBLE_MATCH;
+	if (this.pattern.findReferences) {
+		ExplicitConstructorCall constructorCall = constructor.constructorCall;
+		if (constructorCall != null && constructorCall.accessMode == ExplicitConstructorCall.ImplicitSuper) {
+			// eliminate explicit super call as it will be treated with matchLevel(ExplicitConstructorCall, boolean)
+			referencesLevel = resolveLevel(constructorCall.binding);
+			if (referencesLevel == ACCURATE_MATCH) return ACCURATE_MATCH; // cannot get better
+		}
+	}
+	if (!checkDeclarations) return referencesLevel;
+
+	int declarationsLevel = this.pattern.findDeclarations ? resolveLevel(constructor.binding) : IMPOSSIBLE_MATCH;
+	return referencesLevel >= declarationsLevel ? referencesLevel : declarationsLevel; // answer the stronger match
+}
+protected int resolveLevel(TypeDeclaration type) {
+	// find default constructor
+	AbstractMethodDeclaration[] methods = type.methods;
+	if (methods != null) {
+		for (int i = 0, length = methods.length; i < length; i++) {
+			AbstractMethodDeclaration method = methods[i];
+			if (method.isDefaultConstructor() && method.sourceStart < type.bodyStart) // if synthetic
+				return resolveLevel((ConstructorDeclaration) method, false);
+		}
+	}
+	return IMPOSSIBLE_MATCH;
+}
+public String toString() {
+	return "Locator for " + this.pattern.toString(); //$NON-NLS-1$
+}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java
new file mode 100644
index 0000000..b01dd0d
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
+
+public class ConstructorPattern extends SearchPattern {
+
+private static ThreadLocal indexRecord = new ThreadLocal() {
+	protected Object initialValue() {
+		return new ConstructorPattern(false, false, null,null, null, null, R_EXACT_MATCH | R_CASE_SENSITIVE);
+	}
+};
+
+protected boolean findDeclarations;
+protected boolean findReferences;
+
+public char[] declaringQualification;
+public char[] declaringSimpleName;
+
+public char[][] parameterQualifications;
+public char[][] parameterSimpleNames;
+public int parameterCount;
+
+public static char[] createIndexKey(char[] typeName, int argCount) {
+	ConstructorPattern record = getConstructorRecord();
+	record.declaringSimpleName = typeName;
+	record.parameterCount = argCount;
+	return record.encodeIndexKey();
+}
+public static ConstructorPattern getConstructorRecord() {
+	return (ConstructorPattern)indexRecord.get();
+}
+public ConstructorPattern(
+	boolean findDeclarations,
+	boolean findReferences,
+	char[] declaringSimpleName,
+	char[] declaringQualification,
+	char[][] parameterQualifications,
+	char[][] parameterSimpleNames,
+	int matchRule) {
+
+	super(CONSTRUCTOR_PATTERN, matchRule);
+
+	this.findDeclarations = findDeclarations;
+	this.findReferences = findReferences;
+
+	boolean isCaseSensitive = isCaseSensitive();
+	this.declaringQualification = isCaseSensitive ? declaringQualification : CharOperation.toLowerCase(declaringQualification);
+	this.declaringSimpleName = isCaseSensitive ? declaringSimpleName : CharOperation.toLowerCase(declaringSimpleName);
+	if (parameterSimpleNames != null) {
+		this.parameterCount = parameterSimpleNames.length;
+		this.parameterQualifications = new char[this.parameterCount][];
+		this.parameterSimpleNames = new char[this.parameterCount][];
+		for (int i = 0; i < this.parameterCount; i++) {
+			this.parameterQualifications[i] = isCaseSensitive ? parameterQualifications[i] : CharOperation.toLowerCase(parameterQualifications[i]);
+			this.parameterSimpleNames[i] = isCaseSensitive ? parameterSimpleNames[i] : CharOperation.toLowerCase(parameterSimpleNames[i]);
+		}
+	} else {
+		this.parameterCount = -1;
+	}
+
+	this.mustResolve = mustResolve();
+}
+public void decodeIndexKey(char[] key) {
+	int size = key.length;
+	int lastSeparatorIndex = CharOperation.lastIndexOf(SEPARATOR, key);	
+
+	this.parameterCount = Integer.parseInt(new String(key, lastSeparatorIndex + 1, size - lastSeparatorIndex - 1));
+	this.declaringSimpleName = CharOperation.subarray(key, 0, lastSeparatorIndex);
+}
+/**
+ * Constructor declaration entries are encoded as 'constructorDecl/' TypeName '/' Arity:
+ * e.g. 'constructorDecl/X/0'
+ *
+ * Constructor reference entries are encoded as 'constructorRef/' TypeName '/' Arity:
+ * e.g. 'constructorRef/X/0'
+ */
+public char[] encodeIndexKey() {
+	// will have a common pattern in the new story
+	if (isCaseSensitive() && this.declaringSimpleName != null) {
+		switch(matchMode()) {
+			case EXACT_MATCH :
+				int arity = this.parameterCount;
+				if (arity >= 0) {
+					char[] countChars = arity < 10 ? COUNTS[arity] : ("/" + String.valueOf(arity)).toCharArray(); //$NON-NLS-1$
+					return CharOperation.concat(this.declaringSimpleName, countChars);
+				}
+			case PREFIX_MATCH :
+				return this.declaringSimpleName;
+			case PATTERN_MATCH :
+				int starPos = CharOperation.indexOf('*', this.declaringSimpleName);
+				switch(starPos) {
+					case -1 :
+						return this.declaringSimpleName;
+					default : 
+						char[] result = new char[starPos];
+						System.arraycopy(this.declaringSimpleName, 0, result, 0, starPos);
+						return result;
+					case 0 : // fall through
+				}
+		}
+	}
+	return CharOperation.NO_CHAR; // find them all
+}
+public SearchPattern getIndexRecord() {
+	return getConstructorRecord();
+}
+public char[][] getMatchCategories() {
+	if (this.findReferences)
+		if (this.findDeclarations) 
+			return new char[][] {CONSTRUCTOR_REF, CONSTRUCTOR_DECL};
+		else
+			return new char[][] {CONSTRUCTOR_REF};
+	else
+		if (this.findDeclarations)
+			return new char[][] {CONSTRUCTOR_DECL};
+		else
+			return CharOperation.NO_CHAR_CHAR;
+}
+public boolean isMatchingIndexRecord() {
+	ConstructorPattern record = getConstructorRecord();
+	if (this.parameterCount != -1 && this.parameterCount != record.parameterCount) return false;
+
+	return matchesName(this.declaringSimpleName, record.declaringSimpleName);
+}
+protected boolean mustResolve() {
+	if (this.declaringQualification != null) return true;
+
+	// parameter types
+	if (this.parameterSimpleNames != null)
+		for (int i = 0, max = this.parameterSimpleNames.length; i < max; i++)
+			if (this.parameterQualifications[i] != null) return true;
+	return this.findReferences; // need to check resolved default constructors and explicit constructor calls
+}
+public String toString() {
+	StringBuffer buffer = new StringBuffer(20);
+	if (this.findDeclarations) {
+		buffer.append(this.findReferences
+			? "ConstructorCombinedPattern: " //$NON-NLS-1$
+			: "ConstructorDeclarationPattern: "); //$NON-NLS-1$
+	} else {
+		buffer.append("ConstructorReferencePattern: "); //$NON-NLS-1$
+	}
+	if (declaringQualification != null)
+		buffer.append(declaringQualification).append('.');
+	if (declaringSimpleName != null) 
+		buffer.append(declaringSimpleName);
+	else if (declaringQualification != null)
+		buffer.append("*"); //$NON-NLS-1$
+
+	buffer.append('(');
+	if (parameterSimpleNames == null) {
+		buffer.append("..."); //$NON-NLS-1$
+	} else {
+		for (int i = 0, max = parameterSimpleNames.length; i < max; i++) {
+			if (i > 0) buffer.append(", "); //$NON-NLS-1$
+			if (parameterQualifications[i] != null) buffer.append(parameterQualifications[i]).append('.');
+			if (parameterSimpleNames[i] == null) buffer.append('*'); else buffer.append(parameterSimpleNames[i]);
+		}
+	}
+	buffer.append(')');
+	buffer.append(", "); //$NON-NLS-1$
+	switch(matchMode()) {
+		case EXACT_MATCH : 
+			buffer.append("exact match, "); //$NON-NLS-1$
+			break;
+		case PREFIX_MATCH :
+			buffer.append("prefix match, "); //$NON-NLS-1$
+			break;
+		case PATTERN_MATCH :
+			buffer.append("pattern match, "); //$NON-NLS-1$
+			break;
+	}
+	buffer.append(isCaseSensitive() ? "case sensitive" : "case insensitive"); //$NON-NLS-1$ //$NON-NLS-2$
+	return buffer.toString();
+}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorReferencePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorReferencePattern.java
deleted file mode 100644
index 6c3143e..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorReferencePattern.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.io.IOException;
-
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.indexing.AbstractIndexer;
-
-/**
- * The selector is unused, the constructor name is specified by the type simple name.
- */ 
-public class ConstructorReferencePattern extends MethodReferencePattern {
-
-	private char[] decodedTypeName;
-	
-public ConstructorReferencePattern(
-	char[] declaringSimpleName, 
-	int matchMode, 
-	boolean isCaseSensitive, 
-	char[] declaringQualification, 
-	char[][] parameterQualifications, 
-	char[][] parameterSimpleNames,
-	IType declaringType) {
-		
-	super(
-		null, 
-		matchMode, 
-		isCaseSensitive, 
-		declaringQualification, 
-		declaringSimpleName, 
-		null, 
-		null, 
-		parameterQualifications, 
-		parameterSimpleNames,
-		declaringType);
-}
-public void decodeIndexEntry(IEntryResult entryResult){
-
-	char[] word = entryResult.getWord();
-	int size = word.length;
-	int lastSeparatorIndex = CharOperation.lastIndexOf(SEPARATOR, word);	
-
-	decodedParameterCount = Integer.parseInt(new String(word, lastSeparatorIndex + 1, size - lastSeparatorIndex - 1));
-	decodedTypeName = CharOperation.subarray(word, CONSTRUCTOR_REF.length, lastSeparatorIndex);
-}
-/**
- * see SearchPattern.feedIndexRequestor
- */
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope) throws IOException {
-	for (int i = 0, max = references.length; i < max; i++) {
-		IndexedFile file = input.getIndexedFile(references[i]);
-		String path;
-		if (file != null && scope.encloses(path = IndexedFile.convertPath(file.getPath()))) {
-			requestor.acceptConstructorReference(path, decodedTypeName, decodedParameterCount);
-		}
-	}
-}
-/**
- * @see SearchPattern#indexEntryPrefix
- */
-public char[] indexEntryPrefix() {
-
-	return AbstractIndexer.bestConstructorReferencePrefix(
-			declaringSimpleName, 
-			parameterSimpleNames == null ? -1 : parameterSimpleNames.length, 
-			matchMode, 
-			isCaseSensitive);
-}
-/**
- * @see SearchPattern#matchContainer()
- */
-protected int matchContainer() {
-	return 
-		COMPILATION_UNIT // implicit constructor call: case of Y extends X and Y doesn't define any constructor
-		| CLASS // implicit constructor call: case of constructor declaration with no explicit super call
-		| METHOD // reference in another constructor
-		| FIELD; // anonymous in a field initializer
-}
-/**
- * @see SearchPattern#matchIndexEntry
- */
-protected boolean matchIndexEntry() {
-
-	/* check selector matches */
-	if (declaringSimpleName != null){
-		switch(matchMode){
-			case EXACT_MATCH :
-				if (!CharOperation.equals(declaringSimpleName, decodedTypeName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PREFIX_MATCH :
-				if (!CharOperation.prefixEquals(declaringSimpleName, decodedTypeName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PATTERN_MATCH :
-				if (!CharOperation.match(declaringSimpleName, decodedTypeName, isCaseSensitive)){
-					return false;
-				}
-		}
-	}
-	if (parameterSimpleNames != null){
-		if (parameterSimpleNames.length != decodedParameterCount) return false;
-	}
-	return true;
-}
-public String toString(){
-
-	StringBuffer buffer = new StringBuffer(20);
-	buffer.append("ConstructorReferencePattern: "); //$NON-NLS-1$
-	if (declaringQualification != null) buffer.append(declaringQualification).append('.');
-	if (declaringSimpleName != null) 
-		buffer.append(declaringSimpleName);
-	else if (declaringQualification != null) buffer.append("*"); //$NON-NLS-1$
-	buffer.append('(');
-	if (parameterSimpleNames == null) {
-		buffer.append("..."); //$NON-NLS-1$
-	} else {
-		for (int i = 0, max = parameterSimpleNames.length; i < max; i++){
-			if (i > 0) buffer.append(", "); //$NON-NLS-1$
-			if (parameterQualifications[i] != null) buffer.append(parameterQualifications[i]).append('.');
-			if (parameterSimpleNames[i] == null) buffer.append('*'); else buffer.append(parameterSimpleNames[i]);
-		}
-	}
-	buffer.append(')');
-	buffer.append(", "); //$NON-NLS-1$
-	switch(matchMode){
-		case EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	if (isCaseSensitive)
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
-	return buffer.toString();
-}
-
-/**
- * Returns whether this constructor pattern  matches the given allocation expression.
- * Look at resolved information only if specified.
- */
-private int matchLevel(AllocationExpression allocation, boolean resolve) {
-
-	// constructor name is simple type name
-	char[][] typeName = allocation.type.getTypeName();
-	if (this.declaringSimpleName != null 
-			&& !this.matchesName(this.declaringSimpleName, typeName[typeName.length-1]))
-		return IMPOSSIBLE_MATCH;
-
-	if (resolve) {
-		return this.matchLevel(allocation.binding);
-	} else {
-		// argument types
-		int argumentCount = this.parameterSimpleNames == null ? -1 : this.parameterSimpleNames.length;
-		if (argumentCount > -1) {
-			int parameterCount = allocation.arguments == null ? 0 : allocation.arguments.length;
-			if (parameterCount != argumentCount)
-				return IMPOSSIBLE_MATCH;
-		}
-		return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-	}
-}
-
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
- */
-public int matchLevel(AstNode node, boolean resolve) {
-	if (node instanceof AllocationExpression) {
-		return this.matchLevel((AllocationExpression)node, resolve);
-	} else if (node instanceof ExplicitConstructorCall) {
-		return this.matchLevel((ExplicitConstructorCall)node, resolve);
-	} else if (node instanceof ConstructorDeclaration) {
-		return this.matchLevel((ConstructorDeclaration)node, resolve);
-	} else if (node instanceof TypeDeclaration) {
-		return this.matchLevel((TypeDeclaration)node, resolve);
-	}
-	return IMPOSSIBLE_MATCH;
-}
-/**
- * Returns whether the given constructor declaration has an implicit constructor reference that matches
- * this constructor pattern.
- * Look at resolved information only if specified.
- */
-private int matchLevel(ConstructorDeclaration constructor, boolean resolve) {
-	ExplicitConstructorCall constructorCall = constructor.constructorCall;
-	if (constructorCall != null && constructorCall.accessMode == ExplicitConstructorCall.ImplicitSuper) {
-		return this.matchLevel(constructorCall, resolve);
-	} else {
-		// Eliminate explicit super call as it will be treated with matchLevel(ExplicitConstructorCall, boolean)
-		return IMPOSSIBLE_MATCH;
-	}
-}
-
-/**
- * Returns whether this constructor pattern  matches the given explicit constructor call.
- * Look at resolved information only if specified.
- */
-private int matchLevel(ExplicitConstructorCall call, boolean resolve) {
-	if (resolve) {
-		return this.matchLevel(call.binding);
-	} else {
-		// argument types
-		int argumentCount = this.parameterSimpleNames == null ? -1 : this.parameterSimpleNames.length;
-		if (argumentCount > -1) {
-			int parameterCount = call.arguments == null ? 0 : call.arguments.length;
-			if (parameterCount != argumentCount)
-				return IMPOSSIBLE_MATCH;
-		}
-		return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-	}
-}
-/**
- * Returns whether the given type declaration has an implicit constructor reference that matches
- * this constructor pattern.
- * Look at resolved information only if specified.
- */
-private int matchLevel(TypeDeclaration type, boolean resolve) {
-	if (resolve) {
-		// find default constructor
-		AbstractMethodDeclaration[] methods = type.methods;
-		if (methods != null) {
-			for (int i = 0, length = methods.length; i < length; i++) {
-				AbstractMethodDeclaration method = methods[i];
-				if (method.isDefaultConstructor()
-						&& method.sourceStart < type.bodyStart) { // if synthetic
-					return this.matchLevel((ConstructorDeclaration)method, true);
-				}
-			}
-		}
-		return IMPOSSIBLE_MATCH;
-	} else {
-		// Need to wait for all the constructor bodies to have been parsed
-		return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-	}
-}
-
-/**
- * @see SearchPattern#matchLevel(Binding binding).
- */
-public int matchLevel(Binding binding) {
-	if (binding == null) return INACCURATE_MATCH;
-	if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH;
-	int level;
-
-	// declaring type
-	MethodBinding method = (MethodBinding)binding;
-	ReferenceBinding declaringBinding = method.declaringClass;
-	level = this.matchLevelForType(this.declaringSimpleName, this.declaringQualification, declaringBinding);
-	if (level == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
-		
-	// argument types
-	int argumentCount = this.parameterSimpleNames == null ? -1 : this.parameterSimpleNames.length;
-	if (argumentCount > -1) {
-		if (method.parameters == null) {
-			level = INACCURATE_MATCH;
-		} else {
-			int parameterCount = method.parameters.length;
-			if (parameterCount != argumentCount)
-				return IMPOSSIBLE_MATCH;
-
-			for (int i = 0; i < parameterCount; i++) {
-				char[] qualification = this.parameterQualifications[i];
-				char[] type = this.parameterSimpleNames[i];
-				int newLevel = this.matchLevelForType(type, qualification, method.parameters[i]);
-				switch (newLevel) {
-					case IMPOSSIBLE_MATCH:
-						return IMPOSSIBLE_MATCH;
-					case ACCURATE_MATCH: // keep previous level
-						break;
-					default: // ie. INACCURATE_MATCH
-						level = newLevel;
-						break;
-				}
-			}
-		}
-	}
-
-	return level;
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfAccessedFieldsPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfAccessedFieldsPattern.java
index 001a1ac..d284cbd 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfAccessedFieldsPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfAccessedFieldsPattern.java
@@ -10,111 +10,19 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
-import java.util.HashSet;
-
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.FieldReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
-import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.jdt.internal.core.util.SimpleSet;
 
-public class DeclarationOfAccessedFieldsPattern extends FieldReferencePattern {
-	HashSet knownFields;
-	IJavaElement enclosingElement;
+public class DeclarationOfAccessedFieldsPattern extends FieldPattern {
+
+protected IJavaElement enclosingElement;
+protected SimpleSet knownFields;
+
 public DeclarationOfAccessedFieldsPattern(IJavaElement enclosingElement) {
-	super(
-		null, 
-		PATTERN_MATCH, 
-		false, 
-		null, 
-		null,
-		null,
-		null,
-		true,  // read access
-		true); // write access
-	this.enclosingElement = enclosingElement;
-	this.needsResolve = true;
-	this.knownFields = new HashSet();
-}
+	super(false, true, true, null, null, null, null, null, R_PATTERN_MATCH);
 
-/**
- * @see SearchPattern#matchReportReference
- */
-protected void matchReportReference(AstNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	// need accurate match to be able to open on type ref
-	if (accuracy == IJavaSearchResultCollector.POTENTIAL_MATCH) return;
-	
-	// element that references the field must be included in the enclosing element
-	while (element != null && !this.enclosingElement.equals(element)) {
-		element = element.getParent();
-	}
-	if (element == null) return;
-	
-	if (reference instanceof FieldReference) {
-		this.reportDeclaration(((FieldReference)reference).binding, locator);
-	} else if (reference instanceof QualifiedNameReference) {
-		QualifiedNameReference qNameRef = (QualifiedNameReference)reference;
-		Binding binding = qNameRef.binding;
-		if (binding instanceof FieldBinding) {
-			this.reportDeclaration((FieldBinding)binding, locator);
-		} 
-		int otherMax = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length;
-		for (int i = 0; i < otherMax; i++){
-			this.reportDeclaration(qNameRef.otherBindings[i], locator);
-		}
-	} else if (reference instanceof SingleNameReference) {
-		this.reportDeclaration(
-			(FieldBinding)((SingleNameReference)reference).binding, 
-			locator);
-	}
-}
-private void reportDeclaration(FieldBinding fieldBinding, MatchLocator locator) throws CoreException {
-	// ignore length field
-	if (fieldBinding == ArrayBinding.LengthField) return;
-	
-	ReferenceBinding declaringClass = fieldBinding.declaringClass;
-	IType type = locator.lookupType(declaringClass);
-	if (type == null) return; // case of a secondary type
-	char[] name = fieldBinding.name;
-	IField field = type.getField(new String(name));
-	if (this.knownFields.contains(field)) return;
-	this.knownFields.add(field);
-	IResource resource = type.getResource();
-	boolean isBinary = type.isBinary();
-	IBinaryType info = null;
-	if (isBinary) {
-		if (resource == null) {
-			resource = type.getJavaProject().getProject();
-		}
-		info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile)type.getClassFile(), resource);
-		locator.reportBinaryMatch(resource, field, info, IJavaSearchResultCollector.EXACT_MATCH);
-	} else {
-		TypeDeclaration typeDecl = ((SourceTypeBinding)declaringClass).scope.referenceContext;
-		FieldDeclaration fieldDecl = null;
-		FieldDeclaration[] fieldDecls = typeDecl.fields;
-		for (int i = 0, length = fieldDecls.length; i < length; i++) {
-			if (CharOperation.equals(name, fieldDecls[i].name)) {
-				fieldDecl = fieldDecls[i];
-				break;
-			}
-		} 
-		if (fieldDecl != null) {
-			locator.report(resource, fieldDecl.sourceStart, fieldDecl.sourceEnd, field, IJavaSearchResultCollector.EXACT_MATCH);
-		}
-	}
+	this.enclosingElement = enclosingElement;
+	this.knownFields = new SimpleSet();
+	this.mustResolve = true;
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedMethodsPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedMethodsPattern.java
index 98fd5c4..06ebb29 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedMethodsPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedMethodsPattern.java
@@ -10,98 +10,21 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
-import java.util.HashSet;
+//import java.util.HashSet;
 
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
 import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.Signature;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.MessageSend;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.core.util.SimpleSet;
 
-public class DeclarationOfReferencedMethodsPattern extends MethodReferencePattern {
-	HashSet knownMethods;
-	IJavaElement enclosingElement;
-	
+public class DeclarationOfReferencedMethodsPattern extends MethodPattern {
+
+protected IJavaElement enclosingElement;
+protected SimpleSet knownMethods;
+
 public DeclarationOfReferencedMethodsPattern(IJavaElement enclosingElement) {
-	super(
-		null, 
-		PATTERN_MATCH, 
-		false, 
-		null, 
-		null,
-		null,
-		null,
-		null,
-		null,
-		null);
+	super(false, true, null, null, null, null, null, null, null, null, R_PATTERN_MATCH);
+
 	this.enclosingElement = enclosingElement;
-	this.needsResolve = true;
-	this.knownMethods = new HashSet();
-}
-
-/**
- * @see SearchPattern#matchReportReference
- */
-protected void matchReportReference(AstNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	// need accurate match to be able to open on type ref
-	if (accuracy == IJavaSearchResultCollector.POTENTIAL_MATCH) return;
-	
-	// element that references the method must be included in the enclosing element
-	while (element != null && !this.enclosingElement.equals(element)) {
-		element = element.getParent();
-	}
-	if (element == null) return;
-
-	this.reportDeclaration(((MessageSend)reference).binding, locator);
-}
-private void reportDeclaration(MethodBinding methodBinding, MatchLocator locator) throws CoreException {
-	ReferenceBinding declaringClass = methodBinding.declaringClass;
-	IType type = locator.lookupType(declaringClass);
-	if (type == null) return; // case of a secondary type
-	char[] selector = methodBinding.selector;
-	TypeBinding[] parameters = methodBinding.parameters;
-	int parameterLength = parameters.length;
-	String[] parameterTypes = new String[parameterLength];
-	for (int i = 0; i  < parameterLength; i++) {
-		parameterTypes[i] = Signature.createTypeSignature(parameters[i].sourceName(), false);
-	}
-	IMethod method = type.getMethod(new String(selector), parameterTypes);
-	if (this.knownMethods.contains(method)) return;
-	this.knownMethods.add(method);
-	IResource resource = type.getResource();
-	boolean isBinary = type.isBinary();
-	IBinaryType info = null;
-	if (isBinary) {
-		if (resource == null) {
-			resource = type.getJavaProject().getProject();
-		}
-		info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile)type.getClassFile(), resource);
-		locator.reportBinaryMatch(resource, method, info, IJavaSearchResultCollector.EXACT_MATCH);
-	} else {
-		TypeDeclaration typeDecl = ((SourceTypeBinding)declaringClass).scope.referenceContext;
-		AbstractMethodDeclaration methodDecl = null;
-		AbstractMethodDeclaration[] methodDecls = typeDecl.methods;
-		for (int i = 0, length = methodDecls.length; i < length; i++) {
-			if (CharOperation.equals(selector, methodDecls[i].selector)) {
-				methodDecl = methodDecls[i];
-				break;
-			}
-		} 
-		if (methodDecl != null) {
-			locator.report(resource, methodDecl.sourceStart, methodDecl.sourceEnd, method, IJavaSearchResultCollector.EXACT_MATCH);
-		}
-	}
+	this.knownMethods = new SimpleSet();
+	this.mustResolve = true;
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedTypesPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedTypesPattern.java
index c1fe4c7..80a80fd 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedTypesPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/DeclarationOfReferencedTypesPattern.java
@@ -10,147 +10,19 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
-import java.util.HashSet;
-
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
 import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
-import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.BindingIds;
-import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.core.util.SimpleSet;
 
 public class DeclarationOfReferencedTypesPattern extends TypeReferencePattern {
-	HashSet knownTypes;
-	IJavaElement enclosingElement;
+
+protected SimpleSet knownTypes;
+protected IJavaElement enclosingElement;
+
 public DeclarationOfReferencedTypesPattern(IJavaElement enclosingElement) {
-	super(null, null, PATTERN_MATCH, false);
+	super(null, null, R_PATTERN_MATCH);
+
 	this.enclosingElement = enclosingElement;
-	this.needsResolve = true;
-	this.knownTypes = new HashSet();
-}
-/**
- * @see SearchPattern#matchReportImportRef(ImportReference, Binding, IJavaElement, int, MatchLocator)
- */
-protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	// need accurate match to be able to open on type ref
-	if (accuracy == IJavaSearchResultCollector.POTENTIAL_MATCH) return;
-	
-	// element that references the type must be included in the enclosing element
-	while (element != null && !this.enclosingElement.equals(element)) {
-		element = element.getParent();
-	}
-	if (element == null) return;
-
-	while (binding instanceof ReferenceBinding) {
-		ReferenceBinding typeBinding = (ReferenceBinding)binding;
-		this.reportDeclaration(typeBinding, 1, locator);
-		binding = typeBinding.enclosingType();
-	}
-}
-
-/**
- * @see SearchPattern#matchReportReference
- */
-protected void matchReportReference(AstNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	// need accurate match to be able to open on type ref
-	if (accuracy == IJavaSearchResultCollector.POTENTIAL_MATCH) return;
-	
-	// element that references the type must be included in the enclosing element
-	while (element != null && !this.enclosingElement.equals(element)) {
-		element = element.getParent();
-	}
-	if (element == null) return;
-
-	int maxType = -1;
-	TypeBinding typeBinding = null;
-	if (reference instanceof TypeReference) {
-		typeBinding = ((TypeReference)reference).resolvedType;
-		maxType = Integer.MAX_VALUE;
-	} else if (reference instanceof QualifiedNameReference) {
-		QualifiedNameReference qNameRef = (QualifiedNameReference)reference;
-		Binding binding = qNameRef.binding;
-		maxType = qNameRef.tokens.length-1;
-		switch (qNameRef.bits & AstNode.RestrictiveFlagMASK) {
-			case BindingIds.FIELD : // reading a field
-				typeBinding = qNameRef.actualReceiverType;
-				int otherBindingsCount = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length;			
-				maxType -= otherBindingsCount + 1;
-				break;
-			case BindingIds.TYPE : //=============only type ==============
-				typeBinding = (TypeBinding)binding;
-				break;
-			case BindingIds.VARIABLE : //============unbound cases===========
-			case BindingIds.TYPE | BindingIds.VARIABLE :						
-				if (binding instanceof ProblemBinding) {
-					ProblemBinding pbBinding = (ProblemBinding) binding;
-					typeBinding = pbBinding.searchType; // second chance with recorded type so far
-					char[] partialQualifiedName = pbBinding.name;
-					maxType = CharOperation.occurencesOf('.', partialQualifiedName) - 1; // index of last bound token is one before the pb token
-					if (typeBinding == null || maxType < 0) return;
-				}
-				break;
-		}
-	} else if (reference instanceof SingleNameReference) {
-		typeBinding = (TypeBinding)((SingleNameReference)reference).binding;
-		maxType = 1;
-	}
-	
-	if (typeBinding == null || typeBinding instanceof BaseTypeBinding) return;
-	if (typeBinding instanceof ArrayBinding) {
-		typeBinding = ((ArrayBinding)typeBinding).leafComponentType;
-	}
-	this.reportDeclaration(typeBinding, maxType, locator);
-}
-private void reportDeclaration(TypeBinding typeBinding, int maxType, MatchLocator locator) throws CoreException {
-	IType type = locator.lookupType(typeBinding);
-	if (type == null) return; // case of a secondary type
-	IResource resource = type.getResource();
-	boolean isBinary = type.isBinary();
-	IBinaryType info = null;
-	if (isBinary) {
-		if (resource == null) {
-			resource = type.getJavaProject().getProject();
-		}
-		info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile)type.getClassFile(), resource);
-	}
-	while (maxType >= 0 && type != null) {
-		if (!this.knownTypes.contains(type)) {
-			if (isBinary) {
-				locator.reportBinaryMatch(resource, type, info, IJavaSearchResultCollector.EXACT_MATCH);
-			} else {
-				TypeDeclaration typeDecl = ((SourceTypeBinding)typeBinding).scope.referenceContext;
-				locator.report(resource, typeDecl.sourceStart, typeDecl.sourceEnd, type, IJavaSearchResultCollector.EXACT_MATCH);
-			}
-			this.knownTypes.add(type);
-		}
-		if (typeBinding instanceof BinaryTypeBinding) {
-			typeBinding = ((BinaryTypeBinding)typeBinding).enclosingType();
-		} else {
-			typeBinding = ((SourceTypeBinding)typeBinding).enclosingType();
-		}
-		IJavaElement parent = type.getParent();
-		if (parent instanceof IType) {
-			type = (IType)parent;
-		} else {
-			type = null;
-		}
-		maxType--;
-	}
+	this.knownTypes = new SimpleSet();
+	this.mustResolve = true;
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldDeclarationPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldDeclarationPattern.java
deleted file mode 100644
index a2f4d33..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldDeclarationPattern.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.io.IOException;
-
-import org.eclipse.jdt.core.Signature;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.env.IBinaryField;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.indexing.AbstractIndexer;
-
-public class FieldDeclarationPattern extends SearchPattern {
-
-	// selector	
-	protected char[] name;
-	
-	// declaring type
-	protected char[] declaringQualification;
-	protected char[] declaringSimpleName;
-
-	// type
-	protected char[] typeQualification;
-	protected char[] typeSimpleName;
-
-	protected char[] decodedName;
-public FieldDeclarationPattern(
-	char[] name, 
-	int matchMode, 
-	boolean isCaseSensitive,
-	char[] declaringQualification,
-	char[] declaringSimpleName,	
-	char[] typeQualification, 
-	char[] typeSimpleName) {
-
-	super(matchMode, isCaseSensitive);
-
-	this.name = isCaseSensitive ? name : CharOperation.toLowerCase(name);
-	this.declaringQualification = isCaseSensitive ? declaringQualification : CharOperation.toLowerCase(declaringQualification);
-	this.declaringSimpleName = isCaseSensitive ? declaringSimpleName : CharOperation.toLowerCase(declaringSimpleName);
-	this.typeQualification = isCaseSensitive ? typeQualification : CharOperation.toLowerCase(typeQualification);
-	this.typeSimpleName = isCaseSensitive ? typeSimpleName : CharOperation.toLowerCase(typeSimpleName);
-
-	this.needsResolve = this.needsResolve();
-}
-public void decodeIndexEntry(IEntryResult entryResult){
-
-	char[] word = entryResult.getWord();
-	decodedName = CharOperation.subarray(word, FIELD_DECL.length, word.length);
-}
-/**
- * see SearchPattern.feedIndexRequestor
- */
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope) throws IOException {
-	for (int i = 0, max = references.length; i < max; i++) {
-		IndexedFile file = input.getIndexedFile(references[i]);
-		String path;
-		if (file != null && scope.encloses(path = IndexedFile.convertPath(file.getPath()))) {
-			requestor.acceptFieldDeclaration(path, decodedName);
-		}
-	}
-}
-/**
- * @see SearchPattern#indexEntryPrefix
- */
-public char[] indexEntryPrefix() {
-
-	return AbstractIndexer.bestFieldDeclarationPrefix(
-			name, 
-			matchMode, 
-			isCaseSensitive);
-}
-/**
- * @see SearchPattern#matchContainer()
- */
-protected int matchContainer() {
-	return CLASS;
-}
-/**
- * @see SearchPattern#matchesBinary(Object, Object)
- */
-public boolean matchesBinary(Object binaryInfo, Object enclosingBinaryInfo) {
-	if (!(binaryInfo instanceof IBinaryField)) return false;
-
-	IBinaryField field = (IBinaryField)binaryInfo;
-	
-	// field name
-	if (!this.matchesName(this.name, field.getName()))
-		return false;
-
-	// declaring type
-	IBinaryType declaringType = (IBinaryType)enclosingBinaryInfo;
-	if (declaringType != null) {
-		char[] declaringTypeName = (char[])declaringType.getName().clone();
-		CharOperation.replace(declaringTypeName, '/', '.');
-		if (!this.matchesType(this.declaringSimpleName, this.declaringQualification, declaringTypeName)) {
-			return false;
-		}
-	}
-
-	// field type
-	String fieldTypeSignature = new String(field.getTypeName()).replace('/', '.');
-	if(!this.matchesType(this.typeSimpleName, this.typeQualification, Signature.toString(fieldTypeSignature).toCharArray())) {
-		return false;
-	}
-	
-	return true;
-}
-/**
- * @see SearchPattern#matchIndexEntry
- */
-protected boolean matchIndexEntry() {
-
-	/* check name matches */
-	if (name != null){
-		switch(matchMode){
-			case EXACT_MATCH :
-				if (!CharOperation.equals(name, decodedName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PREFIX_MATCH :
-				if (!CharOperation.prefixEquals(name, decodedName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PATTERN_MATCH :
-				if (!CharOperation.match(name, decodedName, isCaseSensitive)){
-					return false;
-				}
-		}
-	}
-	return true;
-}
-/**
- * Returns whether a method declaration or message send will need to be resolved to 
- * find out if this method pattern matches it.
- */
-private boolean needsResolve() {
-
-	// declaring type
-	if (declaringSimpleName != null || declaringQualification != null) return true;
-
-	// return type
-	if (typeSimpleName != null || typeQualification != null) return true;
-
-	return false;
-}
-public String toString(){
-
-	StringBuffer buffer = new StringBuffer(20);
-	buffer.append("FieldDeclarationPattern: "); //$NON-NLS-1$
-	if (declaringQualification != null) buffer.append(declaringQualification).append('.');
-	if (declaringSimpleName != null) 
-		buffer.append(declaringSimpleName).append('.');
-	else if (declaringQualification != null) buffer.append("*."); //$NON-NLS-1$
-	if (name == null) {
-		buffer.append("*"); //$NON-NLS-1$
-	} else {
-		buffer.append(name);
-	}
-	if (typeQualification != null) 
-		buffer.append(" --> ").append(typeQualification).append('.'); //$NON-NLS-1$
-	else if (typeSimpleName != null) buffer.append(" --> "); //$NON-NLS-1$
-	if (typeSimpleName != null) 
-		buffer.append(typeSimpleName);
-	else if (typeQualification != null) buffer.append("*"); //$NON-NLS-1$
-	buffer.append(", "); //$NON-NLS-1$
-	switch(matchMode){
-		case EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	if (isCaseSensitive)
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
-	return buffer.toString();
-}
-
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
- */
-public int matchLevel(AstNode node, boolean resolve) {
-	if (!(node instanceof FieldDeclaration)) return IMPOSSIBLE_MATCH;
-
-	FieldDeclaration field = (FieldDeclaration)node;
-
-	if (resolve) {
-		return this.matchLevel(field.binding);
-	} else {
-		if (!field.isField()) return IMPOSSIBLE_MATCH; // ignore field initializers
-		
-		// field name
-		if (!this.matchesName(this.name, field.name))
-			return IMPOSSIBLE_MATCH;
-
-		// field type
-		TypeReference fieldType = field.type;
-		char[][] fieldTypeName = fieldType.getTypeName();
-		char[] sourceName = this.toArrayName(
-			fieldTypeName[fieldTypeName.length-1], 
-			fieldType.dimensions());
-		if (!this.matchesName(this.typeSimpleName, sourceName))
-			return IMPOSSIBLE_MATCH;
-
-		return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-	}
-}
-
-/**
- * @see SearchPattern#matchLevel(Binding)
- */
-public int matchLevel(Binding binding) {
-	if (binding == null) return INACCURATE_MATCH;
-	if (!(binding instanceof FieldBinding)) return IMPOSSIBLE_MATCH;
-	int level;
-
-	FieldBinding field = (FieldBinding)binding;
-	
-	// field name
-	if (!this.matchesName(this.name, field.readableName()))
-		return IMPOSSIBLE_MATCH;
-
-	// declaring type
-	ReferenceBinding declaringBinding = field.declaringClass;
-	if (declaringBinding == null ) {
-		return INACCURATE_MATCH;
-	} else {
-		level = this.matchLevelForType(this.declaringSimpleName, this.declaringQualification, declaringBinding);
-		if (level == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
-	}
-
-	// look at field type only if declaring type is not specified
-	if (this.declaringSimpleName == null) {
-		int newLevel = this.matchLevelForType(this.typeSimpleName, this.typeQualification, field.type);
-		switch (newLevel) {
-			case IMPOSSIBLE_MATCH:
-				return IMPOSSIBLE_MATCH;
-			case ACCURATE_MATCH: // keep previous level
-				break;
-			default: // ie. INACCURATE_MATCH
-				level = newLevel;
-				break;
-		}
-	}
-	
-	return level;
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java
new file mode 100644
index 0000000..ba0ac84
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.core.util.SimpleSet;
+
+public class FieldLocator extends VariableLocator {
+
+protected boolean isDeclarationOfAccessedFieldsPattern;
+
+public FieldLocator(FieldPattern pattern) {
+	super(pattern);
+
+	this.isDeclarationOfAccessedFieldsPattern = this.pattern instanceof DeclarationOfAccessedFieldsPattern;
+}
+//public int match(ASTNode node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+public int match(FieldDeclaration node, MatchingNodeSet nodeSet) {
+	int referencesLevel = IMPOSSIBLE_MATCH;
+	if (this.pattern.findReferences)
+		// must be a write only access with an initializer
+		if (this.pattern.writeAccess && !this.pattern.readAccess && node.initialization != null)
+			if (matchesName(this.pattern.name, node.name))
+				referencesLevel = this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
+
+	int declarationsLevel = IMPOSSIBLE_MATCH;
+	if (this.pattern.findDeclarations)
+		if (node.isField()) // ignore field initializers
+			if (matchesName(this.pattern.name, node.name))
+				if (matchesTypeReference(((FieldPattern)this.pattern).typeSimpleName, node.type))
+					declarationsLevel = this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
+
+	return nodeSet.addMatch(node, referencesLevel >= declarationsLevel ? referencesLevel : declarationsLevel); // use the stronger match
+}
+//public int match(MethodDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(MessageSend node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(TypeDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(TypeReference node, MatchingNodeSet nodeSet) - SKIP IT
+
+protected int matchContainer() {
+	if (this.pattern.findReferences) {
+		// need to look almost everywhere to find in javadocs
+		return CLASS_CONTAINER | METHOD_CONTAINER | FIELD_CONTAINER;
+	}
+	return CLASS_CONTAINER;
+}
+protected int matchField(FieldBinding field, boolean matchName) {
+	if (field == null) return INACCURATE_MATCH;
+
+	if (matchName && !matchesName(this.pattern.name, field.readableName())) return IMPOSSIBLE_MATCH;
+
+	FieldPattern fieldPattern = (FieldPattern)this.pattern;
+	ReferenceBinding receiverBinding = field.declaringClass;
+	if (receiverBinding == null) {
+		if (field == ArrayBinding.ArrayLength)
+			// optimized case for length field of an array
+			return fieldPattern.declaringQualification == null && fieldPattern.declaringSimpleName == null
+				? ACCURATE_MATCH
+				: IMPOSSIBLE_MATCH;
+		return INACCURATE_MATCH;
+	}
+
+	// Note there is no dynamic lookup for field access
+	int declaringLevel = resolveLevelForType(fieldPattern.declaringSimpleName, fieldPattern.declaringQualification, receiverBinding);
+	if (declaringLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
+
+	// look at field type only if declaring type is not specified
+	if (fieldPattern.declaringSimpleName == null) return declaringLevel;
+
+	int typeLevel = resolveLevelForType(fieldPattern.typeSimpleName, fieldPattern.typeQualification, field.type);
+	return declaringLevel > typeLevel ? typeLevel : declaringLevel; // return the weaker match
+}
+protected int matchReference(Reference node, MatchingNodeSet nodeSet, boolean writeOnlyAccess) {
+	if (node instanceof FieldReference) {
+		if (matchesName(this.pattern.name, ((FieldReference) node).token))
+			return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+		return IMPOSSIBLE_MATCH;
+	}
+	return super.matchReference(node, nodeSet, writeOnlyAccess);
+}
+protected void matchReportReference(ASTNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	if (this.isDeclarationOfAccessedFieldsPattern) {
+		// need exact match to be able to open on type ref
+		if (accuracy != IJavaSearchResultCollector.EXACT_MATCH) return;
+
+		// element that references the field must be included in the enclosing element
+		DeclarationOfAccessedFieldsPattern declPattern = (DeclarationOfAccessedFieldsPattern) this.pattern; 
+		while (element != null && !declPattern.enclosingElement.equals(element))
+			element = element.getParent();
+		if (element != null) {
+			if (reference instanceof FieldReference) {
+				reportDeclaration(((FieldReference) reference).binding, locator, declPattern.knownFields);
+			} else if (reference instanceof QualifiedNameReference) {
+				QualifiedNameReference qNameRef = (QualifiedNameReference) reference;
+				Binding binding = qNameRef.binding;
+				if (binding instanceof FieldBinding)
+					reportDeclaration((FieldBinding)binding, locator, declPattern.knownFields);
+				int otherMax = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length;
+				for (int i = 0; i < otherMax; i++)
+					reportDeclaration(qNameRef.otherBindings[i], locator, declPattern.knownFields);
+			} else if (reference instanceof SingleNameReference) {
+				reportDeclaration((FieldBinding)((SingleNameReference) reference).binding, locator, declPattern.knownFields);
+			}
+		}
+	} else if (reference instanceof FieldReference) {
+		long position = ((FieldReference) reference).nameSourcePosition;
+		locator.report(position, position, element, accuracy);
+	} else if (reference instanceof SingleNameReference) {
+		locator.report(reference.sourceStart, reference.sourceEnd, element, accuracy);
+	} else if (reference instanceof QualifiedNameReference) {
+		QualifiedNameReference qNameRef = (QualifiedNameReference) reference;
+		int length = qNameRef.tokens.length;
+		int[] accuracies = new int[length];
+		Binding binding = qNameRef.binding;
+		int indexOfFirstFieldBinding = qNameRef.indexOfFirstFieldBinding > 0 ? qNameRef.indexOfFirstFieldBinding-1 : 0;
+		for (int i = 0; i < indexOfFirstFieldBinding; i++)
+			accuracies[i] = -1;
+		// first token
+		if (matchesName(this.pattern.name, qNameRef.tokens[indexOfFirstFieldBinding]) && !(binding instanceof LocalVariableBinding)) {
+			FieldBinding fieldBinding = binding instanceof FieldBinding ? (FieldBinding) binding : null;
+			if (fieldBinding == null) {
+				accuracies[indexOfFirstFieldBinding] = accuracy;
+			} else {
+				switch (matchField(fieldBinding, false)) {
+					case ACCURATE_MATCH:
+						accuracies[indexOfFirstFieldBinding] = IJavaSearchResultCollector.EXACT_MATCH;
+						break;
+					case INACCURATE_MATCH:
+						accuracies[indexOfFirstFieldBinding] = IJavaSearchResultCollector.POTENTIAL_MATCH;
+						break;
+					default:
+						accuracies[indexOfFirstFieldBinding] = -1;
+				}
+			}
+		} else {
+			accuracies[indexOfFirstFieldBinding] = -1;
+		}
+		// other tokens
+		for (int i = indexOfFirstFieldBinding+1; i < length; i++) {
+			char[] token = qNameRef.tokens[i];
+			if (matchesName(this.pattern.name, token)) {
+				FieldBinding otherBinding = qNameRef.otherBindings == null ? null : qNameRef.otherBindings[i-(indexOfFirstFieldBinding+1)];
+				if (otherBinding == null) {
+					accuracies[i] = accuracy;
+				} else {
+					switch (matchField(otherBinding, false)) {
+						case ACCURATE_MATCH:
+							accuracies[i] = IJavaSearchResultCollector.EXACT_MATCH;
+							break;
+						case INACCURATE_MATCH:
+							accuracies[i] = IJavaSearchResultCollector.POTENTIAL_MATCH;
+							break;
+						default:
+							accuracies[i] = -1;
+					}
+				}
+			} else {
+				accuracies[i] = -1;
+			}
+		}
+		locator.reportAccurateReference(reference.sourceStart, reference.sourceEnd, qNameRef.tokens, element, accuracies);
+	}
+}
+protected void reportDeclaration(FieldBinding fieldBinding, MatchLocator locator, SimpleSet knownFields) throws CoreException {
+	// ignore length field
+	if (fieldBinding == ArrayBinding.ArrayLength) return;
+	
+	ReferenceBinding declaringClass = fieldBinding.declaringClass;
+	IType type = locator.lookupType(declaringClass);
+	if (type == null) return; // case of a secondary type
+
+	char[] bindingName = fieldBinding.name;
+	IField field = type.getField(new String(bindingName));
+	if (knownFields.includes(field)) return;
+
+	knownFields.add(field);
+	IResource resource = type.getResource();
+	boolean isBinary = type.isBinary();
+	IBinaryType info = null;
+	if (isBinary) {
+		if (resource == null)
+			resource = type.getJavaProject().getProject();
+		info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile) type.getClassFile(), resource);
+		locator.reportBinaryMatch(resource, field, info, IJavaSearchResultCollector.EXACT_MATCH);
+	} else {
+		ClassScope scope = ((SourceTypeBinding) declaringClass).scope;
+		if (scope != null) {
+			TypeDeclaration typeDecl = scope.referenceContext;
+			FieldDeclaration fieldDecl = null;
+			FieldDeclaration[] fieldDecls = typeDecl.fields;
+			for (int i = 0, length = fieldDecls.length; i < length; i++) {
+				if (CharOperation.equals(bindingName, fieldDecls[i].name)) {
+					fieldDecl = fieldDecls[i];
+					break;
+				}
+			} 
+			if (fieldDecl != null) {
+				locator.report(
+					resource, 
+					fieldDecl.sourceStart, 
+					fieldDecl.sourceEnd, 
+					field,
+					IJavaSearchResultCollector.EXACT_MATCH, 
+					locator.getParticipant());
+
+			}
+		}
+	}
+}
+public int resolveLevel(ASTNode possiblelMatchingNode) {
+	if (this.pattern.findReferences) {
+		if (possiblelMatchingNode instanceof FieldReference)
+			return matchField(((FieldReference) possiblelMatchingNode).binding, true);
+		else if (possiblelMatchingNode instanceof NameReference)
+			return resolveLevel((NameReference) possiblelMatchingNode);
+	}
+	if (possiblelMatchingNode instanceof FieldDeclaration)
+		return matchField(((FieldDeclaration) possiblelMatchingNode).binding, true);
+	return IMPOSSIBLE_MATCH;
+}
+public int resolveLevel(Binding binding) {
+	if (binding == null) return INACCURATE_MATCH;
+	if (!(binding instanceof FieldBinding)) return IMPOSSIBLE_MATCH;
+
+	return matchField((FieldBinding) binding, true);
+}
+protected int resolveLevel(NameReference nameRef) {
+	if (nameRef instanceof SingleNameReference)
+		return resolveLevel(nameRef.binding);
+
+	Binding binding = nameRef.binding;
+	QualifiedNameReference qNameRef = (QualifiedNameReference) nameRef;
+	FieldBinding fieldBinding = null;
+	if (binding instanceof FieldBinding) {
+		fieldBinding = (FieldBinding) binding;
+		char[] bindingName = fieldBinding.name;
+		int lastDot = CharOperation.lastIndexOf('.', bindingName);
+		if (lastDot > -1)
+			bindingName = CharOperation.subarray(bindingName, lastDot+1, bindingName.length);
+		if (matchesName(this.pattern.name, bindingName))
+			return matchField(fieldBinding, false);
+	} 
+	int otherMax = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length;
+	for (int i = 0; i < otherMax; i++) {
+		char[] token = qNameRef.tokens[i + qNameRef.indexOfFirstFieldBinding];
+		if (matchesName(this.pattern.name, token)) {
+			FieldBinding otherBinding = qNameRef.otherBindings[i];
+			int level = matchField(otherBinding, false);
+			if (level != IMPOSSIBLE_MATCH) return level;
+		}
+	}
+	return IMPOSSIBLE_MATCH;
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java
new file mode 100644
index 0000000..ec7e3df
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldPattern.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
+
+public class FieldPattern extends VariablePattern {
+
+private static ThreadLocal indexRecord = new ThreadLocal() {
+	protected Object initialValue() {
+		return new FieldPattern(false, false, false, null, null, null, null, null, R_EXACT_MATCH | R_CASE_SENSITIVE);
+	}
+};
+
+// declaring type
+protected char[] declaringQualification;
+protected char[] declaringSimpleName;
+
+// type
+protected char[] typeQualification;
+protected char[] typeSimpleName;
+
+protected static char[][] REF_CATEGORIES = { FIELD_REF, REF };
+protected static char[][] REF_AND_DECL_CATEGORIES = { FIELD_REF, REF, FIELD_DECL };
+protected static char[][] DECL_CATEGORIES = { FIELD_DECL };
+
+public static char[] createIndexKey(char[] fieldName) {
+	FieldPattern record = getFieldRecord();
+	record.name = fieldName;
+	return record.encodeIndexKey();
+}
+public static FieldPattern getFieldRecord() {
+	return (FieldPattern)indexRecord.get();
+}
+
+public FieldPattern(
+	boolean findDeclarations,
+	boolean readAccess,
+	boolean writeAccess,
+	char[] name, 
+	char[] declaringQualification,
+	char[] declaringSimpleName,	
+	char[] typeQualification, 
+	char[] typeSimpleName,
+	int matchRule) {
+
+	super(FIELD_PATTERN, findDeclarations, readAccess, writeAccess, name, matchRule);
+
+	boolean isCaseSensitive = isCaseSensitive();
+	this.declaringQualification = isCaseSensitive ? declaringQualification : CharOperation.toLowerCase(declaringQualification);
+	this.declaringSimpleName = isCaseSensitive ? declaringSimpleName : CharOperation.toLowerCase(declaringSimpleName);
+	this.typeQualification = isCaseSensitive ? typeQualification : CharOperation.toLowerCase(typeQualification);
+	this.typeSimpleName = isCaseSensitive ? typeSimpleName : CharOperation.toLowerCase(typeSimpleName);
+
+	this.mustResolve = mustResolve();
+}
+public void decodeIndexKey(char[] key) {
+	this.name = key;
+}
+public char[] encodeIndexKey() {
+	return encodeIndexKey(this.name);
+}
+public SearchPattern getIndexRecord() {
+	return getFieldRecord();
+}
+public char[][] getMatchCategories() {
+	return this.findReferences
+			? (this.findDeclarations || this.writeAccess ? REF_AND_DECL_CATEGORIES : REF_CATEGORIES)
+			: DECL_CATEGORIES;
+}
+public boolean isMatchingIndexRecord() {
+	return matchesName(this.name, getFieldRecord().name);
+}
+/**
+ * Returns whether a method declaration or message send will need to be resolved to 
+ * find out if this method pattern matches it.
+ */
+protected boolean mustResolve() {
+	if (this.declaringSimpleName != null || this.declaringQualification != null) return true;
+	if (this.typeSimpleName != null || this.typeQualification != null) return true;
+
+	return super.mustResolve();
+}
+public String toString() {
+	StringBuffer buffer = new StringBuffer(20);
+	if (this.findDeclarations) {
+		buffer.append(this.findReferences
+			? "FieldCombinedPattern: " //$NON-NLS-1$
+			: "FieldDeclarationPattern: "); //$NON-NLS-1$
+	} else {
+		buffer.append("FieldReferencePattern: "); //$NON-NLS-1$
+	}
+	if (declaringQualification != null) buffer.append(declaringQualification).append('.');
+	if (declaringSimpleName != null) 
+		buffer.append(declaringSimpleName).append('.');
+	else if (declaringQualification != null) buffer.append("*."); //$NON-NLS-1$
+	if (name == null) {
+		buffer.append("*"); //$NON-NLS-1$
+	} else {
+		buffer.append(name);
+	}
+	if (typeQualification != null) 
+		buffer.append(" --> ").append(typeQualification).append('.'); //$NON-NLS-1$
+	else if (typeSimpleName != null) buffer.append(" --> "); //$NON-NLS-1$
+	if (typeSimpleName != null) 
+		buffer.append(typeSimpleName);
+	else if (typeQualification != null) buffer.append("*"); //$NON-NLS-1$
+	buffer.append(", "); //$NON-NLS-1$
+	switch(matchMode()){
+		case EXACT_MATCH : 
+			buffer.append("exact match, "); //$NON-NLS-1$
+			break;
+		case PREFIX_MATCH :
+			buffer.append("prefix match, "); //$NON-NLS-1$
+			break;
+		case PATTERN_MATCH :
+			buffer.append("pattern match, "); //$NON-NLS-1$
+			break;
+	}
+	buffer.append(isCaseSensitive() ? "case sensitive" : "case insensitive"); //$NON-NLS-1$ //$NON-NLS-2$
+	return buffer.toString();
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldReferencePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldReferencePattern.java
deleted file mode 100644
index 240bd3b..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/FieldReferencePattern.java
+++ /dev/null
@@ -1,491 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.io.IOException;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ast.Assignment;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.FieldReference;
-import org.eclipse.jdt.internal.compiler.ast.NameReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
-import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
-import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
-import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.indexing.AbstractIndexer;
-
-public class FieldReferencePattern extends MultipleSearchPattern {
-
-	// selector	
-	protected char[] name;
-	
-	// declaring type
-	protected char[] declaringQualification;
-	protected char[] declaringSimpleName;
-
-	// type
-	protected char[] typeQualification;
-	protected char[] typeSimpleName;
-	
-	// read/write access
-	protected boolean readAccess = true;
-	protected boolean writeAccess = true;
-
-	protected char[] decodedName;
-
-	private static char[][] REF_TAGS = { FIELD_REF, REF };
-	private static char[][] REF_AND_DECL_TAGS = { FIELD_REF, REF, FIELD_DECL };
-
-public FieldReferencePattern(
-	char[] name, 
-	int matchMode, 
-	boolean isCaseSensitive,
-	char[] declaringQualification,
-	char[] declaringSimpleName,	
-	char[] typeQualification, 
-	char[] typeSimpleName,
-	boolean readAccess,
-	boolean writeAccess) {
-
-	super(matchMode, isCaseSensitive);
-
-	this.name = isCaseSensitive ? name : CharOperation.toLowerCase(name);
-	this.declaringQualification = isCaseSensitive ? declaringQualification : CharOperation.toLowerCase(declaringQualification);
-	this.declaringSimpleName = isCaseSensitive ? declaringSimpleName : CharOperation.toLowerCase(declaringSimpleName);
-	this.typeQualification = isCaseSensitive ? typeQualification : CharOperation.toLowerCase(typeQualification);
-	this.typeSimpleName = isCaseSensitive ? typeSimpleName : CharOperation.toLowerCase(typeSimpleName);
-	this.readAccess = readAccess;
-	this.writeAccess = writeAccess;
-
-	this.needsResolve = true; // always resolve (in case of a simple name reference being a potential match)
-}
-/**
- * Either decode ref/name, fieldRef/name 
- */ 
-public void decodeIndexEntry(IEntryResult entryResult){
-
-	char[] word = entryResult.getWord();
-	int size = word.length;
-	int tagLength = currentTag.length;
-	int nameLength = CharOperation.indexOf(SEPARATOR, word, tagLength);
-	if (nameLength < 0) nameLength = size;
-	decodedName = CharOperation.subarray(word, tagLength, nameLength);}
-/**
- * see SearchPattern.feedIndexRequestor
- */
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope) throws IOException {
-	if (currentTag == REF) {
-		foundAmbiguousIndexMatches = true;
-	}
-	for (int i = 0, max = references.length; i < max; i++) {
-		int reference = references[i];
-		if (reference != -1) { // if the reference has not been eliminated
-			IndexedFile file = input.getIndexedFile(reference);
-			String path;
-			if (file != null && scope.encloses(path = IndexedFile.convertPath(file.getPath()))) {
-				requestor.acceptFieldReference(path, decodedName);
-			}
-		}
-	}
-}
-protected char[][] getPossibleTags() {
-	if (this.writeAccess && !this.readAccess) {
-		return REF_AND_DECL_TAGS;
-	} else {
-		return REF_TAGS;
-	}
-}
-/**
- * @see AndPattern#hasNextQuery
- */
-protected boolean hasNextQuery() {
-	return false;
-}
-/**
- * see SearchPattern.indexEntryPrefix()
- */
-public char[] indexEntryPrefix(){
-
-	return AbstractIndexer.bestReferencePrefix(
-			currentTag,
-			name,
-			matchMode, 
-			isCaseSensitive);
-}
-/**
- * @see SearchPattern#matchCheck(AstNode, MatchSet)
- */
-protected void matchCheck(AstNode node, MatchSet set) {
-	if (this.readAccess) {
-		super.matchCheck(node, set);
-	}
-	if (node instanceof Assignment) {
-		AstNode lhs = ((Assignment)node).lhs;
-		if (this.writeAccess) {
-			super.matchCheck(lhs, set);
-		} else if (!(node instanceof CompoundAssignment)){
-			// the lhs may have been added when checking if it was a read access
-			set.removePossibleMatch(lhs);
-			set.removeTrustedMatch(lhs);
-		}	
-	} else if (node instanceof FieldDeclaration) {
-		super.matchCheck(node, set);
-	}
-}
-/**
- * @see SearchPattern#matchContainer()
- */
-protected int matchContainer() {
-	int matchContainer = METHOD | FIELD;
-	if (this.writeAccess && !this.readAccess) {
-		matchContainer |= CLASS;
-	}
-	return matchContainer;
-}
-/**
- * @see SearchPattern#matchIndexEntry
- */
-protected boolean matchIndexEntry() {
-
-	/* check name matches */
-	if (name != null){
-		switch(matchMode){
-			case EXACT_MATCH :
-				if (!CharOperation.equals(name, decodedName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PREFIX_MATCH :
-				if (!CharOperation.prefixEquals(name, decodedName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PATTERN_MATCH :
-				if (!CharOperation.match(name, decodedName, isCaseSensitive)){
-					return false;
-				}
-		}
-	}
-	return true;
-}
-/**
- * @see SearchPattern#matchReportReference
- */
-protected void matchReportReference(AstNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	if (reference instanceof QualifiedNameReference) {
-		QualifiedNameReference qNameRef = (QualifiedNameReference)reference;
-		int length = qNameRef.tokens.length;
-		int[] accuracies = new int[length];
-		Binding binding = qNameRef.binding;
-		int indexOfFirstFieldBinding = qNameRef.indexOfFirstFieldBinding > 0 ? qNameRef.indexOfFirstFieldBinding-1 : 0;
-		for (int i = 0; i < indexOfFirstFieldBinding; i++) {
-			accuracies[i] = -1;
-		}
-		// first token
-		if (this.matchesName(this.name, qNameRef.tokens[indexOfFirstFieldBinding])
-				&& !(binding instanceof LocalVariableBinding)) {
-			FieldBinding fieldBinding =
-				binding instanceof FieldBinding ?
-					 (FieldBinding)binding :
-					 null;
-			if (fieldBinding == null) {
-				accuracies[indexOfFirstFieldBinding] = accuracy;
-			} else {
-				int level = this.matchLevel(fieldBinding);
-				switch (level) {
-					case ACCURATE_MATCH:
-						accuracies[indexOfFirstFieldBinding] = IJavaSearchResultCollector.EXACT_MATCH;
-						break;
-					case INACCURATE_MATCH:
-						accuracies[indexOfFirstFieldBinding] = IJavaSearchResultCollector.POTENTIAL_MATCH;
-						break;
-					default:
-						accuracies[indexOfFirstFieldBinding] = -1;
-				}
-			}
-		} else {
-			accuracies[indexOfFirstFieldBinding] = -1;
-		}
-		// other tokens
-		for (int i = indexOfFirstFieldBinding+1; i < length; i++){
-			char[] token = qNameRef.tokens[i];
-			if (this.matchesName(this.name, token)) {
-				FieldBinding otherBinding = qNameRef.otherBindings == null ? null : qNameRef.otherBindings[i-(indexOfFirstFieldBinding+1)];
-				if (otherBinding == null) {
-					accuracies[i] = accuracy;
-				} else {
-					int level = this.matchLevel(otherBinding);
-					switch (level) {
-						case ACCURATE_MATCH:
-							accuracies[i] = IJavaSearchResultCollector.EXACT_MATCH;
-							break;
-						case INACCURATE_MATCH:
-							accuracies[i] = IJavaSearchResultCollector.POTENTIAL_MATCH;
-							break;
-						default:
-							accuracies[i] = -1;
-					}
-				}
-			} else {
-				accuracies[i] = -1;
-			}
-		}
-		locator.reportAccurateReference(
-			reference.sourceStart, 
-			reference.sourceEnd, 
-			qNameRef.tokens, 
-			element, 
-			accuracies);
-	} else {
-		locator.reportAccurateReference(
-			reference.sourceStart, 
-			reference.sourceEnd, 
-			new char[][] {this.name}, 
-			element, 
-			accuracy);
-	}
-}
-/**
- * @see AndPattern#resetQuery
- */
-protected void resetQuery() {
-}
-public String toString(){
-
-	StringBuffer buffer = new StringBuffer(20);
-	buffer.append("FieldReferencePattern: "); //$NON-NLS-1$
-	if (declaringQualification != null) buffer.append(declaringQualification).append('.');
-	if (declaringSimpleName != null) 
-		buffer.append(declaringSimpleName).append('.');
-	else if (declaringQualification != null) buffer.append("*."); //$NON-NLS-1$
-	if (name != null) {
-		buffer.append(name);
-	} else {
-		buffer.append("*"); //$NON-NLS-1$
-	}
-	if (typeQualification != null) 
-		buffer.append(" --> ").append(typeQualification).append('.'); //$NON-NLS-1$
-	else if (typeSimpleName != null) buffer.append(" --> "); //$NON-NLS-1$
-	if (typeSimpleName != null) 
-		buffer.append(typeSimpleName);
-	else if (typeQualification != null) buffer.append("*"); //$NON-NLS-1$
-	buffer.append(", "); //$NON-NLS-1$
-	switch(matchMode){
-		case EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	if (isCaseSensitive)
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
-	return buffer.toString();
-}
-
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
- */
-public int matchLevel(AstNode node, boolean resolve) {
-	if (node instanceof FieldReference) {
-		return this.matchLevel((FieldReference)node, resolve);
-	} else if (node instanceof NameReference) {
-		return this.matchLevel((NameReference)node, resolve);
-	} else if (node instanceof FieldDeclaration) {
-		return this.matchLevel((FieldDeclaration)node, resolve);
-	} 
-	return IMPOSSIBLE_MATCH;
-}
-
-/**
- * Returns whether this field reference pattern matches the given field reference.
- * Look at resolved information only if specified.
- */
-private int matchLevel(FieldReference fieldRef, boolean resolve) {	
-	// field name
-	if (!this.matchesName(this.name, fieldRef.token))
-		return IMPOSSIBLE_MATCH;
-
-	if (resolve) {
-		// receiver type and field type
-		return this.matchLevel(fieldRef.binding);
-	} else {
-		return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-	}
-}
-/**
- * Returns whether this field reference pattern matches the given field declaration in
- * write access.
- * Look at resolved information only if specified.
- */
-private int matchLevel(FieldDeclaration fieldDecl, boolean resolve) {
-	// nedd to be a write only access	
-	if (!this.writeAccess || this.readAccess) return IMPOSSIBLE_MATCH;
-	
-	// need have an initialization
-	if (fieldDecl.initialization == null) return IMPOSSIBLE_MATCH;
-	
-	// field name
-	if (!this.matchesName(this.name, fieldDecl.name))
-		return IMPOSSIBLE_MATCH;
-
-	if (resolve) {
-		// receiver type and field type
-		return this.matchLevel(fieldDecl.binding);
-	} else {
-		return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-	}
-}
-
-/**
- * Returns whether this field reference pattern matches the given name reference.
- * Look at resolved information only if specified.
- */
-private int matchLevel(NameReference nameRef, boolean resolve) {	
-	if (!resolve) {
-		// field name
-		if (this.name == null) {
-			return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-		} else {
-			if (nameRef instanceof SingleNameReference) {
-				if (this.matchesName(this.name, ((SingleNameReference)nameRef).token)) {
-					// can only be a possible match since resolution is needed 
-					// to find out if it is a field ref
-					return POSSIBLE_MATCH;
-				} else {
-					return IMPOSSIBLE_MATCH;
-				}
-			} else { // QualifiedNameReference
-				QualifiedNameReference qNameRef = (QualifiedNameReference)nameRef;
-				char[][] tokens = qNameRef.tokens;
-				if (this.writeAccess && !this.readAccess) {
-					// in the case of the assigment of a qualified name reference, the match must be on the last token
-					if (this.matchesName(this.name, tokens[tokens.length-1])) {
-						// can only be a possible match since resolution is needed 
-						// to find out if it is a field ref
-						return POSSIBLE_MATCH;
-					}
-				} else {
-					for (int i = 0, max = tokens.length; i < max; i++){
-						if (this.matchesName(this.name, tokens[i])) {
-							// can only be a possible match since resolution is needed 
-							// to find out if it is a field ref
-							return POSSIBLE_MATCH;
-						}
-					}
-				}
-				return IMPOSSIBLE_MATCH;
-			}				
-		} 
-	} else {
-		Binding binding = nameRef.binding;
-		if (binding == null) {
-			return INACCURATE_MATCH;
-		} else {
-			if (nameRef instanceof SingleNameReference){
-				if (binding instanceof FieldBinding){
-					return this.matchLevel((FieldBinding) binding);
-				} else {
-					return IMPOSSIBLE_MATCH; // must be a field binding
-				}
-			} else { // QualifiedNameReference
-				QualifiedNameReference qNameRef = (QualifiedNameReference)nameRef;
-				FieldBinding fieldBinding = null;
-				if (binding instanceof FieldBinding) {
-					fieldBinding = (FieldBinding)binding;
-					char[] name = fieldBinding.name;
-					int lastDot = CharOperation.lastIndexOf('.', name);
-					if (lastDot > -1) {
-						name = CharOperation.subarray(name, lastDot+1, name.length);
-					}
-					if (this.matchesName(this.name, name)) {
-						return this.matchLevel(fieldBinding);
-					} 
-				} 
-				int otherLevel = IMPOSSIBLE_MATCH;
-				int otherMax = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length;
-				for (int i = 0; i < otherMax && (otherLevel == IMPOSSIBLE_MATCH); i++){
-					char[] token = qNameRef.tokens[i + qNameRef.indexOfFirstFieldBinding];
-					if (this.matchesName(this.name, token)) {
-						FieldBinding otherBinding = qNameRef.otherBindings[i];
-						otherLevel = this.matchLevel(otherBinding);
-					}
-				}
-				return otherLevel;
-			}
-		}
-	}
-}
-
-/**
- * Returns whether this field reference pattern matches the given field binding.
- */
-private int matchLevel(FieldBinding binding) {
-	if (binding == null) return INACCURATE_MATCH;
-	int level;
-	
-	// receiver type
-	ReferenceBinding receiverBinding = binding.declaringClass;
-	if (receiverBinding == null) {
-		if (binding == ArrayBinding.LengthField) {
-			// optimized case for length field of an array
-			if (this.declaringQualification == null && this.declaringSimpleName == null) {
-				return ACCURATE_MATCH;
-			} else {
-				return IMPOSSIBLE_MATCH;
-			}
-		} else {
-			return INACCURATE_MATCH;
-		}
-	} else {
-		// Note there is no dynamic lookup for field access
-		level = this.matchLevelForType(this.declaringSimpleName, this.declaringQualification, receiverBinding);
-		if (level == IMPOSSIBLE_MATCH) {
-			return IMPOSSIBLE_MATCH;
-		}
-	}
-
-	// look at field type only if declaring type is not specified
-	if (this.declaringSimpleName == null) {
-		int newLevel = this.matchLevelForType(this.typeSimpleName, this.typeQualification, binding.type);
-		switch (newLevel) {
-			case IMPOSSIBLE_MATCH:
-				return IMPOSSIBLE_MATCH;
-			case ACCURATE_MATCH: // keep previous level
-				break;
-			default: // ie. INACCURATE_MATCH
-				level = newLevel;
-				break;
-		}
-	}
-
-	return level;
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchMatch.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchMatch.java
new file mode 100644
index 0000000..bc03040
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchMatch.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.search.SearchMatch;
+import org.eclipse.jdt.core.search.SearchParticipant;
+
+public class JavaSearchMatch extends SearchMatch {
+	
+	public IResource resource;
+	public IJavaElement element;
+	
+	public JavaSearchMatch(
+			IResource resource,
+			IJavaElement element,
+			String documentPath,
+			int accuracy,  
+			SearchParticipant participant,
+			int sourceStart, 
+			int sourceEnd, 
+			int sourceLineNumber) {
+		super(
+			element.getElementName(), 
+			documentPath, 
+			accuracy, 
+			participant, 
+			sourceStart, 
+			sourceEnd, 
+			sourceLineNumber, 
+			element.toString());
+		this.resource = resource;
+		this.element = element;
+	}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
index 2072bb9..27fea53 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
@@ -16,29 +16,29 @@
 import org.eclipse.core.resources.IWorkspaceRoot;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.JavaModel;
 import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.JavaProject;
 import org.eclipse.jdt.internal.core.builder.ClasspathJar;
 import org.eclipse.jdt.internal.core.builder.ClasspathLocation;
 
-// TODO: (jerome) Remove when switching to JavaSearchNameEnvironment2
-public class JavaSearchNameEnvironment implements INameEnvironment {
+/*
+ * A name environment based on the classpath of a Java project.
+ */
+public class JavaSearchNameEnvironment implements INameEnvironment, SuffixConstants {
 	
 	ClasspathLocation[] locations;
 	
 public JavaSearchNameEnvironment(IJavaProject javaProject) {
-	try {
-		computeClasspathLocations(javaProject.getProject().getWorkspace().getRoot(), (JavaProject) javaProject);
-	} catch(CoreException e) {
-		this.locations = new ClasspathLocation[0];
-	}
+	computeClasspathLocations(javaProject.getProject().getWorkspace().getRoot(), (JavaProject) javaProject);
 }
 
 public void cleanup() {
@@ -47,34 +47,47 @@
 	}
 }
 
-private void computeClasspathLocations(
-	IWorkspaceRoot workspaceRoot,
-	JavaProject javaProject) throws CoreException {
+private void computeClasspathLocations(IWorkspaceRoot workspaceRoot, JavaProject javaProject) {
 
 	String encoding = null;
-	IPackageFragmentRoot[] roots = javaProject.getAllPackageFragmentRoots();
+	IPackageFragmentRoot[] roots = null;
+	try {
+		roots = javaProject.getAllPackageFragmentRoots();
+	} catch (JavaModelException e) {
+		// project doesn't exist
+		this.locations = new ClasspathLocation[0];
+		return;
+	}
 	int length = roots.length;
-	ClasspathLocation[] locations = new ClasspathLocation[length];
+	ClasspathLocation[] cpLocations = new ClasspathLocation[length];
+	int index = 0;
 	JavaModelManager manager = JavaModelManager.getJavaModelManager();
 	for (int i = 0; i < length; i++) {
 		IPackageFragmentRoot root = roots[i];
 		IPath path = root.getPath();
-		if (root.isArchive()) {
-			ZipFile zipFile = manager.getZipFile(path);
-			locations[i] = new ClasspathJar(zipFile);
-		} else {
-			Object target = JavaModel.getTarget(workspaceRoot, path, false);
-			if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
-				if (encoding == null) {
-					encoding = javaProject.getOption(JavaCore.CORE_ENCODING, true);
-				}
-				locations[i] = new ClasspathSourceDirectory((IContainer)target, encoding);
+		try {
+			if (root.isArchive()) {
+				ZipFile zipFile = manager.getZipFile(path);
+				cpLocations[index++] = new ClasspathJar(zipFile);
 			} else {
-				locations[i] = ClasspathLocation.forBinaryFolder((IContainer) target, false);
+				Object target = JavaModel.getTarget(workspaceRoot, path, false);
+				if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
+					if (encoding == null) {
+						encoding = javaProject.getOption(JavaCore.CORE_ENCODING, true);
+					}
+					cpLocations[index++] = new ClasspathSourceDirectory((IContainer)target, encoding);
+				} else {
+					cpLocations[index++] = ClasspathLocation.forBinaryFolder((IContainer) target, false);
+				}
 			}
+		} catch (CoreException e1) {
+			// problem opening zip file or getting root kind
+			// consider root corrupt and ignore
+			// just resize cpLocations
+			System.arraycopy(cpLocations, 0, cpLocations = new ClasspathLocation[cpLocations.length-1], 0, index);
 		}
 	}
-	this.locations = locations;
+	this.locations = cpLocations;
 }
 
 private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName) {
@@ -87,7 +100,7 @@
 		NameEnvironmentAnswer answer;
 		if (location instanceof ClasspathSourceDirectory) {
 			if (sourceFileName == null) {
-				qSourceFileName = qualifiedTypeName + ".java"; //$NON-NLS-1$
+				qSourceFileName = qualifiedTypeName + SUFFIX_STRING_java;
 				sourceFileName = qSourceFileName;
 				qPackageName =  ""; //$NON-NLS-1$
 				if (qualifiedTypeName.length() > typeName.length) {
@@ -102,7 +115,7 @@
 				qSourceFileName);
 		} else {
 			if (binaryFileName == null) {
-				qBinaryFileName = qualifiedTypeName + ".class"; //$NON-NLS-1$
+				qBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
 				binaryFileName = qBinaryFileName;
 				qPackageName =  ""; //$NON-NLS-1$
 				if (qualifiedTypeName.length() > typeName.length) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment2.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment2.java
deleted file mode 100644
index 6bb6fc2..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment2.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.util.zip.ZipFile;
-
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
-import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
-import org.eclipse.jdt.internal.core.JavaModel;
-import org.eclipse.jdt.internal.core.JavaModelManager;
-import org.eclipse.jdt.internal.core.JavaProject;
-import org.eclipse.jdt.internal.core.builder.ClasspathJar;
-import org.eclipse.jdt.internal.core.builder.ClasspathLocation;
-
-/*
- * A name environment based on the classpath of a Java project.
- */
-public class JavaSearchNameEnvironment2 implements INameEnvironment {
-	
-	ClasspathLocation[] locations;
-	
-public JavaSearchNameEnvironment2(IJavaProject javaProject) {
-	try {
-		computeClasspathLocations(javaProject.getProject().getWorkspace().getRoot(), (JavaProject) javaProject);
-	} catch(CoreException e) {
-		this.locations = new ClasspathLocation[0];
-	}
-}
-
-public void cleanup() {
-	for (int i = 0, length = this.locations.length; i < length; i++) {
-		this.locations[i].cleanup();
-	}
-}
-
-private void computeClasspathLocations(
-	IWorkspaceRoot workspaceRoot,
-	JavaProject javaProject) throws CoreException {
-
-	String encoding = null;
-	IPackageFragmentRoot[] roots = javaProject.getAllPackageFragmentRoots();
-	int length = roots.length;
-	ClasspathLocation[] locations = new ClasspathLocation[length];
-	JavaModelManager manager = JavaModelManager.getJavaModelManager();
-	for (int i = 0; i < length; i++) {
-		IPackageFragmentRoot root = roots[i];
-		IPath path = root.getPath();
-		if (root.isArchive()) {
-			ZipFile zipFile = manager.getZipFile(path);
-			locations[i] = new ClasspathJar(zipFile);
-		} else {
-			Object target = JavaModel.getTarget(workspaceRoot, path, false);
-			if (root.getKind() == IPackageFragmentRoot.K_SOURCE) {
-				if (encoding == null) {
-					encoding = javaProject.getOption(JavaCore.CORE_ENCODING, true);
-				}
-				locations[i] = new ClasspathSourceDirectory((IContainer)target, encoding);
-			} else {
-				locations[i] = ClasspathLocation.forBinaryFolder((IContainer) target, false);
-			}
-		}
-	}
-	this.locations = locations;
-}
-
-private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName) {
-	String 
-		binaryFileName = null, qBinaryFileName = null, 
-		sourceFileName = null, qSourceFileName = null, 
-		qPackageName = null;
-	for (int i = 0, length = this.locations.length; i < length; i++) {
-		ClasspathLocation location = this.locations[i];
-		NameEnvironmentAnswer answer;
-		if (location instanceof ClasspathSourceDirectory) {
-			if (sourceFileName == null) {
-				qSourceFileName = qualifiedTypeName + ".java"; //$NON-NLS-1$
-				sourceFileName = qSourceFileName;
-				qPackageName =  ""; //$NON-NLS-1$
-				if (qualifiedTypeName.length() > typeName.length) {
-					int typeNameStart = qSourceFileName.length() - typeName.length - 5; // size of ".java"
-					qPackageName =  qSourceFileName.substring(0, typeNameStart - 1);
-					sourceFileName = qSourceFileName.substring(typeNameStart);
-				}
-			}
-			answer = location.findClass(
-				sourceFileName,
-				qPackageName,
-				qSourceFileName);
-		} else {
-			if (binaryFileName == null) {
-				qBinaryFileName = qualifiedTypeName + ".class"; //$NON-NLS-1$
-				binaryFileName = qBinaryFileName;
-				qPackageName =  ""; //$NON-NLS-1$
-				if (qualifiedTypeName.length() > typeName.length) {
-					int typeNameStart = qBinaryFileName.length() - typeName.length - 6; // size of ".class"
-					qPackageName =  qBinaryFileName.substring(0, typeNameStart - 1);
-					binaryFileName = qBinaryFileName.substring(typeNameStart);
-				}
-			}
-			answer = 
-				location.findClass(
-					binaryFileName, 
-					qPackageName, 
-					qBinaryFileName);
-		}
-		if (answer != null) return answer;
-	}
-	return null;
-}
-
-public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
-	if (typeName != null)
-		return findClass(
-			new String(CharOperation.concatWith(packageName, typeName, '/')),
-			typeName);
-	return null;
-}
-
-public NameEnvironmentAnswer findType(char[][] compoundName) {
-	if (compoundName != null)
-		return findClass(
-			new String(CharOperation.concatWith(compoundName, '/')),
-			compoundName[compoundName.length - 1]);
-	return null;
-}
-
-public boolean isPackage(char[][] compoundName, char[] packageName) {
-	return isPackage(new String(CharOperation.concatWith(compoundName, packageName, '/')));
-}
-
-public boolean isPackage(String qualifiedPackageName) {
-	for (int i = 0, length = this.locations.length; i < length; i++)
-		if (this.locations[i].isPackage(qualifiedPackageName))
-			return true;
-	return false;
-}
-
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/LocalVariableLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/LocalVariableLocator.java
new file mode 100644
index 0000000..ad58ceb
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/LocalVariableLocator.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.core.LocalVariable;
+
+public class LocalVariableLocator extends VariableLocator {
+
+public LocalVariableLocator(LocalVariablePattern pattern) {
+	super(pattern);
+}
+public int match(LocalDeclaration node, MatchingNodeSet nodeSet) {
+	int referencesLevel = IMPOSSIBLE_MATCH;
+	if (this.pattern.findReferences)
+		// must be a write only access with an initializer
+		if (this.pattern.writeAccess && !this.pattern.readAccess && node.initialization != null)
+			if (matchesName(this.pattern.name, node.name))
+				referencesLevel = this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
+
+	int declarationsLevel = IMPOSSIBLE_MATCH;
+	if (this.pattern.findDeclarations)
+		if (matchesName(this.pattern.name, node.name))
+			if (node.declarationSourceStart == getLocalVariable().declarationSourceStart)
+				declarationsLevel = this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
+
+	return nodeSet.addMatch(node, referencesLevel >= declarationsLevel ? referencesLevel : declarationsLevel); // use the stronger match
+}
+private LocalVariable getLocalVariable() {
+	return ((LocalVariablePattern) this.pattern).localVariable;
+}
+protected void matchReportReference(ASTNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	if (reference instanceof SingleNameReference) {
+		locator.report(reference.sourceStart, reference.sourceEnd, element, accuracy);
+	} else if (reference instanceof QualifiedNameReference) {
+		QualifiedNameReference qNameRef = (QualifiedNameReference) reference;
+		long sourcePosition = qNameRef.sourcePositions[0];
+		locator.report(sourcePosition, sourcePosition, element, accuracy);
+	} else if (reference instanceof LocalDeclaration) {
+		LocalVariable localVariable = getLocalVariable();
+		locator.report(localVariable.nameStart, localVariable.nameEnd, localVariable, accuracy);
+	}
+}
+protected int matchContainer() {
+	return METHOD_CONTAINER;
+}
+protected int matchLocalVariable(LocalVariableBinding variable, boolean matchName) {
+	if (variable == null) return INACCURATE_MATCH;
+
+	if (matchName && !matchesName(this.pattern.name, variable.readableName())) return IMPOSSIBLE_MATCH;
+
+	return variable.declaration.declarationSourceStart == getLocalVariable().declarationSourceStart
+		? ACCURATE_MATCH
+		: IMPOSSIBLE_MATCH;
+}
+public int resolveLevel(ASTNode possiblelMatchingNode) {
+	if (this.pattern.findReferences)
+		if (possiblelMatchingNode instanceof NameReference)
+			return resolveLevel((NameReference) possiblelMatchingNode);
+	if (possiblelMatchingNode instanceof LocalDeclaration)
+		return matchLocalVariable(((LocalDeclaration) possiblelMatchingNode).binding, true);
+	return IMPOSSIBLE_MATCH;
+}
+public int resolveLevel(Binding binding) {
+	if (binding == null) return INACCURATE_MATCH;
+	if (!(binding instanceof LocalVariableBinding)) return IMPOSSIBLE_MATCH;
+
+	return matchLocalVariable((LocalVariableBinding) binding, true);
+}
+protected int resolveLevel(NameReference nameRef) {
+	return resolveLevel(nameRef.binding);
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/LocalVariablePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/LocalVariablePattern.java
new file mode 100644
index 0000000..e3c322b
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/LocalVariablePattern.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchParticipant;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.LocalVariable;
+import org.eclipse.jdt.internal.core.index.IIndex;
+import org.eclipse.jdt.internal.core.search.IndexQueryRequestor;
+
+public class LocalVariablePattern extends VariablePattern {
+	
+LocalVariable localVariable;
+
+public LocalVariablePattern(
+	boolean findDeclarations,
+	boolean readAccess,
+	boolean writeAccess,
+	LocalVariable localVariable,
+	int matchRule) {
+
+	super(LOCAL_VAR_PATTERN, findDeclarations, readAccess, writeAccess, localVariable.getElementName().toCharArray(), matchRule);
+	this.localVariable = localVariable;
+}
+public void decodeIndexKey(char[] key) {
+	// local variables are not indexed
+}
+public char[] encodeIndexKey() {
+	// local variables are not indexed
+	return null;
+}
+public void findIndexMatches(IIndex index, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope, IProgressMonitor progressMonitor) throws IOException {
+    IPackageFragmentRoot root = (IPackageFragmentRoot)this.localVariable.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+	String path;
+    if (root.isArchive()) {
+        IType type = (IType)this.localVariable.getAncestor(IJavaElement.TYPE);
+        String filePath = (type.getFullyQualifiedName('/')).replace('.', '/') + SuffixConstants.SUFFIX_STRING_class;
+        path = root.getPath() + IJavaSearchScope.JAR_FILE_ENTRY_SEPARATOR + filePath;
+    } else {
+        path = this.localVariable.getPath().toString();
+    }
+	if (scope.encloses(path)) {
+		if (!requestor.acceptIndexMatch(path, this, participant)) 
+			throw new OperationCanceledException();
+	}
+}
+public SearchPattern getIndexRecord() {
+	// local variables are not indexed
+	return null;
+}
+public char[][] getMatchCategories() {
+	// local variables are not indexed
+	return CharOperation.NO_CHAR_CHAR;
+}
+public boolean isMatchingIndexRecord() {
+	// local variables are not indexed
+	return false;
+}
+public String toString() {
+	StringBuffer buffer = new StringBuffer(20);
+	if (this.findDeclarations) {
+		buffer.append(this.findReferences
+			? "LocalVarCombinedPattern: " //$NON-NLS-1$
+			: "LocalVarDeclarationPattern: "); //$NON-NLS-1$
+	} else {
+		buffer.append("LocalVarReferencePattern: "); //$NON-NLS-1$
+	}
+	buffer.append(this.localVariable.toStringWithAncestors());
+	buffer.append(", "); //$NON-NLS-1$
+	switch(matchMode()){
+		case EXACT_MATCH : 
+			buffer.append("exact match, "); //$NON-NLS-1$
+			break;
+		case PREFIX_MATCH :
+			buffer.append("prefix match, "); //$NON-NLS-1$
+			break;
+		case PATTERN_MATCH :
+			buffer.append("pattern match, "); //$NON-NLS-1$
+			break;
+	}
+	buffer.append(isCaseSensitive() ? "case sensitive" : "case insensitive"); //$NON-NLS-1$ //$NON-NLS-2$
+	return buffer.toString();
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
index ee2dd4f..4551fc1 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
@@ -14,14 +14,12 @@
 import java.util.HashMap;
 import java.util.zip.ZipFile;
 
-import org.eclipse.core.resources.*;
+import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.*;
 import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.compiler.InvalidInputException;
-import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
 import org.eclipse.jdt.internal.compiler.ast.*;
@@ -32,1035 +30,251 @@
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
 import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.parser.Scanner;
-import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
-import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
-import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
-import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
-import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.hierarchy.HierarchyResolver;
 import org.eclipse.jdt.internal.core.search.HierarchyScope;
-/**
- * Locate matches in compilation units.
- */
+import org.eclipse.jdt.internal.core.search.JavaSearchParticipant;
+import org.eclipse.jdt.internal.core.util.HandleFactory;
+import org.eclipse.jdt.internal.core.util.SimpleSet;
+import org.eclipse.jdt.internal.core.util.Util;
+
 public class MatchLocator implements ITypeRequestor {
-	public SearchPattern pattern;
-	public int detailLevel;
-	public IJavaSearchResultCollector collector;
-	public IJavaSearchScope scope;
 
-	public MatchLocatorParser parser;
-	public INameEnvironment nameEnvironment;
-	public NameLookup nameLookup;
-	public LookupEnvironment lookupEnvironment;
-	public HashtableOfObject parsedUnits;
-	public MatchingOpenableSet matchingOpenables;
-	private MatchingOpenable currentMatchingOpenable;
-	public HandleFactory handleFactory;
-	public IWorkingCopy[] workingCopies;
-	public HierarchyResolver hierarchyResolver;
-	
-	public IProgressMonitor progressMonitor;
+public static final int MAX_AT_ONCE = 500;
 
-	final static char[] EMPTY_FILE_NAME = CharOperation.NO_CHAR;
-	boolean compilationAborted;
+// permanent state
+public SearchPattern pattern;
+public PatternLocator patternLocator;
+public int matchContainer;
+public SearchRequestor requestor;
+public IJavaSearchScope scope;
+public IProgressMonitor progressMonitor;
 
-	public MatchLocator(
-		SearchPattern pattern,
-		int detailLevel,
-		IJavaSearchResultCollector collector,
-		IJavaSearchScope scope,
-		IProgressMonitor progressMonitor) {
+public org.eclipse.jdt.core.ICompilationUnit[] workingCopies;
+public HandleFactory handleFactory;
 
-		this.pattern = pattern;
-		this.detailLevel = detailLevel;
-		this.collector = collector;
-		this.scope = scope;
-		this.progressMonitor = progressMonitor;
+// cache of all super type names if scope is hierarchy scope
+public char[][][] allSuperTypeNames;
+
+// the following is valid for the current project
+public MatchLocatorParser parser;
+private Parser basicParser;
+public INameEnvironment nameEnvironment;
+public NameLookup nameLookup;
+public LookupEnvironment lookupEnvironment;
+public HierarchyResolver hierarchyResolver;
+
+public CompilerOptions options;
+
+// management of PossibleMatch to be processed
+public int numberOfMatches; // (numberOfMatches - 1) is the last unit in matchesToProcess
+public PossibleMatch[] matchesToProcess;
+public PossibleMatch currentPossibleMatch;
+
+/*
+ * Time spent in the IJavaSearchResultCollector
+ */
+public long resultCollectorTime = 0;
+
+/**
+ * An ast visitor that visits local type declarations.
+ */
+public class LocalDeclarationVisitor extends ASTVisitor {
+	IJavaElement enclosingElement;
+	MatchingNodeSet nodeSet;
+	// TODO (jerome) Use an HashtableOfIntValues instead
+	HashMap occurrencesCounts = new HashMap(); // key = class name (String), value = occurrenceCount (Integer)
+	public LocalDeclarationVisitor(IJavaElement enclosingElement, MatchingNodeSet nodeSet) {
+		this.enclosingElement = enclosingElement;
+		this.nodeSet = nodeSet;
 	}
-	
-	/**
-	 * Add an additional binary type
-	 */
-	public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
-		BinaryTypeBinding binaryBinding =  new BinaryTypeBinding(packageBinding, binaryType, this.lookupEnvironment);
-		ReferenceBinding cachedType = this.lookupEnvironment.getCachedType(binaryBinding.compoundName);
-		if (cachedType == null || cachedType instanceof UnresolvedReferenceBinding) { // NB: cachedType is not null if already cached as a source type
-			this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+	public boolean visit(TypeDeclaration typeDeclaration, BlockScope unused) {
+		try {
+			String simpleName;
+			if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {				
+				simpleName = ""; //$NON-NLS-1$
+			} else {
+				simpleName = new String(typeDeclaration.name);
+			}
+			Integer occurrenceCount = (Integer)occurrencesCounts.get(simpleName);
+			if (occurrenceCount == null) {
+				occurrenceCount = new Integer(1);
+			} else {
+				occurrenceCount = new Integer(occurrenceCount.intValue()+1);
+			}
+			occurrencesCounts.put(simpleName, occurrenceCount);
+			if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {				
+				reportMatching(typeDeclaration, enclosingElement, -1, nodeSet, occurrenceCount.intValue());
+			} else {
+				Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeDeclaration);
+				reportMatching(typeDeclaration, enclosingElement, level != null ? level.intValue() : -1, nodeSet, occurrenceCount.intValue());
+			}
+			return false; // don't visit members as this was done during reportMatching(...)
+		} catch (CoreException e) {
+			throw new WrappedCoreException(e);
 		}
 	}
+}
 
-	/**
-	 * Add an additional compilation unit.
-	 */
-	public void accept(ICompilationUnit sourceUnit) {
-		// diet parse
-		IFile file = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(new Path(new String(sourceUnit.getFileName())));
-		CompilationUnit compilationUnit = (CompilationUnit)JavaCore.create(file);
-		CompilationUnitDeclaration parsedUnit = this.parser.dietParse(sourceUnit, this, file, compilationUnit);
+public class WrappedCoreException extends RuntimeException {
+	public CoreException coreException;
+	public WrappedCoreException(CoreException coreException) {
+		this.coreException = coreException;
+	}
+}
 
-		// build bindings
-		this.lookupEnvironment.buildTypeBindings(parsedUnit);
-		this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
+public static ClassFileReader classFileReader(IType type) {
+	IClassFile classFile = type.getClassFile(); 
+	JavaModelManager manager = JavaModelManager.getJavaModelManager();
+	if (classFile.isOpen())
+		return (ClassFileReader) manager.getInfo(type);
+
+	IPackageFragment pkg = type.getPackageFragment();
+	IPackageFragmentRoot root = (IPackageFragmentRoot) pkg.getParent();
+	try {
+		if (!root.isArchive())
+			return ClassFileReader.read(type.getPath().toOSString());
+
+		IPath zipPath = root.isExternal() ? root.getPath() : root.getResource().getLocation();
+		if (zipPath == null) return null; // location is null
+		ZipFile zipFile = null;
+		try {
+			if (JavaModelManager.ZIP_ACCESS_VERBOSE)
+				System.out.println("(" + Thread.currentThread() + ") [MatchLocator.classFileReader()] Creating ZipFile on " + zipPath); //$NON-NLS-1$	//$NON-NLS-2$
+			zipFile = manager.getZipFile(zipPath);
+			char[] pkgPath = pkg.getElementName().toCharArray();
+			CharOperation.replace(pkgPath, '.', '/');
+			char[] classFileName = classFile.getElementName().toCharArray();
+			char[] path = pkgPath.length == 0 ? classFileName : CharOperation.concat(pkgPath, classFileName, '/');
+			return ClassFileReader.read(zipFile, new String(path));
+		} finally {
+			manager.closeZipFile(zipFile);
+		}
+	} catch (ClassFormatException e) {
+		// invalid class file: return null
+	} catch (CoreException e) {
+		// cannot read class file: return null
+	} catch (IOException e) {
+		// cannot read class file: return null
+	}
+	return null;
+}
+
+public MatchLocator(
+	SearchPattern pattern,
+	SearchRequestor requestor,
+	IJavaSearchScope scope,
+	org.eclipse.jdt.core.ICompilationUnit[] workingCopies,
+	IProgressMonitor progressMonitor) {
 		
-		// remember parsed unit
-		ImportReference pkg = parsedUnit.currentPackage;
-		char[][] packageName = pkg == null ? null : pkg.tokens;
-		char[] mainTypeName = sourceUnit.getMainTypeName();
-		char[] qualifiedName = packageName == null ? mainTypeName : CharOperation.concatWith(packageName, mainTypeName, '.');
-		this.parsedUnits.put(qualifiedName, parsedUnit);
-	}
-
-	/**
-	 * Add an additional source type
-	 */
-	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
-		ISourceType sourceType = sourceTypes[0];
-		while (sourceType.getEnclosingType() != null)
-			sourceType = sourceType.getEnclosingType();
-		if (sourceType instanceof SourceTypeElementInfo) {
-			// get source
-			SourceTypeElementInfo elementInfo = (SourceTypeElementInfo) sourceType;
-			IType type = elementInfo.getHandle();
-			ICompilationUnit sourceUnit = (ICompilationUnit)type.getCompilationUnit();
-			this.accept(sourceUnit);
+	this.pattern = pattern;
+	this.patternLocator = PatternLocator.patternLocator(this.pattern);
+	this.matchContainer = this.patternLocator.matchContainer();
+	this.requestor = requestor;
+	this.scope = scope;
+	this.workingCopies = workingCopies;
+	this.progressMonitor = progressMonitor;
+}
+/**
+ * Add an additional binary type
+ */
+public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
+	this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+}
+/**
+ * Add an additional compilation unit into the loop
+ *  ->  build compilation unit declarations, their bindings and record their results.
+ */
+public void accept(ICompilationUnit sourceUnit) {
+	// Switch the current policy and compilation result for this unit to the requested one.
+	CompilationResult unitResult = new CompilationResult(sourceUnit, 1, 1, this.options.maxProblemsPerUnit);
+	try {
+		CompilationUnitDeclaration parsedUnit = basicParser().dietParse(sourceUnit, unitResult);
+		lookupEnvironment.buildTypeBindings(parsedUnit);
+		lookupEnvironment.completeTypeBindings(parsedUnit, true);
+	} catch (AbortCompilationUnit e) {
+		// at this point, currentCompilationUnitResult may not be sourceUnit, but some other
+		// one requested further along to resolve sourceUnit.
+		if (unitResult.compilationUnit == sourceUnit) { // only report once
+			//requestor.acceptResult(unitResult.tagAsAccepted());
 		} else {
-			CompilationResult result =
-				new CompilationResult(sourceType.getFileName(), 0, 0, 0);
-			CompilationUnitDeclaration unit =
-				SourceTypeConverter.buildCompilationUnit(
-					sourceTypes,//sourceTypes[0] is always toplevel here
-					true, // need field and methods
-					true, // need member types
-					false, // no need for field initialization
-					lookupEnvironment.problemReporter,
-					result);
-			this.lookupEnvironment.buildTypeBindings(unit);
-			this.lookupEnvironment.completeTypeBindings(unit, true);
-			this.parsedUnits.put(sourceType.getQualifiedName(), unit);
+			throw e; // want to abort enclosing request to compile
 		}
 	}
-
-
-
-	/**
-	 * Creates an IField from the given field declaration and type. 
-	 */
-	public IField createFieldHandle(
-		FieldDeclaration field,
-		IType type) {
-		if (type == null) return null;
-		return type.getField(new String(field.name));
+}
+/**
+ * Add additional source types
+ */
+public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
+	// case of SearchableEnvironment of an IJavaProject is used
+	ISourceType sourceType = sourceTypes[0];
+	while (sourceType.getEnclosingType() != null)
+		sourceType = sourceType.getEnclosingType();
+	if (sourceType instanceof SourceTypeElementInfo) {
+		// get source
+		SourceTypeElementInfo elementInfo = (SourceTypeElementInfo) sourceType;
+		IType type = elementInfo.getHandle();
+		ICompilationUnit sourceUnit = (ICompilationUnit) type.getCompilationUnit();
+		accept(sourceUnit);
+	} else {
+		CompilationResult result = new CompilationResult(sourceType.getFileName(), 1, 1, 0);
+		CompilationUnitDeclaration unit =
+			SourceTypeConverter.buildCompilationUnit(
+				sourceTypes,
+				SourceTypeConverter.FIELD_AND_METHOD // need field and methods
+				| SourceTypeConverter.MEMBER_TYPE, // need member types
+				// no need for field initialization
+				lookupEnvironment.problemReporter,
+				result);
+		this.lookupEnvironment.buildTypeBindings(unit);
+		this.lookupEnvironment.completeTypeBindings(unit, true);
 	}
-
-	/**
-	 * Creates an IImportDeclaration from the given import statement
-	 */
-	public IJavaElement createImportHandle(ImportReference importRef) {
-		char[] importName = CharOperation.concatWith(importRef.getImportName(), '.');
-		if (importRef.onDemand) {
-			importName = CharOperation.concat(importName, ".*" .toCharArray()); //$NON-NLS-1$
-		}
-		Openable currentOpenable = this.getCurrentOpenable();
-		if (currentOpenable instanceof CompilationUnit) {
-			return ((CompilationUnit)currentOpenable).getImport(
-				new String(importName));
-		} else {
-			try {
-				return ((org.eclipse.jdt.internal.core.ClassFile)currentOpenable).getType();
-			} catch (JavaModelException e) {
-				return null;
-			}
-		}
-	}
-
-	/**
-	 * Creates an IInitializer from the given field declaration and type. 
-	 */
-	public IInitializer createInitializerHandle(
-		TypeDeclaration typeDecl,
-		FieldDeclaration initializer,
-		IType type) {
-		if (type == null) return null;
-
-		// find occurence count of the given initializer in its type declaration
-		int occurrenceCount = 0;
-		FieldDeclaration[] fields = typeDecl.fields;
-		for (int i = 0, length = fields.length; i < length; i++) {
-			FieldDeclaration field = fields[i];
-			if (!field.isField()) {
-				occurrenceCount++;
-				if (field.equals(initializer)) {
-					break;
-				}
-			}
-		}
-
-		return type.getInitializer(occurrenceCount);
-	}
-
-	/**
-	 * Creates an IMethod from the given method declaration and type. 
-	 */
-	public IMethod createMethodHandle(
-		AbstractMethodDeclaration method,
-		IType type) {
-		if (type == null) return null;
-		Argument[] arguments = method.arguments;
-		int length = arguments == null ? 0 : arguments.length;
-		if (type.isBinary()) {
-			// don't cache the methods of the binary type
-			ClassFileReader reader = this.classFileReader(type);
-			if (reader == null) return null;
-			IBinaryMethod[] methods = reader.getMethods();
-
-			if (methods != null) {
-				for (int i = 0, methodsLength = methods.length; i < methodsLength; i++) {
-					IBinaryMethod binaryMethod = methods[i];
-					char[] selector = binaryMethod.isConstructor() ? type.getElementName().toCharArray() : binaryMethod.getSelector();
-					if (CharOperation.equals(selector, method.selector)) {
-						String[] parameterTypes = Signature.getParameterTypes(new String(binaryMethod.getMethodDescriptor()));
-						if (length != parameterTypes.length) continue;
-						boolean sameParameters = true;
-						for (int j = 0; j < length; j++) {
-							TypeReference parameterType = arguments[j].type;
-							char[] typeName = CharOperation.concatWith(parameterType.getTypeName(), '.');
-							for (int k = 0; k < parameterType.dimensions(); k++) {
-								typeName = CharOperation.concat(typeName, "[]" .toCharArray()); //$NON-NLS-1$
-							}
-							String parameterTypeName = parameterTypes[j].replace('/', '.');
-							if (!Signature.toString(parameterTypeName).endsWith(new String(typeName))) {
-								sameParameters = false;
-								break;
-							} else {
-								parameterTypes[j] = parameterTypeName;
-							}
-						}
-						if (sameParameters) {
-							return type.getMethod(new String(selector), parameterTypes);
-						}
-					}
-				}
-			}
-			return null;
-		} else {
-			String[] parameterTypeSignatures = new String[length];
-			for (int i = 0; i < length; i++) {
-				TypeReference parameterType = arguments[i].type;
-				char[] typeName = CharOperation.concatWith(parameterType.getTypeName(), '.');
-				for (int j = 0; j < parameterType.dimensions(); j++) {
-					typeName = CharOperation.concat(typeName, "[]" .toCharArray()); //$NON-NLS-1$
-				}
-				parameterTypeSignatures[i] = Signature.createTypeSignature(typeName, false);
-			}
-			return type.getMethod(new String(method.selector), parameterTypeSignatures);
-		}
-	}
-
-	private ClassFileReader classFileReader(IType type) {
-		IClassFile classFile = type.getClassFile(); 
-		if (((IOpenable)classFile).isOpen()) {
-			JavaModelManager manager = JavaModelManager.getJavaModelManager();
-			synchronized(manager){
-				return (ClassFileReader)manager.getInfo(type);
-			}
-		} else {
-			IPackageFragment pkg = type.getPackageFragment();
-			IPackageFragmentRoot root = (IPackageFragmentRoot)pkg.getParent();
-			try {
-				if (root.isArchive()) {
-					IPath zipPath = root.isExternal() ? root.getPath() : root.getResource().getLocation();
-					if (zipPath == null) return null; // location is null
-					ZipFile zipFile = null;
-					try {
-						if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
-							System.out.println("(" + Thread.currentThread() + ") [MatchLocator.classFileReader()] Creating ZipFile on " + zipPath); //$NON-NLS-1$	//$NON-NLS-2$
-						}
-						zipFile = new ZipFile(zipPath.toOSString());
-						char[] pkgPath = pkg.getElementName().toCharArray();
-						CharOperation.replace(pkgPath, '.', '/');
-						char[] classFileName = classFile.getElementName().toCharArray();
-						char[] path = pkgPath.length == 0 ? classFileName : CharOperation.concat(pkgPath, classFileName, '/');
-						return ClassFileReader.read(zipFile, new String(path));
-					} finally {
-						if (zipFile != null) {
-							try {
-								zipFile.close();
-							} catch (IOException e) {
-							}
-						}
-					}
-				} else {
-					return ClassFileReader.read(type.getPath().toOSString());
-				}
-			} catch (ClassFormatException e) {
-				return null;
-			} catch (IOException e) {
-				return null;
-			}
-		}
-	}
-
-	/**
-	 * Creates an IType from the given simple top level type name. 
-	 */
-	public IType createTypeHandle(char[] simpleTypeName) {
-		Openable currentOpenable = this.getCurrentOpenable();
-		if (currentOpenable instanceof CompilationUnit) {
-			// creates compilation unit
-			CompilationUnit unit = (CompilationUnit)currentOpenable;
-	
-			// create type
-			return unit.getType(new String(simpleTypeName));
-		} else {
-			IType type; 
-			try {
-				type = ((org.eclipse.jdt.internal.core.ClassFile)currentOpenable).getType();
-			} catch (JavaModelException e) {
-				return null;
-			}
-			// ensure this is a top level type (see bug 20011  Searching for Inner Classes gives bad search results)
-			return MatchingOpenable.getTopLevelType(type);
-		}
-	}
-	/**
-	 * Creates an IType from the given simple inner type name and parent type. 
-	 */
-	public IType createTypeHandle(IType parent, char[] simpleTypeName) {
-		return parent.getType(new String(simpleTypeName));
-	}
-	protected IResource getCurrentResource() {
-		return this.currentMatchingOpenable.resource;
-	}
-
-	protected Scanner getScanner() {
-		return this.parser == null ? null : this.parser.scanner;
-	}
-
-	/**
-	 * Create a new parser for the given project, as well as a lookup environment.
-	 */
-	public void initialize(JavaProject project) throws JavaModelException {
-		// create lookup environment
-		CompilerOptions options = new CompilerOptions(project.getOptions(true));
+}	
+protected Parser basicParser() {
+	if (this.basicParser == null) {
 		ProblemReporter problemReporter =
 			new ProblemReporter(
 				DefaultErrorHandlingPolicies.proceedWithAllProblems(),
-				options,
+				this.options,
 				new DefaultProblemFactory());
-		this.lookupEnvironment =
-			new LookupEnvironment(this, options, problemReporter, this.nameEnvironment);
-			
-		// create parser
-		this.parser = new MatchLocatorParser(problemReporter, options.sourceLevel >= CompilerOptions.JDK1_4);
-		
-		// reset parsed units (they could hold onto obsolete bindings: see bug 16052)
-		MatchingOpenable[] openables = this.matchingOpenables.getMatchingOpenables(project.getPackageFragmentRoots());
-		for (int i = 0, length = openables.length; i < length; i++) {
-			MatchingOpenable matchingOpenable = openables[i];
-			matchingOpenable.reset();
-		}
-		this.parsedUnits = new HashtableOfObject(10);
-		
-		// remember project's name lookup
-		this.nameLookup = project.getNameLookup();
+		this.basicParser = new Parser(problemReporter, false);
 	}
-
-	public void initializeNameEnvironment(JavaProject project) throws JavaModelException {
-		// cleanup and recreate file name environment
-		if (this.nameEnvironment != null) {
-			this.nameEnvironment.cleanup();
-		}
-		this.nameEnvironment = this.getNameEnvironment(project);
-	}
-
-	/**
-	 * Locate the matches in the given files and report them using the search requestor. 
-	 */
-	public void locateMatches(
-		String[] filePaths, 
-		IWorkspace workspace,
-		IWorkingCopy[] workingCopies)
-		throws JavaModelException {
-			
-		if (SearchEngine.VERBOSE) {
-			System.out.println("Locating matches in files ["); //$NON-NLS-1$
-			for (int i = 0, length = filePaths.length; i < length; i++) {
-				String path = filePaths[i];
-				System.out.println("\t" + path); //$NON-NLS-1$
-			}
-			System.out.println("]"); //$NON-NLS-1$
-			if (workingCopies != null) {
-				 System.out.println(" and working copies ["); //$NON-NLS-1$
-				for (int i = 0, length = workingCopies.length; i < length; i++) {
-					IWorkingCopy wc = workingCopies[i];
-					System.out.println("\t" + ((JavaElement)wc).toStringWithAncestors()); //$NON-NLS-1$
-				}
-				System.out.println("]"); //$NON-NLS-1$
-			}
-		}
-		
-		JavaModelManager manager = JavaModelManager.getJavaModelManager();
-		try {
-			// optimize access to zip files during search operation
-			manager.cacheZipFiles();
-				
-			// initialize handle factory (used as a cache of handles so as to optimize space)
-			if (this.handleFactory == null) {
-				this.handleFactory = new HandleFactory(workspace);
-			}
-			
-			// initialize locator with working copies
-			this.workingCopies = workingCopies;
-			
-			// substitute compilation units with working copies
-			HashMap wcPaths = new HashMap(); // a map from path to working copies
-			int wcLength;
-			if (workingCopies != null && (wcLength = workingCopies.length) > 0) {
-				String[] newPaths = new String[wcLength];
-				for (int i = 0; i < wcLength; i++) {
-					IWorkingCopy workingCopy = workingCopies[i];
-					String path = workingCopy.getOriginalElement().getPath().toString();
-					wcPaths.put(path, workingCopy);
-					newPaths[i] = path;
-				}
-				int filePathsLength = filePaths.length;
-				System.arraycopy(filePaths, 0, filePaths = new String[filePathsLength+wcLength], 0, filePathsLength);
-				System.arraycopy(newPaths, 0, filePaths, filePathsLength, wcLength);
-			}
-			
-			int length = filePaths.length;
-			if (progressMonitor != null) {
-				if (this.pattern.needsResolve) {
-					progressMonitor.beginTask("", length * 10); // 1 for file path, 3 for parsing, 6 for binding resolution //$NON-NLS-1$
-				} else {
-					progressMonitor.beginTask("", length * 4); // 1 for file path, 3 for parsing //$NON-NLS-1$
-				}
-			}
-	
-			// sort file paths projects
-			Util.sort(filePaths); 
-			
-			// initialize pattern for polymorphic search (ie. method reference pattern)
-			this.matchingOpenables = new MatchingOpenableSet();
-			this.pattern.initializePolymorphicSearch(this, progressMonitor);
-			
-			JavaProject previousJavaProject = null;
-			for (int i = 0; i < length; i++) {
-				if (progressMonitor != null && progressMonitor.isCanceled()) {
-					throw new OperationCanceledException();
-				}
-				String pathString = filePaths[i];
-				
-				// skip duplicate paths
-				if (i > 0 && pathString.equals(filePaths[i-1])) continue;
-				
-				Openable openable;
-				IWorkingCopy workingCopy = (IWorkingCopy)wcPaths.get(pathString);
-				if (workingCopy != null) {
-					openable = (Openable)workingCopy;
-				} else {
-					openable = this.handleFactory.createOpenable(pathString, this.scope);
-					if (openable == null)
-						continue; // match is outside classpath
-				}
-	
-				// create new parser and lookup environment if this is a new project
-				IResource resource = null;
-				JavaProject javaProject = null;
-				try {
-					javaProject = (JavaProject) openable.getJavaProject();
-					if (workingCopy != null) {
-						resource = workingCopy.getOriginalElement().getResource();
-					} else {
-						resource = openable.getResource();
-					}
-					if (resource == null) { // case of a file in an external jar
-						resource = javaProject.getProject();
-					}
-					if (!javaProject.equals(previousJavaProject)) {
-						// locate matches in previous project
-						if (previousJavaProject != null) {
-							try {
-								this.locateMatches(previousJavaProject);
-							} catch (JavaModelException e) {
-								if (e.getException() instanceof CoreException) {
-									throw e;
-								} else {
-									// problem with classpath in this project -> skip it
-								}
-							}
-							this.matchingOpenables = new MatchingOpenableSet();
-						}
-	
-						// initialization for this project
-						if (length == 1) {
-							// if only one potential match, a file name environment costs too much,
-							// so use the existing searchable  environment wich will populate the java model
-							// only for this potential match and its required types.
-							if (this.nameEnvironment != null) { // cleanup
-								this.nameEnvironment.cleanup();
-							}
-							this.nameEnvironment = javaProject.getSearchableNameEnvironment();
-						} else {
-							this.initializeNameEnvironment(javaProject);
-						}
-						this.initialize(javaProject);
-						previousJavaProject = javaProject;
-					}
-				} catch (JavaModelException e) {
-					// file doesn't exist -> skip it
-					continue;
-				}
-	
-				// add matching openable
-				this.addMatchingOpenable(resource, openable, null/*no CompilationUnitDeclaration yet*/, null/*no Matchset yet*/);
-	
-				if (progressMonitor != null) {
-					progressMonitor.worked(1);
-				}
-			}
-			
-			// last project
-			if (previousJavaProject != null) {
-				try {
-					this.locateMatches(previousJavaProject);
-				} catch (JavaModelException e) {
-					if (e.getException() instanceof CoreException) {
-						throw e;
-					} else {
-						// problem with classpath in last project -> skip it
-					}
-				}
-				this.matchingOpenables = new MatchingOpenableSet();
-			} 
-			
-			if (progressMonitor != null) {
-				progressMonitor.done();
-			}
-		} finally {
-			if (this.nameEnvironment != null) {
-				this.nameEnvironment.cleanup();
-			}
-			this.parsedUnits = null;
-			manager.flushZipFiles();
-		}	
-	}
-
-	/**
-	 * Locates the package declarations corresponding to this locator's pattern. 
-	 */
-	public void locatePackageDeclarations(IWorkspace workspace)
-		throws JavaModelException {
-		this.locatePackageDeclarations(this.pattern, workspace);
-	}
-
-	/**
-	 * Locates the package declarations corresponding to the search pattern. 
-	 */
-	private void locatePackageDeclarations(
-		SearchPattern searchPattern,
-		IWorkspace workspace)
-		throws JavaModelException {
-		if (searchPattern instanceof OrPattern) {
-			OrPattern orPattern = (OrPattern) searchPattern;
-			this.locatePackageDeclarations(orPattern.leftPattern, workspace);
-			this.locatePackageDeclarations(orPattern.rightPattern, workspace);
-		} else
-			if (searchPattern instanceof PackageDeclarationPattern) {
-				PackageDeclarationPattern pkgPattern =
-					(PackageDeclarationPattern) searchPattern;
-				IJavaProject[] projects =
-					JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
-				for (int i = 0, length = projects.length; i < length; i++) {
-					IJavaProject javaProject = projects[i];
-					IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
-					for (int j = 0, rootsLength = roots.length; j < rootsLength; j++) {
-						IJavaElement[] pkgs = roots[j].getChildren();
-						for (int k = 0, pksLength = pkgs.length; k < pksLength; k++) {
-							IPackageFragment pkg = (IPackageFragment)pkgs[k];
-							if (pkg.getChildren().length > 0 
-									&& pkgPattern.matchesName(pkgPattern.pkgName, pkg.getElementName().toCharArray())) {
-								IResource resource = pkg.getResource();
-								if (resource == null) { // case of a file in an external jar
-									resource = javaProject.getProject();
-								}
-								this.currentMatchingOpenable = new MatchingOpenable(this, resource, null, null, null);
-								try {
-									this.report(-1, -2, pkg, IJavaSearchResultCollector.EXACT_MATCH);
-								} catch (CoreException e) {
-									if (e instanceof JavaModelException) {
-										throw (JavaModelException) e;
-									} else {
-										throw new JavaModelException(e);
-									}
-								}
-							}
-						}
-					}
-				}
-			}
-	}
-public IType lookupType(TypeBinding typeBinding) {
-	char[] packageName = typeBinding.qualifiedPackageName();
-	char[] typeName = typeBinding.qualifiedSourceName();
-	
-	// find package fragments
-	IPackageFragment[] pkgs = 
-		this.nameLookup.findPackageFragments(
-			(packageName == null || packageName.length == 0) ? 
-				IPackageFragment.DEFAULT_PACKAGE_NAME : 
-				new String(packageName), 
-			false);
-			
-	// iterate type lookup in each package fragment
-	for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) {
-		IType type = 
-			this.nameLookup.findType(
-				new String(typeName), 
-				pkgs[i], 
-				false, 
-				typeBinding.isClass() ?
-					NameLookup.ACCEPT_CLASSES:
-					NameLookup.ACCEPT_INTERFACES);
-		if (type != null) return type;	
-	}
-	
-	// search inside enclosing element
-	char[][] qualifiedName = CharOperation.splitOn('.', typeName);
-	int length = qualifiedName.length;
-	if (length == 0) return null;
-	IType type = this.createTypeHandle(qualifiedName[0]);
-	if (type == null) return null;
-	for (int i = 1; i < length; i++) {
-		type = this.createTypeHandle(type, qualifiedName[i]);
-		if (type == null) return null;
-	}
-	if (type.exists()) return type;	
-	
-	return null;
+	return this.basicParser;
 }
-	public void report(
-		int sourceStart,
-		int sourceEnd,
-		IJavaElement element,
-		int accuracy)
-		throws CoreException {
+/**
+ * Add the possibleMatch to the loop
+ *  ->  build compilation unit declarations, their bindings and record their results.
+ */
+protected void buildBindings(PossibleMatch possibleMatch) {
+	if (this.progressMonitor != null && this.progressMonitor.isCanceled())
+		throw new OperationCanceledException();
 
-		if (this.scope.encloses(element)) {
-			if (SearchEngine.VERBOSE) {
-				IResource res = this.getCurrentResource();
-				System.out.println("Reporting match"); //$NON-NLS-1$
-				System.out.println("\tResource: " + (res == null ? " <unknown> " : res.getFullPath().toString())); //$NON-NLS-2$//$NON-NLS-1$
-				System.out.println("\tPositions: [" + sourceStart + ", " + sourceEnd + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-				System.out.println("\tJava element: " + ((JavaElement)element).toStringWithAncestors()); //$NON-NLS-1$
-				if (accuracy == IJavaSearchResultCollector.EXACT_MATCH) {
-					System.out.println("\tAccuracy: EXACT_MATCH"); //$NON-NLS-1$
-				} else {
-					System.out.println("\tAccuracy: POTENTIAL_MATCH"); //$NON-NLS-1$
-				}
-			}
-			this.report(
-				this.getCurrentResource(),
-				sourceStart,
-				sourceEnd,
-				element,
-				accuracy);
+	try {
+		if (SearchEngine.VERBOSE)
+			System.out.println("Parsing " + possibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
+
+		this.parser.nodeSet = possibleMatch.nodeSet;
+		CompilationResult unitResult = new CompilationResult(possibleMatch, 1, 1, this.options.maxProblemsPerUnit);
+		CompilationUnitDeclaration parsedUnit = this.parser.dietParse(possibleMatch, unitResult);
+		if (parsedUnit != null) {
+			if (!parsedUnit.isEmpty())
+				this.lookupEnvironment.buildTypeBindings(parsedUnit);
+
+			// add the possibleMatch with its parsedUnit to matchesToProcess
+			possibleMatch.parsedUnit = parsedUnit;
+			int size = this.matchesToProcess.length;
+			if (this.numberOfMatches == size)
+				System.arraycopy(this.matchesToProcess, 0, this.matchesToProcess = new PossibleMatch[size == 0 ? 1 : size * 2], 0, this.numberOfMatches);
+			this.matchesToProcess[this.numberOfMatches++] = possibleMatch;
+
+			if (this.progressMonitor != null)
+				this.progressMonitor.worked(4);
 		}
-	}
-	public void report(
-		IResource resource,
-		int sourceStart,
-		int sourceEnd,
-		IJavaElement element,
-		int accuracy)
-		throws CoreException {
-
-		this.collector.accept(
-			resource,
-			sourceStart,
-			sourceEnd + 1,
-			element,
-			accuracy);
-	}
-
-	public void reportBinaryMatch(
-		IMember binaryMember,
-		IBinaryType info,
-		int accuracy)
-		throws CoreException, JavaModelException {
-			
-		this.reportBinaryMatch(null, binaryMember, info, accuracy);
-	}
-	public void reportBinaryMatch(
-		IResource resource,
-		IMember binaryMember,
-		IBinaryType info,
-		int accuracy)
-		throws CoreException, JavaModelException {
-		ISourceRange range = binaryMember.getNameRange();
-		if (range.getOffset() == -1) {
-			ClassFile classFile = (ClassFile) binaryMember.getClassFile();
-			SourceMapper mapper = classFile.getSourceMapper();
-			if (mapper != null) {
-				IType type = classFile.getType();
-				String sourceFileName = mapper.findSourceFileName(type, info);
-				if (sourceFileName != null) {
-					char[] contents = mapper.findSource(type, sourceFileName);
-					if (contents != null) {
-						range = mapper.mapSource(type, contents, binaryMember);
-					}
-				}
-			}
-		}
-		int startIndex = range.getOffset();
-		int endIndex = startIndex + range.getLength() - 1;
-		if (resource == null) {
-			this.report(startIndex, endIndex, binaryMember, accuracy);
-		} else {
-			this.report(resource, startIndex, endIndex, binaryMember, accuracy);
-		}
-	}
-
-	/**
-	 * Reports the given field declaration to the search requestor.
-	 */
-	public void reportFieldDeclaration(
-		FieldDeclaration fieldDeclaration,
-		IJavaElement parent,
-		int accuracy)
-		throws CoreException {
-
-		// accept field declaration
-		this.report(
-			fieldDeclaration.sourceStart,
-			fieldDeclaration.sourceEnd,
-			(parent instanceof IType) ?
-				((IType)parent).getField(new String(fieldDeclaration.name)) :
-				parent,
-			accuracy);
-	}
-
-	/**
-	 * Reports the given import to the search requestor.
-	 */
-	public void reportImport(ImportReference reference, int accuracy)
-		throws CoreException {
-
-		// create defining import handle
-		IJavaElement importHandle = this.createImportHandle(reference);
-
-		// accept reference
-		this.pattern.matchReportImportRef(reference, null, importHandle, accuracy, this);
-	}
-
-	/**
-	 * Reports the given method declaration to the search requestor.
-	 */
-	public void reportMethodDeclaration(
-		AbstractMethodDeclaration methodDeclaration,
-		IJavaElement parent,
-		int accuracy)
-		throws CoreException {
-
-		IJavaElement enclosingElement;
-		if (parent instanceof IType) {
-			// create method handle
-			enclosingElement = this.createMethodHandle(methodDeclaration, (IType)parent);
-			if (enclosingElement == null) return;
-		} else {
-			enclosingElement = parent;
-		}
-
-		// compute source positions of the selector 
-		Scanner scanner = parser.scanner;
-		int nameSourceStart = methodDeclaration.sourceStart;
-		scanner.setSource(
-			this.currentMatchingOpenable.getSource());
-		scanner.resetTo(nameSourceStart, methodDeclaration.sourceEnd);
-		try {
-			scanner.getNextToken();
-		} catch (InvalidInputException e) {
-		}
-		int nameSourceEnd = scanner.currentPosition - 1;
-
-		// accept method declaration
-		this.report(nameSourceStart, nameSourceEnd, enclosingElement, accuracy);
-	}
-
-	/**
-	 * Reports the given package declaration to the search requestor.
-	 */
-	public void reportPackageDeclaration(ImportReference node) {
-		// TBD
-	}
-
-	/**
-	 * Reports the given package reference to the search requestor.
-	 */
-	public void reportPackageReference(ImportReference node) {
-		// TBD
-	}
-
-	/**
-	 * Finds the accurate positions of the sequence of tokens given by qualifiedName
-	 * in the source and reports a reference to this this qualified name
-	 * to the search requestor.
-	 */
-	public void reportAccurateReference(
-		int sourceStart,
-		int sourceEnd,
-		char[][] qualifiedName,
-		IJavaElement element,
-		int accuracy)
-		throws CoreException {
-	
-		if (accuracy == -1) return;
-	
-		// compute source positions of the qualified reference 
-		Scanner scanner = parser.scanner;
-		scanner.setSource(
-			this.currentMatchingOpenable.getSource());
-		scanner.resetTo(sourceStart, sourceEnd);
-	
-		int refSourceStart = -1, refSourceEnd = -1;
-		int tokenNumber = qualifiedName.length;
-		int token = -1;
-		int previousValid = -1;
-		int i = 0;
-		int currentPosition;
-		do {
-			// find first token that is an identifier (parenthesized expressions include parenthesises in source range - see bug 20693 - Finding references to variables does not find all occurrences  )
-			do {
-				currentPosition = scanner.currentPosition;
-				try {
-					token = scanner.getNextToken();
-				} catch (InvalidInputException e) {
-				}
-			} while (token !=  TerminalTokens.TokenNameIdentifier && token !=  TerminalTokens.TokenNameEOF);
-	
-			if (token != TerminalTokens.TokenNameEOF) {
-				char[] currentTokenSource = scanner.getCurrentTokenSource();
-				boolean equals = false;
-				while (i < tokenNumber
-					&& !(equals = this.pattern.matchesName(qualifiedName[i++], currentTokenSource))) {
-				}
-				if (equals && (previousValid == -1 || previousValid == i - 2)) {
-					previousValid = i - 1;
-					if (refSourceStart == -1) {
-						refSourceStart = currentPosition;
-					}
-					refSourceEnd = scanner.currentPosition - 1;
-				} else {
-					i = 0;
-					refSourceStart = -1;
-					previousValid = -1;
-				}
-				// read '.'
-				try {
-					token = scanner.getNextToken();
-				} catch (InvalidInputException e) {
-				}
-			}
-			if (i == tokenNumber) {
-				// accept reference
-				if (refSourceStart != -1) {
-					this.report(refSourceStart, refSourceEnd, element, accuracy);
-				} else {
-					this.report(sourceStart, sourceEnd, element, accuracy);
-				}
-				return;
-			}
-		} while (token != TerminalTokens.TokenNameEOF);
-	
-	}
-	/**
-	 * Finds the accurate positions of each valid token in the source and
-	 * reports a reference to this token to the search requestor.
-	 * A token is valid if it has an accurracy which is not -1.
-	 */
-	public void reportAccurateReference(
-		int sourceStart,
-		int sourceEnd,
-		char[][] tokens,
-		IJavaElement element,
-		int[] accuracies)
-		throws CoreException {
-
-		// compute source positions of the qualified reference 
-		Scanner scanner = parser.scanner;
-		scanner.setSource(
-			this.currentMatchingOpenable.getSource());
-		scanner.resetTo(sourceStart, sourceEnd);
-
-		int refSourceStart = -1, refSourceEnd = -1;
-		int length = tokens.length;
-		int token = -1;
-		int previousValid = -1;
-		int i = 0;
-		int accuracyIndex = 0;
-		do {
-			int currentPosition = scanner.currentPosition;
-			// read token
-			try {
-				token = scanner.getNextToken();
-			} catch (InvalidInputException e) {
-			}
-			if (token != TerminalTokens.TokenNameEOF) {
-				char[] currentTokenSource = scanner.getCurrentTokenSource();
-				boolean equals = false;
-				while (i < length
-					&& !(equals = this.pattern.matchesName(tokens[i++], currentTokenSource))) {
-				}
-				if (equals && (previousValid == -1 || previousValid == i - 2)) {
-					previousValid = i - 1;
-					if (refSourceStart == -1) {
-						refSourceStart = currentPosition;
-					}
-					refSourceEnd = scanner.currentPosition - 1;
-				} else {
-					i = 0;
-					refSourceStart = -1;
-					previousValid = -1;
-				}
-				// read '.'
-				try {
-					token = scanner.getNextToken();
-				} catch (InvalidInputException e) {
-				}
-			}
-			if (accuracies[accuracyIndex] != -1) {
-				// accept reference
-				if (refSourceStart != -1) {
-					this.report(refSourceStart, refSourceEnd, element, accuracies[accuracyIndex]);
-				} else {
-					this.report(sourceStart, sourceEnd, element, accuracies[accuracyIndex]);
-				}
-				i = 0;
-			}
-			refSourceStart = -1;
-			previousValid = -1;
-			if (accuracyIndex < accuracies.length-1) {
-				accuracyIndex++;
-			}
-		} while (token != TerminalTokens.TokenNameEOF);
-
-	}
-
-	/**
-	 * Reports the given reference to the search requestor.
-	 * It is done in the given method and the method's defining types 
-	 * have the given simple names.
-	 */
-	public void reportReference(
-		AstNode reference,
-		AbstractMethodDeclaration methodDeclaration,
-		IJavaElement parent,
-		int accuracy)
-		throws CoreException {
-
-		IJavaElement enclosingElement;
-		if (parent instanceof IType) {
-			// create defining method handle
-			enclosingElement = this.createMethodHandle(methodDeclaration, (IType)parent);
-			if (enclosingElement == null) return; // case of a match found in a type other than the current class file
-		} else {
-			enclosingElement = parent;
-		}
-
-		// accept reference
-		this.pattern.matchReportReference(reference, enclosingElement, accuracy, this);
-	}
-
-	/**
-	 * Reports the given reference to the search requestor.
-	 * It is done in the given field and given type.
-	 * The field's defining types have the given simple names.
-	 */
-	public void reportReference(
-		AstNode reference,
-		TypeDeclaration typeDeclaration,
-		FieldDeclaration fieldDeclaration,
-		IJavaElement parent,
-		int accuracy)
-		throws CoreException {
-
-		IJavaElement enclosingElement;
-		if (fieldDeclaration.isField()) {
-			if (parent instanceof IType) {
-				// create defining field handle
-				enclosingElement = this.createFieldHandle(fieldDeclaration, (IType)parent);
-				if (enclosingElement == null) return;
-			} else {
-				enclosingElement = parent;
-			}
-
-			// accept reference
-			this.pattern.matchReportReference(reference, enclosingElement, accuracy, this);
-		} else { // initializer
-			if (parent instanceof IType) {
-				// create defining initializer
-				enclosingElement =
-					this.createInitializerHandle(
-						typeDeclaration,
-						fieldDeclaration,
-						(IType)parent);
-				if (enclosingElement == null) return;
-			} else {
-				enclosingElement = parent;
-			}
-
-			// accept reference
-			this.pattern.matchReportReference(reference, enclosingElement, accuracy, this);
-		}
-	}
-
-	/**
-	 * Reports the given super type reference to the search requestor.
-	 * It is done in the given defining type (with the given simple names).
-	 */
-	public void reportSuperTypeReference(
-		TypeReference typeRef,
-		IJavaElement type,
-		int accuracy)
-		throws CoreException {
-
-		// accept type reference
-		this.pattern.matchReportReference(typeRef, type, accuracy, this);
-	}
-
-	/**
-	 * Reports the given type declaration to the search requestor.
-	 */
-	public void reportTypeDeclaration(
-		TypeDeclaration typeDeclaration,
-		IJavaElement parent,
-		int accuracy)
-		throws CoreException {
-
-		// accept class or interface declaration
-		this.report(
-			typeDeclaration.sourceStart,
-			typeDeclaration.sourceEnd,
-			(parent == null) ?
-				this.createTypeHandle(typeDeclaration.name) :
-				(parent instanceof IType) ?
-					this.createTypeHandle((IType)parent, typeDeclaration.name) :
-					parent,
-			accuracy);
-	}
-
-void addMatchingOpenable(
-		IResource resource, 
-		Openable openable,
-		CompilationUnitDeclaration parsedUnit,
-		MatchSet matchSet) {
-		
-	MatchingOpenable matchingOpenable = new MatchingOpenable(this, resource, openable, parsedUnit, matchSet);
-	if (matchingOpenable != null) {
-		this.matchingOpenables.add(matchingOpenable);
+	} finally {
+		this.parser.nodeSet = null;
 	}
 }
 /*
@@ -1068,210 +282,1088 @@
  * Returns the existing one if already cached.
  * Returns null if source type binding was cached.
  */
-BinaryTypeBinding cacheBinaryType(IType type) throws JavaModelException {
+protected BinaryTypeBinding cacheBinaryType(IType type) throws JavaModelException {
 	IType enclosingType = type.getDeclaringType();
-	if (enclosingType != null) {
-		// force caching of enclosing types first, so that binary type can be found in lookup enviroment
-		this.cacheBinaryType(enclosingType);
-	}
-	IBinaryType binaryType = (IBinaryType)((BinaryType)type).getElementInfo();
+	if (enclosingType != null)
+		cacheBinaryType(enclosingType); // cache enclosing types first, so that binary type can be found in lookup enviroment
+	IBinaryType binaryType = (IBinaryType) ((BinaryType) type).getElementInfo();
 	BinaryTypeBinding binding = this.lookupEnvironment.cacheBinaryType(binaryType);
 	if (binding == null) { // it was already cached as a result of a previous query
 		char[][] compoundName = CharOperation.splitOn('.', type.getFullyQualifiedName().toCharArray());
 		ReferenceBinding referenceBinding = this.lookupEnvironment.getCachedType(compoundName);
-		if (referenceBinding != null && (referenceBinding instanceof BinaryTypeBinding)) {
-			// if the binding could be found and if it comes from a binary type,
-			binding = (BinaryTypeBinding)referenceBinding;
-		}
+		if (referenceBinding != null && (referenceBinding instanceof BinaryTypeBinding))
+			binding = (BinaryTypeBinding) referenceBinding; // if the binding could be found and if it comes from a binary type
 	}
 	return binding;
 }
+/*
+ * Computes the super type names of the focus type if any.
+ */
+protected char[][][] computeSuperTypeNames(IType focusType) {
+	String fullyQualifiedName = focusType.getFullyQualifiedName();
+	int lastDot = fullyQualifiedName.lastIndexOf('.');
+	char[] qualification = lastDot == -1 ? CharOperation.NO_CHAR : fullyQualifiedName.substring(0, lastDot).toCharArray();
+	char[] simpleName = focusType.getElementName().toCharArray();
 
+	SuperTypeNamesCollector superTypeNamesCollector = 
+		new SuperTypeNamesCollector(
+			this.pattern, 
+			simpleName,
+			qualification,
+			new MatchLocator(this.pattern, this.requestor, this.scope, this.workingCopies, this.progressMonitor), // clone MatchLocator so that it has no side effect
+			focusType, 
+			this.progressMonitor);
+	try {
+		this.allSuperTypeNames = superTypeNamesCollector.collect();
+	} catch (JavaModelException e) {
+		// problem collecting super type names: leave it null
+	}
+	return this.allSuperTypeNames;
+}
+/**
+ * Creates an IMethod from the given method declaration and type. 
+ */
+protected IJavaElement createHandle(AbstractMethodDeclaration method, IJavaElement parent) {
+	if (!(parent instanceof IType)) return parent;
 
-	private INameEnvironment getNameEnvironment(JavaProject project) throws JavaModelException {
-		//return project.getSearchableNameEnvironment();
-		
-		return new JavaSearchNameEnvironment(project);
+	IType type = (IType) parent;
+	Argument[] arguments = method.arguments;
+	int argCount = arguments == null ? 0 : arguments.length;
+	if (type.isBinary()) {
+		// don't cache the methods of the binary type
+		// fall thru if its a constructor with a synthetic argument... find it the slower way
+		ClassFileReader reader = classFileReader(type);
+		if (reader != null) {
+			IBinaryMethod[] methods = reader.getMethods();
+			if (methods != null) {
+				boolean firstIsSynthetic = false;
+				try {
+					if (type.isMember() && method.isConstructor() && !Flags.isStatic(type.getFlags())) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=48261
+						firstIsSynthetic = true;
+						argCount++;
+					}
+				} catch (JavaModelException e) {
+					// ignored
+				}
+				nextMethod : for (int i = 0, methodsLength = methods.length; i < methodsLength; i++) {
+					IBinaryMethod binaryMethod = methods[i];
+					char[] selector = binaryMethod.isConstructor() ? type.getElementName().toCharArray() : binaryMethod.getSelector();
+					if (CharOperation.equals(selector, method.selector)) {
+						char[][] parameterTypes = Signature.getParameterTypes(binaryMethod.getMethodDescriptor());
+						if (argCount != parameterTypes.length) continue nextMethod;
+						for (int j = 0; j < argCount; j++) {
+							char[] typeName;
+							if (j == 0 && firstIsSynthetic) {
+								typeName = type.getDeclaringType().getFullyQualifiedName().toCharArray();
+							} else {
+								TypeReference typeRef = arguments[firstIsSynthetic ? j - 1 : j].type;
+								typeName = CharOperation.concatWith(typeRef.getTypeName(), '.');
+								for (int k = 0, dim = typeRef.dimensions(); k < dim; k++)
+									typeName = CharOperation.concat(typeName, new char[] {'[', ']'});
+							}
+							char[] parameterTypeName = ClassFileMatchLocator.convertClassFileFormat(parameterTypes[j]);
+							if (!CharOperation.endsWith(Signature.toCharArray(parameterTypeName), typeName))
+								continue nextMethod;
+							parameterTypes[j] = parameterTypeName;
+						}
+						return type.getMethod(new String(selector), CharOperation.toStrings(parameterTypes));
+					}
+				}
+			}
+		}
+		return null;
 	}
 
-	public CompilationUnitDeclaration dietParse(final char[] source) {
-		// source unit
-		ICompilationUnit sourceUnit = new ICompilationUnit() {
-			public char[] getContents() {
-				return source;
-			}
-			public char[] getFileName() {
-				return EMPTY_FILE_NAME; // not used
-			}
-			public char[] getMainTypeName() {
-				return null; // don't need to check if main type name == compilation unit name
-			}
-			public char[][] getPackageName() {
-				return null;
-			}
-		};
-		
-		// diet parse
-		CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);  
-		return this.parser.dietParse(sourceUnit, compilationResult);
+	String[] parameterTypeSignatures = new String[argCount];
+	for (int i = 0; i < argCount; i++) {
+		TypeReference typeRef = arguments[i].type;
+		char[] typeName = CharOperation.concatWith(typeRef.getTypeName(), '.');
+		for (int j = 0, dim = typeRef.dimensions(); j < dim; j++)
+			typeName = CharOperation.concat(typeName, new char[] {'[', ']'});
+		parameterTypeSignatures[i] = Signature.createTypeSignature(typeName, false);
 	}
+	return type.getMethod(new String(method.selector), parameterTypeSignatures);
+}
+/**
+ * Creates an IField from the given field declaration and type. 
+ */
+protected IJavaElement createHandle(FieldDeclaration fieldDeclaration, TypeDeclaration typeDeclaration, IJavaElement parent) {
+	if (!(parent instanceof IType)) return parent;
+
+	if (fieldDeclaration.isField())
+		return ((IType) parent).getField(new String(fieldDeclaration.name));
+
+	// find occurence count of the given initializer in its type declaration
+	int occurrenceCount = 0;
+	FieldDeclaration[] fields = typeDeclaration.fields;
+	for (int i = 0, length = fields.length; i < length; i++) {
+		if (!fields[i].isField()) {
+			occurrenceCount++;
+			if (fields[i].equals(fieldDeclaration)) break;
+		}
+	}
+	return ((IType) parent).getInitializer(occurrenceCount);
+}
+/*
+ * Creates hierarchy resolver if needed. 
+ * Returns whether focus is visible.
+ */
+protected boolean createHierarchyResolver(IType focusType, PossibleMatch[] possibleMatches) {
+	// cache focus type if not a possible match
+	char[][] compoundName = CharOperation.splitOn('.', focusType.getFullyQualifiedName().toCharArray());
+	boolean isPossibleMatch = false;
+	for (int i = 0, length = possibleMatches.length; i < length; i++) {
+		if (CharOperation.equals(possibleMatches[i].compoundName, compoundName)) {
+			isPossibleMatch = true;
+			break;
+		}
+	}
+	if (!isPossibleMatch) {
+		if (focusType.isBinary()) {
+			try {
+				cacheBinaryType(focusType);
+			} catch (JavaModelException e) {
+				return false;
+			}
+		} else {
+			// cache all types in the focus' compilation unit (even secondary types)
+			accept((ICompilationUnit) focusType.getCompilationUnit());
+		}
+	}
+
+	// resolve focus type
+	this.hierarchyResolver = new HierarchyResolver(this.lookupEnvironment, null/*hierarchy is not going to be computed*/);
+	ReferenceBinding binding = this.hierarchyResolver.setFocusType(compoundName);
+	return binding != null && binding.isValidBinding() && (binding.tagBits & TagBits.HierarchyHasProblems) == 0;
+}
+/**
+ * Creates an IImportDeclaration from the given import statement
+ */
+protected IJavaElement createImportHandle(ImportReference importRef) {
+	char[] importName = CharOperation.concatWith(importRef.getImportName(), '.');
+	if (importRef.onDemand)
+		importName = CharOperation.concat(importName, ".*" .toCharArray()); //$NON-NLS-1$
+	Openable openable = this.currentPossibleMatch.openable;
+	if (openable instanceof CompilationUnit)
+		return ((CompilationUnit) openable).getImport(new String(importName));
+
+	// binary types do not contain import statements so just answer the top-level type as the element
+	IType binaryType = ((ClassFile) openable).getType();
+	String typeName = binaryType.getElementName();
+	int lastDollar = typeName.lastIndexOf('$');
+	if (lastDollar == -1) return binaryType;
+	return createTypeHandle(typeName.substring(0, lastDollar));
+}
+/**
+ * Creates an IType from the given simple top level type name. 
+ */
+protected IType createTypeHandle(String simpleTypeName) {
+	Openable openable = this.currentPossibleMatch.openable;
+	if (openable instanceof CompilationUnit)
+		return ((CompilationUnit) openable).getType(simpleTypeName);
+
+	IType binaryType = ((ClassFile) openable).getType();
+	if (simpleTypeName.equals(binaryType.getTypeQualifiedName()))
+		return binaryType; // answer only top-level types, sometimes the classFile is for a member/local type
+
+	try {
+		IClassFile classFile = binaryType.getPackageFragment().getClassFile(simpleTypeName + SuffixConstants.SUFFIX_STRING_class);
+		return classFile.getType();
+	} catch (JavaModelException e) {
+		// ignore as implementation of getType() cannot throw this exception
+	}
+	return null;
+}
+protected IBinaryType getBinaryInfo(ClassFile classFile, IResource resource) throws CoreException {
+	BinaryType binaryType = (BinaryType) classFile.getType();
+	if (classFile.isOpen())
+		return (IBinaryType) binaryType.getElementInfo(); // reuse the info from the java model cache
+
+	// create a temporary info
+	IBinaryType info;
+	try {
+		IJavaElement pkg = classFile.getParent();
+		PackageFragmentRoot root = (PackageFragmentRoot) pkg.getParent();
+		if (root.isArchive()) {
+			// class file in a jar
+			String pkgPath = pkg.getElementName().replace('.', '/');
+			String classFilePath = pkgPath.length() > 0
+				? pkgPath + "/" + classFile.getElementName() //$NON-NLS-1$
+				: classFile.getElementName();
+			ZipFile zipFile = null;
+			try {
+				zipFile = ((JarPackageFragmentRoot) root).getJar();
+				info = ClassFileReader.read(zipFile, classFilePath);
+			} finally {
+				JavaModelManager.getJavaModelManager().closeZipFile(zipFile);
+			}
+		} else {
+			// class file in a directory
+			String osPath = resource.getLocation().toOSString();
+			info = ClassFileReader.read(osPath);
+		}
+		return info;
+	} catch (ClassFormatException e) {
+		//e.printStackTrace();
+		return null;
+	} catch (java.io.IOException e) {
+		throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
+	}
+}
+protected IType getFocusType() {
+	return this.scope instanceof HierarchyScope ? ((HierarchyScope) this.scope).focusType : null;
+}
+protected void getMethodBodies(CompilationUnitDeclaration unit) {
+	if (unit.ignoreMethodBodies) {
+		unit.ignoreFurtherInvestigation = true;
+		return; // if initial diet parse did not work, no need to dig into method bodies.
+	}
+
+	// save existing values to restore them at the end of the parsing process
+	// see bug 47079 for more details
+	int[] oldLineEnds = this.parser.scanner.lineEnds;
+	int oldLinePtr = this.parser.scanner.linePtr;
 	
-	public char[] findSource(ClassFile classFile) {
-		char[] source = null; 
+	try {
+		char[] contents = unit.compilationResult.compilationUnit.getContents();
+		this.parser.scanner.setSource(contents);
+
+		// inline old setLineEnds
+		final int[] lineSeparatorPositions = unit.compilationResult.lineSeparatorPositions;
+		this.parser.scanner.lineEnds = lineSeparatorPositions;
+		this.parser.scanner.linePtr = lineSeparatorPositions.length - 1;
+
+		if (this.parser.javadocParser.checkJavadoc) {
+			this.parser.javadocParser.scanner.setSource(contents);
+		}
+		this.parser.nodeSet = this.currentPossibleMatch.nodeSet;
+		this.parser.parseBodies(unit);
+	} finally {
+		this.parser.nodeSet = null;
+		// this is done to prevent any side effects on the compilation unit result
+		// line separator positions array.
+		this.parser.scanner.lineEnds = oldLineEnds;
+		this.parser.scanner.linePtr = oldLinePtr;
+	}
+}
+protected boolean hasAlreadyDefinedType(CompilationUnitDeclaration parsedUnit) {
+	CompilationResult result = parsedUnit.compilationResult;
+	if (result == null) return false;
+	for (int i = 0; i < result.problemCount; i++)
+		if (result.problems[i].getID() == IProblem.DuplicateTypes)
+			return true;
+	return false;
+}	
+/**
+ * Create a new parser for the given project, as well as a lookup environment.
+ */
+public void initialize(JavaProject project, int possibleMatchSize) throws JavaModelException {
+	if (this.nameEnvironment != null)
+		this.nameEnvironment.cleanup();
+
+	// if only one possible match, a file name environment costs too much,
+	// so use the existing searchable  environment which will populate the java model
+	// only for this possible match and its required types.
+	this.nameEnvironment = possibleMatchSize == 1
+		? (INameEnvironment) project.getSearchableNameEnvironment()
+		: (INameEnvironment) new JavaSearchNameEnvironment(project);
+
+	// create lookup environment
+	this.options = new CompilerOptions(project.getOptions(true));
+	ProblemReporter problemReporter =
+		new ProblemReporter(
+			DefaultErrorHandlingPolicies.proceedWithAllProblems(),
+			this.options,
+			new DefaultProblemFactory());
+	this.lookupEnvironment = new LookupEnvironment(this, this.options, problemReporter, this.nameEnvironment);
+
+	this.parser = MatchLocatorParser.createParser(problemReporter, this);
+
+	// remember project's name lookup
+	this.nameLookup = project.getNameLookup();
+
+	// initialize queue of units
+	this.numberOfMatches = 0;
+	this.matchesToProcess = new PossibleMatch[possibleMatchSize];
+}
+protected void locateMatches(JavaProject javaProject, PossibleMatch[] possibleMatches, int start, int length) throws JavaModelException {
+	initialize(javaProject, length);
+
+	try {
+		this.nameLookup.setUnitsToLookInside(this.workingCopies);
+
+		// create and resolve binding (equivalent to beginCompilation() in Compiler)
+		boolean bindingsWereCreated = true;
 		try {
-			SourceMapper sourceMapper = classFile.getSourceMapper();
-			if (sourceMapper != null) {
-				IType type = classFile.getType();
-				if (classFile.isOpen() && type.getDeclaringType() == null) {
-					source = sourceMapper.findSource(type);
+			for (int i = start, maxUnits = start + length; i < maxUnits; i++)
+				buildBindings(possibleMatches[i]);
+			lookupEnvironment.completeTypeBindings();
+
+			// create hierarchy resolver if needed
+			IType focusType = getFocusType();
+			if (focusType == null) {
+				this.hierarchyResolver = null;
+			} else if (!createHierarchyResolver(focusType, possibleMatches)) {
+				// focus type is not visible, use the super type names instead of the bindings
+				if (computeSuperTypeNames(focusType) == null) return;
+			}
+		} catch (AbortCompilation e) {
+			bindingsWereCreated = false;
+		}
+
+		// possible match resolution
+		for (int i = 0; i < this.numberOfMatches; i++) {
+			if (this.progressMonitor != null && this.progressMonitor.isCanceled())
+				throw new OperationCanceledException();
+			PossibleMatch possibleMatch = this.matchesToProcess[i];
+			this.matchesToProcess[i] = null; // release reference to processed possible match
+			try {
+				process(possibleMatch, bindingsWereCreated);
+			} catch (AbortCompilation e) {
+				// problem with class path: it could not find base classes
+				// continue and try next matching openable reporting innacurate matches (since bindings will be null)
+				bindingsWereCreated = false;
+			} catch (JavaModelException e) {
+				// problem with class path: it could not find base classes
+				// continue and try next matching openable reporting innacurate matches (since bindings will be null)
+				bindingsWereCreated = false;
+			} catch (CoreException e) {
+				// core exception thrown by client's code: let it through
+				throw new JavaModelException(e);
+			} finally {
+				if (this.options.verbose)
+					System.out.println(Util.bind("compilation.done", //$NON-NLS-1$
+						new String[] {
+							String.valueOf(i + 1),
+							String.valueOf(numberOfMatches),
+							new String(possibleMatch.parsedUnit.getFileName())}));
+				// cleanup compilation unit result
+				possibleMatch.parsedUnit.cleanUp();
+				possibleMatch.parsedUnit = null;
+			}
+			if (this.progressMonitor != null)
+				this.progressMonitor.worked(5);
+		}
+	} finally {
+		this.nameLookup.setUnitsToLookInside(null);
+	}
+}
+/**
+ * Locate the matches amongst the possible matches.
+ */
+protected void locateMatches(JavaProject javaProject, PossibleMatchSet matchSet) throws JavaModelException {
+	PossibleMatch[] possibleMatches = matchSet.getPossibleMatches(javaProject.getPackageFragmentRoots());
+	for (int index = 0, length = possibleMatches.length; index < length;) {
+		int max = Math.min(MAX_AT_ONCE, length - index);
+		locateMatches(javaProject, possibleMatches, index, max);
+		index += max;
+	}
+}
+/**
+ * Locate the matches in the given files and report them using the search requestor. 
+ */
+public void locateMatches(SearchDocument[] searchDocuments) throws JavaModelException {
+	if (SearchEngine.VERBOSE) {
+		System.out.println("Locating matches in documents ["); //$NON-NLS-1$
+		for (int i = 0, length = searchDocuments.length; i < length; i++)
+			System.out.println("\t" + searchDocuments[i]); //$NON-NLS-1$
+		System.out.println("]"); //$NON-NLS-1$
+	}
+
+	JavaModelManager manager = JavaModelManager.getJavaModelManager();
+	try {
+		// optimize access to zip files during search operation
+		manager.cacheZipFiles();
+
+		// initialize handle factory (used as a cache of handles so as to optimize space)
+		if (this.handleFactory == null)
+			this.handleFactory = new HandleFactory();
+
+		if (this.progressMonitor != null) {
+			// 1 for file path, 4 for parsing and binding creation, 5 for binding resolution? //$NON-NLS-1$
+			this.progressMonitor.beginTask("", searchDocuments.length * (this.pattern.mustResolve ? 10 : 5)); //$NON-NLS-1$
+		}
+
+		// initialize pattern for polymorphic search (ie. method reference pattern)
+		this.patternLocator.initializePolymorphicSearch(this);
+
+		JavaProject previousJavaProject = null;
+		PossibleMatchSet matchSet = new PossibleMatchSet();
+		Util.sort(searchDocuments, new Util.Comparer() {
+			public int compare(Object a, Object b) {
+				return ((SearchDocument)a).getPath().compareTo(((SearchDocument)b).getPath());
+			}
+		}); 
+		for (int i = 0, l = searchDocuments.length; i < l; i++) {
+			if (this.progressMonitor != null && this.progressMonitor.isCanceled())
+				throw new OperationCanceledException();
+
+			// skip duplicate paths
+			SearchDocument searchDocument = searchDocuments[i];
+			String pathString = searchDocument.getPath();
+			if (i > 0 && pathString.equals(searchDocuments[i - 1].getPath())) continue;
+
+			Openable openable;
+			org.eclipse.jdt.core.ICompilationUnit workingCopy = null;
+			if (searchDocument instanceof JavaSearchParticipant.WorkingCopyDocument) {
+				workingCopy = ((JavaSearchParticipant.WorkingCopyDocument)searchDocument).workingCopy;
+				openable = (Openable) workingCopy;
+			} else {
+				openable = this.handleFactory.createOpenable(pathString, this.scope);
+				if (openable == null) continue; // match is outside classpath
+			}
+
+			// create new parser and lookup environment if this is a new project
+			IResource resource = null;
+			try {
+				JavaProject javaProject = (JavaProject) openable.getJavaProject();
+				resource = workingCopy != null ? workingCopy.getResource() : openable.getResource();
+				if (resource == null)
+					resource = javaProject.getProject(); // case of a file in an external jar
+				if (!javaProject.equals(previousJavaProject)) {
+					// locate matches in previous project
+					if (previousJavaProject != null) {
+						try {
+							locateMatches(previousJavaProject, matchSet);
+						} catch (JavaModelException e) {
+							if (e.getException() instanceof CoreException) throw e;
+							// problem with classpath in this project -> skip it
+						}
+						matchSet.reset();
+					}
+					previousJavaProject = javaProject;
+				}
+			} catch (JavaModelException e) {
+				// file doesn't exist -> skip it
+				continue;
+			}
+			matchSet.add(new PossibleMatch(this, resource, openable, searchDocument));
+
+			if (this.progressMonitor != null)
+				this.progressMonitor.worked(1);
+		}
+
+		// last project
+		if (previousJavaProject != null) {
+			try {
+				locateMatches(previousJavaProject, matchSet);
+			} catch (JavaModelException e) {
+				if (e.getException() instanceof CoreException) throw e;
+				// problem with classpath in last project -> skip it
+			}
+		} 
+
+		if (this.progressMonitor != null)
+			this.progressMonitor.done();
+	} finally {
+		if (this.nameEnvironment != null)
+			this.nameEnvironment.cleanup();
+		manager.flushZipFiles();
+	}	
+}
+/**
+ * Locates the package declarations corresponding to this locator's pattern. 
+ */
+public void locatePackageDeclarations(SearchParticipant participant) throws JavaModelException {
+	locatePackageDeclarations(this.pattern, participant);
+}
+/**
+ * Locates the package declarations corresponding to the search pattern. 
+ */
+protected void locatePackageDeclarations(SearchPattern searchPattern, SearchParticipant participant) throws JavaModelException {
+	if (searchPattern instanceof OrPattern) {
+		SearchPattern[] patterns = ((OrPattern) searchPattern).patterns;
+		for (int i = 0, length = patterns.length; i < length; i++)
+			locatePackageDeclarations(patterns[i], participant);
+	} else if (searchPattern instanceof PackageDeclarationPattern) {
+		if (searchPattern.focus != null) {
+			IResource resource = searchPattern.focus.getResource();
+			SearchDocument document = participant.getDocument(resource.getFullPath().toString());
+			this.currentPossibleMatch = new PossibleMatch(this, resource, null, document);
+			try {
+				this.report(-1, -2, searchPattern.focus, IJavaSearchResultCollector.EXACT_MATCH);
+			} catch (CoreException e) {
+				if (e instanceof JavaModelException) {
+					throw (JavaModelException) e;
 				} else {
-					ClassFileReader reader = this.classFileReader(type);
-					if (reader != null) {
-						String sourceFileName = sourceMapper.findSourceFileName(type, reader);
-						if (sourceFileName != null) {
-							source = sourceMapper.findSource(type, sourceFileName);
+					throw new JavaModelException(e);
+				}
+			}					
+			return;
+		}
+		PackageDeclarationPattern pkgPattern = (PackageDeclarationPattern) searchPattern;
+		IJavaProject[] projects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
+		for (int i = 0, length = projects.length; i < length; i++) {
+			IJavaProject javaProject = projects[i];
+			IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
+			for (int j = 0, rootsLength = roots.length; j < rootsLength; j++) {
+				IJavaElement[] pkgs = roots[j].getChildren();
+				for (int k = 0, pksLength = pkgs.length; k < pksLength; k++) {
+					IPackageFragment pkg = (IPackageFragment) pkgs[k];
+					if (pkg.getChildren().length > 0 
+							&& pkgPattern.matchesName(pkgPattern.pkgName, pkg.getElementName().toCharArray())) {
+						IResource resource = pkg.getResource();
+						if (resource == null) // case of a file in an external jar
+							resource = javaProject.getProject();
+						SearchDocument document = participant.getDocument(resource.getFullPath().toString());
+						this.currentPossibleMatch = new PossibleMatch(this, resource, null, document);
+						try {
+							report(-1, -2, pkg, IJavaSearchResultCollector.EXACT_MATCH);
+						} catch (JavaModelException e) {
+							throw e;
+						} catch (CoreException e) {
+							throw new JavaModelException(e);
 						}
 					}
 				}
 			}
-		} catch (JavaModelException e) {
-		}
-		return source;
-	}
-public IBinaryType getBinaryInfo(org.eclipse.jdt.internal.core.ClassFile classFile, IResource resource) throws CoreException {
-	BinaryType binaryType = (BinaryType)classFile.getType();
-	if (classFile.isOpen()) {
-		// reuse the info from the java model cache
-		return (IBinaryType)binaryType.getElementInfo();
-	} else {
-		// create a temporary info
-		IBinaryType info;
-		try {
-			IJavaElement pkg = classFile.getParent();
-			PackageFragmentRoot root = (PackageFragmentRoot)pkg.getParent();
-			if (root.isArchive()) {
-				// class file in a jar
-				String pkgPath = pkg.getElementName().replace('.', '/');
-				String classFilePath = 
-					(pkgPath.length() > 0) ?
-						pkgPath + "/" + classFile.getElementName() : //$NON-NLS-1$
-						classFile.getElementName();
-				ZipFile zipFile = null;
-				try {
-					zipFile = ((JarPackageFragmentRoot)root).getJar();
-					info = org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.read(
-						zipFile,
-						classFilePath);
-				} finally {
-					JavaModelManager.getJavaModelManager().closeZipFile(zipFile);
-				}
-			} else {
-				// class file in a directory
-				String osPath = resource.getFullPath().toOSString();
-				info = org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.read(osPath);
-			}
-			return info;
-		} catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException e) {
-			//e.printStackTrace();
-			return null;
-		} catch (java.io.IOException e) {
-			throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
 		}
 	}
 }
-	protected Openable getCurrentOpenable() {
-		return this.currentMatchingOpenable.openable;
+protected IType lookupType(ReferenceBinding typeBinding) {
+	if (typeBinding == null) return null;
+
+	char[] packageName = typeBinding.qualifiedPackageName();
+	IPackageFragment[] pkgs = this.nameLookup.findPackageFragments(
+		(packageName == null || packageName.length == 0)
+			? IPackageFragment.DEFAULT_PACKAGE_NAME
+			: new String(packageName),
+		false);
+
+	// iterate type lookup in each package fragment
+	char[] sourceName = typeBinding.qualifiedSourceName();
+	String typeName = new String(sourceName);
+	for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) {
+		IType type = this.nameLookup.findType(
+			typeName,
+			pkgs[i], 
+			false, 
+			typeBinding.isClass() ? NameLookup.ACCEPT_CLASSES : NameLookup.ACCEPT_INTERFACES);
+		if (type != null) return type;
 	}
 
-	/**
-	 * Locate the matches amongst the matching openables.
-	 */
-	private void locateMatches(JavaProject javaProject) throws JavaModelException {
-		MatchingOpenable[] openables = this.matchingOpenables.getMatchingOpenables(javaProject.getPackageFragmentRoots());
-	
-		this.compilationAborted = false;
+	// search inside enclosing element
+	char[][] qualifiedName = CharOperation.splitOn('.', sourceName);
+	int length = qualifiedName.length;
+	if (length == 0) return null;
 
-		if (this.pattern.needsResolve) {
-			this.createAndResolveBindings(openables);
+	IType type = createTypeHandle(new String(qualifiedName[0])); // find the top-level type
+	if (type == null) return null;
+
+	for (int i = 1; i < length; i++) {
+		type = type.getType(new String(qualifiedName[i]));
+		if (type == null) return null;
+	}
+	if (type.exists()) return type;
+	return null;
+}
+/*
+ * Process a compilation unit already parsed and build.
+ */
+protected void process(PossibleMatch possibleMatch, boolean bindingsWereCreated) throws CoreException {
+	this.currentPossibleMatch = possibleMatch;
+	CompilationUnitDeclaration unit = possibleMatch.parsedUnit;
+	try {
+		if (unit.isEmpty()) {
+			if (this.currentPossibleMatch.openable instanceof ClassFile) {
+				ClassFile classFile = (ClassFile) this.currentPossibleMatch.openable;
+				IBinaryType info = getBinaryInfo(classFile, this.currentPossibleMatch.resource);
+				if (info != null)
+					new ClassFileMatchLocator().locateMatches(this, classFile, info);
+			}
+			return;
 		}
+		if (hasAlreadyDefinedType(unit)) return; // skip type has it is hidden so not visible
 
-		// create hierarchy resolver if scope is a hierarchy scope
-		if (this.scope instanceof HierarchyScope) {
-			IType focusType = ((HierarchyScope)this.scope).focusType;
-			if (focusType != null) {
-				if (!focusType.isBinary()) {
-					// cache all types in the focus' compilation unit (even secondary types)
-					this.accept((ICompilationUnit)focusType.getCompilationUnit());
+		getMethodBodies(unit);
+
+		if (bindingsWereCreated && this.pattern.mustResolve && unit.types != null) {
+			if (SearchEngine.VERBOSE)
+				System.out.println("Resolving " + this.currentPossibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
+
+			reduceParseTree(unit);
+
+			if (unit.scope != null)
+				unit.scope.faultInTypes(); // fault in fields & methods
+			unit.resolve();
+
+			reportMatching(unit, true);
+		} else {
+			reportMatching(unit, this.pattern.mustResolve);
+		}
+	} catch (AbortCompilation e) {
+		// could not resolve: report innacurate matches
+		reportMatching(unit, true); // was partially resolved
+		if (!(e instanceof AbortCompilationUnit)) {
+			// problem with class path
+			throw e;
+		}
+	} finally {
+		this.currentPossibleMatch.cleanUp();
+		this.currentPossibleMatch = null;
+	}
+}
+protected void purgeMethodStatements(TypeDeclaration type, boolean checkEachMethod) {
+	checkEachMethod = checkEachMethod
+		&& this.currentPossibleMatch.nodeSet.hasPossibleNodes(type.declarationSourceStart, type.declarationSourceEnd);
+	AbstractMethodDeclaration[] methods = type.methods;
+	if (methods != null) {
+		if (checkEachMethod) {
+			for (int j = 0, length = methods.length; j < length; j++) {
+				AbstractMethodDeclaration method = methods[j];
+				if (!this.currentPossibleMatch.nodeSet.hasPossibleNodes(method.declarationSourceStart, method.declarationSourceEnd)) {
+					method.statements = null;
+					method.javadoc = null;
 				}
-				
-				char[] fullyQualifiedName = focusType.getFullyQualifiedName().toCharArray();
-				this.hierarchyResolver = new HierarchyResolver(this.lookupEnvironment, null/*hierarchy is not going to be computed*/);
-				if (this.hierarchyResolver.setFocusType(CharOperation.splitOn('.', fullyQualifiedName)) == null) {
-					// focus type is not visible from this project
-					return;
-				}
-			} else {
-				this.hierarchyResolver = null;
 			}
 		} else {
-			this.hierarchyResolver = null;
-		}
-
-		// matching openable resolution
-		for (int i = 0, length = openables.length; i < length; i++) { 
-			if (progressMonitor != null && progressMonitor.isCanceled()) {
-				throw new OperationCanceledException();
-			}
-			 
-			try {
-				this.currentMatchingOpenable = openables[i];
-				
-				if (!this.currentMatchingOpenable.hasAlreadyDefinedType()) {
-					this.currentMatchingOpenable.locateMatches();
-				} // else skip type has it is hidden so not visible
-			} catch (AbortCompilation e) {
-				// problem with class path: it could not find base classes
-				// continue and try next matching openable reporting innacurate matches (since bindings will be null)
-				compilationAborted = true;
-			} catch (CoreException e) {
-				if (e instanceof JavaModelException) {
-					// problem with class path: it could not find base classes
-					// continue and try next matching openable reporting innacurate matches (since bindings will be null)
-					compilationAborted = true;
-				} else {
-					// core exception thrown by client's code: let it through
-					throw new JavaModelException(e);
-				}
-			} finally {
-				this.currentMatchingOpenable.reset();
-			}
-			if (progressMonitor != null) {
-				progressMonitor.worked(3);
+			for (int j = 0, length = methods.length; j < length; j++) {
+				methods[j].statements = null;
+				methods[j].javadoc = null;
 			}
 		}
-		this.currentMatchingOpenable = null;
 	}
 
-	void createAndResolveBindings(MatchingOpenable[] openables) {
-		// binding creation
-		for (int i = 0, length = openables.length; i < length; i++) { 
-			openables[i].buildTypeBindings();
-			if (this.progressMonitor != null) {
-				if (this.progressMonitor.isCanceled()) {
-					throw new OperationCanceledException();
-				} else {
-					this.progressMonitor.worked(6);
-				}
-			}
+	TypeDeclaration[] memberTypes = type.memberTypes;
+	if (memberTypes != null)
+		for (int i = 0, l = memberTypes.length; i < l; i++)
+			purgeMethodStatements(memberTypes[i], checkEachMethod);
+}
+/**
+ * Called prior to the unit being resolved. Reduce the parse tree where possible.
+ */
+protected void reduceParseTree(CompilationUnitDeclaration unit) {
+	// remove statements from methods that have no possible matching nodes
+	TypeDeclaration[] types = unit.types;
+	for (int i = 0, l = types.length; i < l; i++)
+		purgeMethodStatements(types[i], true); 
+}
+protected void report(int sourceStart, int sourceEnd, IJavaElement element, int accuracy) throws CoreException {
+	if (element != null && this.scope.encloses(element)) {
+		if (SearchEngine.VERBOSE) {
+			IResource res = this.currentPossibleMatch.resource;
+			System.out.println("Reporting match"); //$NON-NLS-1$
+			System.out.println("\tResource: " + (res == null ? " <unknown> " : res.getFullPath().toString())); //$NON-NLS-2$//$NON-NLS-1$
+			System.out.println("\tPositions: [" + sourceStart + ", " + sourceEnd + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			System.out.println("\tJava element: " + ((JavaElement)element).toStringWithAncestors()); //$NON-NLS-1$
+			System.out.println(accuracy == IJavaSearchResultCollector.EXACT_MATCH
+				? "\tAccuracy: EXACT_MATCH" //$NON-NLS-1$
+				: "\tAccuracy: POTENTIAL_MATCH"); //$NON-NLS-1$
 		}
-		
-		// binding resolution
+		report(
+			this.currentPossibleMatch.resource, 
+			sourceStart, 
+			sourceEnd, 
+			element, 
+			accuracy, 
+			getParticipant());
+	}
+}
+public SearchParticipant getParticipant() {
+	return this.currentPossibleMatch.document.getParticipant();
+}
+
+protected void report(IResource resource, int sourceStart, int sourceEnd, IJavaElement element, int accuracy, SearchParticipant participant) throws CoreException {
+	long start = -1;
+	if (SearchEngine.VERBOSE)
+		start = System.currentTimeMillis();
+	String documentPath = element.getPath().toString();
+	SearchMatch match = new JavaSearchMatch(resource, element, documentPath, accuracy, participant, sourceStart, sourceEnd+1, -1);
+	this.requestor.acceptSearchMatch(match);
+	if (SearchEngine.VERBOSE)
+		this.resultCollectorTime += System.currentTimeMillis()-start;
+}
+protected void report(long start, long end, IJavaElement element, int accuracy) throws CoreException {
+	report((int) (start >>> 32), (int) end, element, accuracy); // extract the start and end from the encoded long positions
+}
+/**
+ * Finds the accurate positions of the sequence of tokens given by qualifiedName
+ * in the source and reports a reference to this this qualified name
+ * to the search requestor.
+ */
+protected void reportAccurateReference(int sourceStart, int sourceEnd, char[] name, IJavaElement element, int accuracy) throws CoreException {
+	if (accuracy == -1) return;
+
+	// compute source positions of the qualified reference 
+	Scanner scanner = this.parser.scanner;
+	scanner.setSource(this.currentPossibleMatch.getContents());
+	scanner.resetTo(sourceStart, sourceEnd);
+
+	int token = -1;
+	int currentPosition;
+	do {
+		currentPosition = scanner.currentPosition;
 		try {
-			this.lookupEnvironment.completeTypeBindings();
-		} catch (AbortCompilation e) {
-			// problem with class path: it could not find base classes
-			// continue reporting innacurate matches (since bindings will be null)
-			this.compilationAborted = true;
+			token = scanner.getNextToken();
+		} catch (InvalidInputException e) {
+			// ignore
+		}
+		if (token == TerminalTokens.TokenNameIdentifier && this.pattern.matchesName(name, scanner.getCurrentTokenSource())) {
+			report(currentPosition, scanner.currentPosition - 1, element, accuracy);
+			return;
+		}
+	} while (token != TerminalTokens.TokenNameEOF);
+	report(sourceStart, sourceEnd, element, accuracy);
+}
+/**
+ * Finds the accurate positions of each valid token in the source and
+ * reports a reference to this token to the search requestor.
+ * A token is valid if it has an accuracy which is not -1.
+ */
+protected void reportAccurateReference(int sourceStart, int sourceEnd, char[][] tokens, IJavaElement element, int[] accuracies) throws CoreException {
+	// compute source positions of the qualified reference 
+	Scanner scanner = this.parser.scanner;
+	scanner.setSource(this.currentPossibleMatch.getContents());
+	scanner.resetTo(sourceStart, sourceEnd);
+
+	int refSourceStart = -1, refSourceEnd = -1;
+	int length = tokens.length;
+	int token = -1;
+	int previousValid = -1;
+	int i = 0;
+	int accuracyIndex = 0;
+	do {
+		int currentPosition = scanner.currentPosition;
+		// read token
+		try {
+			token = scanner.getNextToken();
+		} catch (InvalidInputException e) {
+			//ignore
+		}
+		if (token != TerminalTokens.TokenNameEOF) {
+			char[] currentTokenSource = scanner.getCurrentTokenSource();
+			boolean equals = false;
+			while (i < length && !(equals = this.pattern.matchesName(tokens[i++], currentTokenSource)));
+			if (equals && (previousValid == -1 || previousValid == i - 2)) {
+				previousValid = i - 1;
+				if (refSourceStart == -1)
+					refSourceStart = currentPosition;
+				refSourceEnd = scanner.currentPosition - 1;
+			} else {
+				i = 0;
+				refSourceStart = -1;
+				previousValid = -1;
+			}
+			// read '.'
+			try {
+				token = scanner.getNextToken();
+			} catch (InvalidInputException e) {
+				// ignore
+			}
+		}
+		if (accuracies[accuracyIndex] != -1) {
+			// accept reference
+			if (refSourceStart != -1) {
+				report(refSourceStart, refSourceEnd, element, accuracies[accuracyIndex]);
+			} else {
+				report(sourceStart, sourceEnd, element, accuracies[accuracyIndex]);
+			}
+			i = 0;
+		}
+		refSourceStart = -1;
+		previousValid = -1;
+		if (accuracyIndex < accuracies.length - 1)
+			accuracyIndex++;
+	} while (token != TerminalTokens.TokenNameEOF);
+
+}
+protected void reportBinaryMatch(IResource resource, IMember binaryMember, IBinaryType info, int accuracy) throws CoreException {
+	ISourceRange range = binaryMember.getNameRange();
+	if (range.getOffset() == -1) {
+		ClassFile classFile = (ClassFile) binaryMember.getClassFile();
+		SourceMapper mapper = classFile.getSourceMapper();
+		if (mapper != null) {
+			IType type = classFile.getType();
+			String sourceFileName = mapper.findSourceFileName(type, info);
+			if (sourceFileName != null) {
+				char[] contents = mapper.findSource(type, sourceFileName);
+				if (contents != null)
+					range = mapper.mapSource(type, contents, binaryMember);
+			}
 		}
 	}
+	int startIndex = range.getOffset();
+	int endIndex = startIndex + range.getLength() - 1;
+	if (resource == null)
+		report(startIndex, endIndex, binaryMember, accuracy);
+	else
+		report(resource, startIndex, endIndex, binaryMember, accuracy, getParticipant());
+}
+/**
+ * Visit the given method declaration and report the nodes that match exactly the
+ * search pattern (ie. the ones in the matching nodes set)
+ * Note that the method declaration has already been checked.
+ */
+protected void reportMatching(AbstractMethodDeclaration method, IJavaElement parent, int accuracy, boolean typeInHierarchy, MatchingNodeSet nodeSet) throws CoreException {
+	IJavaElement enclosingElement = null;
+	if (accuracy > -1) {
+		enclosingElement = createHandle(method, parent);
+		if (enclosingElement != null) { // skip if unable to find method
+			// compute source positions of the selector 
+			Scanner scanner = parser.scanner;
+			int nameSourceStart = method.sourceStart;
+			scanner.setSource(this.currentPossibleMatch.getContents());
+			scanner.resetTo(nameSourceStart, method.sourceEnd);
+			try {
+				scanner.getNextToken();
+			} catch (InvalidInputException e) {
+				// ignore
+			}
+			int nameSourceEnd = scanner.currentPosition - 1;
+
+			report(nameSourceStart, nameSourceEnd, enclosingElement, accuracy);
+		}
+	}
+
+	// handle nodes for the local type first
+	if ((method.bits & ASTNode.HasLocalTypeMASK) != 0) {
+		if (enclosingElement == null)
+			enclosingElement = createHandle(method, parent);
+		LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor(enclosingElement, nodeSet);
+		try {
+			method.traverse(localDeclarationVisitor, (ClassScope) null);
+		} catch (WrappedCoreException e) {
+			throw e.coreException;
+		}
+	}
+
+	// references in this method
+	if (typeInHierarchy) {
+		ASTNode[] nodes = nodeSet.matchingNodes(method.declarationSourceStart, method.declarationSourceEnd);
+		if (nodes != null) {
+			if ((this.matchContainer & PatternLocator.METHOD_CONTAINER) != 0) {
+				if (enclosingElement == null)
+					enclosingElement = createHandle(method, parent);
+				if (enclosingElement != null) { // skip if unable to find method
+					for (int i = 0, l = nodes.length; i < l; i++) {
+						ASTNode node = nodes[i];
+						Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
+						this.patternLocator.matchReportReference(node, enclosingElement, level.intValue(), this);
+					}
+					return;
+				}
+			}
+			for (int i = 0, l = nodes.length; i < l; i++)
+				nodeSet.matchingNodes.removeKey(nodes[i]);
+		}
+	}
+}
+/**
+ * Visit the given resolved parse tree and report the nodes that match the search pattern.
+ */
+protected void reportMatching(CompilationUnitDeclaration unit, boolean mustResolve) throws CoreException {
+	MatchingNodeSet nodeSet = this.currentPossibleMatch.nodeSet;
+	if (mustResolve) {
+		// move the possible matching nodes that exactly match the search pattern to the matching nodes set
+		Object[] nodes = nodeSet.possibleMatchingNodesSet.values;
+		for (int i = 0, l = nodes.length; i < l; i++) {
+			ASTNode node = (ASTNode) nodes[i];
+			if (node == null) continue;
+			if (node instanceof ImportReference) {
+				// special case for import refs: they don't know their binding
+				// import ref cannot be in the hirarchy of a type
+				if (this.hierarchyResolver != null) continue;
+
+				ImportReference importRef = (ImportReference) node;
+				Binding binding = importRef.onDemand
+					? unit.scope.getTypeOrPackage(CharOperation.subarray(importRef.tokens, 0, importRef.tokens.length))
+					: unit.scope.getTypeOrPackage(importRef.tokens);
+				this.patternLocator.matchLevelAndReportImportRef(importRef, binding, this);
+			} else {
+				nodeSet.addMatch(node, this.patternLocator.resolveLevel(node));
+			}
+		}
+		nodeSet.possibleMatchingNodesSet = new SimpleSet();
+	}
+
+	if (nodeSet.matchingNodes.elementSize == 0) return; // no matching nodes were found
+
+	boolean matchedUnitContainer = (this.matchContainer & PatternLocator.COMPILATION_UNIT_CONTAINER) != 0;
+	if (matchedUnitContainer) {
+// Currently a no-op
+//	ImportReference pkg = unit.currentPackage;
+//	if (pkg != null && nodeSet.matchingNodes.removeKey(pkg) != null)
+//		reportPackageDeclaration(pkg);
+
+		ImportReference[] imports = unit.imports;
+		if (imports != null) {
+			for (int i = 0, l = imports.length; i < l; i++) {
+				ImportReference importRef = imports[i];
+				Integer level = (Integer) nodeSet.matchingNodes.removeKey(importRef);
+				if (level != null)
+					this.patternLocator.matchReportImportRef(importRef, null, createImportHandle(importRef), level.intValue(), this);
+			}
+		}
+	}
+
+	TypeDeclaration[] types = unit.types;
+	if (types != null) {
+		for (int i = 0, l = types.length; i < l; i++) {
+			if (nodeSet.matchingNodes.elementSize == 0) return; // reported all the matching nodes
+			TypeDeclaration type = types[i];
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(type);
+			int accuracy = (level != null && matchedUnitContainer) ? level.intValue() : -1;
+			reportMatching(type, null, accuracy, nodeSet, 1);
+		}
+	}
+}
+/**
+ * Visit the given field declaration and report the nodes that match exactly the
+ * search pattern (ie. the ones in the matching nodes set)
+ */
+protected void reportMatching(FieldDeclaration field, TypeDeclaration type, IJavaElement parent, int accuracy, boolean typeInHierarchy, MatchingNodeSet nodeSet) throws CoreException {
+	IJavaElement enclosingElement = null;
+	if (accuracy > -1) {
+		enclosingElement = createHandle(field, type, parent);
+		report(field.sourceStart, field.sourceEnd, enclosingElement, accuracy);
+	}
+
+	// handle the nodes for the local type first
+	if ((field.bits & ASTNode.HasLocalTypeMASK) != 0) {
+		if (enclosingElement == null)
+			enclosingElement = createHandle(field, type, parent);
+		LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor(enclosingElement, nodeSet);
+		try {
+			field.traverse(localDeclarationVisitor, null);
+		} catch (WrappedCoreException e) {
+			throw e.coreException;
+		}
+	}
+
+	if (typeInHierarchy) {
+		ASTNode[] nodes = nodeSet.matchingNodes(field.declarationSourceStart, field.declarationSourceEnd);
+		if (nodes != null) {
+			if ((this.matchContainer & PatternLocator.FIELD_CONTAINER) == 0) {
+				for (int i = 0, l = nodes.length; i < l; i++)
+					nodeSet.matchingNodes.removeKey(nodes[i]);
+			} else {
+				if (enclosingElement == null)
+					enclosingElement = createHandle(field, type, parent);
+				for (int i = 0, l = nodes.length; i < l; i++) {
+					ASTNode node = nodes[i];
+					Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
+					this.patternLocator.matchReportReference(node, enclosingElement, level.intValue(), this);
+				}
+			}
+		}
+	}
+}
+/**
+ * Visit the given type declaration and report the nodes that match exactly the
+ * search pattern (ie. the ones in the matching nodes set)
+ */
+protected void reportMatching(TypeDeclaration type, IJavaElement parent, int accuracy, MatchingNodeSet nodeSet, int occurrenceCount) throws CoreException {
+	// create type handle
+	IJavaElement enclosingElement = parent;
+	if (enclosingElement == null) {
+		enclosingElement = createTypeHandle(new String(type.name));
+	} else if (enclosingElement instanceof IType) {
+		enclosingElement = ((IType) parent).getType(new String(type.name));
+	} else if (enclosingElement instanceof IMember) {
+	    IMember member = (IMember) parent;
+	    if (member.isBinary()) 
+	        enclosingElement = parent;
+	    else
+			enclosingElement = member.getType(new String(type.name), occurrenceCount);
+	}
+	if (enclosingElement == null) return;
+
+	// report the type declaration
+	if (accuracy > -1)
+		report(type.sourceStart, type.sourceEnd, enclosingElement, accuracy);
+
+	boolean matchedClassContainer = (this.matchContainer & PatternLocator.CLASS_CONTAINER) != 0;
+
+	// javadoc
+	if (type.javadoc != null) {
+		ASTNode[] nodes = nodeSet.matchingNodes(type.declarationSourceStart, type.sourceStart);
+		if (nodes != null) {
+			if (!matchedClassContainer) {
+				for (int i = 0, l = nodes.length; i < l; i++)
+					nodeSet.matchingNodes.removeKey(nodes[i]);
+			} else {
+				for (int i = 0, l = nodes.length; i < l; i++) {
+					ASTNode node = nodes[i];
+					Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
+					this.patternLocator.matchReportReference(node, enclosingElement, level.intValue(), this);
+				}
+			}
+		}
+	}
+	
+	// super types
+	if ((type.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+		TypeReference superType =type.allocation.type;
+		if (superType != null) {
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(superType);
+			if (level != null && matchedClassContainer)
+				this.patternLocator.matchReportReference(superType, enclosingElement, level.intValue(), this);
+		}
+	} else {
+		TypeReference superClass = type.superclass;
+		if (superClass != null) {
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(superClass);
+			if (level != null && matchedClassContainer)
+				this.patternLocator.matchReportReference(superClass, enclosingElement, level.intValue(), this);
+		}
+		TypeReference[] superInterfaces = type.superInterfaces;
+		if (superInterfaces != null) {
+			for (int i = 0, l = superInterfaces.length; i < l; i++) {
+				TypeReference superInterface = superInterfaces[i];
+				Integer level = (Integer) nodeSet.matchingNodes.removeKey(superInterface);
+				if (level != null && matchedClassContainer)
+					this.patternLocator.matchReportReference(superInterface, enclosingElement, level.intValue(), this);
+			}
+		}
+	}
+
+	// filter out element not in hierarchy scope
+	boolean typeInHierarchy = type.binding == null || typeInHierarchy(type.binding);
+	matchedClassContainer = matchedClassContainer && typeInHierarchy; 
+
+	FieldDeclaration[] fields = type.fields;
+	if (fields != null) {
+		if (nodeSet.matchingNodes.elementSize == 0) return; // reported all the matching nodes
+		for (int i = 0, l = fields.length; i < l; i++) {
+			FieldDeclaration field = fields[i];
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(field);
+			int value = (level != null && matchedClassContainer) ? level.intValue() : -1;
+			reportMatching(field, type, enclosingElement, value, typeInHierarchy, nodeSet);
+		}
+	}
+
+	AbstractMethodDeclaration[] methods = type.methods;
+	if (methods != null) {
+		if (nodeSet.matchingNodes.elementSize == 0) return; // reported all the matching nodes
+		for (int i = 0, l = methods.length; i < l; i++) {
+			AbstractMethodDeclaration method = methods[i];
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(method);
+			int value = (level != null && matchedClassContainer) ? level.intValue() : -1;
+			reportMatching(method, enclosingElement, value, typeInHierarchy, nodeSet);
+		}
+	}
+
+	TypeDeclaration[] memberTypes = type.memberTypes;
+	if (memberTypes != null) {
+		for (int i = 0, l = memberTypes.length; i < l; i++) {
+			if (nodeSet.matchingNodes.elementSize == 0) return; // reported all the matching nodes
+			TypeDeclaration memberType = memberTypes[i];
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(memberType);
+			int value = (level != null && matchedClassContainer) ? level.intValue() : -1;
+			reportMatching(memberType, enclosingElement, value, nodeSet, 1);
+		}
+	}
+}
+protected boolean typeInHierarchy(ReferenceBinding binding) {
+	if (this.hierarchyResolver == null) return true; // not a hierarchy scope
+	if (this.hierarchyResolver.subOrSuperOfFocus(binding)) return true;
+
+	if (this.allSuperTypeNames != null) {
+		char[][] compoundName = binding.compoundName;
+		for (int i = 0, length = this.allSuperTypeNames.length; i < length; i++)
+			if (CharOperation.equals(compoundName, this.allSuperTypeNames[i]))
+				return true;
+	}
+	return false;
+}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator2.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator2.java
deleted file mode 100644
index 332475b..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator2.java
+++ /dev/null
@@ -1,1430 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.zip.ZipFile;
-
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.runtime.*;
-import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.core.compiler.InvalidInputException;
-import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.core.search.SearchEngine;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
-import org.eclipse.jdt.internal.compiler.env.*;
-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
-import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
-import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.parser.Scanner;
-import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
-import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
-import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.hierarchy.HierarchyResolver;
-import org.eclipse.jdt.internal.core.search.HierarchyScope;
-
-// TODO: (jerome) remove extends
-public class MatchLocator2 extends MatchLocator implements ITypeRequestor {
-	public static final int MAX_AT_ONCE = 500;
-	public static final PotentialMatch[] NO_POTENTIAL_MATH = new PotentialMatch[0];
-	
-/*	// permanent state
-	public SearchPattern pattern;
-	public int detailLevel;
-	public IJavaSearchResultCollector collector;
-	public IJavaSearchScope scope;
-	public IProgressMonitor progressMonitor;
-
-	public IWorkingCopy[] workingCopies;
-	public HandleFactory handleFactory;
-
-	// the following is valid for the current project
-	public MatchLocatorParser parser;
-	public INameEnvironment nameEnvironment;
-	public NameLookup nameLookup;
-	public LookupEnvironment lookupEnvironment;
-	public HierarchyResolver hierarchyResolver;
-	boolean compilationAborted;
-*/
-	// cache of all super type names if scope is hierarchy scope
-	public char[][][] allSuperTypeNames;
-
-	public PotentialMatchSet potentialMatches;
-
-	public int parseThreshold = -1;
-	public CompilerOptions options;
-	
-	// management of unit to be processed
-	public CompilationUnitDeclaration[] unitsToProcess;
-	public PotentialMatch[] matchesToProcess;
-	public int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess
-	
-	public PotentialMatch currentPotentialMatch;
-	
-	public MatchLocator2(
-		SearchPattern pattern,
-		int detailLevel,
-		IJavaSearchResultCollector collector,
-		IJavaSearchScope scope,
-		IProgressMonitor progressMonitor) {
-			
-		super(pattern, detailLevel, collector, scope, progressMonitor);
-		
-		this.pattern = pattern;
-		this.detailLevel = detailLevel;
-		this.collector = collector;
-		this.scope = scope;
-		this.progressMonitor = progressMonitor;
-	}
-	/**
-	 * Add an additional binary type
-	 */
-	public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
-		this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
-	}
-	/**
-	 * Add an additional compilation unit into the loop
-	 *  ->  build compilation unit declarations, their bindings and record their results.
-	 */
-	public void accept(ICompilationUnit sourceUnit) {
-		// Switch the current policy and compilation result for this unit to the requested one.
-		CompilationResult unitResult =
-			new CompilationResult(sourceUnit, totalUnits, totalUnits, this.options.maxProblemsPerUnit);
-		try {
-			// diet parsing for large collection of unit
-			CompilationUnitDeclaration parsedUnit;
-			MatchSet originalMatchSet = this.parser.matchSet;
-			try {
-				this.parser.matchSet = new MatchingNodeSet(this);
-				if (totalUnits < parseThreshold) {
-					parsedUnit = parser.parse(sourceUnit, unitResult);
-				} else {
-					parsedUnit = parser.dietParse(sourceUnit, unitResult);
-				}
-			} finally {
-				this.parser.matchSet = originalMatchSet;
-			}
-		
-			// initial type binding creation
-			lookupEnvironment.buildTypeBindings(parsedUnit);
-			this.addCompilationUnit(sourceUnit, parsedUnit);
-	
-			// binding resolution
-			lookupEnvironment.completeTypeBindings(parsedUnit);
-		} catch (AbortCompilationUnit e) {
-			// at this point, currentCompilationUnitResult may not be sourceUnit, but some other
-			// one requested further along to resolve sourceUnit.
-			if (unitResult.compilationUnit == sourceUnit) { // only report once
-				//requestor.acceptResult(unitResult.tagAsAccepted());
-			} else {
-				throw e; // want to abort enclosing request to compile
-			}
-		}
-	}
-	/**
-	 * Add additional source types
-	 */
-	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
-		// case of SearchableEnvironment of an IJavaProject is used
-		ISourceType sourceType = sourceTypes[0];
-		while (sourceType.getEnclosingType() != null)
-			sourceType = sourceType.getEnclosingType();
-		if (sourceType instanceof SourceTypeElementInfo) {
-			// get source
-			SourceTypeElementInfo elementInfo = (SourceTypeElementInfo) sourceType;
-			IType type = elementInfo.getHandle();
-			ICompilationUnit sourceUnit = (ICompilationUnit)type.getCompilationUnit();
-			this.accept(sourceUnit);
-		} else {
-			CompilationResult result =
-				new CompilationResult(sourceType.getFileName(), 0, 0, 0);
-			CompilationUnitDeclaration unit =
-				SourceTypeConverter.buildCompilationUnit(
-					sourceTypes,
-					true, // need field and methods
-					true, // need member types
-					false, // no need for field initialization
-					lookupEnvironment.problemReporter,
-					result);
-			this.lookupEnvironment.buildTypeBindings(unit);
-			this.lookupEnvironment.completeTypeBindings(unit, true);
-		}
-	}	
-	protected void addCompilationUnit(
-		ICompilationUnit sourceUnit,
-		CompilationUnitDeclaration parsedUnit) {
-
-		// append the unit to the list of ones to process later on
-		int size = this.unitsToProcess.length;
-		if (this.totalUnits == size) {
-			// when growing reposition units starting at position 0
-			int newSize = size == 0 ? 1 : size * 2;
-			System.arraycopy(
-				this.unitsToProcess,
-				0,
-				(this.unitsToProcess = new CompilationUnitDeclaration[newSize]),
-				0,
-				this.totalUnits);
-			System.arraycopy(
-				this.matchesToProcess,
-				0,
-				(this.matchesToProcess = new PotentialMatch[newSize]),
-				0,
-				this.totalUnits);
-		}
-		if (sourceUnit instanceof PotentialMatch) {
-			this.matchesToProcess[this.totalUnits] = (PotentialMatch)sourceUnit;
-		}
-		this.unitsToProcess[this.totalUnits] = parsedUnit;
-		this.totalUnits++;
-	}	
-	void addPotentialMatch(IResource resource, Openable openable) {
-		PotentialMatch potentialMatch = new PotentialMatch(this, resource, openable);
-		this.potentialMatches.add(potentialMatch);
-	}
-	/*
-	 * Caches the given binary type in the lookup environment and returns it.
-	 * Returns the existing one if already cached.
-	 * Returns null if source type binding was cached.
-	 */
-	BinaryTypeBinding cacheBinaryType(IType type) throws JavaModelException {
-		IType enclosingType = type.getDeclaringType();
-		if (enclosingType != null) {
-			// force caching of enclosing types first, so that binary type can be found in lookup enviroment
-			this.cacheBinaryType(enclosingType);
-		}
-		IBinaryType binaryType = (IBinaryType)((BinaryType)type).getElementInfo();
-		BinaryTypeBinding binding = this.lookupEnvironment.cacheBinaryType(binaryType);
-		if (binding == null) { // it was already cached as a result of a previous query
-			char[][] compoundName = CharOperation.splitOn('.', type.getFullyQualifiedName().toCharArray());
-			ReferenceBinding referenceBinding = this.lookupEnvironment.getCachedType(compoundName);
-			if (referenceBinding != null && (referenceBinding instanceof BinaryTypeBinding)) {
-				// if the binding could be found and if it comes from a binary type,
-				binding = (BinaryTypeBinding)referenceBinding;
-			}
-		}
-		return binding;
-	}
-	public  ClassFileReader classFileReader(IType type) {
-		IClassFile classFile = type.getClassFile(); 
-		if (((IOpenable)classFile).isOpen()) {
-			JavaModelManager manager = JavaModelManager.getJavaModelManager();
-			synchronized(manager){
-				return (ClassFileReader)manager.getInfo(type);
-			}
-		} else {
-			IPackageFragment pkg = type.getPackageFragment();
-			IPackageFragmentRoot root = (IPackageFragmentRoot)pkg.getParent();
-			try {
-				if (root.isArchive()) {
-					IPath zipPath = root.isExternal() ? root.getPath() : root.getResource().getLocation();
-					if (zipPath == null) return null; // location is null
-					ZipFile zipFile = null;
-					try {
-						if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
-							System.out.println("(" + Thread.currentThread() + ") [MatchLocator.classFileReader()] Creating ZipFile on " + zipPath); //$NON-NLS-1$	//$NON-NLS-2$
-						}
-						// TODO: (jerome) should use JavaModelManager.getZipFile(...) instead
-						zipFile = new ZipFile(zipPath.toOSString());
-						char[] pkgPath = pkg.getElementName().toCharArray();
-						CharOperation.replace(pkgPath, '.', '/');
-						char[] classFileName = classFile.getElementName().toCharArray();
-						char[] path = pkgPath.length == 0 ? classFileName : CharOperation.concat(pkgPath, classFileName, '/');
-						return ClassFileReader.read(zipFile, new String(path));
-					} finally {
-						if (zipFile != null) {
-							try {
-								zipFile.close();
-							} catch (IOException e) {
-							}
-						}
-					}
-				} else {
-					return ClassFileReader.read(type.getPath().toOSString());
-				}
-			} catch (ClassFormatException e) {
-				return null;
-			} catch (IOException e) {
-				return null;
-			}
-		}
-	}
-	/*
-	 * Computes the super type names of the focus type if any.
-	 */
-	private void computeSuperTypeNames() {
-		if (this.allSuperTypeNames != null) 
-			return; // all super types have already been computed
-		
-		IType focusType = getFocusType();
-		if (focusType == null) return;
-
-		String fullyQualifiedName = focusType.getFullyQualifiedName();
-		int lastDot = fullyQualifiedName.lastIndexOf('.');
-		char[] qualification = lastDot == -1 ? CharOperation.NO_CHAR : fullyQualifiedName.substring(0, lastDot).toCharArray();
-		char[] simpleName = focusType.getElementName().toCharArray();
-
-		SuperTypeNamesCollector superTypeNamesCollector = 
-			new SuperTypeNamesCollector(
-				this.pattern, 
-				simpleName,
-				qualification,
-				new MatchLocator2(this.pattern, this.detailLevel, this.collector, this.scope, this.progressMonitor), // clone MatchLocator so that it has no side effect
-				focusType, 
-				this.progressMonitor);
-		try {
-			this.allSuperTypeNames = superTypeNamesCollector.collect();
-		} catch (JavaModelException e) {
-		}
-	}
-	/**
-	 * Add the initial set of compilation units into the loop
-	 *  ->  build compilation unit declarations, their bindings and record their results.
-	 */
-	protected void createAndResolveBindings(PotentialMatch[] potentialMatches, int start, int length) {
-
-		for (int i = start, maxUnits = start+length; i < maxUnits; i++) {
-			if (this.progressMonitor != null && this.progressMonitor.isCanceled()) {
-				throw new OperationCanceledException();
-			}
-			PotentialMatch potentialMatch = potentialMatches[i];
-			try {
-				if (potentialMatch != null) {
-					this.parser.matchSet = potentialMatch.matchingNodeSet;
-				}
-				CompilationResult unitResult =
-					new CompilationResult(potentialMatch, i, maxUnits, this.options.maxProblemsPerUnit);
-					
-				if (SearchEngine.VERBOSE) {
-					System.out.println("Parsing " + potentialMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
-				}
-
-				// diet parsing for large collection of units
-				CompilationUnitDeclaration parsedUnit;
-				if (totalUnits < parseThreshold) {
-					parsedUnit = this.parser.parse(potentialMatch, unitResult);
-				} else {
-					parsedUnit = this.parser.dietParse(potentialMatch, unitResult);
-				}
-								
-				// initial type binding creation
-				if (parsedUnit != null && !parsedUnit.isEmpty()) {
-					this.lookupEnvironment.buildTypeBindings(parsedUnit);
-				}
-				
-				this.addCompilationUnit(potentialMatch, parsedUnit);
-				
-				// progress reporting
-				if (this.progressMonitor != null) {
-					this.progressMonitor.worked(4);
-				}
-			} finally {
-				this.parser.matchSet = null;
-				potentialMatches[i] = null; // no longer hold onto the unit
-			}
-		}
-		// binding resolution
-		lookupEnvironment.completeTypeBindings();
-	}
-	/**
-	 * Creates an IField from the given field declaration and type. 
-	 */
-	public IField createFieldHandle(
-		FieldDeclaration field,
-		IType type) {
-		if (type == null) return null;
-		return type.getField(new String(field.name));
-	}
-	/*
-	 * Creates hierarchy resolver if needed. 
-	 * Returns whether focus is visible.
-	 */
-	protected boolean createHierarchyResolver(PotentialMatch[] potentialMatches) {
-		// create hierarchy resolver if scope is a hierarchy scope
-		IType focusType = getFocusType();
-		if (focusType != null) {
-			// cache focus type if not a potential match
-			char[][] compoundName = CharOperation.splitOn('.', focusType.getFullyQualifiedName().toCharArray());
-			boolean isPotentialMatch = false;
-			for (int i = 0, length = potentialMatches.length; i < length; i++) {
-				if (CharOperation.equals(potentialMatches[i].compoundName, compoundName)) {
-					isPotentialMatch = true;
-					break;
-				}
-			}
-			if (!isPotentialMatch) {
-				if (focusType.isBinary()) {
-					// cache binary type
-					try {
-						this.cacheBinaryType(focusType);
-					} catch (JavaModelException e) {
-						return false;
-					}
-				} else {
-					// cache all types in the focus' compilation unit (even secondary types)
-					this.accept((ICompilationUnit)focusType.getCompilationUnit());
-				}
-			}
-			
-			// resolve focus type
-			this.hierarchyResolver = new HierarchyResolver(this.lookupEnvironment, null/*hierarchy is not going to be computed*/);
-			ReferenceBinding focusTypeBinding = this.hierarchyResolver.setFocusType(compoundName);
-			if (focusTypeBinding == null || !focusTypeBinding.isValidBinding() || (focusTypeBinding.tagBits & TagBits.HierarchyHasProblems) > 0) {
-				// focus type is not visible from this project
-				return false;
-			}
-		} else {
-			this.hierarchyResolver = null;
-		}
-		return true;
-	}
-	/**
-	 * Creates an IImportDeclaration from the given import statement
-	 */
-	public IJavaElement createImportHandle(ImportReference importRef) {
-		char[] importName = CharOperation.concatWith(importRef.getImportName(), '.');
-		if (importRef.onDemand) {
-			importName = CharOperation.concat(importName, ".*" .toCharArray()); //$NON-NLS-1$
-		}
-		Openable currentOpenable = this.getCurrentOpenable();
-		if (currentOpenable instanceof CompilationUnit) {
-			return ((CompilationUnit)currentOpenable).getImport(
-				new String(importName));
-		} else {
-			try {
-				return ((org.eclipse.jdt.internal.core.ClassFile)currentOpenable).getType();
-			} catch (JavaModelException e) {
-				return null;
-			}
-		}
-	}
-	/**
-	 * Creates an IInitializer from the given field declaration and type. 
-	 */
-	public IInitializer createInitializerHandle(
-		TypeDeclaration typeDecl,
-		FieldDeclaration initializer,
-		IType type) {
-		if (type == null) return null;
-
-		// find occurence count of the given initializer in its type declaration
-		int occurrenceCount = 0;
-		FieldDeclaration[] fields = typeDecl.fields;
-		for (int i = 0, length = fields.length; i < length; i++) {
-			FieldDeclaration field = fields[i];
-			if (!field.isField()) {
-				occurrenceCount++;
-				if (field.equals(initializer)) {
-					break;
-				}
-			}
-		}
-
-		return type.getInitializer(occurrenceCount);
-	}
-	/**
-	 * Creates an IMethod from the given method declaration and type. 
-	 */
-	public IMethod createMethodHandle(
-		AbstractMethodDeclaration method,
-		IType type) {
-		if (type == null) return null;
-		Argument[] arguments = method.arguments;
-		int length = arguments == null ? 0 : arguments.length;
-		if (type.isBinary()) {
-			// don't cache the methods of the binary type
-			ClassFileReader reader = this.classFileReader(type);
-			if (reader == null) return null;
-			IBinaryMethod[] methods = reader.getMethods();
-
-			if (methods != null) {
-				for (int i = 0, methodsLength = methods.length; i < methodsLength; i++) {
-					IBinaryMethod binaryMethod = methods[i];
-					char[] selector = binaryMethod.isConstructor() ? type.getElementName().toCharArray() : binaryMethod.getSelector();
-					if (CharOperation.equals(selector, method.selector)) {
-						String[] parameterTypes = Signature.getParameterTypes(new String(binaryMethod.getMethodDescriptor()));
-						if (length != parameterTypes.length) continue;
-						boolean sameParameters = true;
-						for (int j = 0; j < length; j++) {
-							TypeReference parameterType = arguments[j].type;
-							char[] typeName = CharOperation.concatWith(parameterType.getTypeName(), '.');
-							for (int k = 0; k < parameterType.dimensions(); k++) {
-								typeName = CharOperation.concat(typeName, "[]" .toCharArray()); //$NON-NLS-1$
-							}
-							String parameterTypeName = parameterTypes[j].replace('/', '.');
-							if (!Signature.toString(parameterTypeName).endsWith(new String(typeName))) {
-								sameParameters = false;
-								break;
-							} else {
-								parameterTypes[j] = parameterTypeName;
-							}
-						}
-						if (sameParameters) {
-							return type.getMethod(new String(selector), parameterTypes);
-						}
-					}
-				}
-			}
-			return null;
-		} else {
-			String[] parameterTypeSignatures = new String[length];
-			for (int i = 0; i < length; i++) {
-				TypeReference parameterType = arguments[i].type;
-				char[] typeName = CharOperation.concatWith(parameterType.getTypeName(), '.');
-				for (int j = 0; j < parameterType.dimensions(); j++) {
-					typeName = CharOperation.concat(typeName, "[]" .toCharArray()); //$NON-NLS-1$
-				}
-				parameterTypeSignatures[i] = Signature.createTypeSignature(typeName, false);
-			}
-			return type.getMethod(new String(method.selector), parameterTypeSignatures);
-		}
-	}
-	/**
-	 * Creates an IType from the given simple top level type name. 
-	 */
-	public IType createTypeHandle(char[] simpleTypeName) {
-		Openable currentOpenable = this.getCurrentOpenable();
-		if (currentOpenable instanceof CompilationUnit) {
-			// creates compilation unit
-			CompilationUnit unit = (CompilationUnit)currentOpenable;
-	
-			// create type
-			return unit.getType(new String(simpleTypeName));
-		} else {
-			IType type; 
-			try {
-				type = ((org.eclipse.jdt.internal.core.ClassFile)currentOpenable).getType();
-			} catch (JavaModelException e) {
-				return null;
-			}
-			// ensure this is a top level type (see bug 20011  Searching for Inner Classes gives bad search results)
-			return MatchingOpenable.getTopLevelType(type);
-		}
-	}
-	/**
-	 * Creates an IType from the given simple inner type name and parent type. 
-	 */
-	public IType createTypeHandle(IType parent, char[] simpleTypeName) {
-		return parent.getType(new String(simpleTypeName));
-	}
-	protected Openable getCurrentOpenable() {
-		return this.currentPotentialMatch.openable;
-	}
-	protected IResource getCurrentResource() {
-		return this.currentPotentialMatch.resource;
-	}
-	protected IType getFocusType() {
-		return this.scope instanceof HierarchyScope ? ((HierarchyScope)this.scope).focusType : null;
-	}
-	public IBinaryType getBinaryInfo(org.eclipse.jdt.internal.core.ClassFile classFile, IResource resource) throws CoreException {
-		BinaryType binaryType = (BinaryType)classFile.getType();
-		if (classFile.isOpen()) {
-			// reuse the info from the java model cache
-			return (IBinaryType)binaryType.getElementInfo();
-		} else {
-			// create a temporary info
-			IBinaryType info;
-			try {
-				IJavaElement pkg = classFile.getParent();
-				PackageFragmentRoot root = (PackageFragmentRoot)pkg.getParent();
-				if (root.isArchive()) {
-					// class file in a jar
-					String pkgPath = pkg.getElementName().replace('.', '/');
-					String classFilePath = 
-						(pkgPath.length() > 0) ?
-							pkgPath + "/" + classFile.getElementName() : //$NON-NLS-1$
-							classFile.getElementName();
-					ZipFile zipFile = null;
-					try {
-						zipFile = ((JarPackageFragmentRoot)root).getJar();
-						info = org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.read(
-							zipFile,
-							classFilePath);
-					} finally {
-						JavaModelManager.getJavaModelManager().closeZipFile(zipFile);
-					}
-				} else {
-					// class file in a directory
-					String osPath = resource.getFullPath().toOSString();
-					info = org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.read(osPath);
-				}
-				return info;
-			} catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException e) {
-				//e.printStackTrace();
-				return null;
-			} catch (java.io.IOException e) {
-				throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
-			}
-		}
-	}
-	protected void getMethodBodies(CompilationUnitDeclaration unit, int place) {
-		//fill the methods bodies in order for the code to be generated
-
-		if (unit.ignoreMethodBodies) {
-			unit.ignoreFurtherInvestigation = true;
-			return;
-			// if initial diet parse did not work, no need to dig into method bodies.
-		}
-
-		if (place < parseThreshold)
-			return; //work already done ...
-
-		//real parse of the method....
-		this.parser.scanner.setSource(unit.compilationResult.compilationUnit.getContents());
-		this.parser.parseBodies(unit);
-	}
-	/**
-	 * Create a new parser for the given project, as well as a lookup environment.
-	 */
-	public void initialize(JavaProject project) throws JavaModelException {
-		initialize(project, NO_POTENTIAL_MATH);
-	}
-	/**
-	 * Create a new parser for the given project, as well as a lookup environment.
-	 */
-	public void initialize(JavaProject project, PotentialMatch[] potentialMatches) throws JavaModelException {
-		// create name environment
-		if (this.nameEnvironment != null) { // cleanup
-			this.nameEnvironment.cleanup();
-		}
-		if (potentialMatches.length == 1) {
-			// if only one potential match, a file name environment costs too much,
-			// so use the existing searchable  environment which will populate the java model
-			// only for this potential match and its required types.
-			this.nameEnvironment = project.getSearchableNameEnvironment();
-		} else {
-			this.nameEnvironment = new JavaSearchNameEnvironment2(project);
-		}
-
-		// create lookup environment
-		this.options = new CompilerOptions(project.getOptions(true));
-		ProblemReporter problemReporter =
-			new ProblemReporter(
-				DefaultErrorHandlingPolicies.proceedWithAllProblems(),
-				this.options,
-				new DefaultProblemFactory());
-		this.lookupEnvironment =
-			new LookupEnvironment(this, this.options, problemReporter, this.nameEnvironment);
-			
-		// create parser
-		this.parser = new MatchLocatorParser(problemReporter, this.options.sourceLevel >= CompilerOptions.JDK1_4);
-				
-		// remember project's name lookup
-		this.nameLookup = project.getNameLookup();
-		
-		// initialize queue of units
-		this.totalUnits = 0;
-		int maxUnits = potentialMatches.length;
-		this.unitsToProcess = new CompilationUnitDeclaration[maxUnits];
-		this.matchesToProcess = new PotentialMatch[maxUnits];
-
-	}
-	public boolean hasAlreadyDefinedType(CompilationUnitDeclaration parsedUnit) {
-		if (parsedUnit == null) return false;
-		CompilationResult result = parsedUnit.compilationResult;
-		if (result == null) return false;
-		for (int i = 0; i < result.problemCount; i++) {
-			IProblem problem = result.problems[i];
-			if (problem.getID() == IProblem.DuplicateTypes) {
-				return true;
-			}
-		}
-		return false;
-	}	
-	/**
-	 * Locate the matches amongst the potential matches.
-	 */
-	private void locateMatches(JavaProject javaProject) throws JavaModelException {
-		PotentialMatch[] potentialMatches = this.potentialMatches.getPotentialMatches(javaProject.getPackageFragmentRoots());
-		
-		int length = potentialMatches.length;
-		int index = 0;
-		while (index < length) {
-			int max = Math.min(MAX_AT_ONCE, length-index);
-			locateMatches(javaProject, potentialMatches, index, max);
-			index += max;
-		}
-	}
-	private void locateMatches(JavaProject javaProject, PotentialMatch[] potentialMatches, int start, int length) throws JavaModelException {
-		
-		// copy array because elements  from the original are removed below
-		PotentialMatch[] copy = new PotentialMatch[length];
-		System.arraycopy(potentialMatches, start, copy, 0, length);
-		this.initialize(javaProject, copy);
-		
-		this.compilationAborted = false;
-		
-		// create and resolve binding (equivalent to beginCompilation() in Compiler)
-		try {
-			this.createAndResolveBindings(potentialMatches, start, length);
-		} catch (AbortCompilation e) {
-			this.compilationAborted = true;
-		}
-		
-		// create hierarchy resolver if needed
-		try {
-			if (!this.compilationAborted && !this.createHierarchyResolver(copy)) {
-				// focus type is not visible, use the super type names instead of the bindings
-				computeSuperTypeNames();
-				if (this.allSuperTypeNames == null) return;
-			}
-		} catch (AbortCompilation e) {
-			this.compilationAborted = true;
-		}
-		
-		// free memory
-		copy = null;
-		potentialMatches = null;
-		
-		// potential match resolution
-		try {
-			CompilationUnitDeclaration unit = null;
-			for (int i = 0; i < this.totalUnits; i++) {
-				if (this.progressMonitor != null && this.progressMonitor.isCanceled()) {
-					throw new OperationCanceledException();
-				}
-				unit = this.unitsToProcess[i];
-				try {
-					process(unit, i);
-				} catch (AbortCompilation e) {
-					// problem with class path: it could not find base classes
-					// continue and try next matching openable reporting innacurate matches (since bindings will be null)
-					this.compilationAborted = true;
-				} catch (CoreException e) {
-					if (e instanceof JavaModelException) {
-						// problem with class path: it could not find base classes
-						// continue and try next matching openable reporting innacurate matches (since bindings will be null)
-						this.compilationAborted = true;
-					} else {
-						// core exception thrown by client's code: let it through
-						throw new JavaModelException(e);
-					}
-				} finally {
-					// cleanup compilation unit result
-					unit.cleanUp();
-					if (this.options.verbose)
-						System.out.println(Util.bind("compilation.done", //$NON-NLS-1$
-					new String[] {
-						String.valueOf(i + 1),
-						String.valueOf(totalUnits),
-						new String(unitsToProcess[i].getFileName())}));
-				}
-				this.unitsToProcess[i] = null; // release reference to processed unit declaration
-				this.matchesToProcess[i] = null; // release reference to processed potential match
-				if (this.progressMonitor != null) {
-					this.progressMonitor.worked(5);
-				}
-			}
-		} catch (AbortCompilation e) {
-			this.compilationAborted = true;
-		}		
-	}
-	
-	/**
-	 * Locate the matches in the given files and report them using the search requestor. 
-	 */
-	public void locateMatches(
-		String[] filePaths, 
-		IWorkspace workspace,
-		IWorkingCopy[] workingCopies)
-		throws JavaModelException {
-			
-		if (SearchEngine.VERBOSE) {
-			System.out.println("Locating matches in files ["); //$NON-NLS-1$
-			for (int i = 0, length = filePaths.length; i < length; i++) {
-				String path = filePaths[i];
-				System.out.println("\t" + path); //$NON-NLS-1$
-			}
-			System.out.println("]"); //$NON-NLS-1$
-			if (workingCopies != null) {
-				 System.out.println("and working copies ["); //$NON-NLS-1$
-				for (int i = 0, length = workingCopies.length; i < length; i++) {
-					IWorkingCopy wc = workingCopies[i];
-					System.out.println("\t" + ((JavaElement)wc).toStringWithAncestors()); //$NON-NLS-1$
-				}
-				System.out.println("]"); //$NON-NLS-1$
-			}
-		}
-		
-		JavaModelManager manager = JavaModelManager.getJavaModelManager();
-		try {
-			// optimize access to zip files during search operation
-			manager.cacheZipFiles();
-				
-			// initialize handle factory (used as a cache of handles so as to optimize space)
-			if (this.handleFactory == null) {
-				this.handleFactory = new HandleFactory(workspace);
-			}
-			
-			// initialize locator with working copies
-			this.workingCopies = workingCopies;
-			
-			// substitute compilation units with working copies
-			HashMap wcPaths = new HashMap(); // a map from path to working copies
-			int wcLength;
-			if (workingCopies != null && (wcLength = workingCopies.length) > 0) {
-				String[] newPaths = new String[wcLength];
-				for (int i = 0; i < wcLength; i++) {
-					IWorkingCopy workingCopy = workingCopies[i];
-					String path = workingCopy.getOriginalElement().getPath().toString();
-					wcPaths.put(path, workingCopy);
-					newPaths[i] = path;
-				}
-				int filePathsLength = filePaths.length;
-				System.arraycopy(filePaths, 0, filePaths = new String[filePathsLength+wcLength], 0, filePathsLength);
-				System.arraycopy(newPaths, 0, filePaths, filePathsLength, wcLength);
-			}
-			
-			int length = filePaths.length;
-			if (progressMonitor != null) {
-				if (this.pattern.needsResolve) {
-					progressMonitor.beginTask("", length * 10); // 1 for file path, 4 for parsing and binding creation, 5 for binding resolution //$NON-NLS-1$
-				} else {
-					progressMonitor.beginTask("", length * 5); // 1 for file path, 4 for parsing and binding creation //$NON-NLS-1$
-				}
-			}
-	
-			// sort file paths projects
-			Util.sort(filePaths); 
-			
-			// initialize pattern for polymorphic search (ie. method reference pattern)
-			this.potentialMatches = new PotentialMatchSet();
-			this.pattern.initializePolymorphicSearch(this, progressMonitor);
-			
-			JavaProject previousJavaProject = null;
-			for (int i = 0; i < length; i++) {
-				if (progressMonitor != null && progressMonitor.isCanceled()) {
-					throw new OperationCanceledException();
-				}
-				String pathString = filePaths[i];
-				
-				// skip duplicate paths
-				if (i > 0 && pathString.equals(filePaths[i-1])) continue;
-				
-				Openable openable;
-				IWorkingCopy workingCopy = (IWorkingCopy)wcPaths.get(pathString);
-				if (workingCopy != null) {
-					openable = (Openable)workingCopy;
-				} else {
-					openable = this.handleFactory.createOpenable(pathString, this.scope);
-					if (openable == null)
-						continue; // match is outside classpath
-				}
-	
-				// create new parser and lookup environment if this is a new project
-				IResource resource = null;
-				JavaProject javaProject = null;
-				try {
-					javaProject = (JavaProject) openable.getJavaProject();
-					if (workingCopy != null) {
-						resource = workingCopy.getOriginalElement().getResource();
-					} else {
-						resource = openable.getResource();
-					}
-					if (resource == null) { // case of a file in an external jar
-						resource = javaProject.getProject();
-					}
-					if (!javaProject.equals(previousJavaProject)) {
-						// locate matches in previous project
-						if (previousJavaProject != null) {
-							try {
-								this.locateMatches(previousJavaProject);
-							} catch (JavaModelException e) {
-								if (e.getException() instanceof CoreException) {
-									throw e;
-								} else {
-									// problem with classpath in this project -> skip it
-								}
-							}
-							this.potentialMatches = new PotentialMatchSet();
-						}
-	
-						previousJavaProject = javaProject;
-					}
-				} catch (JavaModelException e) {
-					// file doesn't exist -> skip it
-					continue;
-				}
-	
-				// add potential match
-				this.addPotentialMatch(resource, openable);
-	
-				if (progressMonitor != null) {
-					progressMonitor.worked(1);
-				}
-			}
-			
-			// last project
-			if (previousJavaProject != null) {
-				try {
-					this.locateMatches(previousJavaProject);
-				} catch (JavaModelException e) {
-					if (e.getException() instanceof CoreException) {
-						throw e;
-					} else {
-						// problem with classpath in last project -> skip it
-					}
-				}
-				this.potentialMatches = new PotentialMatchSet();
-			} 
-			
-			if (progressMonitor != null) {
-				progressMonitor.done();
-			}
-		} finally {
-			if (this.nameEnvironment != null) {
-				this.nameEnvironment.cleanup();
-			}
-			manager.flushZipFiles();
-		}	
-	}
-	/**
-	 * Locates the package declarations corresponding to this locator's pattern. 
-	 */
-	public void locatePackageDeclarations(IWorkspace workspace)
-		throws JavaModelException {
-		this.locatePackageDeclarations(this.pattern, workspace);
-	}
-
-	/**
-	 * Locates the package declarations corresponding to the search pattern. 
-	 */
-	private void locatePackageDeclarations(
-		SearchPattern searchPattern,
-		IWorkspace workspace)
-		throws JavaModelException {
-		if (searchPattern instanceof OrPattern) {
-			OrPattern orPattern = (OrPattern) searchPattern;
-			this.locatePackageDeclarations(orPattern.leftPattern, workspace);
-			this.locatePackageDeclarations(orPattern.rightPattern, workspace);
-		} else
-			if (searchPattern instanceof PackageDeclarationPattern) {
-				PackageDeclarationPattern pkgPattern =
-					(PackageDeclarationPattern) searchPattern;
-				IJavaProject[] projects =
-					JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
-				for (int i = 0, length = projects.length; i < length; i++) {
-					IJavaProject javaProject = projects[i];
-					IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
-					for (int j = 0, rootsLength = roots.length; j < rootsLength; j++) {
-						IJavaElement[] pkgs = roots[j].getChildren();
-						for (int k = 0, pksLength = pkgs.length; k < pksLength; k++) {
-							IPackageFragment pkg = (IPackageFragment)pkgs[k];
-							if (pkg.getChildren().length > 0 
-									&& pkgPattern.matchesName(pkgPattern.pkgName, pkg.getElementName().toCharArray())) {
-								IResource resource = pkg.getResource();
-								if (resource == null) { // case of a file in an external jar
-									resource = javaProject.getProject();
-								}
-								this.currentPotentialMatch = new PotentialMatch(this, resource, null);
-								try {
-									this.report(-1, -2, pkg, IJavaSearchResultCollector.EXACT_MATCH);
-								} catch (CoreException e) {
-									if (e instanceof JavaModelException) {
-										throw (JavaModelException) e;
-									} else {
-										throw new JavaModelException(e);
-									}
-								}
-							}
-						}
-					}
-				}
-			}
-	}
-	/*
-	 * Process a compilation unit already parsed and build.
-	 */
-	public void process(CompilationUnitDeclaration unit, int i) throws CoreException {
-		MatchingNodeSet matchingNodeSet = null;
-		try {
-			this.currentPotentialMatch = this.matchesToProcess[i];
-			if (this.currentPotentialMatch == null) return;
-			matchingNodeSet = this.currentPotentialMatch.matchingNodeSet;
-			
-			if (unit == null || unit.isEmpty()) {
-				if (this.currentPotentialMatch.openable instanceof org.eclipse.jdt.internal.core.ClassFile) {
-					this.currentPotentialMatch.locateMatchesInClassFile();
-				}
-				return;
-			}
-			if (hasAlreadyDefinedType(unit)) {
-				// skip type has it is hidden so not visible
-				return;
-			}
-	
-			this.parser.matchSet = this.currentPotentialMatch.matchingNodeSet;
-			getMethodBodies(unit, i);
-						
-			// report matches that don't need resolve
-			matchingNodeSet.cuHasBeenResolved = this.compilationAborted;
-			matchingNodeSet.reportMatching(unit);
-
-			if ((this.pattern.needsResolve || matchingNodeSet.needsResolve()/* TODO: do not need this check any longer */) 
-					&& unit.types != null 
-					&& !this.compilationAborted) {
-
-				if (SearchEngine.VERBOSE) {
-					System.out.println("Resolving " + this.currentPotentialMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
-				}
-
-				// fault in fields & methods
-				if (unit.scope != null)
-					unit.scope.faultInTypes();
-		
-				// verify inherited methods
-				if (unit.scope != null)
-					unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier());
-		
-				// type checking
-				unit.resolve();
-		
-				// refresh the total number of units known at this stage
-				unit.compilationResult.totalUnitsKnown = totalUnits;
-
-				// report matches that needed resolve
-				matchingNodeSet.cuHasBeenResolved = true;
-				matchingNodeSet.reportMatching(unit);
-			}
-		} catch (AbortCompilation e) {
-			// could not resolve: report innacurate matches
-			if (matchingNodeSet != null) {
-				matchingNodeSet.cuHasBeenResolved = true;
-				matchingNodeSet.reportMatching(unit);
-			}
-			if (!(e instanceof AbortCompilationUnit)) {
-				// problem with class path
-				throw e;
-			}
-		} finally {
-			this.parser.matchSet = null;
-			this.currentPotentialMatch = null;
-		}
-	}
-	public void report(
-		int sourceStart,
-		int sourceEnd,
-		IJavaElement element,
-		int accuracy)
-		throws CoreException {
-
-		if (this.scope.encloses(element)) {
-			if (SearchEngine.VERBOSE) {
-				IResource res = this.getCurrentResource();
-				System.out.println("Reporting match"); //$NON-NLS-1$
-				System.out.println("\tResource: " + (res == null ? " <unknown> " : res.getFullPath().toString())); //$NON-NLS-2$//$NON-NLS-1$
-				System.out.println("\tPositions: [" + sourceStart + ", " + sourceEnd + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-				System.out.println("\tJava element: " + ((JavaElement)element).toStringWithAncestors()); //$NON-NLS-1$
-				if (accuracy == IJavaSearchResultCollector.EXACT_MATCH) {
-					System.out.println("\tAccuracy: EXACT_MATCH"); //$NON-NLS-1$
-				} else {
-					System.out.println("\tAccuracy: POTENTIAL_MATCH"); //$NON-NLS-1$
-				}
-			}
-			this.report(
-				this.getCurrentResource(),
-				sourceStart,
-				sourceEnd,
-				element,
-				accuracy);
-		}
-	}
-	public void report(
-		IResource resource,
-		int sourceStart,
-		int sourceEnd,
-		IJavaElement element,
-		int accuracy)
-		throws CoreException {
-
-		this.collector.accept(
-			resource,
-			sourceStart,
-			sourceEnd + 1,
-			element,
-			accuracy);
-	}
-	/**
-	 * Finds the accurate positions of the sequence of tokens given by qualifiedName
-	 * in the source and reports a reference to this this qualified name
-	 * to the search requestor.
-	 */
-	public void reportAccurateReference(
-		int sourceStart,
-		int sourceEnd,
-		char[][] qualifiedName,
-		IJavaElement element,
-		int accuracy)
-		throws CoreException {
-	
-		if (accuracy == -1) return;
-	
-		// compute source positions of the qualified reference 
-		Scanner scanner = this.parser.scanner;
-		scanner.setSource(
-			this.currentPotentialMatch.getContents());
-		scanner.resetTo(sourceStart, sourceEnd);
-	
-		int refSourceStart = -1, refSourceEnd = -1;
-		int tokenNumber = qualifiedName.length;
-		int token = -1;
-		int previousValid = -1;
-		int i = 0;
-		int currentPosition;
-		do {
-			// find first token that is an identifier (parenthesized expressions include parenthesises in source range - see bug 20693 - Finding references to variables does not find all occurrences  )
-			do {
-				currentPosition = scanner.currentPosition;
-				try {
-					token = scanner.getNextToken();
-				} catch (InvalidInputException e) {
-				}
-			} while (token !=  TerminalTokens.TokenNameIdentifier && token !=  TerminalTokens.TokenNameEOF);
-	
-			if (token != TerminalTokens.TokenNameEOF) {
-				char[] currentTokenSource = scanner.getCurrentTokenSource();
-				boolean equals = false;
-				while (i < tokenNumber
-					&& !(equals = this.pattern.matchesName(qualifiedName[i++], currentTokenSource))) {
-				}
-				if (equals && (previousValid == -1 || previousValid == i - 2)) {
-					previousValid = i - 1;
-					if (refSourceStart == -1) {
-						refSourceStart = currentPosition;
-					}
-					refSourceEnd = scanner.currentPosition - 1;
-				} else {
-					i = 0;
-					refSourceStart = -1;
-					previousValid = -1;
-				}
-				// read '.'
-				try {
-					token = scanner.getNextToken();
-				} catch (InvalidInputException e) {
-				}
-			}
-			if (i == tokenNumber) {
-				// accept reference
-				if (refSourceStart != -1) {
-					this.report(refSourceStart, refSourceEnd, element, accuracy);
-				} else {
-					this.report(sourceStart, sourceEnd, element, accuracy);
-				}
-				return;
-			}
-		} while (token != TerminalTokens.TokenNameEOF);
-	
-	}
-	/**
-	 * Finds the accurate positions of each valid token in the source and
-	 * reports a reference to this token to the search requestor.
-	 * A token is valid if it has an accurracy which is not -1.
-	 */
-	public void reportAccurateReference(
-		int sourceStart,
-		int sourceEnd,
-		char[][] tokens,
-		IJavaElement element,
-		int[] accuracies)
-		throws CoreException {
-
-		// compute source positions of the qualified reference 
-		Scanner scanner = this.parser.scanner;
-		scanner.setSource(
-			this.currentPotentialMatch.getContents());
-		scanner.resetTo(sourceStart, sourceEnd);
-
-		int refSourceStart = -1, refSourceEnd = -1;
-		int length = tokens.length;
-		int token = -1;
-		int previousValid = -1;
-		int i = 0;
-		int accuracyIndex = 0;
-		do {
-			int currentPosition = scanner.currentPosition;
-			// read token
-			try {
-				token = scanner.getNextToken();
-			} catch (InvalidInputException e) {
-			}
-			if (token != TerminalTokens.TokenNameEOF) {
-				char[] currentTokenSource = scanner.getCurrentTokenSource();
-				boolean equals = false;
-				while (i < length
-					&& !(equals = this.pattern.matchesName(tokens[i++], currentTokenSource))) {
-				}
-				if (equals && (previousValid == -1 || previousValid == i - 2)) {
-					previousValid = i - 1;
-					if (refSourceStart == -1) {
-						refSourceStart = currentPosition;
-					}
-					refSourceEnd = scanner.currentPosition - 1;
-				} else {
-					i = 0;
-					refSourceStart = -1;
-					previousValid = -1;
-				}
-				// read '.'
-				try {
-					token = scanner.getNextToken();
-				} catch (InvalidInputException e) {
-				}
-			}
-			if (accuracies[accuracyIndex] != -1) {
-				// accept reference
-				if (refSourceStart != -1) {
-					this.report(refSourceStart, refSourceEnd, element, accuracies[accuracyIndex]);
-				} else {
-					this.report(sourceStart, sourceEnd, element, accuracies[accuracyIndex]);
-				}
-				i = 0;
-			}
-			refSourceStart = -1;
-			previousValid = -1;
-			if (accuracyIndex < accuracies.length-1) {
-				accuracyIndex++;
-			}
-		} while (token != TerminalTokens.TokenNameEOF);
-
-	}
-	public void reportBinaryMatch(
-		IMember binaryMember,
-		IBinaryType info,
-		int accuracy)
-		throws CoreException, JavaModelException {
-			
-		this.reportBinaryMatch(null, binaryMember, info, accuracy);
-	}
-	public void reportBinaryMatch(
-		IResource resource,
-		IMember binaryMember,
-		IBinaryType info,
-		int accuracy)
-		throws CoreException, JavaModelException {
-		ISourceRange range = binaryMember.getNameRange();
-		if (range.getOffset() == -1) {
-			ClassFile classFile = (ClassFile) binaryMember.getClassFile();
-			SourceMapper mapper = classFile.getSourceMapper();
-			if (mapper != null) {
-				IType type = classFile.getType();
-				String sourceFileName = mapper.findSourceFileName(type, info);
-				if (sourceFileName != null) {
-					char[] contents = mapper.findSource(type, sourceFileName);
-					if (contents != null) {
-						range = mapper.mapSource(type, contents, binaryMember);
-					}
-				}
-			}
-		}
-		int startIndex = range.getOffset();
-		int endIndex = startIndex + range.getLength() - 1;
-		if (resource == null) {
-			this.report(startIndex, endIndex, binaryMember, accuracy);
-		} else {
-			this.report(resource, startIndex, endIndex, binaryMember, accuracy);
-		}
-	}
-	/**
-	 * Reports the given field declaration to the search requestor.
-	 */
-	public void reportFieldDeclaration(
-		FieldDeclaration fieldDeclaration,
-		IJavaElement parent,
-		int accuracy)
-		throws CoreException {
-
-		// accept field declaration
-		this.report(
-			fieldDeclaration.sourceStart,
-			fieldDeclaration.sourceEnd,
-			(parent instanceof IType) ?
-				((IType)parent).getField(new String(fieldDeclaration.name)) :
-				parent,
-			accuracy);
-	}
-	/**
-	 * Reports the given import to the search requestor.
-	 */
-	public void reportImport(ImportReference reference, int accuracy)
-		throws CoreException {
-
-		// create defining import handle
-		IJavaElement importHandle = this.createImportHandle(reference);
-
-		// accept reference
-		this.pattern.matchReportImportRef(reference, null, importHandle, accuracy, this);
-	}
-	/**
-	 * Reports the given method declaration to the search requestor.
-	 */
-	public void reportMethodDeclaration(
-		AbstractMethodDeclaration methodDeclaration,
-		IJavaElement parent,
-		int accuracy)
-		throws CoreException {
-
-		IJavaElement enclosingElement;
-		if (parent instanceof IType) {
-			// create method handle
-			enclosingElement = this.createMethodHandle(methodDeclaration, (IType)parent);
-			if (enclosingElement == null) return;
-		} else {
-			enclosingElement = parent;
-		}
-
-		// compute source positions of the selector 
-		Scanner scanner = parser.scanner;
-		int nameSourceStart = methodDeclaration.sourceStart;
-		scanner.setSource(
-			this.currentPotentialMatch.getContents());
-		scanner.resetTo(nameSourceStart, methodDeclaration.sourceEnd);
-		try {
-			scanner.getNextToken();
-		} catch (InvalidInputException e) {
-		}
-		int nameSourceEnd = scanner.currentPosition - 1;
-
-		// accept method declaration
-		this.report(nameSourceStart, nameSourceEnd, enclosingElement, accuracy);
-	}
-	/**
-	 * Reports the given package declaration to the search requestor.
-	 */
-	public void reportPackageDeclaration(ImportReference node) {
-		// TBD
-	}
-	/**
-	 * Reports the given reference to the search requestor.
-	 * It is done in the given method and the method's defining types 
-	 * have the given simple names.
-	 */
-	public void reportReference(
-		AstNode reference,
-		AbstractMethodDeclaration methodDeclaration,
-		IJavaElement parent,
-		int accuracy)
-		throws CoreException {
-
-		IJavaElement enclosingElement;
-		if (parent instanceof IType) {
-			// create defining method handle
-			enclosingElement = this.createMethodHandle(methodDeclaration, (IType)parent);
-			if (enclosingElement == null) return; // case of a match found in a type other than the current class file
-		} else {
-			enclosingElement = parent;
-		}
-
-		// accept reference
-		this.pattern.matchReportReference(reference, enclosingElement, accuracy, this);
-	}
-	/**
-	 * Reports the given reference to the search requestor.
-	 * It is done in the given field and given type.
-	 * The field's defining types have the given simple names.
-	 */
-	public void reportReference(
-		AstNode reference,
-		TypeDeclaration typeDeclaration,
-		FieldDeclaration fieldDeclaration,
-		IJavaElement parent,
-		int accuracy)
-		throws CoreException {
-
-		IJavaElement enclosingElement;
-		if (fieldDeclaration.isField()) {
-			if (parent instanceof IType) {
-				// create defining field handle
-				enclosingElement = this.createFieldHandle(fieldDeclaration, (IType)parent);
-				if (enclosingElement == null) return;
-			} else {
-				enclosingElement = parent;
-			}
-
-			// accept reference
-			this.pattern.matchReportReference(reference, enclosingElement, accuracy, this);
-		} else { // initializer
-			if (parent instanceof IType) {
-				// create defining initializer
-				enclosingElement =
-					this.createInitializerHandle(
-						typeDeclaration,
-						fieldDeclaration,
-						(IType)parent);
-				if (enclosingElement == null) return;
-			} else {
-				enclosingElement = parent;
-			}
-
-			// accept reference
-			this.pattern.matchReportReference(reference, enclosingElement, accuracy, this);
-		}
-	}
-	/**
-	 * Reports the given super type reference to the search requestor.
-	 * It is done in the given defining type (with the given simple names).
-	 */
-	public void reportSuperTypeReference(
-		TypeReference typeRef,
-		IJavaElement type,
-		int accuracy)
-		throws CoreException {
-
-		// accept type reference
-		this.pattern.matchReportReference(typeRef, type, accuracy, this);
-	}
-	/**
-	 * Reports the given type declaration to the search requestor.
-	 */
-	public void reportTypeDeclaration(
-		TypeDeclaration typeDeclaration,
-		IJavaElement parent,
-		int accuracy)
-		throws CoreException {
-
-		// accept class or interface declaration
-		this.report(
-			typeDeclaration.sourceStart,
-			typeDeclaration.sourceEnd,
-			(parent == null) ?
-				this.createTypeHandle(typeDeclaration.name) :
-				(parent instanceof IType) ?
-					this.createTypeHandle((IType)parent, typeDeclaration.name) :
-					parent,
-			accuracy);
-	}
-	public boolean typeInHierarchy(ReferenceBinding binding) {
-		if (this.hierarchyResolver == null) return true; // not a hierarchy scope
-		if (this.hierarchyResolver.subOrSuperOfFocus(binding)) {
-			return true;
-		} else if (this.allSuperTypeNames != null) {
-			char[][] compoundName = binding.compoundName;
-			for (int i = 0, length = this.allSuperTypeNames.length; i < length; i++) {
-				if (CharOperation.equals(compoundName, this.allSuperTypeNames[i])) 
-					return true;
-			}
-			return false;
-		} else {
-			return false;
-		}	
-	}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
index ffbc36e..d7884ec 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
@@ -10,140 +10,180 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
-import org.eclipse.core.resources.IFile;
-import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Initializer;
-import org.eclipse.jdt.internal.compiler.ast.LocalTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MemberTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.NameReference;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
-import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.parser.Parser;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
-import org.eclipse.jdt.internal.core.CompilationUnit;
 
 /**
  * A parser that locates ast nodes that match a given search pattern.
  */
 public class MatchLocatorParser extends Parser {
 
-	public MatchSet matchSet;
-	private LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor();
-	
+MatchingNodeSet nodeSet;
+PatternLocator patternLocator;
+private ASTVisitor localDeclarationVisitor;
+
+public static MatchLocatorParser createParser(ProblemReporter problemReporter, MatchLocator locator) {
+	if ((locator.matchContainer & PatternLocator.COMPILATION_UNIT_CONTAINER) != 0)
+		return new ImportMatchLocatorParser(problemReporter, locator);
+	return new MatchLocatorParser(problemReporter, locator);
+}
+
 /**
  * An ast visitor that visits local type declarations.
  */
-public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
-	public boolean visit(
-			AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
-			BlockScope scope) {
-		if ((matchSet.matchContainer & SearchPattern.METHOD) != 0) {
-			matchSet.checkMatching(anonymousTypeDeclaration);
-		}
-		return true; 
-	}
-	public boolean visit(
-			ConstructorDeclaration constructorDeclaration,
-			ClassScope scope) {
-		if ((matchSet.matchContainer & SearchPattern.CLASS) != 0) {
-			matchSet.checkMatching(constructorDeclaration);
-		}
-		return (constructorDeclaration.bits & AstNode.HasLocalTypeMASK) != 0; // continue only if it has local type
+public class NoClassNoMethodDeclarationVisitor extends ASTVisitor {
+	public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
+		return (constructorDeclaration.bits & ASTNode.HasLocalTypeMASK) != 0; // continue only if it has local type
 	}
 	public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
-		if ((matchSet.matchContainer & SearchPattern.CLASS) != 0) {
-			matchSet.checkMatching(fieldDeclaration);
-		}
-		return (fieldDeclaration.bits & AstNode.HasLocalTypeMASK) != 0; // continue only if it has local type;
+		return (fieldDeclaration.bits & ASTNode.HasLocalTypeMASK) != 0; // continue only if it has local type;
 	}
 	public boolean visit(Initializer initializer, MethodScope scope) {
-		if ((matchSet.matchContainer & SearchPattern.CLASS) != 0) {
-			matchSet.checkMatching(initializer);
-		}
-		return (initializer.bits & AstNode.HasLocalTypeMASK) != 0; // continue only if it has local type
+		return (initializer.bits & ASTNode.HasLocalTypeMASK) != 0; // continue only if it has local type
 	}
-	public boolean visit(
-			LocalTypeDeclaration localTypeDeclaration,
-			BlockScope scope) {
-		if ((matchSet.matchContainer & SearchPattern.METHOD) != 0) {
-			matchSet.checkMatching(localTypeDeclaration);
-		}
+	public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
+		return (methodDeclaration.bits & ASTNode.HasLocalTypeMASK) != 0; // continue only if it has local type
+	}
+}
+public class MethodButNoClassDeclarationVisitor extends NoClassNoMethodDeclarationVisitor {
+	public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+		patternLocator.match(localTypeDeclaration, nodeSet);
 		return true;
 	}
-	public boolean visit(
-			MemberTypeDeclaration memberTypeDeclaration,
-			ClassScope scope) {
-		if ((matchSet.matchContainer & SearchPattern.CLASS) != 0) {
-			matchSet.checkMatching(memberTypeDeclaration);
-		}
+}
+public class ClassButNoMethodDeclarationVisitor extends ASTVisitor {
+	public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) {
+		patternLocator.match(constructorDeclaration, nodeSet);
+		return (constructorDeclaration.bits & ASTNode.HasLocalTypeMASK) != 0; // continue only if it has local type
+	}
+	public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+		patternLocator.match(fieldDeclaration, nodeSet);
+		return (fieldDeclaration.bits & ASTNode.HasLocalTypeMASK) != 0; // continue only if it has local type;
+	}
+	public boolean visit(Initializer initializer, MethodScope scope) {
+		patternLocator.match(initializer, nodeSet);
+		return (initializer.bits & ASTNode.HasLocalTypeMASK) != 0; // continue only if it has local type
+	}
+	public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
+		patternLocator.match(memberTypeDeclaration, nodeSet);
 		return true;
 	}
 	public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
-		if ((matchSet.matchContainer & SearchPattern.CLASS) != 0) {
-			matchSet.checkMatching(methodDeclaration);
-		}
-		return (methodDeclaration.bits & AstNode.HasLocalTypeMASK) != 0; // continue only if it has local type
+		patternLocator.match(methodDeclaration, nodeSet);
+		return (methodDeclaration.bits & ASTNode.HasLocalTypeMASK) != 0; // continue only if it has local type
 	}
-	
+}
+public class ClassAndMethodDeclarationVisitor extends ClassButNoMethodDeclarationVisitor {
+	public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+		patternLocator.match(localTypeDeclaration, nodeSet);
+		return true;
+	}
 }
 
-public MatchLocatorParser(ProblemReporter problemReporter, boolean assertMode) {
-	super(problemReporter, true, assertMode);
+protected MatchLocatorParser(ProblemReporter problemReporter, MatchLocator locator) {
+	super(problemReporter, true);
+
+	this.patternLocator = locator.patternLocator;
+	if ((locator.matchContainer & PatternLocator.CLASS_CONTAINER) != 0) {
+		this.localDeclarationVisitor = (locator.matchContainer & PatternLocator.METHOD_CONTAINER) != 0
+			? new ClassAndMethodDeclarationVisitor()
+			: new ClassButNoMethodDeclarationVisitor();
+	} else {
+		this.localDeclarationVisitor = (locator.matchContainer & PatternLocator.METHOD_CONTAINER) != 0
+			? new MethodButNoClassDeclarationVisitor()
+			: new NoClassNoMethodDeclarationVisitor();
+	}
+
+	// Always check javadoc while matching indexes
+	this.javadocParser.checkJavadoc = true;
+}
+public void checkComment() {
+	super.checkComment();
+	if (this.javadocParser.checkJavadoc && this.javadoc != null) {
+		// Search for pattern locator matches in javadoc comment @throws/@exception tags
+		TypeReference[] thrownExceptions = this.javadoc.thrownExceptions;
+		int throwsTagsNbre = thrownExceptions == null ? 0 : thrownExceptions.length;
+		for (int i = 0; i < throwsTagsNbre; i++) {
+			TypeReference typeRef = thrownExceptions[i];
+			patternLocator.match(typeRef, nodeSet);
+		}
+
+		// Search for pattern locator matches in javadoc comment @see tags
+		Expression[] references = this.javadoc.references;
+		int seeTagsNbre = references == null ? 0 : references.length;
+		for (int i = 0; i < seeTagsNbre; i++) {
+			Expression reference = references[i];
+			if (reference instanceof TypeReference) {
+				TypeReference typeRef = (TypeReference) reference;
+				patternLocator.match(typeRef, nodeSet);
+			} else if (reference instanceof JavadocFieldReference) {
+				JavadocFieldReference fieldRef = (JavadocFieldReference) reference;
+				patternLocator.match(fieldRef, nodeSet);
+				if (fieldRef.receiver instanceof TypeReference) {
+					TypeReference typeRef = (TypeReference) fieldRef.receiver;
+					patternLocator.match(typeRef, nodeSet);
+				}
+			} else if (reference instanceof JavadocMessageSend) {
+				JavadocMessageSend messageSend = (JavadocMessageSend) reference;
+				patternLocator.match(messageSend, nodeSet);
+				if (messageSend.receiver instanceof TypeReference) {
+					TypeReference typeRef = (TypeReference) messageSend.receiver;
+					patternLocator.match(typeRef, nodeSet);
+				}
+			} else if (reference instanceof JavadocAllocationExpression) {
+				JavadocAllocationExpression constructor = (JavadocAllocationExpression) reference;
+				patternLocator.match(constructor, nodeSet);
+				if (constructor.type != null) {
+					patternLocator.match(constructor.type, nodeSet);
+				}
+			}
+		}
+	}
 }
 protected void classInstanceCreation(boolean alwaysQualified) {
 	super.classInstanceCreation(alwaysQualified);
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(this.expressionStack[this.expressionPtr]);
-	}
+	this.patternLocator.match(this.expressionStack[this.expressionPtr], this.nodeSet);
 }
 protected void consumeAssignment() {
 	super.consumeAssignment();
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(this.expressionStack[this.expressionPtr]);
-	}
+	this.patternLocator.match(this.expressionStack[this.expressionPtr], this.nodeSet);
 }
-	
 protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
 	super.consumeExplicitConstructorInvocation(flag, recFlag);
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(this.astStack[this.astPtr]);
-	}
+	this.patternLocator.match(this.astStack[this.astPtr], this.nodeSet);
 }
 protected void consumeFieldAccess(boolean isSuperAccess) {
 	super.consumeFieldAccess(isSuperAccess);
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(this.expressionStack[this.expressionPtr]);
-	}
+
+	// this is always a Reference
+	this.patternLocator.match((Reference) this.expressionStack[this.expressionPtr], this.nodeSet);
+}
+protected void consumeLocalVariableDeclaration() {
+	super.consumeLocalVariableDeclaration();
+
+	// this is always a LocalDeclaration
+	this.patternLocator.match((LocalDeclaration) this.astStack[this.astPtr], this.nodeSet);
 }
 protected void consumeMethodInvocationName() {
 	super.consumeMethodInvocationName();
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(this.expressionStack[this.expressionPtr]);
-	}
+
+	// this is always a MessageSend
+	this.patternLocator.match((MessageSend) this.expressionStack[this.expressionPtr], this.nodeSet);
 }
 protected void consumeMethodInvocationPrimary() {
-	super.consumeMethodInvocationPrimary();
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(this.expressionStack[this.expressionPtr]);
-	}
+	super.consumeMethodInvocationPrimary(); 
+
+	// this is always a MessageSend
+	this.patternLocator.match((MessageSend) this.expressionStack[this.expressionPtr], this.nodeSet);
 }
 protected void consumeMethodInvocationSuper() {
 	super.consumeMethodInvocationSuper();
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(this.expressionStack[this.expressionPtr]);
-	}
+
+	// this is always a MessageSend
+	this.patternLocator.match((MessageSend) this.expressionStack[this.expressionPtr], this.nodeSet);
 }
 protected void consumePrimaryNoNewArray() {
 	// pop parenthesis positions (and don't update expression positions
@@ -151,126 +191,76 @@
 	intPtr--;
 	intPtr--;
 }
-protected void consumeSingleTypeImportDeclarationName() {
-	super.consumeSingleTypeImportDeclarationName();
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(this.astStack[this.astPtr]);
-	}
-}
-protected void consumeTypeImportOnDemandDeclarationName() {
-	super.consumeTypeImportOnDemandDeclarationName();
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(this.astStack[this.astPtr]);
-	}
-}
 protected void consumeUnaryExpression(int op, boolean post) {
 	super.consumeUnaryExpression(op, post);
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(this.expressionStack[this.expressionPtr]);
-	}
+	this.patternLocator.match(this.expressionStack[this.expressionPtr], this.nodeSet);
 }
 protected TypeReference copyDims(TypeReference typeRef, int dim) {
 	TypeReference result = super.copyDims(typeRef, dim);
-	if (this.matchSet != null) {
-		 if (this.matchSet.removePossibleMatch(typeRef) != null) {
-			this.matchSet.addPossibleMatch(result);
-		 } else if (this.matchSet.removeTrustedMatch(typeRef) != null) {
-			this.matchSet.addTrustedMatch(result);
-		 }
-	}
+	 if (this.nodeSet.removePossibleMatch(typeRef) != null)
+		this.nodeSet.addPossibleMatch(result);
+	 else if (this.nodeSet.removeTrustedMatch(typeRef) != null)
+		this.nodeSet.addTrustedMatch(result, true);
 	return result;
 }
-protected CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, MatchLocator locator, IFile file, CompilationUnit compilationUnit) {
-	MatchSet originalMatchSet = this.matchSet;
-	CompilationUnitDeclaration unit = null;
-	try {
-		this.matchSet = new MatchSet(locator);
-		CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
-		unit = this.dietParse(sourceUnit, compilationResult);
-	} finally {
-		if (originalMatchSet == null) {
-			if (!this.matchSet.isEmpty() 
-					&& unit != null && file != null) {
-				// potential matches were found while initializing the search pattern
-				// from the lookup environment: add the corresponding openable in the list
-				locator.addMatchingOpenable(file, compilationUnit, unit, this.matchSet);
-			}
-			this.matchSet = null;
-		} else {
-			this.matchSet = originalMatchSet;
-		}
-	}
-	return unit;
-}
 protected TypeReference getTypeReference(int dim) {
 	TypeReference typeRef = super.getTypeReference(dim);
-	if (this.matchSet != null) { 
-		this.matchSet.checkMatching(typeRef); // NB: Don't check container since type reference can happen anywhere
-	}
+	this.patternLocator.match(typeRef, this.nodeSet); // NB: Don't check container since type reference can happen anywhere
 	return typeRef;
 }
 protected NameReference getUnspecifiedReference() {
 	NameReference nameRef = super.getUnspecifiedReference();
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(nameRef); // NB: Don't check container since unspecified reference can happen anywhere
-	}
+	this.patternLocator.match(nameRef, this.nodeSet); // NB: Don't check container since unspecified reference can happen anywhere
 	return nameRef;
 }
 protected NameReference getUnspecifiedReferenceOptimized() {
 	NameReference nameRef = super.getUnspecifiedReferenceOptimized();
-	if (this.matchSet != null) {
-		this.matchSet.checkMatching(nameRef); // NB: Don't check container since unspecified reference can happen anywhere
-	}
+	this.patternLocator.match(nameRef, this.nodeSet); // NB: Don't check container since unspecified reference can happen anywhere
 	return nameRef;
 }
 /**
  * Parses the method bodies in the given compilation unit
+ * @param unit CompilationUnitDeclaration
  */
 public void parseBodies(CompilationUnitDeclaration unit) {
 	TypeDeclaration[] types = unit.types;
-	if (types != null) {
-		for (int i = 0; i < types.length; i++) {
-			TypeDeclaration type = types[i];
-			if ((this.matchSet.matchContainer & SearchPattern.COMPILATION_UNIT) != 0 // type declaration in compilation unit
-				|| (this.matchSet.matchContainer & SearchPattern.CLASS) != 0			// or in another type
-				|| (this.matchSet.matchContainer & SearchPattern.METHOD) != 0) {		// or in a local class
-					
-				this.matchSet.checkMatching(type);
-			}
-			this.parseBodies(type, unit);
-		}
+	if (types == null) return;
+
+	for (int i = 0; i < types.length; i++) {
+		TypeDeclaration type = types[i];
+		this.patternLocator.match(type, this.nodeSet);
+		this.parseBodies(type, unit);
 	}
 }
 /**
  * Parses the member bodies in the given type.
+ * @param type TypeDeclaration
+ * @param unit CompilationUnitDeclaration
  */
-private void parseBodies(TypeDeclaration type, CompilationUnitDeclaration unit) {
-	// fields
+protected void parseBodies(TypeDeclaration type, CompilationUnitDeclaration unit) {
 	FieldDeclaration[] fields = type.fields;
 	if (fields != null) {
 		for (int i = 0; i < fields.length; i++) {
 			FieldDeclaration field = fields[i];
-			if (field instanceof Initializer) { // initializer block
-				this.parse((Initializer)field, type, unit);		
-			}
+			if (field instanceof Initializer)
+				this.parse((Initializer) field, type, unit);
 			field.traverse(localDeclarationVisitor, null);
 		}
 	}
-	
-	// methods
+
 	AbstractMethodDeclaration[] methods = type.methods;
 	if (methods != null) {
 		for (int i = 0; i < methods.length; i++) {
 			AbstractMethodDeclaration method = methods[i];
 			if (method.sourceStart >= type.bodyStart) { // if not synthetic
 				if (method instanceof MethodDeclaration) {
-					MethodDeclaration methodDeclaration = (MethodDeclaration)method;
+					MethodDeclaration methodDeclaration = (MethodDeclaration) method;
 					this.parse(methodDeclaration, unit);
-					methodDeclaration.traverse(localDeclarationVisitor, (ClassScope)null);
+					methodDeclaration.traverse(localDeclarationVisitor, (ClassScope) null);
 				} else if (method instanceof ConstructorDeclaration) {
-					ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration)method;
+					ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) method;
 					this.parse(constructorDeclaration, unit);
-					constructorDeclaration.traverse(localDeclarationVisitor, (ClassScope)null);
+					constructorDeclaration.traverse(localDeclarationVisitor, (ClassScope) null);
 				}
 			} else if (method.isDefaultConstructor()) {
 				method.parseStatements(this, unit);
@@ -278,14 +268,28 @@
 		}
 	}
 
-	// member types
-	MemberTypeDeclaration[] memberTypes = type.memberTypes;
+	TypeDeclaration[] memberTypes = type.memberTypes;
 	if (memberTypes != null) {
 		for (int i = 0; i < memberTypes.length; i++) {
-			MemberTypeDeclaration memberType = memberTypes[i];
+			TypeDeclaration memberType = memberTypes[i];
 			this.parseBodies(memberType, unit);
-			memberType.traverse(localDeclarationVisitor, (ClassScope)null);
+			memberType.traverse(localDeclarationVisitor, (ClassScope) null);
 		}
 	}
 }
 }
+
+class ImportMatchLocatorParser extends MatchLocatorParser {
+
+protected ImportMatchLocatorParser(ProblemReporter problemReporter, MatchLocator locator) {
+	super(problemReporter, locator);
+}
+protected void consumeSingleTypeImportDeclarationName() {
+	super.consumeSingleTypeImportDeclarationName();
+	this.patternLocator.match(this.astStack[this.astPtr], this.nodeSet);
+}
+protected void consumeTypeImportOnDemandDeclarationName() {
+	super.consumeTypeImportOnDemandDeclarationName();
+	this.patternLocator.match(this.astStack[this.astPtr], this.nodeSet);
+}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchSet.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchSet.java
deleted file mode 100644
index f443643..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchSet.java
+++ /dev/null
@@ -1,568 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
-import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.LocalTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MemberTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
-import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfLong;
-import org.eclipse.jdt.internal.core.Util;
-
-/**
- * A set of matches and potential matches.
- */
-// TODO: (jerome) Remove when switching to MatchLocator2
-public class MatchSet {
-	
-	MatchLocator locator;
-	int matchContainer;
-	boolean cuHasBeenResolved = false;
-
-	/**
-	 * Set of matching ast nodes that don't need to be resolved.
-	 */
-	Map matchingNodes = new HashMap(5);
-	HashtableOfLong matchingNodesKeys = new HashtableOfLong(5);
-
-	/**
-	 * Set of potential matching ast nodes. They need to be resolved
-	 * to determine if they really match the search pattern.
-	 */
-	Map potentialMatchingNodes = new HashMap(5);
-	HashtableOfLong potentialMatchingNodesKeys = new HashtableOfLong(5);
-	
-/**
- * An ast visitor that visits local type declarations.
- */
-public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
-	IJavaElement enclosingElement;
-	public boolean visit(
-			AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
-			BlockScope scope) {
-		try {
-			reportMatching(anonymousTypeDeclaration, enclosingElement);
-		} catch (CoreException e) {
-			throw new WrappedCoreException(e);
-		}
-		return false; // don't visit members as this was done during reportMatching(...)
-	}
-	public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
-		try {
-			// check type declaration
-			Integer level;
-			if ((level = (Integer)matchingNodes.remove(typeDeclaration)) != null) {
-				locator.reportTypeDeclaration(
-					typeDeclaration, 
-					enclosingElement, 
-					level.intValue() == SearchPattern.ACCURATE_MATCH ?
-						IJavaSearchResultCollector.EXACT_MATCH :
-						IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-			
-			// check inside type declaration
-			reportMatching(typeDeclaration, enclosingElement);
-			
-			return false; // don't visit members as this was done during reportMatching(...)
-		} catch (CoreException e) {
-			throw new WrappedCoreException(e);
-		}
-	}
-	public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
-		try {
-			reportMatching(typeDeclaration, enclosingElement);
-			return false; // don't visit members as this was done during reportMatching(...)
-		} catch (CoreException e) {
-			throw new WrappedCoreException(e);
-		}
-	}
-	
-}	
-
-public class WrappedCoreException extends RuntimeException {
-	public CoreException coreException;
-	public WrappedCoreException(CoreException coreException) {
-		this.coreException = coreException;
-	}
-}
-
-public MatchSet(MatchLocator locator) {
-	this.locator = locator;
-	this.matchContainer = locator.pattern.matchContainer();
-}
-public void addPossibleMatch(AstNode node) {
-
-	// remove existing node at same position from set
-	// (case of recovery that created the same node several time
-	// see http://bugs.eclipse.org/bugs/show_bug.cgi?id=29366)
-	long key = (((long) node.sourceStart) << 32) + node.sourceEnd;
-	AstNode existing = (AstNode)this.potentialMatchingNodesKeys.get(key);
-	if (existing != null && existing.getClass().equals(node.getClass())) {
-		this.potentialMatchingNodes.remove(existing);
-	}
-
-	// add node to set
-	this.potentialMatchingNodes.put(node, new Integer(SearchPattern.POSSIBLE_MATCH));
-	this.potentialMatchingNodesKeys.put(key, node);
-}
-public void addTrustedMatch(AstNode node) {
-	
-	// remove existing node at same position from set
-	// (case of recovery that created the same node several time
-	// see http://bugs.eclipse.org/bugs/show_bug.cgi?id=29366)
-	long key = (((long) node.sourceStart) << 32) + node.sourceEnd;
-	AstNode existing = (AstNode)this.matchingNodesKeys.get(key);
-	if (existing != null && existing.getClass().equals(node.getClass())) {
-		this.matchingNodes.remove(existing);
-	}
-	
-	// add node to set
-	this.matchingNodes.put(node, new Integer(SearchPattern.ACCURATE_MATCH));
-	this.matchingNodesKeys.put(key, node);
-}
-public void checkMatching(AstNode node) {
-	this.locator.pattern.matchCheck(node, this);
-}
-public boolean isEmpty() {
-	return 
-		this.potentialMatchingNodes.size() == 0 
-		&& this.matchingNodes.size() == 0;
-}
-/**
- * Returns the matching nodes that are in the given range.
- */
-private AstNode[] matchingNodes(int start, int end) {
-	return this.nodesInRange(start, end, this.matchingNodes);
-}
-public boolean needsResolve() {
-	return this.potentialMatchingNodes.size() > 0;
-}
-/**
- * Returns the matching nodes that are in the given range in the source order.
- */
-private AstNode[] nodesInRange(int start, int end, Map set) {
-	// collect nodes in the given range
-	ArrayList nodes = new ArrayList();
-	for (Iterator keys = set.keySet().iterator(); keys.hasNext();) {
-		AstNode node = (AstNode)keys.next();
-		if (start <= node.sourceStart && node.sourceEnd <= end) {
-			nodes.add(node);
-		}
-	}
-	AstNode[] result = new AstNode[nodes.size()];
-	nodes.toArray(result);
-
-	// sort nodes by source starts
-	Util.Comparer comparer = new Util.Comparer() {
-		public int compare(Object o1, Object o2) {
-			AstNode node1 = (AstNode) o1;
-			AstNode node2 = (AstNode) o2;
-			return node1.sourceStart - node2.sourceStart;
-		}
-	};
-	Util.sort(result, comparer);
-		
-	return result;
-}
-/**
- * Returns the potential matching nodes that are in the given range.
- */
-private AstNode[] potentialMatchingNodes(int start, int end) {
-	return this.nodesInRange(start, end, this.potentialMatchingNodes);
-}
-public Integer removePossibleMatch(AstNode node) {
-	long key = (((long) node.sourceStart) << 32) + node.sourceEnd;
-	this.potentialMatchingNodesKeys.put(key, null);
-	return (Integer)this.potentialMatchingNodes.remove(node);
-}
-public Integer removeTrustedMatch(AstNode node) {
-	long key = (((long) node.sourceStart) << 32) + node.sourceEnd;
-	this.matchingNodesKeys.put(key, null);
-	return (Integer)this.matchingNodes.remove(node);
-}
-/**
- * Visit the given method declaration and report the nodes that match exactly the
- * search pattern (ie. the ones in the matching nodes set)
- * Note that the method declaration has already been checked.
- */
-private void reportMatching(AbstractMethodDeclaration method, IJavaElement parent, boolean typeInHierarchy) throws CoreException {
-	// declaration in this method
-	// (NB: declarations must be searched first (see bug 20631 Declaration of local binary type not found)
-	if ((method.bits & AstNode.HasLocalTypeMASK) != 0) {
-		LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor();
-		localDeclarationVisitor.enclosingElement = 
-			(parent instanceof IType) ?
-				this.locator.createMethodHandle(method, (IType)parent) :
-				parent;
-		try {
-			method.traverse(localDeclarationVisitor, (ClassScope)null);
-		} catch (WrappedCoreException e) {
-			throw e.coreException;
-		}
-	}
-	
-	// references in this method
-	if (typeInHierarchy) {
-		AstNode[] nodes = this.matchingNodes(method.declarationSourceStart, method.declarationSourceEnd);
-		for (int i = 0; i < nodes.length; i++) {
-			AstNode node = nodes[i];
-			Integer level = (Integer)this.matchingNodes.get(node);
-			if ((this.matchContainer & SearchPattern.METHOD) != 0) {
-				this.locator.reportReference(
-					node, 
-					method, 
-					parent, 
-					level.intValue() == SearchPattern.ACCURATE_MATCH ?
-						IJavaSearchResultCollector.EXACT_MATCH :
-						IJavaSearchResultCollector.POTENTIAL_MATCH);
-				this.matchingNodes.remove(node);
-			}
-		}
-	}
-	if (this.potentialMatchingNodes(method.declarationSourceStart, method.declarationSourceEnd).length == 0) {
-		// no need to resolve the statements in the method
-		method.statements = null;
-	}
-}
-/**
- * Visit the given parse tree and report the nodes that match exactly the
- * search pattern.
- */
-public void reportMatching(CompilationUnitDeclaration unit) throws CoreException {
-	if (this.cuHasBeenResolved) {
-		// move the potential matching nodes that exactly match the search pattern to the matching nodes set
-		for (Iterator potentialMatches = this.potentialMatchingNodes.keySet().iterator(); potentialMatches.hasNext();) {
-			AstNode node = (AstNode) potentialMatches.next();
-			int level;
-			if (node instanceof ImportReference) {
-				// special case for import refs: they don't know their binding
-				
-				// import ref cannot be in the hirarchy of a type
-				if (this.locator.hierarchyResolver != null) continue;
-				
-				ImportReference importRef = (ImportReference)node;
-				Binding binding;
-				if (importRef.onDemand) {
-					binding = unit.scope.getTypeOrPackage(CharOperation.subarray(importRef.tokens, 0, importRef.tokens.length));
-				} else {
-					binding = unit.scope.getTypeOrPackage(importRef.tokens);
-				}
-				level = this.locator.pattern.matchLevel(binding);
-
-				if (level == SearchPattern.ACCURATE_MATCH || level == SearchPattern.INACCURATE_MATCH) {
-					// create defining import handle
-					IJavaElement importHandle = this.locator.createImportHandle(importRef);
-					this.locator.pattern.matchReportImportRef(
-						importRef, 
-						binding, 
-						importHandle, 
-						level == SearchPattern.ACCURATE_MATCH ?
-								IJavaSearchResultCollector.EXACT_MATCH :
-								IJavaSearchResultCollector.POTENTIAL_MATCH,
-						this.locator);
-				}
-			} else {
-				level = this.locator.pattern.matchLevel(node, true);
-				if (level == SearchPattern.ACCURATE_MATCH || level == SearchPattern.INACCURATE_MATCH) {
-					this.matchingNodes.put(node, new Integer(level));
-				}
-			}
-		}
-		this.potentialMatchingNodes = new HashMap();
-	}
-	
-	// package declaration
-	ImportReference pkg = unit.currentPackage;
-	Integer level;
-	if (pkg != null && (level = (Integer)this.matchingNodes.remove(pkg)) != null) {
-		if ((this.matchContainer & SearchPattern.COMPILATION_UNIT) != 0) {
-			this.locator.reportPackageDeclaration(pkg);
-		}
-	}
-
-	// import declarations
-	if (!this.cuHasBeenResolved) {
-		ImportReference[] imports = unit.imports;
-		if (imports != null) {
-			for (int i = 0; i < imports.length; i++) {
-				ImportReference importRef = imports[i];
-				if ((level = (Integer)this.matchingNodes.remove(importRef)) != null) {
-					if ((this.matchContainer & SearchPattern.COMPILATION_UNIT) != 0) {
-						this.locator.reportImport(
-							importRef, 
-							level.intValue() == SearchPattern.ACCURATE_MATCH ?
-								IJavaSearchResultCollector.EXACT_MATCH :
-								IJavaSearchResultCollector.POTENTIAL_MATCH);
-					}
-				}
-			}
-		}
-	} // else import declarations have already been processed above
-
-	// types
-	TypeDeclaration[] types = unit.types;
-	if (types != null) {
-		for (int i = 0; i < types.length; i++) {
-			TypeDeclaration type = types[i];
-			if ((level = (Integer)this.matchingNodes.remove(type)) != null) {
-				if ((this.matchContainer & SearchPattern.COMPILATION_UNIT) != 0) {
-					this.locator.reportTypeDeclaration(
-						type, 
-						null, 
-						level.intValue() == SearchPattern.ACCURATE_MATCH ?
-							IJavaSearchResultCollector.EXACT_MATCH :
-							IJavaSearchResultCollector.POTENTIAL_MATCH);
-				}
-			}
-			this.reportMatching(type, null);
-		}
-	}
-}
-/**
- * Visit the given field declaration and report the nodes that match exactly the
- * search pattern (ie. the ones in the matching nodes set)
- * Note that the field declaration has already been checked.
- */
-private void reportMatching(FieldDeclaration field, IJavaElement parent, TypeDeclaration type, boolean typeInHierarchy) throws CoreException {
-	if (typeInHierarchy) {
-		AstNode[] nodes = this.matchingNodes(field.declarationSourceStart, field.declarationSourceEnd);
-		for (int i = 0; i < nodes.length; i++) {
-			AstNode node = nodes[i];
-			Integer level = (Integer)this.matchingNodes.get(node);
-			if ((this.matchContainer & SearchPattern.FIELD) != 0) {
-				this.locator.reportReference(
-					node, 
-					type, 
-					field, 
-					parent, 
-					level.intValue() == SearchPattern.ACCURATE_MATCH ?
-						IJavaSearchResultCollector.EXACT_MATCH :
-						IJavaSearchResultCollector.POTENTIAL_MATCH);
-				this.matchingNodes.remove(node);
-			}
-		}
-	}
-	if ((field.bits & AstNode.HasLocalTypeMASK) != 0) {
-		LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor();
-		localDeclarationVisitor.enclosingElement = 
-			(parent instanceof IType) ?
-				(field.isField() ?
-					(IJavaElement)this.locator.createFieldHandle(field, (IType)parent) :
-					(IJavaElement)this.locator.createInitializerHandle(type, field, (IType)parent)) :
-				parent;
-		try {
-			field.traverse(localDeclarationVisitor, (MethodScope)null);
-		} catch (WrappedCoreException e) {
-			throw e.coreException;
-		}
-	}
-}
-/**
- * Visit the given type declaration and report the nodes that match exactly the
- * search pattern (ie. the ones in the matching nodes set)
- * Note that the type declaration has already been checked.
- */
-public void reportMatching(TypeDeclaration type, IJavaElement parent) throws CoreException {
-	
-	// filter out element not in hierarchy scope
-	boolean typeInHierarchy = 
-		this.locator.hierarchyResolver == null 
-			|| type.binding == null
-			|| this.locator.hierarchyResolver.subOrSuperOfFocus(type.binding);
-	
-	// create type handle
-	IJavaElement enclosingElement;
-	if (parent == null) {
-		enclosingElement = this.locator.createTypeHandle(type.name);
-	} else if (parent instanceof IType) {
-		enclosingElement = this.locator.createTypeHandle((IType)parent, type.name);
-		if (enclosingElement == null) return;
-	} else {
-		enclosingElement = parent;
-	}
-	Integer level;
-	
-	// fields
-	FieldDeclaration[] fields = type.fields;
-	if (fields != null) {
-		for (int i = 0; i < fields.length; i++) {
-			FieldDeclaration field = fields[i];
-			if ((level = (Integer)this.matchingNodes.remove(field)) != null
-				&& typeInHierarchy
-				&& (this.matchContainer & SearchPattern.CLASS) != 0) {
-					this.locator.reportFieldDeclaration(
-						field, 
-						enclosingElement, 
-						level.intValue() == SearchPattern.ACCURATE_MATCH ?
-							IJavaSearchResultCollector.EXACT_MATCH :
-							IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-			this.reportMatching(field, enclosingElement, type, typeInHierarchy);
-		}
-	}
-
-	// methods
-	AbstractMethodDeclaration[] methods = type.methods;
-	if (methods != null) {
-		for (int i = 0; i < methods.length; i++) {
-			AbstractMethodDeclaration method = methods[i];
-			if ((level = (Integer)this.matchingNodes.remove(method)) != null
-				&& typeInHierarchy
-				&& (this.matchContainer & SearchPattern.CLASS) != 0) {
-					this.locator.reportMethodDeclaration(
-						method, 
-						enclosingElement, 
-						level.intValue() == SearchPattern.ACCURATE_MATCH ?
-							IJavaSearchResultCollector.EXACT_MATCH :
-							IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-			this.reportMatching(method, enclosingElement, typeInHierarchy);
-		}
-	}
-
-	// member types
-	MemberTypeDeclaration[] memberTypes = type.memberTypes;
-	if (memberTypes != null) {
-		for (int i = 0; i < memberTypes.length; i++) {
-			MemberTypeDeclaration memberType = memberTypes[i];
-			if ((level = (Integer)this.matchingNodes.remove(memberType)) != null
-				&& typeInHierarchy
-				&& (this.matchContainer & SearchPattern.CLASS) != 0) {
-					this.locator.reportTypeDeclaration(
-						memberType, 
-						enclosingElement, 
-						level.intValue() == SearchPattern.ACCURATE_MATCH ?
-							IJavaSearchResultCollector.EXACT_MATCH :
-							IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-			this.reportMatching(memberType, enclosingElement);
-		}
-	}
-
-	// super types
-	if (type instanceof AnonymousLocalTypeDeclaration) {
-		TypeReference superType = ((AnonymousLocalTypeDeclaration)type).allocation.type;
-		if (superType != null && (level = (Integer)this.matchingNodes.remove(superType)) != null) {
-			if ((this.matchContainer & SearchPattern.CLASS) != 0) {
-				this.locator.reportSuperTypeReference(
-					superType, 
-					enclosingElement, 
-					level.intValue() == SearchPattern.ACCURATE_MATCH ?
-						IJavaSearchResultCollector.EXACT_MATCH :
-						IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-		}
-	} else {
-		TypeReference superClass = type.superclass;
-		if (superClass != null && (level = (Integer)this.matchingNodes.remove(superClass)) != null) {
-			if ((this.matchContainer & SearchPattern.CLASS) != 0) {
-				this.locator.reportSuperTypeReference(
-					superClass, 
-					enclosingElement, 
-					level.intValue() == SearchPattern.ACCURATE_MATCH ?
-						IJavaSearchResultCollector.EXACT_MATCH :
-						IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-		}
-		TypeReference[] superInterfaces = type.superInterfaces;
-		if (superInterfaces != null) {
-			for (int i = 0; i < superInterfaces.length; i++) {
-				TypeReference superInterface = superInterfaces[i];
-				if ((level = (Integer)this.matchingNodes.get(superInterface)) != null) {
-					if ((this.matchContainer & SearchPattern.CLASS) != 0) {
-						this.locator.reportSuperTypeReference(
-							superInterface, 
-							enclosingElement, 
-							level.intValue() == SearchPattern.ACCURATE_MATCH ?
-								IJavaSearchResultCollector.EXACT_MATCH :
-								IJavaSearchResultCollector.POTENTIAL_MATCH);
-					}
-				}
-			}
-		}
-	}
-}
-public String toString() {
-	StringBuffer result = new StringBuffer();
-	result.append("Exact matches:"); //$NON-NLS-1$
-	for (Iterator iter = this.matchingNodes.keySet().iterator(); iter.hasNext();) {
-		result.append("\n"); //$NON-NLS-1$
-		AstNode node = (AstNode)iter.next();
-		Object value = this.matchingNodes.get(node);
-		if (value instanceof Integer) {
-			result.append('\t');
-			int accuracy = ((Integer)value).intValue();
-			switch (accuracy) {
-				case SearchPattern.IMPOSSIBLE_MATCH:
-					result.append("IMPOSSIBLE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.POSSIBLE_MATCH:
-					result.append("POSSIBLE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.INACCURATE_MATCH:
-					result.append("INACCURATE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.ACCURATE_MATCH:
-					result.append("ACCURATE_MATCH: "); //$NON-NLS-1$
-					break;
-			}
-		} 
-		result.append(node.toString(0));
-	}
-	result.append("\nPotential matches:"); //$NON-NLS-1$
-	for (Iterator iter = this.potentialMatchingNodes.keySet().iterator(); iter.hasNext();) {
-		result.append("\n"); //$NON-NLS-1$
-		AstNode node = (AstNode)iter.next();
-		Object value = this.potentialMatchingNodes.get(node);
-		if (value instanceof Integer) {
-			result.append("\t"); //$NON-NLS-1$
-			int accuracy = ((Integer)value).intValue();
-			switch (accuracy) {
-				case SearchPattern.IMPOSSIBLE_MATCH:
-					result.append("IMPOSSIBLE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.POSSIBLE_MATCH:
-					result.append("POSSIBLE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.INACCURATE_MATCH:
-					result.append("INACCURATE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.ACCURATE_MATCH:
-					result.append("ACCURATE_MATCH: "); //$NON-NLS-1$
-					break;
-			}
-		}
-		result.append(node.toString(0));
-	}
-	return result.toString();
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java
index 793b935..9d391ae 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingNodeSet.java
@@ -11,554 +11,148 @@
 package org.eclipse.jdt.internal.core.search.matching;
 
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
 
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
-import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
-import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.LocalTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MemberTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
-import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.jdt.internal.compiler.ast.*;
 import org.eclipse.jdt.internal.compiler.util.HashtableOfLong;
-import org.eclipse.jdt.internal.core.Util;
+import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+import org.eclipse.jdt.internal.core.util.SimpleSet;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
- * A set of matches and potential matches.
+ * A set of matches and possible matches, which need to be resolved.
  */
-public class MatchingNodeSet extends MatchSet { // TODO: (jerome) remove extends
-	
-	MatchLocator2 locator;
-	int matchContainer;
-	boolean cuHasBeenResolved = false;
+public class MatchingNodeSet {
 
-	/**
-	 * Set of matching ast nodes that don't need to be resolved.
-	 */
-	Map matchingNodes = new HashMap(5);
-	HashtableOfLong matchingNodesKeys = new HashtableOfLong(5);
-
-	/**
-	 * Set of potential matching ast nodes. They need to be resolved
-	 * to determine if they really match the search pattern.
-	 */
-	Map potentialMatchingNodes = new HashMap(5);
-	HashtableOfLong potentialMatchingNodesKeys = new HashtableOfLong(5);
-	
 /**
- * An ast visitor that visits local type declarations.
+ * Map of matching ast nodes that don't need to be resolved to their accuracy level.
+ * Each node is removed as it is reported.
  */
-public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
-	IJavaElement enclosingElement;
-	public boolean visit(
-			AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
-			BlockScope scope) {
-		try {
-			reportMatching(anonymousTypeDeclaration, enclosingElement);
-		} catch (CoreException e) {
-			throw new WrappedCoreException(e);
-		}
-		return false; // don't visit members as this was done during reportMatching(...)
-	}
-	public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
-		try {
-			// check type declaration
-			Integer level;
-			if ((level = (Integer)matchingNodes.remove(typeDeclaration)) != null) {
-				locator.reportTypeDeclaration(
-					typeDeclaration, 
-					enclosingElement, 
-					level.intValue() == SearchPattern.ACCURATE_MATCH ?
-						IJavaSearchResultCollector.EXACT_MATCH :
-						IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-			
-			// check inside type declaration
-			reportMatching(typeDeclaration, enclosingElement);
-			
-			return false; // don't visit members as this was done during reportMatching(...)
-		} catch (CoreException e) {
-			throw new WrappedCoreException(e);
-		}
-	}
-	public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
-		try {
-			reportMatching(typeDeclaration, enclosingElement);
-			return false; // don't visit members as this was done during reportMatching(...)
-		} catch (CoreException e) {
-			throw new WrappedCoreException(e);
-		}
-	}
-	
-}	
+SimpleLookupTable matchingNodes = new SimpleLookupTable(3);
+private HashtableOfLong matchingNodesKeys = new HashtableOfLong(3);
+static Integer EXACT_MATCH = new Integer(IJavaSearchResultCollector.EXACT_MATCH);
+static Integer POTENTIAL_MATCH = new Integer(IJavaSearchResultCollector.POTENTIAL_MATCH);
 
-public class WrappedCoreException extends RuntimeException {
-	public CoreException coreException;
-	public WrappedCoreException(CoreException coreException) {
-		this.coreException = coreException;
+/**
+ * Set of possible matching ast nodes. They need to be resolved
+ * to determine if they really match the search pattern.
+ */
+SimpleSet possibleMatchingNodesSet = new SimpleSet(7);
+private HashtableOfLong possibleMatchingNodesKeys = new HashtableOfLong(7);
+
+public int addMatch(ASTNode node, int matchLevel) {
+	switch (matchLevel) {
+		case PatternLocator.INACCURATE_MATCH:
+			addTrustedMatch(node, false);
+			break;
+		case PatternLocator.POSSIBLE_MATCH:
+			addPossibleMatch(node);
+			break;
+		case PatternLocator.ACCURATE_MATCH:
+			addTrustedMatch(node, true);
 	}
+	return matchLevel;
 }
-
-public MatchingNodeSet(MatchLocator2 locator) {
-	super(locator);
-	this.locator = locator;
-	this.matchContainer = locator.pattern.matchContainer();
-}
-public void addPossibleMatch(AstNode node) {
-
+public void addPossibleMatch(ASTNode node) {
 	// remove existing node at same position from set
 	// (case of recovery that created the same node several time
 	// see http://bugs.eclipse.org/bugs/show_bug.cgi?id=29366)
 	long key = (((long) node.sourceStart) << 32) + node.sourceEnd;
-	AstNode existing = (AstNode)this.potentialMatchingNodesKeys.get(key);
-	if (existing != null && existing.getClass().equals(node.getClass())) {
-		this.potentialMatchingNodes.remove(existing);
-	}
+	ASTNode existing = (ASTNode) this.possibleMatchingNodesKeys.get(key);
+	if (existing != null && existing.getClass().equals(node.getClass()))
+		this.possibleMatchingNodesSet.remove(existing);
 
 	// add node to set
-	this.potentialMatchingNodes.put(node, new Integer(SearchPattern.POSSIBLE_MATCH));
-	this.potentialMatchingNodesKeys.put(key, node);
+	this.possibleMatchingNodesSet.add(node);
+	this.possibleMatchingNodesKeys.put(key, node);
 }
-public void addTrustedMatch(AstNode node) {
-	
+public void addTrustedMatch(ASTNode node, boolean isExact) {
 	// remove existing node at same position from set
 	// (case of recovery that created the same node several time
 	// see http://bugs.eclipse.org/bugs/show_bug.cgi?id=29366)
 	long key = (((long) node.sourceStart) << 32) + node.sourceEnd;
-	AstNode existing = (AstNode)this.matchingNodesKeys.get(key);
-	if (existing != null && existing.getClass().equals(node.getClass())) {
-		this.matchingNodes.remove(existing);
-	}
+	ASTNode existing = (ASTNode) this.matchingNodesKeys.get(key);
+	if (existing != null && existing.getClass().equals(node.getClass()))
+		this.matchingNodes.removeKey(existing);
 	
-	// add node to set
-	this.matchingNodes.put(node, new Integer(SearchPattern.ACCURATE_MATCH));
+	// map node to its accuracy level
+	this.matchingNodes.put(node, isExact ? EXACT_MATCH : POTENTIAL_MATCH);
 	this.matchingNodesKeys.put(key, node);
 }
-public void checkMatching(AstNode node) {
-	this.locator.pattern.matchCheck(node, this);
-}
-public boolean isEmpty() {
-	return 
-		this.potentialMatchingNodes.size() == 0 
-		&& this.matchingNodes.size() == 0;
-}
-/**
- * Returns the matching nodes that are in the given range.
- */
-private AstNode[] matchingNodes(int start, int end) {
-	return this.nodesInRange(start, end, this.matchingNodes);
-}
-public boolean needsResolve() {
-	return this.potentialMatchingNodes.size() > 0;
+protected boolean hasPossibleNodes(int start, int end) {
+	Object[] nodes = this.possibleMatchingNodesSet.values;
+	for (int i = 0, l = nodes.length; i < l; i++) {
+		ASTNode node = (ASTNode) nodes[i];
+		if (node != null && start <= node.sourceStart && node.sourceEnd <= end)
+			return true;
+	}
+	return false;
 }
 /**
  * Returns the matching nodes that are in the given range in the source order.
  */
-private AstNode[] nodesInRange(int start, int end, Map set) {
-	// collect nodes in the given range
-	ArrayList nodes = new ArrayList();
-	for (Iterator keys = set.keySet().iterator(); keys.hasNext();) {
-		AstNode node = (AstNode)keys.next();
-		if (start <= node.sourceStart && node.sourceEnd <= end) {
+protected ASTNode[] matchingNodes(int start, int end) {
+	ArrayList nodes = null;
+	Object[] keyTable = this.matchingNodes.keyTable;
+	for (int i = 0, l = keyTable.length; i < l; i++) {
+		ASTNode node = (ASTNode) keyTable[i];
+		if (node != null && start <= node.sourceStart && node.sourceEnd <= end) {
+			if (nodes == null) nodes = new ArrayList();
 			nodes.add(node);
 		}
 	}
-	AstNode[] result = new AstNode[nodes.size()];
+	if (nodes == null) return null;
+
+	ASTNode[] result = new ASTNode[nodes.size()];
 	nodes.toArray(result);
 
 	// sort nodes by source starts
 	Util.Comparer comparer = new Util.Comparer() {
 		public int compare(Object o1, Object o2) {
-			AstNode node1 = (AstNode) o1;
-			AstNode node2 = (AstNode) o2;
-			return node1.sourceStart - node2.sourceStart;
+			return ((ASTNode) o1).sourceStart - ((ASTNode) o2).sourceStart;
 		}
 	};
 	Util.sort(result, comparer);
-		
 	return result;
 }
-/**
- * Returns the potential matching nodes that are in the given range.
- */
-private AstNode[] potentialMatchingNodes(int start, int end) {
-	return this.nodesInRange(start, end, this.potentialMatchingNodes);
-}
-public Integer removePossibleMatch(AstNode node) {
+public Object removePossibleMatch(ASTNode node) {
 	long key = (((long) node.sourceStart) << 32) + node.sourceEnd;
-	this.potentialMatchingNodesKeys.put(key, null);
-	return (Integer)this.potentialMatchingNodes.remove(node);
+	ASTNode existing = (ASTNode) this.possibleMatchingNodesKeys.get(key);
+	if (existing == null) return null;
+
+	this.possibleMatchingNodesKeys.put(key, null);
+	return this.possibleMatchingNodesSet.remove(node);
 }
-public Integer removeTrustedMatch(AstNode node) {
+public Object removeTrustedMatch(ASTNode node) {
 	long key = (((long) node.sourceStart) << 32) + node.sourceEnd;
+	ASTNode existing = (ASTNode) this.matchingNodesKeys.get(key);
+	if (existing == null) return null;
+
 	this.matchingNodesKeys.put(key, null);
-	return (Integer)this.matchingNodes.remove(node);
-}
-/**
- * Visit the given method declaration and report the nodes that match exactly the
- * search pattern (ie. the ones in the matching nodes set)
- * Note that the method declaration has already been checked.
- */
-private void reportMatching(AbstractMethodDeclaration method, IJavaElement parent, boolean typeInHierarchy) throws CoreException {
-	// declaration in this method
-	// (NB: declarations must be searched first (see bug 20631 Declaration of local binary type not found)
-	if ((method.bits & AstNode.HasLocalTypeMASK) != 0) {
-		LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor();
-		localDeclarationVisitor.enclosingElement = 
-			(parent instanceof IType) ?
-				this.locator.createMethodHandle(method, (IType)parent) :
-				parent;
-		try {
-			method.traverse(localDeclarationVisitor, (ClassScope)null);
-		} catch (WrappedCoreException e) {
-			throw e.coreException;
-		}
-	}
-	
-	// references in this method
-	if (typeInHierarchy) {
-		AstNode[] nodes = this.matchingNodes(method.declarationSourceStart, method.declarationSourceEnd);
-		for (int i = 0; i < nodes.length; i++) {
-			AstNode node = nodes[i];
-			Integer level = (Integer)this.matchingNodes.get(node);
-			if ((this.matchContainer & SearchPattern.METHOD) != 0) {
-				this.locator.reportReference(
-					node, 
-					method, 
-					parent, 
-					level.intValue() == SearchPattern.ACCURATE_MATCH ?
-						IJavaSearchResultCollector.EXACT_MATCH :
-						IJavaSearchResultCollector.POTENTIAL_MATCH);
-				this.matchingNodes.remove(node);
-			}
-		}
-	}
-	if (this.potentialMatchingNodes(method.declarationSourceStart, method.declarationSourceEnd).length == 0) {
-		// no need to resolve the statements in the method
-		method.statements = null;
-	}
-}
-/**
- * Visit the given parse tree and report the nodes that match exactly the
- * search pattern.
- */
-public void reportMatching(CompilationUnitDeclaration unit) throws CoreException {
-	if (this.cuHasBeenResolved) {
-		// move the potential matching nodes that exactly match the search pattern to the matching nodes set
-		for (Iterator potentialMatches = this.potentialMatchingNodes.keySet().iterator(); potentialMatches.hasNext();) {
-			AstNode node = (AstNode) potentialMatches.next();
-			int level;
-			if (node instanceof ImportReference) {
-				// special case for import refs: they don't know their binding
-				
-				// import ref cannot be in the hirarchy of a type
-				if (this.locator.hierarchyResolver != null) continue;
-				
-				ImportReference importRef = (ImportReference)node;
-				Binding binding;
-				if (importRef.onDemand) {
-					binding = unit.scope.getTypeOrPackage(CharOperation.subarray(importRef.tokens, 0, importRef.tokens.length));
-				} else {
-					binding = unit.scope.getTypeOrPackage(importRef.tokens);
-				}
-				level = this.locator.pattern.matchLevel(binding);
-
-				if (level == SearchPattern.ACCURATE_MATCH || level == SearchPattern.INACCURATE_MATCH) {
-					// create defining import handle
-					IJavaElement importHandle = this.locator.createImportHandle(importRef);
-					this.locator.pattern.matchReportImportRef(
-						importRef, 
-						binding, 
-						importHandle, 
-						level == SearchPattern.ACCURATE_MATCH ?
-								IJavaSearchResultCollector.EXACT_MATCH :
-								IJavaSearchResultCollector.POTENTIAL_MATCH,
-						this.locator);
-				}
-			} else {
-				level = this.locator.pattern.matchLevel(node, true);
-				if (level == SearchPattern.ACCURATE_MATCH || level == SearchPattern.INACCURATE_MATCH) {
-					this.matchingNodes.put(node, new Integer(level));
-				}
-			}
-		}
-		this.potentialMatchingNodes = new HashMap();
-	}
-	
-	// package declaration
-	ImportReference pkg = unit.currentPackage;
-	Integer level;
-	if (pkg != null && (level = (Integer)this.matchingNodes.remove(pkg)) != null) {
-		if ((this.matchContainer & SearchPattern.COMPILATION_UNIT) != 0) {
-			this.locator.reportPackageDeclaration(pkg);
-		}
-	}
-
-	// import declarations
-	if (!this.cuHasBeenResolved) {
-		ImportReference[] imports = unit.imports;
-		if (imports != null) {
-			for (int i = 0; i < imports.length; i++) {
-				ImportReference importRef = imports[i];
-				if ((level = (Integer)this.matchingNodes.remove(importRef)) != null) {
-					if ((this.matchContainer & SearchPattern.COMPILATION_UNIT) != 0) {
-						this.locator.reportImport(
-							importRef, 
-							level.intValue() == SearchPattern.ACCURATE_MATCH ?
-								IJavaSearchResultCollector.EXACT_MATCH :
-								IJavaSearchResultCollector.POTENTIAL_MATCH);
-					}
-				}
-			}
-		}
-	} // else import declarations have already been processed above
-
-	// types
-	TypeDeclaration[] types = unit.types;
-	if (types != null) {
-		for (int i = 0; i < types.length; i++) {
-			TypeDeclaration type = types[i];
-			if ((level = (Integer)this.matchingNodes.remove(type)) != null) {
-				if ((this.matchContainer & SearchPattern.COMPILATION_UNIT) != 0) {
-					this.locator.reportTypeDeclaration(
-						type, 
-						null, 
-						level.intValue() == SearchPattern.ACCURATE_MATCH ?
-							IJavaSearchResultCollector.EXACT_MATCH :
-							IJavaSearchResultCollector.POTENTIAL_MATCH);
-				}
-			}
-			this.reportMatching(type, null);
-		}
-	}
-}
-/**
- * Visit the given field declaration and report the nodes that match exactly the
- * search pattern (ie. the ones in the matching nodes set)
- * Note that the field declaration has already been checked.
- */
-private void reportMatching(FieldDeclaration field, IJavaElement parent, TypeDeclaration type, boolean typeInHierarchy) throws CoreException {
-	if (typeInHierarchy) {
-		AstNode[] nodes = this.matchingNodes(field.declarationSourceStart, field.declarationSourceEnd);
-		for (int i = 0; i < nodes.length; i++) {
-			AstNode node = nodes[i];
-			Integer level = (Integer)this.matchingNodes.get(node);
-			if ((this.matchContainer & SearchPattern.FIELD) != 0) {
-				this.locator.reportReference(
-					node, 
-					type, 
-					field, 
-					parent, 
-					level.intValue() == SearchPattern.ACCURATE_MATCH ?
-						IJavaSearchResultCollector.EXACT_MATCH :
-						IJavaSearchResultCollector.POTENTIAL_MATCH);
-				this.matchingNodes.remove(node);
-			}
-		}
-	}
-	if ((field.bits & AstNode.HasLocalTypeMASK) != 0) {
-		LocalDeclarationVisitor localDeclarationVisitor = new LocalDeclarationVisitor();
-		localDeclarationVisitor.enclosingElement = 
-			(parent instanceof IType) ?
-				(field.isField() ?
-					(IJavaElement)this.locator.createFieldHandle(field, (IType)parent) :
-					(IJavaElement)this.locator.createInitializerHandle(type, field, (IType)parent)) :
-				parent;
-		try {
-			field.traverse(localDeclarationVisitor, (MethodScope)null);
-		} catch (WrappedCoreException e) {
-			throw e.coreException;
-		}
-	}
-}
-/**
- * Visit the given type declaration and report the nodes that match exactly the
- * search pattern (ie. the ones in the matching nodes set)
- * Note that the type declaration has already been checked.
- */
-public void reportMatching(TypeDeclaration type, IJavaElement parent) throws CoreException {
-	
-	// filter out element not in hierarchy scope
-	boolean typeInHierarchy = type.binding == null || this.locator.typeInHierarchy(type.binding);
-	
-	// create type handle
-	IJavaElement enclosingElement;
-	if (parent == null) {
-		enclosingElement = this.locator.createTypeHandle(type.name);
-	} else if (parent instanceof IType) {
-		enclosingElement = this.locator.createTypeHandle((IType)parent, type.name);
-		if (enclosingElement == null) return;
-	} else {
-		enclosingElement = parent;
-	}
-	Integer level;
-	
-	// fields
-	FieldDeclaration[] fields = type.fields;
-	if (fields != null) {
-		for (int i = 0; i < fields.length; i++) {
-			FieldDeclaration field = fields[i];
-			if ((level = (Integer)this.matchingNodes.remove(field)) != null
-				&& typeInHierarchy
-				&& (this.matchContainer & SearchPattern.CLASS) != 0) {
-					this.locator.reportFieldDeclaration(
-						field, 
-						enclosingElement, 
-						level.intValue() == SearchPattern.ACCURATE_MATCH ?
-							IJavaSearchResultCollector.EXACT_MATCH :
-							IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-			this.reportMatching(field, enclosingElement, type, typeInHierarchy);
-		}
-	}
-
-	// methods
-	AbstractMethodDeclaration[] methods = type.methods;
-	if (methods != null) {
-		for (int i = 0; i < methods.length; i++) {
-			AbstractMethodDeclaration method = methods[i];
-			if ((level = (Integer)this.matchingNodes.remove(method)) != null
-				&& typeInHierarchy
-				&& (this.matchContainer & SearchPattern.CLASS) != 0) {
-					this.locator.reportMethodDeclaration(
-						method, 
-						enclosingElement, 
-						level.intValue() == SearchPattern.ACCURATE_MATCH ?
-							IJavaSearchResultCollector.EXACT_MATCH :
-							IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-			this.reportMatching(method, enclosingElement, typeInHierarchy);
-		}
-	}
-
-	// member types
-	MemberTypeDeclaration[] memberTypes = type.memberTypes;
-	if (memberTypes != null) {
-		for (int i = 0; i < memberTypes.length; i++) {
-			MemberTypeDeclaration memberType = memberTypes[i];
-			if ((level = (Integer)this.matchingNodes.remove(memberType)) != null
-				&& typeInHierarchy
-				&& (this.matchContainer & SearchPattern.CLASS) != 0) {
-					this.locator.reportTypeDeclaration(
-						memberType, 
-						enclosingElement, 
-						level.intValue() == SearchPattern.ACCURATE_MATCH ?
-							IJavaSearchResultCollector.EXACT_MATCH :
-							IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-			this.reportMatching(memberType, enclosingElement);
-		}
-	}
-
-	// super types
-	if (type instanceof AnonymousLocalTypeDeclaration) {
-		TypeReference superType = ((AnonymousLocalTypeDeclaration)type).allocation.type;
-		if (superType != null && (level = (Integer)this.matchingNodes.remove(superType)) != null) {
-			if ((this.matchContainer & SearchPattern.CLASS) != 0) {
-				this.locator.reportSuperTypeReference(
-					superType, 
-					enclosingElement, 
-					level.intValue() == SearchPattern.ACCURATE_MATCH ?
-						IJavaSearchResultCollector.EXACT_MATCH :
-						IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-		}
-	} else {
-		TypeReference superClass = type.superclass;
-		if (superClass != null && (level = (Integer)this.matchingNodes.remove(superClass)) != null) {
-			if ((this.matchContainer & SearchPattern.CLASS) != 0) {
-				this.locator.reportSuperTypeReference(
-					superClass, 
-					enclosingElement, 
-					level.intValue() == SearchPattern.ACCURATE_MATCH ?
-						IJavaSearchResultCollector.EXACT_MATCH :
-						IJavaSearchResultCollector.POTENTIAL_MATCH);
-			}
-		}
-		TypeReference[] superInterfaces = type.superInterfaces;
-		if (superInterfaces != null) {
-			for (int i = 0; i < superInterfaces.length; i++) {
-				TypeReference superInterface = superInterfaces[i];
-				if ((level = (Integer)this.matchingNodes.get(superInterface)) != null) {
-					if ((this.matchContainer & SearchPattern.CLASS) != 0) {
-						this.locator.reportSuperTypeReference(
-							superInterface, 
-							enclosingElement, 
-							level.intValue() == SearchPattern.ACCURATE_MATCH ?
-								IJavaSearchResultCollector.EXACT_MATCH :
-								IJavaSearchResultCollector.POTENTIAL_MATCH);
-					}
-				}
-			}
-		}
-	}
+	return this.matchingNodes.removeKey(node);
 }
 public String toString() {
 	StringBuffer result = new StringBuffer();
 	result.append("Exact matches:"); //$NON-NLS-1$
-	for (Iterator iter = this.matchingNodes.keySet().iterator(); iter.hasNext();) {
-		result.append("\n"); //$NON-NLS-1$
-		AstNode node = (AstNode)iter.next();
-		Object value = this.matchingNodes.get(node);
-		if (value instanceof Integer) {
-			result.append('\t');
-			int accuracy = ((Integer)value).intValue();
-			switch (accuracy) {
-				case SearchPattern.IMPOSSIBLE_MATCH:
-					result.append("IMPOSSIBLE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.POSSIBLE_MATCH:
-					result.append("POSSIBLE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.INACCURATE_MATCH:
-					result.append("INACCURATE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.ACCURATE_MATCH:
-					result.append("ACCURATE_MATCH: "); //$NON-NLS-1$
-					break;
-			}
-		} 
-		result.append(node.toString(0));
+	Object[] keyTable = this.matchingNodes.keyTable;
+	Object[] valueTable = this.matchingNodes.valueTable;
+	for (int i = 0, l = keyTable.length; i < l; i++) {
+		ASTNode node = (ASTNode) keyTable[i];
+		if (node == null) continue;
+		result.append("\n\t"); //$NON-NLS-1$
+		result.append(valueTable[i] == EXACT_MATCH
+			? "ACCURATE_MATCH: " //$NON-NLS-1$
+			: "INACCURATE_MATCH: "); //$NON-NLS-1$
+		node.print(0, result);
 	}
-	result.append("\nPotential matches:"); //$NON-NLS-1$
-	for (Iterator iter = this.potentialMatchingNodes.keySet().iterator(); iter.hasNext();) {
-		result.append("\n"); //$NON-NLS-1$
-		AstNode node = (AstNode)iter.next();
-		Object value = this.potentialMatchingNodes.get(node);
-		if (value instanceof Integer) {
-			result.append("\t"); //$NON-NLS-1$
-			int accuracy = ((Integer)value).intValue();
-			switch (accuracy) {
-				case SearchPattern.IMPOSSIBLE_MATCH:
-					result.append("IMPOSSIBLE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.POSSIBLE_MATCH:
-					result.append("POSSIBLE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.INACCURATE_MATCH:
-					result.append("INACCURATE_MATCH: "); //$NON-NLS-1$
-					break;
-				case SearchPattern.ACCURATE_MATCH:
-					result.append("ACCURATE_MATCH: "); //$NON-NLS-1$
-					break;
-			}
-		}
-		result.append(node.toString(0));
+
+	result.append("\nPossible matches:"); //$NON-NLS-1$
+	Object[] nodes = this.possibleMatchingNodesSet.values;
+	for (int i = 0, l = nodes.length; i < l; i++) {
+		ASTNode node = (ASTNode) nodes[i];
+		if (node == null) continue;
+		result.append("\nPOSSIBLE_MATCH: "); //$NON-NLS-1$
+		node.print(0, result);
 	}
 	return result.toString();
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingOpenable.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingOpenable.java
deleted file mode 100644
index c596508..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingOpenable.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.env.IBinaryField;
-import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
-import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
-import org.eclipse.jdt.internal.core.*;
- 
-// TODO: (jerome) Remove when switching to MatchLocator2
-public class MatchingOpenable {
-	static final CompilationUnitDeclaration ALREADY_RESOLVED = new CompilationUnitDeclaration(null, null, 0);
-	private MatchLocator locator;
-	public IResource resource;
-	public Openable openable;
-	private CompilationUnitDeclaration parsedUnit;
-	private char[] source;
-	private MatchSet matchSet;
-
-public MatchingOpenable(
-		MatchLocator locator, 
-		IResource resource, 
-		Openable openable,
-		CompilationUnitDeclaration parsedUnit,
-		MatchSet matchSet) {
-	this.locator = locator;
-	this.resource = resource;
-	this.openable = openable;
-	this.parsedUnit = parsedUnit;
-	this.matchSet = matchSet;
-}
-public static IType getTopLevelType(IType binaryType) {
-	
-	// ensure it is not a local or anoymous type (see bug 28752  J Search resports non-existent Java element)
-	String typeName = binaryType.getElementName();
-	int lastDollar = typeName.lastIndexOf('$');
-	int length = typeName.length();
-	if (lastDollar != -1 && lastDollar < length-1) {
-		if (Character.isDigit(typeName.charAt(lastDollar+1))) {
-			// local or anonymous type
-			typeName = typeName.substring(0, lastDollar);
-			IClassFile classFile = binaryType.getPackageFragment().getClassFile(typeName+".class"); //$NON-NLS-1$
-			try {
-				binaryType = classFile.getType();
-			} catch (JavaModelException e) {
-				// ignore as implementation of getType() cannot throw this exception
-			}
-		}
-	}
-	
-	// ensure it is a top level type
-	IType declaringType = binaryType.getDeclaringType();
-	while (declaringType != null) {
-		binaryType = declaringType;
-		declaringType = binaryType.getDeclaringType();
-	}
-	return binaryType;
-}
-public void buildTypeBindings() {
-	
-	if (this.parsedUnit == null) {
-		char[] source = this.getSource();
-		if (source == null) return;
-		this.buildTypeBindings(source);
-	} else {
-		// if a parsed unit's scope is set, its bindings have already been built
-		if (this.parsedUnit.scope != null) return;
-		
-		this.locator.lookupEnvironment.buildTypeBindings(this.parsedUnit);
-	}
-}
-private void buildTypeBindings(final char[] source) {
-	// get qualified name
-	char[] qualifiedName = this.getQualifiedName();
-	if (qualifiedName == null) return;
-
-	// create match set	
-	this.matchSet = new MatchSet(this.locator);
-	
-	try {
-		this.locator.parser.matchSet = this.matchSet;
-
-		this.parsedUnit = (CompilationUnitDeclaration)this.locator.parsedUnits.get(qualifiedName);
-		if (this.parsedUnit == null) {
-			// diet parse
-			this.parsedUnit = this.locator.dietParse(source);
-			
-			// initial type binding creation
-			this.locator.lookupEnvironment.buildTypeBindings(this.parsedUnit);
-		} 
-
-		// free memory and remember that this unit as already been resolved 
-		// (case of 2 matching openables on a binary type and its member type) 
-		this.locator.parsedUnits.put(qualifiedName, ALREADY_RESOLVED);
-
-	} finally {
-		this.locator.parser.matchSet = null;
-	}
-}
-public boolean equals(Object obj) {
-	if (!(obj instanceof MatchingOpenable)) return false;
-	return this.openable.equals(((MatchingOpenable)obj).openable);
-}
-private char[] getQualifiedName() {
-	if (this.openable instanceof CompilationUnit) {
-		// get file name
-		String fileName = this.resource.getFullPath().lastSegment();
-		// get main type name
-		char[] mainTypeName = fileName.substring(0, fileName.length()-5).toCharArray(); 
-		CompilationUnit cu = (CompilationUnit)this.openable;
-		return cu.getType(new String(mainTypeName)).getFullyQualifiedName().toCharArray();
-	} else {
-		org.eclipse.jdt.internal.core.ClassFile classFile = (org.eclipse.jdt.internal.core.ClassFile)this.openable;
-		try {
-			IType type = getTopLevelType(classFile.getType());
-			return type.getFullyQualifiedName().toCharArray();
-		} catch (JavaModelException e) {
-			return null; // nothing we can do here
-		}
-	}
-}
-public char[] getSource() {
-	if (this.source != null) return source;
-	try {
-		if (this.openable instanceof WorkingCopy) {
-			IBuffer buffer = this.openable.getBuffer();
-			if (buffer == null) return null;
-			this.source = buffer.getCharacters();
-		} else if (this.openable instanceof CompilationUnit) {
-			this.source = Util.getResourceContentsAsCharArray((IFile)this.resource);
-		} else if (this.openable instanceof org.eclipse.jdt.internal.core.ClassFile) {
-			org.eclipse.jdt.internal.core.ClassFile classFile = (org.eclipse.jdt.internal.core.ClassFile)this.openable;
-			this.source = this.locator.findSource(classFile);
-		}
-	} catch (JavaModelException e) {
-	}
-	return this.source;
-}
-public int hashCode() {
-	return this.openable.hashCode();
-}
-public boolean hasAlreadyDefinedType() {
-	if (this.parsedUnit == null) return false;
-	CompilationResult result = this.parsedUnit.compilationResult;
-	if (result == null) return false;
-	for (int i = 0; i < result.problemCount; i++) {
-		IProblem problem = result.problems[i];
-		if (problem.getID() == IProblem.DuplicateTypes) {
-			return true;
-		}
-	}
-	return false;
-}
-
-public void locateMatches() throws CoreException {
-	char[] source = this.getSource();
-	if (source == null) {
-		if (this.openable instanceof org.eclipse.jdt.internal.core.ClassFile) {
-			this.locateMatchesInClassFile();
-		}
-	} else {
-		this.locateMatchesInCompilationUnit(source);
-	}
-}
-/**
- * Locate declaration in the current class file. This class file is always in a jar.
- */
-private void locateMatchesInClassFile() throws CoreException, JavaModelException {
-	org.eclipse.jdt.internal.core.ClassFile classFile = (org.eclipse.jdt.internal.core.ClassFile)this.openable;
-	IBinaryType info = this.locator.getBinaryInfo(classFile, this.resource);
-	if (info == null) 
-		return; // unable to go further
-
-	// check class definition
-	BinaryType binaryType = (BinaryType)classFile.getType();
-	if (this.locator.pattern.matchesBinary(info, null)) {
-		this.locator.reportBinaryMatch(binaryType, info, IJavaSearchResultCollector.EXACT_MATCH);
-	}
-
-	boolean compilationAborted = false;
-	if (this.locator.pattern.needsResolve) {
-		// resolve
-		BinaryTypeBinding binding = null;
-		try {
-			binding = this.locator.cacheBinaryType(binaryType);
-			if (binding != null) {
-				// filter out element not in hierarchy scope
-				if (this.locator.hierarchyResolver != null 
-						&& !this.locator.hierarchyResolver.subOrSuperOfFocus(binding)) {
-					return;
-				}
-	
-				// check methods
-				MethodBinding[] methods = binding.methods();
-				for (int i = 0; i < methods.length; i++) {
-					MethodBinding method = methods[i];
-					int level = this.locator.pattern.matchLevel(method);
-					switch (level) {
-						case SearchPattern.IMPOSSIBLE_MATCH:
-						case SearchPattern.INACCURATE_MATCH:
-							break;
-						default:
-							IMethod methodHandle = 
-								binaryType.getMethod(
-									new String(method.isConstructor() ? binding.compoundName[binding.compoundName.length-1] : method.selector),
-									Signature.getParameterTypes(new String(method.signature()).replace('/', '.'))
-								);
-							this.locator.reportBinaryMatch(
-								methodHandle, 
-								info, 
-								level == SearchPattern.ACCURATE_MATCH ? 
-									IJavaSearchResultCollector.EXACT_MATCH : 
-									IJavaSearchResultCollector.POTENTIAL_MATCH);
-					}
-				}
-		
-				// check fields
-				FieldBinding[] fields = binding.fields();
-				for (int i = 0; i < fields.length; i++) {
-					FieldBinding field = fields[i];
-					int level = this.locator.pattern.matchLevel(field);
-					switch (level) {
-						case SearchPattern.IMPOSSIBLE_MATCH:
-						case SearchPattern.INACCURATE_MATCH:
-							break;
-						default:
-							IField fieldHandle = binaryType.getField(new String(field.name));
-							this.locator.reportBinaryMatch(
-								fieldHandle, 
-								info, 
-								level == SearchPattern.ACCURATE_MATCH ? 
-									IJavaSearchResultCollector.EXACT_MATCH : 
-									IJavaSearchResultCollector.POTENTIAL_MATCH);
-					}
-				}
-			}
-		} catch (AbortCompilation e) {
-			binding = null;
-		}
-
-		// no need to check binary info if resolve was successful
-		compilationAborted = binding == null;
-		if (!compilationAborted) return;
-	}
-
-	// if compilation was aborted it is a problem with the class path: 
-	// report as a potential match if binary info matches the pattern
-	int accuracy = compilationAborted ? IJavaSearchResultCollector.POTENTIAL_MATCH : IJavaSearchResultCollector.EXACT_MATCH;
-	
-	// check methods
-	IBinaryMethod[] methods = info.getMethods();
-	int length = methods == null ? 0 : methods.length;
-	for (int i = 0; i < length; i++) {
-		IBinaryMethod method = methods[i];
-		if (this.locator.pattern.matchesBinary(method, info)) {
-			IMethod methodHandle = 
-				binaryType.getMethod(
-					new String(method.isConstructor() ? info.getName() : method.getSelector()),
-					Signature.getParameterTypes(new String(method.getMethodDescriptor()).replace('/', '.'))
-				);
-			this.locator.reportBinaryMatch(methodHandle, info, accuracy);
-		}
-	}
-
-	// check fields
-	IBinaryField[] fields = info.getFields();
-	length = fields == null ? 0 : fields.length;
-	for (int i = 0; i < length; i++) {
-		IBinaryField field = fields[i];
-		if (this.locator.pattern.matchesBinary(field, info)) {
-			IField fieldHandle = binaryType.getField(new String(field.getName()));
-			this.locator.reportBinaryMatch(fieldHandle, info, accuracy);
-		}
-	}
-}
-private void locateMatchesInCompilationUnit(char[] source) throws CoreException {
-	if (this.parsedUnit == null) { // case where no binding resolution is needed
-		// create match set	
-		this.matchSet = new MatchSet(this.locator);
-		this.locator.parser.matchSet = this.matchSet;
-		
-		// diet parse
-		char[] qualifiedName = this.getQualifiedName();
-		if (qualifiedName == null || (this.parsedUnit = (CompilationUnitDeclaration)this.locator.parsedUnits.get(qualifiedName)) == null) {
-			this.parsedUnit = this.locator.dietParse(source);
-		}
-	}
-	if (this.parsedUnit != null && this.parsedUnit != ALREADY_RESOLVED) {
-		try {
-			this.locator.parser.matchSet = this.matchSet;
-			this.locator.parser.scanner.setSource(source);
-			this.locator.parser.parseBodies(this.parsedUnit);
-			// report matches that don't need resolve
-			this.matchSet.cuHasBeenResolved = false;
-			this.matchSet.reportMatching(parsedUnit);
-			
-			// resolve if needed
-			if (this.matchSet.needsResolve() && this.parsedUnit.types != null) {
-				if (!this.locator.compilationAborted) {
-					try {
-						if (this.parsedUnit.scope == null) {
-							// bindings were not created (case of a FieldReferencePattern that doesn't need resolve, 
-							// but we need to resolve because of a SingleNameReference being a potential match)
-							MatchingOpenable[] openables = this.locator.matchingOpenables.getMatchingOpenables(this.openable.getJavaProject().getPackageFragmentRoots());
-							this.locator.createAndResolveBindings(openables);
-						}
-						if (this.parsedUnit.scope != null) {
-							this.parsedUnit.scope.faultInTypes();
-							this.parsedUnit.resolve();
-						}
-						// report matches that needed resolve
-						this.matchSet.cuHasBeenResolved = true;
-						this.matchSet.reportMatching(this.parsedUnit);
-					} catch (AbortCompilation e) {
-						// could not resolve: report innacurate matches
-						this.matchSet.cuHasBeenResolved = true;
-						this.matchSet.reportMatching(this.parsedUnit);
-						if (!(e instanceof AbortCompilationUnit)) {
-							// problem with class path
-							throw e;
-						}
-					}
-				} else {
-					// problem ocured while completing the bindings for the base classes
-					// -> report innacurate matches
-					this.matchSet.cuHasBeenResolved = true;
-					this.matchSet.reportMatching(this.parsedUnit);
-				}
-			}
-		} finally {
-			this.locator.parser.matchSet = null;
-		}
-	}
-}
-/**
- * Free memory.
- */
-public void reset() {
-	this.locator.parsedUnits.removeKey(this.getQualifiedName());
-	this.parsedUnit = null;
-	this.matchSet = null;
-}
-public String toString() {
-	return this.openable.toString();
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingOpenableSet.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingOpenableSet.java
deleted file mode 100644
index db2e9bd..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchingOpenableSet.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
-import org.eclipse.jdt.internal.compiler.util.ObjectVector;
-
-/**
- * A set of MatchingOPenables that is sorted by package fragment roots.
- */
-// TODO: (jerome) Remove when switching to MatchLocator2
-public class MatchingOpenableSet {
-	private HashtableOfObject rootsToOpenable = new HashtableOfObject(5);
-	private int elementCount = 0;
-	
-	public void add(MatchingOpenable matchingOpenable) {
-		IPackageFragmentRoot root = matchingOpenable.openable.getPackageFragmentRoot();
-		char[] path = root.getPath().toString().toCharArray();
-		ObjectVector openables = (ObjectVector)this.rootsToOpenable.get(path);
-		if (openables == null) {
-			openables = new ObjectVector();
-			this.rootsToOpenable.put(path, openables);
-			openables.add(matchingOpenable);
-			this.elementCount++;
-		} else if (!openables.contains(matchingOpenable)) {
-			openables.add(matchingOpenable);
-			this.elementCount++;
-		}
-	}
-	
-	public MatchingOpenable[] getMatchingOpenables(IPackageFragmentRoot[] roots) {
-		MatchingOpenable[] result = new MatchingOpenable[this.elementCount];
-		int index = 0;
-		for (int i = 0, length = roots.length; i < length; i++) {
-			IPackageFragmentRoot root = roots[i];
-			char[] path = root.getPath().toString().toCharArray();
-			ObjectVector openables = (ObjectVector)this.rootsToOpenable.get(path);
-			if (openables != null) {
-				openables.copyInto(result, index);
-				index += openables.size();
-			}
-		}
-		if (index < this.elementCount) {
-			System.arraycopy(
-				result, 
-				0, 
-				result = new MatchingOpenable[index],
-				0,
-				index);
-		}
-		return result;
-	}
-}
-
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodDeclarationPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodDeclarationPattern.java
deleted file mode 100644
index e4c513e..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodDeclarationPattern.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.io.IOException;
-
-import org.eclipse.jdt.core.Signature;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.indexing.AbstractIndexer;
-
-public class MethodDeclarationPattern extends MethodPattern {
-public MethodDeclarationPattern(
-	char[] selector, 
-	int matchMode, 
-	boolean isCaseSensitive,
-	char[] declaringQualification,
-	char[] declaringSimpleName,	
-	char[] returnQualification, 
-	char[] returnSimpleName,
-	char[][] parameterQualifications, 
-	char[][] parameterSimpleNames) {
-
-	super(matchMode, isCaseSensitive);
-
-	this.selector = isCaseSensitive ? selector : CharOperation.toLowerCase(selector);
-	this.declaringQualification = isCaseSensitive ? declaringQualification : CharOperation.toLowerCase(declaringQualification);
-	this.declaringSimpleName = isCaseSensitive ? declaringSimpleName : CharOperation.toLowerCase(declaringSimpleName);
-	this.returnQualification = isCaseSensitive ? returnQualification : CharOperation.toLowerCase(returnQualification);
-	this.returnSimpleName = isCaseSensitive ? returnSimpleName : CharOperation.toLowerCase(returnSimpleName);
-
-	if (parameterSimpleNames != null){
-		this.parameterQualifications = new char[parameterSimpleNames.length][];
-		this.parameterSimpleNames = new char[parameterSimpleNames.length][];
-		for (int i = 0, max = parameterSimpleNames.length; i < max; i++){
-			this.parameterQualifications[i] = isCaseSensitive ? parameterQualifications[i] : CharOperation.toLowerCase(parameterQualifications[i]);
-			this.parameterSimpleNames[i] = isCaseSensitive ? parameterSimpleNames[i] : CharOperation.toLowerCase(parameterSimpleNames[i]);
-		}
-	}	
-	this.needsResolve = this.needsResolve();
-}
-public void decodeIndexEntry(IEntryResult entryResult){
-
-	char[] word = entryResult.getWord();
-	int size = word.length;
-	int lastSeparatorIndex = CharOperation.lastIndexOf(SEPARATOR, word);	
-
-	decodedParameterCount = Integer.parseInt(new String(word, lastSeparatorIndex + 1, size - lastSeparatorIndex - 1));
-	decodedSelector = CharOperation.subarray(word, METHOD_DECL.length, lastSeparatorIndex);
-}
-/**
- * see SearchPattern.feedIndexRequestor
- */
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope) throws IOException {
-	for (int i = 0, max = references.length; i < max; i++) {
-		IndexedFile file = input.getIndexedFile(references[i]);
-		String path;
-		if (file != null && scope.encloses(path = IndexedFile.convertPath(file.getPath()))) {
-			requestor.acceptMethodDeclaration(path, decodedSelector, decodedParameterCount);
-		}
-	}
-}
-public String getPatternName(){
-	return "MethodDeclarationPattern: "; //$NON-NLS-1$
-}
-/**
- * @see SearchPattern#indexEntryPrefix
- */
-public char[] indexEntryPrefix() {
-
-	return AbstractIndexer.bestMethodDeclarationPrefix(
-			selector, 
-			parameterSimpleNames == null ? -1 : parameterSimpleNames.length, 
-			matchMode, 
-			isCaseSensitive);
-}
-/**
- * @see SearchPattern#matchContainer()
- */
-protected int matchContainer() {
-	return CLASS;
-}
-/**
- * @see SearchPattern#matchesBinary(Object, Object)
- */
-public boolean matchesBinary(Object binaryInfo, Object enclosingBinaryInfo) {
-	if (!(binaryInfo instanceof IBinaryMethod)) return false;
-
-	IBinaryMethod method = (IBinaryMethod)binaryInfo;
-	
-	// selector
-	if (!this.matchesName(this.selector, method.getSelector()))
-		return false;
-
-	// declaring type
-	IBinaryType declaringType = (IBinaryType)enclosingBinaryInfo;
-	if (declaringType != null) {
-		char[] declaringTypeName = (char[])declaringType.getName().clone();
-		CharOperation.replace(declaringTypeName, '/', '.');
-		if (!this.matchesType(this.declaringSimpleName, this.declaringQualification, declaringTypeName)) {
-			return false;
-		}
-	}
-
-	String methodDescriptor = new String(method.getMethodDescriptor()).replace('/', '.');
-
-	// look at return type only if declaring type is not specified
-	if (this.declaringSimpleName == null) {
-		String returnTypeSignature = Signature.toString(Signature.getReturnType(methodDescriptor));
-		if (!this.matchesType(this.returnSimpleName, this.returnQualification, returnTypeSignature.toCharArray())) {
-			return false;
-		}
-	}
-		
-	// parameter types
-	int parameterCount = this.parameterSimpleNames == null ? -1 : this.parameterSimpleNames.length;
-	if (parameterCount > -1) {
-		String[] arguments = Signature.getParameterTypes(methodDescriptor);
-		int argumentCount = arguments.length;
-		if (parameterCount != argumentCount)
-			return false;
-		for (int i = 0; i < parameterCount; i++) {
-			char[] qualification = this.parameterQualifications[i];
-			char[] type = this.parameterSimpleNames[i];
-			if (!this.matchesType(type, qualification, Signature.toString(arguments[i]).toCharArray()))
-				return false;
-		}
-	}
-
-	return true;
-}
-
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
- */
-public int matchLevel(AstNode node, boolean resolve) {
-	if (!(node instanceof MethodDeclaration)) return IMPOSSIBLE_MATCH;
-
-	MethodDeclaration method = (MethodDeclaration)node;
-
-	if (resolve) {
-		return this.matchLevel(method.binding);
-	} else {
-		// selector
-		if (!this.matchesName(this.selector, method.selector))
-			return IMPOSSIBLE_MATCH;
-
-		// return type
-		TypeReference methodReturnType = method.returnType;
-		if (methodReturnType != null) {
-			char[][] methodReturnTypeName = methodReturnType.getTypeName();
-			char[] sourceName = this.toArrayName(
-				methodReturnTypeName[methodReturnTypeName.length-1], 
-				methodReturnType.dimensions());
-			if (!this.matchesName(this.returnSimpleName, sourceName))
-				return IMPOSSIBLE_MATCH;
-		}
-			
-		// parameter types
-		int parameterCount = this.parameterSimpleNames == null ? -1 : this.parameterSimpleNames.length;
-		if (parameterCount > -1) {
-			int argumentCount = method.arguments == null ? 0 : method.arguments.length;
-			if (parameterCount != argumentCount)
-				return IMPOSSIBLE_MATCH;
-		}
-
-		return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-	}
-}
-
-/**
- * @see SearchPattern#matchLevel(Binding)
- */
-public int matchLevel(Binding binding) {
-	if (binding == null) return INACCURATE_MATCH;
-	if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH;
-	int level;
-
-	MethodBinding method = (MethodBinding)binding;
-	
-	// selector
-	if (!this.matchesName(this.selector, method.selector))
-		return IMPOSSIBLE_MATCH;
-
-	// declaring type
-	ReferenceBinding declaringType = method.declaringClass;
-	if (!method.isStatic() && !method.isPrivate()) {
-		level = this.matchLevelAsSubtype(declaringType, this.declaringSimpleName, this.declaringQualification);
-	} else {
-		level = this.matchLevelForType(this.declaringSimpleName, this.declaringQualification, declaringType);
-	}
-	if (level == IMPOSSIBLE_MATCH) {
-		return IMPOSSIBLE_MATCH;
-	}
-
-	// look at return type only if declaring type is not specified
-	if (this.declaringSimpleName == null) {
-		int newLevel = this.matchLevelForType(this.returnSimpleName, this.returnQualification, method.returnType);
-		switch (newLevel) {
-			case IMPOSSIBLE_MATCH:
-				return IMPOSSIBLE_MATCH;
-			case ACCURATE_MATCH: // keep previous level
-				break;
-			default: // ie. INACCURATE_MATCH
-				level = newLevel;
-				break;
-		}
-	}
-		
-	// parameter types
-	int parameterCount = this.parameterSimpleNames == null ? -1 : this.parameterSimpleNames.length;
-	if (parameterCount > -1) {
-		int argumentCount = method.parameters == null ? 0 : method.parameters.length;
-		if (parameterCount != argumentCount)
-			return IMPOSSIBLE_MATCH;
-		for (int i = 0; i < parameterCount; i++) {
-			char[] qualification = this.parameterQualifications[i];
-			char[] type = this.parameterSimpleNames[i];
-			int newLevel = this.matchLevelForType(type, qualification, method.parameters[i]);
-			switch (newLevel) {
-				case IMPOSSIBLE_MATCH:
-					return IMPOSSIBLE_MATCH;
-				case ACCURATE_MATCH: // keep previous level
-					break;
-				default: // ie. INACCURATE_MATCH
-					level = newLevel;
-					break;
-			}
-		}
-	}
-
-	return level;
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
new file mode 100644
index 0000000..8a08a5d
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
@@ -0,0 +1,286 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.core.util.SimpleSet;
+
+public class MethodLocator extends PatternLocator {
+
+protected MethodPattern pattern;
+protected boolean isDeclarationOfReferencedMethodsPattern;
+
+//extra reference info
+public char[][][] allSuperDeclaringTypeNames;
+
+public MethodLocator(MethodPattern pattern) {
+	super(pattern);
+
+	this.pattern = pattern;
+	this.isDeclarationOfReferencedMethodsPattern = this.pattern instanceof DeclarationOfReferencedMethodsPattern;
+}
+public void initializePolymorphicSearch(MatchLocator locator) {
+	try {
+		this.allSuperDeclaringTypeNames =
+			new SuperTypeNamesCollector(
+				this.pattern,
+				this.pattern.declaringSimpleName,
+				this.pattern.declaringQualification,
+				locator,
+				this.pattern.declaringType,
+				locator.progressMonitor).collect();
+	} catch (JavaModelException e) {
+		// inaccurate matches will be found
+	}
+}
+/**
+ * Returns whether the code gen will use an invoke virtual for 
+ * this message send or not.
+ */
+protected boolean isVirtualInvoke(MethodBinding method, MessageSend messageSend) {
+	return !method.isStatic() && !method.isPrivate() && !messageSend.isSuperAccess();
+}
+//public int match(ASTNode node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(Expression node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(FieldDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+public int match(MethodDeclaration node, MatchingNodeSet nodeSet) {
+	if (!this.pattern.findDeclarations) return IMPOSSIBLE_MATCH;
+
+	if (!matchesName(this.pattern.selector, node.selector)) return IMPOSSIBLE_MATCH;
+	if (this.pattern.parameterSimpleNames != null) {
+		int length = this.pattern.parameterSimpleNames.length;
+		ASTNode[] args = node.arguments;
+		int argsLength = args == null ? 0 : args.length;
+		if (length != argsLength) return IMPOSSIBLE_MATCH;
+
+		for (int i = 0; i < argsLength; i++)
+			if (!matchesTypeReference(this.pattern.parameterSimpleNames[i], ((Argument) args[i]).type)) return IMPOSSIBLE_MATCH;
+	}
+	if (!matchesTypeReference(this.pattern.returnSimpleName, node.returnType)) return IMPOSSIBLE_MATCH;
+
+	return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+}
+public int match(MessageSend node, MatchingNodeSet nodeSet) {
+	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
+
+	if (!matchesName(this.pattern.selector, node.selector)) return IMPOSSIBLE_MATCH;
+	if (this.pattern.parameterSimpleNames != null) {
+		int length = this.pattern.parameterSimpleNames.length;
+		ASTNode[] args = node.arguments;
+		int argsLength = args == null ? 0 : args.length;
+		if (length != argsLength) return IMPOSSIBLE_MATCH;
+	}
+
+	return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+}
+//public int match(Reference node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(TypeDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(TypeReference node, MatchingNodeSet nodeSet) - SKIP IT
+
+protected int matchContainer() {
+	if (this.pattern.findReferences) {
+		// need to look almost everywhere to find in javadocs
+		return CLASS_CONTAINER | METHOD_CONTAINER | FIELD_CONTAINER;
+	}
+	return CLASS_CONTAINER;
+}
+protected int matchMethod(MethodBinding method) {
+	if (!matchesName(this.pattern.selector, method.selector)) return IMPOSSIBLE_MATCH;
+
+	int level = ACCURATE_MATCH;
+	// look at return type only if declaring type is not specified
+	if (this.pattern.declaringSimpleName == null) {
+		int newLevel = resolveLevelForType(this.pattern.returnSimpleName, this.pattern.returnQualification, method.returnType);
+		if (level > newLevel) {
+			if (newLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
+			level = newLevel; // can only be downgraded
+		}
+	}
+
+	// parameter types
+	int parameterCount = this.pattern.parameterSimpleNames == null ? -1 : this.pattern.parameterSimpleNames.length;
+	if (parameterCount > -1) {
+		if (method.parameters == null) return INACCURATE_MATCH;
+		if (parameterCount != method.parameters.length) return IMPOSSIBLE_MATCH;
+		for (int i = 0; i < parameterCount; i++) {
+			int newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], method.parameters[i]);
+			if (level > newLevel) {
+				if (newLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
+				level = newLevel; // can only be downgraded
+			}
+		}
+	}
+	return level;
+}
+/**
+ * @see SearchPattern#matchReportReference
+ */
+protected void matchReportReference(ASTNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	if (this.isDeclarationOfReferencedMethodsPattern) {
+		// need exact match to be able to open on type ref
+		if (accuracy != IJavaSearchResultCollector.EXACT_MATCH) return;
+
+		// element that references the method must be included in the enclosing element
+		DeclarationOfReferencedMethodsPattern declPattern = (DeclarationOfReferencedMethodsPattern) this.pattern; 
+		while (element != null && !declPattern.enclosingElement.equals(element))
+			element = element.getParent();
+		if (element != null)
+			reportDeclaration(((MessageSend) reference).binding, locator, declPattern.knownMethods);
+	} else if (this.pattern.findReferences && reference instanceof MessageSend) {
+		// message ref are starting at the selector start
+		locator.report(
+			(int) (((MessageSend) reference).nameSourcePosition >>> 32),
+			reference.sourceEnd,
+			element,
+			accuracy);
+	} else {
+		super.matchReportReference(reference, element, accuracy, locator);
+	}
+}
+protected void reportDeclaration(MethodBinding methodBinding, MatchLocator locator, SimpleSet knownMethods) throws CoreException {
+	ReferenceBinding declaringClass = methodBinding.declaringClass;
+	IType type = locator.lookupType(declaringClass);
+	if (type == null) return; // case of a secondary type
+
+	char[] bindingSelector = methodBinding.selector;
+	TypeBinding[] parameters = methodBinding.parameters;
+	int parameterLength = parameters.length;
+	String[] parameterTypes = new String[parameterLength];
+	for (int i = 0; i  < parameterLength; i++)
+		parameterTypes[i] = Signature.createTypeSignature(parameters[i].sourceName(), false);
+	IMethod method = type.getMethod(new String(bindingSelector), parameterTypes);
+	if (knownMethods.includes(method)) return;
+
+	knownMethods.add(method);
+	IResource resource = type.getResource();
+	boolean isBinary = type.isBinary();
+	IBinaryType info = null;
+	if (isBinary) {
+		if (resource == null)
+			resource = type.getJavaProject().getProject();
+		info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile)type.getClassFile(), resource);
+		locator.reportBinaryMatch(resource, method, info, IJavaSearchResultCollector.EXACT_MATCH);
+	} else {
+		ClassScope scope = ((SourceTypeBinding) declaringClass).scope;
+		if (scope != null) {
+			TypeDeclaration typeDecl = scope.referenceContext;
+			AbstractMethodDeclaration methodDecl = null;
+			AbstractMethodDeclaration[] methodDecls = typeDecl.methods;
+			for (int i = 0, length = methodDecls.length; i < length; i++) {
+				if (CharOperation.equals(bindingSelector, methodDecls[i].selector)) {
+					methodDecl = methodDecls[i];
+					break;
+				}
+			} 
+			if (methodDecl != null)
+				locator.report(
+					resource, 
+					methodDecl.sourceStart, 
+					methodDecl.sourceEnd, 
+					method, 
+					IJavaSearchResultCollector.EXACT_MATCH, 
+					locator.getParticipant());
+		}
+	}
+}
+public int resolveLevel(ASTNode possibleMatchingNode) {
+	if (this.pattern.findReferences && possibleMatchingNode instanceof MessageSend)
+		return resolveLevel((MessageSend) possibleMatchingNode);
+	if (this.pattern.findDeclarations && possibleMatchingNode instanceof MethodDeclaration)
+		return resolveLevel(((MethodDeclaration) possibleMatchingNode).binding);
+	return IMPOSSIBLE_MATCH;
+}
+public int resolveLevel(Binding binding) {
+	if (binding == null) return INACCURATE_MATCH;
+	if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH;
+
+	MethodBinding method = (MethodBinding) binding;
+	int methodLevel = matchMethod(method);
+	if (methodLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
+
+	// declaring type
+	char[] qualifiedPattern = qualifiedPattern(this.pattern.declaringSimpleName, this.pattern.declaringQualification);
+	if (qualifiedPattern == null) return methodLevel; // since any declaring class will do
+
+	int declaringLevel = !method.isStatic() && !method.isPrivate()
+		? resolveLevelAsSubtype(qualifiedPattern, method.declaringClass)
+		: resolveLevelForType(qualifiedPattern, method.declaringClass);
+	return methodLevel > declaringLevel ? declaringLevel : methodLevel; // return the weaker match
+}
+protected int resolveLevel(MessageSend messageSend) {
+	MethodBinding method = messageSend.binding;
+	if (method == null) return INACCURATE_MATCH;
+
+	int methodLevel = matchMethod(method);
+	if (methodLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
+
+	// receiver type
+	char[] qualifiedPattern = qualifiedPattern(this.pattern.declaringSimpleName, this.pattern.declaringQualification);
+	if (qualifiedPattern == null) return methodLevel; // since any declaring class will do
+
+	int declaringLevel;
+	if (isVirtualInvoke(method, messageSend) && !(messageSend.receiverType instanceof ArrayBinding)) {
+		declaringLevel = resolveLevelAsSubtype(qualifiedPattern, method.declaringClass);
+		if (declaringLevel == IMPOSSIBLE_MATCH) {
+			if (method.declaringClass == null || this.allSuperDeclaringTypeNames == null) {
+				declaringLevel = INACCURATE_MATCH;
+			} else {
+				char[][] compoundName = method.declaringClass.compoundName;
+				for (int i = 0, max = this.allSuperDeclaringTypeNames.length; i < max; i++)
+					if (CharOperation.equals(this.allSuperDeclaringTypeNames[i], compoundName))
+						return methodLevel; // since this is an ACCURATE_MATCH so return the possibly weaker match
+			}
+		}
+	} else {
+		declaringLevel = resolveLevelForType(qualifiedPattern, method.declaringClass);
+	}
+	return methodLevel > declaringLevel ? declaringLevel : methodLevel; // return the weaker match
+}
+/**
+ * Returns whether the given reference type binding matches or is a subtype of a type
+ * that matches the given qualified pattern.
+ * Returns ACCURATE_MATCH if it does.
+ * Returns INACCURATE_MATCH if resolve fails
+ * Returns IMPOSSIBLE_MATCH if it doesn't.
+ */
+protected int resolveLevelAsSubtype(char[] qualifiedPattern, ReferenceBinding type) {
+	if (type == null) return INACCURATE_MATCH;
+
+	int level = resolveLevelForType(qualifiedPattern, type);
+	if (level != IMPOSSIBLE_MATCH) return level;
+
+	// matches superclass
+	if (!type.isInterface() && !CharOperation.equals(type.compoundName, TypeConstants.JAVA_LANG_OBJECT)) {
+		level = resolveLevelAsSubtype(qualifiedPattern, type.superclass());
+		if (level != IMPOSSIBLE_MATCH) return level;
+	}
+
+	// matches interfaces
+	ReferenceBinding[] interfaces = type.superInterfaces();
+	if (interfaces == null) return INACCURATE_MATCH;
+	for (int i = 0; i < interfaces.length; i++) {
+		level = resolveLevelAsSubtype(qualifiedPattern, interfaces[i]);
+		if (level != IMPOSSIBLE_MATCH) return level;
+	}
+	return IMPOSSIBLE_MATCH;
+}
+public String toString() {
+	return "Locator for " + this.pattern.toString(); //$NON-NLS-1$
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
index 7ec1712..0671406 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
@@ -10,100 +10,195 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
 
-public abstract class MethodPattern extends SearchPattern {
+public class MethodPattern extends SearchPattern {
 
-	// selector	
-	protected char[] selector;
-	
-	// declaring type
-	protected char[] declaringQualification;
-	protected char[] declaringSimpleName;
+private static ThreadLocal indexRecord = new ThreadLocal() {
+	protected Object initialValue() {
+		return new MethodPattern(false, false, null, null, null, null, null, null, null, null, R_EXACT_MATCH | R_CASE_SENSITIVE);
+	}
+};
 
-	// return type
-	protected char[] returnQualification;
-	protected char[] returnSimpleName;
+protected boolean findDeclarations;
+protected boolean findReferences;
 
-	// parameter types
-	protected char[][] parameterQualifications;
-	protected char[][] parameterSimpleNames;
+public char[] selector;
 
-	protected char[] decodedSelector;
-	protected int decodedParameterCount;	
-public MethodPattern(int matchMode, boolean isCaseSensitive) {
-	super(matchMode, isCaseSensitive);
+public char[] declaringQualification;
+public char[] declaringSimpleName;
+
+public char[] returnQualification;
+public char[] returnSimpleName;
+
+public char[][] parameterQualifications;
+public char[][] parameterSimpleNames;
+public int parameterCount;
+
+// extra reference info
+protected IType declaringType;
+
+public static char[] createIndexKey(char[] selector, int argCount) {
+	MethodPattern record = getMethodRecord();
+	record.selector = selector;
+	record.parameterCount = argCount;
+	return record.encodeIndexKey();
 }
-public abstract String getPatternName();
-/**
- * @see SearchPattern#matchIndexEntry
- */
-protected boolean matchIndexEntry() {
+public static MethodPattern getMethodRecord() {
+	return (MethodPattern)indexRecord.get();
+}
+public MethodPattern(
+	boolean findDeclarations,
+	boolean findReferences,
+	char[] selector, 
+	char[] declaringQualification,
+	char[] declaringSimpleName,	
+	char[] returnQualification, 
+	char[] returnSimpleName,
+	char[][] parameterQualifications, 
+	char[][] parameterSimpleNames,
+	IType declaringType,
+	int matchRule) {
 
-	/* check selector matches */
-	if (selector != null){
-		switch(matchMode){
+	super(METHOD_PATTERN, matchRule);
+
+	this.findDeclarations = findDeclarations;
+	this.findReferences = findReferences;
+
+	boolean isCaseSensitive = isCaseSensitive();
+	this.selector = isCaseSensitive ? selector : CharOperation.toLowerCase(selector);
+	this.declaringQualification = isCaseSensitive ? declaringQualification : CharOperation.toLowerCase(declaringQualification);
+	this.declaringSimpleName = isCaseSensitive ? declaringSimpleName : CharOperation.toLowerCase(declaringSimpleName);
+	this.returnQualification = isCaseSensitive ? returnQualification : CharOperation.toLowerCase(returnQualification);
+	this.returnSimpleName = isCaseSensitive ? returnSimpleName : CharOperation.toLowerCase(returnSimpleName);
+	if (parameterSimpleNames != null) {
+		this.parameterCount = parameterSimpleNames.length;
+		this.parameterQualifications = new char[this.parameterCount][];
+		this.parameterSimpleNames = new char[this.parameterCount][];
+		for (int i = 0; i < this.parameterCount; i++) {
+			this.parameterQualifications[i] = isCaseSensitive ? parameterQualifications[i] : CharOperation.toLowerCase(parameterQualifications[i]);
+			this.parameterSimpleNames[i] = isCaseSensitive ? parameterSimpleNames[i] : CharOperation.toLowerCase(parameterSimpleNames[i]);
+		}
+	} else {
+		this.parameterCount = -1;
+	}
+
+	this.declaringType = declaringType;
+	this.mustResolve = mustResolve();
+}
+public void decodeIndexKey(char[] key) {
+	int size = key.length;
+	int lastSeparatorIndex = CharOperation.lastIndexOf(SEPARATOR, key);	
+
+	this.parameterCount = Integer.parseInt(new String(key, lastSeparatorIndex + 1, size - lastSeparatorIndex - 1));
+	this.selector = CharOperation.subarray(key, 0, lastSeparatorIndex);
+}
+/**
+ * Method declaration entries are encoded as 'methodDecl/' selector '/' Arity
+ * e.g. 'methodDecl/X/0'
+ *
+ * Method reference entries are encoded as 'methodRef/' selector '/' Arity
+ * e.g. 'methodRef/X/0'
+ */
+public char[] encodeIndexKey() {
+	// will have a common pattern in the new story
+	if (isCaseSensitive() && this.selector != null) {
+		switch(matchMode()) {
 			case EXACT_MATCH :
-				if (!CharOperation.equals(selector, decodedSelector, isCaseSensitive)){
-					return false;
+				int arity = this.parameterCount;
+				if (arity >= 0) {
+					char[] countChars = arity < 10 ? COUNTS[arity] : ("/" + String.valueOf(arity)).toCharArray(); //$NON-NLS-1$
+					return CharOperation.concat(this.selector, countChars);
 				}
-				break;
 			case PREFIX_MATCH :
-				if (!CharOperation.prefixEquals(selector, decodedSelector, isCaseSensitive)){
-					return false;
-				}
-				break;
+				return this.selector;
 			case PATTERN_MATCH :
-				if (!CharOperation.match(selector, decodedSelector, isCaseSensitive)){
-					return false;
+				int starPos = CharOperation.indexOf('*', this.selector);
+				switch(starPos) {
+					case -1 :
+						return this.selector;
+					default : 
+						char[] result = new char[starPos];
+						System.arraycopy(this.selector, 0, result, 0, starPos);
+						return result;
+					case 0 : // fall through
 				}
 		}
 	}
-	if (parameterSimpleNames != null){
-		if (parameterSimpleNames.length != decodedParameterCount) return false;
-	}
-	return true;
+	return CharOperation.NO_CHAR; // find them all
+}
+public SearchPattern getIndexRecord() {
+	return getMethodRecord();
+}
+public char[][] getMatchCategories() {
+	if (this.findReferences)
+		if (this.findDeclarations) 
+			return new char[][] {METHOD_REF, METHOD_DECL};
+		else
+			return new char[][] {METHOD_REF};
+	else
+		if (this.findDeclarations)
+			return new char[][] {METHOD_DECL};
+		else
+			return CharOperation.NO_CHAR_CHAR;
+}
+public boolean isPolymorphicSearch() {
+	return this.findReferences;
+}
+public boolean isMatchingIndexRecord() {
+	MethodPattern record = getMethodRecord();
+	if (this.parameterCount != -1 && this.parameterCount != record.parameterCount) return false;
+
+	return matchesName(this.selector, record.selector);
 }
 /**
- * Returns whether a method declaration or message send will need to be resolved to 
+ * Returns whether a method declaration or message send must be resolved to 
  * find out if this method pattern matches it.
  */
-protected boolean needsResolve() {
-
-	// TODO: (jerome) should need resolve only if declaringSimpleName, declaringQualification, returnQualification or parameterQualifications[i] is not null
-
-	// declaring type
+protected boolean mustResolve() {
+	// declaring type 
+	// If declaring type is specified - even with simple name - always resolves 
+	// (see MethodPattern.matchLevel)
 	if (declaringSimpleName != null || declaringQualification != null) return true;
 
 	// return type
+	// If return type is specified - even with simple name - always resolves 
+	// (see MethodPattern.matchLevel)
 	if (returnSimpleName != null || returnQualification != null) return true;
 
 	// parameter types
-	if (parameterSimpleNames != null){
-		for (int i = 0, max = parameterSimpleNames.length; i < max; i++){
-			if (parameterQualifications[i] != null || parameterSimpleNames[i] != null) return true;
-		}
-	}
+	if (parameterSimpleNames != null)
+		for (int i = 0, max = parameterSimpleNames.length; i < max; i++)
+			if (parameterQualifications[i] != null) return true;
 	return false;
 }
-public String toString(){
-
+public String toString() {
 	StringBuffer buffer = new StringBuffer(20);
-	buffer.append(this.getPatternName());
-	if (declaringQualification != null) buffer.append(declaringQualification).append('.');
+	if (this.findDeclarations) {
+		buffer.append(this.findReferences
+			? "MethodCombinedPattern: " //$NON-NLS-1$
+			: "MethodDeclarationPattern: "); //$NON-NLS-1$
+	} else {
+		buffer.append("MethodReferencePattern: "); //$NON-NLS-1$
+	}
+	if (declaringQualification != null)
+		buffer.append(declaringQualification).append('.');
 	if (declaringSimpleName != null) 
 		buffer.append(declaringSimpleName).append('.');
-	else if (declaringQualification != null) buffer.append("*."); //$NON-NLS-1$
-	if (selector != null) {
+	else if (declaringQualification != null)
+		buffer.append("*."); //$NON-NLS-1$
+
+	if (selector != null)
 		buffer.append(selector);
-	} else {
+	else
 		buffer.append("*"); //$NON-NLS-1$
-	}
 	buffer.append('(');
 	if (parameterSimpleNames == null) {
 		buffer.append("..."); //$NON-NLS-1$
 	} else {
-		for (int i = 0, max = parameterSimpleNames.length; i < max; i++){
+		for (int i = 0, max = parameterSimpleNames.length; i < max; i++) {
 			if (i > 0) buffer.append(", "); //$NON-NLS-1$
 			if (parameterQualifications[i] != null) buffer.append(parameterQualifications[i]).append('.');
 			if (parameterSimpleNames[i] == null) buffer.append('*'); else buffer.append(parameterSimpleNames[i]);
@@ -112,12 +207,14 @@
 	buffer.append(')');
 	if (returnQualification != null) 
 		buffer.append(" --> ").append(returnQualification).append('.'); //$NON-NLS-1$
-	else if (returnSimpleName != null) buffer.append(" --> "); //$NON-NLS-1$
+	else if (returnSimpleName != null)
+		buffer.append(" --> "); //$NON-NLS-1$
 	if (returnSimpleName != null) 
 		buffer.append(returnSimpleName);
-	else if (returnQualification != null) buffer.append("*"); //$NON-NLS-1$
+	else if (returnQualification != null)
+		buffer.append("*"); //$NON-NLS-1$
 	buffer.append(", "); //$NON-NLS-1$
-	switch(matchMode){
+	switch(matchMode()) {
 		case EXACT_MATCH : 
 			buffer.append("exact match, "); //$NON-NLS-1$
 			break;
@@ -128,10 +225,7 @@
 			buffer.append("pattern match, "); //$NON-NLS-1$
 			break;
 	}
-	if (isCaseSensitive)
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
+	buffer.append(isCaseSensitive() ? "case sensitive" : "case insensitive"); //$NON-NLS-1$ //$NON-NLS-2$
 	return buffer.toString();
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodReferencePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodReferencePattern.java
deleted file mode 100644
index 3b1fe82..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodReferencePattern.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.io.IOException;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.MessageSend;
-import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.indexing.AbstractIndexer;
-
-public class MethodReferencePattern extends MethodPattern {
-	IType declaringType;
-	public char[][][] allSuperDeclaringTypeNames;
-
-public MethodReferencePattern(
-	char[] selector, 
-	int matchMode, 
-	boolean isCaseSensitive,
-	char[] declaringQualification,
-	char[] declaringSimpleName,	
-	char[] returnQualification, 
-	char[] returnSimpleName,
-	char[][] parameterQualifications, 
-	char[][] parameterSimpleNames,
-	IType declaringType) {
-
-	super(matchMode, isCaseSensitive);
-	
-	this.selector = isCaseSensitive ? selector : CharOperation.toLowerCase(selector);
-	this.declaringQualification = isCaseSensitive ? declaringQualification : CharOperation.toLowerCase(declaringQualification);
-	this.declaringSimpleName = isCaseSensitive ? declaringSimpleName : CharOperation.toLowerCase(declaringSimpleName);
-	this.returnQualification = isCaseSensitive ? returnQualification : CharOperation.toLowerCase(returnQualification);
-	this.returnSimpleName = isCaseSensitive ? returnSimpleName : CharOperation.toLowerCase(returnSimpleName);
-	if (parameterSimpleNames != null){
-		this.parameterQualifications = new char[parameterSimpleNames.length][];
-		this.parameterSimpleNames = new char[parameterSimpleNames.length][];
-		for (int i = 0, max = parameterSimpleNames.length; i < max; i++){
-			this.parameterQualifications[i] = isCaseSensitive ? parameterQualifications[i] : CharOperation.toLowerCase(parameterQualifications[i]);
-			this.parameterSimpleNames[i] = isCaseSensitive ? parameterSimpleNames[i] : CharOperation.toLowerCase(parameterSimpleNames[i]);
-		}
-	}
-	this.declaringType = declaringType;
-	this.needsResolve = this.needsResolve();
-}
-public void decodeIndexEntry(IEntryResult entryResult){
-
-	char[] word = entryResult.getWord();
-	int size = word.length;
-	int lastSeparatorIndex = CharOperation.lastIndexOf(SEPARATOR, word);	
-
-	decodedParameterCount = Integer.parseInt(new String(word, lastSeparatorIndex + 1, size - lastSeparatorIndex - 1));
-	decodedSelector = CharOperation.subarray(word, METHOD_REF.length, lastSeparatorIndex);
-}
-/**
- * see SearchPattern.feedIndexRequestor
- */
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope) throws IOException {
-	for (int i = 0, max = references.length; i < max; i++) {
-		IndexedFile file = input.getIndexedFile(references[i]);
-		String path;
-		if (file != null && scope.encloses(path = IndexedFile.convertPath(file.getPath()))) {
-			requestor.acceptMethodReference(path, decodedSelector, decodedParameterCount);
-		}
-	}
-}
-public String getPatternName(){
-	return "MethodReferencePattern: "; //$NON-NLS-1$
-}
-/**
- * @see SearchPattern#indexEntryPrefix
- */
-public char[] indexEntryPrefix() {
-
-	return AbstractIndexer.bestMethodReferencePrefix(
-			selector, 
-			parameterSimpleNames == null ? -1 : parameterSimpleNames.length, 
-			matchMode, 
-			isCaseSensitive);
-}
-/**
- * @see SearchPattern#matchContainer()
- */
-protected int matchContainer() {
-	return METHOD | FIELD;
-}
-
-public void initializePolymorphicSearch(MatchLocator locator, IProgressMonitor progressMonitor) {
-	try {
-		this.allSuperDeclaringTypeNames = 
-			new SuperTypeNamesCollector(
-				this, 
-				this.declaringSimpleName,
-				this.declaringQualification,
-				locator,
-				this.declaringType, 
-				progressMonitor).collect();
-	} catch (JavaModelException e) {
-		// inaccurate matches will be found
-	}
-}
-
-public boolean isPolymorphicSearch() {
-	return true;
-}
-
-/**
- * Returns whether the code gen will use an invoke virtual for 
- * this message send or not.
- */
-private boolean isVirtualInvoke(MethodBinding method, MessageSend messageSend) {
-	return !method.isStatic() && !messageSend.isSuperAccess() && !method.isPrivate();
-}
-
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
- */
-public int matchLevel(AstNode node, boolean resolve) {
-	if (!(node instanceof MessageSend)) return IMPOSSIBLE_MATCH;
-	MessageSend messageSend = (MessageSend)node;
-
-	if (resolve) {
-		return this.matchLevel(messageSend.binding, messageSend);
-	} else {
-		// selector
-		if (this.selector != null && !this.matchesName(this.selector, messageSend.selector))
-			return IMPOSSIBLE_MATCH;
-			
-		// argument types
-		int argumentCount = this.parameterSimpleNames == null ? -1 : this.parameterSimpleNames.length;
-		if (argumentCount > -1) {
-			int parameterCount = messageSend.arguments == null ? 0 : messageSend.arguments.length;
-			if (parameterCount != argumentCount)
-				return IMPOSSIBLE_MATCH;
-		}
-
-		return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-	}
-}
-
-/**
- * @see SearchPattern#matchLevel(Binding)
- */
-public int matchLevel(Binding binding, MessageSend messageSend) {
-	if (binding == null) return INACCURATE_MATCH;
-	if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH;
-	int level;
-
-	MethodBinding method = (MethodBinding)binding;
-
-	// selector
-	if (this.selector != null && !this.matchesName(this.selector, method.selector))
-		return IMPOSSIBLE_MATCH;
-
-	// receiver type
-	ReferenceBinding receiverType = 
-		binding == null ? 
-			null : 
-			method.declaringClass;
-	if (this.isVirtualInvoke(method, messageSend) && (!(messageSend.receiverType instanceof ArrayBinding))) {
-		level = this.matchLevelAsSubtype(receiverType, this.declaringSimpleName, this.declaringQualification);
-		if (level == IMPOSSIBLE_MATCH) {
-			level = this.matchLevelForType(this.allSuperDeclaringTypeNames, receiverType);
-			if (level == IMPOSSIBLE_MATCH) {
-				return IMPOSSIBLE_MATCH;
-			}
-		}
-	} else {
-		level = this.matchLevelForType(this.declaringSimpleName, this.declaringQualification, receiverType);
-		if (level == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH;
-	}
-
-	// look at return type only if declaring type is not specified
-	if (this.declaringSimpleName == null) {
-		int newLevel = this.matchLevelForType(this.returnSimpleName, this.returnQualification, method.returnType);
-		switch (newLevel) {
-			case IMPOSSIBLE_MATCH:
-				return IMPOSSIBLE_MATCH;
-			case ACCURATE_MATCH: // keep previous level
-				break;
-			default: // ie. INACCURATE_MATCH
-				level = newLevel;
-				break;
-		}
-	}
-		
-	// argument types
-	int argumentCount = this.parameterSimpleNames == null ? -1 : this.parameterSimpleNames.length;
-	if (argumentCount > -1) {
-		if (method.parameters == null) {
-			level = INACCURATE_MATCH;
-		} else {
-			int parameterCount = method.parameters.length;
-			if (parameterCount != argumentCount) return IMPOSSIBLE_MATCH;
-			for (int i = 0; i < parameterCount; i++) {
-				char[] qualification = this.parameterQualifications[i];
-				char[] type = this.parameterSimpleNames[i];
-				int newLevel = this.matchLevelForType(type, qualification, method.parameters[i]);
-				switch (newLevel) {
-					case IMPOSSIBLE_MATCH:
-						return IMPOSSIBLE_MATCH;
-					case ACCURATE_MATCH: // keep previous level
-						break;
-					default: // ie. INACCURATE_MATCH
-						level = newLevel;
-						break;
-				}
-			}
-		}
-	}
-
-	return level;
-}
-/**
- * @see SearchPattern#matchReportReference
- */
-protected void matchReportReference(AstNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	if (reference instanceof MessageSend) {
-		// message ref are starting at the selector start
-		locator.report(
-			(int) (((MessageSend) reference).nameSourcePosition >> 32),
-			reference.sourceEnd,
-			element,
-			accuracy);
-	} else {
-		super.matchReportReference(reference, element, accuracy, locator);
-	}
-	
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MultipleSearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MultipleSearchPattern.java
deleted file mode 100644
index 3eb43bc..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MultipleSearchPattern.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.io.IOException;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-
-public abstract class MultipleSearchPattern extends AndPattern {
-
-	protected char[] currentTag;
-	public boolean foundAmbiguousIndexMatches = false;	
-public MultipleSearchPattern(int matchMode, boolean isCaseSensitive) {
-	super(matchMode, isCaseSensitive);
-}
-/**
- * Query a given index for matching entries. 
- */
-public void findIndexMatches(IndexInput input, IIndexSearchRequestor requestor, int detailLevel, IProgressMonitor progressMonitor, IJavaSearchScope scope) throws IOException {
-
-	char[][] possibleTags = getPossibleTags();
-	
-	if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
-
-	/* narrow down a set of entries using prefix criteria */
-	for (int i = 0, max = possibleTags.length; i < max; i++){
-		currentTag = possibleTags[i];
-		super.findIndexMatches(input, requestor, detailLevel, progressMonitor, scope);
-	}
-}
-protected abstract char[][] getPossibleTags();
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrLocator.java
new file mode 100644
index 0000000..ba19fa1
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrLocator.java
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+
+public class OrLocator extends PatternLocator {
+
+protected PatternLocator[] patternLocators;
+
+public OrLocator(OrPattern pattern) {
+	super(pattern);
+
+	SearchPattern[] patterns = pattern.patterns;
+	int length = patterns.length;
+	this.patternLocators = new PatternLocator[length];
+	for (int i = 0; i < length; i++)
+		this.patternLocators[i] = PatternLocator.patternLocator(patterns[i]);
+}
+public void initializePolymorphicSearch(MatchLocator locator) {
+	for (int i = 0, length = this.patternLocators.length; i < length; i++)
+		this.patternLocators[i].initializePolymorphicSearch(locator);
+}
+public int match(ASTNode node, MatchingNodeSet nodeSet) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].match(node, nodeSet);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel;
+		}
+	}
+	return level;
+}
+public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].match(node, nodeSet);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel;
+		}
+	}
+	return level;
+}
+public int match(Expression node, MatchingNodeSet nodeSet) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].match(node, nodeSet);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel;
+		}
+	}
+	return level;
+}
+public int match(FieldDeclaration node, MatchingNodeSet nodeSet) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].match(node, nodeSet);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel;
+		}
+	}
+	return level;
+}
+public int match(LocalDeclaration node, MatchingNodeSet nodeSet) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].match(node, nodeSet);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel;
+		}
+	}
+	return level;
+}
+public int match(MethodDeclaration node, MatchingNodeSet nodeSet) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].match(node, nodeSet);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel;
+		}
+	}
+	return level;
+}
+public int match(MessageSend node, MatchingNodeSet nodeSet) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].match(node, nodeSet);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel;
+		}
+	}
+	return level;
+}
+public int match(Reference node, MatchingNodeSet nodeSet) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].match(node, nodeSet);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel;
+		}
+	}
+	return level;
+}
+public int match(TypeDeclaration node, MatchingNodeSet nodeSet) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].match(node, nodeSet);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel;
+		}
+	}
+	return level;
+}
+public int match(TypeReference node, MatchingNodeSet nodeSet) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].match(node, nodeSet);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel;
+		}
+	}
+	return level;
+}
+protected int matchContainer() {
+	int result = 0;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++)
+		result |= this.patternLocators[i].matchContainer();
+	return result;
+}
+protected void matchLevelAndReportImportRef(ImportReference importRef, Binding binding, MatchLocator locator) throws CoreException {
+	PatternLocator closestPattern = null;
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].resolveLevel(binding);
+		if (newLevel > level) {
+			closestPattern = this.patternLocators[i];
+			if (newLevel == ACCURATE_MATCH) break;
+			level = newLevel;
+		}
+	}
+	if (closestPattern != null)
+		closestPattern.matchLevelAndReportImportRef(importRef, binding, locator);
+}
+protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	PatternLocator closestPattern = null;
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].matchLevel(importRef);
+		if (newLevel > level) {
+			closestPattern = this.patternLocators[i];
+			if (newLevel == ACCURATE_MATCH) break;
+			level = newLevel;
+		}
+	}
+	if (closestPattern != null)
+		closestPattern.matchReportImportRef(importRef, binding, element, accuracy, locator);
+}
+protected void matchReportReference(ASTNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	PatternLocator closestPattern = null;
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].resolveLevel(reference);
+		if (newLevel > level) {
+			closestPattern = this.patternLocators[i];
+			if (newLevel == ACCURATE_MATCH) break;
+			level = newLevel;
+		}
+	}
+	if (closestPattern != null)
+		closestPattern.matchReportReference(reference, element, accuracy, locator);
+}
+public int resolveLevel(ASTNode node) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].resolveLevel(node);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel; // want to answer the stronger match
+		}
+	}
+	return level;
+}
+public int resolveLevel(Binding binding) {
+	int level = IMPOSSIBLE_MATCH;
+	for (int i = 0, length = this.patternLocators.length; i < length; i++) {
+		int newLevel = this.patternLocators[i].resolveLevel(binding);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel; // want to answer the stronger match
+		}
+	}
+	return level;
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrNameCombiner.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrNameCombiner.java
deleted file mode 100644
index 27a1173..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrNameCombiner.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-
-public class OrNameCombiner implements IIndexSearchRequestor {
-
-	IIndexSearchRequestor targetRequestor;
-	HashtableOfObject acceptedAnswers = new HashtableOfObject(5);
-		
-public OrNameCombiner(IIndexSearchRequestor targetRequestor){
-	this.targetRequestor = targetRequestor;
-}
-public void acceptClassDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName){
-
-	if (!this.acceptedAnswers.containsKey(CharOperation.concat(packageName, simpleTypeName, '.'))){
-		this.targetRequestor.acceptClassDeclaration(resourcePath, simpleTypeName, enclosingTypeNames, packageName);
-	}
-}
-public void acceptConstructorDeclaration(String resourcePath, char[] typeName, int parameterCount) {}
-public void acceptConstructorReference(String resourcePath, char[] typeName, int parameterCount) {}
-public void acceptFieldDeclaration(String resourcePath, char[] fieldName) {}
-public void acceptFieldReference(String resourcePath, char[] fieldName) {}
-public void acceptInterfaceDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) {}
-public void acceptMethodDeclaration(String resourcePath, char[] methodName, int parameterCount) {}
-public void acceptMethodReference(String resourcePath, char[] methodName, int parameterCount) {}
-public void acceptPackageReference(String resourcePath, char[] packageName) {}
-public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char[] enclosingTypeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers){
-}
-public void acceptTypeReference(String resourcePath, char[] typeName) {}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPathCombiner.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPathCombiner.java
deleted file mode 100644
index aa0a817..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPathCombiner.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.util.HashSet;
-
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-
-public class OrPathCombiner implements IIndexSearchRequestor {
-
-	IIndexSearchRequestor targetRequestor;
-	HashSet acceptedAnswers = new HashSet(5);
-public OrPathCombiner(IIndexSearchRequestor targetRequestor){
-	this.targetRequestor = targetRequestor;
-}
-public void acceptClassDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName){
-
-	if (this.acceptedAnswers.add(resourcePath)){
-		this.targetRequestor.acceptClassDeclaration(resourcePath, simpleTypeName, enclosingTypeNames, packageName);
-	}
-}
-public void acceptConstructorDeclaration(String resourcePath, char[] typeName, int parameterCount) {
-	if (this.acceptedAnswers.add(resourcePath)){
-		this.targetRequestor.acceptConstructorDeclaration(resourcePath, typeName, parameterCount);
-	}		
-}
-public void acceptConstructorReference(String resourcePath, char[] typeName, int parameterCount) {
-	if (this.acceptedAnswers.add(resourcePath)){
-		this.targetRequestor.acceptConstructorReference(resourcePath, typeName, parameterCount);
-	}			
-}
-public void acceptFieldDeclaration(String resourcePath, char[] fieldName) {
-	if (this.acceptedAnswers.add(resourcePath)){
-		this.targetRequestor.acceptFieldDeclaration(resourcePath, fieldName);
-	}	
-}
-public void acceptFieldReference(String resourcePath, char[] fieldName) {
-	if (this.acceptedAnswers.add(resourcePath)){
-		this.targetRequestor.acceptFieldReference(resourcePath, fieldName);
-	}		
-}
-public void acceptInterfaceDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) {
-	if (this.acceptedAnswers.add(resourcePath)){
-		this.targetRequestor.acceptInterfaceDeclaration(resourcePath, simpleTypeName, enclosingTypeNames, packageName);
-	}		
-}
-public void acceptMethodDeclaration(String resourcePath, char[] methodName, int parameterCount) {
-	if (this.acceptedAnswers.add(resourcePath)){
-		this.targetRequestor.acceptMethodDeclaration(resourcePath, methodName, parameterCount);
-	}		
-}
-public void acceptMethodReference(String resourcePath, char[] methodName, int parameterCount) {
-	if (this.acceptedAnswers.add(resourcePath)){
-		this.targetRequestor.acceptMethodReference(resourcePath, methodName, parameterCount);
-	}			
-}
-public void acceptPackageReference(String resourcePath, char[] packageName) {
-	if (this.acceptedAnswers.add(resourcePath)){
-		this.targetRequestor.acceptPackageReference(resourcePath, packageName);
-	}	
-}
-public void acceptSuperTypeReference(String resourcePath, char[] qualification, char[] typeName, char[] enclosingTypeName, char classOrInterface, char[] superQualification, char[] superTypeName, char superClassOrInterface, int modifiers){
-	if (this.acceptedAnswers.add(resourcePath)){
-		this.targetRequestor.acceptSuperTypeReference(resourcePath, qualification, typeName, enclosingTypeName, classOrInterface, superQualification, superTypeName, superClassOrInterface, modifiers);
-	}
-}
-public void acceptTypeReference(String resourcePath, char[] typeName) {
-	if (this.acceptedAnswers.add(resourcePath)){
-		this.targetRequestor.acceptTypeReference(resourcePath, typeName);
-	}
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPattern.java
index 84c6caa..8df1a85 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/OrPattern.java
@@ -12,166 +12,92 @@
 
 import java.io.IOException;
 
-import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
+import org.eclipse.jdt.core.search.SearchParticipant;
 import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.IInfoConstants;
+import org.eclipse.jdt.internal.core.search.IndexQueryRequestor;
 
 public class OrPattern extends SearchPattern {
 
-	public SearchPattern leftPattern;
-	public SearchPattern rightPattern;
+protected SearchPattern[] patterns;
+
 public OrPattern(SearchPattern leftPattern, SearchPattern rightPattern) {
-	super(-1, false); // values ignored for a OrPattern
-		
-	this.leftPattern = leftPattern;
-	this.rightPattern = rightPattern;
+	super(OR_PATTERN, Math.max(leftPattern.matchRule, rightPattern.matchRule));
+	this.mustResolve = leftPattern.mustResolve || rightPattern.mustResolve;
 
-	this.matchMode = Math.min(leftPattern.matchMode, rightPattern.matchMode);
-	this.isCaseSensitive = leftPattern.isCaseSensitive || rightPattern.isCaseSensitive;
-	this.needsResolve = leftPattern.needsResolve || rightPattern.needsResolve;
+	SearchPattern[] leftPatterns = leftPattern instanceof OrPattern ? ((OrPattern) leftPattern).patterns : null;
+	SearchPattern[] rightPatterns = rightPattern instanceof OrPattern ? ((OrPattern) rightPattern).patterns : null;
+	int leftSize = leftPatterns == null ? 1 : leftPatterns.length;
+	int rightSize = rightPatterns == null ? 1 : rightPatterns.length;
+	this.patterns = new SearchPattern[leftSize + rightSize];
+
+	if (leftPatterns == null)
+		this.patterns[0] = leftPattern;
+	else
+		System.arraycopy(leftPatterns, 0, this.patterns, 0, leftSize);
+	if (rightPatterns == null)
+		this.patterns[leftSize] = rightPattern;
+	else
+		System.arraycopy(rightPatterns, 0, this.patterns, leftSize, rightSize);
 }
-/**
- * see SearchPattern.decodedIndexEntry
- */
-protected void decodeIndexEntry(IEntryResult entry) {
 
-	// will never be directly invoked on a composite pattern
+public void decodeIndexKey(char[] key) {
+	// not used for OrPattern
 }
-/**
- * see SearchPattern.feedIndexRequestor
- */
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope)  throws IOException {
-	// will never be directly invoked on a composite pattern
-}
-/**
- * see SearchPattern.findMatches
- */
-public void findIndexMatches(IndexInput input, IIndexSearchRequestor requestor, int detailLevel, IProgressMonitor progressMonitor, IJavaSearchScope scope) throws IOException {
 
-	if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
-
-	IIndexSearchRequestor orCombiner;
-	if (detailLevel == IInfoConstants.NameInfo) {
-		orCombiner = new OrNameCombiner(requestor);
-	} else {
-		orCombiner = new OrPathCombiner(requestor);
-	}
-	leftPattern.findIndexMatches(input, orCombiner, detailLevel, progressMonitor, scope);
-	if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
-	rightPattern.findIndexMatches(input, orCombiner, detailLevel, progressMonitor, scope);
-}
-/**
- * see SearchPattern.indexEntryPrefix
- */
-public char[] indexEntryPrefix() {
-
-	// will never be directly invoked on a composite pattern
+public char[] encodeIndexKey() {
+	// not used for OrPattern
 	return null;
 }
-/**
- * @see SearchPattern#matchContainer()
- */
-protected int matchContainer() {
-	return leftPattern.matchContainer()
-			| rightPattern.matchContainer();
-}
-/**
- * @see SearchPattern#matchesBinary
- */
-public boolean matchesBinary(Object binaryInfo, Object enclosingBinaryInfo) {
-	return this.leftPattern.matchesBinary(binaryInfo, enclosingBinaryInfo) 
-		|| this.rightPattern.matchesBinary(binaryInfo, enclosingBinaryInfo);
-}
-/**
- * @see SearchPattern#matchIndexEntry
- */
-protected boolean matchIndexEntry() {
-
-	return this.leftPattern.matchIndexEntry()
-			|| this.rightPattern.matchIndexEntry();
-}
-/**
- * @see SearchPattern#matchReportReference
- */
-protected void matchReportReference(AstNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	int leftLevel = this.leftPattern.matchLevel(reference, true);
-	if (leftLevel == ACCURATE_MATCH || leftLevel == INACCURATE_MATCH) {
-		this.leftPattern.matchReportReference(reference, element, accuracy, locator);
-	} else {
-		this.rightPattern.matchReportReference(reference, element, accuracy, locator);
-	}
-}
-public String toString(){
-	return this.leftPattern.toString() + "\n| " + this.rightPattern.toString(); //$NON-NLS-1$
-}
 
 /**
- * see SearchPattern.initializePolymorphicSearch
+ * Query a given index for matching entries. 
+ *
  */
-public void initializePolymorphicSearch(MatchLocator locator, IProgressMonitor progressMonitor) {
+public void findIndexMatches(IndexInput input, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope, IProgressMonitor progressMonitor) throws IOException {
+	// per construction, OR pattern can only be used with a PathCollector (which already gather results using a set)
+	for (int i = 0, length = this.patterns.length; i < length; i++)
+		this.patterns[i].findIndexMatches(input, requestor, participant, scope, progressMonitor);
+}
 
-	this.leftPattern.initializePolymorphicSearch(locator, progressMonitor);
-	this.rightPattern.initializePolymorphicSearch(locator, progressMonitor);
+public SearchPattern getIndexRecord() {
+	// not used for OrPattern
+	return null;
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.core.search.pattern.InternalSearchPattern#isMatchingIndexEntry()
+ */
+public boolean isMatchingIndexRecord() {
+	return false;
 }
 
 /**
  * see SearchPattern.isPolymorphicSearch
  */
 public boolean isPolymorphicSearch() {
-	return this.leftPattern.isPolymorphicSearch() || this.rightPattern.isPolymorphicSearch();
+	for (int i = 0, length = this.patterns.length; i < length; i++)
+		if (this.patterns[i].isPolymorphicSearch()) return true;
+	return false;
 }
 
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.core.search.pattern.InternalSearchPattern#getMatchCategories()
  */
-public int matchLevel(AstNode node, boolean resolve) {
-	switch (this.leftPattern.matchLevel(node, resolve)) {
-		case IMPOSSIBLE_MATCH:
-			return this.rightPattern.matchLevel(node, resolve);
-		case POSSIBLE_MATCH:
-			return POSSIBLE_MATCH;
-		case INACCURATE_MATCH:
-			int rightLevel = this.rightPattern.matchLevel(node, resolve);
-			if (rightLevel != IMPOSSIBLE_MATCH) {
-				return rightLevel;
-			} else {
-				return INACCURATE_MATCH;
-			}
-		case ACCURATE_MATCH:
-			return ACCURATE_MATCH;
-		default:
-			return IMPOSSIBLE_MATCH;
-	}
+public char[][] getMatchCategories() {
+	return CharOperation.NO_CHAR_CHAR;
 }
 
-/**
- * @see SearchPattern#matchLevel(Binding)
- */
-public int matchLevel(Binding binding) {
-	switch (this.leftPattern.matchLevel(binding)) {
-		case IMPOSSIBLE_MATCH:
-			return this.rightPattern.matchLevel(binding);
-		case POSSIBLE_MATCH:
-			return POSSIBLE_MATCH;
-		case INACCURATE_MATCH:
-			int rightLevel = this.rightPattern.matchLevel(binding);
-			if (rightLevel != IMPOSSIBLE_MATCH) {
-				return rightLevel;
-			} else {
-				return INACCURATE_MATCH;
-			}
-		case ACCURATE_MATCH:
-			return ACCURATE_MATCH;
-		default:
-			return IMPOSSIBLE_MATCH;
+public String toString() {
+	StringBuffer buffer = new StringBuffer();
+	buffer.append(this.patterns[0].toString());
+	for (int i = 1, length = this.patterns.length; i < length; i++) {
+		buffer.append("\n| "); //$NON-NLS-1$
+		buffer.append(this.patterns[i].toString());
 	}
+	return buffer.toString();
 }
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageDeclarationLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageDeclarationLocator.java
new file mode 100644
index 0000000..d4e163b
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageDeclarationLocator.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+public class PackageDeclarationLocator extends PatternLocator {
+
+protected PackageDeclarationPattern pattern;
+
+public PackageDeclarationLocator(PackageDeclarationPattern pattern) {
+	super(pattern);
+
+	this.pattern = pattern;
+}
+protected int matchContainer() {
+	return 0;
+}
+public String toString() {
+	return "Locator for " + this.pattern.toString(); //$NON-NLS-1$
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageDeclarationPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageDeclarationPattern.java
index 002c252..5f71f88 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageDeclarationPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageDeclarationPattern.java
@@ -10,66 +10,53 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
-import java.io.IOException;
-
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
 import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
+import org.eclipse.jdt.core.search.SearchParticipant;
 import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
+import org.eclipse.jdt.internal.core.search.IndexQueryRequestor;
 
 public class PackageDeclarationPattern extends SearchPattern {
-	char[] pkgName;
-public PackageDeclarationPattern(char[] pkgName, int matchMode, boolean isCaseSensitive) {
-	super(matchMode, isCaseSensitive);
+
+protected char[] pkgName;
+
+public PackageDeclarationPattern(char[] pkgName, int matchRule) {
+	super(PKG_DECL_PATTERN, matchRule);
 	this.pkgName = pkgName;
 }
-/**
- * @see SearchPattern#decodeIndexEntry
- */
-protected void decodeIndexEntry(IEntryResult entryResult) {
-	// not used
-}
-/**
- * @see SearchPattern#feedIndexRequestor
- */
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope) throws java.io.IOException {
-	// not used
-}
-/**
- * see SearchPattern#findMatches
- */
-public void findIndexMatches(IndexInput input, IIndexSearchRequestor requestor, int detailLevel, IProgressMonitor progressMonitor, IJavaSearchScope scope) throws IOException {
+public void decodeIndexKey(char[] key) {
 	// package declarations are not indexed
 }
-/**
- * @see SearchPattern#indexEntryPrefix
- */
-public char[] indexEntryPrefix() {
-	// not used
+public char[] encodeIndexKey() {
+	// package declarations are not indexed
 	return null;
 }
-/**
- * @see SearchPattern#matchContainer
- */
-protected int matchContainer() {
-	// used only in the case of a OrPattern
-	return 0;
+public void findIndexMatches(IndexInput input, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope, IProgressMonitor progressMonitor) /* throws IOException */ {
+	// package declarations are not indexed
 }
-/**
- * @see SearchPattern#matchIndexEntry
- */
-protected boolean matchIndexEntry() {
-	// used only in the case of a OrPattern
-	return true;
+public SearchPattern getIndexRecord() {
+	// package declarations are not indexed
+	return null;
 }
-public String toString(){
+public char[][] getMatchCategories() {
+	// package declarations are not indexed
+	return CharOperation.NO_CHAR_CHAR;
+}
+public boolean isMatchingIndexRecord() {
+	// package declarations are not indexed
+	return false;
+}
+public String toString() {
 	StringBuffer buffer = new StringBuffer(20);
 	buffer.append("PackageDeclarationPattern: <"); //$NON-NLS-1$
-	if (this.pkgName != null) buffer.append(this.pkgName);
+	if (this.pkgName != null) 
+		buffer.append(this.pkgName);
+	else
+		buffer.append("*"); //$NON-NLS-1$
 	buffer.append(">, "); //$NON-NLS-1$
-	switch(matchMode){
+	switch(matchMode()){
 		case EXACT_MATCH : 
 			buffer.append("exact match, "); //$NON-NLS-1$
 			break;
@@ -80,18 +67,10 @@
 			buffer.append("pattern match, "); //$NON-NLS-1$
 			break;
 	}
-	if (isCaseSensitive)
+	if (isCaseSensitive())
 		buffer.append("case sensitive"); //$NON-NLS-1$
 	else
 		buffer.append("case insensitive"); //$NON-NLS-1$
 	return buffer.toString();
 }
-
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
- */
-public int matchLevel(AstNode node, boolean resolve) {
-	// used only in the case of a OrPattern
-	return ACCURATE_MATCH;
-}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java
new file mode 100644
index 0000000..7277c8f
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferenceLocator.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.runtime.CoreException;
+
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class PackageReferenceLocator extends PatternLocator {
+
+protected PackageReferencePattern pattern;
+	
+public PackageReferenceLocator(PackageReferencePattern pattern) {
+	super(pattern);
+
+	this.pattern = pattern;
+}
+// check that referenced type is actually defined in this package fragment
+public boolean isDeclaringPackageFragment(IPackageFragment packageFragment, ReferenceBinding typeBinding) {
+	char[] fileName = typeBinding.getFileName();
+	if (fileName != null) {
+		// retrieve the actual file name from the full path (sources are generally only containing it already)
+		CharOperation.replace(fileName, '/', '\\');
+		fileName = CharOperation.lastSegment(fileName, '\\');
+		
+		try { 
+			switch (packageFragment.getKind()) {
+				case IPackageFragmentRoot.K_SOURCE :
+					if (!Util.isJavaFileName(fileName) || !packageFragment.getCompilationUnit(new String(fileName)).exists()) {
+						return false; // unit doesn't live in selected package
+					}
+					break;
+				case IPackageFragmentRoot.K_BINARY :
+//					if (Util.isJavaFileName(fileName)) { // binary with attached source
+//						int length = fileName.length;
+//						System.arraycopy(fileName, 0, fileName = new char[length], 0, length - 4); // copy all but extension
+//						System.arraycopy(SuffixConstants.SUFFIX_class, 0, fileName, length - 4, 4);
+//					}
+					if (!Util.isClassFileName(fileName) || !packageFragment.getClassFile(new String(fileName)).exists()) {
+						return false; // classfile doesn't live in selected package
+					}
+					break;
+			}
+		} catch(JavaModelException e) {
+			// unable to determine kind; tolerate this match
+		}
+	}
+	return true; // by default, do not eliminate 
+}
+public int match(ASTNode node, MatchingNodeSet nodeSet) { // interested in ImportReference
+	if (!(node instanceof ImportReference)) return IMPOSSIBLE_MATCH;
+
+	return nodeSet.addMatch(node, matchLevel((ImportReference) node));
+}
+//public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(Expression node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(FieldDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(MethodDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(MessageSend node, MatchingNodeSet nodeSet) - SKIP IT
+public int match(Reference node, MatchingNodeSet nodeSet) { // interested in QualifiedNameReference
+	if (!(node instanceof QualifiedNameReference)) return IMPOSSIBLE_MATCH;
+
+	return nodeSet.addMatch(node, matchLevelForTokens(((QualifiedNameReference) node).tokens));
+}
+//public int match(TypeDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+public int match(TypeReference node, MatchingNodeSet nodeSet) { // interested in QualifiedTypeReference only
+	if (!(node instanceof QualifiedTypeReference)) return IMPOSSIBLE_MATCH;
+
+	return nodeSet.addMatch(node, matchLevelForTokens(((QualifiedTypeReference) node).tokens));
+}
+
+protected int matchLevel(ImportReference importRef) {
+	if (!importRef.onDemand)
+		return matchLevelForTokens(importRef.tokens);
+
+	return matchesName(this.pattern.pkgName, CharOperation.concatWith(importRef.tokens, '.'))
+		? ACCURATE_MATCH
+		: IMPOSSIBLE_MATCH;
+}
+protected int matchLevelForTokens(char[][] tokens) {
+	if (this.pattern.pkgName == null) return ACCURATE_MATCH;
+
+	switch (this.matchMode) {
+		case IJavaSearchConstants.EXACT_MATCH:
+		case IJavaSearchConstants.PREFIX_MATCH:
+			if (CharOperation.prefixEquals(this.pattern.pkgName, CharOperation.concatWith(tokens, '.'), this.isCaseSensitive))
+				return POSSIBLE_MATCH;
+			break;
+		case IJavaSearchConstants.PATTERN_MATCH:
+			char[] patternName = this.pattern.pkgName[this.pattern.pkgName.length - 1] == '*'
+				? this.pattern.pkgName
+				: CharOperation.concat(this.pattern.pkgName, ".*".toCharArray()); //$NON-NLS-1$
+			if (CharOperation.match(patternName, CharOperation.concatWith(tokens, '.'), this.isCaseSensitive))
+				return POSSIBLE_MATCH;
+			break;
+	}
+	return IMPOSSIBLE_MATCH;
+}
+protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	if (binding == null) {
+		this.matchReportReference(importRef, element, accuracy, locator);
+	} else {
+		long[] positions = importRef.sourcePositions;
+		int last = positions.length - 1;
+		if (binding instanceof ProblemReferenceBinding)
+			binding = ((ProblemReferenceBinding) binding).original;
+		if (binding instanceof ReferenceBinding) {
+			PackageBinding pkgBinding = ((ReferenceBinding) binding).fPackage;
+			if (pkgBinding != null)
+				last = pkgBinding.compoundName.length;
+		}
+		locator.report(positions[0], positions[last - 1], element, accuracy);
+	}
+}
+protected void matchReportReference(ASTNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	long[] positions = null;
+	int last = -1;
+	if (reference instanceof ImportReference) {
+		ImportReference importRef = (ImportReference) reference;
+		positions = importRef.sourcePositions;
+		last = importRef.onDemand ? positions.length : positions.length - 1;
+	} else {
+		TypeBinding typeBinding = null;
+		if (reference instanceof QualifiedNameReference) {
+			QualifiedNameReference qNameRef = (QualifiedNameReference) reference;
+			positions = qNameRef.sourcePositions;
+			switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
+				case BindingIds.FIELD : // reading a field
+					typeBinding = qNameRef.actualReceiverType;
+					break;
+				case BindingIds.TYPE : //=============only type ==============
+					if (qNameRef.binding instanceof TypeBinding)
+						typeBinding = (TypeBinding) qNameRef.binding;
+					break;
+				case BindingIds.VARIABLE : //============unbound cases===========
+				case BindingIds.TYPE | BindingIds.VARIABLE :
+					Binding binding = qNameRef.binding; 
+					if (binding instanceof TypeBinding) {
+						typeBinding = (TypeBinding) binding;
+					} else if (binding instanceof ProblemFieldBinding) {
+						typeBinding = qNameRef.actualReceiverType;
+						last = qNameRef.tokens.length - (qNameRef.otherBindings == null ? 2 : qNameRef.otherBindings.length + 2);
+					} else if (binding instanceof ProblemBinding) {
+						ProblemBinding pbBinding = (ProblemBinding) binding;
+						typeBinding = pbBinding.searchType;
+						last = CharOperation.occurencesOf('.', pbBinding.name);
+					}
+					break;					
+			}
+		} else if (reference instanceof QualifiedTypeReference) {
+			QualifiedTypeReference qTypeRef = (QualifiedTypeReference) reference;
+			positions = qTypeRef.sourcePositions;
+			typeBinding = qTypeRef.resolvedType;
+		}
+		if (typeBinding instanceof ArrayBinding)
+			typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
+		if (typeBinding instanceof ProblemReferenceBinding)
+			typeBinding = ((ProblemReferenceBinding) typeBinding).original;
+		if (typeBinding instanceof ReferenceBinding) {
+			PackageBinding pkgBinding = ((ReferenceBinding) typeBinding).fPackage;
+			if (pkgBinding != null)
+				last = pkgBinding.compoundName.length;
+		}
+	}
+	if (last == -1) {
+		last = this.pattern.segments.length;
+		if (last > positions.length) last = positions.length;
+	}
+	locator.report(positions[0], positions[last - 1], element, accuracy);
+}
+public int resolveLevel(ASTNode node) {
+	if (node instanceof QualifiedTypeReference)
+		return resolveLevel(((QualifiedTypeReference) node).resolvedType);
+	if (node instanceof QualifiedNameReference)
+		return this.resolveLevel((QualifiedNameReference) node);
+//	if (node instanceof ImportReference) - Not called when resolve is true, see MatchingNodeSet.reportMatching(unit)
+	return IMPOSSIBLE_MATCH;
+}
+public int resolveLevel(Binding binding) {
+	if (binding == null) return INACCURATE_MATCH;
+
+	char[][] compoundName = null;
+	if (binding instanceof ImportBinding) {
+		compoundName = ((ImportBinding) binding).compoundName;
+	} else {
+		if (binding instanceof ArrayBinding)
+			binding = ((ArrayBinding) binding).leafComponentType;
+		if (binding instanceof ProblemReferenceBinding)
+			binding = ((ProblemReferenceBinding) binding).original;
+		if (binding == null) return INACCURATE_MATCH;
+
+		if (binding instanceof ReferenceBinding) {
+			PackageBinding pkgBinding = ((ReferenceBinding) binding).fPackage;
+			if (pkgBinding == null) return INACCURATE_MATCH;
+			compoundName = pkgBinding.compoundName;
+		}
+	}
+	if (compoundName != null && matchesName(this.pattern.pkgName, CharOperation.concatWith(compoundName, '.'))) {
+		if (this.pattern.focus instanceof IPackageFragment && binding instanceof ReferenceBinding) {
+			// check that type is located inside this instance of a package fragment
+			if (!isDeclaringPackageFragment((IPackageFragment)this.pattern.focus, (ReferenceBinding)binding)) return IMPOSSIBLE_MATCH;
+		}				
+		return ACCURATE_MATCH;
+	} else {
+		return IMPOSSIBLE_MATCH;
+	}
+}
+protected int resolveLevel(QualifiedNameReference qNameRef) {
+	TypeBinding typeBinding = null;
+	switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
+		case BindingIds.FIELD : // reading a field
+			if (qNameRef.tokens.length < (qNameRef.otherBindings == null ? 3 : qNameRef.otherBindings.length + 3))
+				return IMPOSSIBLE_MATCH; // must be at least p1.A.x
+			typeBinding = qNameRef.actualReceiverType;
+			break;
+		case BindingIds.LOCAL : // reading a local variable
+			return IMPOSSIBLE_MATCH; // no package match in it
+		case BindingIds.TYPE : //=============only type ==============
+			if (qNameRef.binding instanceof TypeBinding)
+				typeBinding = (TypeBinding) qNameRef.binding;
+			break;
+		/*
+		 * Handling of unbound qualified name references. The match may reside in the resolved fragment,
+		 * which is recorded inside the problem binding, along with the portion of the name until it became a problem.
+		 */
+		case BindingIds.VARIABLE : //============unbound cases===========
+		case BindingIds.TYPE | BindingIds.VARIABLE :
+			Binding binding = qNameRef.binding; 
+			if (binding instanceof ProblemReferenceBinding) {
+				typeBinding = (TypeBinding) binding;
+			} else if (binding instanceof ProblemFieldBinding) {
+				if (qNameRef.tokens.length < (qNameRef.otherBindings == null ? 3 : qNameRef.otherBindings.length + 3))
+					return IMPOSSIBLE_MATCH; // must be at least p1.A.x
+				typeBinding = qNameRef.actualReceiverType;
+			} else if (binding instanceof ProblemBinding) {
+				ProblemBinding pbBinding = (ProblemBinding) binding;
+				if (CharOperation.occurencesOf('.', pbBinding.name) <= 0) // index of last bound token is one before the pb token
+					return INACCURATE_MATCH;
+				typeBinding = pbBinding.searchType;
+			}
+			break;					
+	}
+	return resolveLevel(typeBinding);
+}
+public String toString() {
+	return "Locator for " + this.pattern.toString(); //$NON-NLS-1$
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferencePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferencePattern.java
index 20ead4a..28cc5b6 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferencePattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PackageReferencePattern.java
@@ -10,196 +10,67 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
-import java.io.IOException;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.BindingIds;
-import org.eclipse.jdt.internal.compiler.lookup.ImportBinding;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.indexing.AbstractIndexer;
+import org.eclipse.jdt.core.search.*;
 
 public class PackageReferencePattern extends AndPattern {
-	private static char[][] TAGS = { REF };
-	private char[] pkgName;
 
-	private char[][] segments;
-	private int currentSegment;
-	private char[] decodedSegment;
+private static ThreadLocal indexRecord = new ThreadLocal() {
+	protected Object initialValue() {
+		return new PackageReferencePattern("*".toCharArray(), R_EXACT_MATCH | R_CASE_SENSITIVE); //$NON-NLS-1$;
+	}
+};
+
+protected char[] pkgName;
+
+protected char[][] segments;
+protected int currentSegment;
+
+public static PackageReferencePattern getPackageReferenceRecord() {
+	return (PackageReferencePattern)indexRecord.get();
+}
 	
-public PackageReferencePattern(char[] pkgName, int matchMode, boolean isCaseSensitive) {
-	super(matchMode, isCaseSensitive);
-	if (!isCaseSensitive) {
-		pkgName = CharOperation.toLowerCase(pkgName);
-	}
-	this.pkgName = pkgName;
-	char[][] splittedName = CharOperation.splitOn('.', pkgName);
-	this.segments = splittedName == CharOperation.NO_CHAR_CHAR ? new char[][]{ pkgName } : splittedName;
-	this.needsResolve = pkgName != null;
-}
-/**
- * ref/name (where name is the last segment of the package name)
- */ 
-public void decodeIndexEntry(IEntryResult entryResult){
+public PackageReferencePattern(char[] pkgName, int matchRule) {
+	super(PKG_REF_PATTERN, matchRule);
 
-	char[] word = entryResult.getWord();
-	int size = word.length;
-	int tagLength = REF.length;
-	int nameLength = CharOperation.indexOf(SEPARATOR, word, tagLength);
-	if (nameLength < 0) nameLength = size;
-	this.decodedSegment = CharOperation.subarray(word, tagLength, nameLength);
-}
-/**
- * @see SearchPattern#feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope)
- */
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope) throws IOException {
-	for (int i = 0, max = references.length; i < max; i++) {
-		int reference = references[i];
-		if (reference != -1) { // if the reference has not been eliminated
-			IndexedFile file = input.getIndexedFile(reference);
-			String path;
-			if (file != null && scope.encloses(path = IndexedFile.convertPath(file.getPath()))) {
-				requestor.acceptPackageReference(path, this.pkgName);
-			}
-		}
+	if (pkgName == null || pkgName.length == 0) {
+		this.pkgName = null;
+		this.segments = new char[][] {CharOperation.NO_CHAR};
+		this.mustResolve = false;
+	} else {
+		this.pkgName = isCaseSensitive() ? pkgName : CharOperation.toLowerCase(pkgName);
+		this.segments = CharOperation.splitOn('.', this.pkgName);
+		this.mustResolve = true;
 	}
 }
-protected char[][] getPossibleTags() {
-	return TAGS;
+public void decodeIndexKey(char[] key) {
+	// Package reference keys are encoded as 'name' (where 'name' is the last segment of the package name)
+	this.segments[0] = key;
 }
-/**
+public char[] encodeIndexKey() {
+	if (this.currentSegment < 0) return null;
+	// Package reference keys are encoded as 'name' (where 'name' is the last segment of the package name)
+	return encodeIndexKey(this.segments[this.currentSegment]);
+}
+public SearchPattern getIndexRecord() {
+	return getPackageReferenceRecord();
+}
+public char[][] getMatchCategories() {
+	return new char[][] {REF};
+}
+/*
  * @see AndPattern#hasNextQuery()
  */
 protected boolean hasNextQuery() {
-	if (this.segments.length > 2) {
-		// if package has more than 2 segments, don't look at the first 2 since they are mostly
-		// redundant (eg. in 'org.eclipse.jdt.core.*' 'org.eclipse' is used all the time)
-		return --this.currentSegment >= 2;
-	} else {
-		return --this.currentSegment >= 0;
-	}
+	// if package has at least 4 segments, don't look at the first 2 since they are mostly
+	// redundant (eg. in 'org.eclipse.jdt.core.*' 'org.eclipse' is used all the time)
+	return --this.currentSegment >= (this.segments.length >= 4 ? 2 : 0);
 }
-/**
- * @see SearchPattern#indexEntryPrefix()
+/*
+ * @see SearchPattern#isMatchingIndexRecord()
  */
-public char[] indexEntryPrefix() {
-	return AbstractIndexer.bestReferencePrefix(
-		REF,
-		this.segments[this.currentSegment],
-		matchMode,
-		isCaseSensitive);
-}
-/**
- * @see SearchPattern#matchContainer()
- */
-protected int matchContainer() {
-	return COMPILATION_UNIT | CLASS | METHOD | FIELD;
-}
-/**
- * Returns whether this package reference pattern matches the given tokens.
- */
-private boolean matches(char[][] tokens) {
-	char[] name = CharOperation.concatWith(tokens, '.');
-	return this.matchesName(this.pkgName, name);
-}
-/**
- * @see SearchPattern#matchIndexEntry()
- */
-protected boolean matchIndexEntry() {
-	switch(matchMode){
-		case EXACT_MATCH :
-			if (!CharOperation.equals(this.segments[this.currentSegment], this.decodedSegment, isCaseSensitive)){
-				return false;
-			}
-			break;
-		case PREFIX_MATCH :
-			if (!CharOperation.prefixEquals(this.segments[this.currentSegment], this.decodedSegment, isCaseSensitive)){
-				return false;
-			}
-			break;
-		case PATTERN_MATCH :
-			if (!CharOperation.match(this.segments[this.currentSegment], this.decodedSegment, isCaseSensitive)){
-				return false;
-			}
-	}
-	return true;
-}
-/**
- * @see SearchPattern#matchReportReference(AstNode reference, IJavaElement element, int accuracy, MatchLocator locator)
- */
-protected void matchReportReference(AstNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	char[][] tokens = null;
-	if (reference instanceof ImportReference) {
-		ImportReference importRef = (ImportReference)reference;
-		if (importRef.onDemand) {
-			tokens = importRef.tokens;
-		} else {
-			int length = importRef.tokens.length - 1;
-			tokens = new char[length][];
-			System.arraycopy(importRef.tokens, 0, tokens, 0, length);
-		}
-	} else if (reference instanceof QualifiedNameReference) {
-		QualifiedNameReference qNameRef = (QualifiedNameReference)reference;
-		Binding binding = qNameRef.binding;
-		TypeBinding typeBinding = null;
-		switch (qNameRef.bits & AstNode.RestrictiveFlagMASK) {
-			case BindingIds.FIELD : // reading a field
-				typeBinding = qNameRef.actualReceiverType;
-				break;
-			case BindingIds.TYPE : //=============only type ==============
-				typeBinding = (TypeBinding)binding;
-				break;
-			case BindingIds.VARIABLE : //============unbound cases===========
-			case BindingIds.TYPE | BindingIds.VARIABLE :						
-				if (binding instanceof ProblemBinding) {
-					ProblemBinding pbBinding = (ProblemBinding) binding;
-					typeBinding = pbBinding.searchType; // second chance with recorded type so far
-				}
-				break;
-		}
-		if (typeBinding instanceof ReferenceBinding) {
-			PackageBinding pkgBinding = ((ReferenceBinding)typeBinding).fPackage;
-			if (pkgBinding != null) {
-				tokens = pkgBinding.compoundName;
-			}
-		} 
-		if (tokens == null) {
-			tokens = qNameRef.tokens;
-		}
-	} else if (reference instanceof QualifiedTypeReference) {
-		QualifiedTypeReference qTypeRef = (QualifiedTypeReference)reference;
-		TypeBinding typeBinding = qTypeRef.resolvedType;
-		if (typeBinding instanceof ArrayBinding) {
-			typeBinding = ((ArrayBinding)typeBinding).leafComponentType;
-		}
-		if (typeBinding instanceof ReferenceBinding) {
-			PackageBinding pkgBinding = ((ReferenceBinding)typeBinding).fPackage;
-			if (pkgBinding != null) {
-				tokens = pkgBinding.compoundName;
-			}
-		} 
-		if (tokens == null) {
-			tokens = qTypeRef.tokens;
-		}
-	}
-	if (tokens == null) tokens = CharOperation.NO_CHAR_CHAR;
-	locator.reportAccurateReference(reference.sourceStart, reference.sourceEnd, tokens, element, accuracy);
+public boolean isMatchingIndexRecord() {
+	return matchesName(this.segments[this.currentSegment], ((PackageReferencePattern)getIndexRecord()).segments[0]);
 }
 /**
  * @see AndPattern#resetQuery()
@@ -208,245 +79,31 @@
 	/* walk the segments from end to start as it will find less potential references using 'lang' than 'java' */
 	this.currentSegment = this.segments.length - 1;
 }
-public String toString(){
+public String toString() {
 	StringBuffer buffer = new StringBuffer(20);
 	buffer.append("PackageReferencePattern: <"); //$NON-NLS-1$
-	if (this.pkgName != null) buffer.append(this.pkgName);
+	if (this.pkgName != null) 
+		buffer.append(this.pkgName);
+	else
+		buffer.append("*"); //$NON-NLS-1$
 	buffer.append(">, "); //$NON-NLS-1$
-	switch(matchMode){
-		case EXACT_MATCH : 
+	switch(matchMode()){
+		case R_EXACT_MATCH : 
 			buffer.append("exact match, "); //$NON-NLS-1$
 			break;
-		case PREFIX_MATCH :
+		case R_PREFIX_MATCH :
 			buffer.append("prefix match, "); //$NON-NLS-1$
 			break;
-		case PATTERN_MATCH :
+		case R_PATTERN_MATCH :
 			buffer.append("pattern match, "); //$NON-NLS-1$
 			break;
+		case R_REGEXP_MATCH :
+			buffer.append("regexp match, "); //$NON-NLS-1$
 	}
-	if (isCaseSensitive)
+	if (isCaseSensitive())
 		buffer.append("case sensitive"); //$NON-NLS-1$
 	else
 		buffer.append("case insensitive"); //$NON-NLS-1$
 	return buffer.toString();
 }
-
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
- */
-public int matchLevel(AstNode node, boolean resolve) {
-	if (node instanceof QualifiedTypeReference) {
-		return this.matchLevel((QualifiedTypeReference)node, resolve);
-	} else if (node instanceof ImportReference) {
-		return this.matchLevel((ImportReference)node, resolve);
-	} else if (node instanceof QualifiedNameReference) {
-		return this.matchLevel((QualifiedNameReference)node, resolve);
-	}
-	return IMPOSSIBLE_MATCH;
-}
-
-/**
- * Returns whether this package reference pattern matches the given import reference.
- * Look at resolved information only if specified.
- */
-private int matchLevel(ImportReference importRef, boolean resolve) {
-	if (importRef.onDemand) {
-		if (this.matches(importRef.tokens)) {
-			return ACCURATE_MATCH;
-		} else {
-			return IMPOSSIBLE_MATCH;
-		}
-	} else {
-		char[] qualifiedTypeName = CharOperation.concatWith(importRef.tokens, '.');
-		switch (this.matchMode) {
-			case EXACT_MATCH :
-			case PREFIX_MATCH :
-				if (CharOperation.prefixEquals(this.pkgName, qualifiedTypeName, this.isCaseSensitive)) {
-					return POSSIBLE_MATCH;
-				} 
-				break;
-			case PATTERN_MATCH :
-				if (CharOperation.match(this.pkgName, qualifiedTypeName, this.isCaseSensitive)) {
-					return POSSIBLE_MATCH;
-				}
-				break;
-		}
-		return IMPOSSIBLE_MATCH;
-	}
-}
-
-/**
- * Returns whether this package reference pattern matches the given qualified name reference.
- * Look at resolved information only if specified.
- */
-private int matchLevel(QualifiedNameReference qNameRef, boolean resolve) {
-	if (!resolve) {
-		if (this.pkgName == null) {
-			return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-		} else {
-			switch (this.matchMode) {
-				case EXACT_MATCH:
-				case PREFIX_MATCH:
-					if (CharOperation.prefixEquals(this.pkgName, CharOperation.concatWith(qNameRef.tokens, '.'), this.isCaseSensitive)) {
-						return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-					} else {
-						return IMPOSSIBLE_MATCH;
-					}
-				case PATTERN_MATCH:
-					char[] pattern = this.pkgName[this.pkgName.length-1] == '*' ? this.pkgName : CharOperation.concat(this.pkgName, ".*".toCharArray()); //$NON-NLS-1$
-					if (CharOperation.match(pattern, CharOperation.concatWith(qNameRef.tokens, '.'), this.isCaseSensitive)) {
-						return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-					} else {
-						return IMPOSSIBLE_MATCH;
-					}
-				default:
-					return IMPOSSIBLE_MATCH;
-			}
-		}
-	} else {
-		Binding binding = qNameRef.binding;
-		if (binding == null) {
-			return INACCURATE_MATCH;
-		} else {
-			TypeBinding typeBinding = null;
-			char[][] tokens = qNameRef.tokens;
-			int lastIndex = tokens.length-1;
-			switch (qNameRef.bits & AstNode.RestrictiveFlagMASK) {
-				case BindingIds.FIELD : // reading a field
-					typeBinding = qNameRef.actualReceiverType;
-					// no valid match amongst fields
-					int otherBindingsCount = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length;			
-					lastIndex -= otherBindingsCount + 1;
-					if (lastIndex < 0) return IMPOSSIBLE_MATCH;
-					break;
-				case BindingIds.LOCAL : // reading a local variable
-					return IMPOSSIBLE_MATCH; // no package match in it
-				case BindingIds.TYPE : //=============only type ==============
-					typeBinding = (TypeBinding)binding;
-					break;
-				/*
-				 * Handling of unbound qualified name references. The match may reside in the resolved fragment,
-				 * which is recorded inside the problem binding, along with the portion of the name until it became a problem.
-				 */
-				case BindingIds.VARIABLE : //============unbound cases===========
-				case BindingIds.TYPE | BindingIds.VARIABLE :						
-					if (binding instanceof ProblemBinding) {
-						ProblemBinding pbBinding = (ProblemBinding) binding;
-						typeBinding = pbBinding.searchType; // second chance with recorded type so far
-						char[] partialQualifiedName = pbBinding.name;
-						lastIndex = CharOperation.occurencesOf('.', partialQualifiedName) - 1; // index of last bound token is one before the pb token
-						if (typeBinding == null || lastIndex < 0) return INACCURATE_MATCH;
-					}
-					break;					
-			}
-			if (typeBinding instanceof ArrayBinding) {
-				typeBinding = ((ArrayBinding)typeBinding).leafComponentType;
-			}
-			if (typeBinding == null) {
-				return INACCURATE_MATCH;
-			} else {
-				if (typeBinding instanceof ReferenceBinding) {
-					PackageBinding pkgBinding = ((ReferenceBinding)typeBinding).fPackage;
-					if (pkgBinding == null) {
-						return INACCURATE_MATCH;
-					} else if (this.matches(pkgBinding.compoundName)) {
-						return ACCURATE_MATCH;
-					} else {
-						return IMPOSSIBLE_MATCH;
-					}
-				} else {
-					return IMPOSSIBLE_MATCH;
-				}
-			}
-		}
-	}
-}
-
-/**
- * Returns whether this package reference pattern matches the given type reference.
- * Look at resolved information only if specified.
- */
-private int matchLevel(QualifiedTypeReference typeRef, boolean resolve) {
-	if (!resolve) {
-		if (this.pkgName == null) {
-			return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-		} else {
-			switch (this.matchMode) {
-				case EXACT_MATCH:
-				case PREFIX_MATCH:
-					if (CharOperation.prefixEquals(this.pkgName, CharOperation.concatWith(typeRef.tokens, '.'), this.isCaseSensitive)) {
-						return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-					} else {
-						return IMPOSSIBLE_MATCH;
-					}
-				case PATTERN_MATCH:
-					char[] pattern = this.pkgName[this.pkgName.length-1] == '*' ? this.pkgName : CharOperation.concat(this.pkgName, ".*".toCharArray()); //$NON-NLS-1$
-					if (CharOperation.match(pattern, CharOperation.concatWith(typeRef.tokens, '.'), this.isCaseSensitive)) {
-						return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-					} else {
-						return IMPOSSIBLE_MATCH;
-					}
-				default:
-					return IMPOSSIBLE_MATCH;
-			}
-		}
-	} else {
-		return this.matchLevel(typeRef.resolvedType);
-	}
-}
-/**
- * @see SearchPattern#matchReportImportRef(ImportReference, Binding, IJavaElement, int, MatchLocator)
- */
-protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	if (binding == null) {
-		this.matchReportReference(importRef, element, accuracy, locator);
-	} else {
-		if (binding instanceof ImportBinding) {
-			locator.reportAccurateReference(importRef.sourceStart, importRef.sourceEnd, importRef.tokens, element, accuracy);
-		} else if (binding instanceof ReferenceBinding) {
-			PackageBinding pkgBinding = ((ReferenceBinding)binding).fPackage;
-			if (pkgBinding != null) {
-				locator.reportAccurateReference(importRef.sourceStart, importRef.sourceEnd, pkgBinding.compoundName, element, accuracy);
-			} else {
-				locator.reportAccurateReference(importRef.sourceStart, importRef.sourceEnd, importRef.tokens, element, accuracy);
-			}
-		} 
-	}
-}
-
-/**
- * @see SearchPattern#matchLevel(Binding)
- */
-public int matchLevel(Binding binding) {
-	if (binding instanceof ImportBinding) {
-		if (this.matches(((ImportBinding)binding).compoundName)) {
-			return ACCURATE_MATCH;
-		} else {
-			return IMPOSSIBLE_MATCH;
-		}
-	} else if (binding instanceof TypeBinding) {
-		TypeBinding typeBinding = (TypeBinding)binding;
-		if (typeBinding == null || typeBinding instanceof ProblemReferenceBinding) {
-			return INACCURATE_MATCH;
-		} else {
-			if (typeBinding instanceof ArrayBinding) {
-				typeBinding = ((ArrayBinding)typeBinding).leafComponentType;
-			}
-			if (typeBinding == null) {
-				return INACCURATE_MATCH;
-			} else if (typeBinding instanceof ReferenceBinding) {
-				PackageBinding pkgBinding = ((ReferenceBinding)typeBinding).fPackage;
-				if (this.matches(pkgBinding.compoundName)) {
-					return ACCURATE_MATCH;
-				} else {
-					return IMPOSSIBLE_MATCH;
-				}
-			} else {
-				return IMPOSSIBLE_MATCH;
-			}
-		}
-	} else {
-		return IMPOSSIBLE_MATCH;
-	}
-}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
new file mode 100644
index 0000000..e98a69c
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
+
+public abstract class PatternLocator implements IIndexConstants {
+
+protected int matchMode;
+protected boolean isCaseSensitive;
+
+/* match levels */
+public static final int IMPOSSIBLE_MATCH = 0;
+public static final int INACCURATE_MATCH = 1;
+public static final int POSSIBLE_MATCH = 2;
+public static final int ACCURATE_MATCH = 3;
+
+/* match container */
+public static final int COMPILATION_UNIT_CONTAINER = 1;
+public static final int CLASS_CONTAINER = 2;
+public static final int METHOD_CONTAINER = 4;
+public static final int FIELD_CONTAINER = 8;
+public static final int ALL_CONTAINER =
+	COMPILATION_UNIT_CONTAINER | CLASS_CONTAINER | METHOD_CONTAINER | FIELD_CONTAINER;
+
+public static PatternLocator patternLocator(SearchPattern pattern) {
+	switch (pattern.kind) {
+		case IIndexConstants.PKG_REF_PATTERN :
+			return new PackageReferenceLocator((PackageReferencePattern) pattern);
+		case IIndexConstants.PKG_DECL_PATTERN :
+			return new PackageDeclarationLocator((PackageDeclarationPattern) pattern);
+		case IIndexConstants.TYPE_REF_PATTERN :
+			return new TypeReferenceLocator((TypeReferencePattern) pattern);
+		case IIndexConstants.TYPE_DECL_PATTERN :
+			return new TypeDeclarationLocator((TypeDeclarationPattern) pattern);
+		case IIndexConstants.SUPER_REF_PATTERN :
+			return new SuperTypeReferenceLocator((SuperTypeReferencePattern) pattern);
+		case IIndexConstants.CONSTRUCTOR_PATTERN :
+			return new ConstructorLocator((ConstructorPattern) pattern);
+		case IIndexConstants.FIELD_PATTERN :
+			return new FieldLocator((FieldPattern) pattern);
+		case IIndexConstants.METHOD_PATTERN :
+			return new MethodLocator((MethodPattern) pattern);
+		case IIndexConstants.OR_PATTERN :
+			return new OrLocator((OrPattern) pattern);
+		case IIndexConstants.LOCAL_VAR_PATTERN :
+			return new LocalVariableLocator((LocalVariablePattern) pattern);
+	}
+	return null;
+}
+public static char[] qualifiedPattern(char[] simpleNamePattern, char[] qualificationPattern) {
+	// NOTE: if case insensitive search then simpleNamePattern & qualificationPattern are assumed to be lowercase
+	if (simpleNamePattern == null) {
+		if (qualificationPattern == null) return null;
+		return CharOperation.concat(qualificationPattern, ONE_STAR, '.');
+	} else {
+		return qualificationPattern == null
+			? CharOperation.concat(ONE_STAR, simpleNamePattern)
+			: CharOperation.concat(qualificationPattern, simpleNamePattern, '.');
+	}
+}
+public static char[] qualifiedSourceName(TypeBinding binding) {
+	if (binding instanceof ReferenceBinding) {
+		ReferenceBinding type = (ReferenceBinding) binding;
+		if (type.isLocalType())
+			return type.isMemberType()
+				? CharOperation.concat(qualifiedSourceName(type.enclosingType()), type.sourceName(), '.')
+				: CharOperation.concat(qualifiedSourceName(type.enclosingType()), new char[] {'.', '1', '.'}, type.sourceName());
+	}
+	return binding != null ? binding.qualifiedSourceName() : null;
+}
+
+
+public PatternLocator(SearchPattern pattern) {
+	this.matchMode = pattern.matchMode();
+	this.isCaseSensitive = pattern.isCaseSensitive();
+}
+/**
+ * Initializes this search pattern so that polymorphic search can be performed.
+ */ 
+public void initializePolymorphicSearch(MatchLocator locator) {
+	// default is to do nothing
+}
+/**
+ * Check if the given ast node syntactically matches this pattern.
+ * If it does, add it to the match set.
+ * Returns the match level.
+ */
+public int match(ASTNode node, MatchingNodeSet nodeSet) { // needed for some generic nodes
+	// each subtype should override if needed
+	return IMPOSSIBLE_MATCH;
+}
+public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) {
+	// each subtype should override if needed
+	return IMPOSSIBLE_MATCH;
+}
+public int match(Expression node, MatchingNodeSet nodeSet) {
+	// each subtype should override if needed
+	return IMPOSSIBLE_MATCH;
+}
+public int match(FieldDeclaration node, MatchingNodeSet nodeSet) {
+	// each subtype should override if needed
+	return IMPOSSIBLE_MATCH;
+}
+public int match(LocalDeclaration node, MatchingNodeSet nodeSet) {
+	// each subtype should override if needed
+	return IMPOSSIBLE_MATCH;
+}
+public int match(MethodDeclaration node, MatchingNodeSet nodeSet) {
+	// each subtype should override if needed
+	return IMPOSSIBLE_MATCH;
+}
+public int match(MessageSend node, MatchingNodeSet nodeSet) {
+	// each subtype should override if needed
+	return IMPOSSIBLE_MATCH;
+}
+public int match(Reference node, MatchingNodeSet nodeSet) {
+	// each subtype should override if needed
+	return IMPOSSIBLE_MATCH;
+}
+public int match(TypeDeclaration node, MatchingNodeSet nodeSet) {
+	// each subtype should override if needed
+	return IMPOSSIBLE_MATCH;
+}
+public int match(TypeReference node, MatchingNodeSet nodeSet) {
+	// each subtype should override if needed
+	return IMPOSSIBLE_MATCH;
+}
+/**
+ * Returns the type(s) of container for this pattern.
+ * It is a bit combination of types, denoting compilation unit, class declarations, field declarations or method declarations.
+ */
+protected int matchContainer() {
+	// override if the pattern can be more specific
+	return ALL_CONTAINER;
+}
+/**
+ * Returns whether the given name matches the given pattern.
+ */
+protected boolean matchesName(char[] pattern, char[] name) {
+	if (pattern == null) return true; // null is as if it was "*"
+	if (name != null) {
+		switch (this.matchMode) {
+			case IJavaSearchConstants.EXACT_MATCH :
+				return CharOperation.equals(pattern, name, this.isCaseSensitive);
+			case IJavaSearchConstants.PREFIX_MATCH :
+				return CharOperation.prefixEquals(pattern, name, this.isCaseSensitive);
+			case IJavaSearchConstants.PATTERN_MATCH :
+				if (!this.isCaseSensitive)
+					pattern = CharOperation.toLowerCase(pattern);
+				return CharOperation.match(pattern, name, this.isCaseSensitive);
+		}
+	}
+	return false;
+}
+/**
+ * Returns whether the given type reference matches the given pattern.
+ */
+protected boolean matchesTypeReference(char[] pattern, TypeReference type) {
+	if (pattern == null) return true; // null is as if it was "*"
+	if (type == null) return true; // treat as an inexact match
+
+	char[][] compoundName = type.getTypeName();
+	char[] simpleName = compoundName[compoundName.length - 1];
+	int dimensions = type.dimensions() * 2;
+	if (dimensions > 0) {
+		int length = simpleName.length;
+		char[] result = new char[length + dimensions];
+		System.arraycopy(simpleName, 0, result, 0, length);
+		for (int i = length, l = result.length; i < l;) {
+			result[i++] = '[';
+			result[i++] = ']';
+		}
+		simpleName = result;
+	}
+
+	return matchesName(pattern, simpleName);
+}
+/**
+ * Returns the match level for the given importRef.
+ */
+protected int matchLevel(ImportReference importRef) {
+	// override if interested in import references which are caught by the generic version of match(ASTNode, MatchingNodeSet)
+	return IMPOSSIBLE_MATCH;
+}
+/**
+ * Reports the match of the given import reference if the resolveLevel is high enough.
+ */
+protected void matchLevelAndReportImportRef(ImportReference importRef, Binding binding, MatchLocator locator) throws CoreException {
+	int level = resolveLevel(binding);
+	if (level >= INACCURATE_MATCH) {
+		matchReportImportRef(
+			importRef, 
+			binding, 
+			locator.createImportHandle(importRef), 
+			level == ACCURATE_MATCH
+				? IJavaSearchResultCollector.EXACT_MATCH
+				: IJavaSearchResultCollector.POTENTIAL_MATCH,
+			locator);
+	}
+}
+/**
+ * Reports the match of the given import reference.
+ */
+protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	// default is to report a match as a regular ref.
+	this.matchReportReference(importRef, element, accuracy, locator);
+}
+/**
+ * Reports the match of the given reference.
+ */
+protected void matchReportReference(ASTNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	// default is to report a match on the whole node.
+	locator.report(reference.sourceStart, reference.sourceEnd, element, accuracy);
+}
+/**
+ * Finds out whether the given ast node matches this search pattern.
+ * Returns IMPOSSIBLE_MATCH if it doesn't.
+ * Returns INACCURATE_MATCH if it potentially matches this search pattern (ie. 
+ * it has already been resolved but resolving failed.)
+ * Returns ACCURATE_MATCH if it matches exactly this search pattern (ie. 
+ * it doesn't need to be resolved or it has already been resolved.)
+ */
+public int resolveLevel(ASTNode possibleMatchingNode) {
+	// only called with nodes which were possible matches to the call to matchLevel
+	// need to do instance of checks to find out exact type of ASTNode
+	return IMPOSSIBLE_MATCH;
+}
+/**
+ * Finds out whether the given binding matches this search pattern.
+ * Returns ACCURATE_MATCH if it does.
+ * Returns INACCURATE_MATCH if resolve failed but match is still possible.
+ * Returns IMPOSSIBLE_MATCH otherwise.
+ * Default is to return INACCURATE_MATCH.
+ */
+public int resolveLevel(Binding binding) {
+	// override if the pattern can match the binding
+	return INACCURATE_MATCH;
+}
+/**
+ * Returns whether the given type binding matches the given simple name pattern 
+ * and qualification pattern.
+ * Returns ACCURATE_MATCH if it does.
+ * Returns INACCURATE_MATCH if resolve failed.
+ * Returns IMPOSSIBLE_MATCH if it doesn't.
+ */
+protected int resolveLevelForType(char[] simpleNamePattern, char[] qualificationPattern, TypeBinding type) {
+	return resolveLevelForType(qualifiedPattern(simpleNamePattern, qualificationPattern), type);
+}
+/**
+ * Returns whether the given type binding matches the given qualified pattern.
+ * Returns ACCURATE_MATCH if it does.
+ * Returns INACCURATE_MATCH if resolve failed.
+ * Returns IMPOSSIBLE_MATCH if it doesn't.
+ */
+protected int resolveLevelForType(char[] qualifiedPattern, TypeBinding type) {
+	if (qualifiedPattern == null) return ACCURATE_MATCH;
+	if (type == null) return INACCURATE_MATCH;
+
+	// NOTE: if case insensitive search then qualifiedPattern is assumed to be lowercase
+
+	char[] qualifiedPackageName = type.qualifiedPackageName();
+	char[] qualifiedSourceName = qualifiedSourceName(type);
+	char[] fullyQualifiedTypeName = qualifiedPackageName.length == 0
+		? qualifiedSourceName
+		: CharOperation.concat(qualifiedPackageName, qualifiedSourceName, '.');
+	return CharOperation.match(qualifiedPattern, fullyQualifiedTypeName, this.isCaseSensitive)
+		? ACCURATE_MATCH
+		: IMPOSSIBLE_MATCH;
+}
+public String toString(){
+	return "SearchPattern"; //$NON-NLS-1$
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java
new file mode 100644
index 0000000..42015dd
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.SearchDocument;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.core.*;
+
+public class PossibleMatch implements ICompilationUnit {
+
+public static final String NO_SOURCE_FILE_NAME = "NO SOURCE FILE NAME"; //$NON-NLS-1$
+
+public IResource resource;
+public Openable openable;
+public MatchingNodeSet nodeSet;
+public char[][] compoundName;
+CompilationUnitDeclaration parsedUnit;
+public SearchDocument document;
+private String sourceFileName;
+private char[] source;
+
+public PossibleMatch(MatchLocator locator, IResource resource, Openable openable, SearchDocument document) {
+	this.resource = resource;
+	this.openable = openable;
+	this.document = document;
+	this.nodeSet = new MatchingNodeSet();
+	char[] qualifiedName = getQualifiedName();
+	if (qualifiedName != null)
+		this.compoundName = CharOperation.splitOn('.', qualifiedName);
+}
+public void cleanUp() {
+	this.source = null;
+}
+public boolean equals(Object obj) {
+	if (this.compoundName == null) return super.equals(obj);
+	if (!(obj instanceof PossibleMatch)) return false;
+
+	// By using the compoundName of the source file, multiple .class files (A, A$M...) are considered equal
+	// Even .class files for secondary types and their nested types
+	return CharOperation.equals(this.compoundName, ((PossibleMatch) obj).compoundName);
+}
+public char[] getContents() {
+	if (this.source != null) return this.source;
+
+	if (this.openable instanceof ClassFile) {
+		String fileName = getSourceFileName();
+		if (fileName == NO_SOURCE_FILE_NAME) return null;
+
+		SourceMapper sourceMapper = this.openable.getSourceMapper();
+		IType type = ((ClassFile) this.openable).getType();
+		return this.source = sourceMapper.findSource(type, fileName);
+	}
+	return this.source = this.document.getCharContents();
+}
+/**
+ * The exact openable file name. In particular, will be the originating .class file for binary openable with attached
+ * source.
+ * @see PackageReferenceLocator#isDeclaringPackageFragment(IPackageFragment, ReferenceBinding)
+ */
+public char[] getFileName() {
+	return this.openable.getElementName().toCharArray();
+}
+public char[] getMainTypeName() {
+	// The file is no longer opened to get its name => remove fix for bug 32182
+	return this.compoundName[this.compoundName.length-1];
+}
+public char[][] getPackageName() {
+	int length = this.compoundName.length;
+	if (length <= 1) return CharOperation.NO_CHAR_CHAR;
+	return CharOperation.subarray(this.compoundName, 0, length - 1);
+}
+/*
+ * Returns the fully qualified name of the main type of the compilation unit
+ * or the main type of the .java file that defined the class file.
+ */
+private char[] getQualifiedName() {
+	if (this.openable instanceof CompilationUnit) {
+		// get file name
+		String fileName = this.resource.getFullPath().lastSegment();
+		// get main type name
+		char[] mainTypeName = fileName.substring(0, fileName.length()-5).toCharArray(); 
+		CompilationUnit cu = (CompilationUnit) this.openable;
+		return cu.getType(new String(mainTypeName)).getFullyQualifiedName().toCharArray();
+	} else if (this.openable instanceof ClassFile) {
+		String fileName = getSourceFileName();
+		if (fileName == NO_SOURCE_FILE_NAME)
+			return ((ClassFile) this.openable).getType().getFullyQualifiedName('.').toCharArray();
+
+		String simpleName = fileName.substring(0, fileName.length() - 5); // length-".java".length()
+		String pkgName = this.openable.getParent().getElementName();
+		if (pkgName.length() == 0)
+			return simpleName.toCharArray();
+		return (pkgName + '.' + simpleName).toCharArray();
+	}
+	return null;
+}
+/*
+ * Returns the source file name of the class file.
+ * Returns NO_SOURCE_FILE_NAME if not found.
+ */
+private String getSourceFileName() {
+	if (this.sourceFileName != null) return this.sourceFileName;
+
+	this.sourceFileName = NO_SOURCE_FILE_NAME; 
+	SourceMapper sourceMapper = this.openable.getSourceMapper();
+	if (sourceMapper != null) {
+		IType type = ((ClassFile) this.openable).getType();
+		ClassFileReader reader = MatchLocator.classFileReader(type);
+		if (reader != null)
+			this.sourceFileName = sourceMapper.findSourceFileName(type, reader);
+	}
+	return this.sourceFileName;
+}	
+public int hashCode() {
+	if (this.compoundName == null) return super.hashCode();
+
+	int hashCode = 0;
+	for (int i = 0, length = this.compoundName.length; i < length; i++)
+		hashCode += CharOperation.hashCode(this.compoundName[i]);
+	return hashCode;
+}
+public String toString() {
+	return this.openable == null ? "Fake PossibleMatch" : this.openable.toString(); //$NON-NLS-1$
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatchSet.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatchSet.java
new file mode 100644
index 0000000..84033c7
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatchSet.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.internal.compiler.util.ObjectVector;
+import org.eclipse.jdt.internal.core.util.SimpleLookupTable;
+
+/**
+ * A set of PossibleMatches that is sorted by package fragment roots.
+ */
+public class PossibleMatchSet {
+
+private SimpleLookupTable rootsToPossibleMatches = new SimpleLookupTable(5);
+private int elementCount = 0;
+
+public void add(PossibleMatch possibleMatch) {
+	IPath path = possibleMatch.openable.getPackageFragmentRoot().getPath();
+	ObjectVector possibleMatches = (ObjectVector) this.rootsToPossibleMatches.get(path);
+	if (possibleMatches != null) {
+		if (possibleMatches.contains(possibleMatch)) return;
+	} else {
+		this.rootsToPossibleMatches.put(path, possibleMatches = new ObjectVector());
+	}
+
+	possibleMatches.add(possibleMatch);
+	this.elementCount++;
+}
+public PossibleMatch[] getPossibleMatches(IPackageFragmentRoot[] roots) {
+	PossibleMatch[] result = new PossibleMatch[this.elementCount];
+	int index = 0;
+	for (int i = 0, length = roots.length; i < length; i++) {
+		ObjectVector possibleMatches = (ObjectVector) this.rootsToPossibleMatches.get(roots[i].getPath());
+		if (possibleMatches != null) {
+			possibleMatches.copyInto(result, index);
+			index += possibleMatches.size();
+		}
+	}
+	if (index < this.elementCount)
+		System.arraycopy(result, 0, result = new PossibleMatch[index], 0, index);
+	return result;
+}
+public void reset() {
+	this.rootsToPossibleMatches = new SimpleLookupTable(5);
+	this.elementCount = 0;
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PotentialMatch.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PotentialMatch.java
deleted file mode 100644
index ec41d93..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PotentialMatch.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchResultCollector;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
-import org.eclipse.jdt.internal.compiler.env.*;
-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
-import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
-import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
-import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
-import org.eclipse.jdt.internal.core.*;
-
-public class PotentialMatch implements ICompilationUnit {
-	public static final String NO_SOURCE_FILE_NAME = "NO SOURCE FILE NAME"; //$NON-NLS-1$
-
-	private MatchLocator2 locator;
-	public IResource resource;
-	public Openable openable;
-	public char[][] compoundName;
-	MatchingNodeSet matchingNodeSet;
-	private String sourceFileName;
-
-	public PotentialMatch(
-			MatchLocator2 locator, 
-			IResource resource, 
-			Openable openable) {
-		this.locator = locator;
-		this.resource = resource;
-		this.openable = openable;
-		this.matchingNodeSet = new MatchingNodeSet(locator);
-		char[] qualifiedName = getQualifiedName();
-		if (qualifiedName != null) {
-			this.compoundName = CharOperation.splitOn('.', qualifiedName);
-		}
-	}
-	public boolean equals(Object obj) {
-		if (this.compoundName == null) return super.equals(obj);
-		if (!(obj instanceof PotentialMatch)) return false;
-		return CharOperation.equals(this.compoundName, ((PotentialMatch)obj).compoundName);
-	}
-
-	/*
-	 * Finds the source of this class file.
-	 * Returns null if not found.
-	 */
-	private char[] findClassFileSource() {
-		String sourceFileName = getSourceFileName();
-		if (sourceFileName == NO_SOURCE_FILE_NAME) return null;
-		char[] source = null; 
-		try {
-			SourceMapper sourceMapper = this.openable.getSourceMapper();
-			if (sourceMapper != null) {
-				IType type = ((ClassFile)this.openable).getType();
-				source = sourceMapper.findSource(type, sourceFileName);
-			}
-		} catch (JavaModelException e) {
-		}
-		return source;
-	}
-	/*
-	 * Returns the source file name of the class file.
-	 * Returns NO_SOURCE_FILE_NAME if not found.
-	 */
-	private String getSourceFileName() {
-		if (this.sourceFileName != null) return this.sourceFileName;
-		this.sourceFileName = NO_SOURCE_FILE_NAME; 
-		try {
-			SourceMapper sourceMapper = this.openable.getSourceMapper();
-			if (sourceMapper != null) {
-				IType type = ((ClassFile)this.openable).getType();
-				ClassFileReader reader = this.locator.classFileReader(type);
-				if (reader != null) {
-					this.sourceFileName = sourceMapper.findSourceFileName(type, reader);
-				}
-			}
-		} catch (JavaModelException e) {
-		}
-		return this.sourceFileName;
-	}	
-	public char[] getContents() {
-		char[] source = null;
-		try {
-			if (this.openable instanceof WorkingCopy) {
-				IBuffer buffer = this.openable.getBuffer();
-				if (buffer == null) return null;
-				source = buffer.getCharacters();
-			} else if (this.openable instanceof CompilationUnit) {
-				source = Util.getResourceContentsAsCharArray((IFile)this.resource);
-			} else if (this.openable instanceof ClassFile) {
-				source = findClassFileSource();
-			}
-		} catch (JavaModelException e) {
-		}
-		if (source == null) return CharOperation.NO_CHAR;
-		return source;
-	}
-	/*
-	 * Returns the fully qualified name of the main type of the compilation unit
-	 * or the main type of the .java file that defined the class file.
-	 */
-	private char[] getQualifiedName() {
-		if (this.openable instanceof CompilationUnit) {
-			// get file name
-			String fileName = this.resource.getFullPath().lastSegment();
-			// get main type name
-			char[] mainTypeName = fileName.substring(0, fileName.length()-5).toCharArray(); 
-			CompilationUnit cu = (CompilationUnit)this.openable;
-			return cu.getType(new String(mainTypeName)).getFullyQualifiedName().toCharArray();
-		} else if (this.openable instanceof ClassFile) {
-			String sourceFileName = getSourceFileName();
-			if (sourceFileName == NO_SOURCE_FILE_NAME) {
-				try {
-					return ((ClassFile)this.openable).getType().getFullyQualifiedName('.').toCharArray();
-				} catch (JavaModelException e) {
-					return null;
-				}
-			}
-			String simpleName = sourceFileName.substring(0, sourceFileName.length()-5); // length-".java".length()
-			String pkgName = this.openable.getParent().getElementName();
-			if (pkgName.length() == 0) {
-				return simpleName.toCharArray();
-			} else {
-				return (pkgName + '.' + simpleName).toCharArray();
-			}
-		} else {
-			return null;
-		}
-	}
-	public int hashCode() {
-		if (this.compoundName == null) return super.hashCode();
-		int hashCode = 0;
-		for (int i = 0, length = this.compoundName.length; i < length; i++) {
-			hashCode += CharOperation.hashCode(this.compoundName[i]);
-		}
-		return hashCode;
-	}
-
-	public char[] getMainTypeName() {
-		return null; // cannot know the main type name without opening .java or .class file
-		                  // see http://bugs.eclipse.org/bugs/show_bug.cgi?id=32182
-	}
-	public char[][] getPackageName() {
-		int length;
-		if ((length = this.compoundName.length) > 1) {
-			return CharOperation.subarray(this.compoundName, 0, length-1);
-		} else {
-			return CharOperation.NO_CHAR_CHAR;
-		}
-	}
-	/**
-	 * Locate declaration in the current class file. This class file is always in a jar.
-	 */
-	public void locateMatchesInClassFile() throws CoreException {
-		org.eclipse.jdt.internal.core.ClassFile classFile = (org.eclipse.jdt.internal.core.ClassFile)this.openable;
-		IBinaryType info = this.locator.getBinaryInfo(classFile, this.resource);
-		if (info == null) 
-			return; // unable to go further
-	
-		// check class definition
-		BinaryType binaryType = (BinaryType)classFile.getType();
-		if (this.locator.pattern.matchesBinary(info, null)) {
-			this.locator.reportBinaryMatch(binaryType, info, IJavaSearchResultCollector.EXACT_MATCH);
-		}
-	
-		boolean compilationAborted = false;
-		if (this.locator.pattern.needsResolve) {
-			// resolve
-			BinaryTypeBinding binding = null;
-			try {
-				binding = this.locator.cacheBinaryType(binaryType);
-				if (binding != null) {
-					// filter out element not in hierarchy scope
-					if (!this.locator.typeInHierarchy(binding)) {
-						return;
-					}
-		
-					// check methods
-					MethodBinding[] methods = binding.methods();
-					for (int i = 0; i < methods.length; i++) {
-						MethodBinding method = methods[i];
-						int level = this.locator.pattern.matchLevel(method);
-						switch (level) {
-							case SearchPattern.IMPOSSIBLE_MATCH:
-							case SearchPattern.INACCURATE_MATCH:
-								break;
-							default:
-								IMethod methodHandle = 
-									binaryType.getMethod(
-										new String(method.isConstructor() ? binding.compoundName[binding.compoundName.length-1] : method.selector),
-										Signature.getParameterTypes(new String(method.signature()).replace('/', '.'))
-									);
-								this.locator.reportBinaryMatch(
-									methodHandle, 
-									info, 
-									level == SearchPattern.ACCURATE_MATCH ? 
-										IJavaSearchResultCollector.EXACT_MATCH : 
-										IJavaSearchResultCollector.POTENTIAL_MATCH);
-						}
-					}
-			
-					// check fields
-					FieldBinding[] fields = binding.fields();
-					for (int i = 0; i < fields.length; i++) {
-						FieldBinding field = fields[i];
-						int level = this.locator.pattern.matchLevel(field);
-						switch (level) {
-							case SearchPattern.IMPOSSIBLE_MATCH:
-							case SearchPattern.INACCURATE_MATCH:
-								break;
-							default:
-								IField fieldHandle = binaryType.getField(new String(field.name));
-								this.locator.reportBinaryMatch(
-									fieldHandle, 
-									info, 
-									level == SearchPattern.ACCURATE_MATCH ? 
-										IJavaSearchResultCollector.EXACT_MATCH : 
-										IJavaSearchResultCollector.POTENTIAL_MATCH);
-						}
-					}
-				}
-			} catch (AbortCompilation e) {
-				binding = null;
-			}
-	
-			// no need to check binary info if resolve was successful
-			compilationAborted = binding == null;
-			if (!compilationAborted) return;
-		}
-	
-		// if compilation was aborted it is a problem with the class path: 
-		// report as a potential match if binary info matches the pattern
-		int accuracy = compilationAborted ? IJavaSearchResultCollector.POTENTIAL_MATCH : IJavaSearchResultCollector.EXACT_MATCH;
-		
-		// check methods
-		IBinaryMethod[] methods = info.getMethods();
-		int length = methods == null ? 0 : methods.length;
-		for (int i = 0; i < length; i++) {
-			IBinaryMethod method = methods[i];
-			if (this.locator.pattern.matchesBinary(method, info)) {
-				IMethod methodHandle = 
-					binaryType.getMethod(
-						new String(method.isConstructor() ? info.getName() : method.getSelector()),
-						Signature.getParameterTypes(new String(method.getMethodDescriptor()).replace('/', '.'))
-					);
-				this.locator.reportBinaryMatch(methodHandle, info, accuracy);
-			}
-		}
-	
-		// check fields
-		IBinaryField[] fields = info.getFields();
-		length = fields == null ? 0 : fields.length;
-		for (int i = 0; i < length; i++) {
-			IBinaryField field = fields[i];
-			if (this.locator.pattern.matchesBinary(field, info)) {
-				IField fieldHandle = binaryType.getField(new String(field.getName()));
-				this.locator.reportBinaryMatch(fieldHandle, info, accuracy);
-			}
-		}
-	}
-	public String toString() {
-		return this.openable == null ? "Fake PotentialMatch" : this.openable.toString(); //$NON-NLS-1$
-	}
-
-	public char[] getFileName() {
-		return this.openable.getPath().toString().toCharArray();
-	}
-
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PotentialMatchSet.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PotentialMatchSet.java
deleted file mode 100644
index 1818a46..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/PotentialMatchSet.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
-import org.eclipse.jdt.internal.compiler.util.ObjectVector;
-
-/**
- * A set of PotentialMatches that is sorted by package fragment roots.
- */
-public class PotentialMatchSet {
-	private HashtableOfObject rootsToPotentialMatches = new HashtableOfObject(5);
-	private int elementCount = 0;
-	
-	public void add(PotentialMatch potentialMatch) {
-		IPackageFragmentRoot root = potentialMatch.openable.getPackageFragmentRoot();
-		char[] path = root.getPath().toString().toCharArray();
-		ObjectVector potentialMatches = (ObjectVector)this.rootsToPotentialMatches.get(path);
-		if (potentialMatches == null) {
-			potentialMatches = new ObjectVector();
-			this.rootsToPotentialMatches.put(path, potentialMatches);
-			potentialMatches.add(potentialMatch);
-			this.elementCount++;
-		} else if (!potentialMatches.contains(potentialMatch)) {
-			potentialMatches.add(potentialMatch);
-			this.elementCount++;
-		}
-	}
-	
-	public PotentialMatch[] getPotentialMatches(IPackageFragmentRoot[] roots) {
-		PotentialMatch[] result = new PotentialMatch[this.elementCount];
-		int index = 0;
-		for (int i = 0, length = roots.length; i < length; i++) {
-			IPackageFragmentRoot root = roots[i];
-			char[] path = root.getPath().toString().toCharArray();
-			ObjectVector potentialMatches = (ObjectVector)this.rootsToPotentialMatches.get(path);
-			if (potentialMatches != null) {
-				potentialMatches.copyInto(result, index);
-				index += potentialMatches.size();
-			}
-		}
-		if (index < this.elementCount) {
-			System.arraycopy(
-				result, 
-				0, 
-				result = new PotentialMatch[index],
-				0,
-				index);
-		}
-		return result;
-	}
-}
-
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/QualifiedTypeDeclarationPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/QualifiedTypeDeclarationPattern.java
index 3f48503..a657c89 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/QualifiedTypeDeclarationPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/QualifiedTypeDeclarationPattern.java
@@ -11,168 +11,75 @@
 package org.eclipse.jdt.internal.core.search.matching;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
+import org.eclipse.jdt.core.search.*;
 
 public class QualifiedTypeDeclarationPattern extends TypeDeclarationPattern {
 	
-	private char[] qualification;
-	private char[] decodedQualification;
-	
+private static ThreadLocal indexRecord = new ThreadLocal() {
+	protected Object initialValue() {
+		return new QualifiedTypeDeclarationPattern(null, null, ' ', R_EXACT_MATCH | R_CASE_SENSITIVE);
+	}
+};
+
+protected char[] qualification;
+
+public static QualifiedTypeDeclarationPattern getQualifiedTypeDeclarationRecord() {
+	return (QualifiedTypeDeclarationPattern)indexRecord.get();
+}
 public QualifiedTypeDeclarationPattern(
 	char[] qualification,
 	char[] simpleName,
 	char classOrInterface,
-	int matchMode, 
-	boolean isCaseSensitive) {
-		
-	super(matchMode, isCaseSensitive);
+	int matchRule) {
 
+	super(matchRule);
+
+	boolean isCaseSensitive = isCaseSensitive();
 	this.qualification = isCaseSensitive ? qualification : CharOperation.toLowerCase(qualification);
 	this.simpleName = isCaseSensitive ? simpleName : CharOperation.toLowerCase(simpleName);
 	this.classOrInterface = classOrInterface;
-	
-	this.needsResolve = qualification != null;
+
+	this.mustResolve = qualification != null;
 }
+public void decodeIndexKey(char[] key) {
+	int size = key.length;
 
-public void decodeIndexEntry(IEntryResult entryResult){
-	
-	char[] word = entryResult.getWord();
-	int size = word.length;
+	this.classOrInterface = key[0];
+	int oldSlash = 1;
+	int slash = CharOperation.indexOf(SEPARATOR, key, oldSlash + 1);
+	char[] pkgName = slash == oldSlash + 1
+		? CharOperation.NO_CHAR
+		: CharOperation.subarray(key, oldSlash+1, slash);
+	this.simpleName = CharOperation.subarray(key, slash + 1, slash = CharOperation.indexOf(SEPARATOR, key, slash + 1));
 
-	this.decodedClassOrInterface = word[TYPE_DECL_LENGTH];
-	int oldSlash = TYPE_DECL_LENGTH+1;
-	int slash = CharOperation.indexOf(SEPARATOR, word, oldSlash+1);
-	char[] pkgName;
-	if (slash == oldSlash+1){ 
-		pkgName = CharOperation.NO_CHAR;
+	char[][] decodedEnclosingTypeNames;
+	if (slash + 1 < size) {
+		decodedEnclosingTypeNames = (slash + 3 == size && key[slash + 1] == ONE_ZERO[0])
+			? ONE_ZERO_CHAR
+			: CharOperation.splitOn('/', CharOperation.subarray(key, slash + 1, size - 1));
 	} else {
-		pkgName = CharOperation.subarray(word, oldSlash+1, slash);
+		decodedEnclosingTypeNames = CharOperation.NO_CHAR_CHAR;
 	}
-	this.decodedSimpleName = CharOperation.subarray(word, slash+1, slash = CharOperation.indexOf(SEPARATOR, word, slash+1));
-
-	char[][] enclosingTypeNames;
-	if (slash+1 < size){
-		if (slash+3 == size && word[slash+1] == ONE_ZERO[0]) {
-			enclosingTypeNames = ONE_ZERO_CHAR;
-		} else {
-			enclosingTypeNames = CharOperation.splitOn('/', CharOperation.subarray(word, slash+1, size-1));
-		}
-	} else {
-		enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
-	}
-	this.decodedQualification = CharOperation.concatWith(pkgName, enclosingTypeNames, '.');
+	this.qualification = CharOperation.concatWith(pkgName, decodedEnclosingTypeNames, '.');
 }
-
-
-/**
- * @see SearchPattern#matchesBinary(Object, Object)
- */
-public boolean matchesBinary(Object binaryInfo, Object enclosingBinaryInfo) {
-	if (!(binaryInfo instanceof IBinaryType)) return false;
-
-	IBinaryType type = (IBinaryType)binaryInfo;
-
-	// fully qualified name
-	char[] typeName = (char[])type.getName().clone();
-	CharOperation.replace(typeName, '/', '.');
-	if (!this.matchesType(this.simpleName, this.qualification, typeName)) {
-		return false;
-	}
-
-	// class or interface
-	switch (this.classOrInterface) {
-		case CLASS_SUFFIX:
-			if (type.isInterface())
-				return false;
-			break;
-		case INTERFACE_SUFFIX:
-			if (!type.isInterface())
-				return false;
-			break;
-	}
-	
-	return true;
+public SearchPattern getIndexRecord() {
+	return getQualifiedTypeDeclarationRecord();
 }
-/**
- * see SearchPattern.matchIndexEntry
- */
-protected boolean matchIndexEntry(){
-
-	/* check class/interface nature */
-	switch(classOrInterface){
+public boolean isMatchingIndexRecord() {
+	QualifiedTypeDeclarationPattern record = getQualifiedTypeDeclarationRecord();
+	switch(this.classOrInterface) {
 		case CLASS_SUFFIX :
 		case INTERFACE_SUFFIX :
-			if (classOrInterface != decodedClassOrInterface) return false;
-		default :
+			if (this.classOrInterface != record.classOrInterface) return false;
+		case TYPE_SUFFIX : // nothing
 	}
-	/* check qualification */
-	if (qualification != null) {
-		switch(matchMode){
-			case EXACT_MATCH :
-				if (!CharOperation.equals(qualification, decodedQualification, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PREFIX_MATCH :
-				if (!CharOperation.prefixEquals(qualification, decodedQualification, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PATTERN_MATCH :
-				if (!CharOperation.match(qualification, decodedQualification, isCaseSensitive)){
-					return false;
-				}
-		}
-	}
-	/* check simple name matches */
-	if (simpleName != null){
-		switch(matchMode){
-			case EXACT_MATCH :
-				if (!CharOperation.equals(simpleName, decodedSimpleName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PREFIX_MATCH :
-				if (!CharOperation.prefixEquals(simpleName, decodedSimpleName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PATTERN_MATCH :
-				if (!CharOperation.match(simpleName, decodedSimpleName, isCaseSensitive)){
-					return false;
-				}
-		}
-	}
-	return true;
+
+	if (!matchesName(this.pkg, record.qualification))
+		return false;
+	
+	return matchesName(this.simpleName, record.simpleName);
 }
-/**
- * @see SearchPattern#matchLevel(Binding)
- */
-public int matchLevel(Binding binding) {
-	if (binding == null) return INACCURATE_MATCH;
-	if (!(binding instanceof TypeBinding)) return IMPOSSIBLE_MATCH;
-
-	TypeBinding type = (TypeBinding)binding;
-
-	// class or interface
-	switch (this.classOrInterface) {
-		case CLASS_SUFFIX:
-			if (type.isInterface())
-				return IMPOSSIBLE_MATCH;
-			break;
-		case INTERFACE_SUFFIX:
-			if (!type.isInterface())
-				return IMPOSSIBLE_MATCH;
-			break;
-	}
-
-	// fully qualified name
-	return this.matchLevelForType(this.simpleName, this.qualification, type);
-}
-public String toString(){
+public String toString() {
 	StringBuffer buffer = new StringBuffer(20);
 	switch (classOrInterface){
 		case CLASS_SUFFIX :
@@ -185,11 +92,17 @@
 			buffer.append("TypeDeclarationPattern: qualification<"); //$NON-NLS-1$
 			break;
 	}
-	if (this.qualification != null) buffer.append(this.qualification);
+	if (this.qualification != null) 
+		buffer.append(this.qualification);
+	else
+		buffer.append("*"); //$NON-NLS-1$
 	buffer.append(">, type<"); //$NON-NLS-1$
-	if (simpleName != null) buffer.append(simpleName);
+	if (simpleName != null) 
+		buffer.append(simpleName);
+	else
+		buffer.append("*"); //$NON-NLS-1$
 	buffer.append(">, "); //$NON-NLS-1$
-	switch(matchMode){
+	switch(matchMode()){
 		case EXACT_MATCH : 
 			buffer.append("exact match, "); //$NON-NLS-1$
 			break;
@@ -200,7 +113,7 @@
 			buffer.append("pattern match, "); //$NON-NLS-1$
 			break;
 	}
-	if (isCaseSensitive)
+	if (isCaseSensitive())
 		buffer.append("case sensitive"); //$NON-NLS-1$
 	else
 		buffer.append("case insensitive"); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SearchPattern.java
deleted file mode 100644
index a0bb1a4..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SearchPattern.java
+++ /dev/null
@@ -1,1416 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import java.io.IOException;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.jdt.core.IField;
-import org.eclipse.jdt.core.IImportDeclaration;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IMethod;
-
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.Signature;
-import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.core.compiler.InvalidInputException;
-import org.eclipse.jdt.core.search.IJavaSearchConstants;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.core.search.ISearchPattern;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
-import org.eclipse.jdt.internal.compiler.parser.Scanner;
-import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.IIndex;
-import org.eclipse.jdt.internal.core.index.impl.BlocksIndexInput;
-import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
-
-public abstract class SearchPattern implements ISearchPattern, IIndexConstants, IJavaSearchConstants {
-
-	protected int matchMode;
-	protected boolean isCaseSensitive;
-	public boolean needsResolve = true;
-
-	/* focus element (used for reference patterns*/
-	public IJavaElement focus;
-
-	/* match level */
-	public static final int IMPOSSIBLE_MATCH = 0;
-	public static final int POSSIBLE_MATCH = 1;
-	public static final int ACCURATE_MATCH = 2;
-	public static final int INACCURATE_MATCH = 3;
-
-	/* match container */
-	public static final int COMPILATION_UNIT = 1;
-	public static final int CLASS = 2;
-	public static final int FIELD = 4;
-	public static final int METHOD = 8;
-	
-public SearchPattern(int matchMode, boolean isCaseSensitive) {
-	this.matchMode = matchMode;
-	this.isCaseSensitive = isCaseSensitive;
-}
-/**
- * Constructor pattern are formed by [declaringQualification.]type[(parameterTypes)]
- * e.g. java.lang.Object()
- *		Main(*)
- */
-private static SearchPattern createConstructorPattern(String patternString, int limitTo, int matchMode, boolean isCaseSensitive) {
-
-	Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, false /*assert*/, null /*taskTags*/, null/*taskPriorities*/);
-	scanner.setSource(patternString.toCharArray());
-	final int InsideName = 1;
-	final int InsideParameter = 2;
-	
-	String declaringQualification = null, typeName = null, parameterType = null;
-	String[] parameterTypes = null;
-	int parameterCount = -1;
-	boolean foundClosingParenthesis = false;
-	int mode = InsideName;
-	int token;
-	try {
-		token = scanner.getNextToken();
-	} catch (InvalidInputException e) {
-		return null;
-	}
-	while (token != TerminalTokens.TokenNameEOF){
-		switch(mode){
-
-			// read declaring type and selector
-			case InsideName :
-				switch (token) {
-					case TerminalTokens.TokenNameDOT:
-						if (declaringQualification == null){
-							if (typeName == null) return null;
-							declaringQualification = typeName;
-						} else {
-							String tokenSource = new String(scanner.getCurrentTokenSource());
-							declaringQualification += tokenSource + typeName;
-						}
-						typeName = null;
-						break;
-					case TerminalTokens.TokenNameLPAREN:
-						parameterTypes = new String[5];
-						parameterCount = 0;
-						mode = InsideParameter;
-						break;
-					case Scanner.TokenNameWHITESPACE:
-						break;
-					default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
-						if (typeName == null) {
-							typeName = new String(scanner.getCurrentTokenSource());
-						} else {
-							typeName += new String(scanner.getCurrentTokenSource());
-						}
-				}
-				break;
-			// read parameter types
-			case InsideParameter :
-				switch (token) {
-					case Scanner.TokenNameWHITESPACE:
-						break;
-					case TerminalTokens.TokenNameCOMMA:
-						if (parameterType == null) return null;
-						if (parameterTypes.length == parameterCount){
-							System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount);
-						}
-						parameterTypes[parameterCount++] = parameterType;
-						parameterType = null;
-						break;
-					case TerminalTokens.TokenNameRPAREN:
-						foundClosingParenthesis = true;
-						if (parameterType != null){
-							if (parameterTypes.length == parameterCount){
-								System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount);
-							}
-							parameterTypes[parameterCount++] = parameterType;
-						}
-						break;
-					default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
-						if (parameterType == null){
-							parameterType = new String(scanner.getCurrentTokenSource());
-						} else {
-							parameterType += new String(scanner.getCurrentTokenSource());
-						}
-				}
-				break;
-		}
-		try {
-			token = scanner.getNextToken();
-		} catch (InvalidInputException e) {
-			return null;
-		}
-	}
-	// parenthesis mismatch
-	if (parameterCount>0 && !foundClosingParenthesis) return null;
-	if (typeName == null) return null;
-
-	char[] typeNameChars = typeName.toCharArray();
-	if (typeNameChars.length == 1 && typeNameChars[0] == '*') typeNameChars = null;
-		
-	char[] declaringQualificationChars = null;
-	if (declaringQualification != null) declaringQualificationChars = declaringQualification.toCharArray();
-	char[][] parameterTypeQualifications = null, parameterTypeSimpleNames = null;
-
-	// extract parameter types infos
-	if (parameterCount >= 0){
-		parameterTypeQualifications = new char[parameterCount][];
-		parameterTypeSimpleNames = new char[parameterCount][];
-		for (int i = 0; i < parameterCount; i++){
-			char[] parameterTypePart = parameterTypes[i].toCharArray();
-			int lastDotPosition = CharOperation.lastIndexOf('.', parameterTypePart);
-			if (lastDotPosition >= 0){
-				parameterTypeQualifications[i] = CharOperation.subarray(parameterTypePart, 0, lastDotPosition);
-				if (parameterTypeQualifications[i].length == 1 && parameterTypeQualifications[i][0] == '*') {
-					parameterTypeQualifications[i] = null;
-				} else {
-					// prefix with a '*' as the full qualification could be bigger (because of an import)
-					parameterTypeQualifications[i] = CharOperation.concat(ONE_STAR, parameterTypeQualifications[i]);
-				}
-				parameterTypeSimpleNames[i] = CharOperation.subarray(parameterTypePart, lastDotPosition+1, parameterTypePart.length);
-			} else {
-				parameterTypeQualifications[i] = null;
-				parameterTypeSimpleNames[i] = parameterTypePart;
-			}
-			if (parameterTypeSimpleNames[i].length == 1 && parameterTypeSimpleNames[i][0] == '*') parameterTypeSimpleNames[i] = null;
-		}
-	}	
-	SearchPattern searchPattern = null;
-	switch (limitTo){
-		case IJavaSearchConstants.DECLARATIONS :
-			searchPattern = 
-				new ConstructorDeclarationPattern(
-					typeNameChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringQualificationChars, 
-					parameterTypeQualifications, 
-					parameterTypeSimpleNames);
-			break;
-		case IJavaSearchConstants.REFERENCES :
-			searchPattern = 
-				new ConstructorReferencePattern(
-					typeNameChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringQualificationChars, 
-					parameterTypeQualifications, 
-					parameterTypeSimpleNames,
-					null);
-			break;
-		case IJavaSearchConstants.ALL_OCCURRENCES :
-			searchPattern = new OrPattern(
-				new ConstructorDeclarationPattern(
-					typeNameChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringQualificationChars, 
-					parameterTypeQualifications, 
-					parameterTypeSimpleNames),
-				new ConstructorReferencePattern(
-					typeNameChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringQualificationChars, 
-					parameterTypeQualifications, 
-					parameterTypeSimpleNames,
-					null));
-			break;
-	}
-	return searchPattern;
-
-}
-/**
- * Field pattern are formed by [declaringType.]name[type]
- * e.g. java.lang.String.serialVersionUID long
- *		field*
- */
-private static SearchPattern createFieldPattern(String patternString, int limitTo, int matchMode, boolean isCaseSensitive) {
-
-	Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, false /*assert*/, null /*taskTags*/, null/*taskPriorities*/); 
-	scanner.setSource(patternString.toCharArray());
-	final int InsideDeclaringPart = 1;
-	final int InsideType = 2;
-	int lastToken = -1;
-	
-	String declaringType = null, fieldName = null;
-	String type = null;
-	int mode = InsideDeclaringPart;
-	int token;
-	try {
-		token = scanner.getNextToken();
-	} catch (InvalidInputException e) {
-		return null;
-	}
-	while (token != TerminalTokens.TokenNameEOF){
-		switch(mode){
-
-			// read declaring type and fieldName
-			case InsideDeclaringPart :
-				switch (token) {
-					case TerminalTokens.TokenNameDOT:
-						if (declaringType == null){
-							if (fieldName == null) return null;
-							declaringType = fieldName;
-						} else {
-							String tokenSource = new String(scanner.getCurrentTokenSource());
-							declaringType += tokenSource + fieldName;
-						}
-						fieldName = null;
-						break;
-					case Scanner.TokenNameWHITESPACE:
-						if (!(Scanner.TokenNameWHITESPACE == lastToken 
-							|| TerminalTokens.TokenNameDOT == lastToken)){
-							mode = InsideType;
-						}
-						break;
-					default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
-						if (fieldName == null) {
-							fieldName = new String(scanner.getCurrentTokenSource());
-						} else {
-							fieldName += new String(scanner.getCurrentTokenSource());
-						}
-				}
-				break;
-			// read type 
-			case InsideType:
-				switch (token) {
-					case Scanner.TokenNameWHITESPACE:
-						break;
-					default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
-						if (type == null){
-							type = new String(scanner.getCurrentTokenSource());
-						} else {
-							type += new String(scanner.getCurrentTokenSource());
-						}
-				}
-				break;
-		}
-		lastToken = token;
-		try {
-			token = scanner.getNextToken();
-		} catch (InvalidInputException e) {
-			return null;
-		}
-	}
-	if (fieldName == null) return null;
-
-	char[] fieldNameChars = fieldName.toCharArray();
-	if (fieldNameChars.length == 1 && fieldNameChars[0] == '*') fieldNameChars = null;
-		
-	char[] declaringTypeQualification = null, declaringTypeSimpleName = null;
-	char[] typeQualification = null, typeSimpleName = null;
-
-	// extract declaring type infos
-	if (declaringType != null){
-		char[] declaringTypePart = declaringType.toCharArray();
-		int lastDotPosition = CharOperation.lastIndexOf('.', declaringTypePart);
-		if (lastDotPosition >= 0){
-			declaringTypeQualification = CharOperation.subarray(declaringTypePart, 0, lastDotPosition);
-			if (declaringTypeQualification.length == 1 && declaringTypeQualification[0] == '*') declaringTypeQualification = null;
-			declaringTypeSimpleName = CharOperation.subarray(declaringTypePart, lastDotPosition+1, declaringTypePart.length);
-		} else {
-			declaringTypeQualification = null;
-			declaringTypeSimpleName = declaringTypePart;
-		}
-		if (declaringTypeSimpleName.length == 1 && declaringTypeSimpleName[0] == '*') declaringTypeSimpleName = null;
-	}
-	// extract type infos
-	if (type != null){
-		char[] typePart = type.toCharArray();
-		int lastDotPosition = CharOperation.lastIndexOf('.', typePart);
-		if (lastDotPosition >= 0){
-			typeQualification = CharOperation.subarray(typePart, 0, lastDotPosition);
-			if (typeQualification.length == 1 && typeQualification[0] == '*') {
-				typeQualification = null;
-			} else {
-				// prefix with a '*' as the full qualification could be bigger (because of an import)
-				typeQualification = CharOperation.concat(ONE_STAR, typeQualification);
-			}
-			typeSimpleName = CharOperation.subarray(typePart, lastDotPosition+1, typePart.length);
-		} else {
-			typeQualification = null;
-			typeSimpleName = typePart;
-		}
-		if (typeSimpleName.length == 1 && typeSimpleName[0] == '*') typeSimpleName = null;
-	}
-	SearchPattern searchPattern = null;
-	switch (limitTo){
-		case IJavaSearchConstants.DECLARATIONS :
-			searchPattern = 
-				new FieldDeclarationPattern(
-				fieldNameChars, 
-				matchMode, 
-				isCaseSensitive, 
-				declaringTypeQualification, 
-				declaringTypeSimpleName, 
-				typeQualification, 
-				typeSimpleName);
-			break;
-		case IJavaSearchConstants.REFERENCES :
-			searchPattern = 
-				new FieldReferencePattern(
-					fieldNameChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringTypeQualification, 
-					declaringTypeSimpleName, 
-					typeQualification, 
-					typeSimpleName,
-					true, // read access
-					true); // write access
-			break;
-		case IJavaSearchConstants.READ_ACCESSES :
-			searchPattern = 
-				new FieldReferencePattern(
-					fieldNameChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringTypeQualification, 
-					declaringTypeSimpleName, 
-					typeQualification, 
-					typeSimpleName,
-					true, // read access only
-					false);
-			break;
-		case IJavaSearchConstants.WRITE_ACCESSES :
-			searchPattern = 
-				new FieldReferencePattern(
-					fieldNameChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringTypeQualification, 
-					declaringTypeSimpleName, 
-					typeQualification, 
-					typeSimpleName,
-					false,
-					true); // write access only
-			break;
-		case IJavaSearchConstants.ALL_OCCURRENCES :
-			searchPattern = new OrPattern(
-				new FieldDeclarationPattern(
-					fieldNameChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringTypeQualification, 
-					declaringTypeSimpleName, 
-					typeQualification, 
-					typeSimpleName),
-				new FieldReferencePattern(
-					fieldNameChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringTypeQualification, 
-					declaringTypeSimpleName, 
-					typeQualification, 
-					typeSimpleName,
-					true, // read access
-					true)); // write access
-			break;
-	}
-	return searchPattern;
-
-}
-/**
- * Method pattern are formed by [declaringType.]selector[(parameterTypes)][returnType]
- * e.g. java.lang.Runnable.run() void
- *		main(*)
- */
-private static SearchPattern createMethodPattern(String patternString, int limitTo, int matchMode, boolean isCaseSensitive) {
-
-	Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, false /*assert*/, null /*taskTags*/, null/*taskPriorities*/); 
-	scanner.setSource(patternString.toCharArray());
-	final int InsideSelector = 1;
-	final int InsideParameter = 2;
-	final int InsideReturnType = 3;
-	int lastToken = -1;
-	
-	String declaringType = null, selector = null, parameterType = null;
-	String[] parameterTypes = null;
-	int parameterCount = -1;
-	String returnType = null;
-	boolean foundClosingParenthesis = false;
-	int mode = InsideSelector;
-	int token;
-	try {
-		token = scanner.getNextToken();
-	} catch (InvalidInputException e) {
-		return null;
-	}
-	while (token != TerminalTokens.TokenNameEOF){
-		switch(mode){
-
-			// read declaring type and selector
-			case InsideSelector :
-				switch (token) {
-					case TerminalTokens.TokenNameDOT:
-						if (declaringType == null){
-							if (selector == null) return null;
-							declaringType = selector;
-						} else {
-							String tokenSource = new String(scanner.getCurrentTokenSource());
-							declaringType += tokenSource + selector;
-						}
-						selector = null;
-						break;
-					case TerminalTokens.TokenNameLPAREN:
-						parameterTypes = new String[5];
-						parameterCount = 0;
-						mode = InsideParameter;
-						break;
-					case Scanner.TokenNameWHITESPACE:
-						if (!(Scanner.TokenNameWHITESPACE == lastToken 
-							|| TerminalTokens.TokenNameDOT == lastToken)){
-							mode = InsideReturnType;
-						}
-						break;
-					default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
-						if (selector == null) {
-							selector = new String(scanner.getCurrentTokenSource());
-						} else {
-							selector += new String(scanner.getCurrentTokenSource());
-						}
-						break;
-				}
-				break;
-			// read parameter types
-			case InsideParameter :
-				switch (token) {
-					case Scanner.TokenNameWHITESPACE:
-						break;
-					case TerminalTokens.TokenNameCOMMA:
-						if (parameterType == null) return null;
-						if (parameterTypes.length == parameterCount){
-							System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount);
-						}
-						parameterTypes[parameterCount++] = parameterType;
-						parameterType = null;
-						break;
-					case TerminalTokens.TokenNameRPAREN:
-						foundClosingParenthesis = true;
-						if (parameterType != null){
-							if (parameterTypes.length == parameterCount){
-								System.arraycopy(parameterTypes, 0, parameterTypes = new String[parameterCount*2], 0, parameterCount);
-							}
-							parameterTypes[parameterCount++] = parameterType;
-						}
-						mode = InsideReturnType;
-						break;
-					default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
-						if (parameterType == null){
-							parameterType = new String(scanner.getCurrentTokenSource());
-						} else {
-							parameterType += new String(scanner.getCurrentTokenSource());
-						}
-				}
-				break;
-			// read return type
-			case InsideReturnType:
-				switch (token) {
-					case Scanner.TokenNameWHITESPACE:
-						break;
-					default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
-						if (returnType == null){
-							returnType = new String(scanner.getCurrentTokenSource());
-						} else {
-							returnType += new String(scanner.getCurrentTokenSource());
-						}
-				}
-				break;
-		}
-		lastToken = token;
-		try {
-			token = scanner.getNextToken();
-		} catch (InvalidInputException e) {
-			return null;
-		}
-	}
-	// parenthesis mismatch
-	if (parameterCount>0 && !foundClosingParenthesis) return null;
-	if (selector == null) return null;
-
-	char[] selectorChars = selector.toCharArray();
-	if (selectorChars.length == 1 && selectorChars[0] == '*') selectorChars = null;
-		
-	char[] declaringTypeQualification = null, declaringTypeSimpleName = null;
-	char[] returnTypeQualification = null, returnTypeSimpleName = null;
-	char[][] parameterTypeQualifications = null, parameterTypeSimpleNames = null;
-
-	// extract declaring type infos
-	if (declaringType != null){
-		char[] declaringTypePart = declaringType.toCharArray();
-		int lastDotPosition = CharOperation.lastIndexOf('.', declaringTypePart);
-		if (lastDotPosition >= 0){
-			declaringTypeQualification = CharOperation.subarray(declaringTypePart, 0, lastDotPosition);
-			if (declaringTypeQualification.length == 1 && declaringTypeQualification[0] == '*') declaringTypeQualification = null;
-			declaringTypeSimpleName = CharOperation.subarray(declaringTypePart, lastDotPosition+1, declaringTypePart.length);
-		} else {
-			declaringTypeQualification = null;
-			declaringTypeSimpleName = declaringTypePart;
-		}
-		if (declaringTypeSimpleName.length == 1 && declaringTypeSimpleName[0] == '*') declaringTypeSimpleName = null;
-	}
-	// extract parameter types infos
-	if (parameterCount >= 0){
-		parameterTypeQualifications = new char[parameterCount][];
-		parameterTypeSimpleNames = new char[parameterCount][];
-		for (int i = 0; i < parameterCount; i++){
-			char[] parameterTypePart = parameterTypes[i].toCharArray();
-			int lastDotPosition = CharOperation.lastIndexOf('.', parameterTypePart);
-			if (lastDotPosition >= 0){
-				parameterTypeQualifications[i] = CharOperation.subarray(parameterTypePart, 0, lastDotPosition);
-				if (parameterTypeQualifications[i].length == 1 && parameterTypeQualifications[i][0] == '*') {
-					parameterTypeQualifications[i] = null;
-				} else {
-					// prefix with a '*' as the full qualification could be bigger (because of an import)
-					parameterTypeQualifications[i] = CharOperation.concat(ONE_STAR, parameterTypeQualifications[i]);
-				}
-				parameterTypeSimpleNames[i] = CharOperation.subarray(parameterTypePart, lastDotPosition+1, parameterTypePart.length);
-			} else {
-				parameterTypeQualifications[i] = null;
-				parameterTypeSimpleNames[i] = parameterTypePart;
-			}
-			if (parameterTypeSimpleNames[i].length == 1 && parameterTypeSimpleNames[i][0] == '*') parameterTypeSimpleNames[i] = null;
-		}
-	}	
-	// extract return type infos
-	if (returnType != null){
-		char[] returnTypePart = returnType.toCharArray();
-		int lastDotPosition = CharOperation.lastIndexOf('.', returnTypePart);
-		if (lastDotPosition >= 0){
-			returnTypeQualification = CharOperation.subarray(returnTypePart, 0, lastDotPosition);
-			if (returnTypeQualification.length == 1 && returnTypeQualification[0] == '*') {
-				returnTypeQualification = null;
-			} else {
-				// because of an import
-				returnTypeQualification = CharOperation.concat(ONE_STAR, returnTypeQualification);
-			}			
-			returnTypeSimpleName = CharOperation.subarray(returnTypePart, lastDotPosition+1, returnTypePart.length);
-		} else {
-			returnTypeQualification = null;
-			returnTypeSimpleName = returnTypePart;
-		}
-		if (returnTypeSimpleName.length == 1 && returnTypeSimpleName[0] == '*') returnTypeSimpleName = null;
-	}
-	SearchPattern searchPattern = null;
-	switch (limitTo){
-		case IJavaSearchConstants.DECLARATIONS :
-			searchPattern = 
-				new MethodDeclarationPattern(
-					selectorChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringTypeQualification, 
-					declaringTypeSimpleName, 
-					returnTypeQualification, 
-					returnTypeSimpleName, 
-					parameterTypeQualifications, 
-					parameterTypeSimpleNames);
-			break;
-		case IJavaSearchConstants.REFERENCES :
-			searchPattern = 
-				new MethodReferencePattern(
-					selectorChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringTypeQualification, 
-					declaringTypeSimpleName, 
-					returnTypeQualification, 
-					returnTypeSimpleName, 
-					parameterTypeQualifications, 
-					parameterTypeSimpleNames,
-					null);
-			break;
-		case IJavaSearchConstants.ALL_OCCURRENCES :
-			searchPattern = new OrPattern(
-				new MethodDeclarationPattern(
-					selectorChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringTypeQualification, 
-					declaringTypeSimpleName, 
-					returnTypeQualification, 
-					returnTypeSimpleName, 
-					parameterTypeQualifications, 
-					parameterTypeSimpleNames),
-				new MethodReferencePattern(
-					selectorChars, 
-					matchMode, 
-					isCaseSensitive, 
-					declaringTypeQualification, 
-					declaringTypeSimpleName, 
-					returnTypeQualification, 
-					returnTypeSimpleName, 
-					parameterTypeQualifications, 
-					parameterTypeSimpleNames,
-					null));
-			break;
-	}
-	return searchPattern;
-
-}
-private static SearchPattern createPackagePattern(String patternString, int limitTo, int matchMode, boolean isCaseSensitive) {
-	SearchPattern searchPattern = null;
-	switch (limitTo){
-		case IJavaSearchConstants.DECLARATIONS :
-			searchPattern = new PackageDeclarationPattern(patternString.toCharArray(), matchMode, isCaseSensitive);
-			break;
-		case IJavaSearchConstants.REFERENCES :
-			searchPattern = new PackageReferencePattern(patternString.toCharArray(), matchMode, isCaseSensitive);
-			break;
-		case IJavaSearchConstants.ALL_OCCURRENCES :
-			searchPattern = new OrPattern(
-				new PackageDeclarationPattern(patternString.toCharArray(), matchMode, isCaseSensitive),
-				new PackageReferencePattern(patternString.toCharArray(), matchMode, isCaseSensitive)
-			);
-			break;
-	}
-	return searchPattern;
-
-}
-public static SearchPattern createPattern(String patternString, int searchFor, int limitTo, int matchMode, boolean isCaseSensitive) {
-
-	if (patternString == null || patternString.length() == 0)
-		return null;
-
-	SearchPattern searchPattern = null;
-	switch (searchFor) {
-
-		case IJavaSearchConstants.TYPE:
-			searchPattern = createTypePattern(patternString, limitTo, matchMode, isCaseSensitive);
-			break;
-		case IJavaSearchConstants.METHOD:
-			searchPattern = createMethodPattern(patternString, limitTo, matchMode, isCaseSensitive);
-			break;			
-		case IJavaSearchConstants.CONSTRUCTOR:
-			searchPattern = createConstructorPattern(patternString, limitTo, matchMode, isCaseSensitive);
-			break;			
-		case IJavaSearchConstants.FIELD:
-			searchPattern = createFieldPattern(patternString, limitTo, matchMode, isCaseSensitive);
-			break;
-		case IJavaSearchConstants.PACKAGE:
-			searchPattern = createPackagePattern(patternString, limitTo, matchMode, isCaseSensitive);
-	}
-	return searchPattern;
-}
-public static SearchPattern createPattern(IJavaElement element, int limitTo) {
-	SearchPattern searchPattern = null;
-	int lastDot;
-	switch (element.getElementType()) {
-		case IJavaElement.FIELD :
-			IField field = (IField) element; 
-			String fullDeclaringName = field.getDeclaringType().getFullyQualifiedName().replace('$', '.');
-			lastDot = fullDeclaringName.lastIndexOf('.');
-			char[] declaringSimpleName = (lastDot != -1 ? fullDeclaringName.substring(lastDot + 1) : fullDeclaringName).toCharArray();
-			char[] declaringQualification = lastDot != -1 ? fullDeclaringName.substring(0, lastDot).toCharArray() : CharOperation.NO_CHAR;
-			char[] name = field.getElementName().toCharArray();
-			char[] typeSimpleName;
-			char[] typeQualification;
-			try {
-				String typeSignature = Signature.toString(field.getTypeSignature()).replace('$', '.');
-				lastDot = typeSignature.lastIndexOf('.');
-				typeSimpleName = (lastDot != -1 ? typeSignature.substring(lastDot + 1) : typeSignature).toCharArray();
-				typeQualification = 
-					lastDot != -1 ? 
-						// prefix with a '*' as the full qualification could be bigger (because of an import)
-						CharOperation.concat(ONE_STAR, typeSignature.substring(0, lastDot).toCharArray()) : 
-						null;
-			} catch (JavaModelException e) {
-				return null;
-			}
-			switch (limitTo) {
-				case IJavaSearchConstants.DECLARATIONS :
-					searchPattern = 
-						new FieldDeclarationPattern(
-							name, 
-							EXACT_MATCH, 
-							CASE_SENSITIVE, 
-							declaringQualification, 
-							declaringSimpleName, 
-							typeQualification, 
-							typeSimpleName);
-					break;
-				case IJavaSearchConstants.REFERENCES :
-					searchPattern = 
-						new FieldReferencePattern(
-							name, 
-							EXACT_MATCH, 
-							CASE_SENSITIVE, 
-							declaringQualification, 
-							declaringSimpleName, 
-							typeQualification, 
-							typeSimpleName,
-							true,  // read access
-							true); // write access
-					break;
-				case IJavaSearchConstants.READ_ACCESSES :
-					searchPattern = 
-						new FieldReferencePattern(
-							name, 
-							EXACT_MATCH, 
-							CASE_SENSITIVE, 
-							declaringQualification, 
-							declaringSimpleName, 
-							typeQualification, 
-							typeSimpleName,
-							true,  // read access only
-							false);
-					break;
-				case IJavaSearchConstants.WRITE_ACCESSES :
-					searchPattern = 
-						new FieldReferencePattern(
-							name, 
-							EXACT_MATCH, 
-							CASE_SENSITIVE, 
-							declaringQualification, 
-							declaringSimpleName, 
-							typeQualification, 
-							typeSimpleName,
-							false,
-							true); // write access only
-					break;
-				case IJavaSearchConstants.ALL_OCCURRENCES :
-					searchPattern = new OrPattern(
-						new FieldDeclarationPattern(
-							name, 
-							EXACT_MATCH, 
-							CASE_SENSITIVE, 
-							declaringQualification, 
-							declaringSimpleName, 
-							typeQualification, 
-							typeSimpleName), 
-						new FieldReferencePattern(
-							name, 
-							EXACT_MATCH, 
-							CASE_SENSITIVE, 
-							declaringQualification, 
-							declaringSimpleName, 
-							typeQualification, 
-							typeSimpleName,
-							true,  // read access
-							true)); // write access
-					break;
-			}
-			break;
-		case IJavaElement.IMPORT_DECLARATION :
-			String elementName = element.getElementName();
-			lastDot = elementName.lastIndexOf('.');
-			if (lastDot == -1) return null; // invalid import declaration
-			IImportDeclaration importDecl = (IImportDeclaration)element;
-			if (importDecl.isOnDemand()) {
-				searchPattern = createPackagePattern(elementName.substring(0, lastDot), limitTo, EXACT_MATCH, CASE_SENSITIVE);
-			} else {
-				searchPattern = 
-					createTypePattern(
-						elementName.substring(lastDot+1).toCharArray(),
-						elementName.substring(0, lastDot).toCharArray(),
-						null,
-						limitTo);
-			}
-			break;
-		case IJavaElement.METHOD :
-			IMethod method = (IMethod) element;
-			boolean isConstructor;
-			try {
-				isConstructor = method.isConstructor();
-			} catch (JavaModelException e) {
-				return null;
-			}
-			fullDeclaringName = method.getDeclaringType().getFullyQualifiedName().replace('$', '.');
-			lastDot = fullDeclaringName.lastIndexOf('.');
-			declaringSimpleName = (lastDot != -1 ? fullDeclaringName.substring(lastDot + 1) : fullDeclaringName).toCharArray();
-			declaringQualification = lastDot != -1 ? fullDeclaringName.substring(0, lastDot).toCharArray() : CharOperation.NO_CHAR;
-			char[] selector = method.getElementName().toCharArray();
-			char[] returnSimpleName;
-			char[] returnQualification;
-			try {
-				String returnType = Signature.toString(method.getReturnType()).replace('$', '.');
-				lastDot = returnType.lastIndexOf('.');
-				returnSimpleName = (lastDot != -1 ? returnType.substring(lastDot + 1) : returnType).toCharArray();
-				returnQualification = 
-					lastDot != -1 ? 
-						// prefix with a '*' as the full qualification could be bigger (because of an import)
-						CharOperation.concat(ONE_STAR, returnType.substring(0, lastDot).toCharArray()) : 
-						null;
-			} catch (JavaModelException e) {
-				return null;
-			}
-			String[] parameterTypes = method.getParameterTypes();
-			int paramCount = parameterTypes.length;
-			char[][] parameterSimpleNames = new char[paramCount][];
-			char[][] parameterQualifications = new char[paramCount][];
-			for (int i = 0; i < paramCount; i++) {
-				String signature = Signature.toString(parameterTypes[i]).replace('$', '.');
-				lastDot = signature.lastIndexOf('.');
-				parameterSimpleNames[i] = (lastDot != -1 ? signature.substring(lastDot + 1) : signature).toCharArray();
-				parameterQualifications[i] = 
-					lastDot != -1 ? 
-						// prefix with a '*' as the full qualification could be bigger (because of an import)
-						CharOperation.concat(ONE_STAR, signature.substring(0, lastDot).toCharArray()) : 
-						null;
-			}
-			switch (limitTo) {
-				case IJavaSearchConstants.DECLARATIONS :
-					if (isConstructor) {
-						searchPattern = 
-							new ConstructorDeclarationPattern(
-								declaringSimpleName, 
-								EXACT_MATCH, 
-								CASE_SENSITIVE, 
-								declaringQualification, 
-								parameterQualifications, 
-								parameterSimpleNames);
-					} else {
-						searchPattern = 
-							new MethodDeclarationPattern(
-								selector, 
-								EXACT_MATCH, 
-								CASE_SENSITIVE, 
-								declaringQualification, 
-								declaringSimpleName, 
-								returnQualification, 
-								returnSimpleName, 
-								parameterQualifications, 
-								parameterSimpleNames);
-					}
-					break;
-				case IJavaSearchConstants.REFERENCES :
-					if (isConstructor) {
-						searchPattern = 
-							new ConstructorReferencePattern(
-								declaringSimpleName, 
-								EXACT_MATCH, 
-								CASE_SENSITIVE, 
-								declaringQualification, 
-								parameterQualifications, 
-								parameterSimpleNames,
-								method.getDeclaringType());
-					} else {
-						searchPattern = 
-							new MethodReferencePattern(
-								selector, 
-								EXACT_MATCH, 
-								CASE_SENSITIVE, 
-								declaringQualification, 
-								declaringSimpleName, 
-								returnQualification, 
-								returnSimpleName, 
-								parameterQualifications, 
-								parameterSimpleNames,
-								method.getDeclaringType());
-					}
-					break;
-				case IJavaSearchConstants.ALL_OCCURRENCES :
-					if (isConstructor) {
-						searchPattern = new OrPattern(
-							new ConstructorDeclarationPattern(
-								declaringSimpleName, 
-								EXACT_MATCH, 
-								CASE_SENSITIVE, 
-								declaringQualification, 
-								parameterQualifications, 
-								parameterSimpleNames), 
-							new ConstructorReferencePattern(
-								declaringSimpleName, 
-								EXACT_MATCH, 
-								CASE_SENSITIVE, 
-								declaringQualification, 
-								parameterQualifications, 
-								parameterSimpleNames,
-								method.getDeclaringType()));
-					} else {
-						searchPattern = new OrPattern(
-							new MethodDeclarationPattern(
-								selector, 
-								EXACT_MATCH, 
-								CASE_SENSITIVE, 
-								declaringQualification, 
-								declaringSimpleName, 
-								returnQualification, 
-								returnSimpleName, 
-								parameterQualifications, 
-								parameterSimpleNames), 
-							new MethodReferencePattern(
-								selector, 
-								EXACT_MATCH, 
-								CASE_SENSITIVE, 
-								declaringQualification, 
-								declaringSimpleName, 
-								returnQualification, 
-								returnSimpleName, 
-								parameterQualifications, 
-								parameterSimpleNames,
-								method.getDeclaringType()));
-					}
-					break;
-			}
-			break;
-		case IJavaElement.TYPE :
-			IType type = (IType)element;
-			searchPattern = 
-				createTypePattern(
-					type.getElementName().toCharArray(), 
-					type.getPackageFragment().getElementName().toCharArray(),
-					enclosingTypeNames(type),
-					limitTo);
-			break;
-		case IJavaElement.PACKAGE_DECLARATION :
-		case IJavaElement.PACKAGE_FRAGMENT :
-			searchPattern = createPackagePattern(element.getElementName(), limitTo, EXACT_MATCH, CASE_SENSITIVE);
-			break;
-	}
-	if (searchPattern != null) {
-		searchPattern.focus = element;
-	}
-	return searchPattern;
-}
-private static SearchPattern createTypePattern(char[] simpleName, char[] packageName, char[][] enclosingTypeNames, int limitTo) {
-	SearchPattern searchPattern = null;
-	switch (limitTo) {
-		case IJavaSearchConstants.DECLARATIONS :
-			searchPattern = 
-				new TypeDeclarationPattern(
-					packageName, 
-					enclosingTypeNames, 
-					simpleName, 
-					TYPE_SUFFIX, 
-					EXACT_MATCH, 
-					CASE_SENSITIVE);
-			break;
-		case IJavaSearchConstants.REFERENCES :
-			searchPattern = 
-				new TypeReferencePattern(
-					CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
-					simpleName, 
-					EXACT_MATCH, 
-					CASE_SENSITIVE);
-			break;
-		case IJavaSearchConstants.IMPLEMENTORS : 
-			searchPattern = 
-				new SuperInterfaceReferencePattern(
-					CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
-					simpleName, 
-					EXACT_MATCH, 
-					CASE_SENSITIVE);
-			break;
-		case IJavaSearchConstants.ALL_OCCURRENCES :
-			searchPattern = new OrPattern(
-				new TypeDeclarationPattern(
-					packageName, 
-					enclosingTypeNames, 
-					simpleName, 
-					TYPE_SUFFIX, 
-					EXACT_MATCH, 
-					CASE_SENSITIVE), 
-				new TypeReferencePattern(
-					CharOperation.concatWith(packageName, enclosingTypeNames, '.'), 
-					simpleName, 
-					EXACT_MATCH, 
-					CASE_SENSITIVE));
-			break;
-	}
-	return searchPattern;
-}
-/**
- * Type pattern are formed by [qualification.]type
- * e.g. java.lang.Object
- *		Runnable
- *
- */
-private static SearchPattern createTypePattern(String patternString, int limitTo, int matchMode, boolean isCaseSensitive) {
-
-	Scanner scanner = new Scanner(false /*comment*/, true /*whitespace*/, false /*nls*/, false /*assert*/, null /*taskTags*/, null/*taskPriorities*/); 
-	scanner.setSource(patternString.toCharArray());
-	String type = null;
-	int token;
-	try {
-		token = scanner.getNextToken();
-	} catch (InvalidInputException e) {
-		return null;
-	}
-	while (token != TerminalTokens.TokenNameEOF){
-		switch (token) {
-			case Scanner.TokenNameWHITESPACE:
-				break;
-			default: // all other tokens are considered identifiers (see bug 21763 Problem in Java search [search])
-				if (type == null){
-					type = new String(scanner.getCurrentTokenSource());
-				} else {
-					type += new String(scanner.getCurrentTokenSource());
-				}
-		}
-		try {
-			token = scanner.getNextToken();
-		} catch (InvalidInputException e) {
-			return null;
-		}
-	}
-	if (type == null) return null;
-
-	char[] qualificationChars = null, typeChars = null;
-
-	// extract declaring type infos
-	if (type != null){
-		char[] typePart = type.toCharArray();
-		int lastDotPosition = CharOperation.lastIndexOf('.', typePart);
-		if (lastDotPosition >= 0){
-			qualificationChars = CharOperation.subarray(typePart, 0, lastDotPosition);
-			if (qualificationChars.length == 1 && qualificationChars[0] == '*') qualificationChars = null;
-			typeChars = CharOperation.subarray(typePart, lastDotPosition+1, typePart.length);
-		} else {
-			qualificationChars = null;
-			typeChars = typePart;
-		}
-		if (typeChars.length == 1 && typeChars[0] == '*') typeChars = null;
-	}
-	SearchPattern searchPattern = null;
-	switch (limitTo){
-		case IJavaSearchConstants.DECLARATIONS : // cannot search for explicit member types
-			searchPattern = new QualifiedTypeDeclarationPattern(qualificationChars, typeChars, TYPE_SUFFIX, matchMode, isCaseSensitive);
-			break;
-		case IJavaSearchConstants.REFERENCES :
-			searchPattern = new TypeReferencePattern(qualificationChars, typeChars, matchMode, isCaseSensitive);
-			break;
-		case IJavaSearchConstants.IMPLEMENTORS : 
-			searchPattern = new SuperInterfaceReferencePattern(qualificationChars, typeChars, matchMode, isCaseSensitive);
-			break;
-		case IJavaSearchConstants.ALL_OCCURRENCES :
-			searchPattern = new OrPattern(
-				new QualifiedTypeDeclarationPattern(qualificationChars, typeChars, TYPE_SUFFIX, matchMode, isCaseSensitive),// cannot search for explicit member types
-				new TypeReferencePattern(qualificationChars, typeChars, matchMode, isCaseSensitive));
-			break;
-	}
-	return searchPattern;
-
-}
-protected abstract void decodeIndexEntry(IEntryResult entryResult);
-/**
- * Returns the enclosing type names of the given type.
- */
-private static char[][] enclosingTypeNames(IType type) {
-	IJavaElement parent = type.getParent();
-	switch (parent.getElementType()) {
-		case IJavaElement.CLASS_FILE:
-			// For a binary type, the parent is not the enclosing type, but the declaring type is.
-			// (see bug 20532  Declaration of member binary type not found)
-			IType declaringType = type.getDeclaringType();
-			if (declaringType == null) {
-				return CharOperation.NO_CHAR_CHAR;
-			} else {
-				return CharOperation.arrayConcat(
-					enclosingTypeNames(declaringType), 
-					declaringType.getElementName().toCharArray());
-			}
-		case IJavaElement.COMPILATION_UNIT:
-			return CharOperation.NO_CHAR_CHAR;
-		case IJavaElement.TYPE:
-			return CharOperation.arrayConcat(
-				enclosingTypeNames((IType)parent), 
-				parent.getElementName().toCharArray());
-		default:
-			return null;
-	}
-}
-/**
- * Feed the requestor according to the current search pattern
- */
-public abstract void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope)  throws IOException ;
-/**
- * Query a given index for matching entries. 
- */
-public void findIndexMatches(IIndex index, IIndexSearchRequestor requestor, int detailLevel, IProgressMonitor progressMonitor, IJavaSearchScope scope) throws IOException {
-
-	if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
-
-	IndexInput input = new BlocksIndexInput(index.getIndexFile());
-	try {
-		input.open();
-		findIndexMatches(input, requestor, detailLevel, progressMonitor,scope);
-	} finally {
-		input.close();
-	}
-}
-/**
- * Query a given index for matching entries. 
- */
-public void findIndexMatches(IndexInput input, IIndexSearchRequestor requestor, int detailLevel, IProgressMonitor progressMonitor, IJavaSearchScope scope) throws IOException {
-
-	if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
-	
-	/* narrow down a set of entries using prefix criteria */
-	IEntryResult[] entries = input.queryEntriesPrefixedBy(indexEntryPrefix());
-	if (entries == null) return;
-	
-	/* only select entries which actually match the entire search pattern */
-	for (int i = 0, max = entries.length; i < max; i++){
-
-		if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
-
-		/* retrieve and decode entry */	
-		IEntryResult entry = entries[i];
-		decodeIndexEntry(entry);
-		if (matchIndexEntry()){
-			feedIndexRequestor(requestor, detailLevel, entry.getFileReferences(), input, scope);
-		}
-	}
-}
-/**
- * Answers the suitable prefix that should be used in order
- * to query indexes for the corresponding item.
- * The more accurate the prefix and the less false hits will have
- * to be eliminated later on.
- */
-public abstract char[] indexEntryPrefix();
-/**
- * Check if the given ast node syntactically matches this pattern.
- * If it does, add it to the match set.
- */
-protected void matchCheck(AstNode node, MatchSet set) {
-	int matchLevel = this.matchLevel(node, false);
-	switch (matchLevel) {
-		case SearchPattern.POSSIBLE_MATCH:
-			set.addPossibleMatch(node);
-			break;
-		case SearchPattern.ACCURATE_MATCH:
-			set.addTrustedMatch(node);
-	}
-}
-
-/**
- * Returns the type(s) of container for this pattern.
- * It is a bit combination of types, denoting compilation unit, class declarations, field declarations or method declarations.
- */
-protected abstract int matchContainer();
-/**
- * Finds out whether the given binary info matches this search pattern.
- * Default is to return false.
- */
-public boolean matchesBinary(Object binaryInfo, Object enclosingBinaryInfo) {
-	return false;
-}
-/**
- * Returns whether the given name matches the given pattern.
- */
-protected boolean matchesName(char[] pattern, char[] name) {
-	if (pattern == null) return true; // null is as if it was "*"
-	if (name != null){
-		switch (this.matchMode) {
-			case EXACT_MATCH :
-				return CharOperation.equals(pattern, name, this.isCaseSensitive);
-			case PREFIX_MATCH :
-				return CharOperation.prefixEquals(pattern, name, this.isCaseSensitive);
-			case PATTERN_MATCH :
-				if (!this.isCaseSensitive) {
-					pattern = CharOperation.toLowerCase(pattern);
-				}
-				return CharOperation.match(pattern, name, this.isCaseSensitive);
-		}
-	}
-	return false;
-}
-/**
- * Returns whether the given type binding matches the given simple name pattern 
- * and qualification pattern.
- */
-protected boolean matchesType(char[] simpleNamePattern, char[] qualificationPattern, char[] fullyQualifiedTypeName) {
-	char[] pattern;
-	if (simpleNamePattern == null) {
-		if (qualificationPattern == null) {
-			pattern = ONE_STAR;
-		} else {
-			pattern = CharOperation.concat(qualificationPattern, ONE_STAR, '.');
-		}
-	} else {
-		if (qualificationPattern == null) {
-			pattern = CharOperation.concat(ONE_STAR, simpleNamePattern);
-		} else {
-			pattern = CharOperation.concat(qualificationPattern, simpleNamePattern, '.');
-		}
-	}
-	if (!this.isCaseSensitive) {
-		pattern = CharOperation.toLowerCase(pattern);
-	}
-	return 
-		CharOperation.match(
-			pattern,
-			fullyQualifiedTypeName,
-			this.isCaseSensitive
-		);
-}
-/**
- * Checks whether an entry matches the current search pattern
- */
-protected abstract boolean matchIndexEntry();
-/**
- * Report the match of the given import reference
- */
-protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	// default is to report a match as a regular ref.
-	this.matchReportReference(importRef, element, accuracy, locator);
-}
-/**
- * Reports the match of the given reference.
- */
-protected void matchReportReference(AstNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	// default is to report a match on the whole node.
-	locator.report(reference.sourceStart, reference.sourceEnd, element, accuracy);
-}
-
-/**
- * Add square brackets to the given simple name
- */
-protected char[] toArrayName(char[] simpleName, int dimensions) {
-	if (dimensions == 0) return simpleName;
-	int length = simpleName.length;
-	char[] result = new char[length + dimensions * 2];
-	System.arraycopy(simpleName, 0, result, 0, length);
-	for (int i = 0; i < dimensions; i++) {
-		result[simpleName.length + i*2] = '[';
-		result[simpleName.length + i*2 + 1] = ']';
-	}
-	return result;
-}
-public String toString(){
-	return "SearchPattern"; //$NON-NLS-1$
-}
-
-/**
- * Initializes this search pattern so that polymorphic search can be performed.
- */ 
-public void initializePolymorphicSearch(MatchLocator locator, IProgressMonitor progressMonitor) {
-	// default is to do nothing
-}
-
-/*
- * Returns whether this pattern is a polymorphic search pattern.
- */
-public boolean isPolymorphicSearch() {
-	return false;
-}
-
-/**
- * Finds out whether the given ast node matches this search pattern.
- * Returns IMPOSSIBLE_MATCH if it doesn't.
- * Returns POSSIBLE_MATCH if it potentially matches this search pattern 
- * and it has not been reolved, and it needs to be resolved to get more information.
- * Returns ACCURATE_MATCH if it matches exactly this search pattern (ie. 
- * it doesn't need to be resolved or it has already been resolved.)
- * Returns INACCURATE_MATCH if it potentially exactly this search pattern (ie. 
- * it has already been resolved but resolving failed.)
- */
-public abstract int matchLevel(AstNode node, boolean resolve);
-
-/**
- * Finds out whether the given binding matches this search pattern.
- * Returns ACCURATE_MATCH if it does.
- * Returns INACCURATE_MATCH if resolve failed but match is still possible.
- * Retunrs IMPOSSIBLE_MATCH otherwise.
- * Default is to return INACCURATE_MATCH.
- */
-public int matchLevel(Binding binding) {
-	return INACCURATE_MATCH;
-}
-
-/**
- * Returns whether the given reference type binding matches or is a subtype of a type
- * that matches the given simple name pattern and qualification pattern.
- * Returns ACCURATE_MATCH if it does.
- * Returns INACCURATE_MATCH if resolve fails
- * Returns IMPOSSIBLE_MATCH if it doesn't.
- */
-protected int matchLevelAsSubtype(ReferenceBinding type, char[] simpleNamePattern, char[] qualificationPattern) {
-	if (type == null) return INACCURATE_MATCH;
-	
-	int level;
-	
-	// matches type
-	if ((level = this.matchLevelForType(simpleNamePattern, qualificationPattern, type)) != IMPOSSIBLE_MATCH)
-		return level;
-	
-	// matches superclass
-	if (!type.isInterface() && !CharOperation.equals(type.compoundName, TypeConstants.JAVA_LANG_OBJECT)) {
-		if ((level = this.matchLevelAsSubtype(type.superclass(), simpleNamePattern, qualificationPattern)) != IMPOSSIBLE_MATCH) {
-			return level;
-		}
-	}
-
-	// matches interfaces
-	ReferenceBinding[] interfaces = type.superInterfaces();
-	if (interfaces == null) {
-		return INACCURATE_MATCH;
-	} else {
-		for (int i = 0; i < interfaces.length; i++) {
-			if ((level = this.matchLevelAsSubtype(interfaces[i], simpleNamePattern, qualificationPattern)) != IMPOSSIBLE_MATCH) {
-				return level;
-			};
-		}
-	}
-
-	return IMPOSSIBLE_MATCH;
-}
-
-/**
- * Returns whether one of the given declaring types is the given receiver type.
- * Returns ACCURATE_MATCH if it does.
- * Returns INACCURATE_MATCH if resolve failed.
- * Returns IMPOSSIBLE_MATCH if it doesn't.
- */
-protected int matchLevelForType(char[][][] declaringTypes, ReferenceBinding receiverType) {
-	if (receiverType == null) return INACCURATE_MATCH;
-	if (declaringTypes == null) {
-		return INACCURATE_MATCH; // we were not able to compute the declaring types, default to inaccurate
-	} else {
-		for (int i = 0, max = declaringTypes.length; i < max; i++) {
-			if (CharOperation.equals(declaringTypes[i], receiverType.compoundName)) {
-				return ACCURATE_MATCH;
-			}
-		}
-		return IMPOSSIBLE_MATCH;
-	}
-}
-
-/**
- * Returns whether the given type binding matches the given simple name pattern 
- * and qualification pattern.
- * Returns ACCURATE_MATCH if it does.
- * Returns INACCURATE_MATCH if resolve failed.
- * Returns IMPOSSIBLE_MATCH if it doesn't.
- */
-protected int matchLevelForType(char[] simpleNamePattern, char[] qualificationPattern, TypeBinding type) {
-	if (type == null) return INACCURATE_MATCH;
-	char[] qualifiedPackageName = type.qualifiedPackageName();
-	char[] qualifiedSourceName = 
-		type instanceof LocalTypeBinding ?
-			CharOperation.concat("1".toCharArray(), type.qualifiedSourceName(), '.') : //$NON-NLS-1$
-			type.qualifiedSourceName();
-	if (this.matchesType(
-			simpleNamePattern, 
-			qualificationPattern, 
-			qualifiedPackageName.length == 0 ? 
-				qualifiedSourceName : 
-				CharOperation.concat(qualifiedPackageName, qualifiedSourceName, '.'))) {
-		return ACCURATE_MATCH;
-	} else {
-		return IMPOSSIBLE_MATCH;
-	}
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperInterfaceReferencePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperInterfaceReferencePattern.java
deleted file mode 100644
index 32e4790..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperInterfaceReferencePattern.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*******************************************************************************
- * 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 org.eclipse.jdt.internal.core.search.matching;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
-
-public class SuperInterfaceReferencePattern extends SuperTypeReferencePattern {
-public SuperInterfaceReferencePattern(char[] superQualification, char[] superSimpleName, int matchMode, boolean isCaseSensitive) {
-	super(superQualification, superSimpleName, matchMode, isCaseSensitive);
-}
-/**
- * @see SearchPattern#matchIndexEntry
- */
-protected boolean matchIndexEntry() {
-	return
-		this.decodedSuperClassOrInterface == IIndexConstants.INTERFACE_SUFFIX
-		&& super.matchIndexEntry();
-}
-public String toString(){
-	StringBuffer buffer = new StringBuffer(20);
-	buffer.append("SuperInterfaceReferencePattern: <"); //$NON-NLS-1$
-	if (superSimpleName != null) buffer.append(superSimpleName);
-	buffer.append(">, "); //$NON-NLS-1$
-	switch(matchMode){
-		case EXACT_MATCH : 
-			buffer.append("exact match, "); //$NON-NLS-1$
-			break;
-		case PREFIX_MATCH :
-			buffer.append("prefix match, "); //$NON-NLS-1$
-			break;
-		case PATTERN_MATCH :
-			buffer.append("pattern match, "); //$NON-NLS-1$
-			break;
-	}
-	if (isCaseSensitive)
-		buffer.append("case sensitive"); //$NON-NLS-1$
-	else
-		buffer.append("case insensitive"); //$NON-NLS-1$
-	return buffer.toString();
-}
-
-/**
- * @see SearchPattern#matchesBinary
- */
-public boolean matchesBinary(Object binaryInfo, Object enclosingBinaryInfo) {
-	if (!(binaryInfo instanceof IBinaryType)) return false;
-	IBinaryType type = (IBinaryType)binaryInfo;
-
-	char[][] superInterfaces = type.getInterfaceNames();
-	if (superInterfaces != null) {
-		for (int i = 0, max = superInterfaces.length; i < max; i++) {
-			char[] superInterfaceName = (char[])superInterfaces[i].clone();
-			CharOperation.replace(superInterfaceName, '/', '.');
-			if (this.matchesType(this.superSimpleName, this.superQualification, superInterfaceName)){
-				return true;
-			}
-		}
-	}
-	return false;
-}
-
-/**
- * @see SearchPattern#matchLevel(Binding)
- */
-public int matchLevel(Binding binding) {
-	if (binding == null) return INACCURATE_MATCH;
-	if (!(binding instanceof ReferenceBinding)) return IMPOSSIBLE_MATCH;
-
-	// super interfaces
-	int level = IMPOSSIBLE_MATCH;
-	ReferenceBinding type = (ReferenceBinding) binding;
-	ReferenceBinding[] superInterfaces = type.superInterfaces();
-	for (int i = 0, max = superInterfaces.length; i < max; i++){
-		int newLevel = this.matchLevelForType(this.superSimpleName, this.superQualification, superInterfaces[i]);
-		switch (newLevel) {
-			case IMPOSSIBLE_MATCH:
-				break;
-			case ACCURATE_MATCH:
-				return ACCURATE_MATCH;
-			default: // ie. INACCURATE_MATCH
-				level = newLevel;
-				break;
-		}
-	}
-	return level;
-}
-}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
index 1e8da4a..24a4592 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeNamesCollector.java
@@ -13,98 +13,58 @@
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.SubProgressMonitor;
-import org.eclipse.jdt.core.IBuffer;
-import org.eclipse.jdt.core.IClassFile;
+import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchConstants;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.core.search.SearchEngine;
-import org.eclipse.jdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.Initializer;
-import org.eclipse.jdt.internal.compiler.ast.LocalTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MemberTypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.env.ISourceType;
-import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
-import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
-import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
-import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.parser.SourceTypeConverter;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
-import org.eclipse.jdt.internal.core.JavaModelManager;
-import org.eclipse.jdt.internal.core.JavaProject;
-import org.eclipse.jdt.internal.core.Openable;
-import org.eclipse.jdt.internal.core.Util;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.IInfoConstants;
-import org.eclipse.jdt.internal.core.search.IndexSearchAdapter;
-import org.eclipse.jdt.internal.core.search.PathCollector;
-import org.eclipse.jdt.internal.core.search.PatternSearchJob;
+import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.search.*;
 import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
 import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Collects the super type names of a given declaring type.
  * Returns NOT_FOUND_DECLARING_TYPE if the declaring type was not found.
  * Returns null if the declaring type pattern doesn't require an exact match.
  */
-public class SuperTypeNamesCollector implements ITypeRequestor {
-	SearchPattern pattern;
-	char[] typeSimpleName;
-	char[] typeQualification;
-	MatchLocator locator;
-	IType type; 
-	IProgressMonitor progressMonitor;
-	char[][][] result;
-	int resultIndex;
-	
-	
+public class SuperTypeNamesCollector {
+
+SearchPattern pattern;
+char[] typeSimpleName;
+char[] typeQualification;
+MatchLocator locator;
+IType type; 
+IProgressMonitor progressMonitor;
+char[][][] result;
+int resultIndex;
+
 /**
  * An ast visitor that visits type declarations and member type declarations
  * collecting their super type names.
  */
-public class TypeDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
-	public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
-		ReferenceBinding type = typeDeclaration.binding;
-		if (SuperTypeNamesCollector.this.matches(type)) {
-			SuperTypeNamesCollector.this.collectSuperTypeNames(type);
-		}
-		return true;
-	}
-	public boolean visit(AnonymousLocalTypeDeclaration typeDeclaration, BlockScope scope) {
-		ReferenceBinding type = typeDeclaration.binding;
-		if (SuperTypeNamesCollector.this.matches(type)) {
-			SuperTypeNamesCollector.this.collectSuperTypeNames(type);
-		}
+public class TypeDeclarationVisitor extends ASTVisitor {
+	public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
+		ReferenceBinding binding = typeDeclaration.binding;
+		if (SuperTypeNamesCollector.this.matches(binding))
+			SuperTypeNamesCollector.this.collectSuperTypeNames(binding);
 		return true;
 	}
 	public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) {
-		ReferenceBinding type = typeDeclaration.binding;
-		if (SuperTypeNamesCollector.this.matches(type)) {
-			SuperTypeNamesCollector.this.collectSuperTypeNames(type);
-		}
+		ReferenceBinding binding = typeDeclaration.binding;
+		if (SuperTypeNamesCollector.this.matches(binding))
+			SuperTypeNamesCollector.this.collectSuperTypeNames(binding);
 		return true;
 	}
-	public boolean visit(MemberTypeDeclaration memberTypeDeclaration, 	ClassScope scope) {
-		ReferenceBinding type = memberTypeDeclaration.binding;
-		if (SuperTypeNamesCollector.this.matches(type)) {
-			SuperTypeNamesCollector.this.collectSuperTypeNames(type);
-		}
+	public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
+		ReferenceBinding binding = memberTypeDeclaration.binding;
+		if (SuperTypeNamesCollector.this.matches(binding))
+			SuperTypeNamesCollector.this.collectSuperTypeNames(binding);
 		return true;
 	}
 	public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
@@ -120,7 +80,7 @@
 		return false; // don't visit method declarations
 	}
 }
-	
+
 public SuperTypeNamesCollector(
 	SearchPattern pattern,
 	char[] typeSimpleName,
@@ -128,7 +88,7 @@
 	MatchLocator locator,
 	IType type, 
 	IProgressMonitor progressMonitor) {
-		
+
 	this.pattern = pattern;
 	this.typeSimpleName = typeSimpleName;
 	this.typeQualification = typeQualification;
@@ -137,303 +97,199 @@
 	this.progressMonitor = progressMonitor;
 }
 
+protected void addToResult(char[][] compoundName) {
+	int resultLength = this.result.length;
+	for (int i = 0; i < resultLength; i++)
+		if (CharOperation.equals(this.result[i], compoundName)) return; // already known
+
+	if (resultLength == this.resultIndex)
+		System.arraycopy(this.result, 0, this.result = new char[resultLength*2][][], 0, resultLength);
+	this.result[this.resultIndex++] = compoundName;
+}
 /*
  * Parse the given compiation unit and build its type bindings.
  * Don't build methods and fields.
  */
-private CompilationUnitDeclaration buildBindings(ICompilationUnit compilationUnit) throws JavaModelException {
-	final IFile file = 
-		compilationUnit.isWorkingCopy() ?
-			(IFile)compilationUnit.getOriginalElement().getResource() :
-			(IFile)compilationUnit.getResource();
-	
-	// get main type name
+protected CompilationUnitDeclaration buildBindings(ICompilationUnit compilationUnit) throws JavaModelException {
+	final IFile file = (IFile) compilationUnit.getResource();
 	final String fileName = file.getFullPath().lastSegment();
-	final char[] mainTypeName =
-		fileName.substring(0, fileName.length() - 5).toCharArray();
-	
+	final char[] mainTypeName = fileName.substring(0, fileName.length() - 5).toCharArray();
+
 	// source unit
-	IBuffer buffer;
+	IBuffer buffer = compilationUnit.getBuffer();
 	final char[] source = 
-		compilationUnit.isWorkingCopy() ?
-			(buffer = compilationUnit.getBuffer()) == null ? null : buffer.getCharacters() :
-			Util.getResourceContentsAsCharArray(file);
+		compilationUnit.isWorkingCopy()
+			? (buffer == null ? null : buffer.getCharacters())
+			: Util.getResourceContentsAsCharArray(file);
 	org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = 
 		new org.eclipse.jdt.internal.compiler.env.ICompilationUnit() {
-			public char[] getContents() {
-				return source;
-			}
-			public char[] getFileName() {
-				return fileName.toCharArray();
-			}
-			public char[] getMainTypeName() {
-				return mainTypeName;
-			}
-			public char[][] getPackageName() {
-				return null;
-			}
+			public char[] getContents() { return source; }
+			public char[] getFileName() { return fileName.toCharArray(); }
+			public char[] getMainTypeName() { return mainTypeName; }
+			public char[][] getPackageName() { return null; }
 		};
-	
-	// diet parse
-	CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, 0);
-	CompilationUnitDeclaration unit = this.locator.parser.dietParse(sourceUnit, compilationResult);
+
+	CompilationResult compilationResult = new CompilationResult(sourceUnit, 1, 1, 0);
+	CompilationUnitDeclaration unit = this.locator.basicParser().dietParse(sourceUnit, compilationResult);
 	if (unit != null) {
 		this.locator.lookupEnvironment.buildTypeBindings(unit);
 		this.locator.lookupEnvironment.completeTypeBindings(unit, false);
 	}
 	return unit;
 }
-
-
-protected char[][][] collect() throws JavaModelException {
-	
+public char[][][] collect() throws JavaModelException {
 	if (this.type != null) {
 		// Collect the paths of the cus that are in the hierarchy of the given type
 		this.result = new char[1][][];
 		this.resultIndex = 0;
-		JavaProject javaProject = (JavaProject)this.type.getJavaProject();
-		this.locator.initializeNameEnvironment(javaProject);
-		this.locator.initialize(javaProject);
-		synchronized(this.locator.nameLookup) { // prevent 2 concurrent accesses to name lookup while the working copies are set
-			this.locator.nameLookup.setUnitsToLookInside(this.locator.workingCopies);
+		JavaProject javaProject = (JavaProject) this.type.getJavaProject();
+		this.locator.initialize(javaProject, 0);
+		this.locator.nameLookup.setUnitsToLookInside(this.locator.workingCopies); // NB: this uses a PerThreadObject, so it is thread safe
+		try {
+			if (this.type.isBinary()) {
+				BinaryTypeBinding binding = this.locator.cacheBinaryType(this.type);
+				if (binding != null)
+					collectSuperTypeNames(binding);
+			} else {
+				ICompilationUnit unit = this.type.getCompilationUnit();
+				CompilationUnitDeclaration parsedUnit = buildBindings(unit);
+				if (parsedUnit != null)
+					parsedUnit.traverse(new TypeDeclarationVisitor(), parsedUnit.scope);
+			}
+		} catch (AbortCompilation e) {
+			// problem with classpath: report inacurrate matches
+			return null;
+		} finally {
+			this.locator.nameLookup.setUnitsToLookInside(null);
+		}
+		if (this.result.length > this.resultIndex)
+			System.arraycopy(this.result, 0, this.result = new char[this.resultIndex][][], 0, this.resultIndex);
+		return this.result;
+	}
+
+	// Collect the paths of the cus that declare a type which matches declaringQualification + declaringSimpleName
+	String[] paths = this.getPathsOfDeclaringType();
+	if (paths == null) return null;
+
+	// Create bindings from source types and binary types and collect super type names of the type declaration 
+	// that match the given declaring type
+	Util.sort(paths); // sort by projects
+	JavaProject previousProject = null;
+	this.result = new char[1][][];
+	this.resultIndex = 0;
+	try {
+		for (int i = 0, length = paths.length; i < length; i++) {
 			try {
-				if (this.type.isBinary()) {
-					BinaryTypeBinding binding = this.locator.cacheBinaryType(this.type);
-					if (binding != null) {
-						this.collectSuperTypeNames(binding);
-					}
-				} else {
-					ICompilationUnit unit = this.type.getCompilationUnit();
-					CompilationUnitDeclaration parsedUnit = this.buildBindings(unit);
-					if (parsedUnit != null) {
+				Openable openable = this.locator.handleFactory.createOpenable(paths[i], this.locator.scope);
+				if (openable == null) continue; // outside classpath
+
+				IJavaProject project = openable.getJavaProject();
+				if (!project.equals(previousProject)) {
+					if (previousProject != null)
+						this.locator.nameLookup.setUnitsToLookInside(null);
+					previousProject = (JavaProject) project;
+					this.locator.initialize(previousProject, 0);
+					this.locator.nameLookup.setUnitsToLookInside(this.locator.workingCopies);
+				}
+				if (openable instanceof ICompilationUnit) {
+					ICompilationUnit unit = (ICompilationUnit) openable;
+					CompilationUnitDeclaration parsedUnit = buildBindings(unit);
+					if (parsedUnit != null)
 						parsedUnit.traverse(new TypeDeclarationVisitor(), parsedUnit.scope);
-					}
+				} else if (openable instanceof IClassFile) {
+					IClassFile classFile = (IClassFile) openable;
+					BinaryTypeBinding binding = this.locator.cacheBinaryType(classFile.getType());
+					if (matches(binding))
+						collectSuperTypeNames(binding);
 				}
 			} catch (AbortCompilation e) {
-				// problem with classpath: report inacurrate matches
-				return null;
-			} finally {
-				this.locator.nameLookup.setUnitsToLookInside(null);
+				// ignore: continue with next element
+			} catch (JavaModelException e) {
+				// ignore: continue with next element
 			}
 		}
-		return this.result;
-	} else {	
-		// Collect the paths of the cus that declare a type which matches declaringQualification + declaringSimpleName
-		String[] paths = this.getPathsOfDeclaringType();
-		
-		// Create bindings from source types and binary types
-		// and collect super type names of the type declaration 
-		// that match the given declaring type
-		if (paths != null) {
-			Util.sort(paths); // sort by projects
-			JavaProject previousProject = null;
-			this.result = new char[1][][];
-			this.resultIndex = 0;
-			try {
-				for (int i = 0, length = paths.length; i < length; i++) {
-					try {
-						Openable openable = this.locator.handleFactory.createOpenable(paths[i], this.locator.scope);
-						if (openable == null)
-							continue; // outside classpath
-						IJavaProject project = openable.getJavaProject();
-						if (!project.equals(previousProject)) {
-							if (previousProject != null) {
-								this.locator.nameLookup.setUnitsToLookInside(null);
-							}
-							previousProject = (JavaProject)project;
-							this.locator.initializeNameEnvironment(previousProject);
-							this.locator.initialize(previousProject);
-							this.locator.nameLookup.setUnitsToLookInside(this.locator.workingCopies);
-						}
-						if (openable instanceof ICompilationUnit) {
-							ICompilationUnit unit = (ICompilationUnit)openable;
-							CompilationUnitDeclaration parsedUnit = this.buildBindings(unit);
-							if (parsedUnit != null) {
-								parsedUnit.traverse(new TypeDeclarationVisitor(), parsedUnit.scope);
-							}
-						} else if (openable instanceof IClassFile) {
-							IClassFile classFile = (IClassFile)openable;
-							BinaryTypeBinding binding = this.locator.cacheBinaryType(classFile.getType());
-							if (this.matches(binding)) {
-								this.collectSuperTypeNames(binding);
-							}
-						}
-					} catch (AbortCompilation e) {
-						// ignore: continue with next element
-					} catch (JavaModelException e) {
-						// ignore: continue with next element
-					}
-				}
-			} finally {
-				if (previousProject != null) {
-					this.locator.nameLookup.setUnitsToLookInside(null);
-				}
-			}
-			System.arraycopy(this.result, 0, this.result = new char[this.resultIndex][][], 0, this.resultIndex);
-			return this.result;
-		} else {
-			return null;
+	} finally {
+		if (previousProject != null)
+			this.locator.nameLookup.setUnitsToLookInside(null);
+	}
+	if (this.result.length > this.resultIndex)
+		System.arraycopy(this.result, 0, this.result = new char[this.resultIndex][][], 0, this.resultIndex);
+	return this.result;
+}
+/**
+ * Collects the names of all the supertypes of the given type.
+ */
+protected void collectSuperTypeNames(ReferenceBinding binding) {
+	ReferenceBinding superclass = binding.superclass();
+	if (superclass != null) {
+		this.addToResult(superclass.compoundName);
+		this.collectSuperTypeNames(superclass);
+	}
+
+	ReferenceBinding[] interfaces = binding.superInterfaces();
+	if (interfaces != null) {
+		for (int i = 0; i < interfaces.length; i++) {
+			ReferenceBinding interfaceBinding = interfaces[i];
+			this.addToResult(interfaceBinding.compoundName);
+			this.collectSuperTypeNames(interfaceBinding);
 		}
 	}
 }
-protected boolean matches(ReferenceBinding type) {
-	if (type == null || type.compoundName == null) return false;
-	return this.matches(type.compoundName);
+protected String[] getPathsOfDeclaringType() {
+	if (this.typeQualification == null && this.typeSimpleName == null) return null;
+
+	final PathCollector pathCollector = new PathCollector();
+	IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
+	IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
+	SearchPattern searchPattern = new TypeDeclarationPattern(
+		this.typeSimpleName != null ? null : this.typeQualification, // use the qualification only if no simple name
+		null, // do find member types
+		this.typeSimpleName,
+		IIndexConstants.TYPE_SUFFIX,
+		this.pattern.matchRule);
+	IndexQueryRequestor searchRequestor = new IndexQueryRequestor(){
+		public boolean acceptIndexMatch(String documentPath, SearchPattern indexRecord, SearchParticipant participant) {
+			TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord;
+			if (record.enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR) {  // filter out local and anonymous classes
+				pathCollector.acceptIndexMatch(documentPath, indexRecord, participant);
+			}
+			return true;
+		}		
+	};		
+
+	indexManager.performConcurrentJob(
+		new PatternSearchJob(
+			searchPattern, 
+			new JavaSearchParticipant(this.locator.workingCopies),
+			scope, 
+			searchRequestor),
+		IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
+		progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));
+	return pathCollector.getPaths();
 }
 protected boolean matches(char[][] compoundName) {
 	int length = compoundName.length;
 	if (length == 0) return false;
 	char[] simpleName = compoundName[length-1];
 	int last = length - 1;
-	if (this.typeSimpleName != null) {
+	if (this.typeSimpleName == null || this.pattern.matchesName(simpleName, this.typeSimpleName)) {
 		// most frequent case: simple name equals last segment of compoundName
-		if (this.pattern.matchesName(simpleName, this.typeSimpleName)) {
-			char[][] qualification = new char[last][];
-			System.arraycopy(compoundName, 0, qualification, 0, last);
-			return 
-				this.pattern.matchesName(
-					this.typeQualification, 
-					CharOperation.concatWith(qualification, '.'));
-		} else if (!CharOperation.endsWith(simpleName, this.typeSimpleName)) {
-			return false;
-		} else {
-			// member type -> transform A.B.C$D into A.B.C.D
-			System.arraycopy(compoundName, 0, compoundName = new char[length+1][], 0, last);
-			int dollar = CharOperation.indexOf('$', simpleName);
-			if (dollar == -1) return false;
-			compoundName[last] = CharOperation.subarray(simpleName, 0, dollar);
-			compoundName[length] = CharOperation.subarray(simpleName, dollar+1, simpleName.length); 
-			return this.matches(compoundName);
-		}
-	} else {
 		char[][] qualification = new char[last][];
 		System.arraycopy(compoundName, 0, qualification, 0, last);
-		return 
-			this.pattern.matchesName(
-				this.typeQualification, 
-				CharOperation.concatWith(qualification, '.'));
-	}
-}
-private void addToResult(char[][] compoundName) {
-	int resultLength = this.result.length;
-	for (int i = 0; i < resultLength; i++) {
-		if (CharOperation.equals(this.result[i], compoundName)) {
-			// already known
-			return;
-		}
-	}
-	if (resultLength == this.resultIndex) {
-		System.arraycopy(
-			this.result, 
-			0, 
-			this.result = new char[resultLength*2][][], 
-			0, 
-			resultLength);
-	}
-	this.result[this.resultIndex++] = compoundName;
-}
-/**
- * Collects the names of all the supertypes of the given type.
- */
-protected void collectSuperTypeNames(ReferenceBinding type) {
-
-	// superclass
-	ReferenceBinding superclass = type.superclass();
-	if (superclass != null) {
-		this.addToResult(superclass.compoundName);
-		this.collectSuperTypeNames(superclass);
+		return this.pattern.matchesName(this.typeQualification, CharOperation.concatWith(qualification, '.'));
 	}
 
-	// interfaces
-	ReferenceBinding[] interfaces = type.superInterfaces();
-	if (interfaces != null) {
-		for (int i = 0; i < interfaces.length; i++) {
-			ReferenceBinding interfase = interfaces[i];
-			this.addToResult(interfase.compoundName);
-			this.collectSuperTypeNames(interfase);
-		}
-	}
+	if (!CharOperation.endsWith(simpleName, this.typeSimpleName)) return false;
+
+	// member type -> transform A.B.C$D into A.B.C.D
+	System.arraycopy(compoundName, 0, compoundName = new char[length+1][], 0, last);
+	int dollar = CharOperation.indexOf('$', simpleName);
+	if (dollar == -1) return false;
+	compoundName[last] = CharOperation.subarray(simpleName, 0, dollar);
+	compoundName[length] = CharOperation.subarray(simpleName, dollar+1, simpleName.length); 
+	return this.matches(compoundName);
 }
-
-
-private String[] getPathsOfDeclaringType() {
-	if (this.typeQualification != null || this.typeSimpleName != null) {
-		final PathCollector pathCollector = new PathCollector();
-		IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
-	
-		IndexManager indexManager = ((JavaModelManager)JavaModelManager.getJavaModelManager())
-										.getIndexManager();
-		int detailLevel = IInfoConstants.PathInfo;
-		SearchPattern searchPattern = new TypeDeclarationPattern(
-			this.typeSimpleName != null ? null : this.typeQualification, // use the qualification only if no simple name
-			null, // do find member types
-			this.typeSimpleName,
-			IIndexConstants.TYPE_SUFFIX,
-			this.pattern.matchMode, 
-			true);
-		IIndexSearchRequestor searchRequestor = new IndexSearchAdapter(){
-			public void acceptClassDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) {
-				if (enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR) { // filter out local and anonymous classes
-					pathCollector.acceptClassDeclaration(resourcePath, simpleTypeName, enclosingTypeNames, packageName);
-				}
-			}		
-			public void acceptInterfaceDeclaration(String resourcePath, char[] simpleTypeName, char[][] enclosingTypeNames, char[] packageName) {
-				if (enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR) { // filter out local and anonymous classes
-					pathCollector.acceptInterfaceDeclaration(resourcePath, simpleTypeName, enclosingTypeNames, packageName);
-				}
-			}		
-		};		
-
-		indexManager.performConcurrentJob(
-			new PatternSearchJob(
-				searchPattern, 
-				scope, 
-				detailLevel, 
-				searchRequestor, 
-				indexManager),
-			IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
-			progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));
-		return pathCollector.getPaths();
-
-	}
-	return null;
+protected boolean matches(ReferenceBinding binding) {
+	return binding != null && binding.compoundName != null && this.matches(binding.compoundName);
 }
-/*
- * @see ITypeRequestor#accept(IBinaryType, PackageBinding)
- */
-public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
-	this.locator.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
 }
-
-/*
- * @see ITypeRequestor#accept(ICompilationUnit)
- */
-public void accept(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit) {
-	this.locator.lookupEnvironment.problemReporter.abortDueToInternalError(
-		new StringBuffer(org.eclipse.jdt.internal.compiler.util.Util.bind("accept.cannot")) //$NON-NLS-1$
-			.append(sourceUnit.getFileName())
-			.toString());
-}
-
-/*
- * @see ITypeRequestor#accept(ISourceType[], PackageBinding)
- */
-public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
-	CompilationResult result = new CompilationResult(sourceTypes[0].getFileName(), 1, 1, 0);
-	CompilationUnitDeclaration unit =
-		SourceTypeConverter.buildCompilationUnit(
-			sourceTypes, //sourceTypes[0] is always toplevel here
-			false, // no need for field and methods
-			true, // need member types
-			false, // no need for field initialization
-			this.locator.lookupEnvironment.problemReporter, 
-			result);
-
-	if (unit != null) {
-		this.locator.lookupEnvironment.buildTypeBindings(unit);
-		this.locator.lookupEnvironment.completeTypeBindings(unit, false);
-	}
-}
-
-}
-
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferenceLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferenceLocator.java
new file mode 100644
index 0000000..929c54a
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferenceLocator.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class SuperTypeReferenceLocator extends PatternLocator {
+
+protected SuperTypeReferencePattern pattern;
+
+public SuperTypeReferenceLocator(SuperTypeReferencePattern pattern) {
+	super(pattern);
+
+	this.pattern = pattern;
+}
+//public int match(ASTNode node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(Expression node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(FieldDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(MethodDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(MessageSend node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(Reference node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(TypeDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+public int match(TypeReference node, MatchingNodeSet nodeSet) {
+	if (this.pattern.superSimpleName == null)
+		return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+
+	char[] typeRefSimpleName = null;
+	if (node instanceof SingleTypeReference) {
+		typeRefSimpleName = ((SingleTypeReference) node).token;
+	} else { // QualifiedTypeReference
+		char[][] tokens = ((QualifiedTypeReference) node).tokens;
+		typeRefSimpleName = tokens[tokens.length-1];
+	}				
+	if (matchesName(this.pattern.superSimpleName, typeRefSimpleName))
+		return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+
+	return IMPOSSIBLE_MATCH;
+}
+
+protected int matchContainer() {
+	return CLASS_CONTAINER;
+}
+public int resolveLevel(ASTNode node) {
+	if (!(node instanceof TypeReference)) return IMPOSSIBLE_MATCH;
+
+	TypeReference typeRef = (TypeReference) node;
+	TypeBinding binding = typeRef.resolvedType;
+	if (binding == null) return INACCURATE_MATCH;
+	return resolveLevelForType(this.pattern.superSimpleName, this.pattern.superQualification, binding);
+}
+public int resolveLevel(Binding binding) {
+	if (binding == null) return INACCURATE_MATCH;
+	if (!(binding instanceof ReferenceBinding)) return IMPOSSIBLE_MATCH;
+
+	ReferenceBinding type = (ReferenceBinding) binding;
+	int level = IMPOSSIBLE_MATCH;
+	if (!this.pattern.checkOnlySuperinterfaces) {
+		level = resolveLevelForType(this.pattern.superSimpleName, this.pattern.superQualification, type.superclass());
+		if (level == ACCURATE_MATCH) return ACCURATE_MATCH;
+	}
+
+	ReferenceBinding[] superInterfaces = type.superInterfaces();
+	for (int i = 0, max = superInterfaces.length; i < max; i++) {
+		int newLevel = resolveLevelForType(this.pattern.superSimpleName, this.pattern.superQualification, superInterfaces[i]);
+		if (newLevel > level) {
+			if (newLevel == ACCURATE_MATCH) return ACCURATE_MATCH;
+			level = newLevel;
+		}
+	}
+	return level;
+}
+public String toString() {
+	return "Locator for " + this.pattern.toString(); //$NON-NLS-1$
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java
index 32e1807..3a25cac 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/SuperTypeReferencePattern.java
@@ -10,205 +10,271 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
-import org.eclipse.jdt.internal.compiler.ast.*;
-import org.eclipse.jdt.internal.compiler.lookup.*;
+import java.io.*;
+import java.util.HashMap;
 
-import org.eclipse.jdt.internal.core.index.*;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.core.search.*;
-import org.eclipse.jdt.internal.core.search.indexing.*;
+import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
 import org.eclipse.jdt.internal.core.index.impl.*;
 import org.eclipse.jdt.internal.core.search.*;
 
-import java.io.*;
-import java.util.HashMap;
-
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-
 public class SuperTypeReferencePattern extends SearchPattern {
 
-	public char[] superQualification;
-	public char[] superSimpleName;
+private static ThreadLocal indexRecord = new ThreadLocal() {
+	protected Object initialValue() {
+		return new SuperTypeReferencePattern(null, null, false, R_EXACT_MATCH | R_CASE_SENSITIVE);
+	}
+};
 
-	protected char[] decodedSuperQualification;
-	protected char[] decodedSuperSimpleName;
-	protected char decodedSuperClassOrInterface;
-	protected char[] decodedQualification;
-	protected char[] decodedSimpleName;
-	protected char[] decodedEnclosingTypeName;
-	protected char decodedClassOrInterface;
-	protected int decodedModifiers;
+public char[] superQualification;
+public char[] superSimpleName;
+public char superClassOrInterface;
+
+public char[] pkgName;
+public char[] simpleName;
+public char[] enclosingTypeName;
+public char classOrInterface;
+public int modifiers;
+
+protected boolean checkOnlySuperinterfaces; // used for IMPLEMENTORS
+
+/**
+ * A map from IndexInputs to IEntryResult[]
+ */
+public HashMap entryResults;
+
+private static final EntryResult[] NO_ENTRY_RESULT = new EntryResult[0];
+
+public static char[] createIndexKey(
+	int modifiers,
+	char[] packageName,
+	char[] typeName,
+	char[][] enclosingTypeNames,
+	char classOrInterface,
+	char[] superTypeName,
+	char superClassOrInterface) {
+
+	SuperTypeReferencePattern record = getSuperTypeReferenceRecord();
+	record.modifiers = modifiers;
+	record.pkgName = packageName;
+	record.classOrInterface = classOrInterface;
+	record.superClassOrInterface = superClassOrInterface;
+	if (superTypeName == null)
+		superTypeName = OBJECT;
+	record.enclosingTypeName = CharOperation.concatWith(enclosingTypeNames, '$');
+	record.simpleName = CharOperation.lastSegment(typeName, '.');
+	record.superSimpleName = CharOperation.lastSegment(superTypeName, '.');
+	record.superQualification = null;
+	if (record.superSimpleName != superTypeName) {
+		int length = superTypeName.length - record.superSimpleName.length - 1;
+		record.superQualification = new char[length];
+		System.arraycopy(superTypeName, 0, record.superQualification, 0, length);
+	}
+
+	// if the supertype name contains a $, then split it into: source name and append the $ prefix to the qualification
+	//	e.g. p.A$B ---> p.A$ + B
+	char[] superTypeSourceName = CharOperation.lastSegment(record.superSimpleName, '$');
+	if (superTypeSourceName != record.superSimpleName) {
+		int start = record.superQualification == null ? 0 : record.superQualification.length + 1;
+		int prefixLength = record.superSimpleName.length - superTypeSourceName.length;
+		char[] mangledQualification = new char[start + prefixLength];
+		if (record.superQualification != null) {
+			System.arraycopy(record.superQualification, 0, mangledQualification, 0, start-1);
+			mangledQualification[start-1] = '.';
+		}
+		System.arraycopy(record.superSimpleName, 0, mangledQualification, start, prefixLength);
+		record.superQualification = mangledQualification;
+		record.superSimpleName = superTypeSourceName;
+	} 
 	
-	/**
-	 * A map from IndexInputs to IEntryResult[]
-	 */
-	public HashMap entryResults;
-	
-	private static final IEntryResult[] NO_ENTRY_RESULT = new IEntryResult[0];
-	
+	return record.encodeIndexKey();
+}
+public static SuperTypeReferencePattern getSuperTypeReferenceRecord() {
+	return (SuperTypeReferencePattern)indexRecord.get();
+}
+public SuperTypeReferencePattern(char[] superQualification, char[] superSimpleName, int matchRule) {
+	this(superQualification, superSimpleName, false, matchRule);
+}
 public SuperTypeReferencePattern(
 	char[] superQualification,
 	char[] superSimpleName,
-	int matchMode, 
-	boolean isCaseSensitive) {
+	boolean checkOnlySuperinterfaces,
+	int matchRule) {
 
-	super(matchMode, isCaseSensitive);
+	super(SUPER_REF_PATTERN, matchRule);
 
+	boolean isCaseSensitive = isCaseSensitive();
 	this.superQualification = isCaseSensitive ? superQualification : CharOperation.toLowerCase(superQualification);
 	this.superSimpleName = isCaseSensitive ? superSimpleName : CharOperation.toLowerCase(superSimpleName);
-	
-	this.needsResolve = superQualification != null;
+	this.mustResolve = superQualification != null;
+	this.checkOnlySuperinterfaces = checkOnlySuperinterfaces; // ie. skip the superclass
 }
 /*
- * "superRef/Object/java.lang/X/p" represents "class p.X extends java.lang.Object"
- * "superRef/Exception//X/p" represents "class p.X extends Exception"
+ * superSimpleName / superQualification / superClassOrInterface /  simpleName / enclosingTypeName / pkgName / classOrInterface modifiers
  */
-public void decodeIndexEntry(IEntryResult entryResult){
-
-	char[] word = entryResult.getWord();
-	int slash = SUPER_REF.length - 1;
-	decodedSuperSimpleName = CharOperation.subarray(word, slash+1, slash = CharOperation.indexOf(SEPARATOR, word, slash+1));
+public void decodeIndexKey(char[] key) {
+	int slash = -1;
+	this.superSimpleName = CharOperation.subarray(key, slash + 1, slash = CharOperation.indexOf(SEPARATOR, key, slash + 1));
 	int oldSlash = slash;
-	slash = CharOperation.indexOf(SEPARATOR, word, slash+1);
-	if (slash == oldSlash+1){ // could not have been known at index time
-		decodedSuperQualification = null;
-	} else {
-		decodedSuperQualification = CharOperation.subarray(word, oldSlash+1, slash);
-	}
-	decodedSuperClassOrInterface = word[slash+1];
+	slash = CharOperation.indexOf(SEPARATOR, key, slash + 1);
+	this.superQualification = (slash == oldSlash + 1)
+		? null // could not have been known at index time
+		: CharOperation.subarray(key, oldSlash + 1, slash);
+	this.superClassOrInterface = key[slash + 1];
 	slash += 2;
-	decodedSimpleName = CharOperation.subarray(word, slash+1, slash = CharOperation.indexOf(SEPARATOR, word, slash+1));
+	this.simpleName = CharOperation.subarray(key, slash + 1, slash = CharOperation.indexOf(SEPARATOR, key, slash + 1));
 	oldSlash = slash;
-	slash = CharOperation.indexOf(SEPARATOR, word, slash+1);
-	if (slash == oldSlash+1){ // could not have been known at index time
-		decodedEnclosingTypeName = null;
+	slash = CharOperation.indexOf(SEPARATOR, key, slash + 1);
+	if (slash == oldSlash + 1) { // could not have been known at index time
+		this.enclosingTypeName = null;
 	} else {
-		if (slash == oldSlash+2 && word[oldSlash+1] == ONE_ZERO[0]) {
-			decodedEnclosingTypeName = ONE_ZERO;
-		} else {
-			decodedEnclosingTypeName = CharOperation.subarray(word, oldSlash+1, slash);
-		}
+		this.enclosingTypeName = (slash == oldSlash + 2 && key[oldSlash + 1] == ONE_ZERO[0])
+			? ONE_ZERO
+			: CharOperation.subarray(key, oldSlash + 1, slash);
 	}
 	oldSlash = slash;
-	slash = CharOperation.indexOf(SEPARATOR, word, slash+1);
-	if (slash == oldSlash+1){ // could not have been known at index time
-		decodedQualification = null;
-	} else {
-		decodedQualification = CharOperation.subarray(word, oldSlash+1, slash);
-	}
-	
-	decodedClassOrInterface = word[slash+1];
-	decodedModifiers = (int)word[slash+2];
+	slash = CharOperation.indexOf(SEPARATOR, key, slash + 1);
+	this.pkgName = (slash == oldSlash + 1)
+		? null // could not have been known at index time
+		: CharOperation.subarray(key, oldSlash + 1, slash);
+	this.classOrInterface = key[slash + 1];
+	this.modifiers = key[slash + 2]; // implicit cast to int type
 }
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope) throws IOException {
-	for (int i = 0, max = references.length; i < max; i++) {
-		IndexedFile file = input.getIndexedFile(references[i]);
-		String path;
-		if (file != null && scope.encloses(path = IndexedFile.convertPath(file.getPath()))) {
-			requestor.acceptSuperTypeReference(path, decodedQualification, decodedSimpleName, decodedEnclosingTypeName, decodedClassOrInterface, decodedSuperQualification, decodedSuperSimpleName, decodedSuperClassOrInterface, decodedModifiers);
-		}
+/*
+ * superSimpleName / superQualification / superClassOrInterface /  simpleName / enclosingTypeName / pkgName / classOrInterface modifiers
+ */
+public char[] encodeIndexKey() {
+	int superSimpleNameLength = this.superSimpleName == null ? 0 : this.superSimpleName.length;
+	int superQualificationLength = this.superQualification == null ? 0 : this.superQualification.length;
+	int simpleNameLength = this.simpleName == null ? 0 : this.simpleName.length;
+	int enclosingTypeNameLength = this.enclosingTypeName == null ? 0 : this.enclosingTypeName.length;
+	int pkgNameLength = this.pkgName == null ? 0 : this.pkgName.length;
+
+	int length = superSimpleNameLength + superQualificationLength + simpleNameLength
+		+ enclosingTypeNameLength + pkgNameLength + 9;
+	char[] result = new char[length];
+	int pos = 0;
+	if (superSimpleNameLength > 0) {
+		System.arraycopy(this.superSimpleName, 0, result, pos, superSimpleNameLength);
+		pos += superSimpleNameLength;
 	}
+	result[pos++] = SEPARATOR;
+	if (this.superClassOrInterface != 0) { // 0 when querying index
+		if (superQualificationLength > 0) {
+			System.arraycopy(this.superQualification, 0, result, pos, superQualificationLength);
+			pos += superQualificationLength;
+		}
+		result[pos++] = SEPARATOR;
+		result[pos++] = this.superClassOrInterface;
+		result[pos++] = SEPARATOR;
+		if (simpleNameLength > 0) {
+			System.arraycopy(this.simpleName, 0, result, pos, simpleNameLength);
+			pos += simpleNameLength;
+		}
+		result[pos++] = SEPARATOR;
+		if (enclosingTypeNameLength > 0) {
+			System.arraycopy(this.enclosingTypeName, 0, result, pos, enclosingTypeNameLength);
+			pos += enclosingTypeNameLength;
+		}
+		result[pos++] = SEPARATOR;
+		if (pkgNameLength > 0) {
+			System.arraycopy(this.pkgName, 0, result, pos, pkgNameLength);
+			pos += pkgNameLength;
+		}
+		result[pos++] = SEPARATOR;
+		result[pos++] = this.classOrInterface;
+		result[pos++] = (char) this.modifiers;
+	}
+	if (pos != length) {
+		System.arraycopy(result, 0, result = new char[pos], 0, pos);
+	}
+	return result;
 }
 /**
  * Query a given index for matching entries. 
  */
-public void findIndexMatches(IndexInput input, IIndexSearchRequestor requestor, int detailLevel, IProgressMonitor progressMonitor, IJavaSearchScope scope) throws IOException {
+public void findIndexMatches(IndexInput input, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope, IProgressMonitor progressMonitor) throws IOException {
 	if (this.entryResults == null) {
 		// non-optimized case
-		super.findIndexMatches(input, requestor, detailLevel, progressMonitor, scope);	
+		super.findIndexMatches(input, requestor, participant, scope, progressMonitor);	
 		return;
 	}
-	
+
 	if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
-	
+
 	/* narrow down a set of entries using prefix criteria */
-	IEntryResult[] entries = (IEntryResult[])this.entryResults.get(input);
+	EntryResult[] entries = (EntryResult[]) this.entryResults.get(input);
 	if (entries == null) {
 		entries = input.queryEntriesPrefixedBy(SUPER_REF);
-		if (entries == null) {
+		if (entries == null)
 			entries = NO_ENTRY_RESULT;
-		}
 		this.entryResults.put(input, entries);
 	}
 	if (entries == NO_ENTRY_RESULT) return;
 
 	/* only select entries which actually match the entire search pattern */
 	int slash = SUPER_REF.length;
-	char[] simpleName = this.superSimpleName;
-	int length = simpleName == null ? 0 : simpleName.length;
-	nextEntry: for (int i = 0, max = entries.length; i < max; i++){
+	char[] name = this.superSimpleName;
+	int length = name == null ? 0 : name.length;
+	nextEntry: for (int i = 0, max = entries.length; i < max; i++) {
 		/* check that the entry is a super ref to the super simple name */
-		IEntryResult entry = entries[i];
-		if (simpleName != null) {
+		EntryResult entry = entries[i];
+		if (name != null) {
 			char[] word = entry.getWord();
 			if (slash + length >= word.length) continue;
 			
 			// ensure it is the end of the ref (a simple name is not a prefix of ref)
-			if (word[length+slash] != '/') continue; 
+			if (word[length + slash] != '/') continue; 
 			
 			// compare ref to simple name
-			for (int j = 0; j < length; j++) {
-				char value = word[j+slash];
-				if (value != simpleName[j]) continue nextEntry;
+			for (int j = 0; j < length; j++)
+				if (word[j + slash] != name[j]) continue nextEntry;
+		}
+
+		/* retrieve and decode entry */	
+		char[] word = entry.getWord();
+		char[] indexKey = CharOperation.subarray(word, SUPER_REF.length, word.length);
+		SearchPattern record = getIndexRecord();
+		record.decodeIndexKey(indexKey);
+
+		int[] references = entry.getFileReferences();
+		for (int iReference = 0, refererencesLength = references.length; iReference < refererencesLength; iReference++) {
+			String documentPath = IndexedFile.convertPath( input.getIndexedFile(references[iReference]).getPath());
+			if (scope.encloses(documentPath)) {
+				if (!requestor.acceptIndexMatch(documentPath, record, participant)) 
+					throw new OperationCanceledException();
 			}
 		}
-		
-		/* retrieve and decode entry */	
-		this.decodeIndexEntry(entry);
-		feedIndexRequestor(requestor, detailLevel, entry.getFileReferences(), input, scope);
 	}
 }
-
-/**
- * see SearchPattern.indexEntryPrefix()
- */
-public char[] indexEntryPrefix(){
-	return AbstractIndexer.bestReferencePrefix(
-			SUPER_REF,
-			superSimpleName, 
-			matchMode, 
-			isCaseSensitive);
+public SearchPattern getIndexRecord() {
+	return getSuperTypeReferenceRecord();
 }
-/**
- * @see SearchPattern#matchContainer()
- */
-protected int matchContainer() {
-	return CLASS;
+public char[][] getMatchCategories() {
+	return new char[][] {SUPER_REF};
 }
-/**
- * @see SearchPattern#matchIndexEntry
- */
-protected boolean matchIndexEntry() {
+public boolean isMatchingIndexRecord() {
+	SuperTypeReferencePattern record = getSuperTypeReferenceRecord();
+	if (this.checkOnlySuperinterfaces)
+		if (record.superClassOrInterface != IIndexConstants.INTERFACE_SUFFIX) return false;
 
-	/* check type name matches */
-	if (superSimpleName != null){
-		switch(matchMode){
-			case EXACT_MATCH :
-				if (!CharOperation.equals(superSimpleName, decodedSuperSimpleName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PREFIX_MATCH :
-				if (!CharOperation.prefixEquals(superSimpleName, decodedSuperSimpleName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PATTERN_MATCH :
-				if (!CharOperation.match(superSimpleName, decodedSuperSimpleName, isCaseSensitive)){
-					return false;
-				}
-		}
-	}
-	return true;
+	return matchesName(this.superSimpleName, record.superSimpleName);
 }
 public String toString(){
 	StringBuffer buffer = new StringBuffer(20);
-	buffer.append("SuperTypeReferencePattern: <"); //$NON-NLS-1$
-	if (superSimpleName != null) buffer.append(superSimpleName);
+	buffer.append(
+		this.checkOnlySuperinterfaces
+			? "SuperInterfaceReferencePattern: <" //$NON-NLS-1$
+			: "SuperTypeReferencePattern: <"); //$NON-NLS-1$
+	if (superSimpleName != null) 
+		buffer.append(superSimpleName);
+	else
+		buffer.append("*"); //$NON-NLS-1$
 	buffer.append(">, "); //$NON-NLS-1$
-	switch(matchMode){
+	switch(matchMode()){
 		case EXACT_MATCH : 
 			buffer.append("exact match, "); //$NON-NLS-1$
 			break;
@@ -219,108 +285,10 @@
 			buffer.append("pattern match, "); //$NON-NLS-1$
 			break;
 	}
-	if (isCaseSensitive)
+	if (isCaseSensitive())
 		buffer.append("case sensitive"); //$NON-NLS-1$
 	else
 		buffer.append("case insensitive"); //$NON-NLS-1$
 	return buffer.toString();
 }
-
-/**
- * @see SearchPattern#matchesBinary
- */
-public boolean matchesBinary(Object binaryInfo, Object enclosingBinaryInfo) {
-	if (!(binaryInfo instanceof IBinaryType)) return false;
-	IBinaryType type = (IBinaryType)binaryInfo;
-
-	char[] vmName = type.getSuperclassName();
-	if (vmName != null) {
-		char[] superclassName = (char[])vmName.clone();
-		CharOperation.replace(vmName, '/', '.');
-		if (this.matchesType(this.superSimpleName, this.superQualification, superclassName)){
-			return true;
-		}
-	}
-	
-	char[][] superInterfaces = type.getInterfaceNames();
-	if (superInterfaces != null) {
-		for (int i = 0, max = superInterfaces.length; i < max; i++) {
-			char[] superInterfaceName = (char[])superInterfaces[i].clone();
-			CharOperation.replace(superInterfaceName, '/', '.');
-			if (this.matchesType(this.superSimpleName, this.superQualification, superInterfaceName)){
-				return true;
-			}
-		}
-	}
-	return false;
-}
-
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
- */
-public int matchLevel(AstNode node, boolean resolve) {
-	if (!(node instanceof TypeReference)) return IMPOSSIBLE_MATCH;
-
-	TypeReference typeRef = (TypeReference)node;
-	if (resolve) {
-		TypeBinding binding = typeRef.resolvedType;
-		if (binding == null) {
-			return INACCURATE_MATCH;
-		} else {
-			return this.matchLevelForType(this.superSimpleName, this.superQualification, binding);
-		}
-	} else {
-		if (this.superSimpleName == null) {
-			return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-		} else {
-			char[] typeRefSimpleName = null;
-			if (typeRef instanceof SingleTypeReference) {
-				typeRefSimpleName = ((SingleTypeReference)typeRef).token;
-			} else { // QualifiedTypeReference
-				char[][] tokens = ((QualifiedTypeReference)typeRef).tokens;
-				typeRefSimpleName = tokens[tokens.length-1];
-			}				
-			if (this.matchesName(this.superSimpleName, typeRefSimpleName))
-				return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-			else
-				return IMPOSSIBLE_MATCH;
-		}
-	}
-}
-
-/**
- * @see SearchPattern#matchLevel(Binding)
- */
-public int matchLevel(Binding binding) {
-	if (binding == null) return INACCURATE_MATCH;
-	if (!(binding instanceof ReferenceBinding)) return IMPOSSIBLE_MATCH;
-
-	// super class
-	ReferenceBinding type = (ReferenceBinding) binding;
-	int level = this.matchLevelForType(this.superSimpleName, this.superQualification, type.superclass());
-	switch (level) {
-		case IMPOSSIBLE_MATCH:
-			break; // try to find match in super interfaces
-		case ACCURATE_MATCH:
-			return ACCURATE_MATCH;
-		default: // ie. INACCURATE_MATCH
-			break; // try to find accurate match in super interfaces
-	}
-
-	// super interfaces
-	ReferenceBinding[] superInterfaces = type.superInterfaces();
-	for (int i = 0, max = superInterfaces.length; i < max; i++){
-		int newLevel = this.matchLevelForType(this.superSimpleName, this.superQualification, superInterfaces[i]);
-		switch (newLevel) {
-			case IMPOSSIBLE_MATCH:
-				break;
-			case ACCURATE_MATCH:
-				return ACCURATE_MATCH;
-			default: // ie. INACCURATE_MATCH
-				level = newLevel;
-				break;
-		}
-	}
-	return level;
-}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationLocator.java
new file mode 100644
index 0000000..f062336
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationLocator.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class TypeDeclarationLocator extends PatternLocator {
+
+protected TypeDeclarationPattern pattern; // can be a QualifiedTypeDeclarationPattern
+
+public TypeDeclarationLocator(TypeDeclarationPattern pattern) {
+	super(pattern);
+
+	this.pattern = pattern;
+}
+//public int match(ASTNode node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(Expression node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(FieldDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(MethodDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(MessageSend node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(Reference node, MatchingNodeSet nodeSet) - SKIP IT
+public int match(TypeDeclaration node, MatchingNodeSet nodeSet) {
+	if (this.pattern.simpleName == null || matchesName(this.pattern.simpleName, node.name))
+		return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+
+	return IMPOSSIBLE_MATCH;
+}
+//public int match(TypeReference node, MatchingNodeSet nodeSet) - SKIP IT
+
+public int resolveLevel(ASTNode node) {
+	if (!(node instanceof TypeDeclaration)) return IMPOSSIBLE_MATCH;
+
+	return resolveLevel(((TypeDeclaration) node).binding);
+}
+public int resolveLevel(Binding binding) {
+	if (binding == null) return INACCURATE_MATCH;
+	if (!(binding instanceof TypeBinding)) return IMPOSSIBLE_MATCH;
+
+	TypeBinding type = (TypeBinding) binding;
+
+	switch (this.pattern.classOrInterface) {
+		case CLASS_SUFFIX:
+			if (type.isInterface()) return IMPOSSIBLE_MATCH;
+			break;
+		case INTERFACE_SUFFIX:
+			if (!type.isInterface()) return IMPOSSIBLE_MATCH;
+			break;
+		case TYPE_SUFFIX : // nothing
+	}
+
+	// fully qualified name
+	if (this.pattern instanceof QualifiedTypeDeclarationPattern) {
+		QualifiedTypeDeclarationPattern qualifiedPattern = (QualifiedTypeDeclarationPattern) this.pattern;
+		return resolveLevelForType(qualifiedPattern.simpleName, qualifiedPattern.qualification, type);
+	} else {
+		char[] enclosingTypeName = this.pattern.enclosingTypeNames == null ? null : CharOperation.concatWith(this.pattern.enclosingTypeNames, '.');
+		return resolveLevelForType(this.pattern.simpleName, this.pattern.pkg, enclosingTypeName, type);
+	}
+}
+/**
+ * Returns whether the given type binding matches the given simple name pattern 
+ * qualification pattern and enclosing type name pattern.
+ */
+protected int resolveLevelForType(char[] simpleNamePattern, char[] qualificationPattern, char[] enclosingNamePattern, TypeBinding type) {
+	if (enclosingNamePattern == null)
+		return resolveLevelForType(simpleNamePattern, qualificationPattern, type);
+	if (qualificationPattern == null)
+		return resolveLevelForType(simpleNamePattern, enclosingNamePattern, type);
+
+	// case of an import reference while searching for ALL_OCCURENCES of a type (see bug 37166)
+	if (type instanceof ProblemReferenceBinding) return IMPOSSIBLE_MATCH;
+
+	// pattern was created from a Java element: qualification is the package name.
+	char[] fullQualificationPattern = CharOperation.concat(qualificationPattern, enclosingNamePattern, '.');
+	if (CharOperation.equals(this.pattern.pkg, CharOperation.concatWith(type.getPackage().compoundName, '.')))
+		return resolveLevelForType(simpleNamePattern, fullQualificationPattern, type);
+	return IMPOSSIBLE_MATCH;
+}
+public String toString() {
+	return "Locator for " + this.pattern.toString(); //$NON-NLS-1$
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java
index 8e92009..9243333 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java
@@ -10,219 +10,191 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
-import java.io.IOException;
-
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.env.IBinaryType;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.indexing.AbstractIndexer;
+import org.eclipse.jdt.core.search.*;
 
 public class TypeDeclarationPattern extends SearchPattern {
 
-	private char[] pkg;
-	private char[][] enclosingTypeNames;
-	protected char[] simpleName;
+private static ThreadLocal indexRecord = new ThreadLocal() {
+	protected Object initialValue() {
+		return new TypeDeclarationPattern(null, null, null, ' ', R_EXACT_MATCH | R_CASE_SENSITIVE);
+	}
+};
 
-	// set to CLASS_SUFFIX for only matching classes 
-	// set to INTERFACE_SUFFIX for only matching interfaces
-	// set to TYPE_SUFFIX for matching both classes and interfaces
-	protected char classOrInterface; 
+public char[] simpleName;
+public char[] pkg;
+public char[][] enclosingTypeNames;
 
-	private char[] decodedPackage;
-	private char[][] decodedEnclosingTypeNames;
-	protected char[] decodedSimpleName;
-	protected char decodedClassOrInterface;
-	
-public TypeDeclarationPattern(int matchMode, boolean isCaseSensitive) {
-	super(matchMode, isCaseSensitive);
+// set to CLASS_SUFFIX for only matching classes 
+// set to INTERFACE_SUFFIX for only matching interfaces
+// set to TYPE_SUFFIX for matching both classes and interfaces
+public char classOrInterface; 
+
+public static char[] createIndexKey(char[] packageName, char[][] enclosingTypeNames, char[] typeName, boolean isClass) {
+	TypeDeclarationPattern record = getTypeDeclarationRecord();
+	record.pkg = packageName;
+	record.enclosingTypeNames = enclosingTypeNames;
+	record.simpleName = typeName;
+	record.classOrInterface = isClass ? CLASS_SUFFIX : INTERFACE_SUFFIX;
+	return record.encodeIndexKey();
+}
+public static TypeDeclarationPattern getTypeDeclarationRecord() {
+	return (TypeDeclarationPattern)indexRecord.get();
+}
+public TypeDeclarationPattern(int matchRule) {
+	super(TYPE_DECL_PATTERN, matchRule);
 }
 public TypeDeclarationPattern(
 	char[] pkg,
 	char[][] enclosingTypeNames,
 	char[] simpleName,
 	char classOrInterface,
-	int matchMode, 
-	boolean isCaseSensitive) {
+	int matchRule) {
 
-	super(matchMode, isCaseSensitive);
+	super(TYPE_DECL_PATTERN, matchRule);
 
+	boolean isCaseSensitive = isCaseSensitive();
 	this.pkg = isCaseSensitive ? pkg : CharOperation.toLowerCase(pkg);
 	if (isCaseSensitive || enclosingTypeNames == null) {
 		this.enclosingTypeNames = enclosingTypeNames;
 	} else {
 		int length = enclosingTypeNames.length;
 		this.enclosingTypeNames = new char[length][];
-		for (int i = 0; i < length; i++){
+		for (int i = 0; i < length; i++)
 			this.enclosingTypeNames[i] = CharOperation.toLowerCase(enclosingTypeNames[i]);
-		}
 	}
 	this.simpleName = isCaseSensitive ? simpleName : CharOperation.toLowerCase(simpleName);
 	this.classOrInterface = classOrInterface;
 	
-	this.needsResolve = pkg != null && enclosingTypeNames != null;
+	this.mustResolve = pkg != null && enclosingTypeNames != null;
 }
-public void decodeIndexEntry(IEntryResult entryResult){
-
-	char[] word = entryResult.getWord();
-	int size = word.length;
-
-	this.decodedClassOrInterface = word[TYPE_DECL_LENGTH];
-	int oldSlash = TYPE_DECL_LENGTH+1;
-	int slash = CharOperation.indexOf(SEPARATOR, word, oldSlash+1);
-	if (slash == oldSlash+1){ 
-		this.decodedPackage = CharOperation.NO_CHAR;
-	} else {
-		this.decodedPackage = CharOperation.subarray(word, oldSlash+1, slash);
-	}
-	this.decodedSimpleName = CharOperation.subarray(word, slash+1, slash = CharOperation.indexOf(SEPARATOR, word, slash+1));
-
-	if (slash+1 < size){
-		if (slash+3 == size && word[slash+1] == ONE_ZERO[0]) {
-			this.decodedEnclosingTypeNames = ONE_ZERO_CHAR;
-		} else {
-			this.decodedEnclosingTypeNames = CharOperation.splitOn('/', CharOperation.subarray(word, slash+1, size-1));
-		}
-	} else {
-		this.decodedEnclosingTypeNames = CharOperation.NO_CHAR_CHAR;
-	}
-}
-/**
- * see SearchPattern.feedIndexRequestor
+/*
+ * Type entries are encoded as 'typeDecl/' ('C' | 'I') '/' PackageName '/' TypeName '/' EnclosingTypeName
+ * e.g. typeDecl/C/java.lang/Object/
+ * e.g. typeDecl/I/java.lang/Cloneable/
+ * e.g. typeDecl/C/javax.swing/LazyValue/UIDefaults
+ * 
+ * Current encoding is optimized for queries: all classes/interfaces
  */
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope) throws IOException {
-	boolean isClass = decodedClassOrInterface == CLASS_SUFFIX;
-	for (int i = 0, max = references.length; i < max; i++) {
-		IndexedFile file = input.getIndexedFile(references[i]);
-		String path;
-		if (file != null && scope.encloses(path =IndexedFile.convertPath(file.getPath()))) {
-			if (isClass) {
-				requestor.acceptClassDeclaration(path, decodedSimpleName, decodedEnclosingTypeNames, decodedPackage);
-			} else {
-				requestor.acceptInterfaceDeclaration(path, decodedSimpleName, decodedEnclosingTypeNames, decodedPackage);
+public void decodeIndexKey(char[] key) {
+	int size = key.length;
+
+	this.classOrInterface = key[0];
+	int oldSlash = 1;
+	int slash = CharOperation.indexOf(SEPARATOR, key, oldSlash + 1);
+	this.pkg = (slash == oldSlash + 1)
+		? CharOperation.NO_CHAR
+		: CharOperation.subarray(key, oldSlash + 1, slash);
+	this.simpleName = CharOperation.subarray(key, slash + 1, slash = CharOperation.indexOf(SEPARATOR, key, slash + 1));
+
+	if (slash+1 < size) {
+		this.enclosingTypeNames = (slash + 3 == size && key[slash + 1] == ONE_ZERO[0])
+			? ONE_ZERO_CHAR
+			: CharOperation.splitOn('/', CharOperation.subarray(key, slash+1, size-1));
+	} else {
+		this.enclosingTypeNames = CharOperation.NO_CHAR_CHAR;
+	}
+}
+/*
+ * classOrInterface / package / simpleName / enclosingTypeNames
+ */
+public char[] encodeIndexKey() {
+	char[] packageName = isCaseSensitive() ? pkg : null;
+	switch(this.classOrInterface) {
+		case CLASS_SUFFIX :
+			if (packageName == null) 
+				return new char[] {CLASS_SUFFIX, SEPARATOR};
+			break;
+		case INTERFACE_SUFFIX :
+			if (packageName == null) 
+				return new char[] {INTERFACE_SUFFIX, SEPARATOR};
+			break;
+		default :
+			return CharOperation.NO_CHAR; // cannot do better given encoding
+	}
+
+	char[] typeName = isCaseSensitive() ? this.simpleName : null;
+	if (typeName != null && matchMode() == PATTERN_MATCH) {
+		int starPos = CharOperation.indexOf('*', typeName);
+		switch(starPos) {
+			case -1 :
+				break;
+			case 0 :
+				typeName = null;
+				break;
+			default : 
+				typeName = CharOperation.subarray(typeName, 0, starPos);
+		}
+	}
+
+	int packageLength = packageName.length;
+	int enclosingTypeNamesLength = 0;
+	if (this.enclosingTypeNames != null)
+		for (int i = 0, length = this.enclosingTypeNames.length; i < length; i++)
+			enclosingTypeNamesLength += this.enclosingTypeNames[i].length + 1;
+	int pos = 0;
+	int typeNameLength = typeName == null ? 0 : typeName.length;
+	int resultLength = pos + packageLength + typeNameLength + enclosingTypeNamesLength + 4;
+	char[] result = new char[resultLength];
+	result[pos++] = this.classOrInterface;
+	result[pos++] = SEPARATOR;
+	if (packageLength > 0) {
+		System.arraycopy(packageName, 0, result, pos, packageLength);
+		pos += packageLength;
+	}
+	result[pos++] = SEPARATOR;
+	if (typeName != null) {
+		System.arraycopy(typeName, 0, result, pos, typeNameLength);
+		pos += typeNameLength;
+
+		result[pos++] = SEPARATOR;
+		if (enclosingTypeNames != null) {
+			for (int i = 0, length = this.enclosingTypeNames.length; i < length; i++) {
+				int enclosingTypeNameLength = this.enclosingTypeNames[i].length;
+				System.arraycopy(this.enclosingTypeNames[i], 0, result, pos, enclosingTypeNameLength);
+				pos += enclosingTypeNameLength;
+				result[pos++] = SEPARATOR;
 			}
 		}
 	}
-}
-/**
- * see SearchPattern.indexEntryPrefix()
- */
-public char[] indexEntryPrefix(){
-
-	return AbstractIndexer.bestTypeDeclarationPrefix(
-			pkg,
-			simpleName,
-			classOrInterface,
-			matchMode, 
-			isCaseSensitive);
-}
-/**
- * @see SearchPattern#matchContainer()
- */
-protected int matchContainer() {
-	return COMPILATION_UNIT | CLASS | METHOD | FIELD;
-}
-/**
- * @see SearchPattern#matchesBinary(Object, Object)
- */
-public boolean matchesBinary(Object binaryInfo, Object enclosingBinaryInfo) {
-	if (!(binaryInfo instanceof IBinaryType)) return false;
-
-	IBinaryType type = (IBinaryType)binaryInfo;
-
-	// fully qualified name
-	char[] typeName = (char[])type.getName().clone();
-	CharOperation.replace(typeName, '/', '.');
-	char[] enclosingTypeName = this.enclosingTypeNames == null ? null : CharOperation.concatWith(this.enclosingTypeNames, '.');
-	if (!this.matchesType(this.simpleName, this.pkg, enclosingTypeName, typeName)) {
-		return false;
+	if (pos != resultLength) {
+		System.arraycopy(result, 0, result = new char[pos], 0, pos);
 	}
-
-	// class or interface
-	switch (this.classOrInterface) {
-		case CLASS_SUFFIX:
-			if (type.isInterface())
-				return false;
-			break;
-		case INTERFACE_SUFFIX:
-			if (!type.isInterface())
-				return false;
-			break;
-	}
-	
-	return true;
+	return result;
 }
-/**
- * Returns whether the given type binding matches the given simple name pattern 
- * package pattern and enclosing name pattern.
- */
-protected boolean matchesType(char[] simpleNamePattern, char[] pkgPattern, char[] enclosingNamePattern, char[] fullyQualifiedTypeName) {
-	if (enclosingNamePattern == null) {
-		return this.matchesType(simpleNamePattern, pkgPattern, fullyQualifiedTypeName);
-	} else {
-		char[] pattern;
-		if (pkgPattern == null) {
-			pattern = enclosingNamePattern;
-		} else {
-			pattern = CharOperation.concat(pkgPattern, enclosingNamePattern, '.');
-		}
-		return this.matchesType(simpleNamePattern, pattern, fullyQualifiedTypeName);
-	}
+public SearchPattern getIndexRecord() {
+	return getTypeDeclarationRecord();
 }
-
-/**
- * see SearchPattern.matchIndexEntry
- */
-protected boolean matchIndexEntry(){
-
-	/* check class/interface nature */
-	switch(classOrInterface){
+public char[][] getMatchCategories() {
+	return new char[][] {TYPE_DECL};
+}
+public boolean isMatchingIndexRecord() {
+	TypeDeclarationPattern record = getTypeDeclarationRecord();
+	switch(this.classOrInterface) {
 		case CLASS_SUFFIX :
 		case INTERFACE_SUFFIX :
-			if (classOrInterface != decodedClassOrInterface) return false;
-		default :
+			if (this.classOrInterface != record.classOrInterface) return false;
+		case TYPE_SUFFIX : // nothing
 	}
+
 	/* check qualification - exact match only */
-	if (pkg != null && !CharOperation.equals(pkg, decodedPackage, isCaseSensitive))
+	if (this.pkg != null && !CharOperation.equals(this.pkg, record.pkg, isCaseSensitive()))
 		return false;
 	/* check enclosingTypeName - exact match only */
-	if (enclosingTypeNames != null){
+	if (this.enclosingTypeNames != null) {
 		// empty char[][] means no enclosing type (in which case, the decoded one is the empty char array)
-		if (enclosingTypeNames.length == 0){
-			if (decodedEnclosingTypeNames != CharOperation.NO_CHAR_CHAR) return false;
+		if (this.enclosingTypeNames.length == 0) {
+			if (record.enclosingTypeNames != CharOperation.NO_CHAR_CHAR) return false;
 		} else {
-			if (!CharOperation.equals(enclosingTypeNames, decodedEnclosingTypeNames, isCaseSensitive)) return false;
+			if (!CharOperation.equals(this.enclosingTypeNames, record.enclosingTypeNames, isCaseSensitive()))
+				if (!CharOperation.equals(record.enclosingTypeNames, ONE_ZERO_CHAR)) // if not a local or anonymous type
+					return false;
 		}
 	}
-	/* check simple name matches */
-	if (simpleName != null){
-		switch(matchMode){
-			case EXACT_MATCH :
-				if (!CharOperation.equals(simpleName, decodedSimpleName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PREFIX_MATCH :
-				if (!CharOperation.prefixEquals(simpleName, decodedSimpleName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PATTERN_MATCH :
-				if (!CharOperation.match(simpleName, decodedSimpleName, isCaseSensitive)){
-					return false;
-				}
-		}
-	}
-	return true;
+
+	return matchesName(this.simpleName, record.simpleName);
 }
-public String toString(){
+public String toString() {
 	StringBuffer buffer = new StringBuffer(20);
 	switch (classOrInterface){
 		case CLASS_SUFFIX :
@@ -235,7 +207,10 @@
 			buffer.append("TypeDeclarationPattern: pkg<"); //$NON-NLS-1$
 			break;
 	}
-	if (pkg != null) buffer.append(pkg);
+	if (pkg != null) 
+		buffer.append(pkg);
+	else
+		buffer.append("*"); //$NON-NLS-1$
 	buffer.append(">, enclosing<"); //$NON-NLS-1$
 	if (enclosingTypeNames != null) {
 		for (int i = 0; i < enclosingTypeNames.length; i++){
@@ -243,11 +218,16 @@
 			if (i < enclosingTypeNames.length - 1)
 				buffer.append('.');
 		}
+	} else {
+		buffer.append("*"); //$NON-NLS-1$
 	}
 	buffer.append(">, type<"); //$NON-NLS-1$
-	if (simpleName != null) buffer.append(simpleName);
+	if (simpleName != null) 
+		buffer.append(simpleName);
+	else
+		buffer.append("*"); //$NON-NLS-1$
 	buffer.append(">, "); //$NON-NLS-1$
-	switch(matchMode){
+	switch(matchMode()){
 		case EXACT_MATCH : 
 			buffer.append("exact match, "); //$NON-NLS-1$
 			break;
@@ -258,77 +238,10 @@
 			buffer.append("pattern match, "); //$NON-NLS-1$
 			break;
 	}
-	if (isCaseSensitive)
+	if (isCaseSensitive())
 		buffer.append("case sensitive"); //$NON-NLS-1$
 	else
 		buffer.append("case insensitive"); //$NON-NLS-1$
 	return buffer.toString();
 }
-
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
- */
-public int matchLevel(AstNode node, boolean resolve) {
-	if (!(node instanceof TypeDeclaration)) return IMPOSSIBLE_MATCH;
-
-	TypeDeclaration type = (TypeDeclaration)node;
-
-	if (resolve) {
-		return this.matchLevel(type.binding);
-	} else {
-		// type name
-		if (this.simpleName != null && !this.matchesName(this.simpleName, type.name))
-			return IMPOSSIBLE_MATCH;
-		else
-			return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-	}
-}
-
-/**
- * @see SearchPattern#matchLevel(Binding)
- */
-public int matchLevel(Binding binding) {
-	if (binding == null) return INACCURATE_MATCH;
-	if (!(binding instanceof TypeBinding)) return IMPOSSIBLE_MATCH;
-
-	TypeBinding type = (TypeBinding)binding;
-
-	// class or interface
-	switch (this.classOrInterface) {
-		case CLASS_SUFFIX:
-			if (type.isInterface())
-				return IMPOSSIBLE_MATCH;
-			break;
-		case INTERFACE_SUFFIX:
-			if (!type.isInterface())
-				return IMPOSSIBLE_MATCH;
-			break;
-	}
-
-	// fully qualified name
-	char[] enclosingTypeName = this.enclosingTypeNames == null ? null : CharOperation.concatWith(this.enclosingTypeNames, '.');
-	return this.matchLevelForType(this.simpleName, this.pkg, enclosingTypeName, type);
-}
-
-/**
- * Returns whether the given type binding matches the given simple name pattern 
- * qualification pattern and enclosing type name pattern.
- */
-protected int matchLevelForType(char[] simpleNamePattern, char[] qualificationPattern, char[] enclosingNamePattern, TypeBinding type) {
-	if (enclosingNamePattern == null) {
-		return this.matchLevelForType(simpleNamePattern, qualificationPattern, type);
-	} else {
-		if (qualificationPattern == null) {
-			return matchLevelForType(simpleNamePattern, enclosingNamePattern, type);
-		} else {
-			// pattern was created from a Java element: qualification is the package name.
-			char[] fullQualificationPattern = CharOperation.concat(qualificationPattern, enclosingNamePattern, '.');
-			if ( CharOperation.equals(pkg, CharOperation.concatWith(type.getPackage().compoundName, '.'))) {
-				return this.matchLevelForType(simpleNamePattern, fullQualificationPattern, type);
-			} else {
-				return IMPOSSIBLE_MATCH;
-			}
-		}
-	}
-}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java
new file mode 100644
index 0000000..d530ab0
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java
@@ -0,0 +1,429 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.*;
+import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.core.util.SimpleSet;
+
+public class TypeReferenceLocator extends PatternLocator {
+
+protected TypeReferencePattern pattern;
+protected boolean isDeclarationOfReferencedTypesPattern;
+
+public TypeReferenceLocator(TypeReferencePattern pattern) {
+	super(pattern);
+
+	this.pattern = pattern;
+	this.isDeclarationOfReferencedTypesPattern = this.pattern instanceof DeclarationOfReferencedTypesPattern;
+}
+protected IJavaElement findElement(IJavaElement element, int accuracy) {
+	// need exact match to be able to open on type ref
+	if (accuracy != IJavaSearchResultCollector.EXACT_MATCH) return null;
+
+	// element that references the type must be included in the enclosing element
+	DeclarationOfReferencedTypesPattern declPattern = (DeclarationOfReferencedTypesPattern) this.pattern; 
+	while (element != null && !declPattern.enclosingElement.equals(element))
+		element = element.getParent();
+	return element;
+}
+public int match(ASTNode node, MatchingNodeSet nodeSet) { // interested in ImportReference
+	if (!(node instanceof ImportReference)) return IMPOSSIBLE_MATCH;
+
+	return nodeSet.addMatch(node, matchLevel((ImportReference) node));
+}
+//public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(Expression node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(FieldDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(MethodDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+//public int match(MessageSend node, MatchingNodeSet nodeSet) - SKIP IT
+public int match(Reference node, MatchingNodeSet nodeSet) { // interested in NameReference & its subtypes
+	if (!(node instanceof NameReference)) return IMPOSSIBLE_MATCH;
+
+	if (this.pattern.simpleName == null)
+		return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+
+	if (node instanceof SingleNameReference) {
+		if (matchesName(this.pattern.simpleName, ((SingleNameReference) node).token))
+			return nodeSet.addMatch(node, POSSIBLE_MATCH); // resolution is needed to find out if it is a type ref 
+	} else {
+		char[][] tokens = ((QualifiedNameReference) node).tokens;
+		for (int i = 0, max = tokens.length; i < max; i++)
+			if (matchesName(this.pattern.simpleName, tokens[i]))
+				return nodeSet.addMatch(node, POSSIBLE_MATCH); // resolution is needed to find out if it is a type ref
+	}
+
+	return IMPOSSIBLE_MATCH;
+}
+//public int match(TypeDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
+public int match(TypeReference node, MatchingNodeSet nodeSet) {
+	if (this.pattern.simpleName == null)
+		return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+
+	if (node instanceof SingleTypeReference) {
+		if (matchesName(this.pattern.simpleName, ((SingleTypeReference) node).token))
+			return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+	} else {
+		char[][] tokens = ((QualifiedTypeReference) node).tokens;
+		for (int i = 0, max = tokens.length; i < max; i++)
+			if (matchesName(this.pattern.simpleName, tokens[i]))
+				return nodeSet.addMatch(node, POSSIBLE_MATCH); // resolution is needed to find out if it is a type ref
+	}
+
+	return IMPOSSIBLE_MATCH;
+}
+
+protected int matchLevel(ImportReference importRef) {
+	if (this.pattern.qualification == null) {
+		if (this.pattern.simpleName == null) return ACCURATE_MATCH;
+		char[][] tokens = importRef.tokens;
+		for (int i = 0, length = tokens.length; i < length; i++)
+			if (matchesName(this.pattern.simpleName, tokens[i])) return ACCURATE_MATCH;
+	} else {
+		char[][] tokens = importRef.tokens;
+		char[] qualifiedPattern = this.pattern.simpleName == null
+			? this.pattern.qualification
+			: CharOperation.concat(this.pattern.qualification, this.pattern.simpleName, '.');
+		char[] qualifiedTypeName = CharOperation.concatWith(tokens, '.');
+		switch (this.matchMode) {
+			case IJavaSearchConstants.EXACT_MATCH :
+			case IJavaSearchConstants.PREFIX_MATCH :
+				if (CharOperation.prefixEquals(qualifiedPattern, qualifiedTypeName, this.isCaseSensitive)) return POSSIBLE_MATCH;
+				break;
+			case IJavaSearchConstants.PATTERN_MATCH:
+				if (CharOperation.match(qualifiedPattern, qualifiedTypeName, this.isCaseSensitive)) return POSSIBLE_MATCH;
+				break;
+		}
+	}
+	return IMPOSSIBLE_MATCH;
+}
+protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	if (this.isDeclarationOfReferencedTypesPattern) {
+		if ((element = findElement(element, accuracy)) != null) {
+			SimpleSet knownTypes = ((DeclarationOfReferencedTypesPattern) this.pattern).knownTypes; 
+			while (binding instanceof ReferenceBinding) {
+				ReferenceBinding typeBinding = (ReferenceBinding) binding;
+				reportDeclaration(typeBinding, 1, locator, knownTypes);
+				binding = typeBinding.enclosingType();
+			}
+		}
+		return;
+	}
+
+	if (binding instanceof ReferenceBinding) {
+		int lastIndex = importRef.tokens.length - 1;
+		ReferenceBinding typeBinding = (ReferenceBinding) binding;
+		if (typeBinding instanceof ProblemReferenceBinding) {
+			ProblemReferenceBinding pbBinding = (ProblemReferenceBinding) typeBinding;
+			typeBinding = pbBinding.original;
+			lastIndex = pbBinding.compoundName.length - 1;
+		}
+		// try to match all enclosing types for which the token matches as well.
+		while (typeBinding != null && lastIndex >= 0) {
+			if (resolveLevelForType(this.pattern.simpleName, this.pattern.qualification, typeBinding) == ACCURATE_MATCH) {
+				long[] positions = importRef.sourcePositions;
+				locator.report(positions[this.pattern.qualification == null ? lastIndex : 0], positions[lastIndex], element, accuracy);
+				return;
+			}
+			lastIndex--;
+			typeBinding = typeBinding.enclosingType();
+		}
+	}
+	locator.reportAccurateReference(importRef.sourceStart, importRef.sourceEnd, this.pattern.simpleName, element, accuracy);
+}
+protected void matchReportReference(ArrayTypeReference arrayRef, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	if (this.pattern.simpleName == null)
+		locator.report(arrayRef.sourceStart, arrayRef.sourceEnd, element, accuracy);
+	else
+		locator.reportAccurateReference(arrayRef.sourceStart, arrayRef.sourceEnd, this.pattern.simpleName, element, accuracy);
+}
+protected void matchReportReference(ASTNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	if (this.isDeclarationOfReferencedTypesPattern) {
+		if ((element = findElement(element, accuracy)) != null)
+			reportDeclaration(reference, element, locator, ((DeclarationOfReferencedTypesPattern) this.pattern).knownTypes);
+		return;
+	}
+
+	if (reference instanceof QualifiedNameReference)
+		matchReportReference((QualifiedNameReference) reference, element, accuracy, locator);
+	else if (reference instanceof QualifiedTypeReference)
+		matchReportReference((QualifiedTypeReference) reference, element, accuracy, locator);
+	else if (reference instanceof ArrayTypeReference)
+		matchReportReference((ArrayTypeReference) reference, element, accuracy, locator);
+	else
+		super.matchReportReference(reference, element, accuracy, locator);
+}
+protected void matchReportReference(QualifiedNameReference qNameRef, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	Binding binding = qNameRef.binding;
+	TypeBinding typeBinding = null;
+	int lastIndex = qNameRef.tokens.length - 1;
+	switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
+		case BindingIds.FIELD : // reading a field
+			typeBinding = qNameRef.actualReceiverType;
+			lastIndex -= qNameRef.otherBindings == null ? 1 : qNameRef.otherBindings.length + 1;
+			break;
+		case BindingIds.TYPE : //=============only type ==============
+			if (binding instanceof TypeBinding)
+				typeBinding = (TypeBinding) binding;
+			break;
+		case BindingIds.VARIABLE : //============unbound cases===========
+		case BindingIds.TYPE | BindingIds.VARIABLE :
+			if (binding instanceof ProblemReferenceBinding) {
+				typeBinding = (TypeBinding) binding;
+			} else if (binding instanceof ProblemFieldBinding) {
+				typeBinding = qNameRef.actualReceiverType;
+				lastIndex -= qNameRef.otherBindings == null ? 1 : qNameRef.otherBindings.length + 1;
+			} else if (binding instanceof ProblemBinding) {
+				typeBinding = ((ProblemBinding) binding).searchType;
+			}
+			break;					
+	}
+	if (typeBinding instanceof ProblemReferenceBinding) {
+		ProblemReferenceBinding pbBinding = (ProblemReferenceBinding) typeBinding;
+		typeBinding = pbBinding.original;
+		lastIndex = pbBinding.compoundName.length - 1;
+	}
+	// try to match all enclosing types for which the token matches as well.
+	if (typeBinding instanceof ReferenceBinding) {
+		ReferenceBinding refBinding = (ReferenceBinding) typeBinding; 
+		while (refBinding != null && lastIndex >= 0) {
+			if (resolveLevelForType(this.pattern.simpleName, this.pattern.qualification, refBinding) == ACCURATE_MATCH) {
+				long[] positions = qNameRef.sourcePositions;
+				locator.report(positions[this.pattern.qualification == null ? lastIndex : 0], positions[lastIndex], element, accuracy);
+				return;
+			}
+			lastIndex--;
+			refBinding = refBinding.enclosingType();
+		}
+	}
+	locator.reportAccurateReference(qNameRef.sourceStart, qNameRef.sourceEnd, this.pattern.simpleName, element, accuracy);
+}
+protected void matchReportReference(QualifiedTypeReference qTypeRef, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
+	TypeBinding typeBinding = qTypeRef.resolvedType;
+	int lastIndex = qTypeRef.tokens.length - 1;
+	if (typeBinding instanceof ArrayBinding)
+		typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
+	if (typeBinding instanceof ProblemReferenceBinding) {
+		ProblemReferenceBinding pbBinding = (ProblemReferenceBinding) typeBinding;
+		typeBinding = pbBinding.original;
+		lastIndex = pbBinding.compoundName.length - 1;
+	}
+	// try to match all enclosing types for which the token matches as well
+	if (typeBinding instanceof ReferenceBinding) {
+		ReferenceBinding refBinding = (ReferenceBinding) typeBinding; 
+		while (refBinding != null && lastIndex >= 0) {
+			if (resolveLevelForType(this.pattern.simpleName, this.pattern.qualification, refBinding) == ACCURATE_MATCH) {
+				long[] positions = qTypeRef.sourcePositions;
+				locator.report(positions[this.pattern.qualification == null ? lastIndex : 0], positions[lastIndex], element, accuracy);
+				return;
+			}
+			lastIndex--;
+			refBinding = refBinding.enclosingType();
+		}
+	}
+	locator.reportAccurateReference(qTypeRef.sourceStart, qTypeRef.sourceEnd, this.pattern.simpleName, element, accuracy);
+}
+protected void reportDeclaration(ASTNode reference, IJavaElement element, MatchLocator locator, SimpleSet knownTypes) throws CoreException {
+	int maxType = -1;
+	TypeBinding typeBinding = null;
+	if (reference instanceof TypeReference) {
+		typeBinding = ((TypeReference) reference).resolvedType;
+		maxType = Integer.MAX_VALUE;
+	} else if (reference instanceof QualifiedNameReference) {
+		QualifiedNameReference qNameRef = (QualifiedNameReference) reference;
+		Binding binding = qNameRef.binding;
+		maxType = qNameRef.tokens.length - 1;
+		switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
+			case BindingIds.FIELD : // reading a field
+				typeBinding = qNameRef.actualReceiverType;
+				maxType -= qNameRef.otherBindings == null ? 1 : qNameRef.otherBindings.length + 1;
+				break;
+			case BindingIds.TYPE : //=============only type ==============
+				if (binding instanceof TypeBinding)
+					typeBinding = (TypeBinding) binding;
+				break;
+			case BindingIds.VARIABLE : //============unbound cases===========
+			case BindingIds.TYPE | BindingIds.VARIABLE :
+				if (binding instanceof ProblemFieldBinding) {
+					typeBinding = qNameRef.actualReceiverType;
+					maxType -= qNameRef.otherBindings == null ? 1 : qNameRef.otherBindings.length + 1;
+				} else if (binding instanceof ProblemBinding) {
+					ProblemBinding pbBinding = (ProblemBinding) binding;
+					typeBinding = pbBinding.searchType; // second chance with recorded type so far
+					char[] partialQualifiedName = pbBinding.name;
+					maxType = CharOperation.occurencesOf('.', partialQualifiedName) - 1; // index of last bound token is one before the pb token
+					if (typeBinding == null || maxType < 0) return;
+				}
+				break;
+		}
+	} else if (reference instanceof SingleNameReference) {
+		typeBinding = (TypeBinding) ((SingleNameReference) reference).binding;
+		maxType = 1;
+	}
+	
+	if (typeBinding instanceof ArrayBinding)
+		typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
+	if (typeBinding == null || typeBinding instanceof BaseTypeBinding) return;
+	if (typeBinding instanceof ProblemReferenceBinding)
+		typeBinding = ((ProblemReferenceBinding) typeBinding).original;
+	reportDeclaration((ReferenceBinding) typeBinding, maxType, locator, knownTypes);
+}
+protected void reportDeclaration(ReferenceBinding typeBinding, int maxType, MatchLocator locator, SimpleSet knownTypes) throws CoreException {
+	IType type = locator.lookupType(typeBinding);
+	if (type == null) return; // case of a secondary type
+
+	IResource resource = type.getResource();
+	boolean isBinary = type.isBinary();
+	IBinaryType info = null;
+	if (isBinary) {
+		if (resource == null)
+			resource = type.getJavaProject().getProject();
+		info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile) type.getClassFile(), resource);
+	}
+	while (maxType >= 0 && type != null) {
+		if (!knownTypes.includes(type)) {
+			if (isBinary) {
+				locator.reportBinaryMatch(resource, type, info, IJavaSearchResultCollector.EXACT_MATCH);
+			} else {
+				ClassScope scope = ((SourceTypeBinding) typeBinding).scope;
+				if (scope != null) {
+					TypeDeclaration typeDecl = scope.referenceContext;
+					locator.report(
+						resource, 
+						typeDecl.sourceStart, 
+						typeDecl.sourceEnd, 
+						type, 
+						IJavaSearchResultCollector.EXACT_MATCH, 
+						locator.getParticipant());
+				}
+			}
+			knownTypes.add(type);
+		}
+		typeBinding = typeBinding.enclosingType();
+		IJavaElement parent = type.getParent();
+		if (parent instanceof IType) {
+			type = (IType)parent;
+		} else {
+			type = null;
+		}
+		maxType--;
+	}
+}
+public int resolveLevel(ASTNode node) {
+	if (node instanceof TypeReference)
+		return resolveLevel((TypeReference) node);
+	if (node instanceof NameReference)
+		return resolveLevel((NameReference) node);
+//	if (node instanceof ImportReference) - Not called when resolve is true, see MatchingNodeSet.reportMatching(unit)
+	return IMPOSSIBLE_MATCH;
+}
+public int resolveLevel(Binding binding) {
+	if (binding == null) return INACCURATE_MATCH;
+	if (!(binding instanceof TypeBinding)) return IMPOSSIBLE_MATCH;
+
+	TypeBinding typeBinding = (TypeBinding) binding;
+	if (typeBinding instanceof ArrayBinding)
+		typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
+	if (typeBinding instanceof ProblemReferenceBinding)
+		typeBinding = ((ProblemReferenceBinding) typeBinding).original;
+
+	return resolveLevelForTypeOrEnclosingTypes(this.pattern.simpleName, this.pattern.qualification, typeBinding);
+}
+protected int resolveLevel(NameReference nameRef) {
+	Binding binding = nameRef.binding;
+
+	if (nameRef instanceof SingleNameReference) {
+		if (binding instanceof ProblemReferenceBinding)
+			binding = ((ProblemReferenceBinding) binding).original;
+		if (binding instanceof ReferenceBinding)
+			return resolveLevelForType(this.pattern.simpleName, this.pattern.qualification, (ReferenceBinding) binding);
+		return binding == null || binding instanceof ProblemBinding ? INACCURATE_MATCH : IMPOSSIBLE_MATCH;
+	}
+
+	TypeBinding typeBinding = null;
+	QualifiedNameReference qNameRef = (QualifiedNameReference) nameRef;
+	switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
+		case BindingIds.FIELD : // reading a field
+			if (qNameRef.tokens.length < (qNameRef.otherBindings == null ? 2 : qNameRef.otherBindings.length + 2))
+				return IMPOSSIBLE_MATCH; // must be at least A.x
+			typeBinding = nameRef.actualReceiverType;
+			break;
+		case BindingIds.LOCAL : // reading a local variable
+			return IMPOSSIBLE_MATCH; // no type match in it
+		case BindingIds.TYPE : //=============only type ==============
+			if (binding instanceof TypeBinding)
+				typeBinding = (TypeBinding) binding;
+			break;
+		/*
+		 * Handling of unbound qualified name references. The match may reside in the resolved fragment,
+		 * which is recorded inside the problem binding, along with the portion of the name until it became a problem.
+		 */
+		case BindingIds.VARIABLE : //============unbound cases===========
+		case BindingIds.TYPE | BindingIds.VARIABLE :
+			if (binding instanceof ProblemReferenceBinding) {
+				typeBinding = (TypeBinding) binding;
+			} else if (binding instanceof ProblemFieldBinding) {
+				if (qNameRef.tokens.length < (qNameRef.otherBindings == null ? 2 : qNameRef.otherBindings.length + 2))
+					return IMPOSSIBLE_MATCH; // must be at least A.x
+				typeBinding = nameRef.actualReceiverType;
+			} else if (binding instanceof ProblemBinding) {
+				ProblemBinding pbBinding = (ProblemBinding) binding;
+				if (CharOperation.occurencesOf('.', pbBinding.name) <= 0) // index of last bound token is one before the pb token
+					return INACCURATE_MATCH;
+				typeBinding = pbBinding.searchType;
+			}
+			break;
+	}
+	return resolveLevel(typeBinding);
+}
+protected int resolveLevel(TypeReference typeRef) {
+	TypeBinding typeBinding = typeRef.resolvedType;
+	if (typeBinding instanceof ArrayBinding)
+		typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
+	if (typeBinding instanceof ProblemReferenceBinding)
+		typeBinding = ((ProblemReferenceBinding) typeBinding).original;
+
+	if (typeRef instanceof SingleTypeReference)
+		return resolveLevelForType(this.pattern.simpleName, this.pattern.qualification, typeBinding);
+	else
+		return resolveLevelForTypeOrEnclosingTypes(this.pattern.simpleName, this.pattern.qualification, typeBinding);
+}
+/**
+ * Returns whether the given type binding or one of its enclosing types
+ * matches the given simple name pattern and qualification pattern.
+ * Returns ACCURATE_MATCH if it does.
+ * Returns INACCURATE_MATCH if resolve failed.
+ * Returns IMPOSSIBLE_MATCH if it doesn't.
+ */
+protected int resolveLevelForTypeOrEnclosingTypes(char[] simpleNamePattern, char[] qualificationPattern, TypeBinding binding) {
+	if (binding == null) return INACCURATE_MATCH;
+
+	if (binding instanceof ReferenceBinding) {
+		ReferenceBinding type = (ReferenceBinding) binding;
+		char[] qualifiedPattern = qualifiedPattern(simpleNamePattern, qualificationPattern);
+		while (type != null) {
+			if (resolveLevelForType(qualifiedPattern, type) == ACCURATE_MATCH) return ACCURATE_MATCH;
+	
+			type = type.enclosingType();
+		}
+	}
+	return IMPOSSIBLE_MATCH;
+}
+public String toString() {
+	return "Locator for " + this.pattern.toString(); //$NON-NLS-1$
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java
index 0534e58..8e561c9 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/TypeReferencePattern.java
@@ -10,331 +10,114 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.matching;
 
-import java.io.IOException;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.search.IJavaSearchScope;
-import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.AstNode;
-import org.eclipse.jdt.internal.compiler.ast.ImportReference;
-import org.eclipse.jdt.internal.compiler.ast.NameReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
-import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
-import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.BindingIds;
-import org.eclipse.jdt.internal.compiler.lookup.ProblemBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
-import org.eclipse.jdt.internal.core.index.IEntryResult;
-import org.eclipse.jdt.internal.core.index.impl.IndexInput;
-import org.eclipse.jdt.internal.core.index.impl.IndexedFile;
-import org.eclipse.jdt.internal.core.search.IIndexSearchRequestor;
-import org.eclipse.jdt.internal.core.search.indexing.AbstractIndexer;
+import org.eclipse.jdt.core.search.*;
 
-public class TypeReferencePattern extends MultipleSearchPattern {
+public class TypeReferencePattern extends AndPattern {
 
-	private char[] qualification;
-	private char[] simpleName;
+private static ThreadLocal indexRecord = new ThreadLocal() {
+	protected Object initialValue() {
+		return new TypeReferencePattern(null, null, R_EXACT_MATCH | R_CASE_SENSITIVE);
+	}
+};
 
-	private char[] decodedSimpleName;
+protected char[] qualification;
+protected char[] simpleName;
 
-	private static char[][] TAGS = { TYPE_REF, SUPER_REF, REF, CONSTRUCTOR_REF };
-	private static char[][] REF_TAGS = { REF };
+protected char[] currentCategory;
 
-	/* Optimization: case where simpleName == null */
-	private char[][] segments;
-	private int currentSegment;
-	private char[] decodedSegment;
-	
-public TypeReferencePattern(
-	char[] qualification,
-	char[] simpleName,
-	int matchMode, 
-	boolean isCaseSensitive) {
+/* Optimization: case where simpleName == null */
+protected char[][] segments;
+protected int currentSegment;
 
-	super(matchMode, isCaseSensitive);
+protected static char[][] CATEGORIES = { TYPE_REF, SUPER_REF, REF, CONSTRUCTOR_REF };
+protected static char[][] REF_CATEGORIES = { REF };
 
-	this.qualification = isCaseSensitive ? qualification : CharOperation.toLowerCase(qualification);
-	this.simpleName = isCaseSensitive ? simpleName : CharOperation.toLowerCase(simpleName);
+public static char[] createIndexKey(char[] typeName) {
+	TypeReferencePattern record = getTypeReferenceRecord();
+	record.simpleName = typeName;
+	return record.encodeIndexKey();
+}
+public static TypeReferencePattern getTypeReferenceRecord() {
+	return (TypeReferencePattern)indexRecord.get();
+}
+public TypeReferencePattern(char[] qualification, char[] simpleName, int matchRule) {
+	super(TYPE_REF_PATTERN, matchRule);
 
-	if (simpleName == null) {
+	this.qualification = isCaseSensitive() ? qualification : CharOperation.toLowerCase(qualification);
+	this.simpleName = isCaseSensitive() ? simpleName : CharOperation.toLowerCase(simpleName);
+
+	if (simpleName == null)
 		this.segments = this.qualification == null ? ONE_STAR_CHAR : CharOperation.splitOn('.', this.qualification);
-	}
 	
-	this.needsResolve = true; // always resolve (in case of a simple name reference being a potential match)
+	this.mustResolve = true; // always resolve (in case of a simple name reference being a potential match)
 }
-/**
- * Either decode ref/name, typeRef/name or superRef/superName/name
- */ 
-public void decodeIndexEntry(IEntryResult entryResult){
+public void decodeIndexKey(char[] key) {
+	int nameLength = CharOperation.indexOf(SEPARATOR, key);
+	if (nameLength != -1)
+		key = CharOperation.subarray(key, 0, nameLength);
+	
+	this.simpleName = key;
 
-	char[] word = entryResult.getWord();
-	int size = word.length;
-	int tagLength = currentTag.length;
-	int nameLength = CharOperation.indexOf(SEPARATOR, word, tagLength);
-	if (nameLength < 0) nameLength = size;
-	if (this.simpleName == null) {
-		// Optimization, eg. type reference is 'org.eclipse.jdt.core.*'
-		this.decodedSegment = CharOperation.subarray(word, tagLength, nameLength);
-	} else {
-		this.decodedSimpleName = CharOperation.subarray(word, tagLength, nameLength);
-	}
+	// Optimization, eg. type reference is 'org.eclipse.jdt.core.*'
+	this.segments[0] = key;
 }
-public void feedIndexRequestor(IIndexSearchRequestor requestor, int detailLevel, int[] references, IndexInput input, IJavaSearchScope scope) throws IOException {
-	if (currentTag == REF) {
-		foundAmbiguousIndexMatches = true;
-	}
-	for (int i = 0, max = references.length; i < max; i++) {
-		int reference = references[i];
-		if (reference != -1) { // if the reference has not been eliminated
-			IndexedFile file = input.getIndexedFile(reference);
-			String path;
-			if (file != null && scope.encloses(path = IndexedFile.convertPath(file.getPath()))) {
-				requestor.acceptTypeReference(path, decodedSimpleName);
-			}
-		}
-	}
+public char[] encodeIndexKey() {
+	if (this.simpleName == null) // Optimization, eg. type reference is 'org.eclipse.jdt.core.*'
+		if (this.currentSegment < 0) 
+			return null;
+		else
+			return encodeIndexKey(this.segments[this.currentSegment]);
+	else
+		return encodeIndexKey(this.simpleName);
 }
-protected char[][] getPossibleTags(){
-	if (this.simpleName == null) {
-		return REF_TAGS;
-	} else {
-		return TAGS;
-	}
+public SearchPattern getIndexRecord() {
+	return getTypeReferenceRecord();
+}
+public char[][] getMatchCategories() {
+	return this.simpleName == null ? REF_CATEGORIES : CATEGORIES;
 }
 /**
  * @see AndPattern#hasNextQuery
  */
 protected boolean hasNextQuery() {
+	if (this.simpleName != null) return false;
+
+	// Optimization, eg. type reference is 'org.eclipse.jdt.core.*'
+	// if package has at least 4 segments, don't look at the first 2 since they are mostly
+	// redundant (eg. in 'org.eclipse.jdt.core.*' 'org.eclipse' is used all the time)
+	return --this.currentSegment >= (this.segments.length >= 4 ? 2 : 0);
+}
+public boolean isMatchingIndexRecord() {
 	if (this.simpleName == null) {
 		// Optimization, eg. type reference is 'org.eclipse.jdt.core.*'
-		if (this.segments.length > 2) {
-			// if package has more than 2 segments, don't look at the first 2 since they are mostly
-			// redundant (eg. in 'org.eclipse.jdt.core.*', 'org.eclipse is used all the time)
-			return --this.currentSegment >= 2;
-		} else {
-			return --this.currentSegment >= 0;
-		}
+		return matchesName(this.segments[this.currentSegment], getTypeReferenceRecord().segments[0]);
 	} else {
-		return false;
+		return matchesName(this.simpleName, getTypeReferenceRecord().simpleName);
 	}
 }
 /**
- * see SearchPattern.indexEntryPrefix()
- */
-public char[] indexEntryPrefix(){
-
-	if (this.simpleName == null) {
-		// Optimization, eg. type reference is 'org.eclipse.jdt.core.*'
-		return AbstractIndexer.bestReferencePrefix(
-			REF,
-			this.segments[this.currentSegment],
-			matchMode, 
-			isCaseSensitive);
-	} else {
-		return AbstractIndexer.bestReferencePrefix(
-			currentTag,
-			simpleName,
-			matchMode, 
-			isCaseSensitive);
-	}
-}
-/**
- * @see SearchPattern#matchContainer()
- */
-protected int matchContainer() {
-	return COMPILATION_UNIT | CLASS | METHOD | FIELD;
-}
-/**
- * @see SearchPattern#matchIndexEntry
- */
-protected boolean matchIndexEntry() {
-
-	/* check type name matches */
-	if (simpleName == null) {
-		// Optimization, eg. type reference is 'org.eclipse.jdt.core.*'
-		switch(matchMode){
-			case EXACT_MATCH :
-				if (!CharOperation.equals(this.segments[this.currentSegment], this.decodedSegment, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PREFIX_MATCH :
-				if (!CharOperation.prefixEquals(this.segments[this.currentSegment], this.decodedSegment, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PATTERN_MATCH :
-				if (!CharOperation.match(this.segments[this.currentSegment], this.decodedSegment, isCaseSensitive)){
-					return false;
-				}
-		}
-	} else {
-		switch(matchMode){
-			case EXACT_MATCH :
-				if (!CharOperation.equals(simpleName, decodedSimpleName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PREFIX_MATCH :
-				if (!CharOperation.prefixEquals(simpleName, decodedSimpleName, isCaseSensitive)){
-					return false;
-				}
-				break;
-			case PATTERN_MATCH :
-				if (!CharOperation.match(simpleName, decodedSimpleName, isCaseSensitive)){
-					return false;
-				}
-		}
-	}
-	return true;
-}
-/**
- * @see SearchPattern#matchReportReference
- */
-protected void matchReportReference(AstNode reference, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	if (reference instanceof QualifiedNameReference) {
-		this.matchReportReference((QualifiedNameReference)reference, element, accuracy, locator);
-	} else if (reference instanceof QualifiedTypeReference) {
-		this.matchReportReference((QualifiedTypeReference)reference, element, accuracy, locator);
-	} else if (reference instanceof ArrayTypeReference) {
-		this.matchReportReference((ArrayTypeReference)reference, element, accuracy, locator);
-	} else {
-		super.matchReportReference(reference, element, accuracy, locator);
-	}
-}
-/**
- * Reports the match of the given qualified name reference.
- */
-protected void matchReportReference(QualifiedNameReference qNameRef, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	char[][] tokens = null;
-	Binding binding = qNameRef.binding;
-	TypeBinding typeBinding = null;
-	char[][] nameTokens = qNameRef.tokens;
-	int lastIndex = nameTokens.length-1;
-	switch (qNameRef.bits & AstNode.RestrictiveFlagMASK) {
-		case BindingIds.FIELD : // reading a field
-			typeBinding = qNameRef.actualReceiverType;
-			int otherBindingsCount = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length;			
-			lastIndex -= otherBindingsCount + 1;
-			break;
-		case BindingIds.TYPE : //=============only type ==============
-			typeBinding = (TypeBinding)binding;
-			break;
-		case BindingIds.VARIABLE : //============unbound cases===========
-		case BindingIds.TYPE | BindingIds.VARIABLE :						
-			if (binding instanceof ProblemBinding) {
-				ProblemBinding pbBinding = (ProblemBinding) binding;
-				typeBinding = pbBinding.searchType; // second chance with recorded type so far
-				char[] partialQualifiedName = pbBinding.name;
-				lastIndex = CharOperation.occurencesOf('.', partialQualifiedName) - 1; // index of last bound token is one before the pb token
-			}
-			break;
-	}
-	// try to match all enclosing types for which the token matches as well.
-	while (typeBinding != null && lastIndex >= 0){
-		if (this.matchesName(this.simpleName, nameTokens[lastIndex--])) {
-			int level = this.matchLevelForType(this.simpleName, this.qualification, typeBinding);
-			if (level != IMPOSSIBLE_MATCH) {
-				tokens = new char[lastIndex+2][];
-				System.arraycopy(nameTokens, 0, tokens, 0, lastIndex+2);
-				break;
-			}
-		}
-		if (typeBinding instanceof ReferenceBinding){
-			typeBinding = ((ReferenceBinding)typeBinding).enclosingType();
-		} else {
-			typeBinding = null;
-		}
-	} 
-	if (tokens == null) {
-		if (binding == null || binding instanceof ProblemBinding) {
-			tokens = new char[][] {this.simpleName};
-		} else {
-			tokens = qNameRef.tokens;
-		}
-		if (!this.isCaseSensitive) {
-			int length = tokens.length;
-			char[][] lowerCaseTokens = new char[length][];
-			for (int i = 0; i < length; i++) {
-				char[] token = tokens[i];
-				lowerCaseTokens[i] = CharOperation.toLowerCase(token);
-			}
-			tokens = lowerCaseTokens;
-		}
-	}
-	locator.reportAccurateReference(qNameRef.sourceStart, qNameRef.sourceEnd, tokens, element, accuracy);
-}
-/**
- * Reports the match of the given qualified type reference.
- */
-protected void matchReportReference(QualifiedTypeReference qTypeRef, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	char[][] tokens = null;
-	TypeBinding typeBinding = qTypeRef.resolvedType;
-	if (typeBinding instanceof ArrayBinding) {
-		typeBinding = ((ArrayBinding)typeBinding).leafComponentType;
-	}
-	char[][] typeTokens = qTypeRef.tokens;
-	int lastIndex = typeTokens.length-1;
-	// try to match all enclosing types for which the token matches as well.
-	while (typeBinding != null && lastIndex >= 0){
-		if (matchesName(this.simpleName, typeTokens[lastIndex--])) {
-			int level = this.matchLevelForType(this.simpleName, this.qualification, typeBinding);
-			if (level != IMPOSSIBLE_MATCH) {
-				tokens = new char[lastIndex+2][];
-				System.arraycopy(typeTokens, 0, tokens, 0, lastIndex+2);
-				break;
-			}
-		}
-		if (typeBinding instanceof ReferenceBinding){
-			typeBinding = ((ReferenceBinding)typeBinding).enclosingType();
-		} else {
-			typeBinding = null;
-		}
-	}
-	if (tokens == null) {
-		if (typeBinding == null || typeBinding instanceof ProblemReferenceBinding) {
-			tokens = new char[][] {this.simpleName};
-		} else {
-			tokens = qTypeRef.tokens;
-		}
-		if (!this.isCaseSensitive) {
-			int length = tokens.length;
-			char[][] lowerCaseTokens = new char[length][];
-			for (int i = 0; i < length; i++) {
-				char[] token = tokens[i];
-				lowerCaseTokens[i] = CharOperation.toLowerCase(token);
-			}
-			tokens = lowerCaseTokens;
-		}
-	}
-	locator.reportAccurateReference(qTypeRef.sourceStart, qTypeRef.sourceEnd, tokens, element, accuracy);
-}
-/**
  * @see AndPattern#resetQuery
  */
 protected void resetQuery() {
-	if (this.simpleName == null) {
-		/* walk the segments from end to start as it will find less potential references using 'lang' than 'java' */
+	/* walk the segments from end to start as it will find less potential references using 'lang' than 'java' */
+	if (this.simpleName == null)
 		this.currentSegment = this.segments.length - 1;
-	}
 }
-public String toString(){
+public String toString() {
 	StringBuffer buffer = new StringBuffer(20);
-	buffer.append("TypeReferencePattern: pkg<"); //$NON-NLS-1$
-	if (qualification != null) buffer.append(qualification);
+	buffer.append("TypeReferencePattern: qualification<"); //$NON-NLS-1$
+	if (qualification != null) 
+		buffer.append(qualification);
+	else
+		buffer.append("*"); //$NON-NLS-1$
 	buffer.append(">, type<"); //$NON-NLS-1$
-	if (simpleName != null) buffer.append(simpleName);
+	if (simpleName != null) 
+		buffer.append(simpleName);
+	else
+		buffer.append("*"); //$NON-NLS-1$
 	buffer.append(">, "); //$NON-NLS-1$
-	switch(matchMode){
+	switch(matchMode()){
 		case EXACT_MATCH : 
 			buffer.append("exact match, "); //$NON-NLS-1$
 			break;
@@ -345,326 +128,10 @@
 			buffer.append("pattern match, "); //$NON-NLS-1$
 			break;
 	}
-	if (isCaseSensitive)
+	if (isCaseSensitive())
 		buffer.append("case sensitive"); //$NON-NLS-1$
 	else
 		buffer.append("case insensitive"); //$NON-NLS-1$
 	return buffer.toString();
 }
-
-/**
- * @see SearchPattern#matchLevel(AstNode, boolean)
- */
-public int matchLevel(AstNode node, boolean resolve) {
-	if (node instanceof TypeReference) {
-		return this.matchLevel((TypeReference)node, resolve);
-	} else if (node instanceof NameReference) {
-		return this.matchLevel((NameReference)node, resolve);
-	} else if (node instanceof ImportReference) {
-		return this.matchLevel((ImportReference)node, resolve);
-	}
-	return IMPOSSIBLE_MATCH;
-}
-
-/**
- * Returns whether this type pattern matches the given import reference.
- * Look at resolved information only if specified.
- */
-private int matchLevel(ImportReference importRef, boolean resolve) {
-
-	char[][] tokens = importRef.tokens;
-	int importLength = tokens.length;
-	
-	if (this.qualification != null) {
-		char[] pattern;
-		if (this.simpleName == null) {
-			pattern = this.qualification;
-		} else {
-			pattern = CharOperation.concat(this.qualification, this.simpleName, '.');
-		}
-		char[] qualifiedTypeName = CharOperation.concatWith(importRef.tokens, '.');
-		switch (this.matchMode) {
-			case EXACT_MATCH :
-			case PREFIX_MATCH :
-				if (CharOperation.prefixEquals(pattern, qualifiedTypeName, this.isCaseSensitive)) {
-					return POSSIBLE_MATCH;
-				} 
-				break;
-			case PATTERN_MATCH:
-				if (CharOperation.match(pattern, qualifiedTypeName, this.isCaseSensitive)) {
-					return POSSIBLE_MATCH;
-				}
-				break;
-		}
-		return IMPOSSIBLE_MATCH;
-	} else {
-		if (this.simpleName == null) {
-			return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-		} else {
-			for (int i = 0; i < importLength; i++){
-				if (this.matchesName(this.simpleName, tokens[i])){
-					return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-				}
-			}
-			return IMPOSSIBLE_MATCH;
-		}
-	}
-}
-
-/**
- * Returns whether this type pattern matches the given name reference.
- * Look at resolved information only if specified.
- */
-private int matchLevel(NameReference nameRef, boolean resolve) {
-	if (!resolve) {
-		if (this.simpleName == null) {
-			return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-		} else {
-			if (nameRef instanceof SingleNameReference) {
-				if (this.matchesName(this.simpleName, ((SingleNameReference)nameRef).token)) {
-					// can only be a possible match since resolution is needed 
-					// to find out if it is a type ref
-					return POSSIBLE_MATCH;
-				} else {
-					return IMPOSSIBLE_MATCH;
-				}
-			} else { // QualifiedNameReference
-				char[][] tokens = ((QualifiedNameReference)nameRef).tokens;
-				for (int i = 0, max = tokens.length; i < max; i++){
-					if (this.matchesName(this.simpleName, tokens[i])) {
-						// can only be a possible match since resolution is needed 
-						// to find out if it is a type ref
-						return POSSIBLE_MATCH;
-					}
-				}
-				return IMPOSSIBLE_MATCH;
-			}				
-		}
-	} else {
-		Binding binding = nameRef.binding;
-
-		if (nameRef instanceof SingleNameReference) {
-			if (binding instanceof ProblemReferenceBinding) {
-				binding = ((ProblemReferenceBinding)binding).original;
-			}
-			if (binding instanceof VariableBinding) {
-				return IMPOSSIBLE_MATCH;
-			} else if (!(binding instanceof TypeBinding)){
-				return INACCURATE_MATCH;
-			} else {
-				return this.matchLevelForType(this.simpleName, this.qualification, (TypeBinding) binding);
-			}
-		} else { // QualifiedNameReference
-			TypeBinding typeBinding = null;
-			QualifiedNameReference qNameRef = (QualifiedNameReference)nameRef;
-			char[][] tokens = qNameRef.tokens;
-			int lastIndex = tokens.length-1;
-			switch (qNameRef.bits & AstNode.RestrictiveFlagMASK) {
-				case BindingIds.FIELD : // reading a field
-					typeBinding = nameRef.actualReceiverType;
-					// no valid match amongst fields
-					int otherBindingsCount = qNameRef.otherBindings == null ? 0 : qNameRef.otherBindings.length;			
-					lastIndex -= otherBindingsCount + 1;
-					if (lastIndex < 0) return IMPOSSIBLE_MATCH;
-					break;
-				case BindingIds.LOCAL : // reading a local variable
-					return IMPOSSIBLE_MATCH; // no type match in it
-				case BindingIds.TYPE : //=============only type ==============
-					if (binding instanceof ProblemReferenceBinding) {
-						binding = ((ProblemReferenceBinding)binding).original;
-					}
-					if (!(binding instanceof TypeBinding)) {
-						return INACCURATE_MATCH;
-					}
-					typeBinding = (TypeBinding)binding;
-					break;
-				/*
-				 * Handling of unbound qualified name references. The match may reside in the resolved fragment,
-				 * which is recorded inside the problem binding, along with the portion of the name until it became a problem.
-				 */
-				case BindingIds.VARIABLE : //============unbound cases===========
-				case BindingIds.TYPE | BindingIds.VARIABLE :						
-					if (binding instanceof ProblemBinding) {
-						ProblemBinding pbBinding = (ProblemBinding) binding;
-						typeBinding = pbBinding.searchType; // second chance with recorded type so far
-						char[] partialQualifiedName = pbBinding.name;
-						lastIndex = CharOperation.occurencesOf('.', partialQualifiedName) - 1; // index of last bound token is one before the pb token
-						if (typeBinding == null || lastIndex < 0) return INACCURATE_MATCH;
-					} else if (binding instanceof ProblemReferenceBinding) {
-						ProblemReferenceBinding pbBinding = (ProblemReferenceBinding)binding;
-						binding = pbBinding.original;
-						if (!(binding instanceof TypeBinding)) {
-							return INACCURATE_MATCH;
-						}
-						typeBinding = (TypeBinding)binding;
-						char[][] partialQualifiedName = pbBinding.compoundName;
-						lastIndex = partialQualifiedName == null ? -1 : partialQualifiedName.length - 1; // index of last bound token is one before the pb token
-						if (typeBinding == null || lastIndex < 0) return INACCURATE_MATCH;
-					}
-					break;
-			}
-			// try to match all enclosing types for which the token matches as well.
-			while (typeBinding != null && lastIndex >= 0){
-				if (this.matchesName(this.simpleName, tokens[lastIndex--])) {
-					int level = this.matchLevelForType(this.simpleName, this.qualification, typeBinding);
-					if (level != IMPOSSIBLE_MATCH) {
-						return level;
-					}
-				}
-				if (typeBinding instanceof ReferenceBinding){
-					typeBinding = ((ReferenceBinding)typeBinding).enclosingType();
-				} else {
-					typeBinding = null;
-				}
-			}
-			return IMPOSSIBLE_MATCH;
-		}
-	}
-}
-
-/**
- * Reports the match of the given array type reference.
- */
-protected void matchReportReference(ArrayTypeReference arrayRef, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	char[][] tokens = this.simpleName == null ? CharOperation.NO_CHAR_CHAR : new char[][] {this.simpleName};
-	locator.reportAccurateReference(arrayRef.sourceStart, arrayRef.sourceEnd, tokens, element, accuracy);
-}
-
-/**
- * Returns whether this type pattern matches the given type reference.
- * Look at resolved information only if specified.
- */
-private int matchLevel(TypeReference typeRef, boolean resolve) {
-	if (!resolve) {
-		if (this.simpleName == null) {
-			return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-		} else {
-			if (typeRef instanceof SingleTypeReference) {
-				if (this.matchesName(this.simpleName, ((SingleTypeReference)typeRef).token)) {
-					return this.needsResolve ? POSSIBLE_MATCH : ACCURATE_MATCH;
-				} else {
-					return IMPOSSIBLE_MATCH;
-				}
-			} else { // QualifiedTypeReference
-				char[][] tokens = ((QualifiedTypeReference)typeRef).tokens;
-				for (int i = 0, max = tokens.length; i < max; i++){
-					if (this.matchesName(this.simpleName, tokens[i])) {
-						// can only be a possible match since resolution is needed 
-						// to find out if it is a type ref
-						return POSSIBLE_MATCH;
-					}
-				}
-				return IMPOSSIBLE_MATCH;
-			}				
-		} 
-	} else {
-		TypeBinding typeBinding = typeRef.resolvedType;
-		if (typeBinding instanceof ArrayBinding) {
-			typeBinding = ((ArrayBinding)typeBinding).leafComponentType;
-		}
-		if (typeBinding instanceof ProblemReferenceBinding) {
-			Binding binding = ((ProblemReferenceBinding)typeBinding).original;
-			if (binding instanceof TypeBinding) {
-				typeBinding = (TypeBinding)binding;
-			} else if (binding == null) {
-				typeBinding = null;
-			}
-		}
-		if (typeBinding == null) {
-			return INACCURATE_MATCH;
-		}
-		if (typeRef instanceof SingleTypeReference){
-			return this.matchLevelForType(this.simpleName, this.qualification, typeBinding);
-		} else { // QualifiedTypeReference
-			QualifiedTypeReference qTypeRef = (QualifiedTypeReference)typeRef;
-			char[][] tokens = qTypeRef.tokens;
-			int lastIndex = tokens.length-1;
-			// try to match all enclosing types for which the token matches as well.
-			while (typeBinding != null && lastIndex >= 0){
-				if (matchesName(this.simpleName, tokens[lastIndex--])) {
-					int level = this.matchLevelForType(this.simpleName, this.qualification, typeBinding);
-					if (level != IMPOSSIBLE_MATCH) {
-						return level;
-					}
-				}
-				if (typeBinding instanceof ReferenceBinding){
-					typeBinding = ((ReferenceBinding)typeBinding).enclosingType();
-				} else {
-					typeBinding = null;
-				}
-			}
-			return IMPOSSIBLE_MATCH;
-		} 
-			
-	}
-}
-/**
- * @see SearchPattern#matchReportImportRef(ImportReference, Binding, IJavaElement, int, MatchLocator)
- */
-protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
-	ReferenceBinding typeBinding = null;
-	char[][] tokens = null;
-	if (binding instanceof ReferenceBinding) {
-		typeBinding = (ReferenceBinding)binding;
-	}
-	char[][] typeTokens = importRef.tokens;
-	int lastIndex = typeTokens.length-1;
-	// try to match all enclosing types for which the token matches as well.
-	while (typeBinding != null && lastIndex >= 0){
-		if (matchesName(this.simpleName, typeTokens[lastIndex--])) {
-			int level = this.matchLevelForType(this.simpleName, this.qualification, typeBinding);
-			if (level != IMPOSSIBLE_MATCH) {
-				tokens = new char[lastIndex+2][];
-				System.arraycopy(typeTokens, 0, tokens, 0, lastIndex+2);
-				break;
-			}
-		}
-		if (typeBinding instanceof ReferenceBinding){
-			typeBinding = ((ReferenceBinding)typeBinding).enclosingType();
-		} else {
-			typeBinding = null;
-		}
-	}
-	if (tokens == null) {
-		if (typeBinding == null || typeBinding instanceof ProblemReferenceBinding) {
-			tokens = new char[][] {this.simpleName};
-		} else {
-			tokens = importRef.tokens;
-		}
-		if (!this.isCaseSensitive) {
-			int length = tokens.length;
-			char[][] lowerCaseTokens = new char[length][];
-			for (int i = 0; i < length; i++) {
-				char[] token = tokens[i];
-				lowerCaseTokens[i] = CharOperation.toLowerCase(token);
-			}
-			tokens = lowerCaseTokens;
-		}
-	}
-	locator.reportAccurateReference(importRef.sourceStart, importRef.sourceEnd, tokens, element, accuracy);
-}
-
-/**
- * @see SearchPattern#matchLevel(Binding)
- */
-public int matchLevel(Binding binding) {
-	if (binding == null) return INACCURATE_MATCH;
-	if (!(binding instanceof TypeBinding)) return IMPOSSIBLE_MATCH;
-	TypeBinding typeBinding = (TypeBinding)binding;
-	if (typeBinding instanceof ArrayBinding) typeBinding = ((ArrayBinding)typeBinding).leafComponentType;
-	if (typeBinding instanceof ProblemReferenceBinding) return INACCURATE_MATCH;
-
-	while (typeBinding != null ) {
-		int level = this.matchLevelForType(this.simpleName, this.qualification, typeBinding);
-		if (level != IMPOSSIBLE_MATCH) {
-			return level;
-		}
-		if (typeBinding instanceof ReferenceBinding){
-			typeBinding = ((ReferenceBinding)typeBinding).enclosingType();
-		} else {
-			typeBinding = null;
-		}
-	}
-	return IMPOSSIBLE_MATCH;
-}
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/VariableLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/VariableLocator.java
new file mode 100644
index 0000000..52ca6a1
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/VariableLocator.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.jdt.internal.compiler.ast.*;
+
+public class VariableLocator extends PatternLocator {
+
+protected VariablePattern pattern;
+
+public VariableLocator(VariablePattern pattern) {
+	super(pattern);
+
+	this.pattern = pattern;
+}
+public int match(Expression node, MatchingNodeSet nodeSet) { // interested in Assignment
+	if (this.pattern.writeAccess) {
+		if (this.pattern.readAccess) return IMPOSSIBLE_MATCH; // already checked the lhs in match(Reference...) before we reached here
+
+		if (node instanceof Assignment) {
+			Expression lhs = ((Assignment) node).lhs;
+			if (lhs instanceof Reference)
+				return matchReference((Reference) lhs, nodeSet, true);
+		}
+	} else if (this.pattern.readAccess) {
+		if (node instanceof Assignment && !(node instanceof CompoundAssignment)) {
+			// the lhs of a simple assignment may be added in match(Reference...) before we reach here
+			// for example, the fieldRef to 'this.x' in the statement this.x = x; is not considered a readAccess
+			Expression lhs = ((Assignment) node).lhs;
+			nodeSet.removePossibleMatch(lhs);
+			nodeSet.removeTrustedMatch(lhs);
+		}
+	}
+	return IMPOSSIBLE_MATCH;
+}
+public int match(Reference node, MatchingNodeSet nodeSet) { // interested in NameReference & its subtypes
+	return this.pattern.readAccess
+		? matchReference(node, nodeSet, false)
+		: IMPOSSIBLE_MATCH;
+}
+protected int matchReference(Reference node, MatchingNodeSet nodeSet, boolean writeOnlyAccess) {
+	if (node instanceof NameReference) {
+		if (this.pattern.name == null) {
+			return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
+		} else if (node instanceof SingleNameReference) {
+			if (matchesName(this.pattern.name, ((SingleNameReference) node).token))
+				return nodeSet.addMatch(node, POSSIBLE_MATCH);
+		} else {
+			QualifiedNameReference qNameRef = (QualifiedNameReference) node;
+			char[][] tokens = qNameRef.tokens;
+			if (writeOnlyAccess) {
+				// in the case of the assigment of a qualified name reference, the match must be on the last token
+				if (matchesName(this.pattern.name, tokens[tokens.length-1]))
+					return nodeSet.addMatch(node, POSSIBLE_MATCH);
+			} else {
+				for (int i = 0, max = tokens.length; i < max; i++)
+					if (matchesName(this.pattern.name, tokens[i]))
+						return nodeSet.addMatch(node, POSSIBLE_MATCH);
+			}
+		}
+	}
+	return IMPOSSIBLE_MATCH;
+}
+public String toString() {
+	return "Locator for " + this.pattern.toString(); //$NON-NLS-1$
+}
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/VariablePattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/VariablePattern.java
new file mode 100644
index 0000000..e2ebe94
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/VariablePattern.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.matching;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
+
+public abstract class VariablePattern extends SearchPattern {
+
+protected boolean findDeclarations;
+protected boolean findReferences;
+protected boolean readAccess;
+protected boolean writeAccess;
+
+protected char[] name;
+	
+public VariablePattern(
+	int patternKind,
+	boolean findDeclarations,
+	boolean readAccess,
+	boolean writeAccess,
+	char[] name,
+	int matchRule) {
+
+	super(patternKind, matchRule);
+
+	this.findDeclarations = findDeclarations; // set to find declarations & all occurences
+	this.readAccess = readAccess; // set to find any reference, read only references & all occurences
+	this.writeAccess = writeAccess; // set to find any reference, write only references & all occurences
+	this.findReferences = readAccess || writeAccess;
+
+	this.name = isCaseSensitive() ? name : CharOperation.toLowerCase(name);
+}
+/*
+ * Returns whether a method declaration or message send will need to be resolved to 
+ * find out if this method pattern matches it.
+ */
+protected boolean mustResolve() {
+	// would like to change this so that we only do it if generic references are found
+	return this.findReferences; // always resolve (in case of a simple name reference being a potential match)
+}	
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/messages.properties b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/messages.properties
deleted file mode 100644
index 15541ac..0000000
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/messages.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-###############################################################################
-# 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
-###############################################################################
-### Eclipse Java Core Search messages.
-
-engine.searching = Searching...
-exception.wrongFormat = Wrong format
-process.name = Java indexing
-manager.filesToIndex = {0} files to index
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/pattern/InternalSearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/pattern/InternalSearchPattern.java
new file mode 100644
index 0000000..ec588ff
--- /dev/null
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/pattern/InternalSearchPattern.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * 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 org.eclipse.jdt.internal.core.search.pattern;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.search.*;
+import org.eclipse.jdt.internal.core.JavaModelManager;
+import org.eclipse.jdt.internal.core.index.IIndex;
+import org.eclipse.jdt.internal.core.index.impl.*;
+import org.eclipse.jdt.internal.core.search.*;
+import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
+import org.eclipse.jdt.internal.core.util.Util;
+
+/**
+ * TODO add spec
+ */
+public abstract class InternalSearchPattern {
+
+	public final int kind;
+	public final int matchRule;
+	
+	/* focus element (used for reference patterns*/
+	public IJavaElement focus;
+
+	public InternalSearchPattern(int patternKind, int matchRule) {
+		this.kind = patternKind;
+		this.matchRule = matchRule;
+	}
+	
+	/*
+	 * @see SearchPattern
+	 */
+	public abstract void decodeIndexKey(char[] key);
+
+	/*
+	 * @see SearchPattern
+	 */
+	public abstract char[] encodeIndexKey();
+
+	protected char[] encodeIndexKey(char[] key) {
+		// TODO (kent) with new index, need to encode key for case insensitive queries too
+		// also want to pass along the entire pattern
+		if (isCaseSensitive() && key != null) {
+			switch(matchMode()) {
+				case SearchPattern.R_EXACT_MATCH :
+				case  SearchPattern.R_PREFIX_MATCH :
+					return key;
+				case  SearchPattern.R_PATTERN_MATCH :
+					int starPos = CharOperation.indexOf('*', key);
+					switch(starPos) {
+						case -1 :
+							return key;
+						default : 
+							char[] result = new char[starPos];
+							System.arraycopy(key, 0, result, 0, starPos);
+							return result;
+						case 0 : // fall through
+					}
+					break;
+				case  SearchPattern.R_REGEXP_MATCH:
+					// TODO (jerome) implement
+					return key;
+			}
+		}
+		return CharOperation.NO_CHAR; // find them all
+	}
+
+	/**
+	 * Query a given index for matching entries. 
+	 */
+	public void findIndexMatches(IIndex index, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope, IProgressMonitor progressMonitor) throws IOException {
+	
+		if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
+		IndexInput input = new BlocksIndexInput(index.getIndexFile());
+		try {
+			input.open();
+			findIndexMatches(input, requestor, participant, scope, progressMonitor);
+		} finally {
+			input.close();
+		}
+	}
+	
+	/**
+	 * Query a given index for matching entries. 
+	 *
+	 */
+	public void findIndexMatches(IndexInput input, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope, IProgressMonitor progressMonitor) throws IOException {
+	
+		char[][] categories = getMatchCategories();
+		char[] queryKey = encodeIndexKey();
+		for (int iCategory = 0, categoriesLength = categories.length; iCategory < categoriesLength; iCategory++) {
+			if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
+
+			char[] category = categories[iCategory];
+			findIndexMatches(input, requestor, participant, scope, progressMonitor, queryKey, category);
+		}
+	}
+	
+	protected void findIndexMatches(IndexInput input, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope, IProgressMonitor progressMonitor, char[] queryKey, char[] category) throws IOException {
+		/* narrow down a set of entries using prefix criteria */
+		// TODO per construction the queryKey will always be the most specific prefix. This should evolve to be the search pattern directly, using proper match rule
+		// ideally the index query API should be defined to avoid the need for concatenating the category to the key
+		char[] pattern = CharOperation.concat(category, queryKey);
+		EntryResult[] entries = input.queryEntries(pattern, SearchPattern.R_PREFIX_MATCH);
+		if (entries == null) return;
+
+		/* only select entries which actually match the entire search pattern */
+		for (int iMatch = 0, matchesLength = entries.length; iMatch < matchesLength; iMatch++) {
+			if (progressMonitor != null && progressMonitor.isCanceled()) throw new OperationCanceledException();
+
+			/* retrieve and decode entry */	
+			EntryResult entry = entries[iMatch];
+			char[] word = entry.getWord();
+			char[] indexKey = CharOperation.subarray(word, category.length, word.length);
+			SearchPattern indexRecord = getIndexRecord();
+			indexRecord.decodeIndexKey(indexKey);
+			if (isMatchingIndexRecord()) {
+				int[] references = entry.getFileReferences();
+				for (int iReference = 0, refererencesLength = references.length; iReference < refererencesLength; iReference++) {
+					String documentPath = IndexedFile.convertPath( input.getIndexedFile(references[iReference]).getPath());
+					if (scope.encloses(documentPath)) {
+						if (!requestor.acceptIndexMatch(documentPath, indexRecord, participant)) 
+							throw new OperationCanceledException();
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Searches for matches to a given query. Search queries can be created using helper
+	 * methods (from a String pattern or a Java element) and encapsulate the description of what is
+	 * being searched (for example, search method declarations in a case sensitive way).
+	 *
+	 * @param scope the search result has to be limited to the given scope
+	 * @param resultCollector a callback object to which each match is reported
+	 */
+	public void findMatches(SearchParticipant[] participants, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException {
+		
+		if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+		
+		/* initialize progress monitor */
+		if (monitor != null) {
+			monitor.beginTask(Util.bind("engine.searching"), 100); //$NON-NLS-1$
+		}
+
+		if (SearchEngine.VERBOSE) {
+			System.out.println("Searching for " + this + " in " + scope); //$NON-NLS-1$//$NON-NLS-2$
+		}
+	
+		IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
+		try {
+			requestor.beginReporting();
+			
+			for (int iParticipant = 0, length = participants == null ? 0 : participants.length; iParticipant < length; iParticipant++) {
+				
+				if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+	
+				SearchParticipant participant = participants[iParticipant];
+				try {
+					participant.beginSearching();
+					requestor.enterParticipant(participant);
+		
+					// find index matches			
+					PathCollector pathCollector = new PathCollector();
+					indexManager.performConcurrentJob(
+						new PatternSearchJob(
+							(SearchPattern)this, 
+							participant,
+							scope, 
+							pathCollector),
+						IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
+						monitor);
+					if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+		
+					// locate index matches if any (note that all search matches could have been issued during index querying)
+					String[] indexMatchPaths = pathCollector.getPaths();
+					pathCollector = null; // release
+					int indexMatchLength = indexMatchPaths == null ? 0 : indexMatchPaths.length;
+					SearchDocument[] indexMatches = new SearchDocument[indexMatchLength];
+					for (int iMatch = 0;iMatch < indexMatchLength; iMatch++) {
+						String documentPath = indexMatchPaths[iMatch];
+						indexMatches[iMatch] = participant.getDocument(documentPath);
+					}
+					participant.locateMatches(indexMatches, (SearchPattern)this, scope, requestor, monitor);
+				} finally {		
+					requestor.exitParticipant(participant);
+					participant.doneSearching();
+				}
+
+				if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+			}
+		} finally {
+			requestor.endReporting();
+			if (monitor != null) monitor.done();
+		}
+	}			
+
+	public abstract SearchPattern getIndexRecord();
+	
+	public abstract char[][] getMatchCategories();
+
+	public boolean isCaseSensitive() {
+		return (this.matchRule & SearchPattern.R_CASE_SENSITIVE) != 0;
+	}
+	
+	public abstract boolean isMatchingIndexRecord();
+
+	/*
+	 * Returns whether this pattern is a polymorphic search pattern.
+	 */
+	public boolean isPolymorphicSearch() {
+		return false;
+	}
+
+	/*
+	 * One of R_EXACT_MATCH, R_PATTERN_MATCH, R_PREFIX_MATCH or R_REGEDP_MATCH
+	 */
+	public int matchMode() {
+		return this.matchRule & ~SearchPattern.R_CASE_SENSITIVE;
+	}
+
+}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/IJob.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/IJob.java
index b53d454..b800a59 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/IJob.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/IJob.java
@@ -33,11 +33,11 @@
 	 */
 	public void cancel();
 	/**
+	 * Ensures that this job is ready to run.
+	 */
+	public void ensureReadyToRun();
+	/**
 	 * Execute the current job, answer whether it was successful.
 	 */
 	public boolean execute(IProgressMonitor progress);
-	/**
-	 * Answer whether the job is ready to run.
-	 */
-	public boolean isReadyToRun();
 }
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
index 5a1e1a1..3763cd1 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/processing/JobManager.java
@@ -13,7 +13,7 @@
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.core.runtime.SubProgressMonitor;
-import org.eclipse.jdt.internal.core.search.Util;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public abstract class JobManager implements Runnable {
 
@@ -24,7 +24,7 @@
 	protected boolean executing = false;
 
 	/* background processing */
-	protected Thread thread;
+	protected Thread processingThread;
 
 	/* flag indicating whether job execution is enabled or not */
 	private boolean enabled = true;
@@ -49,30 +49,20 @@
 	 * Answer the amount of awaiting jobs.
 	 */
 	public synchronized int awaitingJobsCount() {
-
 		// pretend busy in case concurrent job attempts performing before activated
-		if (!activated)
-			return 1;
-
-		return jobEnd - jobStart + 1;
-
+		return this.activated ? this.jobEnd - this.jobStart + 1 : 1;
 	}
 	/**
 	 * Answers the first job in the queue, or null if there is no job available
 	 * Until the job has completed, the job manager will keep answering the same job.
 	 */
 	public synchronized IJob currentJob() {
-
-		if (!enabled)
-			return null;
-
-		if (jobStart <= jobEnd) {
-			return awaitingJobs[jobStart];
-		}
+		if (this.enabled && this.jobStart <= this.jobEnd)
+			return this.awaitingJobs[this.jobStart];
 		return null;
 	}
-	public synchronized void disable() {
-		enabled = false;
+	public void disable() {
+		this.enabled = false;
 		if (VERBOSE)
 			JobManager.verbose("DISABLING background indexing"); //$NON-NLS-1$
 	}
@@ -93,39 +83,37 @@
 				currentJob = this.currentJob();
 				disable();
 			}
-			if (currentJob != null 
-					&& (jobFamily == null || currentJob.belongsTo(jobFamily))) {
-	
+			if (currentJob != null && (jobFamily == null || currentJob.belongsTo(jobFamily))) {
 				currentJob.cancel();
-			
+
 				// wait until current active job has finished
-				while (thread != null && executing){
+				while (this.processingThread != null && this.executing){
 					try {
 						if (VERBOSE)
 							JobManager.verbose("-> waiting end of current background job - " + currentJob); //$NON-NLS-1$ //$NON-NLS-2$
 						Thread.sleep(50);
 					} catch(InterruptedException e){
+						// ignore
 					}
 				}
 			}
-	
+
 			// flush and compact awaiting jobs
 			int loc = -1;
 			synchronized(this) {
-				for (int i = jobStart; i <= jobEnd; i++) {
-					currentJob = awaitingJobs[i];
-					awaitingJobs[i] = null;
-					if (!(jobFamily == null
-						|| currentJob.belongsTo(jobFamily))) { // copy down, compacting
-						awaitingJobs[++loc] = currentJob;
+				for (int i = this.jobStart; i <= this.jobEnd; i++) {
+					currentJob = this.awaitingJobs[i];
+					this.awaitingJobs[i] = null;
+					if (!(jobFamily == null || currentJob.belongsTo(jobFamily))) { // copy down, compacting
+						this.awaitingJobs[++loc] = currentJob;
 					} else {
 						if (VERBOSE)
 							JobManager.verbose("-> discarding background job  - " + currentJob); //$NON-NLS-1$
 						currentJob.cancel();
 					}
 				}
-				jobStart = 0;
-				jobEnd = loc;
+				this.jobStart = 0;
+				this.jobEnd = loc;
 			}
 		} finally {
 			if (wasEnabled)
@@ -135,26 +123,26 @@
 			JobManager.verbose("DISCARD   DONE with background job family - " + jobFamily); //$NON-NLS-1$
 	}
 	public synchronized void enable() {
-		enabled = true;
+		this.enabled = true;
 		if (VERBOSE)
 			JobManager.verbose("ENABLING  background indexing"); //$NON-NLS-1$
+		this.notifyAll(); // wake up the background thread if it is waiting (context must be synchronized)			
 	}
-	public synchronized boolean isEnabled() {
-		return enabled;
+	public boolean isEnabled() {
+		return this.enabled;
 	}
 	/**
 	 * Advance to the next available job, once the current one has been completed.
 	 * Note: clients awaiting until the job count is zero are still waiting at this point.
 	 */
 	protected synchronized void moveToNextJob() {
-
 		//if (!enabled) return;
 
-		if (jobStart <= jobEnd) {
-			awaitingJobs[jobStart++] = null;
-			if (jobStart > jobEnd) {
-				jobStart = 0;
-				jobEnd = -1;
+		if (this.jobStart <= this.jobEnd) {
+			this.awaitingJobs[this.jobStart++] = null;
+			if (this.jobStart > this.jobEnd) {
+				this.jobStart = 0;
+				this.jobEnd = -1;
 			}
 		}
 	}
@@ -162,6 +150,7 @@
 	 * When idle, give chance to do something
 	 */
 	protected void notifyIdle(long idlingTime) {
+		// do nothing
 	}
 	/**
 	 * This API is allowing to run one job in concurrence with background processing.
@@ -178,18 +167,11 @@
 	 * 		IJobConstants.WaitUntilReadyToSearch
 	 *
 	 */
-	public boolean performConcurrentJob(
-		IJob searchJob,
-		int waitingPolicy,
-		IProgressMonitor progress) {
-
+	public boolean performConcurrentJob(IJob searchJob, int waitingPolicy, IProgressMonitor progress) {
 		if (VERBOSE)
 			JobManager.verbose("STARTING  concurrent job - " + searchJob); //$NON-NLS-1$
-		if (!searchJob.isReadyToRun()) {
-			if (VERBOSE)
-				JobManager.verbose("ABORTED   concurrent job - " + searchJob); //$NON-NLS-1$
-			return IJob.FAILED;
-		}
+
+		searchJob.ensureReadyToRun();
 
 		int concurrentJobWork = 100;
 		if (progress != null)
@@ -212,7 +194,7 @@
 					if (VERBOSE)
 						JobManager.verbose("FINISHED  concurrent job - " + searchJob); //$NON-NLS-1$
 					return status;
-					
+
 				case IJob.CancelIfNotReady :
 					if (VERBOSE)
 						JobManager.verbose("-> NOT READY - cancelling - " + searchJob); //$NON-NLS-1$
@@ -232,15 +214,14 @@
 						subProgress.beginTask("", totalWork); //$NON-NLS-1$
 						concurrentJobWork = concurrentJobWork / 2;
 					}
-					int originalPriority = this.thread.getPriority();
+					// use local variable to avoid potential NPE (see bug 20435 NPE when searching java method
+					// and bug 42760 NullPointerException in JobManager when searching)
+					Thread t = this.processingThread;
+					int originalPriority = t == null ? -1 : t.getPriority();
 					try {
+						if (t != null)
+							t.setPriority(Thread.currentThread().getPriority());
 						synchronized(this) {
-							
-							// use local variable to avoid potential NPE (see Bug 20435 NPE when searching java method)
-							Thread t = this.thread;
-							if (t != null) {
-								t.setPriority(Thread.currentThread().getPriority());
-							}
 							this.awaitingClients++;
 						}
 						while ((awaitingWork = awaitingJobsCount()) > 0) {
@@ -259,30 +240,27 @@
 								previousJob = currentJob;
 							}
 							try {
+								if (VERBOSE)
+									JobManager.verbose("-> GOING TO SLEEP - " + searchJob);//$NON-NLS-1$
 								Thread.sleep(50);
 							} catch (InterruptedException e) {
+								// ignore
 							}
 						}
 					} finally {
 						synchronized(this) {
 							this.awaitingClients--;
-							
-							// use local variable to avoid potential NPE (see Bug 20435 NPE when searching java method)
-							Thread t = this.thread;
-							if (t != null) {
-								t.setPriority(originalPriority);
-							}
 						}
+						if (originalPriority > -1 && t.isAlive())
+							t.setPriority(originalPriority);
 					}
-					if (subProgress != null) {
+					if (subProgress != null)
 						subProgress.done();
-					}
 			}
 		}
 		status = searchJob.execute(progress == null ? null : new SubProgressMonitor(progress, concurrentJobWork));
-		if (progress != null) {
+		if (progress != null)
 			progress.done();
-		}
 		if (VERBOSE)
 			JobManager.verbose("FINISHED  concurrent job - " + searchJob); //$NON-NLS-1$
 		return status;
@@ -290,28 +268,22 @@
 	public abstract String processName();
 	
 	public synchronized void request(IJob job) {
-		if (!job.isReadyToRun()) {
-			if (VERBOSE)
-				JobManager.verbose("ABORTED request of background job - " + job); //$NON-NLS-1$
-			return;
-		}
+
+		job.ensureReadyToRun();
 
 		// append the job to the list of ones to process later on
-		int size = awaitingJobs.length;
-		if (++jobEnd == size) { // when growing, relocate jobs starting at position 0
-			jobEnd -= jobStart;
-			System.arraycopy(
-				awaitingJobs,
-				jobStart,
-				(awaitingJobs = new IJob[size * 2]),
-				0,
-				jobEnd);
-			jobStart = 0;
+		int size = this.awaitingJobs.length;
+		if (++this.jobEnd == size) { // when growing, relocate jobs starting at position 0
+			this.jobEnd -= this.jobStart;
+			System.arraycopy(this.awaitingJobs, this.jobStart, this.awaitingJobs = new IJob[size * 2], 0, this.jobEnd);
+			this.jobStart = 0;
 		}
-		awaitingJobs[jobEnd] = job;
-		if (VERBOSE)
+		this.awaitingJobs[this.jobEnd] = job;
+		if (VERBOSE) {
 			JobManager.verbose("REQUEST   background job - " + job); //$NON-NLS-1$
-
+			JobManager.verbose("AWAITING JOBS count: " + awaitingJobsCount()); //$NON-NLS-1$
+		}
+		notifyAll(); // wake up the background thread if it is waiting
 	}
 	/**
 	 * Flush current state
@@ -320,15 +292,15 @@
 		if (VERBOSE)
 			JobManager.verbose("Reset"); //$NON-NLS-1$
 
-		if (thread != null) {
+		if (this.processingThread != null) {
 			discardJobs(null); // discard all jobs
 		} else {
 			/* initiate background processing */
-			thread = new Thread(this, this.processName());
-			thread.setDaemon(true);
+			this.processingThread = new Thread(this, this.processName());
+			this.processingThread.setDaemon(true);
 			// less prioritary by default, priority is raised if clients are actively waiting on it
-			thread.setPriority(Thread.NORM_PRIORITY-1); 
-			thread.start();
+			this.processingThread.setPriority(Thread.NORM_PRIORITY-1); 
+			this.processingThread.start();
 		}
 	}
 	/**
@@ -339,58 +311,68 @@
 		long idlingStart = -1;
 		activateProcessing();
 		try {
-			while (this.thread != null) {
+			while (this.processingThread != null) {
 				try {
 					IJob job;
-					if ((job = currentJob()) == null) {
-						if (idlingStart < 0)
-							idlingStart = System.currentTimeMillis();
+					synchronized (this) {
+						// handle shutdown case when notifyAll came before the wait but after the while loop was entered
+						if (this.processingThread == null) continue;
+
+						// must check for new job inside this sync block to avoid timing hole
+						if ((job = currentJob()) == null) {
+							if (idlingStart < 0)
+								idlingStart = System.currentTimeMillis();
+							else
+								notifyIdle(System.currentTimeMillis() - idlingStart);
+							this.wait(); // wait until a new job is posted (or reenabled:38901)
+						} else {
+							idlingStart = -1;
+						}
+					}
+					if (job == null) {
 						notifyIdle(System.currentTimeMillis() - idlingStart);
+						// just woke up, delay before processing any new jobs, allow some time for the active thread to finish
 						Thread.sleep(500);
 						continue;
-					} else {
-						idlingStart = -1;
 					}
 					if (VERBOSE) {
 						JobManager.verbose(awaitingJobsCount() + " awaiting jobs"); //$NON-NLS-1$
 						JobManager.verbose("STARTING background job - " + job); //$NON-NLS-1$
 					}
 					try {
-						executing = true;
+						this.executing = true;
 						/*boolean status = */job.execute(null);
 						//if (status == FAILED) request(job);
 					} finally {
-						executing = false;
-						if (VERBOSE) {
+						this.executing = false;
+						if (VERBOSE)
 							JobManager.verbose("FINISHED background job - " + job); //$NON-NLS-1$
-						}
 						moveToNextJob();
-						if (this.awaitingClients == 0) {
+						if (this.awaitingClients == 0)
 							Thread.sleep(50);
-						}
 					}
 				} catch (InterruptedException e) { // background indexing was interrupted
 				}
 			}
 		} catch (RuntimeException e) {
-			if (this.thread != null) { // if not shutting down
+			if (this.processingThread != null) { // if not shutting down
 				// log exception
-				org.eclipse.jdt.internal.core.Util.log(e, "Background Indexer Crash Recovery"); //$NON-NLS-1$
+				Util.log(e, "Background Indexer Crash Recovery"); //$NON-NLS-1$
 				
 				// keep job manager alive
 				this.discardJobs(null);
-				this.thread = null;
+				this.processingThread = null;
 				this.reset(); // this will fork a new thread with no waiting jobs, some indexes will be inconsistent
 			}
 			throw e;
 		} catch (Error e) {
-			if (this.thread != null && !(e instanceof ThreadDeath)) {
+			if (this.processingThread != null && !(e instanceof ThreadDeath)) {
 				// log exception
-				org.eclipse.jdt.internal.core.Util.log(e, "Background Indexer Crash Recovery"); //$NON-NLS-1$
+				Util.log(e, "Background Indexer Crash Recovery"); //$NON-NLS-1$
 				
 				// keep job manager alive
 				this.discardJobs(null);
-				this.thread = null;
+				this.processingThread = null;
 				this.reset(); // this will fork a new thread with no waiting jobs, some indexes will be inconsistent
 			}
 			throw e;
@@ -403,23 +385,28 @@
 
 		disable();
 		discardJobs(null); // will wait until current executing job has completed
-		Thread thread = this.thread;
-		this.thread = null; // mark the job manager as shutting down so that the thread will stop by itself
+		Thread thread = this.processingThread;
 		try {
 			if (thread != null) { // see http://bugs.eclipse.org/bugs/show_bug.cgi?id=31858
+				synchronized (this) {
+					this.processingThread = null; // mark the job manager as shutting down so that the thread will stop by itself
+					this.notifyAll(); // ensure its awake so it can be shutdown
+				}
+				// in case processing thread is handling a job
 				thread.join();
 			}
 		} catch (InterruptedException e) {
+			// ignore
 		}
 	}
-public String toString() {
-	StringBuffer buffer = new StringBuffer(10);
-	buffer.append("Enabled:").append(this.enabled).append('\n'); //$NON-NLS-1$
-	int numJobs = jobEnd - jobStart + 1;
-	buffer.append("Jobs in queue:").append(numJobs).append('\n'); //$NON-NLS-1$
-	for (int i = 0; i < numJobs && i < 15; i++) {
-		buffer.append(i).append(" - job["+i+"]: ").append(awaitingJobs[jobStart+i]).append('\n'); //$NON-NLS-1$ //$NON-NLS-2$
-	}
-	return buffer.toString();
-}	
+	public String toString() {
+		StringBuffer buffer = new StringBuffer(10);
+		buffer.append("Enabled:").append(this.enabled).append('\n'); //$NON-NLS-1$
+		int numJobs = this.jobEnd - this.jobStart + 1;
+		buffer.append("Jobs in queue:").append(numJobs).append('\n'); //$NON-NLS-1$
+		for (int i = 0; i < numJobs && i < 15; i++) {
+			buffer.append(i).append(" - job["+i+"]: ").append(this.awaitingJobs[this.jobStart+i]).append('\n'); //$NON-NLS-1$ //$NON-NLS-2$
+		}
+		return buffer.toString();
+	}	
 }