APT_32 - Merge with 3.2 M4 (v_631)
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 296ef11..0a090e7 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,4 @@
-#Fri Apr 15 23:54:42 CEST 2005
+#Fri Dec 16 15:10:20 CET 2005
 eclipse.preferences.version=1
 org.eclipse.jdt.core.builder.cleanOutputFolder=clean
 org.eclipse.jdt.core.builder.duplicateResourceTask=warning
@@ -29,6 +29,9 @@
 org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
 org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
 org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
 org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
 org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
 org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF
index 4787171..0a46081 100644
--- a/META-INF/MANIFEST.MF
+++ b/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.jdt.core; singleton:=true
-Bundle-Version: 3.2.0.apt02
+Bundle-Version: 3.2.0.qualifier
 Bundle-ClassPath: .
 Bundle-Activator: org.eclipse.jdt.core.JavaCore
 Bundle-Vendor: %providerName
@@ -51,8 +51,9 @@
  org.eclipse.jdt.internal.formatter.align;x-internal:=true,
  org.eclipse.jdt.internal.formatter.comment;x-internal:=true,
  org.eclipse.jdt.internal.formatter.old;x-internal:=true
-Require-Bundle: org.eclipse.core.resources,
- org.eclipse.core.runtime,
- org.eclipse.text,
- org.eclipse.team.core;resolution:=optional
+Require-Bundle: org.eclipse.core.resources;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.core.runtime;bundle-version="[3.1.0,4.0.0)",
+ org.eclipse.core.filesystem,
+ org.eclipse.text;bundle-version="[3.1.0,4.0.0)",
+ org.eclipse.team.core;bundle-version="[3.1.0,4.0.0)";resolution:=optional
 Eclipse-LazyStart: true
diff --git a/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java b/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
index 2f87ab2..8895815 100644
--- a/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
+++ b/antadapter/org/eclipse/jdt/core/JDTCompilerAdapter.java
@@ -11,10 +11,16 @@
 package org.eclipse.jdt.core;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.tools.ant.BuildException;
@@ -24,10 +30,14 @@
 import org.apache.tools.ant.types.Commandline;
 import org.apache.tools.ant.types.FileSet;
 import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Commandline.Argument;
 import org.apache.tools.ant.util.JavaEnvUtils;
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.antadapter.AntAdapterMessages;
 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;
 
 /**
  * Ant 1.5 compiler adapter for the Eclipse Java compiler. This adapter permits the
@@ -43,9 +53,16 @@
  * @since 2.0
  */
 public class JDTCompilerAdapter extends DefaultCompilerAdapter {
+	private static final char[] SEPARATOR_CHARS = new char[] { '/', '\\' };
+	private static final char[] ADAPTER_PREFIX = "#ADAPTER#".toCharArray(); //$NON-NLS-1$
+	private static final char[] ADAPTER_ENCODING = "ENCODING#".toCharArray(); //$NON-NLS-1$
+	private static final char[] ADAPTER_ACCESS = "ACCESS#".toCharArray(); //$NON-NLS-1$
 	private static String compilerClass = "org.eclipse.jdt.internal.compiler.batch.Main"; //$NON-NLS-1$
 	String logFileName;
 	Map customDefaultOptions;
+	private Map fileEncodings = null;
+	private Map dirEncodings = null;
+	private List accessRules = null;
 	
 	/**
 	 * Performs a compile using the JDT batch compiler
@@ -78,6 +95,14 @@
 	protected Commandline setupJavacCommand() throws BuildException {
 		Commandline cmd = new Commandline();
 		this.customDefaultOptions = new CompilerOptions().getMap();
+		
+		Class javacClass = Javac.class;
+		
+		/*
+		 * Read in the compiler arguments first since we might need to modify
+		 * the classpath if any access rules were specified
+		 */
+		String [] compilerArgs = processCompilerArguments(javacClass);
 
 		/*
 		 * This option is used to never exit at the end of the ant task. 
@@ -115,7 +140,6 @@
         
         // retrieve the method getSourcepath() using reflect
         // This is done to improve the compatibility to ant 1.5
-        Class javacClass = Javac.class;
         Method getSourcepathMethod = null;
         try {
 	        getSourcepathMethod = javacClass.getMethod("getSourcepath", null); //$NON-NLS-1$
@@ -142,7 +166,7 @@
 		 * Set the classpath for the Eclipse compiler.
 		 */
 		cmd.createArgument().setValue("-classpath"); //$NON-NLS-1$
-		cmd.createArgument().setPath(classpath);
+		createClasspathArgument(cmd, classpath);
 
         final String javaVersion = JavaEnvUtils.getJavaVersion();
 		String memoryParameterPrefix = javaVersion.equals(JavaEnvUtils.JAVA_1_1) ? "-J-" : "-J-X";//$NON-NLS-1$//$NON-NLS-2$
@@ -213,26 +237,6 @@
 			this.customDefaultOptions.put(CompilerOptions.OPTION_LineNumberAttribute, CompilerOptions.DO_NOT_GENERATE);
 			this.customDefaultOptions.put(CompilerOptions.OPTION_SourceFileAttribute , CompilerOptions.DO_NOT_GENERATE);
         }
-        
-       // 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(this.attributes, null);
-			} catch (IllegalAccessException e) {
-				// should never happen
-			} catch (InvocationTargetException e) {
-				// should never happen
-			}
-    	}
     	
 		/*
 		 * Handle the nowarn option. If none, then we generate all warnings.
@@ -313,8 +317,11 @@
 				this.customDefaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3);
 			} else if (this.target.equals(CompilerOptions.VERSION_1_4)) {
 				this.customDefaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
-			} else if (this.target.equals(CompilerOptions.VERSION_1_5)) {
+			} else if (this.target.equals(CompilerOptions.VERSION_1_5)
+					|| this.target.equals("5.0") //$NON-NLS-1$
+					|| this.target.equals("5")) { //$NON-NLS-1$
 				this.customDefaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
+				this.target = CompilerOptions.VERSION_1_5;
 			} else {
 	            this.attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.unknownTarget", this.target), Project.MSG_WARN); //$NON-NLS-1$
 			}
@@ -331,8 +338,11 @@
 				this.customDefaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
 			} else if (source.equals(CompilerOptions.VERSION_1_4)) {
 				this.customDefaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
-			} else if (source.equals(CompilerOptions.VERSION_1_5)) {
+			} else if (source.equals(CompilerOptions.VERSION_1_5)
+					|| source.equals("5.0") //$NON-NLS-1$
+					|| source.equals("5")) { //$NON-NLS-1$
 				this.customDefaultOptions.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
+				source = CompilerOptions.VERSION_1_5;
 			} else {
 	            this.attributes.log(AntAdapterMessages.getString("ant.jdtadapter.info.unknownSource", source), Project.MSG_WARN); //$NON-NLS-1$
 			}
@@ -401,6 +411,219 @@
         return cmd;
 	}
 	
+	/**
+	 * Get the compiler arguments
+	 * @param javacClass
+	 * @return String[] the array of arguments
+	 */
+	private String[] processCompilerArguments(Class javacClass) {
+		// 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(this.attributes, null);
+			} catch (IllegalAccessException e) {
+				// should never happen
+			} catch (InvocationTargetException e) {
+				// should never happen
+			}
+		}
+		//check the compiler arguments for anything requiring extra processing
+		if (compilerArgs != null) checkCompilerArgs(compilerArgs);
+		return compilerArgs;
+	}
+	/**
+	 * check the compiler arguments.
+	 * Extract from files specified using @, lines marked with ADAPTER_PREFIX
+	 * These lines specify information that needs to be interpreted by us.
+	 * @param args compiler arguments to process
+	 */
+	private void checkCompilerArgs(String[] args) {
+		for (int i = 0; i < args.length; i++) {
+			if (args[i].charAt(0) == '@') {
+				try {
+					char[] content = Util.getFileCharContent(new File(args[i].substring(1)), null);
+					int offset = 0;
+					int prefixLength = ADAPTER_PREFIX.length;
+					while ((offset = CharOperation.indexOf(ADAPTER_PREFIX, content, true, offset)) > -1) {
+						int start = offset + prefixLength;
+						int end = CharOperation.indexOf('\n', content, start);
+						if (end == -1)
+							end = content.length;
+						while (CharOperation.isWhitespace(content[end])) {
+							end--;
+						}
+						
+						// end is inclusive, but in the API end is exclusive 
+						if (CharOperation.equals(ADAPTER_ENCODING, content, start, start + ADAPTER_ENCODING.length)) {
+							CharOperation.replace(content, SEPARATOR_CHARS, File.separatorChar, start, end + 1);
+							// file or folder level custom encoding
+							start += ADAPTER_ENCODING.length;
+							int encodeStart = CharOperation.lastIndexOf('[', content, start, end);
+							if (start < encodeStart && encodeStart < end) {
+								boolean isFile = CharOperation.equals(SuffixConstants.SUFFIX_java, content, encodeStart - 5, encodeStart, false);
+
+								String str = String.valueOf(content, start, encodeStart - start);
+								String enc = String.valueOf(content, encodeStart, end - encodeStart + 1);
+								if (isFile) {
+									if (fileEncodings == null)
+										fileEncodings = new HashMap();
+									//use File to translate the string into a path with the correct File.seperator
+									fileEncodings.put(str, enc);
+								} else {
+									if (dirEncodings == null)
+										dirEncodings = new HashMap();
+									dirEncodings.put(str, enc);
+								}
+							}
+						} else if (CharOperation.equals(ADAPTER_ACCESS, content, start, start + ADAPTER_ACCESS.length)) {
+							// access rules for the classpath
+							start += ADAPTER_ACCESS.length;
+							int accessStart = CharOperation.indexOf('[', content, start, end);
+							CharOperation.replace(content, SEPARATOR_CHARS, File.separatorChar, start, accessStart);
+							if (start < accessStart && accessStart < end) {
+								String path = String.valueOf(content, start, accessStart - start);
+								String access = String.valueOf(content, accessStart, end - accessStart + 1);
+								if (accessRules == null)
+									accessRules = new ArrayList();
+								accessRules.add(path);
+								accessRules.add(access);
+							}
+						}
+						offset = end;
+					}
+				} catch (IOException e) {
+					//ignore
+				}
+			}
+		}
+
+	}
+	
+	/**
+	 * Copy the classpath to the command line with access rules included.
+	 * @param cmd the given command line
+	 * @param classpath the given classpath entry
+	 */
+	private void createClasspathArgument(Commandline cmd, Path classpath) {
+		Argument arg = cmd.createArgument();
+		final String[] pathElements = classpath.list();
+
+		// empty path return empty string
+		if (pathElements.length == 0) {
+			arg.setValue(""); //$NON-NLS-1$
+			return;
+		}
+
+		// no access rules, can set the path directly
+		if (accessRules == null) {
+			arg.setPath(classpath);
+			return;
+		}
+
+		int rulesLength = accessRules.size();
+		String[] rules = (String[]) accessRules.toArray(new String[rulesLength]);
+		int nextRule = 0;
+		final StringBuffer result = new StringBuffer();
+
+		//access rules are expected in the same order as the classpath, but there could
+		//be elements in the classpath not in the access rules or access rules not in the classpath
+		for (int i = 0; i < pathElements.length; i++) {
+			if (i > 0)
+				result.append(File.pathSeparatorChar);
+			result.append(pathElements[i]);
+			//the rules list is [path, rule, path, rule, ...]
+			for (int j = nextRule; j < rulesLength; j += 2) {
+				if (pathElements[i].endsWith(rules[j])) {
+					result.append(rules[j + 1]);
+					nextRule = j + 2;
+					break;
+				}
+			}
+		}
+
+		arg.setValue(result.toString());
+	}
+	/**
+	 * Modified from base class, Logs the compilation parameters, adds the files 
+	 * to compile and logs the &quot;niceSourceList&quot;
+	 * Appends encoding information at the end of arguments
+	 * 
+	 * @param cmd the given command line
+	 */
+	protected void logAndAddFilesToCompile(Commandline cmd) {
+		attributes.log("Compilation " + cmd.describeArguments(), //$NON-NLS-1$
+				Project.MSG_VERBOSE);
+
+		StringBuffer niceSourceList = new StringBuffer("File"); //$NON-NLS-1$
+		if (compileList.length != 1) {
+			niceSourceList.append("s"); //$NON-NLS-1$
+		}
+		niceSourceList.append(" to be compiled:"); //$NON-NLS-1$
+		niceSourceList.append(lSep);
+
+		String[] encodedFiles = null, encodedDirs = null;
+		int encodedFilesLength = 0, encodedDirsLength = 0;
+		if (fileEncodings != null) {
+			encodedFilesLength = fileEncodings.size();
+			encodedFiles = new String[encodedFilesLength];
+			fileEncodings.keySet().toArray(encodedFiles);
+		}
+		if (dirEncodings != null) {
+			encodedDirsLength = dirEncodings.size();
+			encodedDirs = new String[encodedDirsLength];
+			dirEncodings.keySet().toArray(encodedDirs);
+			//we need the directories sorted, longest first,since sub directories can
+			//override encodings for their parent directories
+			Comparator comparator = new Comparator() {
+				public int compare(Object o1, Object o2) {
+					return ((String) o2).length() - ((String) o1).length();
+				}
+			};
+			Arrays.sort(encodedDirs, comparator);
+		}
+
+		for (int i = 0; i < compileList.length; i++) {
+			String arg = compileList[i].getAbsolutePath();
+			boolean encoded = false;
+			if (encodedFiles != null) {
+				//check for file level custom encoding
+				for (int j = 0; j < encodedFilesLength; j++) {
+					if (arg.endsWith(encodedFiles[j])) {
+						//found encoding, remove it from the list to speed things up next time around
+						arg = arg + (String) fileEncodings.get(encodedFiles[j]);
+						if (j < encodedFilesLength - 1) {
+							System.arraycopy(encodedFiles, j + 1, encodedFiles, j, encodedFilesLength - j - 1);
+						}
+						encodedFiles[--encodedFilesLength] = null;
+						encoded = true;
+						break;
+					}
+				}
+			}
+			if (!encoded && encodedDirs != null) {
+				//check folder level custom encoding
+				for (int j = 0; j < encodedDirsLength; j++) {
+					if (arg.lastIndexOf(encodedDirs[j]) != -1) {
+						arg = arg + (String) dirEncodings.get(encodedDirs[j]);
+						break;
+					}
+				}
+			}
+			cmd.createArgument().setValue(arg);
+			niceSourceList.append("    " + arg + lSep); //$NON-NLS-1$
+		}
+
+		attributes.log(niceSourceList.toString(), Project.MSG_VERBOSE);
+	}
     /**
      * Emulation of extdirs feature in java >= 1.2.
      * This method adds all files in the given
diff --git a/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java b/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
index a0219b7..b9f872e 100644
--- a/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
+++ b/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathLocation.java
@@ -10,6 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.batch;
 
+import java.io.File;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
@@ -29,16 +32,21 @@
 	 * 
 	 * @param qualifiedBinaryFileName
 	 *            tested type specification, formed as:
-	 *            "org/eclipse/jdt/core/JavaCore.class"
+	 *            "org/eclipse/jdt/core/JavaCore.class"; on systems that
+	 *            use \ as File.separator, the 
+	 *            "org\eclipse\jdt\core\JavaCore.class" is accepted as well
 	 * @return the first access rule which is violated when accessing a given
 	 *         type, or null if none applies
 	 */
 	AccessRestriction fetchAccessRestriction(String qualifiedBinaryFileName) {
 		if (this.accessRuleSet == null)
 			return null;
-		return this.accessRuleSet
-					.getViolatedRestriction(
-						qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SUFFIX_CLASS.length)
-						.toCharArray());
+		char [] qualifiedTypeName = qualifiedBinaryFileName.
+			substring(0, qualifiedBinaryFileName.length() - SUFFIX_CLASS.length)
+			.toCharArray(); 
+		if (File.separatorChar == '\\') {
+			CharOperation.replace(qualifiedTypeName, File.separatorChar, '/');
+		}
+		return this.accessRuleSet.getViolatedRestriction(qualifiedTypeName);
 	}
 }
diff --git a/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index 1c67335..53cf393 100644
--- a/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -1982,22 +1982,31 @@
 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3);
 				} else if (currentArg.equals("1.4")) { //$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_4) {
-						throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
+					if (didSpecifyCompliance) {
+						if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_4) {
+							throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
+						}
+					} else {
+						this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
 					}
-					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
 				} else if (currentArg.equals("1.5") || currentArg.equals("5") || currentArg.equals("5.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
-					if (didSpecifyCompliance && CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_5) {
-						throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
+					if (didSpecifyCompliance) {
+						if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_5) {
+							throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
+						}
+					} else {
+						this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
 					}
-					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
 				} else if (currentArg.equals("1.6") || currentArg.equals("6") || currentArg.equals("6.0")) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
 					this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
-					if (didSpecifyCompliance && CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_6) {
-						throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
+					if (didSpecifyCompliance) {
+						if (CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) < ClassFileConstants.JDK1_6) {
+							throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget", (String)this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
+						}
+					} else {
+						this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
 					}
-					this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
 				} else {
 					throw new InvalidInputException(Main.bind("configure.targetJDK", currentArg)); //$NON-NLS-1$
 				}
@@ -2106,6 +2115,7 @@
 						case readyToCloseOrOtherEntry:
 							state = readyToCloseOrOtherEntry;
 							addNewEntry(InsideClasspath, InsideSourcepath, bootclasspaths, classpaths, sourcepathClasspaths, currentClasspathName, currentRuleSpecs, mode, customEncoding);
+							currentRuleSpecs.clear();
 							break;
 						case rulesReadyToClose:
 							state = rulesNeedAnotherRule;
diff --git a/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties b/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
index b98a293..4af16a7 100644
--- a/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
+++ b/batch/org/eclipse/jdt/internal/compiler/batch/messages.properties
@@ -14,7 +14,7 @@
 #Format: compiler.name = word1 word2 word3
 compiler.name = Eclipse Java Compiler
 #Format: compiler.version = 0.XXX[, other words (don't forget the comma if adding other words)]
-compiler.version = 0.619_APT, pre-3.2.0 milestone-3
+compiler.version = 0.631_APT, 3.2.0 milestone-4
 compiler.copyright = Copyright IBM Corp 2000, 2005. All rights reserved.
 
 ### scanning
diff --git a/buildnotes_jdt-core.html b/buildnotes_jdt-core.html
index 8d116d9..f94ce8b 100644
--- a/buildnotes_jdt-core.html
+++ b/buildnotes_jdt-core.html
@@ -13,7 +13,7 @@
       <font size="+3"><b>jdt core - build notes 3.2 stream</b></font>
     </td>
   </tr>
-  <tr><td td align="left" width="72%" class="title2"><font size="-2">java development tooling core</font></td></tr>
+  <tr><td align="left" width="72%" class="title2"><font size="-2">java development tooling core</font></td></tr>
   <tr><td>&nbsp;</td></tr>
   <tr>
   	<td class="title3">
@@ -42,13 +42,13 @@
   </tr>
 </table>
 
-<a name="v_548_APT_merged_with_v_619_R3_2_MILESTONE_3"></a>
+<a name="v_548_APT_merged_with_v_631_R3_2_MILESTONE_4"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes&nbsp;<br>
 Java Development Tooling Core</h1>
-Eclipse SDK 3.2M3 + APT - 2nd November 2005
-<br>Project org.eclipse.jdt.core v_548_APT_merged_with_v_619_R3_2_MILESTONE_3
-(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_548_APT_merged_with_v_619_R3_2_MILESTONE_3">cvs</a>).
+Eclipse SDK 3.2M4 + APT - 16th December 2005
+<br>Project org.eclipse.jdt.core v_548_APT_merged_with_v_631_R3_2_MILESTONE_4
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_548_APT_merged_with_v_631_R3_2_MILESTONE_4">cvs</a>).
 <h2>
 What's new in this drop</h2>
 <ul>
@@ -57,6 +57,747 @@
 <h3>Problem Reports Fixed</h3>
 
 
+<a name="v_631"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 14th December 2005
+<br>Project org.eclipse.jdt.core v_631 - 3.2 MILESTONE 4
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_631">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=120902">120902</a>
+Member.getJavadocRange() causes AIOOBE
+
+
+<a name="v_630"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 14th December 2005
+<br>Project org.eclipse.jdt.core v_630
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_630">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=120847">120847</a>
+[javadoc] AIOOBE while getting attached javadoc in Javadoc view
+
+<a name="v_629"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 13th December 2005
+<br>Project org.eclipse.jdt.core v_629
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_629">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>The constant <code>JavaCore.CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC</code> has been deprecated and it will be removed
+after M4. Use <code>JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC</code> instead.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=120640">120640</a>
+[javadoc] Open External Javadoc fails for nested binary types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=120597">120597</a>
+JME extracting Javadoc for public fields from 1.5 doc
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=120637">120637</a>
+javadoc extraction: includes field title for Java 5 classes
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=120559">120559</a>
+Getting Javadoc from attached Javadoc gives JavaModelException
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=120545">120545</a>
+Misleading constant: CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=120522">120522</a>
+[assist] No proposal in @Target annotation attributes
+
+<a name="v_628"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 12th December 2005
+<br>Project org.eclipse.jdt.core v_628
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_628">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=120350">120350</a>
+[model] Secondary type not found by code resolve
+
+<a name="v_627"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 9th December 2005
+<br>Project org.eclipse.jdt.core v_627
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_627">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Change the default value of JavaCore#CODEASSIST_CAMEL_CASE_MATCH to "enabled" as
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114098">bug 114098</a> is fixed.</li>
+<li>Added support for EFS on non zip file. Support for zip and jar files is blocked by 
+     <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=119244">bug 119244</a></li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=120092">120092</a>
+[search] Java like extensions functionality causes performance issue for search engine
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117740">117740</a>
+Parameter names completion should be done asynchronoulsy
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110422">110422</a>
+[search] BasicSearchEngine doesn't find all type declarations
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110291">110291</a>
+[search] BasicSearchEngine return constructor declarations that doesn't exist in source
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=83064">83064</a>
+[plan][1.5] Unidentical bindings for declaration of and reference to Class.MethodArray
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=119545">119545</a>
+[search] Binary java method model elements returned by SearchEngine have unresolved parameter types
+
+<a name="v_626"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 6th December 2005
+<br>Project org.eclipse.jdt.core v_626
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_626">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=119430">119430</a>
+Potential performance problem in getViolatedRestriction()
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=113944">113944</a>
+[plan] Support for refactoring of JAR files
+
+<a name="v_625"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 6th December 2005
+<br>Project org.eclipse.jdt.core v_625
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_625">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added API methods on IJavaProject to find secondary types while searching for type
+on a project (see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118789">118789</a>):
+<pre>
+	/**
+	 * Same functionality as {@link #findType(String)} but also look for secondary
+	 * types if given name does not match a compilation unit name.
+	 * 
+	 * @param fullyQualifiedName the given fully qualified name
+	 * @param progressMonitor the progress monitor to report progress to,
+	 * 	or <code>null</code> if no progress monitor is provided
+	 * @exception JavaModelException if this project 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.2
+	 */
+	IType findType(String fullyQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException;
+	/**
+	 * Same functionality as {@link #findType(String, WorkingCopyOwner)}
+	 * but also look for secondary types if given name does not match
+	 * a compilation unit name.
+	 * 
+	 * @param fullyQualifiedName the given fully qualified name
+	 * @param owner the owner of the returned type's compilation unit
+	 * @param progressMonitor the progress monitor to report progress to,
+	 * 	or <code>null</code> if no progress monitor is provided
+	 * @exception JavaModelException if this project 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.2
+	 */
+	IType findType(String fullyQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException;
+	/**
+	 * Same functionality as {@link #findType(String, String)} but also look for
+	 * secondary types if given name does not match a compilation unit name.
+	 * 
+	 * @param packageName the given package name
+	 * @param typeQualifiedName the given type qualified name
+	 * @param progressMonitor the progress monitor to report progress to,
+	 * 	or <code>null</code> if no progress monitor is provided
+	 * @exception JavaModelException if this project 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.2
+	 */
+	IType findType(String packageName, String typeQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException;
+	/**
+	 * Same functionality as {@link #findType(String, String, WorkingCopyOwner)}
+	 * but also look for secondary types if given name does not match a compilation unit name.
+	 * 
+	 * @param packageName the given package name
+	 * @param typeQualifiedName the given type qualified name
+	 * @param owner the owner of the returned type's compilation unit
+	 * @param progressMonitor the progress monitor to report progress to,
+	 * 	or <code>null</code> if no progress monitor is provided
+	 * @exception JavaModelException if this project 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.2
+	 */
+	IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException;
+</pre>
+Note that previously existing find type API methods:
+<ul>
+<li><code>IJavaproject#findType(String)</code></li>
+<li><code>IJavaproject#findType(String, WorkingCopyOwner)</code></li>
+<li><code>IJavaproject#findType(String, String)</code></li>
+<li><code>IJavaproject#findType(String, String, WorkingCopyOwner)</code></li>
+</ul>
+will <b>not</b> find secondary types (same behavior than for 3.1 version).<br>
+This means that fix for bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36032">36032</a>
+was slightly modified as it introduced an non-deterministic behavior of these API methods
+(see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118789">118789</a> for the whole story...).
+</li>
+<li>Added API <code>SearchParticipant#removeIndex(IPath)</code> to remove both index file
+    from a given location and its corresponding Index in IndexManager cache.
+</li>
+<li>Added API <code>IJavaProject#setRawClasspath(IClasspathEntry[], IPath, boolean, IProgressMonitor)</code>
+     to change the output location as well as the classpath without touching resources.</li>
+<li>Added constant constant JavaCore#JAVA_SOURCE_CONTENT_TYPE to retrieve the Java source content type from 
+     the content type manager (see org.eclipse.core.runtime.content.IContentTypeManager#getContentType(String))</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=119108">119108</a>
+Access Rules and Path separators
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=119203">119203</a>
+[search] references to method gives many inaccurate matches in Plug-in Dependencies
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110593">110593</a>
+[1.5][compiler] NPE in ProblemReporter
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=115693">115693</a>
+[1.5][compiler] Unnecessary double checkcast instruction emmited
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118789">118789</a>
+IJavaProject#findType(String) returns null for secondary type quickly after creation
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118876">118876</a>
+[dom] TypeDeclaration nodes aren't flagged as MALFORMED
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=105592">105592</a>
+Enum switch statement compile error
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118888">118888</a>
+Need an entry point to create a org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader using a stream
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118092">118092</a>
+Eclipse hangs on code assist when writing ?&lt;c
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=116650">116650</a>
+[search] SearchParticipant has no way to remove specific index file from IndexManager cache
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118798">118798</a>
+Unexpected JME on IMethod.getParameterNames
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114571">114571</a>
+concurrent access to HashMap
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=71460">71460</a>
+[model] Non *.java file association with Java contents.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118397">118397</a>
+[javadoc][assist] No completion available while completing inside a qualified reference
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118393">118393</a>
+ICompilationUnit.findPrimaryType: Should use JavaCore.removeJavaLikeExtension
+
+<a name="v_624"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 29th November 2005
+<br>Project org.eclipse.jdt.core v_624
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_624">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added API <code>IJavaProject#setRawClasspath(IClasspathEntry[], boolean, IProgressMonitor)</code> 
+     to set the classpath without touching the .classpath file.</li>
+<li>Added API <code>org.eclipse.jdt.core.compiler.CharOperation#equals(char[], char[], int, int, boolean)</code>.</li>
+<li>Added API <code>org.eclipse.jdt.core.compiler.CharOperation#replace(char[], char[], char, int, int)</code>.</li>
+<li>Plugin version now respects new versionning requirements. See <a href="http://eclipse.org/equinox/documents/plugin-versioning.html">plugin versioning</a> and bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=99393">99393</a>.</li>
+<li>Fix for <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36032">bug 36032</a> required the index version to be incremented. 
+     Indexes will be automatically regenerated upon subsequent search queries (accounting for indexing notification in search progress dialogs).
+</li>
+<li>Added API <code>IMember#getOccurrenceCount()</code> to return the relative position of the member in the source.</li>
+<li>Added API <code>WorkingCopyOwner#newWorkingCopy(String,IProgressMonitor)</code> to create a new working copy 
+     without an underlying resource.</li>
+<li>Added API on TypeReferenceMatch to report local element and other elements while
+searching for type references (see bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110336">110336</a>):
+<pre>
+	/**
+	 * Returns the local element of this search match.
+	 * This may be a local variable which declaring type is the referenced one
+	 * or a type parameter which extends it.
+	 * 
+	 * @return the element of the search match, or <code>null</code> if none or there's
+	 * 	no more specific local element than the element itself ({@link SearchMatch#getElement()}).
+	 */
+	public final IJavaElement getLocalElement()
+	/**
+	 * Returns other enclosing elements of this search match.
+	 *
+	 * If {@link #getLocalElement()} is not <code>null</code>, these may be other
+	 * local elements such as additional local variables of a multiple local
+	 * variables declaration. Otherwise, these may be other elements such as
+	 * additional fields of a multiple fields declaration.
+	 * 
+	 * @return the other elements of the search match, or <code>null</code> if none
+	 */
+	public final IJavaElement[] getOtherElements()
+	/**
+	 * Sets the local element of this search match.
+	 * 
+	 * @param localElement A more specific local element that corresponds to the match,
+	 * 	or <code>null</code> if none
+	 */
+	public final void setLocalElement(IJavaElement localElement)
+	/**
+	 * Sets the other elements of this search match.
+	 * 
+	 * @param otherElements the other elements of the match,
+	 * 	or <code>null</code> if none
+	 */
+	public final void setOtherElements(IJavaElement[] otherElements)
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118246">118246</a>
+Definition of getJavaLikeExtensions() leads to programming errors
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118311">118311</a>
+type \@ in javadoc comment and code assist == hang
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117020">117020</a>
+[search] Search for '*' does not report empty packages
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=111416">111416</a>
+[search] wrong potential matches on a static method open
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118214">118214</a>
+[completion] "has inconsistent hierarchy" field should not be proposed
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118105">118105</a>
+[javadoc][assist] Hang with 100% CPU during code assist on comment
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=118064">118064</a>
+Access rules are not flushed between classpaths in batch mode.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117451">117451</a>
+[compiler] Codegen could better optimize field access when value not required
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117120">117120</a>
+[compiler] VerifyError: Expecting to find integer on stack
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=36032">36032</a>
+[plan] JavaProject.findType() fails to find second type in source file
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117183">117183</a>
+[javadoc][assist] No completion in text when cursor location is followed by a '.'
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=116573">116573</a>
+wrong guess of binding with overloaded methods
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117861">117861</a>
+[1.5][compiler] invalid handling of static import
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110336">110336</a>
+[plan][search] Should optionaly return the local variable for type reference
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117890">117890</a>
+JavaElement.getURLContents(...) leaves file open
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117589">117589</a>
+Completion dialog shows html file name
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=115040">115040</a>
+Provide API for getting occurrence count from initializers and types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117121">117121</a>
+Can't create class called A$B in eclipse
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=116858">116858</a>
+java code formatter problem with switch statements and comments
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117495">117495</a>
+Compiler: ternary ops return wrong type when condition is boolean literal
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61013">61013</a>
+[plan][model] Minimal support for editing units outside workspace
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117487">117487</a>
+Classpaths in the build scripts need to be updated
+
+<a name="v_623"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 22nd November 2005
+<br>Project org.eclipse.jdt.core v_623
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_623">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li><code>JavaCore#initializeAfterLoad(IProgressMonitor)</code> used to schedule a job to do its work. 
+      It now does it in the same thread. Note this is not an API change as the spec allows both scenarii.
+</li>
+<li> DOM type bindings for generics got adjusted. There were situations where a reference to a generic type from within itself would expose the declared 
+generic type binding, instead of a parameterized type binding (using its own type parameters as type arguments). This is now corrected, clients should 
+ensure they did not rely on the previous inconsistency (note: no change was required from direct JDT dependents).
+</li>
+<li>Added APIs <code>JavaCore#getJavaLikeExtensions(), isJavaLikeFileName(String), and removeJavaLikeExtension(String)</code>
+     to get the available Java-like extensions (from the Java source content-type), checking if a file is a Java-like file, and removing
+     the Java-like extension from a file name.
+</li>
+<li>Added new API for org.eclipse.jdt.core.dom.CompilationUnit:
+<pre>
+	/**
+	 * Returns the column number corresponding to the given source character
+	 * position in the original source string. Column number are zero-based. 
+	 * Return <code>-1</code> if it is beyond the valid range or <code>-2</code>
+	 * if the column number information is unknown.
+	 * 
+	 * @param position a 0-based character position, possibly
+	 *   negative or out of range
+	 * @return the 0-based column number, or <code>-1</code> if the character
+	 *    position does not correspond to a source line in the original
+	 *    source file or <code>-2</code> if column number information is unknown for this
+	 *    compilation unit
+	 * @see ASTParser
+	 * @since 3.2
+	 */
+	public int getColumnNumber(final int position)
+	/**
+	 * Given a line number and column number, returns the corresponding 
+	 * position in the original source string.
+	 * Returns -2 if no line number information is available for this
+	 * compilation unit. 
+	 * Returns the total size of the source string if <code>line</code>
+	 * is greater than the actual number lines in the unit.
+	 * Returns -1 if <code>column</code> is less than 0,  
+	 * or the position of the last character of the line if <code>column</code>
+	 * is beyond the legal range, or the given line number is less than one. 
+	 * 
+	 * @param line the one-based line number
+	 * @param column the zero-based column number
+	 * @return the 0-based character position in the source string; 
+	 * <code>-2</code> if line/column number information is not known 
+	 * for this compilation unit or <code>-1</code> the inputs are not valid
+	 * @since 3.2
+	 */
+	 public int getPosition(int line, int column)
+	/**
+	 * Returns the line number corresponding to the given source character
+	 * position in the original source string. The initial line of the 
+	 * compilation unit is numbered 1, and each line extends through the
+	 * last character of the end-of-line delimiter. The very last line extends
+	 * through the end of the source string and has no line delimiter.
+	 * For example, the source string <code>class A\n{\n}</code> has 3 lines
+	 * corresponding to inclusive character ranges [0,7], [8,9], and [10,10].
+	 * Returns -1 for a character position that does not correspond to any
+	 * source line, or -2 if no line number information is available for this
+	 * compilation unit.
+	 * 
+	 * @param position a 0-based character position, possibly
+	 *   negative or out of range
+	 * @return the 1-based line number, or <code>-1</code> if the character
+	 *    position does not correspond to a source line in the original
+	 *    source file or <code>-2</code> if line number information is not known for this
+	 *    compilation unit
+	 * @see ASTParser
+	 * @since 3.2
+	 */
+	public int getLineNumber(int position) 	
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117382">117382</a>
+synthetic class$N fields generated unnecessarily
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=115658">115658</a>
+ReconcileContext/CompilationParticipant clarifications
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=61946">61946</a>
+AST: NPE in IVariableBinding.getConstantValue
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=116472">116472</a>
+Ambigous API definition on CompilationUnit.getPosition()
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=117032">117032</a>
+AST line numbers: Problems with single line source
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=116745">116745</a>
+[compiler] VerifyError: Incompatible type for getting or setting field
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=98154">98154</a>
+Code assist from Javadoc
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=116464">116464</a>
+[javadoc] Unicode tag name are not correctly parsed
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114941">114941</a>
+Remove init job
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114935">114935</a>
+ASTParser.createASTs parses more CUs then required
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=116311">116311</a>
+[search] NPE searching for reference to our Assert class
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=115067">115067</a>
+Util#getJavaLikeExtensions should become API
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=80472">80472</a>
+Binding of parameterized return type List&lt;E&gt; subList(...) should not be generic binding
+
+
+<a name="v_622"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 16th November 2005
+<br>Project org.eclipse.jdt.core v_622
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_622">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added API <code>IMethod#getRawParameterNames()</code> that returns the invented names arg0...argn for a binary method.</li>
+<li>Added API <code>IOpenable#findRecommendedLineSeparator()</code> that finds the line separator for the given Java element.</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=116419">116419</a>
+code assist regression: POTENTIAL_METHOD_DECLARATION not offered anymore
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=84750">84750</a>
+[perf] BinaryMethod.getParameterNames does not follow IMethod API contract
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110650">110650</a>
+Need API for determining Java line delimiter
+
+<a name="v_621"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 15th November 2005
+<br>Project org.eclipse.jdt.core v_621
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_621">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>
+Due to bug <a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110964">110964</a> fix,
+some javadoc compiler options default value have been changed.
+<pre>
+JavaCore.COMPILER_PB_INVALID_JAVADOC_TAGS:
+	- old default value = "enabled"
+	- new default value = "disabled"
+JavaCore.COMPILER_PB_INVALID_JAVADOC_TAGS__DEPRECATED_REF
+	- old default value = "enabled"
+	- new default value = "disabled"
+JavaCore.COMPILER_PB_INVALID_JAVADOC_TAGS__NOT_VISIBLE_REF
+	- old default value = "enabled"
+	- new default value = "disabled"
+JavaCore.COMPILER_PB_INVALID_JAVADOC_TAGS_VISIBILITY
+	- old default value = "private"
+	- new default value = "public"
+JavaCore.COMPILER_PB_MISSING_JAVADOC_TAGS_VISIBILITY
+	- old default value = "private"
+	- new default value = "public"
+</pre>
+</li>
+<li>Added new API for org.eclipse.jdt.core.dom.CompilationUnit:
+<pre>
+	/**
+	 * Return the index in the whole comments list {@link #getCommentList() }
+	 * of the first leading comments associated with the given node. 
+	 * 
+	 * @param node the node
+	 * @return 0-based index of first leading comment or -1 if node has
+	 *	no associated comment before its start position.
+	 * @since 3.2
+	 */
+	public int firstLeadingCommentIndex(ASTNode node)
+	/**
+	 * Return the index in the whole comments list {@link #getCommentList() }
+	 * of the last trailing comments associated with the given node. 
+	 * 
+	 * @param node the node
+	 * @return 0-based index of last trailing comment or -1 if node has
+	 * 	no associated comment after its end position.
+	 * @since 3.2
+	 */
+	public int lastTrailingCommentIndex(ASTNode node)
+	/**
+	 * Returns the column number corresponding to the given source character
+	 * position in the original source string. Column number are zero-based. 
+	 * Return zero if it is beyond the valid range.
+	 * 
+	 * @param position a 0-based character position, possibly
+	 *   negative or out of range
+	 * @return the 0-based coloumn number, or <code>0</code> if the character
+	 *    position does not correspond to a source line in the original
+	 *    source file or if column number information is not known for this
+	 *    compilation unit
+	 * @see ASTParser
+	 * @since 3.2
+	 */
+	public int columnNumber(final int position)
+	/**
+	 * Given a line number and column number, returns the corresponding 
+	 * position in the original source string.
+	 * Returns 0 if no line number information is available for this
+	 * compilation unit or the requested line number is less than one. 
+	 * Returns the total size of the source string if <code>line</code>
+	 * is greater than the actual number lines in the unit.
+	 * Returns 0 if <code>column</code> is less than 0,  
+	 * or the position of the last character of the line if <code>column</code>
+	 * is beyond the legal range. 
+	 * 
+	 * @param line the one-based line number
+	 * @param column the zero-based column number
+	 * @return the 0-based character position in the source string; 
+	 * returns <code>0</code> if line/column number information is not known 
+	 * for this compilation unit or the inputs are not valid
+	 * @since 3.2
+	 */
+	 public int getPosition(int line, int column)
+</pre>
+</li>
+<li>A tool to automate the update of the build notes is available on this update-site:<br>
+http://www.eclipse.org/jdt/core/tools/jdtcoretools/update-site/<br>
+<p>This is matching the format of the JDT/Core buildnotes. But the code can be easily customized for a different format.</p>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=115662">115662</a>
+[javadoc][assist] link completion in types
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=106140">106140</a>
+[compiler] Eclipse3.1.0: unrecognized class invisibility
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=113108">113108</a>
+[API][comments] CompilationUnit.getNodeComments(ASTNode)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110964">110964</a>
+[javadoc] Change compiler default options to have minimum javadoc warnings
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=116028">116028</a>
+annotations only applied to first field in a declaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=112843">112843</a>
+Cut blocked by background build
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=116028">116028</a>
+annotations only applied to first field in a declaration
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110797">110797</a>
+In case of multiple task tags on a single line, the tasks view does not show the complete line for each tag
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110173">110173</a>
+[plan] API to extract the Javadoc as HTML from attached HTML
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110188">110188</a>
+[plan][assist] Provide hook for completing inside string literal
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=107105">107105</a>
+[1.5][compiler] method override check does not detect differences in additional type bounds
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=115408">115408</a>
+[compiler] ArrayIndexOutOfBoundsException in CodeStream.java
+	  	
+<a name="v_620"></a>
+<p><hr><h1>
+Eclipse Platform Build Notes<br>
+Java Development Tooling Core</h1>
+Eclipse SDK 3.2M4 - 8th November 2005
+<br>Project org.eclipse.jdt.core v_620
+(<a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jdt.core/?only_with_tag=v_620">cvs</a>).
+<h2>
+What's new in this drop</h2>
+<ul>
+<li>Added support for participating in reconcile (see <code>compilationParticipant</code> extension point as well as 
+     <code>CompilationParticipant</code> and <code>ReconcileContext</code> classes.)
+     Note that this support is still work in progress and it is subject to change.
+     Ability to participate in building will be added later.
+</li>
+<li>Code Assist: added support for completing on label in break/continue statement.
+</li>
+<li>Added new CompletionContext API (first part of fix for bug
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=110181">110181</a>) :
+<pre>
+/**
+ * Returns the completed token.
+ * This token is either the identifier or Java language keyword
+ * or the string literal under, immediately preceding, 
+ * the original request offset. If the original request offset
+ * is not within or immediately after an identifier or keyword or
+ * a string literal then the returned value is &lt;code&gt;null&lt;/code&gt;.
+ * 
+ * @return completed token or &lt;code&gt;null&lt;/code&gt;
+ * @since 3.2
+ */
+public char[] getToken()
+
+/**
+ * Returns the kind of completion token being proposed.
+ * 
+ * The set of different kinds of completion token is
+ * expected to change over time. It is strongly recommended
+ * that clients do not assume that the kind is one of the
+ * ones they know about, and code defensively for the
+ * possibility of unexpected future growth.
+ * 
+ * @return the kind; one of the kind constants declared on
+ * this class whose name starts with &lt;code&gt;TOKEN_KIND&lt;/code&gt;,
+ * or possibly a kind unknown to the caller
+ * @since 3.2
+ */
+public int getTokenKind()
+
+/**
+ * Returns the character index of the start of the
+ * subrange in the source file buffer containing the
+ * relevant token being completed. This
+ * token is either the identifier or Java language keyword
+ * under, or immediately preceding, the original request 
+ * offset. If the original request offset is not within
+ * or immediately after an identifier or keyword, then the
+ * position returned is original request offset and the
+ * token range is empty.
+ * 
+ * @return character index of token start position (inclusive)
+ * @since 3.2
+ */
+public int getTokenStart()
+
+/**
+ * Returns the character index of the end (exclusive) of the subrange
+ * in the source file buffer containing the
+ * relevant token. When there is no relevant token, the
+ * range is empty
+ * (&lt;code&gt;getTokenEnd() == getTokenStart()&lt;/code&gt;).
+ * 
+ * @return character index of token end position (exclusive)
+ * @since 3.2
+ */
+public int getTokenEnd()
+
+/**
+ * Returns the offset position in the source file buffer
+ * after which code assist is requested.
+ * 
+ * @return offset position in the source file buffer
+ * @since 3.2
+ */
+public int getOffset()
+</pre>
+</li>
+</ul>
+
+<h3>Problem Reports Fixed</h3>
+<a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=115363">115363</a>
+java.lang.VerifyError in org.eclipse.ui.workbench from HEAD, using N20051107
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=22072">22072</a>
+Code completion on continue label: broken.
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=113950">113950</a>
+[1.5][compiler] Problems implementing inherited generic abstract methods and type erasure
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=115181">115181</a>
+[1.5][compiler] Wrongly flagged "Usage of a raw type"
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=113945">113945</a>
+No codeassist in anonymous class in generics
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114086">114086</a>
+Refactor->Rename of instance variables fails with "-1" when Code Style->Fields prefix list has dangling ","
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114341">114341</a>
+[javadoc][assist] range of the qualified type completion in javadoc text isn't correct
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114338">114338</a>
+[javadoc] Reconciler reports wrong javadoc warning (missing return type)
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=102286">102286</a>
+Error when trying F4-Type Hierarchy
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114909">114909</a>
+AST: String concatenation represented as single node
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114539">114539</a>
+[search] Internal error when refactoring code with errors
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114855">114855</a>
+[compiler] OutOfMemoryError compiling deeply nested try-catch
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114087">114087</a>
+[1.5][compiler] Eclipse compiles code that cannot be compiled with JDK!
+<br><a href="http://bugs.eclipse.org/bugs/show_bug.cgi?id=114304">114304</a>
+[1.5][compiler] Return type not compatible with generic subinterface.
+
+
 <a name="v_619"></a>
 <p><hr><h1>
 Eclipse Platform Build Notes<br>
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index 92d2a12..707dc33 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -646,7 +646,11 @@
 		}
 	}
 		
-	private void buildContext(ASTNode astNode) {
+	private void buildContext(
+			ASTNode astNode,
+			ASTNode astNodeParent,
+			Binding qualifiedBinding,
+			Scope scope) {
 		CompletionContext context = new CompletionContext();
 		
 		// build expected types context
@@ -662,11 +666,46 @@
 			context.setExpectedTypesKeys(expKeys);
 		}
 		
+		context.setOffset(this.actualCompletionPosition + 1);
+		
 		// Set javadoc info
 		if (astNode instanceof CompletionOnJavadoc) {
 			this.assistNodeInJavadoc = ((CompletionOnJavadoc)astNode).getCompletionFlags();
 			context.setJavadoc(this.assistNodeInJavadoc);
 		}
+		
+		if (!(astNode instanceof CompletionOnJavadoc)) {
+			CompletionScanner scanner = (CompletionScanner)this.parser.scanner;
+			context.setToken(scanner.completionIdentifier);
+			context.setTokenRange(
+					scanner.completedIdentifierStart,
+					scanner.completedIdentifierEnd,
+					scanner.endOfEmptyToken);
+		} else if(astNode instanceof CompletionOnJavadocTag) {
+			CompletionOnJavadocTag javadocTag = (CompletionOnJavadocTag) astNode;
+			context.setToken(CharOperation.concat(new char[]{'@'}, javadocTag.token));
+			context.setTokenRange(
+					javadocTag.tagSourceStart,
+					javadocTag.tagSourceEnd,
+					((CompletionScanner)this.parser.javadocParser.scanner).endOfEmptyToken);
+		} else {
+			CompletionScanner scanner = (CompletionScanner)this.parser.javadocParser.scanner;
+			context.setToken(scanner.completionIdentifier);
+			context.setTokenRange(
+					scanner.completedIdentifierStart,
+					scanner.completedIdentifierEnd,
+					scanner.endOfEmptyToken);
+		}
+		
+		if(astNode instanceof CompletionOnStringLiteral) {
+			context.setTokenKind(CompletionContext.TOKEN_KIND_STRING_LITERAL);
+		} else {
+			context.setTokenKind(CompletionContext.TOKEN_KIND_NAME);
+		}
+		
+		if(DEBUG) {
+			System.out.println(context.toString());
+		}
 		this.requestor.acceptContext(context);
 	}
 	
@@ -680,9 +719,9 @@
 			if(!isValidParent(astNodeParent, astNode, scope)) return false;
 			computeExpectedTypes(astNodeParent, astNode, scope);
 		}
-
-		buildContext(astNode);
-
+		
+		buildContext(astNode, astNodeParent, qualifiedBinding, scope);
+		
 		if (astNode instanceof CompletionOnFieldType) {
 
 			CompletionOnFieldType field = (CompletionOnFieldType) astNode;
@@ -772,12 +811,14 @@
 
 		} else if (astNode instanceof CompletionOnSingleTypeReference) {
 
-			this.completionToken = ((CompletionOnSingleTypeReference) astNode).token;
+			CompletionOnSingleTypeReference singleRef = (CompletionOnSingleTypeReference) astNode;
+			
+			this.completionToken = singleRef.token;
 
-			this.assistNodeIsClass = astNode instanceof CompletionOnClassReference;
-			this.assistNodeIsException = astNode instanceof CompletionOnExceptionReference;
-			this.assistNodeIsInterface = astNode instanceof CompletionOnInterfaceReference;
-			this.assistNodeIsConstructor = ((CompletionOnSingleTypeReference) astNode).isConstructorType;
+			this.assistNodeIsClass = singleRef.isClass();
+			this.assistNodeIsException = singleRef.isException();
+			this.assistNodeIsInterface = singleRef.isInterface();
+			this.assistNodeIsConstructor = singleRef.isConstructorType;
 
 			// can be the start of a qualified type name
 			if (qualifiedBinding == null) {
@@ -905,12 +946,13 @@
 
 			this.insideQualifiedReference = true;
 			
-			this.assistNodeIsClass = astNode instanceof CompletionOnQualifiedClassReference;
-			this.assistNodeIsException = astNode instanceof CompletionOnQualifiedExceptionReference;
-			this.assistNodeIsInterface = astNode instanceof CompletionOnQualifiedInterfaceReference;
-			
 			CompletionOnQualifiedTypeReference ref =
 				(CompletionOnQualifiedTypeReference) astNode;
+			
+			this.assistNodeIsClass = ref.isClass();
+			this.assistNodeIsException = ref.isException();
+			this.assistNodeIsInterface = ref.isInterface();
+			
 			this.completionToken = ref.completionIdentifier;
 			long completionPosition = ref.sourcePositions[ref.tokens.length];
 
@@ -1142,44 +1184,54 @@
 				}
 			}
 		} else if (astNode instanceof CompletionOnMemberValueName) {
-			if (!this.requestor.isIgnored(CompletionProposal.ANNOTATION_ATTRIBUTE_REF)) {
-				CompletionOnMemberValueName memberValuePair = (CompletionOnMemberValueName) astNode;
-				Annotation annotation = (Annotation) astNodeParent;
-				
-				this.completionToken = memberValuePair.name;
-				
-				if (this.completionToken.length == 0) {
+			CompletionOnMemberValueName memberValuePair = (CompletionOnMemberValueName) astNode;
+			Annotation annotation = (Annotation) astNodeParent;
+			
+			this.completionToken = memberValuePair.name;
+			
+			if (this.completionToken.length == 0) {
+				if(!this.requestor.isIgnored(CompletionProposal.TYPE_REF)) {
 					this.setSourceRange(astNode.sourceStart, astNode.sourceStart - 1, false);
 
 					findAnnotationReference(annotation.type);
-				} else {
-					MemberValuePair[] memberValuePairs = annotation.memberValuePairs();
+				}
+			} else {
+				MemberValuePair[] memberValuePairs = annotation.memberValuePairs();
+				if (!this.requestor.isIgnored(CompletionProposal.ANNOTATION_ATTRIBUTE_REF)) {
 					this.findAnnotationAttributes(this.completionToken, annotation.memberValuePairs(), (ReferenceBinding)annotation.resolvedType);
-					if (memberValuePairs == null || memberValuePairs.length == 0) {
-						if (annotation.resolvedType instanceof ReferenceBinding) {
-							MethodBinding[] methodBindings =
-								((ReferenceBinding)annotation.resolvedType).availableMethods();
-							if (methodBindings != null &&
-									methodBindings.length == 1 &&
-									CharOperation.equals(methodBindings[0].selector, VALUE)) {
-								if (this.expectedTypesPtr > -1 && this.expectedTypes[0].isAnnotationType()) {
-									findTypesAndPackages(this.completionToken, scope);
-								} else {
-									findVariablesAndMethods(
-										this.completionToken,
-										scope,
-										FakeInvocationSite,
-										scope,
-										insideTypeAnnotation,
-										true);
-									// can be the start of a qualified type name
-									findTypesAndPackages(this.completionToken, scope);
-								}
+				}
+				if (memberValuePairs == null || memberValuePairs.length == 0) {
+					if (annotation.resolvedType instanceof ReferenceBinding) {
+						MethodBinding[] methodBindings =
+							((ReferenceBinding)annotation.resolvedType).availableMethods();
+						if (methodBindings != null &&
+								methodBindings.length == 1 &&
+								CharOperation.equals(methodBindings[0].selector, VALUE)) {
+							if (this.expectedTypesPtr > -1 && this.expectedTypes[0].isAnnotationType()) {
+								findTypesAndPackages(this.completionToken, scope);
+							} else {
+								findVariablesAndMethods(
+									this.completionToken,
+									scope,
+									FakeInvocationSite,
+									scope,
+									insideTypeAnnotation,
+									true);
+								// can be the start of a qualified type name
+								findTypesAndPackages(this.completionToken, scope);
 							}
 						}
 					}
 				}
 			}
+		} else if(astNode instanceof CompletionOnBrankStatementLabel) {
+			if (!this.requestor.isIgnored(CompletionProposal.LABEL_REF)) {
+				CompletionOnBrankStatementLabel label = (CompletionOnBrankStatementLabel) astNode;
+				
+				this.completionToken = label.label;
+				
+				this.findLabels(this.completionToken, label.possibleLabels);
+			}
 		// Completion on Javadoc nodes
 		} else if ((astNode.bits & ASTNode.InsideJavadoc) != 0) {
 			if (astNode instanceof CompletionOnJavadocSingleTypeReference) {
@@ -1202,7 +1254,8 @@
 				// get the source positions of the completion identifier
 				if (qualifiedBinding instanceof ReferenceBinding && !(qualifiedBinding instanceof TypeVariableBinding)) {
 					if (!this.requestor.isIgnored(CompletionProposal.JAVADOC_TYPE_REF)) {
-						setSourceRange((int) (completionPosition >>> 32), (int) completionPosition);
+						int rangeStart = typeRef.completeInText() ? typeRef.sourceStart : (int) (completionPosition >>> 32);
+						setSourceRange(rangeStart, (int) completionPosition);
 						findMemberTypes(this.completionToken,
 							(ReferenceBinding) qualifiedBinding,
 							scope,
@@ -1552,7 +1605,7 @@
 				// scan the package & import statements first
 				if (parsedUnit.currentPackage instanceof CompletionOnPackageReference) {
 					contextAccepted = true;
-					this.requestor.acceptContext(new CompletionContext());
+					this.buildContext(parsedUnit.currentPackage, null, null, null);
 					if(!this.requestor.isIgnored(CompletionProposal.PACKAGE_REF)) {
 						findPackages((CompletionOnPackageReference) parsedUnit.currentPackage);
 					}
@@ -1573,7 +1626,7 @@
 							this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
 							if ((this.unitScope = parsedUnit.scope) != null) {
 								contextAccepted = true;
-								this.requestor.acceptContext(new CompletionContext());
+								this.buildContext(importReference, null, null, null);
 								
 								setSourceRange(
 									importReference.sourceStart,
@@ -1620,7 +1673,7 @@
 							return;
 						} else if(importReference instanceof CompletionOnKeyword) {
 							contextAccepted = true;
-							this.requestor.acceptContext(new CompletionContext());
+							this.buildContext(importReference, null, null, null);
 							if(!this.requestor.isIgnored(CompletionProposal.KEYWORD)) {
 								setSourceRange(importReference.sourceStart, importReference.sourceEnd);
 								CompletionOnKeyword keyword = (CompletionOnKeyword)importReference;
@@ -1673,7 +1726,10 @@
 			if(this.noProposal && this.problem != null) {
 				if(!contextAccepted) {
 					contextAccepted = true;
-					this.requestor.acceptContext(new CompletionContext());
+					CompletionContext context = new CompletionContext();
+					context.setOffset(completionPosition);
+					context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN);
+					this.requestor.acceptContext(context);
 				}
 				this.requestor.completionFailure(this.problem);
 				if(DEBUG) {
@@ -1715,7 +1771,10 @@
 			reset();
 			if(!contextAccepted) {
 				contextAccepted = true;
-				this.requestor.acceptContext(new CompletionContext());
+				CompletionContext context = new CompletionContext();
+				context.setTokenKind(CompletionContext.TOKEN_KIND_UNKNOWN);
+				context.setOffset(completionPosition);
+				this.requestor.acceptContext(context);
 			}
 			this.requestor.endReporting();
 		}
@@ -2272,6 +2331,8 @@
 			FieldBinding field = fields[f];
 
 			if (field.isSynthetic())	continue next;
+			
+			if (field.name == ClassScope.IncompleteHierarchy) continue next;
 
 			if (onlyStaticFields && !field.isStatic()) continue next;
 
@@ -4092,6 +4153,36 @@
 			addUninterestingBindings(((FieldDeclaration)parent).binding);
 		} 
 	}
+	
+	private void findLabels(char[] label, char[][] choices) {
+		if(choices == null || choices.length == 0) return;
+		
+		int length = label.length;
+		for (int i = 0; i < choices.length; i++) {
+			if (length <= choices[i].length
+				&& CharOperation.prefixEquals(label, choices[i], false /* ignore case */
+			)){
+				int relevance = computeBaseRelevance();
+				relevance += computeRelevanceForInterestingProposal();
+				relevance += computeRelevanceForCaseMatching(label, choices[i]);
+				relevance += computeRelevanceForRestrictions(IAccessRule.K_ACCESSIBLE); // no access restriction for keywors
+				
+				this.noProposal = false;
+				if(!this.requestor.isIgnored(CompletionProposal.LABEL_REF)) {
+					CompletionProposal proposal = this.createProposal(CompletionProposal.LABEL_REF, this.actualCompletionPosition);
+					proposal.setName(choices[i]);
+					proposal.setCompletion(choices[i]);
+					proposal.setReplaceRange(this.startPosition - this.offset, this.endPosition - this.offset);
+					proposal.setRelevance(relevance);
+					this.requestor.accept(proposal);
+					if(DEBUG) {
+						this.printDebug(proposal);
+					}
+				}
+			}
+		}
+	}
+	
 	// Helper method for findMethods(char[], MethodBinding[], Scope, ObjectVector, boolean, boolean, boolean, TypeBinding)
 	private void findLocalMethodDeclarations(
 		char[] methodName,
@@ -4495,7 +4586,7 @@
 				}
 			}
 			
-			if (notInJavadoc && hasPotentialDefaultAbstractMethods && currentType.isAbstract()){
+			if (notInJavadoc && hasPotentialDefaultAbstractMethods && (currentType.isAbstract() || currentType.isTypeVariable())){
 				findInterfacesMethods(
 					selector,
 					argTypes,
@@ -4514,7 +4605,7 @@
 			} else {
 				hasPotentialDefaultAbstractMethods = false;
 			}
-			currentType = notInJavadoc ? currentType.superclass() : null;
+			currentType = currentType.superclass();
 		}
 	}
 	private char[][] findMethodParameterNames(MethodBinding method, char[][] parameterTypeNames){
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionContext.java b/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionContext.java
index 18af0be..6cedbb9 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionContext.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionContext.java
@@ -20,6 +20,12 @@
 	protected char[][] expectedTypesKeys;
 	protected int javadoc;
 	
+	protected int offset = -1;
+	protected int tokenStart = -1;
+	protected int tokenEnd = -1;
+	protected char[] token = null;
+	protected int tokenKind;
+	
 	protected void setExpectedTypesSignatures(char[][] expectedTypesSignatures) {
 		this.expectedTypesSignatures = expectedTypesSignatures;
 	}
@@ -31,4 +37,24 @@
 	protected void setJavadoc(int javadoc) {
 		this.javadoc = javadoc;
 	}
+	
+	protected void setOffset(int offset) {
+		this.offset = offset;
+	}
+	
+	protected void setTokenRange(int start, int end) {
+		this.setTokenRange(start, end, -1);
+	}
+	protected void setTokenRange(int start, int end, int endOfEmptyToken) {
+		this.tokenStart = start;
+		this.tokenEnd = endOfEmptyToken > end ? endOfEmptyToken : end;
+	}
+	
+	protected void setToken(char[] token) {
+		this.token = token;
+	}
+	
+	protected void setTokenKind(int tokenKind) {
+		this.tokenKind = tokenKind;
+	}
 }
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java b/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java
index 39b98f0..3912cfc 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/InternalCompletionProposal.java
@@ -94,14 +94,14 @@
 			}
 		} else { 
 			// TODO (david) shouldn't it be NameLookup.ACCEPT_ALL ?
-			type = this.nameLookup.findType(new String(tName), false, NameLookup.ACCEPT_CLASSES & NameLookup.ACCEPT_INTERFACES);
+			type = this.nameLookup.findType(new String(tName),
+				false,
+				NameLookup.ACCEPT_CLASSES & NameLookup.ACCEPT_INTERFACES,
+				true/* consider secondary types */,
+				false/* do NOT wait for indexes */,
+				null);
 			if(type instanceof BinaryType){
-				if(((BinaryType)type).getSourceMapper() != null) {
-					this.completionEngine.typeCache.put(tName, type);
-				} else {
-					this.completionEngine.typeCache.put(tName, NO_ATTACHED_SOURCE);
-					type = null;
-				}
+				this.completionEngine.typeCache.put(tName, type);
 			} else {
 				type = null;
 			}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadoc.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadoc.java
index 298b14d..f1692f2 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadoc.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadoc.java
@@ -63,7 +63,7 @@
 					if (scope.kind == Scope.METHOD_SCOPE) {
 						paramNameReference.missingParams = missingParamTags(paramNameReference.binding, (MethodScope)scope);
 					}
-					if (paramNameReference.token == null) {
+					if (paramNameReference.token == null || paramNameReference.token.length == 0) {
 						paramNameReference.missingTypeParams = missingTypeParameterTags(paramNameReference.binding, scope);
 					}
 				} else if (this.completionNode instanceof CompletionOnJavadocTypeParamReference) {
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java
index e127cee..c424d0b 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionJavadocParser.java
@@ -54,7 +54,7 @@
 	public CompletionJavadocParser(CompletionParser sourceParser) {
 		super(sourceParser);
 		this.scanner = new CompletionScanner(ClassFileConstants.JDK1_3);
-		this.kind = COMPLETION_PARSER;
+		this.kind = COMPLETION_PARSER | TEXT_PARSE;
 		this.reportProblems = false;
 		initLevelTags();
 	}
@@ -66,13 +66,13 @@
 		this.cursorLocation = ((CompletionParser)sourceParser).cursorLocation;
 		CompletionScanner completionScanner = (CompletionScanner)this.scanner;
 		completionScanner.cursorLocation = this.cursorLocation;
-		completionScanner.completionIdentifier = null;
 		this.javadocStart = this.sourceParser.scanner.commentStarts[commentPtr];
 		this.javadocEnd = this.sourceParser.scanner.commentStops[commentPtr];
 		if (this.javadocStart <= this.cursorLocation && this.cursorLocation <= this.javadocEnd) {
 			if (CompletionEngine.DEBUG) {
 				System.out.println("COMPLETION in Javadoc:"); //$NON-NLS-1$
 			}
+			completionScanner.completionIdentifier = null;
 			this.firstTagPosition = 1;
 			super.checkDeprecation(commentPtr);
 		} else {
@@ -156,7 +156,14 @@
 		if (inCompletion) {
 			ASTNode node = (ASTNode) super.createMethodReference(receiver, arguments);
 			if (node instanceof JavadocMessageSend) {
-				this.completionNode = new CompletionOnJavadocMessageSend((JavadocMessageSend)node, this.memberStart);
+				JavadocMessageSend messageSend = (JavadocMessageSend) node;
+				int nameStart = (int) (messageSend.nameSourcePosition >>> 32);
+				int nameEnd = (int) messageSend.nameSourcePosition;
+				if ((nameStart <= (this.cursorLocation+1) && this.cursorLocation <= nameEnd)) {
+					this.completionNode = new CompletionOnJavadocFieldReference(messageSend, this.memberStart);
+				} else {
+					this.completionNode = new CompletionOnJavadocMessageSend(messageSend, this.memberStart);
+				}
 			} else if (node instanceof JavadocAllocationExpression) {
 				this.completionNode = new CompletionOnJavadocAllocationExpression((JavadocAllocationExpression)node, this.memberStart);
 			}
@@ -189,29 +196,34 @@
 						this.identifierPositionStack[this.identifierPtr],
 						this.tagSourceStart,
 						this.tagSourceEnd);
-			if (this.identifierStack[this.identifierPtr] == CompletionScanner.EmptyCompletionIdentifier) {
-				return null;
-			}
 		} else if (nbIdentifiers > 1) { // Qualified Type ref
-			// See if completion is in qualification
-			int size = nbIdentifiers;
-			if (this.tagSourceStart <= this.cursorLocation && this.cursorLocation <= this.tagSourceEnd) {
-				for (size=0; size<nbIdentifiers; size++) {
-					int start = (int) (this.identifierPositionStack[size] >>> 32);
-					int end = (int) this.identifierPositionStack[size];
-					if (start <= this.cursorLocation && this.cursorLocation <= end) {
-						size++;
-						break;
+			for (int i=startPtr; i<this.identifierPtr; i++) {
+				int start = (int) (this.identifierPositionStack[i] >>> 32);
+				int end = (int) this.identifierPositionStack[i];
+				if (start <= this.cursorLocation && this.cursorLocation <= end) {
+					if (i == startPtr) {
+						this.completionNode = new CompletionOnJavadocSingleTypeReference(
+									this.identifierStack[startPtr],
+									this.identifierPositionStack[startPtr],
+									this.tagSourceStart,
+									this.tagSourceEnd);
+					} else {
+						char[][] tokens = new char[i][];
+						System.arraycopy(this.identifierStack, startPtr, tokens, 0, i);
+						long[] positions = new long[i+1];
+						System.arraycopy(this.identifierPositionStack, startPtr, positions, 0, i+1);
+						this.completionNode = new CompletionOnJavadocQualifiedTypeReference(tokens, this.identifierStack[i], positions, this.tagSourceStart, this.tagSourceEnd);
 					}
+					break;
 				}
 			}
-			
-			// Copy only tokens necessary for completion
-			char[][] tokens = new char[size-1][];
-			System.arraycopy(this.identifierStack, startPtr, tokens, 0, size-1);
-			long[] positions = new long[size];
-			System.arraycopy(this.identifierPositionStack, startPtr, positions, 0, size);
-			this.completionNode = new CompletionOnJavadocQualifiedTypeReference(tokens, this.identifierStack[this.identifierPtr], positions, this.tagSourceStart, this.tagSourceEnd);
+			if (this.completionNode == null) {
+				char[][] tokens = new char[nbIdentifiers-1][];
+				System.arraycopy(this.identifierStack, startPtr, tokens, 0, nbIdentifiers-1);
+				long[] positions = new long[nbIdentifiers];
+				System.arraycopy(this.identifierPositionStack, startPtr, positions, 0, nbIdentifiers);
+				this.completionNode = new CompletionOnJavadocQualifiedTypeReference(tokens, this.identifierStack[this.identifierPtr], positions, this.tagSourceStart, this.tagSourceEnd);
+			}
 		}
 		this.identifierPtr -= nbIdentifiers;
 
@@ -337,7 +349,8 @@
 				return syntaxRecoverEmptyArgumentType(methodRef);
 			}
 			if (this.index >= this.scanner.eofPosition) {
-				Object argument = createArgumentReference(this.scanner.getCurrentIdentifierSource(), 0, false, typeRef, null, (((long)this.scanner.getCurrentTokenStartPosition())<<32)+this.scanner.getCurrentTokenEndPosition());
+				int argumentStart = ((ASTNode)typeRef).sourceStart;
+				Object argument = createArgumentReference(this.scanner.getCurrentIdentifierSource(), 0, false, typeRef, null, (((long)argumentStart)<<32)+this.tokenPreviousPosition-1);
 				return syntaxRecoverArgumentType(receiver, arguments, argument);
 			}
 			if (this.index >= this.cursorLocation) {
@@ -449,22 +462,15 @@
 			char[] name = null;
 			CompletionScanner completionScanner = (CompletionScanner) this.scanner;
 			boolean isTypeParam = false;
-			if (this.identifierPtr < 0) {
-				// workaround, empty token should set an empty identifier by scanner and so identifierPtr should be == 0
-				if (completionScanner.getCurrentIdentifierSource() == CompletionScanner.EmptyCompletionIdentifier) {
-					namePosition = completionScanner.completedIdentifierStart;
-					startPosition = completionScanner.completedIdentifierStart;
-					endPosition = completionScanner.completedIdentifierEnd;
-				}
-			} else {
+			if (this.identifierPtr >= 0) {
 				char[] identifier = null;
 				switch (this.identifierPtr) {
 					case 2:
-						if (!valid && completionScanner.getCurrentIdentifierSource() == CompletionScanner.EmptyCompletionIdentifier) {
+						if (!valid && completionScanner.completionIdentifier != null && completionScanner.completionIdentifier.length == 0) {
 							valid = pushParamName(true);
 						}
 					case 1:
-						isTypeParam = true;
+						isTypeParam = this.identifierStack[0][0] == '<';
 						identifier = this.identifierStack[1];
 						namePosition = this.identifierPositionStack[1];
 						break;
@@ -627,8 +633,8 @@
 							consumeToken();
 							break;
 						case TerminalTokens.TokenNameERROR :
+							consumeToken();
 							if (this.scanner.currentCharacter == '#') { // @see ...#member
-								consumeToken();
 								Object member = null;
 								try {
 									this.scanner.tokenizeWhiteSpace = false;
@@ -768,15 +774,13 @@
 	}
 
 	/* (non-Javadoc)
-	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#readTokenAndConsume()
-	 * TODO (frederic) remove when bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=114115 will be fixed
+	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#readToken()
 	 */
-	protected int readTokenAndConsume() throws InvalidInputException {
-		int token = super.readTokenAndConsume();
-		if (token == TerminalTokens.TokenNameIdentifier) {
-			if (this.scanner.currentPosition == this.scanner.startPosition) {
-				this.scanner.getCurrentIdentifierSource();
-			}
+	protected int readToken() throws InvalidInputException {
+		int token = super.readToken();
+		if (token == TerminalTokens.TokenNameIdentifier && this.scanner.currentPosition == this.scanner.startPosition) {
+			// Scanner is looping on empty token => read it... 
+			this.scanner.getCurrentIdentifierSource();
 		}
 		return token;
 	}
@@ -784,7 +788,11 @@
 	/* 
 	 * Recover syntax on invalid qualified name.
 	 */
-	protected Object syntaxRecoverQualifiedName() throws InvalidInputException {
+	protected Object syntaxRecoverQualifiedName(int primitiveToken) throws InvalidInputException {
+		if (this.cursorLocation == ((int)this.identifierPositionStack[this.identifierPtr])) {
+			// special case of completion just before the dot.
+			return createTypeReference(primitiveToken);
+		}
 		int idLength = this.identifierLengthStack[this.identifierLengthPtr--];
 		char[][] tokens = new char[idLength][];
 		int startPtr = this.identifierPtr-idLength+1;
@@ -816,6 +824,7 @@
 				return this.completionNode;
 			}
 		}
+		// Filter empty token
 		if (this.completionNode instanceof CompletionOnJavadocSingleTypeReference) {
 			CompletionOnJavadocSingleTypeReference singleTypeReference = (CompletionOnJavadocSingleTypeReference) this.completionNode;
 			if (singleTypeReference.token != null && singleTypeReference.token.length > 0) {
@@ -826,14 +835,22 @@
 			if (qualifiedTypeReference.tokens != null && qualifiedTypeReference.tokens.length == qualifiedTypeReference.sourcePositions.length) {
 				arguments.add(argument);
 			}
+		} else {
+			arguments.add(argument);
 		}
-		Object methodRef = createMethodReference(receiver, arguments);
+		Object methodRef = super.createMethodReference(receiver, arguments);
 		if (methodRef instanceof JavadocMessageSend) {
 			JavadocMessageSend msgSend = (JavadocMessageSend) methodRef;
 			if (this.index > this.cursorLocation) {
 				msgSend.sourceEnd = this.tokenPreviousPosition-1;
 			}
-			this.completionNode = new CompletionOnJavadocMessageSend(msgSend, this.memberStart);
+			int nameStart = (int) (msgSend.nameSourcePosition >>> 32);
+			int nameEnd = (int) msgSend.nameSourcePosition;
+			if ((nameStart <= (this.cursorLocation+1) && this.cursorLocation <= nameEnd)) {
+				this.completionNode = new CompletionOnJavadocFieldReference(msgSend, this.memberStart);
+			} else {
+				this.completionNode = new CompletionOnJavadocMessageSend(msgSend, this.memberStart);
+			}
 		} else if (methodRef instanceof JavadocAllocationExpression) {
 			JavadocAllocationExpression allocExp = (JavadocAllocationExpression) methodRef;
 			if (this.index > this.cursorLocation) {
@@ -881,4 +898,17 @@
 			getCompletionJavadoc().completionNode = (Expression) completionNode;
 		}
 	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#verifySpaceOrEndComment()
+	 */
+	protected boolean verifySpaceOrEndComment() {
+		CompletionScanner completionScanner = (CompletionScanner) this.scanner;
+		if (completionScanner.completionIdentifier != null && completionScanner.completedIdentifierStart <= this.cursorLocation && this.cursorLocation <= completionScanner.completedIdentifierEnd) {
+			// if we're on completion location do not verify end...
+			return true;
+		}
+		return super.verifySpaceOrEndComment();
+	}
+	
 }
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
index a7ae738..1e9d67b 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionNodeDetector.java
@@ -263,6 +263,9 @@
 	public boolean visit(SingleTypeReference singleTypeReference, ClassScope scope) {
 		return this.visit(singleTypeReference);
 	}
+	public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
+		return this.visit(stringLiteral);
+	}
 	public boolean visit(SuperReference superReference, BlockScope scope) {
 		return this.visit(superReference);
 	}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnBrankStatementLabel.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnBrankStatementLabel.java
new file mode 100644
index 0000000..111e4af
--- /dev/null
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnBrankStatementLabel.java
@@ -0,0 +1,42 @@
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.internal.compiler.ast.BranchStatement;
+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 CompletionOnBrankStatementLabel extends BranchStatement {
+	public static final int BREAK = 1;
+	public static final int CONTINUE = 2;
+	
+	private int kind;
+	public char[][] possibleLabels;
+	
+	public CompletionOnBrankStatementLabel(int kind, char[] l, int s, int e, char[][] possibleLabels) {
+		super(l, s, e);
+		this.kind = kind;
+		this.possibleLabels = possibleLabels;
+	}
+
+	public FlowInfo analyseCode(BlockScope currentScope,
+			FlowContext flowContext, FlowInfo flowInfo) {
+		// Is never called
+		return null;
+	}
+
+	public void resolve(BlockScope scope) {
+		throw new CompletionNodeFound(this, scope);
+	}
+	public StringBuffer printStatement(int indent, StringBuffer output) {
+		printIndent(indent, output);
+		if(kind == CONTINUE) {
+			output.append("continue "); //$NON-NLS-1$
+		} else {
+			output.append("break "); //$NON-NLS-1$
+		}
+		output.append("<CompleteOnLabel:"); //$NON-NLS-1$
+		output.append(label);
+		return output.append(">;"); //$NON-NLS-1$
+	}
+
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassReference.java
deleted file mode 100644
index 9ff248c..0000000
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnClassReference.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.codeassist.complete;
-
-public class CompletionOnClassReference extends CompletionOnSingleTypeReference {
-
-	public CompletionOnClassReference(char[] source, long pos) {
-
-		super(source, pos);
-	}
-
-	public StringBuffer printExpression(int indent, StringBuffer output) {
-		
-		return output.append("<CompleteOnClass:").append(this.token).append('>'); //$NON-NLS-1$
-	}
-}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
deleted file mode 100644
index 45bc49e..0000000
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnExceptionReference.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.codeassist.complete;
-
-/*
- * Completion node build by the parser in any case it was intending to
- * reduce an exception type reference containing the completion identifier.
- * e.g.
- *
- *	class X {
- *    void foo() {
- *      try {
- *        bar();
- *      } catch (IOExc[cursor] e) {
- *      }
- *    }
- *  }
- *
- *	---> class X {
- *         void foo() {
- *           try {
- *             bar();
- *           } catch (<CompleteOnException:IOExc> e) {
- *           }
- *         }
- *       }
- *
- * The source range of the completion node denotes the source range
- * which should be replaced by the completion.
- */
-public class CompletionOnExceptionReference extends CompletionOnSingleTypeReference {
-
-	public CompletionOnExceptionReference(char[] source, long pos) {
-
-		super(source, pos);
-	}
-
-	public StringBuffer printExpression(int indent, StringBuffer output) {
-		
-		return output.append("<CompleteOnException:").append(this.token).append('>'); //$NON-NLS-1$
-	}
-}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnInterfaceReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnInterfaceReference.java
deleted file mode 100644
index 3f0b1a6..0000000
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnInterfaceReference.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.codeassist.complete;
-
-public class CompletionOnInterfaceReference extends CompletionOnSingleTypeReference {
-	public CompletionOnInterfaceReference(char[] source, long pos) {
-		super(source, pos);
-	}
-	public StringBuffer printExpression(int indent, StringBuffer output) {
-		return output.append("<CompleteOnInterface:").append(token).append('>');//$NON-NLS-1$
-	}
-}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java
index 45f3462..8dcf80c 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocFieldReference.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.jdt.internal.compiler.ast.JavadocMessageSend;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
 import org.eclipse.jdt.internal.compiler.lookup.Scope;
@@ -40,6 +41,15 @@
 		this.tagValue = fieldRef.tagValue;
 	}
 
+	public CompletionOnJavadocFieldReference(JavadocMessageSend msgSend, int position) {
+		super(msgSend.selector, ((msgSend.nameSourcePosition>>32)<<32)+msgSend.sourceEnd);
+		this.receiver = msgSend.receiver;
+		this.separatorPosition = position;
+		this.tagSourceStart = msgSend.tagSourceStart;
+		this.tagSourceEnd = msgSend.tagSourceEnd;
+		this.tagValue = msgSend.tagValue;
+	}
+
 	/**
 	 * @param flags The completionFlags to set.
 	 */
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocParamNameReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocParamNameReference.java
index 08f764e..5fb27d3 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocParamNameReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocParamNameReference.java
@@ -47,7 +47,7 @@
 	 * @see org.eclipse.jdt.internal.compiler.ast.AllocationExpression#printExpression(int, java.lang.StringBuffer)
 	 */
 	public StringBuffer printExpression(int indent, StringBuffer output) {
-		output.append("<CompleteOnJavadocSingleNameReference:"); //$NON-NLS-1$
+		output.append("<CompletionOnJavadocParamNameReference:"); //$NON-NLS-1$
 		if (this.token != null) super.printExpression(indent, output);
 		return output.append('>');
 	}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTypeParamReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTypeParamReference.java
index 4666743..f913bc3 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTypeParamReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTypeParamReference.java
@@ -46,7 +46,7 @@
 	 * @see org.eclipse.jdt.internal.compiler.ast.AllocationExpression#printExpression(int, java.lang.StringBuffer)
 	 */
 	public StringBuffer printExpression(int indent, StringBuffer output) {
-		output.append("<CompleteOnJavadocSingleNameReference:"); //$NON-NLS-1$
+		output.append("<CompletionOnJavadocTypeParamReference:"); //$NON-NLS-1$
 		if (this.token != null) super.printExpression(indent, output);
 		return output.append('>');
 	}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedClassReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedClassReference.java
deleted file mode 100644
index c526d1c..0000000
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedClassReference.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.codeassist.complete;
-
-public class CompletionOnQualifiedClassReference extends CompletionOnQualifiedTypeReference {
-public CompletionOnQualifiedClassReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
-	super(previousIdentifiers, completionIdentifier, positions);
-}
-public StringBuffer printExpression(int indent, StringBuffer output) {
-
-	output.append("<CompleteOnClass:"); //$NON-NLS-1$
-	for (int i = 0; i < tokens.length; i++) {
-		output.append(tokens[i]);
-		output.append('.');
-	}
-	output.append(completionIdentifier).append('>');
-	return output;
-}
-}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
deleted file mode 100644
index c17b83a..0000000
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedExceptionReference.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.codeassist.complete;
-
-/*
- * Completion node build by the parser in any case it was intending to
- * reduce an exception type reference containing the completion identifier 
- * as part of a qualified name.
- * e.g.
- *
- *	class X {
- *    void foo() {
- *      try {
- *        bar();
- *      } catch (java.io.IOExc[cursor] e) {
- *      }
- *    }
- *  }
- *
- *	---> class X {
- *         void foo() {
- *           try {
- *             bar();
- *           } catch (<CompleteOnException:java.io.IOExc> e) {
- *           }
- *         }
- *       }
- *
- * The source range of the completion node denotes the source range
- * which should be replaced by the completion.
- */
-public class CompletionOnQualifiedExceptionReference extends CompletionOnQualifiedTypeReference {
-public CompletionOnQualifiedExceptionReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
-	super(previousIdentifiers, completionIdentifier, positions);
-}
-public StringBuffer printExpression(int indent, StringBuffer output) {
-
-	output.append("<CompleteOnException:"); //$NON-NLS-1$
-	for (int i = 0; i < tokens.length; i++) {
-		output.append(tokens[i]);
-		output.append('.'); 
-	}
-	output.append(completionIdentifier).append('>');
-	return output;
-}
-}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedInterfaceReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedInterfaceReference.java
deleted file mode 100644
index 72d1f28..0000000
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedInterfaceReference.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.codeassist.complete;
-
-public class CompletionOnQualifiedInterfaceReference  extends CompletionOnQualifiedTypeReference {
-public CompletionOnQualifiedInterfaceReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
-	super(previousIdentifiers, completionIdentifier, positions);
-}
-public StringBuffer printExpression(int indent, StringBuffer output) {
-
-	output.append("<CompleteOnInterface:"); //$NON-NLS-1$
-	for (int i = 0; i < tokens.length; i++) {
-		output.append(tokens[i]);
-		output.append('.'); 
-	}
-	output.append(completionIdentifier).append('>'); 
-	return output;
-}
-}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
index cf2de0a..cccc656 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
@@ -28,10 +28,20 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class CompletionOnQualifiedTypeReference extends QualifiedTypeReference {
+	public static final int K_TYPE = 0;
+	public static final int K_CLASS = 1;
+	public static final int K_INTERFACE = 2;
+	public static final int K_EXCEPTION = 3;
+	
+	private int kind = K_TYPE;
 	public char[] completionIdentifier;
 public CompletionOnQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions) {
+	this(previousIdentifiers, completionIdentifier, positions, K_TYPE);
+}
+public CompletionOnQualifiedTypeReference(char[][] previousIdentifiers, char[] completionIdentifier, long[] positions, int kind) {
 	super(previousIdentifiers, positions);
 	this.completionIdentifier = completionIdentifier;
+	this.kind = kind;
 }
 public void aboutToResolve(Scope scope) {
 	getTypeBinding(scope);
@@ -52,9 +62,32 @@
 
 	throw new CompletionNodeFound(this, binding, scope);
 }
-public StringBuffer printExpression(int indent, StringBuffer output) {
+public boolean isClass(){
+	return this.kind == K_CLASS;
+}
 
-	output.append("<CompleteOnType:"); //$NON-NLS-1$
+public boolean isInterface(){
+	return this.kind == K_INTERFACE;
+}
+
+public boolean isException(){
+	return this.kind == K_EXCEPTION;
+}
+public StringBuffer printExpression(int indent, StringBuffer output) {
+	switch (this.kind) {
+		case K_CLASS :
+			output.append("<CompleteOnClass:");//$NON-NLS-1$
+			break;
+		case K_INTERFACE :
+			output.append("<CompleteOnInterface:");//$NON-NLS-1$
+			break;
+		case K_EXCEPTION :
+			output.append("<CompleteOnException:");//$NON-NLS-1$
+			break;
+		default :
+			output.append("<CompleteOnType:");//$NON-NLS-1$
+			break;
+	}
 	for (int i = 0; i < tokens.length; i++) {
 		output.append(tokens[i]);
 		output.append('.'); 
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
index a7f415d..2594ce1 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
@@ -28,13 +28,23 @@
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class CompletionOnSingleTypeReference extends SingleTypeReference {
+public static final int K_TYPE = 0;
+public static final int K_CLASS = 1;
+public static final int K_INTERFACE = 2;
+public static final int K_EXCEPTION = 3;
+
+private int kind = K_TYPE;
 public boolean isCompletionNode;
 public boolean isConstructorType;
 public CompletionOnFieldType fieldTypeCompletionNode;
 
 public CompletionOnSingleTypeReference(char[] source, long pos) {
+	this(source, pos, K_TYPE);
+}
+public CompletionOnSingleTypeReference(char[] source, long pos, int kind) {
 	super(source, pos);
 	isCompletionNode = true;
+	this.kind = kind;
 }
 public void aboutToResolve(Scope scope) {
 	getTypeBinding(scope);
@@ -55,8 +65,31 @@
 		return super.getTypeBinding(scope);
 	}
 }
+public boolean isClass(){
+	return this.kind == K_CLASS;
+}
+public boolean isInterface(){
+	return this.kind == K_INTERFACE;
+}
+public boolean isException(){
+	return this.kind == K_EXCEPTION;
+}
 public StringBuffer printExpression(int indent, StringBuffer output){
-	return output.append("<CompleteOnType:").append(token).append('>'); //$NON-NLS-1$
+	switch (this.kind) {
+		case K_CLASS :
+			output.append("<CompleteOnClass:");//$NON-NLS-1$
+			break;
+		case K_INTERFACE :
+			output.append("<CompleteOnInterface:");//$NON-NLS-1$
+			break;
+		case K_EXCEPTION :
+			output.append("<CompleteOnException:");//$NON-NLS-1$
+			break;
+		default :
+			output.append("<CompleteOnType:");//$NON-NLS-1$
+			break;
+	}
+	return output.append(token).append('>');
 }
 public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
     if (this.fieldTypeCompletionNode != null) {
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnStringLiteral.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnStringLiteral.java
new file mode 100644
index 0000000..0a0469b
--- /dev/null
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnStringLiteral.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.codeassist.complete;
+
+import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+/*
+ * Completion node build by the parser in any case it was intending to
+ * reduce a string literal.
+ * e.g.
+ *
+ *	class X {
+ *    void foo() {
+ *      String s = "a[cursor]"
+ *    }
+ *  }
+ *
+ *	---> class X {
+ *         void foo() {
+ *           String s = <CompleteOnStringLiteral:a>
+ *         }
+ *       }
+ */
+
+public class CompletionOnStringLiteral extends StringLiteral {
+	public int contentStart;
+	public int contentEnd;
+	public CompletionOnStringLiteral(char[] token, int s, int e, int cs, int ce, int lineNumber) {
+		super(token, s, e, lineNumber);
+		this.contentStart = cs;
+		this.contentEnd = ce;
+	}
+
+	public CompletionOnStringLiteral(int s, int e, int cs, int ce) {
+		super(s,e);
+		this.contentStart = cs;
+		this.contentEnd = ce;
+	}
+	public TypeBinding resolveType(ClassScope scope) {
+		throw new CompletionNodeFound(this, null, scope);
+	}
+	public TypeBinding resolveType(BlockScope scope) {
+		throw new CompletionNodeFound(this, null, scope);
+	}
+	
+	public StringBuffer printExpression(int indent, StringBuffer output) {
+		output.append("<CompletionOnString:"); //$NON-NLS-1$
+		output = super.printExpression(indent, output);
+		return output.append('>');
+	}
+}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
index a9b1c93..b831619 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
@@ -68,7 +68,10 @@
 	protected static final int K_PARAMETERIZED_ALLOCATION = COMPLETION_PARSER + 31;
 	protected static final int K_PARAMETERIZED_CAST = COMPLETION_PARSER + 32;
 	protected static final int K_BETWEEN_ANNOTATION_NAME_AND_RPAREN = COMPLETION_PARSER + 33;
-
+	protected static final int K_INSIDE_BREAK_STATEMENT = COMPLETION_PARSER + 34;
+	protected static final int K_INSIDE_CONTINUE_STATEMENT = COMPLETION_PARSER + 35;
+	protected static final int K_LABEL = COMPLETION_PARSER + 36;
+	
 	public final static char[] FAKE_TYPE_NAME = new char[]{' '};
 	public final static char[] VALUE = new char[]{'v', 'a', 'l', 'u', 'e'};
 	
@@ -126,6 +129,10 @@
 	static final int NEXTTOKEN = 1;
 	static final int YES = 2;
 	
+	protected static final int LabelStackIncrement = 10;
+	char[][] labelStack = new char[LabelStackIncrement][];
+	int labelPtr = -1;
+	
 	boolean isAlreadyAttached;
 public CompletionParser(ProblemReporter problemReporter) {
 	super(problemReporter);
@@ -1032,19 +1039,16 @@
 			char[][] keywords = new char[Keywords.COUNT][];
 			int count = 0;
 			if(unit.typeCount == 0
-				&& lastModifiers == ClassFileConstants.AccDefault
-				&& CharOperation.prefixEquals(identifierStack[ptr], Keywords.IMPORT)) {
+				&& lastModifiers == ClassFileConstants.AccDefault) {
 				keywords[count++] = Keywords.IMPORT;
 			}
 			if(unit.typeCount == 0
 				&& unit.importCount == 0
 				&& lastModifiers == ClassFileConstants.AccDefault
-				&& compilationUnit.currentPackage == null
-				&& CharOperation.prefixEquals(identifierStack[ptr], Keywords.PACKAGE)) {
+				&& compilationUnit.currentPackage == null) {
 				keywords[count++] = Keywords.PACKAGE;
 			}
-			if((lastModifiers & ClassFileConstants.AccPublic) == 0
-				&& CharOperation.prefixEquals(identifierStack[ptr], Keywords.PUBLIC)) {
+			if((lastModifiers & ClassFileConstants.AccPublic) == 0) {
 				boolean hasNoPublicType = true;
 				for (int i = 0; i < unit.typeCount; i++) {
 					if((unit.types[i].typeDeclaration.modifiers & ClassFileConstants.AccPublic) != 0) {
@@ -1056,20 +1060,17 @@
 				}
 			}
 			if((lastModifiers & ClassFileConstants.AccAbstract) == 0
-				&& (lastModifiers & ClassFileConstants.AccFinal) == 0
-				&& CharOperation.prefixEquals(identifierStack[ptr], Keywords.ABSTRACT)) {
+				&& (lastModifiers & ClassFileConstants.AccFinal) == 0) {
 				keywords[count++] = Keywords.ABSTRACT;
 			}
 			if((lastModifiers & ClassFileConstants.AccAbstract) == 0
-				&& (lastModifiers & ClassFileConstants.AccFinal) == 0
-				&& CharOperation.prefixEquals(identifierStack[ptr], Keywords.FINAL)) {
+				&& (lastModifiers & ClassFileConstants.AccFinal) == 0) {
 				keywords[count++] = Keywords.FINAL;
 			}
-			if(CharOperation.prefixEquals(identifierStack[ptr], Keywords.CLASS)) {
-				keywords[count++] = Keywords.CLASS;
-			}
-			if((lastModifiers & ClassFileConstants.AccFinal) == 0
-				&& CharOperation.prefixEquals(identifierStack[ptr], Keywords.INTERFACE)) {
+			
+			keywords[count++] = Keywords.CLASS;
+			
+			if((lastModifiers & ClassFileConstants.AccFinal) == 0) {
 				keywords[count++] = Keywords.INTERFACE;
 			}
 			if(count != 0) {
@@ -1249,6 +1250,45 @@
 	}
 	return false;
 }
+private boolean checkLabelStatement() {
+	if(isInsideMethod() || isInsideFieldInitialization()) {
+	
+		int kind = this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER);
+		if(kind != K_INSIDE_BREAK_STATEMENT && kind != K_INSIDE_CONTINUE_STATEMENT) return false;
+	
+		if (indexOfAssistIdentifier() != 0) return false;
+		
+		char[][] labels = new char[this.labelPtr + 1][];
+		int labelCount = 0;
+		
+		int labelKind = kind;
+		int index = 1;
+		while(labelKind != 0 && labelKind != K_METHOD_DELIMITER) {
+			labelKind = this.topKnownElementKind(COMPLETION_OR_ASSIST_PARSER, index);
+			if(labelKind == K_LABEL) {
+				int ptr = this.topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER, index);
+				labels[labelCount++] = this.labelStack[ptr];
+			}
+			index++;
+		}
+		System.arraycopy(labels, 0, labels = new char[labelCount][], 0, labelCount);
+		
+		long position = this.identifierPositionStack[this.identifierPtr];
+		CompletionOnBrankStatementLabel statementLabel =
+			new CompletionOnBrankStatementLabel(
+					kind == K_INSIDE_BREAK_STATEMENT ? CompletionOnBrankStatementLabel.BREAK : CompletionOnBrankStatementLabel.CONTINUE,
+					this.identifierStack[this.identifierPtr--],
+					(int) (position >>> 32),
+					(int)position,
+					labels);
+		
+		this.assistNode = statementLabel;
+		this.lastCheckPoint = this.assistNode.sourceEnd + 1;
+		this.isOrphanCompletionNode = true;
+		return true;
+	}
+	return false;
+}
 /**
  * Checks if the completion is on a member access (ie. in an identifier following a dot).
  * Returns whether we found a completion node.
@@ -1517,6 +1557,7 @@
 	if (checkInvocation()) return;
 
 	if (checkParemeterizedType()) return;
+	if (checkLabelStatement()) return;
 	if (checkNameCompletion()) return;
 }
 protected void consumeArrayCreationExpressionWithInitializer() {
@@ -2148,8 +2189,7 @@
 				/* filter out cases where scanner is still inside type header */
 				if (!recoveredMethod.foundOpeningBrace) {
 					AbstractMethodDeclaration method = recoveredMethod.methodDeclaration;
-					if(method.thrownExceptions == null
-						&& CharOperation.prefixEquals(identifierStack[ptr], Keywords.THROWS)) {
+					if(method.thrownExceptions == null) {
 						CompletionOnKeyword1 completionOnKeyword = new CompletionOnKeyword1(
 							identifierStack[ptr],
 							identifierPositionStack[ptr],
@@ -2248,6 +2288,11 @@
 	
 	this.lastCheckPoint = markerAnnotation.sourceEnd + 1;
 }
+protected void consumeLabel() {
+	super.consumeLabel();
+	this.pushOnLabelStack(this.identifierStack[this.identifierPtr]);
+	this.pushOnElementStack(K_LABEL, this.labelPtr);
+}
 protected void consumeMarkerAnnotation() {
 	this.popElement(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN);
 	super.consumeMarkerAnnotation();
@@ -2322,6 +2367,10 @@
 	this.popElement(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN);
 	super.consumeSingleMemberAnnotation();
 }
+protected void consumeStatementLabel() {
+	this.popElement(K_LABEL);
+	super.consumeStatementLabel();
+}
 protected void consumeStatementSwitch() {
 	super.consumeStatementSwitch();
 	if(topKnownElementKind(COMPLETION_OR_ASSIST_PARSER) == K_SWITCH_LABEL) {
@@ -2642,6 +2691,16 @@
 							popElement(K_INSIDE_ASSERT_STATEMENT);
 						}
 						break;
+					case K_INSIDE_BREAK_STATEMENT:
+						if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
+							popElement(K_INSIDE_BREAK_STATEMENT);
+						}
+						break;
+					case K_INSIDE_CONTINUE_STATEMENT:
+						if(topKnownElementInfo(COMPLETION_OR_ASSIST_PARSER) == this.bracketDepth) {
+							popElement(K_INSIDE_CONTINUE_STATEMENT);
+						}
+						break;
 				}
 				break;
 			case TokenNamereturn:
@@ -2772,6 +2831,12 @@
 			case TokenNameextends:
 				pushOnElementStack(K_EXTENDS_KEYWORD);
 				break;
+			case TokenNamebreak:
+				pushOnElementStack(K_INSIDE_BREAK_STATEMENT, bracketDepth);
+				break;
+			case TokenNamecontinue:
+				pushOnElementStack(K_INSIDE_CONTINUE_STATEMENT, bracketDepth);
+				break;
 		}
 	} else {
 		switch(token) {
@@ -2989,13 +3054,28 @@
 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, assistName, positions);
+			return new CompletionOnQualifiedTypeReference(
+					previousIdentifiers,
+					assistName,
+					positions,
+					CompletionOnQualifiedTypeReference.K_EXCEPTION);
 		case K_NEXT_TYPEREF_IS_CLASS :
-			return new CompletionOnQualifiedClassReference(previousIdentifiers, assistName, positions);
+			return new CompletionOnQualifiedTypeReference(
+					previousIdentifiers,
+					assistName,
+					positions,
+					CompletionOnQualifiedTypeReference.K_CLASS);
 		case K_NEXT_TYPEREF_IS_INTERFACE :
-			return new CompletionOnQualifiedInterfaceReference(previousIdentifiers, assistName, positions);
+			return new CompletionOnQualifiedTypeReference(
+					previousIdentifiers,
+					assistName,
+					positions,
+					CompletionOnQualifiedTypeReference.K_INTERFACE);
 		default :
-			return new CompletionOnQualifiedTypeReference(previousIdentifiers, assistName, positions); 
+			return new CompletionOnQualifiedTypeReference(
+					previousIdentifiers,
+					assistName,
+					positions); 
 	}
 }
 public TypeReference createParameterizedQualifiedAssistTypeReference(char[][] previousIdentifiers, TypeReference[][] typeArguments, char[] assistName, TypeReference[] assistTypeArguments, long[] positions) {
@@ -3124,11 +3204,11 @@
 public TypeReference createSingleAssistTypeReference(char[] assistName, long position) {
 	switch (topKnownElementKind(COMPLETION_OR_ASSIST_PARSER)) {
 		case K_NEXT_TYPEREF_IS_EXCEPTION :
-			return new CompletionOnExceptionReference(assistName, position) ;
+			return new CompletionOnSingleTypeReference(assistName, position, CompletionOnSingleTypeReference.K_EXCEPTION) ;
 		case K_NEXT_TYPEREF_IS_CLASS :
-			return new CompletionOnClassReference(assistName, position);
+			return new CompletionOnSingleTypeReference(assistName, position, CompletionOnSingleTypeReference.K_CLASS);
 		case K_NEXT_TYPEREF_IS_INTERFACE :
-			return new CompletionOnInterfaceReference(assistName, position);
+			return new CompletionOnSingleTypeReference(assistName, position, CompletionOnSingleTypeReference.K_INTERFACE);
 		default :
 			return new CompletionOnSingleTypeReference(assistName, position); 
 	}
@@ -3136,7 +3216,64 @@
 public TypeReference createParameterizedSingleAssistTypeReference(TypeReference[] typeArguments, char[] assistName, long position) {
 	return this.createSingleAssistTypeReference(assistName, position);
 }
-
+protected StringLiteral createStringLiteral(char[] token, int start, int end, int lineNumber) {
+	if (start <= this.cursorLocation && this.cursorLocation <= end){
+		char[] source = this.scanner.source;
+		
+		int contentStart = start;
+		int contentEnd = end;
+		
+		// " could be as unicode \u0022
+		int pos = contentStart;
+		if(source[pos] == '\"') {
+			contentStart = pos + 1;
+		} else if(source[pos] == '\\' && source[pos+1] == 'u') {
+			pos += 2;
+			while (source[pos] == 'u') {
+				pos++;
+			}
+			if(source[pos] == 0 && source[pos + 1] == 0 && source[pos + 2] == 2 && source[pos + 3] == 2) {
+				contentStart = pos + 4;
+			}
+		}
+		
+		pos = contentEnd;
+		if(source[pos] == '\"') {
+			contentEnd = pos - 1;
+		} else if(source.length > 5 && source[pos-4] == 'u') {
+			if(source[pos - 3] == 0 && source[pos - 2] == 0 && source[pos - 1] == 2 && source[pos] == 2) {
+				pos -= 5;
+				while (pos > -1 && source[pos] == 'u') {
+					pos--;
+				}
+				if(pos > -1 && source[pos] == '\\') {
+					contentEnd = pos - 1;
+				} 
+			}
+		}
+		
+		if(contentEnd < start) {
+			contentEnd = end;
+		}
+		
+		if(this.cursorLocation != end || end == contentEnd) {
+			CompletionOnStringLiteral stringLiteral = new CompletionOnStringLiteral(
+					token,
+					start,
+					end,
+					contentStart, 
+					contentEnd,
+					lineNumber);
+			
+			this.assistNode = stringLiteral;
+			this.restartRecovery = true;
+			this.lastCheckPoint = end;
+			
+			return stringLiteral;
+		}
+	}
+	return super.createStringLiteral(token, start, end, lineNumber);
+}
 public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult, int cursorLoc) {
 
 	this.cursorLocation = cursorLoc;
@@ -3201,10 +3338,12 @@
 }
 public void initialize() {
 	super.initialize();
+	this.labelPtr = -1;
 	this.initializeForBlockStatements();
 }
 public void initialize(boolean initializeNLS) {
 	super.initialize(initializeNLS);
+	this.labelPtr = -1;
 	this.initializeForBlockStatements();
 }
 /*
@@ -3352,6 +3491,18 @@
 
 	this.initializeForBlockStatements();
 }
+protected void pushOnLabelStack(char[] label){
+	if (this.labelPtr < -1) return;
+	
+	int stackLength = this.labelStack.length;
+	if (++this.labelPtr >= stackLength) {
+		System.arraycopy(
+			this.labelStack, 0,
+			this.labelStack = new char[stackLength + LabelStackIncrement][], 0,
+			stackLength);
+	}
+	this.labelStack[this.labelPtr] = label;
+}
 /**
  * Creates a completion on member access node and push it
  * on the expression stack.
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
index 0d47d1b..ec6e0d8 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionScanner.java
@@ -21,7 +21,6 @@
  *  n  means completion behind the n-th character
  */
 import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 
 public class CompletionScanner extends Scanner {
@@ -82,6 +81,25 @@
 	return super.getCurrentIdentifierSource();
 }
 
+public char[] getCurrentTokenSourceString() {
+	if (this.completionIdentifier == null){
+		if (this.cursorLocation+1 >= this.startPosition && this.cursorLocation < this.currentPosition){
+			// remember actual identifier positions
+			this.completedIdentifierStart = this.startPosition;
+			this.completedIdentifierEnd = this.currentPosition - 1;
+			if (this.withoutUnicodePtr != 0){			// check unicode scenario
+				int length = this.cursorLocation - this.startPosition - this.unicodeCharSize;
+				System.arraycopy(this.withoutUnicodeBuffer, 2, this.completionIdentifier = new char[length], 0, length);
+			} else {
+				// no char[] sharing around completionIdentifier, we want it to be unique so as to use identity checks	
+				int length = this.cursorLocation - this.startPosition;
+				System.arraycopy(this.source, this.startPosition + 1, (this.completionIdentifier = new char[length]), 0, length);
+			}
+			return this.completionIdentifier;
+		}
+	}
+	return super.getCurrentTokenSourceString();
+}
 public int getNextToken() throws InvalidInputException {
 
 	this.wasAcr = false;
@@ -149,11 +167,6 @@
 					&& (this.cursorLocation < this.startPosition)
 					&& !Character.isJavaIdentifierStart(this.currentCharacter)){
 					this.currentPosition = this.startPosition; // for next token read
-					/* Warning:
-					 * Above statement reset scanner position at token start which can make
-					 * scanner enter in an infinite loop if completionIdentifier is still null!
-					 * (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=114115)
-					 */
 					return TokenNameIdentifier;
 				}
 			} while (isWhiteSpace);
@@ -414,9 +427,18 @@
 						while (this.currentCharacter != '"') {
 							/**** \r and \n are not valid in string literals ****/
 							if ((this.currentCharacter == '\n') || (this.currentCharacter == '\r')) {
-								// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
 								if (isUnicode) {
-									int start = this.currentPosition;
+									int start = this.currentPosition - 5;
+									while(this.source[start] != '\\') {
+										start--;
+									}
+									if(this.startPosition <= this.cursorLocation
+											&& this.cursorLocation <= this.currentPosition-1) {
+										this.currentPosition = start;
+										// complete inside a string literal
+										return TokenNameStringLiteral;
+									}
+									start = this.currentPosition;
 									for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
 										if (this.currentPosition >= this.eofPosition) {
 											this.currentPosition = start;
@@ -438,6 +460,11 @@
 									}
 								} else {
 									this.currentPosition--; // set current position on new line character
+									if(this.startPosition <= this.cursorLocation
+											&& this.cursorLocation <= this.currentPosition-1) {
+										// complete inside a string literal
+										return TokenNameStringLiteral;
+									}
 								}
 								throw new InvalidInputException(INVALID_CHAR_IN_STRING);
 							}
@@ -448,7 +475,10 @@
 									this.unicodeAsBackSlash = false;
 									if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
 										getNextUnicodeChar();
+										isUnicode = true;
 										this.withoutUnicodePtr--;
+									} else {
+										isUnicode = false;
 									}
 								} else {
 									if (this.withoutUnicodePtr == 0) {
@@ -468,7 +498,9 @@
 							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
 								&& (this.source[this.currentPosition] == 'u')) {
 								getNextUnicodeChar();
+								isUnicode = true;
 							} else {
+								isUnicode = false;
 								if (this.withoutUnicodePtr != 0) {
 								    this.unicodeStore();
 								}
@@ -477,6 +509,11 @@
 						}
 					} catch (IndexOutOfBoundsException e) {
 						this.currentPosition--;
+						if(this.startPosition <= this.cursorLocation
+							&& this.cursorLocation < this.currentPosition) {
+							// complete inside a string literal
+							return TokenNameStringLiteral;
+						}
 						throw new InvalidInputException(UNTERMINATED_STRING);
 					} catch (InvalidInputException e) {
 						if (e.getMessage().equals(INVALID_ESCAPE)) {
@@ -495,9 +532,6 @@
 						}
 						throw e; // rethrow
 					}
-					if (this.startPosition <= this.cursorLocation && this.cursorLocation <= this.currentPosition-1){
-						throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_STRING);
-					}
 					return TokenNameStringLiteral;
 				case '/' :
 					{
@@ -765,7 +799,9 @@
 public final void getNextUnicodeChar() throws InvalidInputException {
 	int temp = this.currentPosition; // the \ is already read
 	super.getNextUnicodeChar();
-	this.unicodeCharSize += (this.currentPosition - temp);
+	if(this.cursorLocation > temp) {
+		this.unicodeCharSize += (this.currentPosition - temp);
+	}
 	if (temp < this.cursorLocation && this.cursorLocation < this.currentPosition-1){
 		throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_UNICODE);
 	}
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java b/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
index ac52588..c569469 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
@@ -99,7 +99,7 @@
 			if (optionValue instanceof String) {
 				String stringValue = (String) optionValue;
 				if (stringValue.length() > 0){
-					this.fieldPrefixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+					this.fieldPrefixes = this.splitAndTrimOn(',', stringValue.toCharArray());
 				} else {
 					this.fieldPrefixes = null;
 				}
@@ -109,7 +109,7 @@
 			if (optionValue instanceof String) {
 				String stringValue = (String) optionValue;
 				if (stringValue.length() > 0){
-					this.staticFieldPrefixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+					this.staticFieldPrefixes = this.splitAndTrimOn(',', stringValue.toCharArray());
 				} else {
 					this.staticFieldPrefixes = null;
 				}
@@ -119,7 +119,7 @@
 			if (optionValue instanceof String) {
 				String stringValue = (String) optionValue;
 				if (stringValue.length() > 0){
-					this.localPrefixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+					this.localPrefixes = this.splitAndTrimOn(',', stringValue.toCharArray());
 				} else {
 					this.localPrefixes = null;
 				}
@@ -129,7 +129,7 @@
 			if (optionValue instanceof String) {
 				String stringValue = (String) optionValue;
 				if (stringValue.length() > 0){
-					this.argumentPrefixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+					this.argumentPrefixes = this.splitAndTrimOn(',', stringValue.toCharArray());
 				} else {
 					this.argumentPrefixes = null;
 				}
@@ -139,7 +139,7 @@
 			if (optionValue instanceof String) {
 				String stringValue = (String) optionValue;
 				if (stringValue.length() > 0){
-					this.fieldSuffixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+					this.fieldSuffixes = this.splitAndTrimOn(',', stringValue.toCharArray());
 				} else {
 					this.fieldSuffixes = null;
 				}
@@ -149,7 +149,7 @@
 			if (optionValue instanceof String) {
 				String stringValue = (String) optionValue;
 				if (stringValue.length() > 0){
-					this.staticFieldSuffixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+					this.staticFieldSuffixes = this.splitAndTrimOn(',', stringValue.toCharArray());
 				} else {
 					this.staticFieldSuffixes = null;
 				}
@@ -159,7 +159,7 @@
 			if (optionValue instanceof String) {
 				String stringValue = (String) optionValue;
 				if (stringValue.length() > 0){
-					this.localSuffixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+					this.localSuffixes = this.splitAndTrimOn(',', stringValue.toCharArray());
 				} else {
 					this.localSuffixes = null;
 				}
@@ -169,7 +169,7 @@
 			if (optionValue instanceof String) {
 				String stringValue = (String) optionValue;
 				if (stringValue.length() > 0){
-					this.argumentSuffixes = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+					this.argumentSuffixes = this.splitAndTrimOn(',', stringValue.toCharArray());
 				} else {
 					this.argumentSuffixes = null;
 				}
@@ -197,4 +197,21 @@
 			}
 		}
 	}
+	
+	private char[][] splitAndTrimOn(char divider, char[] arrayToSplit) {
+		char[][] result = CharOperation.splitAndTrimOn(',', arrayToSplit);
+		
+		int length = result.length;
+		
+		int resultCount = 0;
+		for (int i = 0; i < length; i++) {
+			if(result[i].length != 0) {
+				result[resultCount++] = result[i];
+			}
+		}
+		if(resultCount != length) {
+			System.arraycopy(result, 0, result = new char[resultCount][], 0, resultCount);
+		}
+		return result;
+	}
 }
diff --git a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionJavadocParser.java b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionJavadocParser.java
index cca0de5..b884420 100644
--- a/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionJavadocParser.java
+++ b/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionJavadocParser.java
@@ -28,7 +28,7 @@
 
 	public SelectionJavadocParser(SelectionParser sourceParser) {
 		super(sourceParser);
-		this.kind = SELECTION_PARSER;
+		this.kind = SELECTION_PARSER | TEXT_PARSE;
 	}
 
 	/*
diff --git a/compiler/org/eclipse/jdt/core/compiler/CharOperation.java b/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
index b6f635d..3f04156 100644
--- a/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
+++ b/compiler/org/eclipse/jdt/core/compiler/CharOperation.java
@@ -1360,16 +1360,85 @@
  * @since 3.0
  */
 public static final boolean equals(char[] first, char[] second, int secondStart, int secondEnd) {
+	return equals(first, second, secondStart, secondEnd, true);
+}
+/**
+ * <p>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 could be either 
+ * case sensitive or case insensitive according to the value of the <code>isCaseSensitive</code> parameter.
+ * </p>
+ * <p>For example:</p>
+ * <ol>
+ * <li><pre>
+ *    first = null
+ *    second = null
+ *    secondStart = 0
+ *    secondEnd = 0
+ *    isCaseSensitive = false
+ *    result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ *    first = { }
+ *    second = null
+ *    secondStart = 0
+ *    secondEnd = 0
+ *    isCaseSensitive = false
+ *    result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ *    first = { 'a' }
+ *    second = { 'a' }
+ *    secondStart = 0
+ *    secondEnd = 1
+ *    isCaseSensitive = true
+ *    result => true
+ * </pre>
+ * </li>
+ * <li><pre>
+ *    first = { 'a' }
+ *    second = { 'A' }
+ *    secondStart = 0
+ *    secondEnd = 1
+ *    isCaseSensitive = true
+ *    result => false
+ * </pre>
+ * </li>
+ * <li><pre>
+ *    first = { 'a' }
+ *    second = { 'A' }
+ *    secondStart = 0
+ *    secondEnd = 1
+ *    isCaseSensitive = false
+ *    result => true
+ * </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
+ * @param isCaseSensitive check whether or not the equality should be case sensitive
+ * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false
+ * @since 3.2
+ */
+public static final boolean equals(char[] first, char[] second, int secondStart, int secondEnd, boolean isCaseSensitive) {
 	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;
+	if (isCaseSensitive) {
+		for (int i = first.length; --i >= 0;)
+			if (first[i] != second[i+secondStart])
+				return false;
+	} else {
+		for (int i = first.length; --i >= 0;)
+			if (Character.toLowerCase(first[i]) != Character.toLowerCase(second[i+secondStart]))
+				return false;
+	}
 	return true;
 }
 
@@ -2586,7 +2655,7 @@
 }
 
 /**
- * Replace all occurrence of characters to be replaced with the remplacement character in the
+ * Replace all occurrences of characters to be replaced with the remplacement character in the
  * given array.
  * <br>
  * <br>
@@ -2608,12 +2677,41 @@
  * @since 3.1
  */
 public static final void replace(char[] array, char[] toBeReplaced, char replacementChar) {
-	for (int i = array.length; --i >= 0;)
+	replace(array, toBeReplaced, replacementChar, 0, array.length);
+}
+
+/**
+ * Replace all occurrences of characters to be replaced with the remplacement character in the
+ * given array from the start position (inclusive) to the end position (exclusive).
+ * <br>
+ * <br>
+ * For example:
+ * <ol>
+ * <li><pre>
+ *    array = { 'a' , 'b', 'b', 'c', 'a', 'b', 'c', 'a' }
+ *    toBeReplaced = { 'b', 'c' }
+ *    replacementChar = 'a'
+ *    start = 4
+ *    end = 8
+ *    result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'c', 'a', 'a', 'a', 'a' }
+ * </pre>
+ * </li>
+ * </ol>
+ * 
+ * @param array the given array
+ * @param toBeReplaced characters to be replaced
+ * @param replacementChar the replacement character
+ * @param start the given start position (inclusive)
+ * @param end  the given end position (exclusive)
+ * @throws NullPointerException if arrays are null.
+ * @since 3.2
+ */
+public static final void replace(char[] array, char[] toBeReplaced, char replacementChar, int start, int end) {
+	for (int i = end; --i >= start;)
 		for (int j = toBeReplaced.length; --j >= 0;)
 			if (array[i] == toBeReplaced[j])
 				array[i] = replacementChar;
 }
-
 /**
  * Answers a new array of characters with substitutions. No side-effect is operated on the original
  * array, in case no substitution happened, then the result is the same as the
diff --git a/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index fd67887..247a697 100644
--- a/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -728,6 +728,7 @@
 	
 	// 1.5 features
 	int UseEnumAsAnIdentifier = Internal + 441;
+	int EnumConstantsCannotBeSurroundedByParenthesis = Syntax + Internal + 442;
 	
 	// detected task
 	/** @since 2.1 */
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index 7f6df98..8785342 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -134,11 +134,6 @@
 		// add its fields
 		FieldBinding[] fields = typeBinding.fields;
 		if ((fields != null) && (fields != NoFields)) {
-			for (int i = 0, max = fields.length; i < max; i++) {
-				if (fields[i].constant() == null) {
-					FieldReference.getConstantFor(fields[i], null, false, null);
-				}
-			}
 			classFile.addFieldInfos();
 		} else {
 			// we have to set the number of fields to be equals to 0
@@ -680,7 +675,8 @@
 		int attributesNumber = 0;
 		// 4.7.2 only static constant fields get a ConstantAttribute
 		// Generate the constantValueAttribute
-		if (fieldBinding.isConstantValue()){
+		Constant fieldConstant = fieldBinding.constant();
+		if (fieldConstant != Constant.NotAConstant){
 			if (contentsOffset + 8 >= contents.length) {
 				resizeContents(8);
 			}
@@ -696,7 +692,6 @@
 			contents[contentsOffset++] = 2;
 			attributesNumber++;
 			// Need to add the constant_value_index
-			Constant fieldConstant = fieldBinding.constant();
 			switch (fieldConstant.typeID()) {
 				case T_boolean :
 					int booleanValueIndex =
diff --git a/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java b/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
index 6169efb..7bb858e 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
@@ -57,6 +57,7 @@
 	private int maxProblemPerUnit;
 	public char[][][] qualifiedReferences;
 	public char[][] simpleNameReferences;
+	public boolean declaresAnnotations = false;
 
 	public int lineSeparatorPositions[];
 	public Map compiledTypes = new Hashtable(11);
diff --git a/compiler/org/eclipse/jdt/internal/compiler/Compiler.java b/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
index b85ad9c..86f3114 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
@@ -158,6 +158,7 @@
 
 		// create a problem handler given a handling policy
 		this.options = new CompilerOptions(settings);
+		this.options.parseLiteralExpressionsAsConstants = parseLiteralExpressionsAsConstants;
 		
 		// wrap requestor in DebugRequestor if one is specified
 		if(DebugRequestor == null) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
index 6d3763d..1efcead 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
@@ -29,8 +29,8 @@
 	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
 
 		Constant cst = this.left.optimizedBooleanConstant();
-		boolean isLeftOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
-		boolean isLeftOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+		boolean isLeftOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
+		boolean isLeftOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;
 
 		if (isLeftOptimizedTrue) {
 			// TRUE && anything
@@ -81,7 +81,7 @@
 			return;
 		}
 		Constant cst = right.constant;
-		if (cst != NotAConstant) {
+		if (cst != Constant.NotAConstant) {
 			// <expr> && true --> <expr>
 			if (cst.booleanValue() == true) {
 				this.left.generateCode(currentScope, codeStream, valueRequired);
@@ -101,11 +101,11 @@
 		
 		Label falseLabel = new Label(codeStream), endLabel;
 		cst = left.optimizedBooleanConstant();
-		boolean leftIsConst = cst != NotAConstant;
+		boolean leftIsConst = cst != Constant.NotAConstant;
 		boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
 
 		cst = right.optimizedBooleanConstant();
-		boolean rightIsConst = cst != NotAConstant;
+		boolean rightIsConst = cst != Constant.NotAConstant;
 		boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
 
 		generateOperands : {
@@ -184,7 +184,7 @@
 
 		// <expr> && true --> <expr>
 		Constant cst = right.constant;
-		if (cst != NotAConstant && cst.booleanValue() == true) {
+		if (cst != Constant.NotAConstant && cst.booleanValue() == true) {
 			int pc = codeStream.position;
 			this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
 			if (mergedInitStateIndex != -1) {
@@ -194,11 +194,11 @@
 			return;
 		}
 		cst = left.optimizedBooleanConstant();
-		boolean leftIsConst = cst != NotAConstant;
+		boolean leftIsConst = cst != Constant.NotAConstant;
 		boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
 
 		cst = right.optimizedBooleanConstant();
-		boolean rightIsConst = cst != NotAConstant;
+		boolean rightIsConst = cst != Constant.NotAConstant;
 		boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
 
 		// default case
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 339dc80..f5e3a8f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -12,7 +12,6 @@
 
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
-import org.eclipse.jdt.internal.compiler.impl.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 
@@ -20,23 +19,20 @@
 	
 	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) | supertype ref (type ref)
-	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 Bit6 = 0x20; 						// depth (name ref, msg) | ignore need cast check (cast expression)
 	public final static int Bit7 = 0x40; 						// depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement)
 	public final static int Bit8 = 0x80; 						// depth (name ref, msg) | operator (operator) | unsafe cast (cast expression)
 	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) | has abstract methods (type decl)
-	public final static int Bit13 = 0x1000; 				// depth (name ref, msg) 
+	public final static int Bit13 = 0x1000; 				// depth (name ref, msg) | is secondary type (type decl)
 	public final static int Bit14 = 0x2000; 				// strictly assigned (reference lhs)
 	public final static int Bit15 = 0x4000; 				// is unnecessary cast (expression) | is varargs (type ref)
 	public final static int Bit16 = 0x8000; 				// in javadoc comment (name ref, type ref, msg)
@@ -92,7 +88,6 @@
 
 	// for binary expressions
 	public static final int IsReturnedValue = Bit5; 
-	public static final int OnlyValueRequired = Bit6; 
 
 	// for cast expressions
 	public static final int UnnecessaryCast = Bit15;
@@ -122,7 +117,8 @@
 	public static final int IsAnonymousType = Bit10; // used to test for anonymous 
 	public static final int IsMemberType = Bit11; // local member do not know it is local at parse time (need to look at binding)
 	public static final int HasAbstractMethods = Bit12; // used to promote abstract enums
-	
+	public static final int IsSecondaryType = Bit13; // used to test for secondary
+
 	// for type, method and field declarations 
 	public static final int HasLocalType = Bit2; // cannot conflict with AddAssertionMASK
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index 2e96c2d..24aca94 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -413,6 +413,13 @@
 			resolveJavadoc();
 			resolveAnnotations(scope, this.annotations, this.binding);
 			resolveStatements();
+			// check @Deprecated annotation presence
+			if (this.binding != null
+					&& (this.binding.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0
+					&& (this.binding.modifiers & ClassFileConstants.AccDeprecated) != 0
+					&& this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
+				this.scope.problemReporter().missingDeprecatedAnnotationForMethod(this);
+			}			
 		} catch (AbortMethod e) {	// ========= abort on fatal error =============
 			this.ignoreFurtherInvestigation = true;
 		} 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 7ff4da1..edcee96 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -14,6 +14,7 @@
 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.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class AllocationExpression extends Expression implements InvocationSite {
@@ -233,10 +234,10 @@
 	public TypeBinding resolveType(BlockScope scope) {
 
 		// Propagate the type checking to the arguments, and check if the constructor is defined.
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		if (this.type == null) {
 			// initialization of an enum constant
-			this.resolvedType = scope.enclosingSourceType();
+			this.resolvedType = scope.enclosingReceiverType();
 		} else {
 			this.resolvedType = this.type.resolveType(scope, true /* check bounds*/);
 			checkParameterizedAllocation: {
@@ -293,6 +294,13 @@
 				}
 			}
 			if (argHasError) {
+				if (this.resolvedType instanceof ReferenceBinding) {
+					// record a best guess, for clients who need hint about possible contructor match
+					TypeBinding[] pseudoArgs = new TypeBinding[length];
+					for (int i = length; --i >= 0;)
+						pseudoArgs[i] = argumentTypes[i] == null ? this.resolvedType : argumentTypes[i]; // replace args with errors with receiver
+					this.binding = scope.findMethod((ReferenceBinding) this.resolvedType, TypeConstants.INIT, pseudoArgs, this);
+				}
 				return this.resolvedType;
 			}
 		}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
index bd2d115..6dc334c 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
@@ -216,7 +216,7 @@
 		if(this.compilerAnnotation != null)
 			return this.resolvedType;		
 		
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		
 		TypeBinding typeBinding = this.type.resolveType(scope);
 		if (typeBinding == null){	
@@ -238,7 +238,11 @@
 		MemberValuePair valueAttribute = null; // remember the first 'value' pair
 		MemberValuePair[] pairs;
 		int pairsLength = originalValuePairs.length;
-		System.arraycopy(originalValuePairs, 0, pairs = new MemberValuePair[pairsLength], 0, pairsLength);
+		if (pairsLength > 0) {
+			System.arraycopy(originalValuePairs, 0, pairs = new MemberValuePair[pairsLength], 0, pairsLength);
+		} else {
+			pairs = originalValuePairs;
+		}		
 		
 		nextMember: for (int i = 0, requiredLength = methods.length; i < requiredLength; i++) {
 			MethodBinding method = methods[i];
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
index eb3ba27..c2aa924 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class Argument extends LocalDeclaration {
@@ -100,7 +101,7 @@
 
 		TypeBinding exceptionType = this.type.resolveType(scope, true /* check bounds*/);
 		if (exceptionType == null) return null;
-		if (exceptionType.isGenericType() || exceptionType.isBoundParameterizedType()) {
+		if (exceptionType.isBoundParameterizedType()) {
 			scope.problemReporter().invalidParameterizedExceptionType(exceptionType, this);
 			return null;
 		}
@@ -127,7 +128,7 @@
 		resolveAnnotations(scope, this.annotations, this.binding);
 		
 		scope.addLocalVariable(binding);
-		binding.setConstant(NotAConstant);
+		binding.setConstant(Constant.NotAConstant);
 		return exceptionType;
 	}
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
index 514a763..f2e0343 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
@@ -14,6 +14,7 @@
 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.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class ArrayInitializer extends Expression {
@@ -54,7 +55,7 @@
 			int elementsTypeID = binding.dimensions > 1 ? -1 : binding.leafComponentType.id;
 			for (int i = 0; i < expressionLength; i++) {
 				Expression expr;
-				if ((expr = expressions[i]).constant != NotAConstant) {
+				if ((expr = expressions[i]).constant != Constant.NotAConstant) {
 					switch (elementsTypeID) { // filter out initializations to default values
 						case T_int :
 						case T_short :
@@ -136,12 +137,12 @@
 	
 		// this method is recursive... (the test on isArrayType is the stop case)
 	
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		
 		// allow new List<?>[5]
 		if ((this.bits & IsAnnotationDefaultValue) == 0) { // annotation default value need only to be commensurate JLS9.7
 			TypeBinding leafComponentType = expectedType.leafComponentType();
-			if (leafComponentType.isBoundParameterizedType() || leafComponentType.isGenericType() || leafComponentType.isTypeVariable()) {
+			if (leafComponentType.isBoundParameterizedType() || leafComponentType.isTypeVariable()) {
 			    scope.problemReporter().illegalGenericArray(leafComponentType, this);
 			}
 		}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
index 2f839c0..33094c5 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
@@ -51,8 +51,8 @@
 		preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
 
 		Constant cst = this.assertExpression.optimizedBooleanConstant();		
-		boolean isOptimizedTrueAssertion = cst != NotAConstant && cst.booleanValue() == true;
-		boolean isOptimizedFalseAssertion = cst != NotAConstant && cst.booleanValue() == false;
+		boolean isOptimizedTrueAssertion = cst != Constant.NotAConstant && cst.booleanValue() == true;
+		boolean isOptimizedFalseAssertion = cst != Constant.NotAConstant && cst.booleanValue() == false;
 
 		FlowInfo assertInfo = flowInfo.copy();
 		if (isOptimizedTrueAssertion) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index 344336e..c012960 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -15,6 +15,7 @@
 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.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class Assignment extends Expression {
@@ -176,7 +177,7 @@
 	public TypeBinding resolveType(BlockScope scope) {
 
 		// due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		if (!(this.lhs instanceof Reference) || this.lhs.isThis()) {
 			scope.problemReporter().expressionShouldBeAVariable(this.lhs);
 			return null;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
index 6d22966..8b0ea97 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
@@ -86,14 +86,12 @@
 		boolean valueRequired) {
 
 		int pc = codeStream.position;
-		Label falseLabel, endLabel;
 		if (constant != Constant.NotAConstant) {
 			if (valueRequired)
 				codeStream.generateConstant(constant, implicitConversion);
 			codeStream.recordPositionsFrom(pc, this.sourceStart);
 			return;
 		}
-		bits |= OnlyValueRequired;
 		switch ((bits & OperatorMASK) >> OperatorSHIFT) {
 			case PLUS :
 				switch (bits & ReturnTypeIDMASK) {
@@ -295,33 +293,8 @@
 						}
 						break;
 					case T_boolean : // logical and
-						generateOptimizedLogicalAnd(
-							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 & IsReturnedValue) != 0) {
-									codeStream.generateImplicitConversion(this.implicitConversion);
-									codeStream.generateReturnBytecode(this);
-									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();
-							}
-						}
+						generateLogicalAnd(currentScope, codeStream, valueRequired);
+						break;
 				}
 				break;
 			case OR :
@@ -367,33 +340,8 @@
 						}
 						break;
 					case T_boolean : // logical or
-						generateOptimizedLogicalOr(
-							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 & IsReturnedValue) != 0) {
-									codeStream.generateImplicitConversion(this.implicitConversion);
-									codeStream.generateReturnBytecode(this);
-									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();
-							}
-						}
+						generateLogicalOr(currentScope, codeStream, valueRequired);
+						break;
 				}
 				break;
 			case XOR :
@@ -439,33 +387,8 @@
 						}
 						break;
 					case T_boolean :
-						generateOptimizedLogicalXor(
-							currentScope,
-							codeStream,
-							null,
-							(falseLabel = new Label(codeStream)),
-							valueRequired);
-						/* improving code gen for such a case: boolean b = i < 0 ^ bool;
-						 * 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 & IsReturnedValue) != 0) {
-									codeStream.generateImplicitConversion(this.implicitConversion);
-									codeStream.generateReturnBytecode(this);
-									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();
-							}
-						}
+						generateLogicalXor(currentScope, 	codeStream, valueRequired);
+						break;
 				}
 				break;
 			case LEFT_SHIFT :
@@ -514,6 +437,7 @@
 				}
 				break;
 			case GREATER :
+				Label falseLabel, endLabel;
 				generateOptimizedGreaterThan(
 					currentScope,
 					codeStream,
@@ -711,7 +635,7 @@
 		// both sides got promoted in the same way
 		if (promotedTypeID == T_int) {
 			// 0 > x
-			if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+			if ((left.constant != Constant.NotAConstant) && (left.constant.intValue() == 0)) {
 				right.generateCode(currentScope, codeStream, valueRequired);
 				if (valueRequired) {
 					if (falseLabel == null) {
@@ -733,7 +657,7 @@
 				return;
 			}
 			// x > 0
-			if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
+			if ((right.constant != Constant.NotAConstant) && (right.constant.intValue() == 0)) {
 				left.generateCode(currentScope, codeStream, valueRequired);
 				if (valueRequired) {
 					if (falseLabel == null) {
@@ -825,7 +749,7 @@
 		// both sides got promoted in the same way
 		if (promotedTypeID == T_int) {
 			// 0 >= x
-			if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+			if ((left.constant != Constant.NotAConstant) && (left.constant.intValue() == 0)) {
 				right.generateCode(currentScope, codeStream, valueRequired);
 				if (valueRequired) {
 					if (falseLabel == null) {
@@ -847,7 +771,7 @@
 				return;
 			}
 			// x >= 0
-			if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
+			if ((right.constant != Constant.NotAConstant) && (right.constant.intValue() == 0)) {
 				left.generateCode(currentScope, codeStream, valueRequired);
 				if (valueRequired) {
 					if (falseLabel == null) {
@@ -939,7 +863,7 @@
 		// both sides got promoted in the same way
 		if (promotedTypeID == T_int) {
 			// 0 < x
-			if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+			if ((left.constant != Constant.NotAConstant) && (left.constant.intValue() == 0)) {
 				right.generateCode(currentScope, codeStream, valueRequired);
 				if (valueRequired) {
 					if (falseLabel == null) {
@@ -960,7 +884,7 @@
 				return;
 			}
 			// x < 0
-			if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
+			if ((right.constant != Constant.NotAConstant) && (right.constant.intValue() == 0)) {
 				left.generateCode(currentScope, codeStream, valueRequired);
 				if (valueRequired) {
 					if (falseLabel == null) {
@@ -1049,7 +973,7 @@
 		// both sides got promoted in the same way
 		if (promotedTypeID == T_int) {
 			// 0 <= x
-			if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+			if ((left.constant != Constant.NotAConstant) && (left.constant.intValue() == 0)) {
 				right.generateCode(currentScope, codeStream, valueRequired);
 				if (valueRequired) {
 					if (falseLabel == null) {
@@ -1071,7 +995,7 @@
 				return;
 			}
 			// x <= 0
-			if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
+			if ((right.constant != Constant.NotAConstant) && (right.constant.intValue() == 0)) {
 				left.generateCode(currentScope, codeStream, valueRequired);
 				if (valueRequired) {
 					if (falseLabel == null) {
@@ -1152,6 +1076,167 @@
 	/**
 	 * Boolean generation for &
 	 */
+	public void generateLogicalAnd(
+		BlockScope currentScope,
+		CodeStream codeStream,
+		boolean valueRequired) {
+			
+		Constant condConst;
+		if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
+			if ((condConst = left.optimizedBooleanConstant()) != Constant.NotAConstant) {
+				if (condConst.booleanValue() == true) {
+					// <something equivalent to true> & x
+					left.generateCode(currentScope, codeStream, false);
+					right.generateCode(currentScope, codeStream, valueRequired);
+				} else {
+					// <something equivalent to false> & x
+					left.generateCode(currentScope, codeStream, false);
+					right.generateCode(currentScope, codeStream, false);
+					if (valueRequired) {
+						codeStream.iconst_0();
+					}
+					// reposition the endPC
+					codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);					
+				}
+				return;
+			} 
+			if ((condConst = right.optimizedBooleanConstant()) != Constant.NotAConstant) {
+				if (condConst.booleanValue() == true) {
+					// x & <something equivalent to true>
+					left.generateCode(currentScope, codeStream, valueRequired);
+					right.generateCode(currentScope, codeStream, false);
+				} else {
+					// x & <something equivalent to false>
+					left.generateCode(currentScope, codeStream, false);
+					right.generateCode(currentScope, codeStream, false);
+					if (valueRequired) {
+						codeStream.iconst_0();
+					}
+					// reposition the endPC
+					codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);					
+				}
+				return;
+			}
+		}
+		// default case
+		left.generateCode(currentScope, codeStream, valueRequired);
+		right.generateCode(currentScope, codeStream, valueRequired);
+		if (valueRequired) {
+			codeStream.iand();
+		}
+		// reposition the endPC
+		codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);					
+	}
+	
+	/**
+	 * Boolean generation for |
+	 */
+	public void generateLogicalOr(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+			
+		Constant condConst;
+		if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
+			if ((condConst = left.optimizedBooleanConstant()) != Constant.NotAConstant) {
+				if (condConst.booleanValue() == true) {
+					// <something equivalent to true> | x
+					left.generateCode(currentScope, codeStream, false);
+					right.generateCode(currentScope, codeStream, false);
+					if (valueRequired) {
+						codeStream.iconst_1();
+					}
+					// reposition the endPC
+					codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);					
+				} else {
+					// <something equivalent to false> | x
+					left.generateCode(currentScope, codeStream, false);
+					right.generateCode(currentScope, codeStream, valueRequired);
+				}
+				return;
+			}
+			if ((condConst = right.optimizedBooleanConstant()) != Constant.NotAConstant) {
+				if (condConst.booleanValue() == true) {
+					// x | <something equivalent to true>
+					left.generateCode(currentScope, codeStream, false);
+					right.generateCode(currentScope, codeStream, false);
+					if (valueRequired) {
+						codeStream.iconst_1();
+					}
+					// reposition the endPC
+					codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);					
+				} else {
+					// x | <something equivalent to false>
+					left.generateCode(currentScope, codeStream, valueRequired);
+					right.generateCode(currentScope, codeStream, false);
+				}
+				return;
+			}
+		}
+		// default case
+		left.generateCode(currentScope, codeStream, valueRequired);
+		right.generateCode(currentScope, codeStream, valueRequired);
+		if (valueRequired) {
+			codeStream.ior();
+		}
+		// reposition the endPC
+		codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);					
+	}
+	
+	/**
+	 * Boolean generation for ^
+	 */
+	public void generateLogicalXor(BlockScope currentScope,	CodeStream codeStream, boolean valueRequired) {
+			
+		Constant condConst;
+		if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
+			if ((condConst = left.optimizedBooleanConstant()) != Constant.NotAConstant) {
+				if (condConst.booleanValue() == true) {
+					// <something equivalent to true> ^ x
+					left.generateCode(currentScope, codeStream, false);
+					if (valueRequired) {
+						codeStream.iconst_1();
+					}
+					right.generateCode(currentScope, codeStream, valueRequired);
+					if (valueRequired) {
+						codeStream.ixor(); // negate
+						codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);					
+					}
+				} else {
+					// <something equivalent to false> ^ x
+					left.generateCode(currentScope, codeStream, false);
+					right.generateCode(currentScope, codeStream, valueRequired);
+				}
+				return;
+			}
+			if ((condConst = right.optimizedBooleanConstant()) != Constant.NotAConstant) {
+				if (condConst.booleanValue() == true) {
+					// x ^ <something equivalent to true>
+					left.generateCode(currentScope, codeStream, valueRequired);
+					right.generateCode(currentScope, codeStream, false);
+					if (valueRequired) {
+						codeStream.iconst_1();
+						codeStream.ixor(); // negate
+						codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);					
+					}
+				} else {
+					// x ^ <something equivalent to false>
+					left.generateCode(currentScope, codeStream, valueRequired);
+					right.generateCode(currentScope, codeStream, false);
+				}
+				return;
+			}
+		}
+		// default case
+		left.generateCode(currentScope, codeStream, valueRequired);
+		right.generateCode(currentScope, codeStream, valueRequired);
+		if (valueRequired) {
+			codeStream.ixor();
+		}
+		// reposition the endPC
+		codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);					
+	}	
+	
+	/**
+	 * Boolean generation for &
+	 */
 	public void generateOptimizedLogicalAnd(
 		BlockScope currentScope,
 		CodeStream codeStream,
@@ -1161,7 +1246,7 @@
 			
 		Constant condConst;
 		if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
-			if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
+			if ((condConst = left.optimizedBooleanConstant()) != Constant.NotAConstant) {
 				if (condConst.booleanValue() == true) {
 					// <something equivalent to true> & x
 					left.generateOptimizedBoolean(
@@ -1170,16 +1255,12 @@
 						trueLabel,
 						falseLabel,
 						false);
-					if ((bits & OnlyValueRequired) != 0) {
-						right.generateCode(currentScope, codeStream, valueRequired);
-					} else {
-						right.generateOptimizedBoolean(
-							currentScope,
-							codeStream,
-							trueLabel,
-							falseLabel,
-							valueRequired);
-					}
+					right.generateOptimizedBoolean(
+						currentScope,
+						codeStream,
+						trueLabel,
+						falseLabel,
+						valueRequired);
 				} else {
 					// <something equivalent to false> & x
 					left.generateOptimizedBoolean(
@@ -1188,22 +1269,16 @@
 						trueLabel,
 						falseLabel,
 						false);
-					Label internalTrueLabel = new Label(codeStream);
 					right.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
 						trueLabel,
 						falseLabel,
 						false);
-					internalTrueLabel.place();
 					if (valueRequired) {
-						if ((bits & OnlyValueRequired) != 0) {
-							codeStream.iconst_0();
-						} else {
-							if (falseLabel != null) {
-								// implicit falling through the TRUE case
-								codeStream.goto_(falseLabel);
-							}
+						if (falseLabel != null) {
+							// implicit falling through the TRUE case
+							codeStream.goto_(falseLabel);
 						}
 					}
 					// reposition the endPC
@@ -1211,19 +1286,15 @@
 				}
 				return;
 			}
-			if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
+			if ((condConst = right.optimizedBooleanConstant()) != Constant.NotAConstant) {
 				if (condConst.booleanValue() == true) {
 					// x & <something equivalent to true>
-					if ((bits & OnlyValueRequired) != 0) {
-						left.generateCode(currentScope, codeStream, valueRequired);
-					} else {
-						left.generateOptimizedBoolean(
-							currentScope,
-							codeStream,
-							trueLabel,
-							falseLabel,
-							valueRequired);
-					}
+					left.generateOptimizedBoolean(
+						currentScope,
+						codeStream,
+						trueLabel,
+						falseLabel,
+						valueRequired);
 					right.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
@@ -1247,13 +1318,9 @@
 						falseLabel,
 						false);
 					if (valueRequired) {
-						if ((bits & OnlyValueRequired) != 0) {
-							codeStream.iconst_0();
-						} else {
-							if (falseLabel != null) {
-								// implicit falling through the TRUE case
-								codeStream.goto_(falseLabel);
-							}
+						if (falseLabel != null) {
+							// implicit falling through the TRUE case
+							codeStream.goto_(falseLabel);
 						}
 					}
 					// reposition the endPC
@@ -1267,19 +1334,17 @@
 		right.generateCode(currentScope, codeStream, valueRequired);
 		if (valueRequired) {
 			codeStream.iand();
-			if ((bits & OnlyValueRequired) == 0) {
-				if (falseLabel == null) {
-					if (trueLabel != null) {
-						// implicit falling through the FALSE case
-						codeStream.ifne(trueLabel);
-					}
+			if (falseLabel == null) {
+				if (trueLabel != null) {
+					// implicit falling through the FALSE case
+					codeStream.ifne(trueLabel);
+				}
+			} else {
+				// implicit falling through the TRUE case
+				if (trueLabel == null) {
+					codeStream.ifeq(falseLabel);
 				} else {
-					// implicit falling through the TRUE case
-					if (trueLabel == null) {
-						codeStream.ifeq(falseLabel);
-					} else {
-						// no implicit fall through TRUE/FALSE --> should never occur
-					}
+					// no implicit fall through TRUE/FALSE --> should never occur
 				}
 			}
 		}
@@ -1299,7 +1364,7 @@
 			
 		Constant condConst;
 		if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
-			if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
+			if ((condConst = left.optimizedBooleanConstant()) != Constant.NotAConstant) {
 				if (condConst.booleanValue() == true) {
 					// <something equivalent to true> | x
 					left.generateOptimizedBoolean(
@@ -1317,12 +1382,8 @@
 						false);
 					internalFalseLabel.place();
 					if (valueRequired) {
-						if ((bits & OnlyValueRequired) != 0) {
-							codeStream.iconst_1();
-						} else {
-							if (trueLabel != null) {
-								codeStream.goto_(trueLabel);
-							}
+						if (trueLabel != null) {
+							codeStream.goto_(trueLabel);
 						}
 					}
 					// reposition the endPC
@@ -1335,20 +1396,16 @@
 						trueLabel,
 						falseLabel,
 						false);
-					if ((bits & OnlyValueRequired) != 0) {
-						right.generateCode(currentScope, codeStream, valueRequired);
-					} else {
-						right.generateOptimizedBoolean(
-							currentScope,
-							codeStream,
-							trueLabel,
-							falseLabel,
-							valueRequired);
-					}
+					right.generateOptimizedBoolean(
+						currentScope,
+						codeStream,
+						trueLabel,
+						falseLabel,
+						valueRequired);
 				}
 				return;
 			}
-			if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
+			if ((condConst = right.optimizedBooleanConstant()) != Constant.NotAConstant) {
 				if (condConst.booleanValue() == true) {
 					// x | <something equivalent to true>
 					Label internalFalseLabel = new Label(codeStream);
@@ -1366,28 +1423,20 @@
 						falseLabel,
 						false);
 					if (valueRequired) {
-						if ((bits & OnlyValueRequired) != 0) {
-							codeStream.iconst_1();
-						} else {
-							if (trueLabel != null) {
-								codeStream.goto_(trueLabel);
-							}
+						if (trueLabel != null) {
+							codeStream.goto_(trueLabel);
 						}
 					}
 					// reposition the endPC
 					codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);					
 				} else {
 					// x | <something equivalent to false>
-					if ((bits & OnlyValueRequired) != 0) {
-						left.generateCode(currentScope, codeStream, valueRequired);
-					} else {
-						left.generateOptimizedBoolean(
-							currentScope,
-							codeStream,
-							trueLabel,
-							falseLabel,
-							valueRequired);
-					}
+					left.generateOptimizedBoolean(
+						currentScope,
+						codeStream,
+						trueLabel,
+						falseLabel,
+						valueRequired);
 					right.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
@@ -1403,19 +1452,17 @@
 		right.generateCode(currentScope, codeStream, valueRequired);
 		if (valueRequired) {
 			codeStream.ior();
-			if ((bits & OnlyValueRequired) == 0) {
-				if (falseLabel == null) {
-					if (trueLabel != null) {
-						// implicit falling through the FALSE case
-						codeStream.ifne(trueLabel);
-					}
+			if (falseLabel == null) {
+				if (trueLabel != null) {
+					// implicit falling through the FALSE case
+					codeStream.ifne(trueLabel);
+				}
+			} else {
+				// implicit falling through the TRUE case
+				if (trueLabel == null) {
+					codeStream.ifeq(falseLabel);
 				} else {
-					// implicit falling through the TRUE case
-					if (trueLabel == null) {
-						codeStream.ifeq(falseLabel);
-					} else {
-						// no implicit fall through TRUE/FALSE --> should never occur
-					}
+					// no implicit fall through TRUE/FALSE --> should never occur
 				}
 			}
 		}
@@ -1435,7 +1482,7 @@
 			
 		Constant condConst;
 		if ((left.implicitConversion & COMPILE_TYPE_MASK) == T_boolean) {
-			if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
+			if ((condConst = left.optimizedBooleanConstant()) != Constant.NotAConstant) {
 				if (condConst.booleanValue() == true) {
 					// <something equivalent to true> ^ x
 					left.generateOptimizedBoolean(
@@ -1447,7 +1494,7 @@
 					right.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
-						falseLabel,
+						falseLabel, // negating
 						trueLabel,
 						valueRequired);
 				} else {
@@ -1458,26 +1505,22 @@
 						trueLabel,
 						falseLabel,
 						false);
-					if ((bits & OnlyValueRequired) != 0) {
-						right.generateCode(currentScope, codeStream, valueRequired);
-					} else {
-						right.generateOptimizedBoolean(
-							currentScope,
-							codeStream,
-							trueLabel,
-							falseLabel,
-							valueRequired);
-					}
+					right.generateOptimizedBoolean(
+						currentScope,
+						codeStream,
+						trueLabel,
+						falseLabel,
+						valueRequired);
 				}
 				return;
 			}
-			if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
+			if ((condConst = right.optimizedBooleanConstant()) != Constant.NotAConstant) {
 				if (condConst.booleanValue() == true) {
 					// x ^ <something equivalent to true>
 					left.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
-						falseLabel,
+						falseLabel, // negating
 						trueLabel,
 						valueRequired);
 					right.generateOptimizedBoolean(
@@ -1488,16 +1531,12 @@
 						false);
 				} else {
 					// x ^ <something equivalent to false>
-					if ((bits & OnlyValueRequired) != 0) {
-						left.generateCode(currentScope, codeStream, valueRequired);
-					} else {
-						left.generateOptimizedBoolean(
-							currentScope,
-							codeStream,
-							trueLabel,
-							falseLabel,
-							valueRequired);
-					}
+					left.generateOptimizedBoolean(
+						currentScope,
+						codeStream,
+						trueLabel,
+						falseLabel,
+						valueRequired);
 					right.generateOptimizedBoolean(
 						currentScope,
 						codeStream,
@@ -1513,19 +1552,17 @@
 		right.generateCode(currentScope, codeStream, valueRequired);
 		if (valueRequired) {
 			codeStream.ixor();
-			if ((bits & OnlyValueRequired) == 0) {
-				if (falseLabel == null) {
-					if (trueLabel != null) {
-						// implicit falling through the FALSE case
-						codeStream.ifne(trueLabel);
-					}
+			if (falseLabel == null) {
+				if (trueLabel != null) {
+					// implicit falling through the FALSE case
+					codeStream.ifne(trueLabel);
+				}
+			} else {
+				// implicit falling through the TRUE case
+				if (trueLabel == null) {
+					codeStream.ifeq(falseLabel);
 				} else {
-					// implicit falling through the TRUE case
-					if (trueLabel == null) {
-						codeStream.ifeq(falseLabel);
-					} else {
-						// no implicit fall through TRUE/FALSE --> should never occur
-					}
+					// no implicit fall through TRUE/FALSE --> should never occur
 				}
 			}
 		}
@@ -1545,7 +1582,7 @@
 
 		if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
 			&& ((bits & ReturnTypeIDMASK) == T_JavaLangString)) {
-			if (constant != NotAConstant) {
+			if (constant != Constant.NotAConstant) {
 				codeStream.generateConstant(constant, implicitConversion);
 				codeStream.invokeStringConcatenationAppendForType(implicitConversion & COMPILE_TYPE_MASK);
 			} else {
@@ -1579,7 +1616,7 @@
 
 		if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
 			&& ((bits & ReturnTypeIDMASK) == T_JavaLangString)) {
-			if (constant != NotAConstant) {
+			if (constant != Constant.NotAConstant) {
 				codeStream.newStringContatenation(); // new: java.lang.StringBuffer
 				codeStream.dup();
 				codeStream.ldc(constant.stringValue());
@@ -1617,19 +1654,19 @@
 					return;
 			case AND_AND :
 				Constant cst;
-				if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
+				if ((cst = left.optimizedBooleanConstant()) != Constant.NotAConstant) {
 					if (cst.booleanValue() == false) { // left is equivalent to false
 						optimizedBooleanConstant = cst; // constant(false)
 						return;
 					} else { //left is equivalent to true
-						if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+						if ((cst = right.optimizedBooleanConstant()) != Constant.NotAConstant) {
 							optimizedBooleanConstant = cst;
 							// the conditional result is equivalent to the right conditional value
 						}
 						return;
 					}
 				}
-				if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+				if ((cst = right.optimizedBooleanConstant()) != Constant.NotAConstant) {
 					if (cst.booleanValue() == false) { // right is equivalent to false
 						optimizedBooleanConstant = cst; // constant(false)
 					}
@@ -1639,18 +1676,18 @@
 				if ((leftId != T_boolean) || (rightId != T_boolean))
 					return;
 			case OR_OR :
-				if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
+				if ((cst = left.optimizedBooleanConstant()) != Constant.NotAConstant) {
 					if (cst.booleanValue() == true) { // left is equivalent to true
 						optimizedBooleanConstant = cst; // constant(true)
 						return;
 					} else { //left is equivalent to false
-						if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+						if ((cst = right.optimizedBooleanConstant()) != Constant.NotAConstant) {
 							optimizedBooleanConstant = cst;
 						}
 						return;
 					}
 				}
-				if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+				if ((cst = right.optimizedBooleanConstant()) != Constant.NotAConstant) {
 					if (cst.booleanValue() == true) { // right is equivalent to true
 						optimizedBooleanConstant = cst; // constant(true)
 					}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
index 7949f51..b1e60b6 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
@@ -35,7 +35,7 @@
 		FlowInfo flowInfo) {
 
 		if (constantExpression != null) {
-			if (!this.isEnumConstant && constantExpression.constant == NotAConstant) {
+			if (!this.isEnumConstant && constantExpression.constant == Constant.NotAConstant) {
 				currentScope.problemReporter().caseExpressionMustBeConstant(constantExpression);
 			}
 			this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
@@ -94,7 +94,7 @@
 	
 			// on error the last default will be the selected one ...	
 			switchStatement.defaultCase = this;
-			return NotAConstant;
+			return Constant.NotAConstant;
 		}
 		// add into the collection of cases of the associated switch statement
 		switchStatement.cases[switchStatement.caseCount++] = this;
@@ -103,11 +103,15 @@
 			((SingleNameReference) constantExpression).setActualReceiverType((ReferenceBinding)switchExpressionType);
 		}
 		TypeBinding caseType = constantExpression.resolveType(scope);
-		if (caseType == null || switchExpressionType == null) return NotAConstant;
+		if (caseType == null || switchExpressionType == null) return Constant.NotAConstant;
 		if (constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchExpressionType)
 				|| caseType.isCompatibleWith(switchExpressionType)) {
 			if (caseType.isEnum()) {
 				this.isEnumConstant = true;
+				if (((this.constantExpression.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) != 0) {
+					scope.problemReporter().enumConstantsCannotBeSurroundedByParenthesis(this.constantExpression);
+				}
+
 				if (constantExpression instanceof NameReference
 						&& (constantExpression.bits & RestrictiveFlagMASK) == Binding.FIELD) {
 					NameReference reference = (NameReference) constantExpression;
@@ -127,7 +131,7 @@
 			return constantExpression.constant;
 		}
 		scope.problemReporter().typeMismatchError(caseType, switchExpressionType, constantExpression);
-		return NotAConstant;
+		return Constant.NotAConstant;
 	}
 
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index 0826979..44c0222 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -271,9 +271,7 @@
 		}
 		if (match != null && (
 				castType.isBoundParameterizedType() 
-				|| castType.isGenericType() 
-				|| 	expressionType.isBoundParameterizedType() 
-				|| expressionType.isGenericType())) {
+				|| 	expressionType.isBoundParameterizedType())) {
 			
 			if (match.isProvablyDistinctFrom(isNarrowing ? expressionType : castType, 0)) {
 				return false; 
@@ -283,15 +281,14 @@
 				return true;
 			}
 			if ((castType.tagBits & TagBits.HasDirectWildcard) == 0) {
-				if ((!match.isParameterizedType() && !match.isGenericType())
-						|| expressionType.isRawType()) {
+				if (!match.isParameterizedType() || expressionType.isRawType()) {
 					this.bits |= UnsafeCast;
 					return true;
 				}
 			}
 		} else if (isNarrowing) {
 			TypeBinding leafType = castType.leafComponentType();
-			if (expressionType.id == T_JavaLangObject && castType.isArrayType() && (leafType.isBoundParameterizedType() || leafType.isGenericType())) {
+			if (expressionType.id == T_JavaLangObject && castType.isArrayType() && leafType.isBoundParameterizedType()) {
 				this.bits |= UnsafeCast;
 				return true;
 			}
@@ -320,7 +317,7 @@
 	
 		int pc = codeStream.position;
 		boolean needRuntimeCheckcast = (this.bits & GenerateCheckcast) != 0;
-		if (constant != NotAConstant) {
+		if (constant != Constant.NotAConstant) {
 			if (valueRequired || needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check
 				codeStream.generateConstant(constant, implicitConversion);
 				if (needRuntimeCheckcast) {
@@ -339,7 +336,8 @@
 			currentScope,
 			codeStream,
 			valueRequired || needRuntimeCheckcast);
-		if (needRuntimeCheckcast) {
+		if (needRuntimeCheckcast 
+				&& this.expression.generatedType(currentScope) != this.resolvedType) { // no need to issue a checkcast if already done as genericCast
 			codeStream.checkcast(this.resolvedType);
 			if (valueRequired) {
 				codeStream.generateImplicitConversion(implicitConversion);
@@ -381,7 +379,7 @@
 			case T_JavaLangBoolean :
 				return this.expression.optimizedBooleanConstant();
 		}
-		return NotAConstant;
+		return Constant.NotAConstant;
 	}
 	
 	public StringBuffer printExpression(int indent, StringBuffer output) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
index 6c706f7..3ab237f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
@@ -14,6 +14,7 @@
 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.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class ClassLiteralAccess extends Expression {
@@ -22,9 +23,10 @@
 	public TypeBinding targetType;
 	FieldBinding syntheticField;
 
-	public ClassLiteralAccess(int sourceEnd, TypeReference t) {
-		type = t;
-		this.sourceStart = t.sourceStart;
+	public ClassLiteralAccess(int sourceEnd, TypeReference type) {
+		this.type = type;
+		type.bits |= IgnoreRawTypeCheck; // no need to worry about raw type usage
+		this.sourceStart = type.sourceStart;
 		this.sourceEnd = sourceEnd;
 	}
 
@@ -39,7 +41,7 @@
 		if ((!(sourceType.isInterface()
 				// no field generated in interface case (would'nt verify) see 1FHHEZL
 				|| sourceType.isBaseType()))
-				&& currentScope.compilerOptions().sourceLevel <= ClassFileConstants.JDK1_5) {
+				&& currentScope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5) {
 			syntheticField = sourceType.addSyntheticFieldForClassLiteral(targetType, currentScope);
 		}
 		return flowInfo;
@@ -73,7 +75,7 @@
 
 	public TypeBinding resolveType(BlockScope scope) {
 
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		if ((targetType = type.resolveType(scope, true /* check bounds*/)) == null)
 			return null;
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
index ade0c75..214c0da 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
@@ -146,6 +146,8 @@
 				cleanUp(type.memberTypes[i]);
 			}
 		}
+		if (type.binding != null && type.binding.isAnnotationType())
+			compilationResult.declaresAnnotations = true;
 		if (type.binding != null) {
 			// null out the type's scope backpointers
 			type.binding.scope = null;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java b/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
index 302ba62..13f326c 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
@@ -14,6 +14,7 @@
 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.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class CompoundAssignment extends Assignment implements OperatorIds {
@@ -94,7 +95,7 @@
 	}
 	
 	public TypeBinding resolveType(BlockScope scope) {
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		if (!(this.lhs instanceof Reference) || this.lhs.isThis()) {
 			scope.problemReporter().expressionShouldBeAVariable(this.lhs);
 			return null;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index 438a125..3a8e4e0 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -46,11 +46,11 @@
 		FlowInfo flowInfo) {
 
 		Constant cst = this.condition.optimizedBooleanConstant();
-		boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
-		boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+		boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
+		boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;
 
 		int mode = flowInfo.reachMode();
-		flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo, cst == NotAConstant);
+		flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo, cst == Constant.NotAConstant);
 		
 		// process the if-true part
 		FlowInfo trueFlowInfo = flowInfo.initsWhenTrue().copy();
@@ -77,12 +77,12 @@
 		} else {
 			// if ((t && (v = t)) ? t : t && (v = f)) r = v;  -- ok
 			cst = this.optimizedIfTrueConstant;
-			boolean isValueIfTrueOptimizedTrue = cst != null && cst != NotAConstant && cst.booleanValue() == true;
-			boolean isValueIfTrueOptimizedFalse = cst != null && cst != NotAConstant && cst.booleanValue() == false;
+			boolean isValueIfTrueOptimizedTrue = cst != null && cst != Constant.NotAConstant && cst.booleanValue() == true;
+			boolean isValueIfTrueOptimizedFalse = cst != null && cst != Constant.NotAConstant && cst.booleanValue() == false;
 			
 			cst = this.optimizedIfFalseConstant;
-			boolean isValueIfFalseOptimizedTrue = cst != null && cst != NotAConstant && cst.booleanValue() == true;
-			boolean isValueIfFalseOptimizedFalse = cst != null && cst != NotAConstant && cst.booleanValue() == false;
+			boolean isValueIfFalseOptimizedTrue = cst != null && cst != Constant.NotAConstant && cst.booleanValue() == true;
+			boolean isValueIfFalseOptimizedFalse = cst != null && cst != Constant.NotAConstant && cst.booleanValue() == false;
 
 			UnconditionalFlowInfo trueInfoWhenTrue = trueFlowInfo.initsWhenTrue().copy().unconditionalInits();
 			if (isValueIfTrueOptimizedFalse) trueInfoWhenTrue.setReachMode(FlowInfo.UNREACHABLE); 
@@ -121,7 +121,7 @@
 
 		int pc = codeStream.position;
 		Label endifLabel, falseLabel;
-		if (constant != NotAConstant) {
+		if (constant != Constant.NotAConstant) {
 			if (valueRequired)
 				codeStream.generateConstant(constant, implicitConversion);
 			codeStream.recordPositionsFrom(pc, this.sourceStart);
@@ -130,15 +130,15 @@
 		Constant cst = condition.constant;
 		Constant condCst = condition.optimizedBooleanConstant();
 		boolean needTruePart =
-			!(((cst != NotAConstant) && (cst.booleanValue() == false))
-				|| ((condCst != NotAConstant) && (condCst.booleanValue() == false)));
+			!(((cst != Constant.NotAConstant) && (cst.booleanValue() == false))
+				|| ((condCst != Constant.NotAConstant) && (condCst.booleanValue() == false)));
 		boolean needFalsePart =
-			!(((cst != NotAConstant) && (cst.booleanValue() == true))
-				|| ((condCst != NotAConstant) && (condCst.booleanValue() == true)));
+			!(((cst != Constant.NotAConstant) && (cst.booleanValue() == true))
+				|| ((condCst != Constant.NotAConstant) && (condCst.booleanValue() == true)));
 		endifLabel = new Label(codeStream);
 
 		// Generate code for the condition
-		boolean needConditionValue = (cst == NotAConstant) && (condCst == NotAConstant);
+		boolean needConditionValue = (cst == Constant.NotAConstant) && (condCst == Constant.NotAConstant);
 		condition.generateOptimizedBoolean(
 			currentScope,
 			codeStream,
@@ -208,16 +208,16 @@
 		Constant cst = condition.constant;
 		Constant condCst = condition.optimizedBooleanConstant();
 		boolean needTruePart =
-			!(((cst != NotAConstant) && (cst.booleanValue() == false))
-				|| ((condCst != NotAConstant) && (condCst.booleanValue() == false)));
+			!(((cst != Constant.NotAConstant) && (cst.booleanValue() == false))
+				|| ((condCst != Constant.NotAConstant) && (condCst.booleanValue() == false)));
 		boolean needFalsePart =
-			!(((cst != NotAConstant) && (cst.booleanValue() == true))
-				|| ((condCst != NotAConstant) && (condCst.booleanValue() == true)));
+			!(((cst != Constant.NotAConstant) && (cst.booleanValue() == true))
+				|| ((condCst != Constant.NotAConstant) && (condCst.booleanValue() == true)));
 
 		Label internalFalseLabel, endifLabel = new Label(codeStream);
 
 		// Generate code for the condition
-		boolean needConditionValue = (cst == NotAConstant) && (condCst == NotAConstant);
+		boolean needConditionValue = (cst == Constant.NotAConstant) && (condCst == Constant.NotAConstant);
 		condition.generateOptimizedBoolean(
 				currentScope,
 				codeStream,
@@ -277,7 +277,7 @@
 
 	public TypeBinding resolveType(BlockScope scope) {
 		// JLS3 15.25
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		LookupEnvironment env = scope.environment();
 		boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
 		TypeBinding conditionType = condition.resolveTypeExpecting(scope, BooleanBinding);
@@ -332,9 +332,9 @@
 		}
 		// Propagate the constant value from the valueIfTrue and valueIFFalse expression if it is possible
 		Constant condConstant, trueConstant, falseConstant;
-		if ((condConstant = condition.constant) != NotAConstant
-			&& (trueConstant = valueIfTrue.constant) != NotAConstant
-			&& (falseConstant = valueIfFalse.constant) != NotAConstant) {
+		if ((condConstant = condition.constant) != Constant.NotAConstant
+			&& (trueConstant = valueIfTrue.constant) != Constant.NotAConstant
+			&& (falseConstant = valueIfFalse.constant) != Constant.NotAConstant) {
 			// all terms are constant expression so we can propagate the constant
 			// from valueIFTrue or valueIfFalse to the receiver constant
 			constant = condConstant.booleanValue() ? trueConstant : falseConstant;
@@ -345,12 +345,12 @@
 			if (valueIfTrueType == BooleanBinding) {
 				this.optimizedIfTrueConstant = valueIfTrue.optimizedBooleanConstant();
 				this.optimizedIfFalseConstant = valueIfFalse.optimizedBooleanConstant();
-				if (this.optimizedIfTrueConstant != NotAConstant 
-						&& this.optimizedIfFalseConstant != NotAConstant
+				if (this.optimizedIfTrueConstant != Constant.NotAConstant 
+						&& this.optimizedIfFalseConstant != Constant.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
+				} else if ((condConstant = condition.optimizedBooleanConstant()) != Constant.NotAConstant) { // Propagate the optimized boolean constant if possible
 					this.optimizedBooleanConstant = condConstant.booleanValue()
 						? this.optimizedIfTrueConstant
 						: this.optimizedIfFalseConstant;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
index 8fb60ae..7566dcc 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
@@ -52,10 +52,10 @@
 				currentScope);
 
 		Constant cst = condition.constant;
-		boolean isConditionTrue = cst != NotAConstant && cst.booleanValue() == true;
+		boolean isConditionTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
 		cst = condition.optimizedBooleanConstant();
-		boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
-		boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+		boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
+		boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;
 
 		int previousMode = flowInfo.reachMode();
 				
@@ -120,17 +120,24 @@
 		if (action != null) {
 			action.generateCode(currentScope, codeStream);
 		}
-		// generate condition
-		if (continueLabel != null) {
-			continueLabel.place();
-			condition.generateOptimizedBoolean(
-				currentScope,
-				codeStream,
-				actionLabel,
-				null,
-				true);
+		Constant cst = condition.optimizedBooleanConstant();
+		boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;		
+		if (isConditionOptimizedFalse){
+			condition.generateCode(currentScope, codeStream, false);
+		} else {
+			// generate condition
+			if (continueLabel != null) {
+				continueLabel.place();
+				condition.generateOptimizedBoolean(
+					currentScope,
+					codeStream,
+					actionLabel,
+					null,
+					true);
+			}
 		}
-		breakLabel.place();
+		if (breakLabel.hasForwardReferences())
+			breakLabel.place();
 
 		// May loose some local variable initializations : affecting the local variable attributes
 		if (mergedInitStateIndex != -1) {
@@ -138,7 +145,6 @@
 			codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
 		}
 		codeStream.recordPositionsFrom(pc, this.sourceStart);
-
 	}
 
 	public StringBuffer printStatement(int indent, StringBuffer output) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
index 8a5555f..552ab46 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
@@ -56,7 +56,7 @@
 	
 	public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
 		if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
-			if ((left.constant != NotAConstant) && (left.constant.typeID() == T_boolean)) {
+			if ((left.constant != Constant.NotAConstant) && (left.constant.typeID() == T_boolean)) {
 				if (left.constant.booleanValue()) { //  true == anything
 					//  this is equivalent to the right argument inits 
 					return right.analyseCode(currentScope, flowContext, flowInfo);
@@ -65,7 +65,7 @@
 					return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
 				}
 			}
-			if ((right.constant != NotAConstant) && (right.constant.typeID() == T_boolean)) {
+			if ((right.constant != Constant.NotAConstant) && (right.constant.typeID() == T_boolean)) {
 				if (right.constant.booleanValue()) { //  anything == true
 					//  this is equivalent to the right argument inits 
 					return left.analyseCode(currentScope, flowContext, flowInfo);
@@ -78,7 +78,7 @@
 				currentScope, flowContext, 
 				left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits()).unconditionalInits();
 		} else { //NOT_EQUAL :
-			if ((left.constant != NotAConstant) && (left.constant.typeID() == T_boolean)) {
+			if ((left.constant != Constant.NotAConstant) && (left.constant.typeID() == T_boolean)) {
 				if (!left.constant.booleanValue()) { //  false != anything
 					//  this is equivalent to the right argument inits 
 					return right.analyseCode(currentScope, flowContext, flowInfo);
@@ -87,7 +87,7 @@
 					return right.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
 				}
 			}
-			if ((right.constant != NotAConstant) && (right.constant.typeID() == T_boolean)) {
+			if ((right.constant != Constant.NotAConstant) && (right.constant.typeID() == T_boolean)) {
 				if (!right.constant.booleanValue()) { //  anything != false
 					//  this is equivalent to the right argument inits 
 					return left.analyseCode(currentScope, flowContext, flowInfo);
@@ -103,7 +103,7 @@
 	}
 	
 	public final void computeConstant(TypeBinding leftType, TypeBinding rightType) {
-		if ((this.left.constant != NotAConstant) && (this.right.constant != NotAConstant)) {
+		if ((this.left.constant != Constant.NotAConstant) && (this.right.constant != Constant.NotAConstant)) {
 			this.constant =
 				Constant.computeConstantOperationEQUAL_EQUAL(
 					left.constant,
@@ -113,7 +113,7 @@
 			if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL)
 				constant = Constant.fromValue(!constant.booleanValue());
 		} else {
-			this.constant = NotAConstant;
+			this.constant = Constant.NotAConstant;
 			// no optimization for null == null
 		}
 	}
@@ -126,45 +126,23 @@
 	 */
 	public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 	
-		if (constant != NotAConstant) {
-			int pc = codeStream.position;
+		int pc = codeStream.position;
+		if (constant != Constant.NotAConstant) {
 			if (valueRequired) 
 				codeStream.generateConstant(constant, implicitConversion);
 			codeStream.recordPositionsFrom(pc, this.sourceStart);
 			return;
 		}
-		Label falseLabel;
-		bits |= OnlyValueRequired;
-		generateOptimizedBoolean(
-			currentScope, 
-			codeStream, 
-			null, 
-			falseLabel = new Label(codeStream), 
-			valueRequired);
-		if (falseLabel.hasForwardReferences()) {
-			if (valueRequired){
-				// comparison is TRUE 
-				codeStream.iconst_1();
-				if ((bits & IsReturnedValue) != 0){
-					codeStream.generateImplicitConversion(this.implicitConversion);
-					codeStream.generateReturnBytecode(this);
-					// comparison is FALSE
-					falseLabel.place();
-					codeStream.iconst_0();
-				} else {
-					Label endLabel = new Label(codeStream);
-					codeStream.goto_(endLabel);
-					codeStream.decrStackSize(1);
-					// comparison is FALSE
-					falseLabel.place();
-					codeStream.iconst_0();
-					endLabel.place();
-				}
-				codeStream.generateImplicitConversion(implicitConversion);
-			} else {
-				falseLabel.place();
-			}	
+		
+		if ((left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) {
+			generateBooleanEqual(currentScope, codeStream, valueRequired);
+		} else {
+			generateNonBooleanEqual(currentScope, codeStream, valueRequired);
 		}
+		if (valueRequired) {
+			codeStream.generateImplicitConversion(implicitConversion);
+		}
+		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
 	/**
 	 * Boolean operator code generation
@@ -190,6 +168,155 @@
 			}
 		}
 	}
+
+	/**
+	 * Boolean generation for == with boolean operands
+	 *
+	 * Note this code does not optimize conditional constants !!!!
+	 */
+	public void generateBooleanEqual(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+	
+		// optimized cases: <something equivalent to true> == x, <something equivalent to false> == x, 
+		// optimized cases: <something equivalent to false> != x, <something equivalent to true> != x, 
+		boolean isEqualOperator = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL;
+		Constant cst = left.optimizedBooleanConstant();
+		if (cst != Constant.NotAConstant) {
+			Constant rightCst = right.optimizedBooleanConstant();
+			if (rightCst != Constant.NotAConstant) {
+				// <something equivalent to true> == <something equivalent to true>, <something equivalent to false> != <something equivalent to true>
+				// <something equivalent to true> == <something equivalent to false>, <something equivalent to false> != <something equivalent to false>
+				left.generateCode(currentScope, codeStream, false);
+				right.generateCode(currentScope, codeStream, false);
+				if (valueRequired) {
+					boolean leftBool = cst.booleanValue();
+					boolean rightBool = rightCst.booleanValue();
+					if (isEqualOperator) {
+						if (leftBool == rightBool) {
+							codeStream.iconst_1();
+						} else {
+							codeStream.iconst_0();
+						}
+					} else {
+						if (leftBool != rightBool) {
+							codeStream.iconst_1();
+						} else {
+							codeStream.iconst_0();
+						}
+					}
+				}
+			} else if (cst.booleanValue() == isEqualOperator) {
+				// <something equivalent to true> == x, <something equivalent to false> != x
+				left.generateCode(currentScope, codeStream, false);
+				right.generateCode(currentScope, codeStream, valueRequired);
+			} else {
+				// <something equivalent to false> == x, <something equivalent to true> != x
+				if (valueRequired) {
+					Label falseLabel = new Label(codeStream);
+					left.generateCode(currentScope, codeStream, false);
+					right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired);
+					// comparison is TRUE 
+					codeStream.iconst_0();
+					if ((bits & IsReturnedValue) != 0){
+						codeStream.generateImplicitConversion(this.implicitConversion);
+						codeStream.generateReturnBytecode(this);
+						// comparison is FALSE
+						falseLabel.place();
+						codeStream.iconst_1();
+					} else {
+						Label endLabel = new Label(codeStream);
+						codeStream.goto_(endLabel);
+						codeStream.decrStackSize(1);
+						// comparison is FALSE
+						falseLabel.place();
+						codeStream.iconst_1();
+						endLabel.place();
+					}
+				} else {
+					left.generateCode(currentScope, codeStream, false);
+					right.generateCode(currentScope, codeStream, false);
+				}
+//				left.generateCode(currentScope, codeStream, false);
+//				right.generateCode(currentScope, codeStream, valueRequired);
+//				if (valueRequired) {
+//					codeStream.iconst_1();
+//					codeStream.ixor(); // negate
+//				}
+			}
+			return;
+		} 
+		cst = right.optimizedBooleanConstant();
+		if (cst != Constant.NotAConstant) {
+			if (cst.booleanValue() == isEqualOperator) {
+				// x == <something equivalent to true>, x != <something equivalent to false>
+				left.generateCode(currentScope, codeStream, valueRequired);
+				right.generateCode(currentScope, codeStream, false);
+			} else {
+				// x == <something equivalent to false>, x != <something equivalent to true>
+				if (valueRequired) {
+					Label falseLabel = new Label(codeStream);
+					left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired);
+					right.generateCode(currentScope, codeStream, false);
+					// comparison is TRUE 
+					codeStream.iconst_0();
+					if ((bits & IsReturnedValue) != 0){
+						codeStream.generateImplicitConversion(this.implicitConversion);
+						codeStream.generateReturnBytecode(this);
+						// comparison is FALSE
+						falseLabel.place();
+						codeStream.iconst_1();
+					} else {
+						Label endLabel = new Label(codeStream);
+						codeStream.goto_(endLabel);
+						codeStream.decrStackSize(1);
+						// comparison is FALSE
+						falseLabel.place();
+						codeStream.iconst_1();
+						endLabel.place();
+					}
+				} else {
+					left.generateCode(currentScope, codeStream, false);
+					right.generateCode(currentScope, codeStream, false);
+				}
+//				left.generateCode(currentScope, codeStream, valueRequired);
+//				right.generateCode(currentScope, codeStream, false);
+//				if (valueRequired) {
+//					codeStream.iconst_1();
+//					codeStream.ixor(); // negate
+//				}
+			}
+			return;
+		} 
+		// default case
+		left.generateCode(currentScope, codeStream, valueRequired);
+		right.generateCode(currentScope, codeStream, valueRequired);
+
+		if (valueRequired) {
+			if (isEqualOperator) {
+				Label falseLabel;
+				codeStream.if_icmpne(falseLabel = new Label(codeStream));
+				// comparison is TRUE 
+				codeStream.iconst_1();
+				if ((bits & IsReturnedValue) != 0){
+					codeStream.generateImplicitConversion(this.implicitConversion);
+					codeStream.generateReturnBytecode(this);
+					// comparison is FALSE
+					falseLabel.place();
+					codeStream.iconst_0();
+				} else {
+					Label endLabel = new Label(codeStream);
+					codeStream.goto_(endLabel);
+					codeStream.decrStackSize(1);
+					// comparison is FALSE
+					falseLabel.place();
+					codeStream.iconst_0();
+					endLabel.place();
+				}
+			} else {
+				codeStream.ixor();				
+			}
+		}
+	}
+	
 	/**
 	 * Boolean generation for == with boolean operands
 	 *
@@ -198,12 +325,12 @@
 	public void generateOptimizedBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
 	
 		// optimized cases: true == x, false == x
-		if (left.constant != NotAConstant) {
+		if (left.constant != Constant.NotAConstant) {
 			boolean inline = left.constant.booleanValue();
 			right.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
 			return;
 		} // optimized cases: x == true, x == false
-		if (right.constant != NotAConstant) {
+		if (right.constant != Constant.NotAConstant) {
 			boolean inline = right.constant.booleanValue();
 			left.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
 			return;
@@ -233,11 +360,220 @@
 	 * Boolean generation for == with non-boolean operands
 	 *
 	 */
+	public void generateNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+	
+		boolean isEqualOperator = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL;
+		if (((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) {
+			Constant cst;
+			if ((cst = left.constant) != Constant.NotAConstant && cst.intValue() == 0) {
+				// optimized case: 0 == x, 0 != x
+				right.generateCode(currentScope, codeStream, valueRequired);
+				if (valueRequired) {
+					Label falseLabel = new Label(codeStream);
+					if (isEqualOperator) {
+						codeStream.ifne(falseLabel);
+					} else {
+						codeStream.ifeq(falseLabel);
+					}
+					// comparison is TRUE 
+					codeStream.iconst_1();
+					if ((bits & IsReturnedValue) != 0){
+						codeStream.generateImplicitConversion(this.implicitConversion);
+						codeStream.generateReturnBytecode(this);
+						// comparison is FALSE
+						falseLabel.place();
+						codeStream.iconst_0();
+					} else {
+						Label endLabel = new Label(codeStream);
+						codeStream.goto_(endLabel);
+						codeStream.decrStackSize(1);
+						// comparison is FALSE
+						falseLabel.place();
+						codeStream.iconst_0();
+						endLabel.place();
+					}
+				}				
+				return;
+			}
+			if ((cst = right.constant) != Constant.NotAConstant && cst.intValue() == 0) {
+				// optimized case: x == 0, x != 0
+				left.generateCode(currentScope, codeStream, valueRequired);
+				if (valueRequired) {
+					Label falseLabel = new Label(codeStream);
+					if (isEqualOperator) {
+						codeStream.ifne(falseLabel);
+					} else {
+						codeStream.ifeq(falseLabel);
+					}
+					// comparison is TRUE 
+					codeStream.iconst_1();
+					if ((bits & IsReturnedValue) != 0){
+						codeStream.generateImplicitConversion(this.implicitConversion);
+						codeStream.generateReturnBytecode(this);
+						// comparison is FALSE
+						falseLabel.place();
+						codeStream.iconst_0();
+					} else {
+						Label endLabel = new Label(codeStream);
+						codeStream.goto_(endLabel);
+						codeStream.decrStackSize(1);
+						// comparison is FALSE
+						falseLabel.place();
+						codeStream.iconst_0();
+						endLabel.place();
+					}
+				}				
+				return;
+			}			
+		}
+
+		// null cases
+		if (right instanceof NullLiteral) {
+			if (left instanceof NullLiteral) {
+				// null == null, null != null
+				if (valueRequired) {
+					if (isEqualOperator) {
+						codeStream.iconst_1();
+					} else {
+						codeStream.iconst_0();
+					}
+				}
+			} else {
+				// x == null, x != null
+				left.generateCode(currentScope, codeStream, valueRequired);
+				if (valueRequired) {
+					Label falseLabel = new Label(codeStream);
+					if (isEqualOperator) {
+						codeStream.ifnonnull(falseLabel);
+					} else {
+						codeStream.ifnull(falseLabel);
+					}
+					// comparison is TRUE 
+					codeStream.iconst_1();
+					if ((bits & IsReturnedValue) != 0){
+						codeStream.generateImplicitConversion(this.implicitConversion);
+						codeStream.generateReturnBytecode(this);
+						// comparison is FALSE
+						falseLabel.place();
+						codeStream.iconst_0();
+					} else {
+						Label endLabel = new Label(codeStream);
+						codeStream.goto_(endLabel);
+						codeStream.decrStackSize(1);
+						// comparison is FALSE
+						falseLabel.place();
+						codeStream.iconst_0();
+						endLabel.place();
+					}
+				}
+			}
+			return;
+		} else if (left instanceof NullLiteral) {
+			// null = x, null != x
+			right.generateCode(currentScope, codeStream, valueRequired);
+			if (valueRequired) {
+				Label falseLabel = new Label(codeStream);
+				if (isEqualOperator) {
+					codeStream.ifnonnull(falseLabel);
+				} else {
+					codeStream.ifnull(falseLabel);
+				}
+				// comparison is TRUE 
+				codeStream.iconst_1();
+				if ((bits & IsReturnedValue) != 0){
+					codeStream.generateImplicitConversion(this.implicitConversion);
+					codeStream.generateReturnBytecode(this);
+					// comparison is FALSE
+					falseLabel.place();
+					codeStream.iconst_0();
+				} else {
+					Label endLabel = new Label(codeStream);
+					codeStream.goto_(endLabel);
+					codeStream.decrStackSize(1);
+					// comparison is FALSE
+					falseLabel.place();
+					codeStream.iconst_0();
+					endLabel.place();
+				}
+			}				
+			return;
+		}
+	
+		// default case
+		left.generateCode(currentScope, codeStream, valueRequired);
+		right.generateCode(currentScope, codeStream, valueRequired);
+		if (valueRequired) {
+			Label falseLabel = new Label(codeStream);
+			if (isEqualOperator) {
+				switch ((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { // operand runtime type
+					case T_int :
+						codeStream.if_icmpne(falseLabel);
+						break;
+					case T_float :
+						codeStream.fcmpl();
+						codeStream.ifne(falseLabel);
+						break;
+					case T_long :
+						codeStream.lcmp();
+						codeStream.ifne(falseLabel);
+						break;
+					case T_double :
+						codeStream.dcmpl();
+						codeStream.ifne(falseLabel);
+						break;
+					default :
+						codeStream.if_acmpne(falseLabel);
+				}
+			} else {
+				switch ((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) { // operand runtime type
+					case T_int :
+						codeStream.if_icmpeq(falseLabel);
+						break;
+					case T_float :
+						codeStream.fcmpl();
+						codeStream.ifeq(falseLabel);
+						break;
+					case T_long :
+						codeStream.lcmp();
+						codeStream.ifeq(falseLabel);
+						break;
+					case T_double :
+						codeStream.dcmpl();
+						codeStream.ifeq(falseLabel);
+						break;
+					default :
+						codeStream.if_acmpeq(falseLabel);
+				}				
+			}
+			// comparison is TRUE 
+			codeStream.iconst_1();
+			if ((bits & IsReturnedValue) != 0){
+				codeStream.generateImplicitConversion(this.implicitConversion);
+				codeStream.generateReturnBytecode(this);
+				// comparison is FALSE
+				falseLabel.place();
+				codeStream.iconst_0();
+			} else {
+				Label endLabel = new Label(codeStream);
+				codeStream.goto_(endLabel);
+				codeStream.decrStackSize(1);
+				// comparison is FALSE
+				falseLabel.place();
+				codeStream.iconst_0();
+				endLabel.place();
+			}			
+		}
+	}
+	
+	/**
+	 * Boolean generation for == with non-boolean operands
+	 *
+	 */
 	public void generateOptimizedNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
 	
 		int pc = codeStream.position;
 		Constant inline;
-		if ((inline = right.constant) != NotAConstant) {
+		if ((inline = right.constant) != Constant.NotAConstant) {
 			// optimized case: x == 0
 			if ((((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) && (inline.intValue() == 0)) {
 				left.generateCode(currentScope, codeStream, valueRequired);
@@ -260,7 +596,7 @@
 				return;
 			}
 		}
-		if ((inline = left.constant) != NotAConstant) {
+		if ((inline = left.constant) != Constant.NotAConstant) {
 			// optimized case: 0 == x
 			if ((((left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int)
 				&& (inline.intValue() == 0)) {
@@ -290,19 +626,11 @@
 			if (left instanceof NullLiteral) {
 				// null == null
 				if (valueRequired) {
-						if ((bits & OnlyValueRequired) != 0) {
-							if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
-								codeStream.iconst_1();
-							} else {
-								codeStream.iconst_0();
-							}
-						} else {
-							if (falseLabel == null) {
-								// implicit falling through the FALSE case
-								if (trueLabel != null) {
-									codeStream.goto_(trueLabel);
-								}
-							}
+					if (falseLabel == null) {
+						// implicit falling through the FALSE case
+						if (trueLabel != null) {
+							codeStream.goto_(trueLabel);
+						}
 					}
 				}
 			} else {
@@ -416,7 +744,7 @@
 	
 		// always return BooleanBinding
 		if (originalLeftType == null || originalRightType == null){
-			constant = NotAConstant;		
+			constant = Constant.NotAConstant;		
 			return null;
 		}
 	
@@ -471,7 +799,7 @@
 			if ((rightType.id == T_JavaLangString) && (leftType.id == T_JavaLangString)) {
 				computeConstant(leftType, rightType);
 			} else {
-				constant = NotAConstant;
+				constant = Constant.NotAConstant;
 			}
 			TypeBinding objectType = scope.getJavaLangObject();
 			left.computeConversion(scope, objectType, leftType);
@@ -490,7 +818,7 @@
 			}
 			return this.resolvedType = BooleanBinding;
 		}
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		scope.problemReporter().notCompatibleTypesError(this, leftType, rightType);
 		return null;
 	}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
index 8051f76..9d9a09a 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
@@ -256,7 +256,7 @@
 				return;
 			}
 			methodScope.isConstructorCall = true;
-			ReferenceBinding receiverType = scope.enclosingSourceType();
+			ReferenceBinding receiverType = scope.enclosingReceiverType();
 			if (accessMode != This)
 				receiverType = receiverType.superclass();
 
@@ -318,6 +318,11 @@
 					}
 				}
 				if (argHasError) {
+					// record a best guess, for clients who need hint about possible contructor match
+					TypeBinding[] pseudoArgs = new TypeBinding[length];
+					for (int i = length; --i >= 0;)
+						pseudoArgs[i] = argumentTypes[i] == null ? receiverType : argumentTypes[i]; // replace args with errors with receiver
+					this.binding = scope.findMethod(receiverType, TypeConstants.INIT, pseudoArgs, this);
 					return;
 				}
 			} else if (receiverType.erasure().id == T_JavaLangEnum) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
index d8a9bf3..6634539 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -527,9 +527,7 @@
 		}
 		if (match != null && (
 				castType.isBoundParameterizedType() 
-				|| castType.isGenericType() 
-				|| 	expressionType.isBoundParameterizedType() 
-				|| expressionType.isGenericType())) {
+				|| 	expressionType.isBoundParameterizedType())) {
 			
 			if (match.isProvablyDistinctFrom(isNarrowing ? expressionType : castType, 0)) {
 				return false; 
@@ -593,6 +591,7 @@
 //				}		
 		}
 	}	
+	
 	/**
 	 * Expression statements are plain expressions, however they generate like
 	 * normal expressions with no value required.
@@ -620,7 +619,7 @@
 		CodeStream codeStream,
 		boolean valueRequired) {
 
-		if (constant != NotAConstant) {
+		if (constant != Constant.NotAConstant) {
 			// generate a constant expression
 			int pc = codeStream.position;
 			codeStream.generateConstant(constant, implicitConversion);
@@ -706,7 +705,7 @@
 		CodeStream codeStream,
 		int typeID) {
 
-		if (typeID == T_JavaLangString && this.constant != NotAConstant && this.constant.stringValue().length() == 0) {
+		if (typeID == T_JavaLangString && this.constant != Constant.NotAConstant && this.constant.stringValue().length() == 0) {
 			return; // optimize str + ""
 		}
 		generateCode(blockScope, codeStream, true);
@@ -735,7 +734,7 @@
 				return;
 			case T_JavaLangString :
 			case T_null :
-				if (constant != NotAConstant) {
+				if (constant != Constant.NotAConstant) {
 					String stringValue = constant.stringValue();
 					if (stringValue.length() == 0) {  // optimize ""+<str> 
 						codeStream.invokeStringConcatenationDefaultConstructor();
@@ -754,6 +753,48 @@
 		}
 		codeStream.invokeStringConcatenationStringConstructor();
 	}
+	
+	/**
+	 * Returns the type of the expression after required implicit conversions. When expression type gets promoted
+	 * or inserted a generic cast, the converted type will differ from the resolved type (surface side-effects from
+	 * #computeConversion(...)).
+	 * @return the type after conversion
+	 */
+	public TypeBinding generatedType(Scope scope) {
+		TypeBinding convertedType = this.resolvedType;
+		int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
+		switch (runtimeType) {
+			case T_boolean :
+				convertedType = BooleanBinding;
+				break;
+			case T_byte :
+				convertedType = ByteBinding;
+				break;
+			case T_short :
+				convertedType = ShortBinding;
+				break;
+			case T_char :
+				convertedType = CharBinding;
+				break;
+			case T_int :
+				convertedType = IntBinding;
+				break;
+			case T_float :
+				convertedType = FloatBinding;
+				break;
+			case T_long :
+				convertedType = LongBinding;
+				break;
+			case T_double :
+				convertedType = DoubleBinding;
+				break;
+			default :
+		}		
+		if ((this.implicitConversion & BOXING) != 0) {
+			convertedType = scope.environment().computeBoxingType(convertedType);
+		}
+		return convertedType;
+	}	
 
 	public boolean isCompactableOperation() {
 
@@ -788,7 +829,7 @@
 	
 	public int nullStatus(FlowInfo flowInfo) {
 		
-		if (this.constant != null && this.constant != NotAConstant)
+		if (this.constant != null && this.constant != Constant.NotAConstant)
 			return FlowInfo.NON_NULL; // constant expression cannot be null
 		
 		LocalVariableBinding local = localVariableBinding();
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java b/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
index 317393d..f071170 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
@@ -68,7 +68,7 @@
 		if (this.binding != null
 				&& this.binding.isValidBinding()
 				&& this.binding.isStatic()
-				&& !this.binding.isConstantValue()
+				&& this.binding.constant() == Constant.NotAConstant
 				&& this.binding.declaringClass.isNestedType()
 				&& !this.binding.declaringClass.isStatic()) {
 			initializationScope.problemReporter().unexpectedStaticModifierForField(
@@ -103,7 +103,7 @@
 		int pc = codeStream.position;
 		boolean isStatic;
 		if (this.initialization != null
-			&& !((isStatic = this.binding.isStatic()) && this.binding.isConstantValue())) {
+			&& !((isStatic = this.binding.isStatic()) && this.binding.constant() != Constant.NotAConstant)) {
 			// non-static field, need receiver
 			if (!isStatic)
 				codeStream.aload_0();
@@ -192,7 +192,12 @@
 				initializationScope.lastVisibleFieldID = this.binding.id;
 
 				resolveAnnotations(initializationScope, this.annotations, this.binding);
-				
+				// check @Deprecated annotation presence
+				if ((this.binding.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0
+						&& (this.binding.modifiers & ClassFileConstants.AccDeprecated) != 0
+						&& initializationScope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
+					initializationScope.problemReporter().missingDeprecatedAnnotationForField(this);
+				}						
 				// the resolution of the initialization hasn't been done
 				if (this.initialization == null) {
 					this.binding.setConstant(Constant.NotAConstant);
@@ -241,7 +246,7 @@
 							this.binding.setConstant(this.initialization.constant.castTo((this.binding.type.id << 4) + this.initialization.constant.typeID()));
 						}
 					} else {
-						this.binding.setConstant(NotAConstant);
+						this.binding.setConstant(Constant.NotAConstant);
 					}
 				}
 				// Resolve Javadoc comment if one is present
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
index d851b6a..50ddaab 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
@@ -31,577 +31,525 @@
 	public TypeBinding receiverType;
 	public TypeBinding genericCast;
 	
-	public FieldReference(char[] source, long pos) {
+public FieldReference(char[] source, long pos) {
+	token = source;
+	nameSourcePosition = pos;
+	//by default the position are the one of the field (not true for super access)
+	sourceStart = (int) (pos >>> 32);
+	sourceEnd = (int) (pos & 0x00000000FFFFFFFFL);
+	bits |= Binding.FIELD;
 
-		token = source;
-		nameSourcePosition = pos;
-		//by default the position are the one of the field (not true for super access)
-		sourceStart = (int) (pos >>> 32);
-		sourceEnd = (int) (pos & 0x00000000FFFFFFFFL);
-		bits |= Binding.FIELD;
+}
 
-	}
-
-	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
-			if (binding.isBlankFinal()
-				&& receiver.isThis()
-				&& currentScope.allowBlankFinalFieldAssignment(binding)
-				&& (!flowInfo.isDefinitelyAssigned(binding))) {
-				currentScope.problemReporter().uninitializedBlankFinalField(binding, this);
-				// we could improve error msg here telling "cannot use compound assignment on final blank field"
-			}
-			manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
+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
+		if (binding.isBlankFinal()
+			&& receiver.isThis()
+			&& currentScope.allowBlankFinalFieldAssignment(binding)
+			&& (!flowInfo.isDefinitelyAssigned(binding))) {
+			currentScope.problemReporter().uninitializedBlankFinalField(binding, this);
+			// we could improve error msg here telling "cannot use compound assignment on final blank field"
 		}
+		manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
+	}
+	flowInfo =
+		receiver
+			.analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic())
+			.unconditionalInits();
+	if (assignment.expression != null) {
 		flowInfo =
-			receiver
-				.analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic())
+			assignment
+				.expression
+				.analyseCode(currentScope, flowContext, flowInfo)
 				.unconditionalInits();
-		if (assignment.expression != null) {
-			flowInfo =
-				assignment
-					.expression
-					.analyseCode(currentScope, flowContext, flowInfo)
-					.unconditionalInits();
-		}
-		manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/);
+	}
+	manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/);
 
-		// check if assigning a final field 
-		if (binding.isFinal()) {
-			// in a context where it can be assigned?
-			if (binding.isBlankFinal()
-				&& !isCompound
-				&& receiver.isThis()
-				&& !(receiver instanceof QualifiedThisReference)
-				&& ((receiver.bits & ParenthesizedMASK) == 0) // (this).x is forbidden
-				&& currentScope.allowBlankFinalFieldAssignment(binding)) {
-				if (flowInfo.isPotentiallyAssigned(binding)) {
-					currentScope.problemReporter().duplicateInitializationOfBlankFinalField(
-						binding,
-						this);
-				} else {
-					flowContext.recordSettingFinal(binding, this, flowInfo);
-				}
-				flowInfo.markAsDefinitelyAssigned(binding);
+	// check if assigning a final field 
+	if (binding.isFinal()) {
+		// in a context where it can be assigned?
+		if (binding.isBlankFinal()
+			&& !isCompound
+			&& receiver.isThis()
+			&& !(receiver instanceof QualifiedThisReference)
+			&& ((receiver.bits & ParenthesizedMASK) == 0) // (this).x is forbidden
+			&& currentScope.allowBlankFinalFieldAssignment(binding)) {
+			if (flowInfo.isPotentiallyAssigned(binding)) {
+				currentScope.problemReporter().duplicateInitializationOfBlankFinalField(
+					binding,
+					this);
 			} else {
-				// assigning a final field outside an initializer or constructor or wrong reference
-				currentScope.problemReporter().cannotAssignToFinalField(binding, this);
+				flowContext.recordSettingFinal(binding, this, 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) {
-
-		boolean nonStatic = !binding.isStatic();
-		receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic);
-		if (nonStatic) receiver.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
-		
-		if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
-			manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
-		}
-		return flowInfo;
-	}
-
-	/**
-	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
-	 */
-	public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
-		if (runtimeTimeType == null || compileTimeType == null)
-			return;		
-		// set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
-		if (this.binding != null && this.binding.isValidBinding()) {
-			FieldBinding originalBinding = this.binding.original();
-			if (originalBinding != this.binding) {
-			    // extra cast needed if method return type has type variable
-			    if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
-			    	TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) 
-			    		? compileTimeType  // unboxing: checkcast before conversion
-			    		: runtimeTimeType;
-			        this.genericCast = originalBinding.type.genericCast(targetType);
-			    }
-			}
-		} 	
-		super.computeConversion(scope, runtimeTimeType, compileTimeType);
-	}
-
-	public FieldBinding fieldBinding() {
-
-		return binding;
-	}
-
-	public void generateAssignment(
-		BlockScope currentScope,
-		CodeStream codeStream,
-		Assignment assignment,
-		boolean valueRequired) {
-
-		int pc = codeStream.position;
-		receiver.generateCode(
-			currentScope,
-			codeStream,
-			!this.codegenBinding.isStatic());
-		codeStream.recordPositionsFrom(pc, this.sourceStart);
-		assignment.expression.generateCode(currentScope, codeStream, true);
-		fieldStore(
-			codeStream,
-			this.codegenBinding,
-			syntheticAccessors == null ? null : syntheticAccessors[WRITE],
-			valueRequired);
-		if (valueRequired) {
-			codeStream.generateImplicitConversion(assignment.implicitConversion);
-		}
-		// no need for generic cast as value got dupped
-	}
-
-	/**
-	 * Field reference code generation
-	 *
-	 * @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) {
-
-		int pc = codeStream.position;
-		if (constant != NotAConstant) {
-			if (valueRequired) {
-				codeStream.generateConstant(constant, implicitConversion);
-			}
+			flowInfo.markAsDefinitelyAssigned(binding);
 		} else {
-			boolean isStatic = this.codegenBinding.isStatic();
-			if (this.codegenBinding.isConstantValue()) {
+			// assigning a final field outside an initializer or constructor or wrong reference
+			currentScope.problemReporter().cannotAssignToFinalField(binding, this);
+		}
+	}
+	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) {
+	boolean nonStatic = !binding.isStatic();
+	receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic);
+	if (nonStatic) receiver.checkNullStatus(currentScope, flowContext, flowInfo, FlowInfo.NON_NULL);
+	
+	if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
+		manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/);
+	}
+	return flowInfo;
+}
+
+/**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.jdt.internal.compiler.lookup.Scope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+ */
+public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) {
+	if (runtimeTimeType == null || compileTimeType == null)
+		return;		
+	// set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
+	if (this.binding != null && this.binding.isValidBinding()) {
+		FieldBinding originalBinding = this.binding.original();
+		if (originalBinding != this.binding && originalBinding.type != this.binding.type) {
+		    // extra cast needed if method return type has type variable
+		    if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
+		    	TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) 
+		    		? compileTimeType  // unboxing: checkcast before conversion
+		    		: runtimeTimeType;
+		        this.genericCast = originalBinding.type.genericCast(targetType);
+		    }
+		}
+	} 	
+	super.computeConversion(scope, runtimeTimeType, compileTimeType);
+}
+
+public FieldBinding fieldBinding() {
+	return binding;
+}
+
+public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
+	int pc = codeStream.position;
+	receiver.generateCode(
+		currentScope,
+		codeStream,
+		!this.codegenBinding.isStatic());
+	codeStream.recordPositionsFrom(pc, this.sourceStart);
+	assignment.expression.generateCode(currentScope, codeStream, true);
+	fieldStore(
+		codeStream,
+		this.codegenBinding,
+		syntheticAccessors == null ? null : syntheticAccessors[WRITE],
+		valueRequired);
+	if (valueRequired) {
+		codeStream.generateImplicitConversion(assignment.implicitConversion);
+	}
+	// no need for generic cast as value got dupped
+}
+
+/**
+ * Field reference code generation
+ *
+ * @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) {
+	int pc = codeStream.position;
+	if (constant != Constant.NotAConstant) {
+		if (valueRequired) {
+			codeStream.generateConstant(constant, implicitConversion);
+		}
+	} else {
+		boolean isStatic = this.codegenBinding.isStatic();
+		boolean isThisReceiver = this.receiver instanceof ThisReference;
+		Constant fieldConstant = this.codegenBinding.constant();
+		if (fieldConstant != Constant.NotAConstant) {
+			if (!isThisReceiver) {
 				receiver.generateCode(currentScope, codeStream, !isStatic);
 				if (!isStatic){
 					codeStream.invokeObjectGetClass();
 					codeStream.pop();
 				}
-				if (valueRequired) {
-					codeStream.generateConstant(this.codegenBinding.constant(), implicitConversion);
-				}
-			} else {
+			}
+			if (valueRequired) {
+				codeStream.generateConstant(fieldConstant, implicitConversion);
+			}
+		} else {
+			if (valueRequired || (!isThisReceiver && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)) {
 				receiver.generateCode(currentScope, codeStream, !isStatic);
-				if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
-					if (this.codegenBinding.declaringClass == null) { // array length
-						codeStream.arraylength();
-						if (valueRequired) {
-							codeStream.generateImplicitConversion(implicitConversion);
-						} else {
-							// could occur if !valueRequired but compliance >= 1.4
-							codeStream.pop();
-						}
+				if (this.codegenBinding.declaringClass == null) { // array length
+					codeStream.arraylength();
+					if (valueRequired) {
+						codeStream.generateImplicitConversion(implicitConversion);
 					} else {
-						if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
-							if (isStatic) {
-								codeStream.getstatic(this.codegenBinding);
-							} else {
-								codeStream.getfield(this.codegenBinding);
-							}
-						} else {
-							codeStream.invokestatic(syntheticAccessors[READ]);
-						}
-						if (valueRequired) {
-							if (this.genericCast != null) codeStream.checkcast(this.genericCast);			
-							codeStream.generateImplicitConversion(implicitConversion);
-						} else {
-							// could occur if !valueRequired but compliance >= 1.4
-							switch (this.codegenBinding.type.id) {
-								case T_long :
-								case T_double :
-									codeStream.pop2();
-									break;
-								default :
-									codeStream.pop();
-							}
-						}
+						// could occur if !valueRequired but compliance >= 1.4
+						codeStream.pop();
 					}
 				} else {
+					if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
+						if (isStatic) {
+							codeStream.getstatic(this.codegenBinding);
+						} else {
+							codeStream.getfield(this.codegenBinding);
+						}
+					} else {
+						codeStream.invokestatic(syntheticAccessors[READ]);
+					}
+					if (valueRequired) {
+						if (this.genericCast != null) codeStream.checkcast(this.genericCast);			
+						codeStream.generateImplicitConversion(implicitConversion);
+					} else {
+						// could occur if !valueRequired but compliance >= 1.4
+						switch (this.codegenBinding.type.id) {
+							case T_long :
+							case T_double :
+								codeStream.pop2();
+								break;
+							default :
+								codeStream.pop();
+						}
+					}
+				}
+			} else {
+				if (!isThisReceiver) {
+					receiver.generateCode(currentScope, codeStream, !isStatic);				
 					if (!isStatic){
-						if (!(this.receiver instanceof ThisReference)) codeStream.invokeObjectGetClass(); // perform null check
+						codeStream.invokeObjectGetClass(); // perform null check
 						codeStream.pop();
 					}
 				}
 			}
 		}
-		codeStream.recordPositionsFrom(pc, this.sourceStart);
 	}
+	codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
 
-	public void generateCompoundAssignment(
-		BlockScope currentScope,
-		CodeStream codeStream,
-		Expression expression,
-		int operator,
-		int assignmentImplicitConversion,
-		boolean valueRequired) {
-
-		boolean isStatic;
-		receiver.generateCode(
-			currentScope,
-			codeStream,
-			!(isStatic = this.codegenBinding.isStatic()));
-		if (isStatic) {
-			if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
-				codeStream.getstatic(this.codegenBinding);
-			} else {
-				codeStream.invokestatic(syntheticAccessors[READ]);
-			}
+public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
+	boolean isStatic;
+	receiver.generateCode(
+		currentScope,
+		codeStream,
+		!(isStatic = this.codegenBinding.isStatic()));
+	if (isStatic) {
+		if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
+			codeStream.getstatic(this.codegenBinding);
 		} else {
-			codeStream.dup();
-			if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
-				codeStream.getfield(this.codegenBinding);
-			} else {
-				codeStream.invokestatic(syntheticAccessors[READ]);
-			}
+			codeStream.invokestatic(syntheticAccessors[READ]);
 		}
-		int operationTypeID;
-		switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
-			case T_JavaLangString :
-			case T_JavaLangObject :
-			case T_undefined :
-				codeStream.generateStringConcatenationAppend(currentScope, null, expression);
-				break;
-			default :
-				if (this.genericCast != null)
-					codeStream.checkcast(this.genericCast);				
-				// 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 {
-					expression.generateCode(currentScope, codeStream, true);
-				}
-				// perform the operation
-				codeStream.sendOperator(operator, operationTypeID);
-				// cast the value back to the array reference type
-				codeStream.generateImplicitConversion(assignmentImplicitConversion);
-		}
-		fieldStore(
-			codeStream,
-			this.codegenBinding,
-			syntheticAccessors == null ? null : syntheticAccessors[WRITE],
-			valueRequired);
-		// no need for generic cast as value got dupped
-	}
-
-	public void generatePostIncrement(
-		BlockScope currentScope,
-		CodeStream codeStream,
-		CompoundAssignment postIncrement,
-		boolean valueRequired) {
-
-		boolean isStatic;
-		receiver.generateCode(
-			currentScope,
-			codeStream,
-			!(isStatic = this.codegenBinding.isStatic()));
-		if (isStatic) {
-			if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
-				codeStream.getstatic(this.codegenBinding);
-			} else {
-				codeStream.invokestatic(syntheticAccessors[READ]);
-			}
+	} else {
+		codeStream.dup();
+		if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
+			codeStream.getfield(this.codegenBinding);
 		} else {
-			codeStream.dup();
-			if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
-				codeStream.getfield(this.codegenBinding);
+			codeStream.invokestatic(syntheticAccessors[READ]);
+		}
+	}
+	int operationTypeID;
+	switch(operationTypeID = (implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) {
+		case T_JavaLangString :
+		case T_JavaLangObject :
+		case T_undefined :
+			codeStream.generateStringConcatenationAppend(currentScope, null, expression);
+			break;
+		default :
+			if (this.genericCast != null)
+				codeStream.checkcast(this.genericCast);				
+			// 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 {
-				codeStream.invokestatic(syntheticAccessors[READ]);
+				expression.generateCode(currentScope, codeStream, true);
+			}
+			// perform the operation
+			codeStream.sendOperator(operator, operationTypeID);
+			// cast the value back to the array reference type
+			codeStream.generateImplicitConversion(assignmentImplicitConversion);
+	}
+	fieldStore(
+		codeStream,
+		this.codegenBinding,
+		syntheticAccessors == null ? null : syntheticAccessors[WRITE],
+		valueRequired);
+	// no need for generic cast as value got dupped
+}
+
+/**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#generatedType(Scope)
+ */
+public TypeBinding generatedType(Scope scope) {
+	TypeBinding convertedType = this.resolvedType;
+	if (this.genericCast != null) 
+		convertedType = this.genericCast;
+	int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
+	switch (runtimeType) {
+		case T_boolean :
+			convertedType = BooleanBinding;
+			break;
+		case T_byte :
+			convertedType = ByteBinding;
+			break;
+		case T_short :
+			convertedType = ShortBinding;
+			break;
+		case T_char :
+			convertedType = CharBinding;
+			break;
+		case T_int :
+			convertedType = IntBinding;
+			break;
+		case T_float :
+			convertedType = FloatBinding;
+			break;
+		case T_long :
+			convertedType = LongBinding;
+			break;
+		case T_double :
+			convertedType = DoubleBinding;
+			break;
+		default :
+	}		
+	if ((this.implicitConversion & BOXING) != 0) {
+		convertedType = scope.environment().computeBoxingType(convertedType);
+	}
+	return convertedType;
+}	
+
+public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
+	boolean isStatic;
+	receiver.generateCode(
+		currentScope,
+		codeStream,
+		!(isStatic = this.codegenBinding.isStatic()));
+	if (isStatic) {
+		if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
+			codeStream.getstatic(this.codegenBinding);
+		} else {
+			codeStream.invokestatic(syntheticAccessors[READ]);
+		}
+	} else {
+		codeStream.dup();
+		if (syntheticAccessors == null || syntheticAccessors[READ] == null) {
+			codeStream.getfield(this.codegenBinding);
+		} else {
+			codeStream.invokestatic(syntheticAccessors[READ]);
+		}
+	}
+	if (valueRequired) {
+		if (isStatic) {
+			if ((this.codegenBinding.type == LongBinding)
+				|| (this.codegenBinding.type == DoubleBinding)) {
+				codeStream.dup2();
+			} else {
+				codeStream.dup();
+			}
+		} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
+			if ((this.codegenBinding.type == LongBinding)
+				|| (this.codegenBinding.type == DoubleBinding)) {
+				codeStream.dup2_x1();
+			} else {
+				codeStream.dup_x1();
 			}
 		}
-		if (valueRequired) {
-			if (isStatic) {
-				if ((this.codegenBinding.type == LongBinding)
-					|| (this.codegenBinding.type == DoubleBinding)) {
-					codeStream.dup2();
-				} else {
-					codeStream.dup();
-				}
-			} else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
-				if ((this.codegenBinding.type == LongBinding)
-					|| (this.codegenBinding.type == DoubleBinding)) {
-					codeStream.dup2_x1();
-				} else {
-					codeStream.dup_x1();
-				}
-			}
-		}
-		if (this.genericCast != null)
-			codeStream.checkcast(this.genericCast);
-		codeStream.generateImplicitConversion(this.implicitConversion);		
-		codeStream.generateConstant(
-			postIncrement.expression.constant,
-			this.implicitConversion);
-		codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
-		codeStream.generateImplicitConversion(
-			postIncrement.preAssignImplicitConversion);
-		fieldStore(codeStream, this.codegenBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], false);
 	}
-	/**
-	 * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
-	 */
-	public TypeBinding[] genericTypeArguments() {
-		return null;
-	}
-	public static final Constant getConstantFor(
-		FieldBinding binding,
-		Reference reference,
-		boolean isImplicit,
-		Scope referenceScope) {
+	if (this.genericCast != null)
+		codeStream.checkcast(this.genericCast);
+	codeStream.generateImplicitConversion(this.implicitConversion);		
+	codeStream.generateConstant(
+		postIncrement.expression.constant,
+		this.implicitConversion);
+	codeStream.sendOperator(postIncrement.operator, this.implicitConversion & COMPILE_TYPE_MASK);
+	codeStream.generateImplicitConversion(
+		postIncrement.preAssignImplicitConversion);
+	fieldStore(codeStream, this.codegenBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], false);
+}
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
+ */
+public TypeBinding[] genericTypeArguments() {
+	return null;
+}
 
-		//propagation of the constant.
+public boolean isSuperAccess() {
+	return receiver.isSuper();
+}
 
-		//ref can be a FieldReference, a SingleNameReference or a QualifiedNameReference
-		//indexInQualification may have a value greater than zero only for QualifiednameReference
-		//if ref==null then indexInQualification==0 AND implicitReceiver == false. This case is a 
-		//degenerated case where a fake reference field (null) 
-		//is associted to a real FieldBinding in order 
-		//to allow its constant computation using the regular path (in other words, find the fieldDeclaration
-		//and proceed to its type resolution). As implicitReceiver is false, no error reporting
-		//against ref will be used ==> no nullPointerException risk .... 
+public boolean isTypeAccess() {
+	return receiver != null && receiver.isTypeReference();
+}
 
-		//special treatment for langage-built-in  field (their declaring class is null)
-		if (binding.declaringClass == null) {
-			//currently only one field "length" : the constant computation is never done
-			return NotAConstant;
-		}
-		if (!binding.isFinal()) {
-			binding.setConstant(NotAConstant);
-			return NotAConstant;
-		}
-		Constant fieldConstant = binding.constant();
-		if (fieldConstant != null) {
-			if (isImplicit || (reference instanceof QualifiedNameReference
-					&& binding == ((QualifiedNameReference)reference).binding)) {
-				return fieldConstant;
-			}
-			return NotAConstant;
-		}
-
-		//The field has not been yet type checked.
-		//It also means that the field is not coming from a class that
-		//has already been compiled. It can only be from a class within
-		//compilation units to process. Thus the field is NOT from a BinaryTypeBinbing
-
-		FieldBinding originalField = binding.original();
-		SourceTypeBinding sourceType = (SourceTypeBinding) originalField.declaringClass;
-		TypeDeclaration typeDecl = sourceType.scope.referenceContext;
-		FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField);
-
-		fieldDecl.resolve(originalField.isStatic() //side effect on binding 
-				? typeDecl.staticInitializerScope
-				: typeDecl.initializerScope); 
-
-		if (isImplicit || (reference instanceof QualifiedNameReference
-				&& binding == ((QualifiedNameReference)reference).binding)) {
-			return binding.constant();
-		}
-		return NotAConstant;
-	}
-
-	public boolean isSuperAccess() {
-
-		return receiver.isSuper();
-	}
-
-	public boolean isTypeAccess() {
-
-		return receiver != null && receiver.isTypeReference();
-	}
-
-	/*
-	 * No need to emulate access to protected fields since not implicitly accessed
-	 */
-	public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) {
-
-		if (!flowInfo.isReachable()) return;
-		// if field from parameterized type got found, use the original field at codegen time
-		this.codegenBinding = this.binding.original();
-		
-		if (binding.isPrivate()) {
-			if ((currentScope.enclosingSourceType() != this.codegenBinding.declaringClass) && !binding.isConstantValue()) {
-				if (syntheticAccessors == null)
-					syntheticAccessors = new MethodBinding[2];
-				syntheticAccessors[isReadAccess ? READ : WRITE] = 
-					((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isReadAccess);
-				currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
-				return;
-			}
-
-		} else if (receiver instanceof QualifiedSuperReference) { // qualified super
-
-			// qualified super need emulation always
-			SourceTypeBinding destinationType =
-				(SourceTypeBinding) (((QualifiedSuperReference) receiver)
-					.currentCompatibleType);
+/*
+ * No need to emulate access to protected fields since not implicitly accessed
+ */
+public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) {
+	if (!flowInfo.isReachable()) return;
+	// if field from parameterized type got found, use the original field at codegen time
+	this.codegenBinding = this.binding.original();
+	
+	if (binding.isPrivate()) {
+		if ((currentScope.enclosingSourceType() != this.codegenBinding.declaringClass) 
+				&& binding.constant() == Constant.NotAConstant) {
 			if (syntheticAccessors == null)
 				syntheticAccessors = new MethodBinding[2];
-			syntheticAccessors[isReadAccess ? READ : WRITE] = destinationType.addSyntheticMethod(this.codegenBinding, isReadAccess);
+			syntheticAccessors[isReadAccess ? READ : WRITE] = 
+				((SourceTypeBinding) this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isReadAccess);
 			currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
 			return;
-
-		} else if (binding.isProtected()) {
-
-			SourceTypeBinding enclosingSourceType;
-			if (((bits & DepthMASK) != 0)
-				&& binding.declaringClass.getPackage()
-					!= (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()) {
-
-				SourceTypeBinding currentCompatibleType =
-					(SourceTypeBinding) enclosingSourceType.enclosingTypeAt(
-						(bits & DepthMASK) >> DepthSHIFT);
-				if (syntheticAccessors == null)
-					syntheticAccessors = new MethodBinding[2];
-				syntheticAccessors[isReadAccess ? READ : WRITE] = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isReadAccess);
-				currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
-				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 (this.binding.declaringClass != this.receiverType
-				&& !this.receiverType.isArrayType()
-				&& this.binding.declaringClass != null // array.length
-				&& !this.binding.isConstantValue()) {
-			CompilerOptions options = currentScope.compilerOptions();
-			if ((options.targetJDK >= ClassFileConstants.JDK1_2
-					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !receiver.isImplicitThis() || !this.codegenBinding.isStatic())
-					&& this.binding.declaringClass.id != T_JavaLangObject) // no change for Object fields
-				|| !this.binding.declaringClass.canBeSeenBy(currentScope)) {
-	
-				this.codegenBinding =
-					currentScope.enclosingSourceType().getUpdatedFieldBinding(
-						this.codegenBinding,
-						(ReferenceBinding) this.receiverType.erasure());
-			}
-		}		
-	}
 
-	public Constant optimizedBooleanConstant() {
+	} else if (receiver instanceof QualifiedSuperReference) { // qualified super
 
-		switch (this.resolvedType.id) {
-			case T_boolean :
-			case T_JavaLangBoolean :		
-				return this.constant != NotAConstant ? this.constant : this.binding.constant();
-			default :
-				return NotAConstant;
+		// qualified super need emulation always
+		SourceTypeBinding destinationType =
+			(SourceTypeBinding) (((QualifiedSuperReference) receiver)
+				.currentCompatibleType);
+		if (syntheticAccessors == null)
+			syntheticAccessors = new MethodBinding[2];
+		syntheticAccessors[isReadAccess ? READ : WRITE] = destinationType.addSyntheticMethod(this.codegenBinding, isReadAccess);
+		currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
+		return;
+
+	} else if (binding.isProtected()) {
+
+		SourceTypeBinding enclosingSourceType;
+		if (((bits & DepthMASK) != 0)
+			&& binding.declaringClass.getPackage()
+				!= (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()) {
+
+			SourceTypeBinding currentCompatibleType =
+				(SourceTypeBinding) enclosingSourceType.enclosingTypeAt(
+					(bits & DepthMASK) >> DepthSHIFT);
+			if (syntheticAccessors == null)
+				syntheticAccessors = new MethodBinding[2];
+			syntheticAccessors[isReadAccess ? READ : WRITE] = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isReadAccess);
+			currentScope.problemReporter().needToEmulateFieldAccess(this.codegenBinding, this, isReadAccess);
+			return;
 		}
 	}
-	
-	public StringBuffer printExpression(int indent, StringBuffer output) {
+	// 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 (this.binding.declaringClass != this.receiverType
+			&& !this.receiverType.isArrayType()
+			&& this.binding.declaringClass != null // array.length
+			&& this.binding.constant() == Constant.NotAConstant) {
+		CompilerOptions options = currentScope.compilerOptions();
+		if ((options.targetJDK >= ClassFileConstants.JDK1_2
+				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(receiver.isImplicitThis() && this.codegenBinding.isStatic()))
+				&& this.binding.declaringClass.id != T_JavaLangObject) // no change for Object fields
+			|| !this.binding.declaringClass.canBeSeenBy(currentScope)) {
 
-		return receiver.printExpression(0, output).append('.').append(token);
+			this.codegenBinding =
+				currentScope.enclosingSourceType().getUpdatedFieldBinding(
+					this.codegenBinding,
+					(ReferenceBinding) this.receiverType.erasure());
+		}
+	}		
+}
+
+public Constant optimizedBooleanConstant() {
+	switch (this.resolvedType.id) {
+		case T_boolean :
+		case T_JavaLangBoolean :		
+			return this.constant != Constant.NotAConstant ? this.constant : this.binding.constant();
+		default :
+			return Constant.NotAConstant;
 	}
-	
-	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 
+public StringBuffer printExpression(int indent, StringBuffer output) {
+	return receiver.printExpression(0, output).append('.').append(token);
+}
 
-		//always ignore receiver cast, since may affect constant pool reference
-		boolean receiverCast = false;
-		if (this.receiver instanceof CastExpression) {
-			this.receiver.bits |= DisableUnnecessaryCastCheck; // 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
-		FieldBinding fieldBinding = this.codegenBinding = this.binding = scope.getField(this.receiverType, token, this);
-		if (!fieldBinding.isValidBinding()) {
-			constant = NotAConstant;
-			scope.problemReporter().invalidField(this, this.receiverType);
-			return null;
-		}
-		TypeBinding receiverErasure = this.receiverType.erasure();
-		if (receiverErasure instanceof ReferenceBinding) {
-			ReferenceBinding match = ((ReferenceBinding)receiverErasure).findSuperTypeWithSameErasure(fieldBinding.declaringClass);
-			if (match == null) {
-				this.receiverType = fieldBinding.declaringClass; // handle indirect inheritance thru variable secondary bound
-			}
-		}
-		this.receiver.computeConversion(scope, this.receiverType, this.receiverType);
-		if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssigned) !=0)) {
-			scope.problemReporter().deprecatedField(fieldBinding, this);
-		}
-		boolean isImplicitThisRcv = receiver.isImplicitThis();
-		constant = FieldReference.getConstantFor(fieldBinding, this, isImplicitThisRcv, scope);
-		if (!isImplicitThisRcv) {
-			constant = NotAConstant;
-		}
-		if (fieldBinding.isStatic()) {
-			// static field accessed through receiver? legal but unoptimal (optional warning)
-			if (!(isImplicitThisRcv
-					|| (receiver instanceof NameReference 
-						&& (((NameReference) receiver).bits & Binding.TYPE) != 0))) {
-				scope.problemReporter().nonStaticAccessToStaticField(this, fieldBinding);
-			}
-			if (!isImplicitThisRcv && fieldBinding.declaringClass != receiverType) {
-				scope.problemReporter().indirectAccessToStaticField(this, fieldBinding);
-			}
-		}
-		// perform capture conversion if read access
-		return this.resolvedType = 
-			(((this.bits & IsStrictlyAssigned) == 0) 
-				? fieldBinding.type.capture(scope, this.sourceEnd)
-				: fieldBinding.type);
+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 
+
+	//always ignore receiver cast, since may affect constant pool reference
+	boolean receiverCast = false;
+	if (this.receiver instanceof CastExpression) {
+		this.receiver.bits |= DisableUnnecessaryCastCheck; // will check later on
+		receiverCast = true;
 	}
-
-	public void setActualReceiverType(ReferenceBinding receiverType) {
-		// ignored
+	this.receiverType = receiver.resolveType(scope);
+	if (this.receiverType == null) {
+		constant = Constant.NotAConstant;
+		return null;
 	}
-
-	public void setDepth(int depth) {
-
-		bits &= ~DepthMASK; // flush previous depth if any			
-		if (depth > 0) {
-			bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits
+	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
+	FieldBinding fieldBinding = this.codegenBinding = this.binding = scope.getField(this.receiverType, token, this);
+	if (!fieldBinding.isValidBinding()) {
+		constant = Constant.NotAConstant;
+		scope.problemReporter().invalidField(this, this.receiverType);
+		return null;
+	}
+	TypeBinding receiverErasure = this.receiverType.erasure();
+	if (receiverErasure instanceof ReferenceBinding) {
+		ReferenceBinding match = ((ReferenceBinding)receiverErasure).findSuperTypeWithSameErasure(fieldBinding.declaringClass);
+		if (match == null) {
+			this.receiverType = fieldBinding.declaringClass; // handle indirect inheritance thru variable secondary bound
 		}
 	}
-
-	public void setFieldIndex(int index) {
-		// ignored
+	this.receiver.computeConversion(scope, this.receiverType, this.receiverType);
+	if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssigned) !=0)) {
+		scope.problemReporter().deprecatedField(fieldBinding, this);
 	}
-
-	public void traverse(ASTVisitor visitor, BlockScope scope) {
-
-		if (visitor.visit(this, scope)) {
-			receiver.traverse(visitor, scope);
+	boolean isImplicitThisRcv = receiver.isImplicitThis();
+	constant = isImplicitThisRcv ? fieldBinding.constant() : Constant.NotAConstant;
+	if (!isImplicitThisRcv) {
+		constant = Constant.NotAConstant;
+	}
+	if (fieldBinding.isStatic()) {
+		// static field accessed through receiver? legal but unoptimal (optional warning)
+		if (!(isImplicitThisRcv
+				|| (receiver instanceof NameReference 
+					&& (((NameReference) receiver).bits & Binding.TYPE) != 0))) {
+			scope.problemReporter().nonStaticAccessToStaticField(this, fieldBinding);
 		}
-		visitor.endVisit(this, scope);
+		if (!isImplicitThisRcv && fieldBinding.declaringClass != receiverType) {
+			scope.problemReporter().indirectAccessToStaticField(this, fieldBinding);
+		}
 	}
+	// perform capture conversion if read access
+	return this.resolvedType = 
+		(((this.bits & IsStrictlyAssigned) == 0) 
+			? fieldBinding.type.capture(scope, this.sourceEnd)
+			: fieldBinding.type);
+}
+
+public void setActualReceiverType(ReferenceBinding receiverType) {
+	// ignored
+}
+
+public void setDepth(int depth) {
+	bits &= ~DepthMASK; // flush previous depth if any			
+	if (depth > 0) {
+		bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits
+	}
+}
+
+public void setFieldIndex(int index) {
+	// ignored
+}
+
+public void traverse(ASTVisitor visitor, BlockScope scope) {
+	if (visitor.visit(this, scope)) {
+		receiver.traverse(visitor, scope);
+	}
+	visitor.endVisit(this, scope);
+}
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
index 09d9663..76d6e57 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
@@ -74,12 +74,12 @@
 			currentScope.methodScope().recordInitializationStates(flowInfo);
 
 		Constant cst = this.condition == null ? null : this.condition.constant;
-		boolean isConditionTrue = cst == null || (cst != NotAConstant && cst.booleanValue() == true);
-		boolean isConditionFalse = cst != null && (cst != NotAConstant && cst.booleanValue() == false);
+		boolean isConditionTrue = cst == null || (cst != Constant.NotAConstant && cst.booleanValue() == true);
+		boolean isConditionFalse = cst != null && (cst != Constant.NotAConstant && cst.booleanValue() == false);
 
 		cst = this.condition == null ? null : this.condition.optimizedBooleanConstant();
-		boolean isConditionOptimizedTrue = cst == null ||  (cst != NotAConstant && cst.booleanValue() == true);
-		boolean isConditionOptimizedFalse = cst != null && (cst != NotAConstant && cst.booleanValue() == false);
+		boolean isConditionOptimizedTrue = cst == null ||  (cst != Constant.NotAConstant && cst.booleanValue() == true);
+		boolean isConditionOptimizedFalse = cst != null && (cst != Constant.NotAConstant && cst.booleanValue() == false);
 		
 		// process the condition
 		LoopingFlowContext condLoopContext = null;
@@ -186,7 +186,22 @@
 				initializations[i].generateCode(scope, codeStream);
 			}
 		}
-
+		Constant cst = this.condition == null ? null : this.condition.optimizedBooleanConstant();
+		boolean isConditionOptimizedFalse = cst != null && (cst != Constant.NotAConstant && cst.booleanValue() == false);
+		if (isConditionOptimizedFalse) {
+			condition.generateCode(scope, codeStream, false);
+			// May loose some local variable initializations : affecting the local variable attributes
+			if (neededScope) {
+				codeStream.exitUserScope(scope);
+			}
+			if (mergedInitStateIndex != -1) {
+				codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+				codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+			}
+			codeStream.recordPositionsFrom(pc, this.sourceStart);
+			return;
+		}
+		
 		// label management
 		Label actionLabel = new Label(codeStream);
 		Label conditionLabel = new Label(codeStream);
@@ -196,7 +211,7 @@
 		}
 		// jump over the actionBlock
 		if ((condition != null)
-			&& (condition.constant == NotAConstant)
+			&& (condition.constant == Constant.NotAConstant)
 			&& !((action == null || action.isEmptyBlock()) && (increments == null))) {
 			int jumpPC = codeStream.position;
 			codeStream.goto_(conditionLabel);
@@ -232,7 +247,7 @@
 
 		// generate the condition
 		conditionLabel.place();
-		if ((condition != null) && (condition.constant == NotAConstant)) {
+		if ((condition != null) && (condition.constant == Constant.NotAConstant)) {
 			condition.generateOptimizedBoolean(scope, codeStream, actionLabel, null, true);
 		} else {
 			if (continueLabel != null) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
index f6e5bf7..cc85af6 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ForeachStatement.java
@@ -17,6 +17,7 @@
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.flow.LoopingFlowContext;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -427,23 +428,23 @@
 					// allocate #index secret variable (of type int)
 					this.indexVariable = new LocalVariableBinding(SecretIndexVariableName, IntBinding, ClassFileConstants.AccDefault, false);
 					scope.addLocalVariable(this.indexVariable);
-					this.indexVariable.setConstant(NotAConstant); // not inlinable
+					this.indexVariable.setConstant(Constant.NotAConstant); // not inlinable
 					
 					// allocate #max secret variable
 					this.maxVariable = new LocalVariableBinding(SecretMaxVariableName, IntBinding, ClassFileConstants.AccDefault, false);
 					scope.addLocalVariable(this.maxVariable);
-					this.maxVariable.setConstant(NotAConstant); // not inlinable
+					this.maxVariable.setConstant(Constant.NotAConstant); // not inlinable
 					// add #array secret variable (of collection type)
 					this.collectionVariable = new LocalVariableBinding(SecretCollectionVariableName, collectionType, ClassFileConstants.AccDefault, false);
 					scope.addLocalVariable(this.collectionVariable);
-					this.collectionVariable.setConstant(NotAConstant); // not inlinable
+					this.collectionVariable.setConstant(Constant.NotAConstant); // not inlinable
 					break;
 				case RAW_ITERABLE :
 				case GENERIC_ITERABLE :
 					// allocate #index secret variable (of type Iterator)
 					this.indexVariable = new LocalVariableBinding(SecretIndexVariableName, scope.getJavaUtilIterator(), ClassFileConstants.AccDefault, false);
 					scope.addLocalVariable(this.indexVariable);
-					this.indexVariable.setConstant(NotAConstant); // not inlinable
+					this.indexVariable.setConstant(Constant.NotAConstant); // not inlinable
 					break;
 				default :
 					scope.problemReporter().invalidTypeForCollection(collection);
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
index 292cf00..8fcc47b 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
@@ -63,8 +63,8 @@
 		flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
 
 		Constant cst = this.condition.optimizedBooleanConstant();
-		boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
-		boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+		boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
+		boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;
 		
 		// process the THEN part
 		FlowInfo thenFlowInfo = flowInfo.initsWhenTrue().copy();
@@ -133,12 +133,12 @@
 		// optimizing the then/else part code gen
 		Constant cst;
 		boolean hasThenPart = 
-			!(((cst = this.condition.optimizedBooleanConstant()) != NotAConstant
+			!(((cst = this.condition.optimizedBooleanConstant()) != Constant.NotAConstant
 					&& cst.booleanValue() == false)
 				|| this.thenStatement == null
 				|| this.thenStatement.isEmptyBlock());
 		boolean hasElsePart =
-			!((cst != NotAConstant && cst.booleanValue() == true)
+			!((cst != Constant.NotAConstant && cst.booleanValue() == true)
 				|| this.elseStatement == null
 				|| this.elseStatement.isEmptyBlock());
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index 112a7ca..755f133 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -13,6 +13,7 @@
 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.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class InstanceOfExpression extends OperatorExpression {
@@ -73,7 +74,7 @@
 
 	public TypeBinding resolveType(BlockScope scope) {
 
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		TypeBinding expressionType = expression.resolveType(scope);
 		TypeBinding checkedType = type.resolveType(scope, true /* check bounds*/);
 		if (expressionType == null || checkedType == null)
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java b/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
index 239145a..58b503c 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
@@ -125,7 +125,7 @@
 
 	TypeBinding tb = super.resolveType(scope);
 	if (constant == FORMAT_ERROR) {
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		scope.problemReporter().constantOutOfFormat(this);
 		this.resolvedType = null;
 		return null;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
index 245b2e5..cc1099f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class JavadocAllocationExpression extends AllocationExpression {
@@ -30,7 +31,7 @@
 	private TypeBinding internalResolveType(Scope scope) {
 	
 		// Propagate the type checking to the arguments, and check if the constructor is defined.
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		if (this.type == null) {
 			this.resolvedType = scope.enclosingSourceType();
 		} else if (scope.kind == Scope.CLASS_SCOPE) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java
index e070309..5d755e5 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class JavadocArgumentExpression extends Expression {
@@ -31,7 +32,7 @@
 	 * Resolves type on a Block or Class scope.
 	 */
 	private TypeBinding internalResolveType(Scope scope) {
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		if (this.resolvedType != null) // is a shared type reference which was already resolved
 			return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java
index a61c1b4..0cdcfad 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class JavadocFieldReference extends FieldReference {
@@ -39,7 +40,7 @@
 	 */
 	protected TypeBinding internalResolveType(Scope scope) {
 
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		if (this.receiver == null) {
 			this.receiverType = scope.enclosingSourceType();
 		} else if (scope.kind == Scope.CLASS_SCOPE) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocImplicitTypeReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocImplicitTypeReference.java
index b173c98..835521a 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocImplicitTypeReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocImplicitTypeReference.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class JavadocImplicitTypeReference extends TypeReference {
@@ -34,7 +35,7 @@
 	 * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
 	 */
 	protected TypeBinding getTypeBinding(Scope scope) {
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		return this.resolvedType = scope.enclosingSourceType();
 	}
 
@@ -58,7 +59,7 @@
 	 */
 	private TypeBinding internalResolveType(Scope scope) {
 		// handle the error here
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		if (this.resolvedType != null) // is a shared type reference which was already resolved
 			return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
index ecf97d4..2d9993a 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 
@@ -39,7 +40,7 @@
 	private TypeBinding internalResolveType(Scope scope) {
 		// Answer the signature return type
 		// Base type promotion
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		if (this.receiver == null) {
 			this.actualReceiverType = scope.enclosingSourceType();
 		} else if (scope.kind == Scope.CLASS_SCOPE) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
index 0f4d84c..d85a0a3 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 
@@ -51,7 +52,7 @@
 	 */
 	private TypeBinding internalResolveType(Scope scope, boolean checkBounds) {
 		// handle the error here
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		if (resolvedType != null) // is a shared type reference which was already resolved
 			return resolvedType.isValidBinding() ? resolvedType : null; // already reported error
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
index 48d5262..f8b2e76 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 
@@ -52,7 +53,7 @@
 	 */
 	TypeBinding internalResolveType(Scope scope) {
 		// handle the error here
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		if (this.resolvedType != null)// is a shared type reference which was already resolved
 			return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
index c23615a..cc7b7d3 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
@@ -92,7 +92,7 @@
 		// something to initialize?
 		if (initialization != null) {
 			// initialize to constant value?
-			if ((inlinedValue = initialization.constant) != NotAConstant) {
+			if ((inlinedValue = initialization.constant) != Constant.NotAConstant) {
 				// forget initializing unused or final locals set to constant value (final ones are inlined)
 				if (binding.resolvedPosition != -1) { // may need to preserve variable
 					int initPC = codeStream.position;
@@ -176,7 +176,7 @@
 			}
 			this.binding = new LocalVariableBinding(this, variableType, modifiers, false);
 			scope.addLocalVariable(binding);
-			this.binding.setConstant(NotAConstant);
+			this.binding.setConstant(Constant.NotAConstant);
 			// allow to recursivelly target the binding....
 			// the correct constant is harmed if correctly computed at the end of this method
 		}
@@ -235,7 +235,7 @@
 				binding.setConstant(
 					binding.isFinal()
 						? initialization.constant.castTo((variableType.id << 4) + initialization.constant.typeID())
-						: NotAConstant);
+						: Constant.NotAConstant);
 			}
 		}
 		// only resolve annotation at the end, for constant to be positionned before (96991)
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java b/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
index 300b141..cad3a51 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
@@ -147,7 +147,7 @@
 
 	TypeBinding tb = super.resolveType(scope);
 	if (constant == FORMAT_ERROR) {
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		scope.problemReporter().constantOutOfFormat(this);
 		this.resolvedType = null;
 		return null;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java b/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java
index 1235e8e..055dd60 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java
@@ -11,6 +11,7 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
 import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -114,12 +115,12 @@
 						final Expression[] expressions = initializer.expressions;
 						if (expressions != null) {
 							for (int i =0, max = expressions.length; i < max; i++) {
-								if (expressions[i].constant == NotAConstant) {
+								if (expressions[i].constant == Constant.NotAConstant) {
 									scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, expressions[i]);
 								}
 							}
 						}
-					} else if (this.value.constant == NotAConstant) {
+					} else if (this.value.constant == Constant.NotAConstant) {
 						scope.problemReporter().annotationValueMustBeConstant(this.binding.declaringClass, this.name, this.value);
 					}
 					break checkAnnotationMethodType;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index adf41be..3182abd 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -15,6 +15,7 @@
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 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.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -66,7 +67,7 @@
 	// set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
 	if (this.binding != null && this.binding.isValidBinding()) {
 		MethodBinding originalBinding = this.binding.original();
-		if (originalBinding != this.binding) {
+		if (originalBinding != this.binding && originalBinding.returnType != this.binding.returnType) {
 		    // extra cast needed if method return type has type variable
 		    if ((originalBinding.returnType.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
 		    	TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) 
@@ -85,6 +86,7 @@
 	}
 	super.computeConversion(scope, runtimeTimeType, compileTimeType);
 }
+
 /**
  * MessageSend code generation
  *
@@ -149,6 +151,48 @@
 	}
 	codeStream.recordPositionsFrom(pc, (int)(this.nameSourcePosition >>> 32)); // highlight selector
 }
+
+/**
+ * @see org.eclipse.jdt.internal.compiler.ast.Expression#generatedType(Scope)
+ */
+public TypeBinding generatedType(Scope scope) {
+	TypeBinding convertedType = this.resolvedType;
+	if (this.valueCast != null) 
+		convertedType = this.valueCast;
+	int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
+	switch (runtimeType) {
+		case T_boolean :
+			convertedType = BooleanBinding;
+			break;
+		case T_byte :
+			convertedType = ByteBinding;
+			break;
+		case T_short :
+			convertedType = ShortBinding;
+			break;
+		case T_char :
+			convertedType = CharBinding;
+			break;
+		case T_int :
+			convertedType = IntBinding;
+			break;
+		case T_float :
+			convertedType = FloatBinding;
+			break;
+		case T_long :
+			convertedType = LongBinding;
+			break;
+		case T_double :
+			convertedType = DoubleBinding;
+			break;
+		default :
+	}		
+	if ((this.implicitConversion & BOXING) != 0) {
+		convertedType = scope.environment().computeBoxingType(convertedType);
+	}
+	return convertedType;
+}	
+
 /**
  * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
  */
@@ -207,7 +251,7 @@
 			&& !this.actualReceiverType.isArrayType()) {
 		CompilerOptions options = currentScope.compilerOptions();
 		if ((options.targetJDK >= ClassFileConstants.JDK1_2
-				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !receiver.isImplicitThis() || !this.codegenBinding.isStatic())
+				&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(receiver.isImplicitThis() && this.codegenBinding.isStatic()))
 				&& this.binding.declaringClass.id != T_JavaLangObject) // no change for Object methods
 			|| !this.binding.declaringClass.canBeSeenBy(currentScope)) {
 
@@ -250,7 +294,7 @@
 	// Answer the signature return type
 	// Base type promotion
 
-	constant = NotAConstant;
+	constant = Constant.NotAConstant;
 	boolean receiverCast = false, argsContainCast = false; 
 	if (this.receiver instanceof CastExpression) {
 		this.receiver.bits |= DisableUnnecessaryCastCheck; // will check later on
@@ -295,18 +339,13 @@
 			}
 		}
 		if (argHasError) {
-			if(actualReceiverType instanceof ReferenceBinding) {
-				// record any selector match, for clients who may still need hint about possible method match
-				int resolvedCount = 0;
-				for (int i = 0; i < length; i++)
-					if (argumentTypes[i] != null)
-						resolvedCount++;
-				TypeBinding[] knownArgs = new TypeBinding[resolvedCount];
+			if (actualReceiverType instanceof ReferenceBinding) {
+				//  record a best guess, for clients who need hint about possible method match
+				TypeBinding[] pseudoArgs = new TypeBinding[length];
 				for (int i = length; --i >= 0;)
-					if (argumentTypes[i] != null)
-						knownArgs[--resolvedCount] = argumentTypes[i];
-				this.binding = scope.findMethod((ReferenceBinding)actualReceiverType, selector, knownArgs, this);
-			}			
+					pseudoArgs[i] = argumentTypes[i] == null ? actualReceiverType : argumentTypes[i]; // replace args with errors with receiver
+				this.binding = scope.findMethod((ReferenceBinding) actualReceiverType, selector, pseudoArgs, this);
+			}
 			return null;
 		}
 	}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java b/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
index 88f0d54..9b5029e 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
@@ -13,6 +13,7 @@
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class NullLiteral extends MagicLiteral {
@@ -26,7 +27,7 @@
 
 	public void computeConstant() {
 	
-		constant = NotAConstant; 
+		constant = Constant.NotAConstant; 
 	}
 
 	/**
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
index 3a59eff..1a6a369 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
@@ -32,8 +32,8 @@
 		FlowInfo flowInfo) {
 
 		Constant cst = this.left.optimizedBooleanConstant();
-		boolean isLeftOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
-		boolean isLeftOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+		boolean isLeftOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
+		boolean isLeftOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;
 
 		if (isLeftOptimizedFalse) {
 			// FALSE || anything
@@ -86,7 +86,7 @@
 			return;
 		}
 		Constant cst = right.constant;
-		if (cst != NotAConstant) {
+		if (cst != Constant.NotAConstant) {
 			// <expr> || true --> true
 			if (cst.booleanValue() == true) {
 				this.left.generateCode(currentScope, codeStream, false);
@@ -106,11 +106,11 @@
 		
 		Label trueLabel = new Label(codeStream), endLabel;
 		cst = left.optimizedBooleanConstant();
-		boolean leftIsConst = cst != NotAConstant;
+		boolean leftIsConst = cst != Constant.NotAConstant;
 		boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
 
 		cst = right.optimizedBooleanConstant();
-		boolean rightIsConst = cst != NotAConstant;
+		boolean rightIsConst = cst != Constant.NotAConstant;
 		boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
 
 		generateOperands : {
@@ -187,7 +187,7 @@
 
 		// <expr> || false --> <expr>
 		Constant cst = right.constant;
-		if (cst != NotAConstant && cst.booleanValue() == false) {
+		if (cst != Constant.NotAConstant && cst.booleanValue() == false) {
 			int pc = codeStream.position;
 			this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
 			if (mergedInitStateIndex != -1) {
@@ -198,11 +198,11 @@
 		}
 	
 		cst = left.optimizedBooleanConstant();
-		boolean leftIsConst = cst != NotAConstant;
+		boolean leftIsConst = cst != Constant.NotAConstant;
 		boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
 
 		cst = right.optimizedBooleanConstant();
-		boolean rightIsConst = cst != NotAConstant;
+		boolean rightIsConst = cst != Constant.NotAConstant;
 		boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
 
 		// default case
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
index c389e47..9aec8ae 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 /**
@@ -109,7 +110,7 @@
 	private TypeBinding internalResolveType(Scope scope, boolean checkBounds) {
 
 		// handle the error here
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		if (this.didResolve) { // is a shared type reference which was already resolved
 			if (this.resolvedType != null && !this.resolvedType.isValidBinding())
 				return null; // already reported error
@@ -136,8 +137,10 @@
 			ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
 			if (qualifiedType == null) {
 				qualifiedType = currentType.enclosingType(); // if member type
-				if (qualifiedType != null && currentType.isStatic() && (qualifiedType.isGenericType() || qualifiedType.isParameterizedType())) {
-					qualifiedType = scope.environment().createRawType((ReferenceBinding)qualifiedType.erasure(), qualifiedType.enclosingType());
+				if (qualifiedType != null && qualifiedType.isGenericType()) {
+					qualifiedType = currentType.isStatic()
+						? (ReferenceBinding) scope.environment().convertToRawType(qualifiedType)
+						: scope.environment().convertToParameterizedType(qualifiedType);
 				}
 			}				
 			if (typeIsConsistent && currentType.isStatic() && qualifiedType != null && (qualifiedType.isParameterizedType() || qualifiedType.isGenericType())) {
@@ -189,25 +192,11 @@
 							this, scope.environment().createRawType((ReferenceBinding)currentType.erasure(), qualifiedType), argTypes);
 					typeIsConsistent = false;				
 				}
-				// if generic type X<T> is referred to as parameterized X<T>, then answer itself
-				boolean isIdentical = (qualifiedType == null) || (qualifiedType instanceof SourceTypeBinding);
-				if (isIdentical) {
-				    for (int j = 0; j < argLength; j++) {
-						if (typeVariables[j] != argTypes[j]) {
-							isIdentical = false;
-						    break;
-						}
-					}
-				}
-			    if (isIdentical) {
-			    	qualifiedType = (ReferenceBinding) currentType.erasure();
-			    } else {
-					ParameterizedTypeBinding parameterizedType = scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), argTypes, qualifiedType);
-					// check argument type compatibility
-					if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
-						parameterizedType.boundCheck(scope, args);
-					qualifiedType = parameterizedType;
-			    }
+				ParameterizedTypeBinding parameterizedType = scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), argTypes, qualifiedType);
+				// check argument type compatibility
+				if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
+					parameterizedType.boundCheck(scope, args);
+				qualifiedType = parameterizedType;
 		    } else {
 				if (isClassScope)
 					if (((ClassScope) scope).detectHierarchyCycle(currentType, this, null))
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
index f9faa0e..f5c77ef 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 /**
@@ -87,7 +88,7 @@
 	private TypeBinding internalResolveType(Scope scope, ReferenceBinding enclosingType, boolean checkBounds) {
 
 		// handle the error here
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		if (this.didResolve) { // is a shared type reference which was already resolved
 			if (this.resolvedType != null && !this.resolvedType.isValidBinding())
 				return null; // already reported error
@@ -101,13 +102,11 @@
 				return null;
 			}
 			enclosingType = this.resolvedType.enclosingType(); // if member type
-			if (enclosingType != null) {
+			if (enclosingType != null && enclosingType.isGenericType()) {
 				ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
-				if (currentType.isStatic() 
-						|| (enclosingType.isGenericType() 
-								&& enclosingType.outermostEnclosingType() != scope.outerMostClassScope().referenceContext.binding)) {
-					enclosingType = (ReferenceBinding) scope.environment().convertToRawType(enclosingType);
-				}
+				enclosingType = currentType.isStatic()
+				? (ReferenceBinding) scope.environment().convertToRawType(enclosingType)
+				: scope.environment().convertToParameterizedType(enclosingType);
 			}
 		} else { // resolving member type (relatively to enclosingType)
 			this.resolvedType = scope.getMemberType(token, (ReferenceBinding)enclosingType.erasure());		    
@@ -161,28 +160,15 @@
 			return null;
 		}
 
-		// if generic type X<T> is referred to as parameterized X<T>, then answer itself
-		boolean isIdentical = true; //this.resolvedType instanceof SourceTypeBinding;
-		if (isIdentical) {
-		    for (int i = 0; i < argLength; i++) {
-				if (typeVariables[i] != argTypes[i]) {
-					isIdentical = false;
-				    break;
-				}
-			}
-		}		
-	    if (!isIdentical) {
-	    	ParameterizedTypeBinding parameterizedType = scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), argTypes, enclosingType);
-			// check argument type compatibility
-			if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
-				parameterizedType.boundCheck(scope, this.typeArguments);
-	
-			this.resolvedType = parameterizedType;
-			if (isTypeUseDeprecated(this.resolvedType, scope))
-				reportDeprecatedType(scope);
-		} else {
-			this.resolvedType = this.resolvedType.erasure();
-		}
+    	ParameterizedTypeBinding parameterizedType = scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), argTypes, enclosingType);
+		// check argument type compatibility
+		if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method resolution
+			parameterizedType.boundCheck(scope, this.typeArguments);
+
+		this.resolvedType = parameterizedType;
+		if (isTypeUseDeprecated(this.resolvedType, scope))
+			reportDeprecatedType(scope);
+
 		// array type ?
 		if (this.dimensions > 0) {
 			if (dimensions > 255)
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index 0b098c3..efe164f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -14,6 +14,7 @@
 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.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 /**
@@ -198,7 +199,7 @@
 		// ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
 		// ClassInstanceCreationExpression ::= Name '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
 		
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		TypeBinding enclosingInstanceType = null;
 		TypeBinding receiverType = null;
 		boolean hasError = false;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
index 6c925a8..f43fb63 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
@@ -68,7 +68,7 @@
 						SourceTypeBinding sourceType = methodScope.enclosingSourceType();
 						if (lastFieldBinding.isStatic()
 								&& (sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body
-								&& lastFieldBinding.constant() == NotAConstant
+								&& lastFieldBinding.constant() == Constant.NotAConstant
 								&& !methodScope.isStatic
 								&& methodScope.isInsideInitializerOrConstructor()) {
 							currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(lastFieldBinding, this);
@@ -125,7 +125,7 @@
 		}
 
 		if (isCompound) {
-			if (binding == lastFieldBinding
+			if (otherBindingsCount == 0
 				&& lastFieldBinding.isBlankFinal()
 				&& currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)
 				&& (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) {
@@ -134,20 +134,22 @@
 					this);
 			}
 			TypeBinding lastReceiverType;
-			if (lastFieldBinding == binding){
-				lastReceiverType = this.actualReceiverType;
-			} else if (otherBindingsCount == 1){
-				lastReceiverType = ((VariableBinding)this.binding).type;
-			} else {
-				lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
+			switch (otherBindingsCount) {
+				case 0 :
+					lastReceiverType = this.actualReceiverType;
+					break;
+				case 1 :
+					lastReceiverType = ((VariableBinding)this.binding).type;
+					break;
+				default:
+					lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
+					break;
 			}
 			manageSyntheticAccessIfNecessary(
 				currentScope,
 				lastFieldBinding,
 				lastReceiverType,
-				lastFieldBinding == binding
-					? 0 
-					: otherBindingsCount, 
+				otherBindingsCount, 
 				flowInfo);
 		}
 		
@@ -181,12 +183,16 @@
 		}
 		// equivalent to valuesRequired[maxOtherBindings]
 		TypeBinding lastReceiverType;
-		if (lastFieldBinding == binding){
-			lastReceiverType = this.actualReceiverType;
-		} else if (otherBindingsCount == 1){
-			lastReceiverType = ((VariableBinding)this.binding).type;
-		} else {
-			lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
+		switch (otherBindingsCount) {
+			case 0 :
+				lastReceiverType = this.actualReceiverType;
+				break;
+			case 1 :
+				lastReceiverType = ((VariableBinding)this.binding).type;
+				break;
+			default :
+				lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
+				break;
 		}
 		manageSyntheticAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, -1 /*write-access*/, flowInfo);
 
@@ -214,7 +220,7 @@
 		boolean complyTo14 = currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4;
 		switch (bits & RestrictiveFlagMASK) {
 			case Binding.FIELD : // reading a field
-				if (needValue || complyTo14) {
+				if (needValue) {
 					manageSyntheticAccessIfNecessary(currentScope, (FieldBinding) binding, this.actualReceiverType, 0, flowInfo);
 				}
 				if (this.indexOfFirstFieldBinding == 1) { // was an implicit reference to the first field binding
@@ -226,7 +232,7 @@
 						SourceTypeBinding sourceType = methodScope.enclosingSourceType();
 						if (fieldBinding.isStatic()
 								&& (sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body
-								&& fieldBinding.constant() == NotAConstant
+								&& fieldBinding.constant() == Constant.NotAConstant
 								&& !methodScope.isStatic
 								&& methodScope.isInsideInitializerOrConstructor()) {
 							currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this);
@@ -255,12 +261,12 @@
 		}
 		if (needValue) {
 			manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
-			// only for first binding
+			// only for first binding (if value needed only)
 		}
 		if (otherBindings != null) {
 			for (int i = 0; i < otherBindingsCount; i++) {
 				needValue = i < otherBindingsCount-1 ? !otherBindings[i+1].isStatic() : valueRequired;
-				if (needValue || complyTo14) {
+				if (needValue || (i > 0 && complyTo14)) {
 					TypeBinding lastReceiverType = getGenericCast(i);
 					if (lastReceiverType == null) {
 						if (i == 0) {
@@ -317,7 +323,7 @@
 		}
 		if (field != null) {
 			FieldBinding originalBinding = field.original();
-			if (originalBinding != field) {
+			if (originalBinding != field && originalBinding.type != field.type) {
 			    // extra cast needed if method return type has type variable
 			    if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
 			    	TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) 
@@ -352,7 +358,7 @@
 		boolean valueRequired) {
 			
 		int pc = codeStream.position;
-		if (constant != NotAConstant) {
+		if (constant != Constant.NotAConstant) {
 			if (valueRequired) {
 				codeStream.generateConstant(constant, implicitConversion);
 			}
@@ -360,16 +366,20 @@
 			FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
 			if (lastFieldBinding != null) {
 				boolean isStatic = lastFieldBinding.isStatic();
-				if (lastFieldBinding.isConstantValue()) {
+				Constant fieldConstant = lastFieldBinding.constant();
+				if (fieldConstant != Constant.NotAConstant) {
 					if (!isStatic){
 						codeStream.invokeObjectGetClass();
 						codeStream.pop();
 					}
 					if (valueRequired) { // inline the last field constant
-						codeStream.generateConstant(lastFieldBinding.constant(), implicitConversion);
+						codeStream.generateConstant(fieldConstant, implicitConversion);
 					}
 				} else {
-					if (valueRequired  || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
+					boolean isFirst = lastFieldBinding == this.binding 
+													&& (this.indexOfFirstFieldBinding == 1 || lastFieldBinding.declaringClass == currentScope.enclosingReceiverType())
+													&& this.otherBindings == null; // could be dup: next.next.next
+					if (valueRequired  || (!isFirst && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)) {
 						if (lastFieldBinding.declaringClass == null) { // array length
 							codeStream.arraylength();
 							if (valueRequired) {
@@ -475,6 +485,49 @@
 		fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, valueRequired);
 		// equivalent to valuesRequired[maxOtherBindings]
 	}
+	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#generatedType(Scope)
+	 */
+	public TypeBinding generatedType(Scope scope) {
+		TypeBinding convertedType = this.resolvedType;
+		TypeBinding requiredGenericCast = getGenericCast(this.otherCodegenBindings == null ? 0 : this.otherCodegenBindings.length);
+		if (requiredGenericCast != null) 
+			convertedType = requiredGenericCast;
+		int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
+		switch (runtimeType) {
+			case T_boolean :
+				convertedType = BooleanBinding;
+				break;
+			case T_byte :
+				convertedType = ByteBinding;
+				break;
+			case T_short :
+				convertedType = ShortBinding;
+				break;
+			case T_char :
+				convertedType = CharBinding;
+				break;
+			case T_int :
+				convertedType = IntBinding;
+				break;
+			case T_float :
+				convertedType = FloatBinding;
+				break;
+			case T_long :
+				convertedType = LongBinding;
+				break;
+			case T_double :
+				convertedType = DoubleBinding;
+				break;
+			default :
+		}		
+		if ((this.implicitConversion & BOXING) != 0) {
+			convertedType = scope.environment().computeBoxingType(convertedType);
+		}
+		return convertedType;
+	}	
+	
 	public void generatePostIncrement(
 		BlockScope currentScope,
 		CodeStream codeStream,
@@ -548,10 +601,10 @@
 				lastFieldBinding = (FieldBinding) this.codegenBinding;
 				lastGenericCast = this.genericCast;
 				// if first field is actually constant, we can inline it
-				if (lastFieldBinding.isConstantValue()) {
+				if (lastFieldBinding.constant() != Constant.NotAConstant) {
 					break;
 				}
-				if ((needValue || complyTo14) && !lastFieldBinding.isStatic()) {
+				if (needValue && !lastFieldBinding.isStatic()) {
 					int pc = codeStream.position;
 					if ((bits & DepthMASK) != 0) {
 						ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
@@ -567,8 +620,9 @@
 				if (!needValue) break; // no value needed
 				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 				// regular local variable read
-				if (localBinding.isConstantValue()) {
-					codeStream.generateConstant(localBinding.constant(), 0);
+				Constant localConstant = localBinding.constant();
+				if (localConstant != Constant.NotAConstant) {
+					codeStream.generateConstant(localConstant, 0);
 					// no implicit conversion
 				} else {
 					// outer local?
@@ -590,16 +644,17 @@
 				TypeBinding nextGenericCast = this.otherGenericCasts == null ? null : this.otherGenericCasts[i];
 				if (lastFieldBinding != null) {
 					needValue = !nextField.isStatic();
-					if (lastFieldBinding.isConstantValue()) {
-						if (lastFieldBinding != this.codegenBinding && !lastFieldBinding.isStatic()) {
+					Constant fieldConstant = lastFieldBinding.constant();
+					if (fieldConstant != Constant.NotAConstant) {
+						if (i > 0 && !lastFieldBinding.isStatic()) {
 							codeStream.invokeObjectGetClass(); // perform null check
 							codeStream.pop();
 						}
 						if (needValue) {
-							codeStream.generateConstant(lastFieldBinding.constant(), 0);
+							codeStream.generateConstant(fieldConstant, 0);
 						}
 					} else {
-						if (needValue || complyTo14) {
+						if (needValue || (i > 0 && complyTo14)) {
 							MethodBinding accessor = syntheticReadAccessors == null ? null : syntheticReadAccessors[i]; 
 							if (accessor == null) {
 								if (lastFieldBinding.isStatic()) {
@@ -688,7 +743,7 @@
 		TypeBinding type = ((VariableBinding) binding).type;
 		int index = indexOfFirstFieldBinding;
 		if (index == length) { //	restrictiveFlag == FIELD
-			this.constant = FieldReference.getConstantFor((FieldBinding) binding, this, false, scope);
+			this.constant = ((FieldBinding) binding).constant();
 			// perform capture conversion if read access
 			return (type != null && (this.bits & IsStrictlyAssigned) == 0)
 					? type.capture(scope, this.sourceEnd)
@@ -700,9 +755,7 @@
 		otherDepths = new int[otherBindingsLength];
 		
 		// fill the first constant (the one of the binding)
-		this.constant = field != null
-				? FieldReference.getConstantFor((FieldBinding) binding, this, false, scope)
-				: ((VariableBinding) binding).constant();
+		this.constant = ((VariableBinding) binding).constant();
 		// save first depth, since will be updated by visibility checks of other bindings
 		int firstDepth = (bits & DepthMASK) >> DepthSHIFT;
 		// iteration on each field	
@@ -737,10 +790,9 @@
 				if (isFieldUseDeprecated(field, scope, (this.bits & IsStrictlyAssigned) !=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;					
+				if (this.constant != Constant.NotAConstant) {
+					this.constant = field.constant();					
 				}
 
 				if (field.isStatic()) {
@@ -754,7 +806,7 @@
 				type = field.type;
 				index++;
 			} else {
-				constant = NotAConstant; //don't fill other constants slots...
+				constant = Constant.NotAConstant; //don't fill other constants slots...
 				scope.problemReporter().invalidField(this, field, index, type);
 				setDepth(firstDepth);
 				return null;
@@ -770,7 +822,7 @@
 	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)) {
+		if (((bits & DepthMASK) == 0) || (constant != Constant.NotAConstant)) {
 			return;
 		}
 		if ((bits & RestrictiveFlagMASK) == Binding.LOCAL) {
@@ -789,7 +841,7 @@
 	    
 		if (!flowInfo.isReachable()) return;
 		// index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings', index < 0 denotes a write access (to last binding)
-		if (fieldBinding.isConstantValue())
+		if (fieldBinding.constant() != Constant.NotAConstant)
 			return;
 
 		// if field from parameterized type got found, use the original field at codegen time
@@ -807,7 +859,7 @@
 				return;
 			}
 		} else if (fieldBinding.isProtected()){
-		    int depth = fieldBinding == binding 
+		    int depth = (index == 0 || (index < 0 && this.otherDepths == null))
 		    		? (bits & DepthMASK) >> DepthSHIFT 
 		    		 : otherDepths[index < 0 ? otherDepths.length-1 : index-1];
 			
@@ -827,10 +879,10 @@
 		if (fieldBinding.declaringClass != lastReceiverType
 				&& !lastReceiverType.isArrayType()
 				&& fieldBinding.declaringClass != null // array.length
-				&& !fieldBinding.isConstantValue()) {
+				&& fieldBinding.constant() == Constant.NotAConstant) {
 			CompilerOptions options = currentScope.compilerOptions();
 			if ((options.targetJDK >= ClassFileConstants.JDK1_2
-					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || fieldBinding != binding || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
+					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(index <= 1 &&  indexOfFirstFieldBinding == 1 && fieldBinding.isStatic()))
 					&& fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields
 				|| !fieldBinding.declaringClass.canBeSeenBy(currentScope)) {
 	
@@ -848,7 +900,7 @@
 		switch (this.resolvedType.id) {
 			case T_boolean :
 			case T_JavaLangBoolean :
-				if (this.constant != NotAConstant) return this.constant;
+				if (this.constant != Constant.NotAConstant) return this.constant;
 				switch (bits & RestrictiveFlagMASK) {
 					case Binding.FIELD : // reading a field
 						if (this.otherBindings == null)
@@ -858,7 +910,7 @@
 						return this.otherBindings[this.otherBindings.length-1].constant();
 				}
 		}
-		return NotAConstant;
+		return Constant.NotAConstant;
 	}
 	
 	public StringBuffer printExpression(int indent, StringBuffer output) {
@@ -887,7 +939,7 @@
 		// field and/or local are done before type lookups
 		// the only available value for the restrictiveFlag BEFORE
 		// the TC is Flag_Type Flag_LocalField and Flag_TypeLocalField 
-		this.actualReceiverType = scope.enclosingSourceType();
+		this.actualReceiverType = scope.enclosingReceiverType();
 		constant = Constant.NotAConstant;
 		if ((this.codegenBinding = this.binding = scope.getBinding(tokens, bits & RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
 			switch (bits & RestrictiveFlagMASK) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
index a784cfc..ded9ed1 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
@@ -13,6 +13,7 @@
 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.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class QualifiedThisReference extends ThisReference {
@@ -72,7 +73,7 @@
 
 	public TypeBinding resolveType(BlockScope scope) {
 
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		TypeBinding type = this.qualification.resolveType(scope, true /* check bounds*/);
 		if (type == null) return null;
 		// X.this is not a param/raw type as denoting enclosing instance
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
index acffa43..bdf2f3b 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
@@ -81,7 +81,7 @@
 					qualifiedType = scope.environment().createRawType(currentType, qualifiedType);
 				} else if ((rawQualified = qualifiedType.isRawType()) && !currentType.isStatic()) {
 					qualifiedType = scope.environment().createRawType((ReferenceBinding)currentType.erasure(), qualifiedType);
-				} else if (rawQualified || qualifiedType.isParameterizedType()) {
+				} else if ((rawQualified || qualifiedType.isParameterizedType()) && qualifiedType.erasure() == currentType.enclosingType().erasure()) {
 					qualifiedType = scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifiedType);
 				} else {
 					qualifiedType = currentType;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
index cb6e8ed..2a37373 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public abstract class Reference extends Expression  {
@@ -70,7 +71,7 @@
 
 public int nullStatus(FlowInfo flowInfo) {
 
-	if (this.constant != null && this.constant != NotAConstant)
+	if (this.constant != null && this.constant != Constant.NotAConstant)
 		return FlowInfo.NON_NULL; // constant expression cannot be null
 	
 	LocalVariableBinding local = localVariableBinding();
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
index 76f7436..87c97bf 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
@@ -13,6 +13,7 @@
 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.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class ReturnStatement extends Statement {
@@ -40,7 +41,7 @@
 		FlowContext traversedContext = flowContext;
 		int subIndex = 0, maxSub = 5;
 		boolean saveValueNeeded = false;
-		boolean hasValueToSave = this.expression != null && this.expression.constant == NotAConstant;
+		boolean hasValueToSave = this.expression != null && this.expression.constant == Constant.NotAConstant;
 		do {
 			SubRoutineStatement sub;
 			if ((sub = traversedContext.subRoutine()) != null) {
@@ -112,7 +113,7 @@
 		}
 		int pc = codeStream.position;
 		// generate the expression
-		if ((this.expression != null) && (this.expression.constant == NotAConstant)) {
+		if ((this.expression != null) && (this.expression.constant == Constant.NotAConstant)) {
 			this.expression.generateCode(currentScope, codeStream, needValue()); // no value needed if non-returning subroutine
 			generateStoreSaveValueIfNecessary(codeStream);
 		}
@@ -132,7 +133,7 @@
 		}
 		if (saveValueVariable != null) codeStream.load(saveValueVariable);
 		
-		if ((this.expression != null) && (this.expression.constant != NotAConstant)) {
+		if ((this.expression != null) && (this.expression.constant != Constant.NotAConstant)) {
 			codeStream.generateConstant(this.expression.constant, this.expression.implicitConversion);
 			generateStoreSaveValueIfNecessary(codeStream);		
 		}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
index d42971f..ec4cdb8 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
@@ -76,7 +76,7 @@
 					MethodScope methodScope = currentScope.methodScope();
 					SourceTypeBinding sourceType = currentScope.enclosingSourceType();
 					if (fieldBinding.isStatic()
-							&& this.constant == NotAConstant
+							&& this.constant == Constant.NotAConstant
 							&& !methodScope.isStatic
 							&& (sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body
 							&& methodScope.isInsideInitializerOrConstructor()) {
@@ -141,7 +141,7 @@
 					MethodScope methodScope = currentScope.methodScope();
 					SourceTypeBinding sourceType = currentScope.enclosingSourceType();
 					if (fieldBinding.isStatic()
-							&& this.constant == NotAConstant
+							&& this.constant == Constant.NotAConstant
 							&& !methodScope.isStatic
 							&& (sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body
 							&& methodScope.isInsideInitializerOrConstructor()) {
@@ -184,11 +184,11 @@
 			// must check for the static status....
 			if (methodScope.isStatic) {
 				scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding);
-				this.constant = NotAConstant;
+				this.constant = Constant.NotAConstant;
 				return fieldBinding.type;
 			}
 		}
-		this.constant = FieldReference.getConstantFor(fieldBinding, this, true, scope);
+		this.constant = fieldBinding.constant();
 	
 		if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssigned) !=0))
 			scope.problemReporter().deprecatedField(fieldBinding, this);
@@ -215,8 +215,9 @@
 			return;				
 		if ((bits & Binding.FIELD) != 0 && this.binding != null && this.binding.isValidBinding()) {
 			// set the generic cast after the fact, once the type expectation is fully known (no need for strict cast)
-			FieldBinding originalBinding = ((FieldBinding)this.binding).original();
-			if (originalBinding != this.binding) {
+			FieldBinding field = (FieldBinding) this.binding;
+			FieldBinding originalBinding = field.original();
+			if (originalBinding != field && originalBinding.type != field.type) {
 			    // extra cast needed if method return type has type variable
 			    if ((originalBinding.type.tagBits & TagBits.HasTypeVariable) != 0 && runtimeTimeType.id != T_JavaLangObject) {
 			    	TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) 
@@ -247,7 +248,7 @@
 			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.constant != Constant.NotAConstant) // exclude non constant expressions, since could have side-effect
 					&& (((operation.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString) // exclude string concatenation which would occur backwards
 					&& (((operation.right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString)) { // 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
@@ -284,7 +285,7 @@
 				if (localBinding.resolvedPosition != -1) {
 					assignment.expression.generateCode(currentScope, codeStream, true);
 				} else {
-					if (assignment.expression.constant != NotAConstant) {
+					if (assignment.expression.constant != Constant.NotAConstant) {
 						// assigning an unused local to a constant value = no actual assignment is necessary
 						if (valueRequired) {
 							codeStream.generateConstant(assignment.expression.constant, assignment.implicitConversion);
@@ -326,7 +327,7 @@
 	}
 	public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 		int pc = codeStream.position;
-		if (constant != NotAConstant) {
+		if (constant != Constant.NotAConstant) {
 			if (valueRequired) {
 				codeStream.generateConstant(constant, implicitConversion);
 			}
@@ -334,13 +335,14 @@
 			switch (bits & RestrictiveFlagMASK) {
 				case Binding.FIELD : // reading a field
 					FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
-					if (fieldBinding.isConstantValue()) {
+					Constant fieldConstant = fieldBinding.constant();
+					if (fieldConstant != Constant.NotAConstant) {
 						// directly use inlined value for constant fields
 						if (valueRequired) {
-							codeStream.generateConstant(fieldBinding.constant(), implicitConversion);
+							codeStream.generateConstant(fieldConstant, implicitConversion);
 						}
 					} else {
-						if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
+						if (valueRequired) {
 							boolean isStatic = fieldBinding.isStatic();
 							if (!isStatic) {
 								if ((bits & DepthMASK) != 0) {
@@ -457,7 +459,7 @@
 						codeStream.store(localBinding, false);
 						return;
 					case T_int :
-						if (((assignConstant = expression.constant) != NotAConstant) 
+						if (((assignConstant = expression.constant) != Constant.NotAConstant) 
 							&& (assignConstant.typeID() != T_float) // only for integral types
 							&& (assignConstant.typeID() != T_double)
 							&& ((increment = assignConstant.intValue()) == (short) increment)) { // 16 bits value
@@ -527,6 +529,47 @@
 		}
 	}
 	
+	/**
+	 * @see org.eclipse.jdt.internal.compiler.ast.Expression#generatedType(Scope)
+	 */
+	public TypeBinding generatedType(Scope scope) {
+		TypeBinding convertedType = this.resolvedType;
+		if (this.genericCast != null) 
+			convertedType = this.genericCast;
+		int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4;
+		switch (runtimeType) {
+			case T_boolean :
+				convertedType = BooleanBinding;
+				break;
+			case T_byte :
+				convertedType = ByteBinding;
+				break;
+			case T_short :
+				convertedType = ShortBinding;
+				break;
+			case T_char :
+				convertedType = CharBinding;
+				break;
+			case T_int :
+				convertedType = IntBinding;
+				break;
+			case T_float :
+				convertedType = FloatBinding;
+				break;
+			case T_long :
+				convertedType = LongBinding;
+				break;
+			case T_double :
+				convertedType = DoubleBinding;
+				break;
+			default :
+		}		
+		if ((this.implicitConversion & BOXING) != 0) {
+			convertedType = scope.environment().computeBoxingType(convertedType);
+		}
+		return convertedType;
+	}	
+	
 	public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
 		switch (bits & RestrictiveFlagMASK) {
 			case Binding.FIELD : // assigning to a field
@@ -622,7 +665,7 @@
 	
 		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 & DepthMASK) == 0) || (constant != Constant.NotAConstant)) return;
 	
 		if ((bits & RestrictiveFlagMASK) == Binding.LOCAL) {
 			currentScope.emulateOuterAccess((LocalVariableBinding) binding);
@@ -633,7 +676,7 @@
 		if (!flowInfo.isReachable()) return;
 	
 		//If inlinable field, forget the access emulation, the code gen will directly target it
-		if (constant != NotAConstant)
+		if (constant != Constant.NotAConstant)
 			return;
 	
 		if ((bits & Binding.FIELD) != 0) {
@@ -659,7 +702,7 @@
 			if (fieldBinding.declaringClass != this.actualReceiverType
 					&& !this.actualReceiverType.isArrayType()
 					&& fieldBinding.declaringClass != null // array.length
-					&& !fieldBinding.isConstantValue()) {
+					&& fieldBinding.constant() == Constant.NotAConstant) {
 				CompilerOptions options = currentScope.compilerOptions();
 				if ((options.targetJDK >= ClassFileConstants.JDK1_2
 						&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic())
@@ -720,7 +763,7 @@
 								if (fieldType != null) 
 									fieldType = fieldType.capture(scope, this.sourceEnd); // perform capture conversion if read access
 							} else {
-								constant = NotAConstant;
+								constant = Constant.NotAConstant;
 							}
 							return this.resolvedType = fieldType;
 						}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
index 6631878..7ea1a60 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -138,7 +138,7 @@
 		// statement within a switch that are not case are treated as normal statement.... 
 
 		resolve(scope);
-		return NotAConstant;
+		return Constant.NotAConstant;
 	}
 
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
index 88a9c39..10fe475 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
@@ -11,8 +11,9 @@
 package org.eclipse.jdt.internal.compiler.ast;
 
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
-import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
 
 public class SuperReference extends ThisReference {
@@ -50,15 +51,15 @@
 
 	public TypeBinding resolveType(BlockScope scope) {
 
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		if (!checkAccess(scope.methodScope()))
 			return null;
-		SourceTypeBinding enclosingTb = scope.enclosingSourceType();
-		if (enclosingTb.id == T_JavaLangObject) {
+		ReferenceBinding enclosingReceiverType = scope.enclosingReceiverType();
+		if (enclosingReceiverType.id == T_JavaLangObject) {
 			scope.problemReporter().cannotUseSuperInJavaLangObject(this);
 			return null;
 		}
-		return this.resolvedType = enclosingTb.superclass;
+		return this.resolvedType = enclosingReceiverType.superclass();
 	}
 
 	public void traverse(ASTVisitor visitor, BlockScope blockScope) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
index 806daed..14ce03c 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
@@ -14,6 +14,7 @@
 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.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class SynchronizedStatement extends SubRoutineStatement {
@@ -168,7 +169,7 @@
 		//continue even on errors in order to have the TC done into the statements
 		synchroVariable = new LocalVariableBinding(SecretLocalDeclarationName, type, ClassFileConstants.AccDefault, false);
 		scope.addLocalVariable(synchroVariable);
-		synchroVariable.setConstant(NotAConstant); // not inlinable
+		synchroVariable.setConstant(Constant.NotAConstant); // not inlinable
 		expression.computeConversion(scope, type, type);
 		block.resolveUsing(scope);
 	}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
index 35d6e8a..d280269 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
@@ -14,6 +14,7 @@
 import org.eclipse.jdt.internal.compiler.codegen.*;
 import org.eclipse.jdt.internal.compiler.flow.FlowContext;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class ThisReference extends Reference {
@@ -109,11 +110,11 @@
 
 	public TypeBinding resolveType(BlockScope scope) {
 	
-		constant = NotAConstant;
+		constant = Constant.NotAConstant;
 		if (!this.isImplicitThis() &&!checkAccess(scope.methodScope())) {
 			return null;
 		}
-		return this.resolvedType = scope.enclosingSourceType();
+		return this.resolvedType = scope.enclosingReceiverType();
 	}
 
 	public void traverse(ASTVisitor visitor, BlockScope blockScope) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
index 14d23b4..7e42018 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
@@ -14,6 +14,7 @@
 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.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 
 public class TryStatement extends SubRoutineStatement {
@@ -470,14 +471,14 @@
 					this.returnAddressVariable =
 						new LocalVariableBinding(SecretReturnName, upperScope.getJavaLangObject(), ClassFileConstants.AccDefault, false);
 					finallyScope.addLocalVariable(returnAddressVariable);
-					this.returnAddressVariable.setConstant(NotAConstant); // not inlinable
+					this.returnAddressVariable.setConstant(Constant.NotAConstant); // not inlinable
 				}
 				this.subRoutineStartLabel = new Label();
 	
 				this.anyExceptionVariable =
 					new LocalVariableBinding(SecretAnyHandlerName, scope.getJavaLangThrowable(), ClassFileConstants.AccDefault, false);
 				finallyScope.addLocalVariable(this.anyExceptionVariable);
-				this.anyExceptionVariable.setConstant(NotAConstant); // not inlinable
+				this.anyExceptionVariable.setConstant(Constant.NotAConstant); // not inlinable
 	
 				if (!methodScope.isInsideInitializer()) {
 					MethodBinding methodBinding =
@@ -492,7 +493,7 @@
 									ClassFileConstants.AccDefault,
 									false);
 							finallyScope.addLocalVariable(this.secretReturnValue);
-							this.secretReturnValue.setConstant(NotAConstant); // not inlinable
+							this.secretReturnValue.setConstant(Constant.NotAConstant); // not inlinable
 						}
 					}
 				}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index 6995da0..b82e9ac 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -982,7 +982,12 @@
 			} finally {
 				this.staticInitializerScope.insideTypeAnnotation = old;
 			}
-			
+			// check @Deprecated annotation
+			if ((sourceType.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0
+					&& (sourceType.modifiers & ClassFileConstants.AccDeprecated) != 0 
+					&& scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
+				scope.problemReporter().missingDeprecatedAnnotationForType(this);
+			}			
 			if ((this.bits & UndocumentedEmptyBlock) != 0) {
 				this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd);
 			}
@@ -1326,4 +1331,11 @@
 			maxFieldCount = outerMostType.maxFieldCount; // down
 		}
 	}	
+
+	/**
+	 * Returns whether the type is a secondary one or not.
+	 */
+	public boolean isSecondary() {
+		return (this.bits & IsSecondaryType) != 0;
+	}
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
index e64379a..666e433 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
@@ -14,6 +14,7 @@
 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.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
 
@@ -119,7 +120,7 @@
 
 public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
 	// handle the error here
-	this.constant = NotAConstant;
+	this.constant = Constant.NotAConstant;
 	if (this.resolvedType != null) // is a shared type reference which was already resolved
 		return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
 
@@ -142,7 +143,7 @@
 }
 public TypeBinding resolveType(ClassScope scope) {
 	// handle the error here
-	this.constant = NotAConstant;
+	this.constant = Constant.NotAConstant;
 	if (this.resolvedType != null) // is a shared type reference which was already resolved
 		return this.resolvedType.isValidBinding() ? this.resolvedType : null; // already reported error
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
index d05e899..abc1ebc 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
@@ -117,7 +117,7 @@
 				break;
 			case MINUS :
 				// - <num>
-				if (this.constant != NotAConstant) {
+				if (this.constant != Constant.NotAConstant) {
 					if (valueRequired) {
 						switch ((this.expression.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4){ /* runtime */
 							case T_int :
@@ -210,7 +210,7 @@
 		if ((expressionIsCast = this.expression instanceof CastExpression) == true) this.expression.bits |= DisableUnnecessaryCastCheck; // will check later on
 		TypeBinding expressionType = this.expression.resolveType(scope);
 		if (expressionType == null) {
-			this.constant = NotAConstant;
+			this.constant = Constant.NotAConstant;
 			return null;
 		}
 		int expressionTypeID = expressionType.id;
@@ -222,7 +222,7 @@
 			}
 		}		
 		if (expressionTypeID > 15) {
-			this.constant = NotAConstant;
+			this.constant = Constant.NotAConstant;
 			scope.problemReporter().invalidOperator(this, expressionType);
 			return null;
 		}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java b/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
index d665dae..288f7ec 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
@@ -45,12 +45,12 @@
 		continueLabel = new Label(); 
 
 		Constant cst = this.condition.constant;
-		boolean isConditionTrue = cst != NotAConstant && cst.booleanValue() == true;
-		boolean isConditionFalse = cst != NotAConstant && cst.booleanValue() == false;
+		boolean isConditionTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
+		boolean isConditionFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;
 
 		cst = this.condition.optimizedBooleanConstant();
-		boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
-		boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+		boolean isConditionOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
+		boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;
 		
 		preCondInitStateIndex =
 			currentScope.methodScope().recordInitializationStates(flowInfo);
@@ -143,12 +143,25 @@
 			return;
 		}
 		int pc = codeStream.position;
+		Constant cst = this.condition.optimizedBooleanConstant();
+		boolean isConditionOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;
+		if (isConditionOptimizedFalse) {
+			condition.generateCode(currentScope, 	codeStream, false);
+			// May loose some local variable initializations : affecting the local variable attributes
+			if (mergedInitStateIndex != -1) {
+				codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+				codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+			}
+			codeStream.recordPositionsFrom(pc, this.sourceStart);
+			return;
+		}
+		
 		breakLabel.initialize(codeStream);
 
 		// generate condition
 		if (continueLabel == null) {
 			// no need to reverse condition
-			if (condition.constant == NotAConstant) {
+			if (condition.constant == Constant.NotAConstant) {
 				condition.generateOptimizedBoolean(
 					currentScope,
 					codeStream,
@@ -158,7 +171,7 @@
 			}
 		} else {
 			continueLabel.initialize(codeStream);
-			if (!(((condition.constant != NotAConstant)
+			if (!(((condition.constant != Constant.NotAConstant)
 				&& (condition.constant.booleanValue() == true))
 				|| (action == null)
 				|| action.isEmptyBlock())) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
index a05b32a..b366773 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
@@ -12,6 +12,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.Arrays;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
@@ -23,9 +24,20 @@
 import org.eclipse.jdt.internal.compiler.util.Util;
 
 public class ClassFileReader extends ClassFileStruct implements IBinaryType {
+public static ClassFileReader read(InputStream stream, String fileName) throws ClassFormatException, IOException {
+	return read(stream, fileName, false);
+}
 public static ClassFileReader read(File file) throws ClassFormatException, IOException {
 	return read(file, false);
 }
+public static ClassFileReader read(InputStream stream, String fileName, boolean fullyInitialize) throws ClassFormatException, IOException {
+	byte classFileBytes[] = Util.getInputStreamAsByteArray(stream, -1);
+	ClassFileReader classFileReader = new ClassFileReader(classFileBytes, fileName.toCharArray());
+	if (fullyInitialize) {
+		classFileReader.initialize();
+	}
+	return classFileReader;
+}
 public static ClassFileReader read(File file, boolean fullyInitialize) throws ClassFormatException, IOException {
 	byte classFileBytes[] = Util.getFileByteContent(file);
 	ClassFileReader classFileReader = new ClassFileReader(classFileBytes, file.getAbsolutePath().toCharArray());
@@ -121,52 +133,52 @@
 		for (int i = 1; i < constantPoolCount; i++) {
 			int tag = this.u1At(readOffset);
 			switch (tag) {
-				case Utf8Tag :
+				case ClassFileConstants.Utf8Tag :
 					this.constantPoolOffsets[i] = readOffset;
 					readOffset += u2At(readOffset + 1);
-					readOffset += ConstantUtf8FixedSize;
+					readOffset += ClassFileConstants.ConstantUtf8FixedSize;
 					break;
-				case IntegerTag :
+				case ClassFileConstants.IntegerTag :
 					this.constantPoolOffsets[i] = readOffset;
-					readOffset += ConstantIntegerFixedSize;
+					readOffset += ClassFileConstants.ConstantIntegerFixedSize;
 					break;
-				case FloatTag :
+				case ClassFileConstants.FloatTag :
 					this.constantPoolOffsets[i] = readOffset;
-					readOffset += ConstantFloatFixedSize;
+					readOffset += ClassFileConstants.ConstantFloatFixedSize;
 					break;
-				case LongTag :
+				case ClassFileConstants.LongTag :
 					this.constantPoolOffsets[i] = readOffset;
-					readOffset += ConstantLongFixedSize;
+					readOffset += ClassFileConstants.ConstantLongFixedSize;
 					i++;
 					break;
-				case DoubleTag :
+				case ClassFileConstants.DoubleTag :
 					this.constantPoolOffsets[i] = readOffset;
-					readOffset += ConstantDoubleFixedSize;
+					readOffset += ClassFileConstants.ConstantDoubleFixedSize;
 					i++;
 					break;
-				case ClassTag :
+				case ClassFileConstants.ClassTag :
 					this.constantPoolOffsets[i] = readOffset;
-					readOffset += ConstantClassFixedSize;
+					readOffset += ClassFileConstants.ConstantClassFixedSize;
 					break;
-				case StringTag :
+				case ClassFileConstants.StringTag :
 					this.constantPoolOffsets[i] = readOffset;
-					readOffset += ConstantStringFixedSize;
+					readOffset += ClassFileConstants.ConstantStringFixedSize;
 					break;
-				case FieldRefTag :
+				case ClassFileConstants.FieldRefTag :
 					this.constantPoolOffsets[i] = readOffset;
-					readOffset += ConstantFieldRefFixedSize;
+					readOffset += ClassFileConstants.ConstantFieldRefFixedSize;
 					break;
-				case MethodRefTag :
+				case ClassFileConstants.MethodRefTag :
 					this.constantPoolOffsets[i] = readOffset;
-					readOffset += ConstantMethodRefFixedSize;
+					readOffset += ClassFileConstants.ConstantMethodRefFixedSize;
 					break;
-				case InterfaceMethodRefTag :
+				case ClassFileConstants.InterfaceMethodRefTag :
 					this.constantPoolOffsets[i] = readOffset;
-					readOffset += ConstantInterfaceMethodRefFixedSize;
+					readOffset += ClassFileConstants.ConstantInterfaceMethodRefFixedSize;
 					break;
-				case NameAndTypeTag :
+				case ClassFileConstants.NameAndTypeTag :
 					this.constantPoolOffsets[i] = readOffset;
-					readOffset += ConstantNameAndTypeFixedSize;
+					readOffset += ClassFileConstants.ConstantNameAndTypeFixedSize;
 			}
 		}
 		// Read and validate access flags
@@ -215,7 +227,7 @@
 		if (this.methodsCount != 0) {
 			this.methods = new MethodInfo[this.methodsCount];
 			MethodInfo method;
-			final boolean isAnnotationType = (this.accessFlags & AccAnnotation) != 0;
+			final boolean isAnnotationType = (this.accessFlags & ClassFileConstants.AccAnnotation) != 0;
 			for (int i = 0; i < this.methodsCount; i++) {
 				if( isAnnotationType )
 					method = AnnotationMethodInfo.createAnnotationMethod(reference, this.constantPoolOffsets, readOffset);
@@ -240,7 +252,7 @@
 			switch(attributeName[0] ) {
 				case 'D' :
 					if (CharOperation.equals(attributeName, AttributeNamesConstants.DeprecatedName)) {
-						this.accessFlags |= AccDeprecated;
+						this.accessFlags |= ClassFileConstants.AccDeprecated;
 					}
 					break;
 				case 'I' :
@@ -273,7 +285,7 @@
 								break;
 							case 'y' :
 								if (CharOperation.equals(attributeName, AttributeNamesConstants.SyntheticName)) {
-									this.accessFlags |= AccSynthetic;
+									this.accessFlags |= ClassFileConstants.AccSynthetic;
 								}
 								break;
 							case 'i' :
@@ -285,7 +297,8 @@
 					}
 					break;
 				case 'R' :
-					if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) {
+					if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)
+							|| CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) {
 						decodeAnnotations(readOffset, true);
 					}
 					else if(CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName )){
@@ -534,7 +547,7 @@
  */
 public int getModifiers() {
 	if (this.innerInfo != null) {
-		return this.innerInfo.getModifiers() | (this.accessFlags & AccDeprecated);
+		return this.innerInfo.getModifiers() | (this.accessFlags & ClassFileConstants.AccDeprecated);
 	}
 	return this.accessFlags;
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java
index 0a938b4..f04cb5a 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java
@@ -10,7 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.classfmt;
 
-abstract public class ClassFileStruct implements ClassFileConstants {
+abstract public class ClassFileStruct {
 	byte[] reference;
 	int structOffset;
 public ClassFileStruct(byte classFileBytes[], int off) {
@@ -54,12 +54,12 @@
 	java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
 	java.io.PrintWriter print = new java.io.PrintWriter(out);
 
-	if ((modifiers & AccPublic) != 0) print.print("public "); //$NON-NLS-1$
-	if ((modifiers & AccPrivate) != 0) print.print("private "); //$NON-NLS-1$
-	if ((modifiers & AccFinal) != 0) print.print("final "); //$NON-NLS-1$
-	if ((modifiers & AccSuper) != 0) print.print("super "); //$NON-NLS-1$
-	if ((modifiers & AccInterface) != 0) print.print("interface "); //$NON-NLS-1$
-	if ((modifiers & AccAbstract) != 0) print.print("abstract "); //$NON-NLS-1$
+	if ((modifiers & ClassFileConstants.AccPublic) != 0) print.print("public "); //$NON-NLS-1$
+	if ((modifiers & ClassFileConstants.AccPrivate) != 0) print.print("private "); //$NON-NLS-1$
+	if ((modifiers & ClassFileConstants.AccFinal) != 0) print.print("final "); //$NON-NLS-1$
+	if ((modifiers & ClassFileConstants.AccSuper) != 0) print.print("super "); //$NON-NLS-1$
+	if ((modifiers & ClassFileConstants.AccInterface) != 0) print.print("interface "); //$NON-NLS-1$
+	if ((modifiers & ClassFileConstants.AccAbstract) != 0) print.print("abstract "); //$NON-NLS-1$
 	print.flush();
 	return out.toString();
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
index 3db68fa..52df381 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
@@ -27,7 +27,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
 import org.eclipse.jdt.internal.compiler.util.Util;
 
-public class FieldInfo extends ClassFileStruct implements IBinaryField, Comparable, TypeIds {
+public class FieldInfo extends ClassFileStruct implements IBinaryField, Comparable {
 	protected int accessFlags;
 	protected int attributeBytes;
 	protected Constant constant;
@@ -59,7 +59,8 @@
 					break;
 				case 'R' :
 					AnnotationInfo[] decodedAnnos = null;
-					if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) {
+					if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)
+							|| CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) {
 						decodedAnnos = decodeAnnotations(readOffset, true, fieldInfo);
 					}
 					else if(CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) {
@@ -244,31 +245,31 @@
 		if (hasConstant()) {
 			Constant fieldConstant = getConstant();
 			switch (fieldConstant.typeID()) {
-				case T_int :
+				case TypeIds.T_int :
 					this.wrappedConstantValue = new Integer(fieldConstant.intValue());
 					break;
-				case T_byte :
+				case TypeIds.T_byte :
 					this.wrappedConstantValue = new Byte(fieldConstant.byteValue());
 					break;
-				case T_short :
+				case TypeIds.T_short :
 					this.wrappedConstantValue = new Short(fieldConstant.shortValue());
 					break;
-				case T_char :
+				case TypeIds.T_char :
 					this.wrappedConstantValue = new Character(fieldConstant.charValue());
 					break;
-				case T_float :
+				case TypeIds.T_float :
 					this.wrappedConstantValue = new Float(fieldConstant.floatValue());
 					break;
-				case T_double :
+				case TypeIds.T_double :
 					this.wrappedConstantValue = new Double(fieldConstant.doubleValue());
 					break;
-				case T_boolean :
+				case TypeIds.T_boolean :
 					this.wrappedConstantValue = Util.toBoolean(fieldConstant.booleanValue());
 					break;
-				case T_long :
+				case TypeIds.T_long :
 					this.wrappedConstantValue = new Long(fieldConstant.longValue());
 					break;
-				case T_JavaLangString :
+				case TypeIds.T_JavaLangString :
 					this.wrappedConstantValue = fieldConstant.stringValue();
 			}
 		}
@@ -299,7 +300,7 @@
  * @return boolean
  */
 public boolean isSynthetic() {
-	return (getModifiers() & AccSynthetic) != 0;
+	return (getModifiers() & ClassFileConstants.AccSynthetic) != 0;
 }
 
 private void readConstantAttribute() {
@@ -315,7 +316,7 @@
 			// read the right constant
 			int relativeOffset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset;
 			switch (u1At(relativeOffset)) {
-				case IntegerTag :
+				case ClassFileConstants.IntegerTag :
 					char[] sign = getTypeName();
 					if (sign.length == 1) {
 						switch (sign[0]) {
@@ -341,16 +342,16 @@
 						constant = Constant.NotAConstant;
 					}
 					break;
-				case FloatTag :
+				case ClassFileConstants.FloatTag :
 					constant = new FloatConstant(floatAt(relativeOffset + 1));
 					break;
-				case DoubleTag :
+				case ClassFileConstants.DoubleTag :
 					constant = new DoubleConstant(doubleAt(relativeOffset + 1));
 					break;
-				case LongTag :
+				case ClassFileConstants.LongTag :
 					constant = new LongConstant(i8At(relativeOffset + 1));
 					break;
-				case StringTag :
+				case ClassFileConstants.StringTag :
 					utf8Offset = constantPoolOffsets[u2At(relativeOffset + 1)] - structOffset;
 					constant = 
 						new StringConstant(
@@ -375,11 +376,11 @@
 			switch(attributeName[0]) {
 				case 'D' :
 					if (CharOperation.equals(attributeName, AttributeNamesConstants.DeprecatedName))
-						this.accessFlags |= AccDeprecated;
+						this.accessFlags |= ClassFileConstants.AccDeprecated;
 					break;
 				case 'S' :
 					if (CharOperation.equals(attributeName, AttributeNamesConstants.SyntheticName))
-						this.accessFlags |= AccSynthetic;
+						this.accessFlags |= ClassFileConstants.AccSynthetic;
 					break;
 			}
 		}
@@ -413,7 +414,7 @@
 	buffer
 		.append("{") //$NON-NLS-1$
 		.append(
-			((modifiers & AccDeprecated) != 0 ? "deprecated " : "") //$NON-NLS-1$ //$NON-NLS-2$
+			((modifiers & ClassFileConstants.AccDeprecated) != 0 ? "deprecated " : "") //$NON-NLS-1$ //$NON-NLS-2$
 				+ ((modifiers & 0x0001) == 1 ? "public " : "") //$NON-NLS-1$ //$NON-NLS-2$
 				+ ((modifiers & 0x0002) == 0x0002 ? "private " : "") //$NON-NLS-1$ //$NON-NLS-2$
 				+ ((modifiers & 0x0004) == 0x0004 ? "protected " : "") //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
index 90812ed..7710d13 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
@@ -65,7 +65,8 @@
 				case 'R' :
 					AnnotationInfo[] methodAnnos = null;
 					AnnotationInfo[][] paramAnnos = null;
-					if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) {
+					if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)
+							|| CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) {
 						methodAnnos = decodeMethodAnnotations(readOffset, true, methodInfo);						
 					}
 					else if (CharOperation.equals(attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) {
@@ -382,7 +383,7 @@
  * @return boolean
  */
 public boolean isSynthetic() {
-	return (getModifiers() & AccSynthetic) != 0;
+	return (getModifiers() & ClassFileConstants.AccSynthetic) != 0;
 }
 private void readExceptionAttributes() {
 	int attributesCount = u2At(6);
@@ -427,15 +428,15 @@
 			switch(attributeName[0]) {
 				case 'D' :
 					if (CharOperation.equals(attributeName, AttributeNamesConstants.DeprecatedName))
-						this.accessFlags |= AccDeprecated;
+						this.accessFlags |= ClassFileConstants.AccDeprecated;
 					break;
 				case 'S' :
 					if (CharOperation.equals(attributeName, AttributeNamesConstants.SyntheticName))
-						this.accessFlags |= AccSynthetic;
+						this.accessFlags |= ClassFileConstants.AccSynthetic;
 					break;
 				case 'A' :
 					if (CharOperation.equals(attributeName, AttributeNamesConstants.AnnotationDefaultName))
-						this.accessFlags |= AccAnnotationDefault;
+						this.accessFlags |= ClassFileConstants.AccAnnotationDefault;
 					break;
 			}
 		}
@@ -466,7 +467,7 @@
 	buffer
 	.append("{") //$NON-NLS-1$
 	.append(
-		((modifiers & AccDeprecated) != 0 ? "deprecated " : "") //$NON-NLS-1$ //$NON-NLS-2$
+		((modifiers & ClassFileConstants.AccDeprecated) != 0 ? "deprecated " : "") //$NON-NLS-1$ //$NON-NLS-2$
 			+ ((modifiers & 0x0001) == 1 ? "public " : "") //$NON-NLS-1$ //$NON-NLS-2$
 			+ ((modifiers & 0x0002) == 0x0002 ? "private " : "") //$NON-NLS-1$ //$NON-NLS-2$
 			+ ((modifiers & 0x0004) == 0x0004 ? "protected " : "") //$NON-NLS-1$ //$NON-NLS-2$
diff --git a/compiler/org/eclipse/jdt/internal/compiler/codegen/CaseLabel.java b/compiler/org/eclipse/jdt/internal/compiler/codegen/CaseLabel.java
index 7380a06..d01ef26 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/codegen/CaseLabel.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/codegen/CaseLabel.java
@@ -72,7 +72,7 @@
 }
 
 /*
-* 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 placeInstruction() {
 	if (instructionPosition == POS_NOT_SET) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
index 2a7ff99..c9a6c72 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
@@ -900,7 +900,7 @@
 	bCodeStream[classFileOffset++] = OPC_dup2_x2;
 }
 public void exitUserScope(BlockScope currentScope) {
-	// mark all the scope's locals as loosing their definite assignment
+	// mark all the scope's locals as losing their definite assignment
 
 	if (!generateLocalVariableTableAttributes)
 		return;
@@ -911,7 +911,7 @@
 		if (visibleLocal.declaringScope != currentScope) // left currentScope
 			break;
 
-		// there maybe some some preserved locals never initialized
+		// there may be some preserved locals never initialized
 		if (visibleLocal.initializationCount > 0){
 			visibleLocal.recordInitializationEndPC(position);
 		}
@@ -2171,87 +2171,219 @@
 	}
 }
 public void generateBoxingConversion(int unboxedTypeID) {
-	switch (unboxedTypeID) {
-		case T_byte :
-			// invokestatic: Byte.valueOf(byte)
-			this.invoke(
-				OPC_invokestatic,
-				1, // argCount
-				1, // return type size
-				ConstantPool.JavaLangByteConstantPoolName,
-				ConstantPool.ValueOf,
-				ConstantPool.byteByteSignature);
-			break;
-		case T_short :
-			// invokestatic: Short.valueOf(short)
-			this.invoke(
-				OPC_invokestatic,
-				1, // argCount
-				1, // return type size
-				ConstantPool.JavaLangShortConstantPoolName,
-				ConstantPool.ValueOf,
-				ConstantPool.shortShortSignature);
-			break;
-		case T_char :
-			// invokestatic: Character.valueOf(char)
-			this.invoke(
-				OPC_invokestatic,
-				1, // argCount
-				1, // return type size
-				ConstantPool.JavaLangCharacterConstantPoolName,
-				ConstantPool.ValueOf,
-				ConstantPool.charCharacterSignature);
-			break;
-		case T_int :
-			// invokestatic: Integer.valueOf(int)
-			this.invoke(
-				OPC_invokestatic,
-				1, // argCount
-				1, // return type size
-				ConstantPool.JavaLangIntegerConstantPoolName,
-				ConstantPool.ValueOf,
-				ConstantPool.IntIntegerSignature);
-			break;
-		case T_long :
-			// invokestatic: Long.valueOf(long)
-			this.invoke(
-				OPC_invokestatic,
-				2, // argCount
-				1, // return type size
-				ConstantPool.JavaLangLongConstantPoolName,
-				ConstantPool.ValueOf,
-				ConstantPool.longLongSignature);
-			break;
-		case T_float :
-			// invokestatic: Float.valueOf(float)
-			this.invoke(
-				OPC_invokestatic,
-				1, // argCount
-				1, // return type size
-				ConstantPool.JavaLangFloatConstantPoolName,
-				ConstantPool.ValueOf,
-				ConstantPool.floatFloatSignature);
-			break;
-		case T_double :
-			// invokestatic: Double.valueOf(double)
-			this.invoke(
-				OPC_invokestatic,
-				2, // argCount
-				1, // return type size
-				ConstantPool.JavaLangDoubleConstantPoolName,
-				ConstantPool.ValueOf,
-				ConstantPool.doubleDoubleSignature);
-			break;
-		case T_boolean :
-			// invokestatic: Boolean.valueOf(boolean)
-			this.invoke(
-				OPC_invokestatic,
-				1, // argCount
-				1, // return type size
-				ConstantPool.JavaLangBooleanConstantPoolName,
-				ConstantPool.ValueOf,
-				ConstantPool.booleanBooleanSignature);
-	}
+    switch (unboxedTypeID) {
+        case T_byte :
+            if (this.targetLevel >= ClassFileConstants.JDK1_5) {
+    			if (DEBUG) System.out.println(position + "\t\tinvokestatic java.lang.Byte.valueOf(byte)"); //$NON-NLS-1$
+               // invokestatic: Byte.valueOf(byte)
+                this.invoke(
+                    OPC_invokestatic,
+                    1, // argCount
+                    1, // return type size
+                    ConstantPool.JavaLangByteConstantPoolName,
+                    ConstantPool.ValueOf,
+                    ConstantPool.byteByteSignature);
+            } else {
+               // new Byte( byte )
+    			if (DEBUG) System.out.println(position + "\t\tinvokespecial java.lang.Byte(byte)"); //$NON-NLS-1$
+                newWrapperFor(unboxedTypeID);
+                dup_x1();
+                swap();
+                this.invoke(
+                    OPC_invokespecial,
+                    1, // argCount
+                    0, // return type size
+                    ConstantPool.JavaLangByteConstantPoolName,
+                    ConstantPool.Init,
+                    ConstantPool.ByteConstrSignature);
+            }       
+            break;
+        case T_short :
+            if ( this.targetLevel >= ClassFileConstants.JDK1_5 ) {
+                // invokestatic: Short.valueOf(short)
+    			if (DEBUG) System.out.println(position + "\t\tinvokestatic java.lang.Short.valueOf(short)"); //$NON-NLS-1$
+                this.invoke(
+                    OPC_invokestatic,
+                    1, // argCount
+                    1, // return type size
+                    ConstantPool.JavaLangShortConstantPoolName,
+                    ConstantPool.ValueOf,
+                    ConstantPool.shortShortSignature);
+            } else {
+                // new Short(short)
+            	if (DEBUG) System.out.println(position + "\t\tinvokespecial java.lang.Short(short)"); //$NON-NLS-1$
+            	newWrapperFor(unboxedTypeID);                
+                dup_x1();
+                swap();             
+                this.invoke(
+                    OPC_invokespecial,
+                    1, // argCount
+                    0, // return type size
+                    ConstantPool.JavaLangShortConstantPoolName,
+                    ConstantPool.Init,
+                    ConstantPool.ShortConstrSignature);     
+            }
+            break;
+        case T_char :
+            if ( this.targetLevel >= ClassFileConstants.JDK1_5 ) {
+                // invokestatic: Character.valueOf(char)
+            	if (DEBUG) System.out.println(position + "\t\tinvokestatic java.lang.Character.valueOf(char)"); //$NON-NLS-1$
+                this.invoke(
+                    OPC_invokestatic,
+                    1, // argCount
+                    1, // return type size
+                    ConstantPool.JavaLangCharacterConstantPoolName,
+                    ConstantPool.ValueOf,
+                    ConstantPool.charCharacterSignature);
+            } else {
+                // new Char( char )
+            	if (DEBUG) System.out.println(position + "\t\tinvokespecial java.lang.Character(char)"); //$NON-NLS-1$
+                newWrapperFor(unboxedTypeID);
+                dup_x1();
+                swap();
+                this.invoke(
+                    OPC_invokespecial,
+                    1, // argCount
+                    0, // return type size
+                    ConstantPool.JavaLangCharacterConstantPoolName,
+                    ConstantPool.Init,
+                    ConstantPool.CharConstrSignature);
+            }       
+            break;
+        case T_int :             
+            if (this.targetLevel >= ClassFileConstants.JDK1_5) {
+                // invokestatic: Integer.valueOf(int)
+            	if (DEBUG) System.out.println(position + "\t\tinvokestatic java.lang.Integer.valueOf(int)"); //$NON-NLS-1$
+                this.invoke(
+                    OPC_invokestatic,
+                    1, // argCount
+                    1, // return type size
+                    ConstantPool.JavaLangIntegerConstantPoolName,
+                    ConstantPool.ValueOf,
+                    ConstantPool.IntIntegerSignature);
+            } else {
+                // new Integer(int)
+            	if (DEBUG) System.out.println(position + "\t\tinvokespecial java.lang.Integer(int)"); //$NON-NLS-1$
+                newWrapperFor(unboxedTypeID);
+                dup_x1();
+                swap();             
+                this.invoke(
+                    OPC_invokespecial,
+                    1, // argCount
+                    0, // return type size
+                    ConstantPool.JavaLangIntegerConstantPoolName,
+                    ConstantPool.Init,
+                    ConstantPool.IntConstrSignature);
+            }
+            break;
+        case T_long :
+            if (this.targetLevel >= ClassFileConstants.JDK1_5) { 
+                // invokestatic: Long.valueOf(long)
+            	if (DEBUG) System.out.println(position + "\t\tinvokestatic java.lang.Long.valueOf(long)"); //$NON-NLS-1$
+                this.invoke(
+                    OPC_invokestatic,
+                    2, // argCount
+                    1, // return type size
+                    ConstantPool.JavaLangLongConstantPoolName,
+                    ConstantPool.ValueOf,
+                    ConstantPool.longLongSignature);
+            } else {
+                // new Long( long )
+            	if (DEBUG) System.out.println(position + "\t\tinvokespecial java.lang.Long(long)"); //$NON-NLS-1$
+                newWrapperFor(unboxedTypeID);
+                dup_x2();
+                dup_x2();
+                pop();
+                this.invoke(
+                    OPC_invokespecial,
+                    2, // argCount
+                    0, // return type size
+                    ConstantPool.JavaLangLongConstantPoolName,
+                    ConstantPool.Init,
+                    ConstantPool.LongConstrSignature);
+            }                   
+            break;
+        case T_float :
+            if ( this.targetLevel >= ClassFileConstants.JDK1_5 ) {
+                // invokestatic: Float.valueOf(float)
+            	if (DEBUG) System.out.println(position + "\t\tinvokestatic java.lang.Float.valueOf(float)"); //$NON-NLS-1$
+                this.invoke(
+                    OPC_invokestatic,
+                    1, // argCount
+                    1, // return type size
+                    ConstantPool.JavaLangFloatConstantPoolName,
+                    ConstantPool.ValueOf,
+                    ConstantPool.floatFloatSignature);
+            } else {
+                // new Float(float)
+            	if (DEBUG) System.out.println(position + "\t\tinvokespecial java.lang.Float(float)"); //$NON-NLS-1$
+                newWrapperFor(unboxedTypeID);
+                dup_x1();
+                swap();             
+                this.invoke(
+                    OPC_invokespecial,
+                    1, // argCount
+                    0, // return type size
+                    ConstantPool.JavaLangFloatConstantPoolName,
+                    ConstantPool.Init,
+                    ConstantPool.FloatConstrSignature);
+            }       
+            break;
+        case T_double :
+            if ( this.targetLevel >= ClassFileConstants.JDK1_5 ) { 
+                // invokestatic: Double.valueOf(double)
+            	if (DEBUG) System.out.println(position + "\t\tinvokestatic java.lang.Double.valueOf(double)"); //$NON-NLS-1$
+                this.invoke(
+                    OPC_invokestatic,
+                    2, // argCount
+                    1, // return type size
+                    ConstantPool.JavaLangDoubleConstantPoolName,
+                    ConstantPool.ValueOf,
+                    ConstantPool.doubleDoubleSignature);
+            } else {
+                // new Double( double )
+            	if (DEBUG) System.out.println(position + "\t\tinvokespecial java.lang.Double(double)"); //$NON-NLS-1$
+            	newWrapperFor(unboxedTypeID);                
+                dup_x2();
+                dup_x2();
+                pop();
+                
+                this.invoke(
+                    OPC_invokespecial,
+                    2, // argCount
+                    0, // return type size
+                    ConstantPool.JavaLangDoubleConstantPoolName,
+                    ConstantPool.Init,
+                    ConstantPool.DoubleConstrSignature);
+            }       
+            
+            break;  
+        case T_boolean :
+            if ( this.targetLevel >= ClassFileConstants.JDK1_5 ) {
+                // invokestatic: Boolean.valueOf(boolean)
+            	if (DEBUG) System.out.println(position + "\t\tinvokestatic java.lang.Boolean.valueOf(boolean)"); //$NON-NLS-1$
+                this.invoke(
+                    OPC_invokestatic,
+                    1, // argCount
+                    1, // return type size
+                    ConstantPool.JavaLangBooleanConstantPoolName,
+                    ConstantPool.ValueOf,
+                    ConstantPool.booleanBooleanSignature);
+            } else {
+                // new Boolean(boolean)
+            	if (DEBUG) System.out.println(position + "\t\tinvokespecial java.lang.Boolean(boolean)"); //$NON-NLS-1$
+                newWrapperFor(unboxedTypeID);
+                dup_x1();
+                swap();             
+                this.invoke(
+                    OPC_invokespecial,
+                    1, // argCount
+                    0, // return type size
+                    ConstantPool.JavaLangBooleanConstantPoolName,
+                    ConstantPool.Init,
+                    ConstantPool.BooleanConstrSignature);
+            }
+    }
 }
 public void generateUnboxingConversion(int unboxedTypeID) {
 	switch (unboxedTypeID) {
@@ -5518,8 +5650,8 @@
 private final void resizeByteArray() {
 	int length = bCodeStream.length;
 	int requiredSize = length + length;
-	if (classFileOffset > requiredSize) {
-		// must be sure to grow by enough
+	if (classFileOffset >= requiredSize) {
+		// must be sure to grow enough
 		requiredSize = classFileOffset + length;
 	}
 	System.arraycopy(bCodeStream, 0, bCodeStream = new byte[requiredSize], 0, length);
diff --git a/compiler/org/eclipse/jdt/internal/compiler/codegen/Label.java b/compiler/org/eclipse/jdt/internal/compiler/codegen/Label.java
index ff5e739..ac1a1c4 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/codegen/Label.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/codegen/Label.java
@@ -10,6 +10,8 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.codegen;
 
+import java.util.Arrays;
+
 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
 import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
 
@@ -43,27 +45,70 @@
 /**
  * Add a forward refrence for the array.
  */
-void addForwardReference(int iPos) {
-	int length;
-	if (forwardReferenceCount >= (length = forwardReferences.length))
-		System.arraycopy(forwardReferences, 0, (forwardReferences = new int[2*length]), 0, length);
-	forwardReferences[forwardReferenceCount++] = iPos;
+void addForwardReference(int pos) {
+	final int count = this.forwardReferenceCount;
+	if (count >= 1) {
+		int previousValue = this.forwardReferences[count - 1];
+		if (previousValue < pos) {
+			int length;
+			if (count >= (length = this.forwardReferences.length))
+				System.arraycopy(this.forwardReferences, 0, (this.forwardReferences = new int[2*length]), 0, length);
+			this.forwardReferences[this.forwardReferenceCount++] = pos;			
+		} else if (previousValue > pos) {
+			int[] refs = this.forwardReferences;
+			// check for duplicates
+			for (int i = 0, max = this.forwardReferenceCount; i < max; i++) {
+				if (refs[i] == pos) return; // already recorded
+			}
+			int length;
+			if (count >= (length = refs.length))
+				System.arraycopy(refs, 0, (this.forwardReferences = new int[2*length]), 0, length);
+			this.forwardReferences[this.forwardReferenceCount++] = pos;
+			Arrays.sort(this.forwardReferences, 0, this.forwardReferenceCount);
+		}
+	} else {
+		int length;
+		if (count >= (length = this.forwardReferences.length))
+			System.arraycopy(this.forwardReferences, 0, (this.forwardReferences = new int[2*length]), 0, length);
+		this.forwardReferences[this.forwardReferenceCount++] = pos;
+	}
 }
 
 /**
- * Add a forward refrence for the array.
+ * Add a forward reference for the array.
  */
 public void appendForwardReferencesFrom(Label otherLabel) {
-	int otherCount = otherLabel.forwardReferenceCount;
+	final int otherCount = otherLabel.forwardReferenceCount;
 	if (otherCount == 0) return;
-	int length = forwardReferences.length;
-	int neededSpace = otherCount + forwardReferenceCount;
-	if (neededSpace >= length){
-		System.arraycopy(forwardReferences, 0, (forwardReferences = new int[neededSpace]), 0, forwardReferenceCount);
+	// need to merge the two sorted arrays of forward references
+	int[] mergedForwardReferences = new int[this.forwardReferenceCount + otherCount];
+	int indexInMerge = 0;
+	int j = 0;
+	int i = 0;
+	int max = this.forwardReferenceCount;
+	int max2 = otherLabel.forwardReferenceCount;
+	loop1 : for (; i < max; i++) {
+		final int value1 = this.forwardReferences[i];
+		for (; j < max2; j++) {
+			final int value2 = otherLabel.forwardReferences[j];
+			if (value1 < value2) {
+				mergedForwardReferences[indexInMerge++] = value1;
+				continue loop1;
+			} else if (value1 == value2) {
+				mergedForwardReferences[indexInMerge++] = value1;
+				j++;
+				continue loop1;
+			} else {
+				mergedForwardReferences[indexInMerge++] = value2;
+			}
+		}
+		mergedForwardReferences[indexInMerge++] = value1;
 	}
-	// append other forward references at the end, so they will get updated as well
-	System.arraycopy(otherLabel.forwardReferences, 0, forwardReferences, forwardReferenceCount, otherCount);
-	forwardReferenceCount = neededSpace;
+	for (; j < max2; j++) {
+		mergedForwardReferences[indexInMerge++] = otherLabel.forwardReferences[j];
+	}
+	this.forwardReferences = mergedForwardReferences;
+	this.forwardReferenceCount = indexInMerge;
 }
 
 /*
@@ -172,7 +217,7 @@
 				codeStream.classFileOffset -= 3;
 				forwardReferenceCount--;
 				// also update the PCs in the related debug attributes
-				/** OLD CODE
+				/* OLD CODE
 					int index = codeStream.pcToSourceMapSize - 1;
 						while ((index >= 0) && (codeStream.pcToSourceMap[index][1] == oldPosition)) {
 							codeStream.pcToSourceMap[index--][1] = position;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/env/AccessRuleSet.java b/compiler/org/eclipse/jdt/internal/compiler/env/AccessRuleSet.java
index 408acf0..d8aef1f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/env/AccessRuleSet.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/env/AccessRuleSet.java
@@ -52,26 +52,29 @@
 		return this.accessRules;
 	}
 	
-	/**
-	 * Select the first access rule which is violated when accessing a given type, or null if no 'non accessible' access rule applies.
-	 * Target type file path is formed as: "org/eclipse/jdt/core/JavaCore".
-	 */
-	public AccessRestriction getViolatedRestriction(char[] targetTypeFilePath) {
-		
-		for (int i = 0, length = this.accessRules.length; i < length; i++) {
-			AccessRule accessRule = this.accessRules[i];
-			if (CharOperation.pathMatch(accessRule.pattern, targetTypeFilePath, true/*case sensitive*/, '/')) {
-				switch (accessRule.problemId) {
-					case IProblem.ForbiddenReference:
-					case IProblem.DiscouragedReference:
-						return new AccessRestriction(accessRule, this.messageTemplate);
-					default:
-						return null;
-				}
+/**
+ * Select the first access rule which is violated when accessing a given type, 
+ * or null if no 'non accessible' access rule applies.
+ * @param targetTypeFilePath the target type file path, formed as: 
+ * "org/eclipse/jdt/core/JavaCore"
+ * @return the first access restriction that applies if any, null else
+ */
+public AccessRestriction getViolatedRestriction(char[] targetTypeFilePath) {
+	for (int i = 0, length = this.accessRules.length; i < length; i++) {
+		AccessRule accessRule = this.accessRules[i];
+		if (CharOperation.pathMatch(accessRule.pattern, targetTypeFilePath, 
+				true/*case sensitive*/, '/')) {
+			switch (accessRule.problemId) {
+				case IProblem.ForbiddenReference:
+				case IProblem.DiscouragedReference:
+					return new AccessRestriction(accessRule, this.messageTemplate);
+				default:
+					return null;
 			}
 		}
-		return null;
 	}
+	return null;
+}
 	
 	public String toString() {
 		return toString(true/*wrap lines*/);
diff --git a/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
index 52e7f2a..5c37059 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.flow;
 
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -385,7 +386,7 @@
 			return true;
 
 		// final constants are inlined, and thus considered as always initialized
-		if (local.isConstantValue()) {
+		if (local.constant() != Constant.NotAConstant) {
 			return true;
 		}
 		return isDefinitelyAssigned(local.id + maxFieldCount);
@@ -413,7 +414,7 @@
 		if ((this.reachMode & UNREACHABLE) != 0)
 			return false;
 		// final constants are inlined, and thus considered as always initialized
-		if (local.isConstantValue()) {
+		if (local.constant() != Constant.NotAConstant) {
 			return true;
 		}
 		return isDefinitelyNonNull(local.id + maxFieldCount);
@@ -483,7 +484,7 @@
 	final public boolean isPotentiallyAssigned(LocalVariableBinding local) {
 		
 		// final constants are inlined, and thus considered as always initialized
-		if (local.isConstantValue()) {
+		if (local.constant() != Constant.NotAConstant) {
 			return true;
 		}
 		return isPotentiallyAssigned(local.id + maxFieldCount);
diff --git a/compiler/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java b/compiler/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java
index 4eb624b..4e55858 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java
@@ -9,9 +9,6 @@
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.impl;
-
-import org.eclipse.jdt.internal.compiler.util.Util;
-
 public class BooleanConstant extends Constant {
 
 	boolean value;
@@ -26,9 +23,7 @@
 
 	public String stringValue() {
 		//spec 15.17.11
-		String s = Util.toBoolean(value).toString();
-		if (s == null) return "null"; //$NON-NLS-1$
-		return s;
+		return String.valueOf(this.value);
 	}
 
 	public String toString(){
diff --git a/compiler/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java b/compiler/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java
index d73ea9a..994666b 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java
@@ -38,10 +38,7 @@
 }
 public String stringValue() {
 	//spec 15.17.11
-	
-	String s = new Integer(value).toString() ;
-	if (s == null) return "null"; //$NON-NLS-1$
-	return s;
+	return String.valueOf(this.value) ;
 }
 public String toString(){
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/impl/CharConstant.java b/compiler/org/eclipse/jdt/internal/compiler/impl/CharConstant.java
index ddf344a..f5834a2 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/impl/CharConstant.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/impl/CharConstant.java
@@ -40,10 +40,7 @@
 	}
 	public String stringValue() {
 		//spec 15.17.11
-		
-		String s = new Character(value).toString() ;
-		if (s == null) return "null"; //$NON-NLS-1$
-		return s;
+		return String.valueOf(this.value);
 	}
 	public String toString(){
 	
diff --git a/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 2b49381..9930d0e 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -269,13 +269,13 @@
 	public boolean reportSpecialParameterHidingField = false;
 
 	// check javadoc comments tags
-	public int reportInvalidJavadocTagsVisibility = ClassFileConstants.AccPrivate; 
-	public boolean reportInvalidJavadocTags = true;
-	public boolean reportInvalidJavadocTagsDeprecatedRef = true;
-	public boolean reportInvalidJavadocTagsNotVisibleRef = true;
+	public int reportInvalidJavadocTagsVisibility = ClassFileConstants.AccPublic; 
+	public boolean reportInvalidJavadocTags = false;
+	public boolean reportInvalidJavadocTagsDeprecatedRef = false;
+	public boolean reportInvalidJavadocTagsNotVisibleRef = false;
 
 	// check missing javadoc tags
-	public int reportMissingJavadocTagsVisibility = ClassFileConstants.AccPrivate; 
+	public int reportMissingJavadocTagsVisibility = ClassFileConstants.AccPublic; 
 	public boolean reportMissingJavadocTagsOverriding = false;
 
 	// check missing javadoc comments
diff --git a/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java b/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java
index fe5bb5a..6fe3676 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java
@@ -1240,29 +1240,29 @@
 			break;
 			case T_JavaLangString :
 				switch (rightId){
-					case T_char :	return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_float:	return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_double:	return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_byte:	return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_short:	return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_int:		return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_long:	return Constant.fromValue(left.stringValue() + right.stringValue());
+					case T_char :	return Constant.fromValue(left.stringValue() + String.valueOf(right.charValue()));
+					case T_float:	return Constant.fromValue(left.stringValue() + String.valueOf(right.floatValue()));
+					case T_double:	return Constant.fromValue(left.stringValue() + String.valueOf(right.doubleValue()));
+					case T_byte:	return Constant.fromValue(left.stringValue() + String.valueOf(right.byteValue()));
+					case T_short:	return Constant.fromValue(left.stringValue() + String.valueOf(right.shortValue()));
+					case T_int:		return Constant.fromValue(left.stringValue() + String.valueOf(right.intValue()));
+					case T_long:	return Constant.fromValue(left.stringValue() + String.valueOf(right.longValue()));
 					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
-					case T_boolean:	return Constant.fromValue(left.stringValue() + right.stringValue());
+					case T_boolean:	return Constant.fromValue(left.stringValue() + right.booleanValue());
 				}
 			break;	
-			case T_null :
-				switch (rightId){
-					case T_char :	return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_float:	return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_double:	return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_byte:	return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_short:	return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_int:		return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_long:	return Constant.fromValue(left.stringValue() + right.stringValue());
-					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
-				}
-				
+//			case T_null :
+//				switch (rightId){
+//					case T_char :	return Constant.fromValue(left.stringValue() + String.valueOf(right.charValue()));
+//					case T_float:	return Constant.fromValue(left.stringValue() + String.valueOf(right.floatValue()));
+//					case T_double:	return Constant.fromValue(left.stringValue() + String.valueOf(right.doubleValue()));
+//					case T_byte:	return Constant.fromValue(left.stringValue() + String.valueOf(right.byteValue()));
+//					case T_short:	return Constant.fromValue(left.stringValue() + String.valueOf(right.shortValue()));
+//					case T_int:		return Constant.fromValue(left.stringValue() + String.valueOf(right.intValue()));
+//					case T_long:	return Constant.fromValue(left.stringValue() + String.valueOf(right.longValue()));
+//					case T_JavaLangString:	return Constant.fromValue(left.stringValue() + right.stringValue()); 
+//					case T_boolean:	return Constant.fromValue(left.stringValue() + right.booleanValue());
+//				}				
 			}
 		
 		return NotAConstant;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java b/compiler/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java
index d6ff773..ce72b72 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java
@@ -47,9 +47,7 @@
 	}
 	
 	public String stringValue() {
-		String s = Double.toString(value);
-		if (s == null) return "null"; //$NON-NLS-1$
-		return s;
+		return String.valueOf(this.value);
 	}
 	
 	public String toString() {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java b/compiler/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java
index 53a0c51..efa77d3 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java
@@ -47,9 +47,7 @@
 	}
 	
 	public String stringValue() {
-		String s = Float.toString(value);
-		if (s == null) return "null"; //$NON-NLS-1$
-		return s;
+		return String.valueOf(this.value);
 	}
 
 	public String toString() {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/impl/IntConstant.java b/compiler/org/eclipse/jdt/internal/compiler/impl/IntConstant.java
index 149ea6d..cd15e52 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/impl/IntConstant.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/impl/IntConstant.java
@@ -48,9 +48,7 @@
 	
 	public String stringValue() {
 		//spec 15.17.11
-		String s = new Integer(value).toString();
-		if (s == null) return "null"; //$NON-NLS-1$
-		return s;
+		return String.valueOf(this.value);
 	}
 
 	public String toString() {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/impl/LongConstant.java b/compiler/org/eclipse/jdt/internal/compiler/impl/LongConstant.java
index 20f22c7..5e3e2d6 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/impl/LongConstant.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/impl/LongConstant.java
@@ -38,10 +38,7 @@
 }
 public String stringValue() {
 	//spec 15.17.11
-	
-	String s = new Long(value).toString() ;
-	if (s == null) return "null"; //$NON-NLS-1$
-	return s;
+	return String.valueOf(this.value);
 }
 public String toString(){
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java b/compiler/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java
index df8eb6e..5c192a8 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java
@@ -38,10 +38,7 @@
 }
 public String stringValue() {
 	//spec 15.17.11
-	
-	String s = new Integer(value).toString() ;
-	if (s == null) return "null"; //$NON-NLS-1$
-	return s;
+	return String.valueOf(this.value);
 }
 public String toString(){
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index be1c13b..4585ecc 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -14,6 +14,7 @@
 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.Constant;
 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
 
 public class BlockScope extends Scope {
@@ -145,7 +146,7 @@
 	 */
 	public final boolean allowBlankFinalFieldAssignment(FieldBinding binding) {
 
-		if (enclosingSourceType() != binding.declaringClass)
+		if (enclosingReceiverType() != binding.declaringClass)
 			return false;
 
 		MethodScope methodScope = methodScope();
@@ -221,7 +222,7 @@
 				LocalVariableBinding local = locals[ilocal]; // if no local at all, will be locals[ilocal]==null
 				
 				// check if variable is actually used, and may force it to be preserved
-				boolean generateCurrentLocalVar = (local.useFlag == LocalVariableBinding.USED && !local.isConstantValue());
+				boolean generateCurrentLocalVar = (local.useFlag == LocalVariableBinding.USED && local.constant() == Constant.NotAConstant);
 					
 				// do not report fake used variable
 				if (local.useFlag == LocalVariableBinding.UNUSED
@@ -298,6 +299,63 @@
 		}
 	}
 
+	/**
+	 * Returns all declarations of most specific locals containing a given position in their source range.
+	 * This code does not recurse in nested types.
+	 * Returned array may have null values at trailing indexes.
+	 */
+	public LocalDeclaration[] findLocalVariableDeclarations(int position) {
+
+		// local variable init
+		int ilocal = 0, maxLocals = this.localIndex;
+		boolean hasMoreVariables = maxLocals > 0;
+		LocalDeclaration[] localDeclarations = null;
+		int declPtr = 0;
+
+		// scope init
+		int iscope = 0, maxScopes = this.subscopeCount;
+		boolean hasMoreScopes = maxScopes > 0;
+
+		// iterate scopes and variables in parallel
+		while (hasMoreVariables || hasMoreScopes) {
+			if (hasMoreScopes
+				&& (!hasMoreVariables || (subscopes[iscope].startIndex() <= ilocal))) {
+				// consider subscope first
+				Scope subscope = subscopes[iscope];
+				if (subscope.kind == Scope.BLOCK_SCOPE) { // do not dive in nested types
+					localDeclarations = ((BlockScope)subscope).findLocalVariableDeclarations(position);
+					if (localDeclarations != null) {
+						return localDeclarations;
+					}
+				}
+				hasMoreScopes = ++iscope < maxScopes;
+			} else {
+				// consider variable first
+				LocalVariableBinding local = locals[ilocal]; // if no local at all, will be locals[ilocal]==null
+				if (local != null) {
+					LocalDeclaration localDecl = local.declaration;
+					if (localDecl != null) {
+						if (localDecl.declarationSourceStart <= position) {
+							if (position <= localDecl.declarationSourceEnd) {
+								if (localDeclarations == null) {
+									localDeclarations = new LocalDeclaration[maxLocals];
+								}
+								localDeclarations[declPtr++] = localDecl;
+							}
+						} else {
+							return localDeclarations;
+						}
+					}
+				}
+				hasMoreVariables = ++ilocal < maxLocals;
+				if (!hasMoreVariables && localDeclarations != null) {
+					return localDeclarations;
+				}
+			}
+		}
+		return null;
+	}
+
 	/* Note that it must never produce a direct access to the targetEnclosingType,
 	 * but instead a field sequence (this$2.this$1.this$0) so as to handle such a test case:
 	 *
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index c6d0bcb..ba2a3d7 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -32,7 +32,7 @@
 	public TypeDeclaration referenceContext;
 	public TypeReference superTypeReference;
 
-	private final static char[] IncompleteHierarchy = new char[] {'h', 'a', 's', ' ', 'i', 'n', 'c', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', ' ', 'h', 'i', 'e', 'r', 'a', 'r', 'c', 'h', 'y'};
+	public final static char[] IncompleteHierarchy = new char[] {'h', 'a', 's', ' ', 'i', 'n', 'c', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', ' ', 'h', 'i', 'e', 'r', 'a', 'r', 'c', 'h', 'y'};
 
 	public ClassScope(Scope parent, TypeDeclaration context) {
 		super(CLASS_SCOPE, parent);
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
index 23aac27..50147aa 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
@@ -188,6 +188,38 @@
 	System.arraycopy(returnTypeKey, 0, uniqueKey, index, returnTypeLength);
 	return uniqueKey;
 }
+
+public Constant constant() {
+	Constant fieldConstant = this.constant;
+	if (fieldConstant == null) {
+		if (this.isFinal()) {
+			//The field has not been yet type checked.
+			//It also means that the field is not coming from a class that
+			//has already been compiled. It can only be from a class within
+			//compilation units to process. Thus the field is NOT from a BinaryTypeBinbing
+			FieldBinding originalField = this.original();
+			if (originalField.declaringClass instanceof SourceTypeBinding) {
+				SourceTypeBinding sourceType = (SourceTypeBinding) originalField.declaringClass;
+				if (sourceType.scope != null) {
+					TypeDeclaration typeDecl = sourceType.scope.referenceContext;
+					FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField);
+					fieldDecl.resolve(originalField.isStatic() //side effect on binding 
+							? typeDecl.staticInitializerScope
+							: typeDecl.initializerScope);
+					fieldConstant = originalField.constant();
+				} else {
+					fieldConstant = Constant.NotAConstant; // shouldn't occur per construction (paranoid null check)
+				} 
+			} else {
+				fieldConstant = Constant.NotAConstant; // shouldn't occur per construction (paranoid null check)
+			}
+		} else {
+			fieldConstant = Constant.NotAConstant;
+		}
+		this.constant = fieldConstant;
+	}
+	return fieldConstant;
+}
 /**
  * X<T> t   -->  LX<TT;>;
  */
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index a455d88..3f12f5b 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -352,6 +352,29 @@
 	return packageBinding;
 }
 
+/**
+ * Convert a given source type into a parameterized form if generic.
+ * generic X<E> --> param X<E>
+ */
+public ReferenceBinding convertToParameterizedType(ReferenceBinding originalType) {
+	if (originalType != null) {
+		boolean isGeneric = originalType.isGenericType();
+		ReferenceBinding originalEnclosingType = originalType.enclosingType();
+		ReferenceBinding convertedEnclosingType = originalEnclosingType;
+		boolean needToConvert = isGeneric;
+		if (originalEnclosingType != null) {
+			convertedEnclosingType = originalType.isStatic() 
+				? (ReferenceBinding) convertToRawType(originalEnclosingType) 
+				: convertToParameterizedType(originalEnclosingType);
+			needToConvert |= originalEnclosingType != convertedEnclosingType;
+		}
+		if (needToConvert) {
+			return createParameterizedType(originalType, isGeneric ? originalType.typeVariables() : null, convertedEnclosingType);
+		}
+	}
+	return originalType;
+}
+
 public TypeBinding convertToRawType(TypeBinding type) {
 
 	int dimension;
@@ -391,29 +414,22 @@
 		convertedType = needToConvert ? createRawType((ReferenceBinding)originalType.erasure(), null) : originalType;
 	} else {
 		ReferenceBinding convertedEnclosing;
-		switch (originalEnclosing.kind()) {
-			case Binding.GENERIC_TYPE :
-			case Binding.PARAMETERIZED_TYPE :
-				if (needToConvert || ((ReferenceBinding)originalType).isStatic()) {
-					convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing);
-				} else {
-					convertedEnclosing = originalEnclosing;
-				}
-				break;
-			case Binding.RAW_TYPE :
-				needToConvert |= !((ReferenceBinding)originalType).isStatic();
-			default :
-				convertedEnclosing = originalEnclosing;
-				break;
+		if (originalEnclosing.kind() == Binding.RAW_TYPE) {
+			needToConvert |= !((ReferenceBinding)originalType).isStatic();
+			convertedEnclosing = originalEnclosing;
+		} else if (needToConvert || ((ReferenceBinding)originalType).isStatic()) {
+			convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing);
+		} else {
+//		} else if (originalEnclosing instanceof SourceTypeBinding){
+			convertedEnclosing = convertToParameterizedType(originalEnclosing);
+//		} else {
+//			convertedEnclosing = originalEnclosing;
 		}
 		ReferenceBinding originalGeneric = (ReferenceBinding) originalType.erasure();
 		if (needToConvert) {
 			convertedType = createRawType(originalGeneric, convertedEnclosing);
 		} else if (originalEnclosing != convertedEnclosing) {
-			if (originalGeneric.isStatic())
-				convertedType = createParameterizedType(originalGeneric, null, convertedEnclosing);
-			else 
-				convertedType = createRawType(originalGeneric, convertedEnclosing);
+			convertedType = createParameterizedType(originalGeneric, null, convertedEnclosing);
 		} else {
 			convertedType = originalType;
 		}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index 78f06b7..5e23234 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -332,9 +332,6 @@
  * p.X { <T> void bar(X<T> t) } --> Lp/X;.bar<T:Ljava/lang/Object;>(LX<TT;>;)V
  */
 public char[] computeUniqueKey(boolean isLeaf) {
-	return computeUniqueKey(this, isLeaf);
-}
-protected char[] computeUniqueKey(MethodBinding methodBinding, boolean isLeaf) {
 	// declaring class 
 	char[] declaringKey = this.declaringClass.computeUniqueKey(false/*not a leaf*/);
 	int declaringLength = declaringKey.length;
@@ -343,8 +340,8 @@
 	int selectorLength = this.selector == TypeConstants.INIT ? 0 : this.selector.length;
 	
 	// generic signature
-	char[] sig = methodBinding.genericSignature();
-	if (sig == null) sig = methodBinding.signature();
+	char[] sig = genericSignature();
+	if (sig == null) sig = signature();
 	int signatureLength = sig.length;
 	
 	char[] uniqueKey = new char[declaringLength + 1 + selectorLength + signatureLength];
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
index 379bb29..3d816fb 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
@@ -19,7 +19,7 @@
 }
 boolean areMethodsEqual(MethodBinding one, MethodBinding two) {
 	MethodBinding sub = computeSubstituteMethod(two, one);
-	return sub != null && super.areMethodsEqual(one, sub);
+	return sub != null && doesSubstituteMethodOverride(one, sub) && areReturnTypesEqual(one, sub);
 }
 boolean areParametersEqual(MethodBinding one, MethodBinding two) {
 	TypeBinding[] oneArgs = one.parameters;
@@ -80,17 +80,6 @@
 	//		return ((UnresolvedReferenceBinding) two).resolvedType == one;
 	return false; // all other type bindings are identical
 }
-boolean areTypeVariablesInterchangeable(MethodBinding one, MethodBinding two) {
-	TypeVariableBinding[] vars = one.typeVariables;
-	TypeVariableBinding[] vars2 = two.typeVariables;
-	if (vars.length != vars2.length)
-		return false;
-	
-	for (int v = vars.length; --v >= 0;)
-		if (!vars[v].isInterchangeableWith(this.environment, vars2[v]))
-			return false;
-	return true;
-}
 boolean canSkipInheritedMethods() {
 	if (this.type.superclass() != null)
 		if (this.type.superclass().isAbstract() || this.type.superclass().isParameterizedType())
@@ -152,7 +141,14 @@
 		for (int i = 0, l = allInheritedMethods.length; i < l; i++) {
 			MethodBinding otherInheritedMethod = allInheritedMethods[i];
 			MethodBinding otherOriginal = otherInheritedMethod.original();
-			if (otherOriginal == otherInheritedMethod || doesMethodOverride(inheritedMethod, otherInheritedMethod)) continue;
+			if (otherOriginal == originalInherited || otherOriginal == otherInheritedMethod) continue;
+
+			MethodBinding compareMethod = inheritedMethod instanceof ParameterizedGenericMethodBinding
+				? ((ParameterizedGenericMethodBinding) inheritedMethod).originalMethod
+				: inheritedMethod;
+			MethodBinding substitute = computeSubstituteMethod(otherInheritedMethod, compareMethod);
+			if (substitute == null || doesSubstituteMethodOverride(compareMethod, substitute))
+				continue;
 			if (detectInheritedMethodClash(originalInherited, otherOriginal))
 				return;
 		}
@@ -232,10 +228,11 @@
 		superType = superType.superclass(); // now start with its superclass
 		while (superType != null && superType.isValidBinding()) {
 			MethodBinding[] methods = superType.getMethods(currentMethod.selector);
-			for (int m = 0, n = methods.length; m < n; m++)
-				if (currentMethod.parameters.length == methods[m].parameters.length)
-					if (!doesMethodOverride(currentMethod, methods[m]) && detectNameClash(currentMethod, methods[m]))
-						return;
+			for (int m = 0, n = methods.length; m < n; m++) {
+				MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod);
+				if (substitute != null && !doesSubstituteMethodOverride(currentMethod, substitute) && detectNameClash(currentMethod, substitute))
+					return;
+			}
 			if ((itsInterfaces = superType.superInterfaces()) != NoSuperInterfaces) {
 				if (++lastPosition == interfacesToVisit.length)
 					System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
@@ -250,10 +247,11 @@
 				superType = interfaces[j];
 				if (superType.isValidBinding()) {
 					MethodBinding[] methods = superType.getMethods(currentMethod.selector);
-					for (int m = 0, n = methods.length; m < n; m++)
-						if (currentMethod.parameters.length == methods[m].parameters.length)
-							if (!doesMethodOverride(currentMethod, methods[m]) && detectNameClash(currentMethod, methods[m]))
-								return;
+					for (int m = 0, n = methods.length; m < n; m++){
+						MethodBinding substitute = computeSubstituteMethod(methods[m], currentMethod);
+						if (substitute != null && !doesSubstituteMethodOverride(currentMethod, substitute) && detectNameClash(currentMethod, substitute))
+							return;
+					}
 					if ((itsInterfaces = superType.superInterfaces()) != NoSuperInterfaces) {
 						if (++lastPosition == interfacesToVisit.length)
 							System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
@@ -317,7 +315,7 @@
 				for (int j = 0, length2 = inherited.length; j < length2; j++) {
 					MethodBinding inheritedMethod = computeSubstituteMethod(inherited[j], currentMethod);
 					if (inheritedMethod != null) {
-						if (foundMatch[j] == 0 && doesMethodOverride(currentMethod, inheritedMethod)) {
+						if (foundMatch[j] == 0 && doesSubstituteMethodOverride(currentMethod, inheritedMethod)) {
 							matchingInherited[++index] = inheritedMethod;
 							foundMatch[j] = 1; // cannot null out inherited methods
 						} else {
@@ -343,7 +341,7 @@
 					continue;
 				otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod);
 				if (otherInheritedMethod != null) {
-					if (doesMethodOverride(inheritedMethod, otherInheritedMethod)) {
+					if (doesSubstituteMethodOverride(inheritedMethod, otherInheritedMethod)) {
 						matchingInherited[++index] = otherInheritedMethod;
 						foundMatch[j] = 1; // cannot null out inherited methods
 					} else {
@@ -380,7 +378,7 @@
 					if (canSkipInheritedMethods(inheritedMethod, otherInheritedMethod))
 						continue;
 					otherInheritedMethod = computeSubstituteMethod(otherInheritedMethod, inheritedMethod);
-					if (otherInheritedMethod != null && doesMethodOverride(inheritedMethod, otherInheritedMethod)) {
+					if (otherInheritedMethod != null && doesSubstituteMethodOverride(inheritedMethod, otherInheritedMethod)) {
 						matchingInherited[++index] = otherInheritedMethod;
 						inherited[j] = null; // do not want to find it again
 					}
@@ -413,6 +411,7 @@
 	int inheritedLength = inheritedTypeVariables.length;
 	TypeVariableBinding[] typeVariables = currentMethod.typeVariables;
 	int length = typeVariables.length;
+	if (length > 0 && inheritedLength != length) return inheritedMethod;
 	TypeBinding[] arguments = new TypeBinding[inheritedLength];
 	if (inheritedLength <= length) {
 		System.arraycopy(typeVariables, 0, arguments, 0, inheritedLength);
@@ -423,9 +422,32 @@
 	}
 	ParameterizedGenericMethodBinding substitute =
 		new ParameterizedGenericMethodBinding(inheritedMethod, arguments, this.environment);
-	for (int i = 0; i < inheritedLength; i++)
-	    if (inheritedTypeVariables[i].boundCheck(substitute, arguments[i]) != TypeConstants.OK)
-	    	return inheritedMethod; // incompatible due to bound check
+
+	// interface I { <T> void foo(T t); }
+	// class X implements I { public <T extends I> void foo(T t) {} }
+	// for the above case, we do not want to answer the substitute method since its not a match
+	for (int i = 0; i < inheritedLength; i++) {
+		TypeVariableBinding inheritedTypeVariable = inheritedTypeVariables[i];
+		TypeBinding argument = arguments[i];
+		if (argument instanceof TypeVariableBinding) {
+			TypeVariableBinding typeVariable = (TypeVariableBinding) argument;
+			if (Scope.substitute(substitute, inheritedTypeVariable.superclass) != typeVariable.superclass)  
+				return inheritedMethod; // not a match
+			int interfaceLength = inheritedTypeVariable.superInterfaces.length;
+			ReferenceBinding[] interfaces = typeVariable.superInterfaces;
+			if (interfaceLength != interfaces.length)
+				return inheritedMethod; // not a match
+			next : for (int j = 0; j < interfaceLength; j++) {
+				TypeBinding superType = Scope.substitute(substitute, inheritedTypeVariable.superInterfaces[j]);
+				for (int k = 0; k < interfaceLength; k++)
+					if (superType == interfaces[k])
+						continue next;
+				return inheritedMethod; // not a match
+			}
+		} else if (inheritedTypeVariables[i].boundCheck(substitute, argument) != TypeConstants.OK) {
+	    	return inheritedMethod;
+		}
+	}
    return substitute;
 }
 boolean detectInheritedMethodClash(MethodBinding inherited, MethodBinding otherInherited) {
@@ -446,20 +468,24 @@
 	return false;
 }
 public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) {
-	if (doTypeVariablesClash(method, inheritedMethod)) return false;
-	if (areParametersEqual(method, inheritedMethod)) return true;
-	if (method.declaringClass == inheritedMethod.declaringClass) return false;
+	MethodBinding substitute = computeSubstituteMethod(inheritedMethod, method);
+	return substitute != null && doesSubstituteMethodOverride(method, substitute);
+}
+boolean doesSubstituteMethodOverride(MethodBinding method, MethodBinding substituteMethod) {
+	if (doTypeVariablesClash(method, substituteMethod)) return false;
+	if (areParametersEqual(method, substituteMethod)) return true;
+	if (method.declaringClass == substituteMethod.declaringClass) return false;
 
 	TypeBinding[] params = method.parameters;
-	TypeBinding[] inheritedParams = inheritedMethod.parameters;
+	TypeBinding[] inheritedParams = substituteMethod.parameters;
 	int length = params.length;
 	if (length != inheritedParams.length)
 		return false;
 
 	// also allow a method such as Number foo(Number) to override <U> T foo(T) where T extends Number
-	if (method.typeVariables != NoTypeVariables || !inheritedMethod.hasSubstitutedParameters())
+	if (method.typeVariables != NoTypeVariables || !substituteMethod.hasSubstitutedParameters())
 		return false;
-	if (method.declaringClass.findSuperTypeWithSameErasure(inheritedMethod.declaringClass) == null)
+	if (method.declaringClass.findSuperTypeWithSameErasure(substituteMethod.declaringClass) == null)
 		return false;
 
 	for (int i = 0; i < length; i++)
@@ -490,11 +516,8 @@
 	return false;
 }
 boolean doTypeVariablesClash(MethodBinding one, MethodBinding substituteTwo) {
-	if (one.typeVariables == NoTypeVariables) return false;
-	MethodBinding subTwo = substituteTwo instanceof ParameterizedGenericMethodBinding
-		? ((ParameterizedGenericMethodBinding) substituteTwo).originalMethod
-		: substituteTwo;
-	return !one.areTypeVariableErasuresEqual(subTwo);
+	// one has type variables and substituteTwo did not pass bounds check in computeSubstituteMethod()
+	return one.typeVariables != NoTypeVariables && !(substituteTwo instanceof ParameterizedGenericMethodBinding);
 }
 boolean isInterfaceMethodImplemented(MethodBinding inheritedMethod, MethodBinding existingMethod, ReferenceBinding superType) {
 	if (inheritedMethod.original() != inheritedMethod && existingMethod.declaringClass.isInterface())
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java
index c0942e6..aba2c09 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedFieldBinding.java
@@ -23,48 +23,45 @@
     
     public FieldBinding originalField;
     
-	public ParameterizedFieldBinding(ParameterizedTypeBinding parameterizedDeclaringClass, FieldBinding originalField) {
-	    super (
-	            originalField.name, 
-	            (originalField.modifiers & ClassFileConstants.AccEnum) != 0
-	            	? parameterizedDeclaringClass // enum constant get paramType as its type
-           			: (originalField.modifiers & ClassFileConstants.AccStatic) != 0 
-           					? originalField.type // no subst for static field
-           					: Scope.substitute(parameterizedDeclaringClass, originalField.type), 
-	            originalField.modifiers, 
-	            parameterizedDeclaringClass, 
-	            null);
-	    this.originalField = originalField;
-	    this.id = originalField.id;
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.compiler.lookup.VariableBinding#constant()
-	 */
-	public Constant constant() {
-		return this.originalField.constant();
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.compiler.lookup.VariableBinding#isConstantValue()
-	 */
-	public boolean isConstantValue() {
-		return this.originalField.isConstantValue();
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.compiler.lookup.FieldBinding#original()
-	 */
-	public FieldBinding original() {
-		return this.originalField.original();
-	}
-	/**
-	 * @see org.eclipse.jdt.internal.compiler.lookup.VariableBinding#constant()
-	 */
-	public void setConstant(Constant constant) {
-		this.originalField.setConstant(constant);
-	}
+public ParameterizedFieldBinding(ParameterizedTypeBinding parameterizedDeclaringClass, FieldBinding originalField) {
+    super (
+            originalField.name, 
+            (originalField.modifiers & ClassFileConstants.AccEnum) != 0
+            	? parameterizedDeclaringClass // enum constant get paramType as its type
+       			: (originalField.modifiers & ClassFileConstants.AccStatic) != 0 
+       					? originalField.type // no subst for static field
+       					: Scope.substitute(parameterizedDeclaringClass, originalField.type), 
+            originalField.modifiers, 
+            parameterizedDeclaringClass, 
+            null);
+    this.originalField = originalField;
+    this.tagBits = originalField.tagBits;
+    this.id = originalField.id;
+}
 	
-	public IAnnotationInstance[] getAnnotations()
-	{
-		return original().getAnnotations();
-	}
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.VariableBinding#constant()
+ */
+public Constant constant() {
+	return this.originalField.constant();
+}
+
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.FieldBinding#original()
+ */
+public FieldBinding original() {
+	return this.originalField.original();
+}
+
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.VariableBinding#constant()
+ */
+public void setConstant(Constant constant) {
+	this.originalField.setConstant(constant);
+}
+
+public IAnnotationInstance[] getAnnotations() {
+	return original().getAnnotations();
+}
 }
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
index 9e83e69..01ffc4f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
@@ -131,6 +131,7 @@
 			// process mandatory arguments
 			for (int i = 0; i < minArgLength; i++) {
 				parameters[i].collectSubstitutes(scope, arguments[i], collectedSubstitutes, CONSTRAINT_EXTENDS);
+				if (collectedSubstitutes.get(VoidBinding) != null) return null; // impossible substitution
 			}
 			// process optional arguments
 			if (minArgLength < argLength) {
@@ -154,12 +155,14 @@
 				}
 				for (int i = minArgLength; i < argLength; i++) {
 					varargType.collectSubstitutes(scope, arguments[i], collectedSubstitutes, CONSTRAINT_EXTENDS);
+					if (collectedSubstitutes.get(VoidBinding) != null) return null; // impossible substitution
 				}
 			}
 		} else {
 			int paramLength = parameters.length;
 			for (int i = 0; i < paramLength; i++) {
 				parameters[i].collectSubstitutes(scope, arguments[i], collectedSubstitutes, CONSTRAINT_EXTENDS);
+				if (collectedSubstitutes.get(VoidBinding) != null) return null; // impossible substitution
 			}
 		}
 		TypeVariableBinding[] originalVariables = originalMethod.typeVariables;
@@ -206,7 +209,6 @@
 						for (int j = 0, equalLength = equalSubstitutes.length; j < equalLength; j++) {
 							TypeBinding equalSubstitute = equalSubstitutes[j];
 							if (equalSubstitute == null) continue nextConstraint;
-//							if (equalSubstitute == current) continue nextConstraint;
 							if (equalSubstitute == current) {
 								// try to find a better different match if any in subsequent equal candidates
 								for (int k = j+1; k < equalLength; k++) {
@@ -285,6 +287,7 @@
 			rawArguments[i] =  environment.convertToRawType(originalVariables[i].erasure());
 		}		
 	    this.isRaw = true;
+	    this.tagBits = originalMethod.tagBits;
 		this.isUnchecked = false;
 	    this.environment = environment;
 		this.modifiers = originalMethod.modifiers;
@@ -318,6 +321,7 @@
 	    this.typeVariables = NoTypeVariables;
 	    this.typeArguments = typeArguments;
 	    this.isRaw = false;
+	    this.tagBits = originalMethod.tagBits;
 		this.isUnchecked = false;
 	    this.originalMethod = originalMethod;
 	    this.parameters = Scope.substitute(this, originalMethod.parameters);
@@ -387,6 +391,7 @@
 		    // infer from expected return type
 			if (expectedType != null) {
 			    this.returnType.collectSubstitutes(scope, expectedType, collectedSubstitutes, CONSTRAINT_SUPER);
+				if (collectedSubstitutes.get(VoidBinding) != null) return null; // impossible substitution
 			}
 		    // infer from bounds of type parameters
 			for (int i = 0; i < varLength; i++) {
@@ -396,18 +401,22 @@
 				if (originalVariable.firstBound == originalVariable.superclass) {
 					TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superclass);
 					argument.collectSubstitutes(scope, substitutedBound, collectedSubstitutes, CONSTRAINT_SUPER);
+					if (collectedSubstitutes.get(VoidBinding) != null) return null; // impossible substitution
 					// JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference
 					// e.g. given: <E extends Object, S extends Collection<E>> S test1(S param)
 					//                   invocation: test1(new Vector<String>())    will infer: S=Vector<String>  and with code below: E=String
 					if (argAlreadyInferred)
 						substitutedBound.collectSubstitutes(scope, argument, collectedSubstitutes, CONSTRAINT_EXTENDS);
+						if (collectedSubstitutes.get(VoidBinding) != null) return null; // impossible substitution
 				}
 				for (int j = 0, max = originalVariable.superInterfaces.length; j < max; j++) {
 					TypeBinding substitutedBound = Scope.substitute(this, originalVariable.superInterfaces[j]);
 					argument.collectSubstitutes(scope, substitutedBound, collectedSubstitutes, CONSTRAINT_SUPER);
+					if (collectedSubstitutes.get(VoidBinding) != null) return null; // impossible substitution
 					// JLS 15.12.2.8 claims reverse inference shouldn't occur, however it improves inference
 					if (argAlreadyInferred)
 						substitutedBound.collectSubstitutes(scope, argument, collectedSubstitutes, CONSTRAINT_EXTENDS);
+						if (collectedSubstitutes.get(VoidBinding) != null) return null; // impossible substitution
 				}
 			}
 			substitutes = resolveSubstituteConstraints(scope, originalVariables, substitutes, true/*consider Ti<:Uk*/, collectedSubstitutes);
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
index d1d47cf..817379d 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
@@ -18,7 +18,6 @@
  * their signature did involve generics or not, so as to get the proper declaringClass for
  * these methods.
  */
-
 public class ParameterizedMethodBinding extends MethodBinding {
 
 	protected MethodBinding originalMethod;
@@ -36,7 +35,8 @@
 				originalMethod.thrownExceptions,
 				parameterizedDeclaringClass);
 		this.originalMethod = originalMethod;
-
+		this.tagBits = originalMethod.tagBits;
+		
 		final TypeVariableBinding[] originalVariables = originalMethod.typeVariables;
 		Substitution substitution = null;
 		final int length = originalVariables.length;
@@ -77,14 +77,28 @@
 				TypeVariableBinding originalVariable = originalVariables[i];
 				TypeVariableBinding substitutedVariable = substitutedVariables[i];
 				TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass);
-				substitutedVariable.superclass = (ReferenceBinding) (substitutedSuperclass.isArrayType() 
-							? parameterizedDeclaringClass.environment.getType(JAVA_LANG_OBJECT)
-							: substitutedSuperclass);
-				substitutedVariable.superInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces);
+				ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces);
 				if (originalVariable.firstBound != null) {
 					substitutedVariable.firstBound = originalVariable.firstBound == originalVariable.superclass
-						? substitutedSuperclass // could be array type
-						: substitutedVariable.superInterfaces[0];
+						? substitutedSuperclass // could be array type or interface
+						: substitutedInterfaces[0];
+				}				
+				switch (substitutedSuperclass.kind()) {
+					case Binding.ARRAY_TYPE :
+						substitutedVariable.superclass = parameterizedDeclaringClass.environment.getType(JAVA_LANG_OBJECT);
+						substitutedVariable.superInterfaces = substitutedInterfaces;
+						break;
+					default:
+						if (substitutedSuperclass.isInterface()) {
+							substitutedVariable.superclass = parameterizedDeclaringClass.environment.getType(JAVA_LANG_OBJECT);
+							int interfaceCount = substitutedInterfaces.length;
+							System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount);
+							substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass;
+							substitutedVariable.superInterfaces = substitutedInterfaces;
+						} else {
+							substitutedVariable.superclass = (ReferenceBinding) substitutedSuperclass; // typeVar was extending other typeVar which got substituted with interface
+							substitutedVariable.superInterfaces = substitutedInterfaces;
+						}
 				}
 			}
 		}
@@ -139,14 +153,12 @@
 	public MethodBinding original() {
 		return this.originalMethod.original();
 	}
-	
-	public IAnnotationInstance[] getAnnotations()
-	{
+
+	public IAnnotationInstance[] getAnnotations() {
 		return original().getAnnotations();
 	}
-	
-	public IAnnotationInstance[] getParameterAnnotations(int index)
-	{
+
+	public IAnnotationInstance[] getParameterAnnotations(int index) {
 		return original().getParameterAnnotations(index);
 	}
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
index 721349f..1d8d2cb 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -35,6 +35,11 @@
 
 		this.environment = environment;
 		this.enclosingType = enclosingType; // never unresolved, never lazy per construction
+//		if (enclosingType != null && enclosingType.isGenericType()) {
+//			RuntimeException e = new RuntimeException("PARAM TYPE with GENERIC ENCLOSING");
+//			e.printStackTrace();
+//			throw e;
+//		}
 		initialize(type, arguments);
 		if (type instanceof UnresolvedReferenceBinding)
 			((UnresolvedReferenceBinding) type).addWrapper(this);
@@ -161,6 +166,9 @@
         		break;
         	case Binding.RAW_TYPE :
         		substitutes.clear(); // clear all variables to indicate raw generic method in the end
+        		if (constraint == CONSTRAINT_EQUAL) {
+        			substitutes.put(VoidBinding, NoTypes); // marker for impossible inference
+        		}
         		return;
         	default :
         		return;
@@ -204,13 +212,14 @@
 	
 	public char[] computeUniqueKey(boolean isLeaf) {
 	    StringBuffer sig = new StringBuffer(10);
-		if (this.isMemberType() && enclosingType().isParameterizedType()) {
-		    char[] typeSig = enclosingType().computeUniqueKey(false/*not a leaf*/);
+	    ReferenceBinding enclosing;
+		if (isMemberType() && ((enclosing = enclosingType()).isParameterizedType() || enclosing.isRawType())) {
+		    char[] typeSig = enclosing.computeUniqueKey(false/*not a leaf*/);
 		    for (int i = 0; i < typeSig.length-1; i++) sig.append(typeSig[i]); // copy all but trailing semicolon
 		    sig.append('.').append(sourceName());
 		} else if(this.type.isLocalType()){
 			LocalTypeBinding localTypeBinding = (LocalTypeBinding) this.type;
-			ReferenceBinding enclosing = localTypeBinding.enclosingType();
+			enclosing = localTypeBinding.enclosingType();
 			ReferenceBinding temp;
 			while ((temp = enclosing.enclosingType()) != null)
 				enclosing = temp;
@@ -239,12 +248,12 @@
 			sig.insert(0, "&"); //$NON-NLS-1$
 			sig.insert(0, captureSourceType.computeUniqueKey(false/*not a leaf*/));
 		}
-
+	
 		int sigLength = sig.length();
 		char[] uniqueKey = new char[sigLength];
 		sig.getChars(0, sigLength, uniqueKey, 0);			
 		return uniqueKey;
-   	}
+	}
 
 	/**
 	 * @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#constantPoolName()
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index 93f4cad..c6224d1 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -65,7 +65,7 @@
 /* Answer true if the receiver is visible to the receiverType and the invocationType.
 */
 
-public final boolean canBeSeenBy(ReferenceBinding receiverType, SourceTypeBinding invocationType) {
+public final boolean canBeSeenBy(ReferenceBinding receiverType, ReferenceBinding invocationType) {
 	if (isPublic()) return true;
 
 	if (invocationType == this && invocationType == receiverType) return true;
@@ -83,12 +83,10 @@
 		ReferenceBinding currentType = invocationType;
 		ReferenceBinding declaringClass = enclosingType(); // protected types always have an enclosing one
 		if (declaringClass == invocationType) return true;
-
-		ReferenceBinding declaringErasure = (ReferenceBinding) declaringClass.erasure();
 		if (declaringClass == null) return false; // could be null if incorrect top-level protected type
 		//int depth = 0;
 		do {
-			if (currentType.findSuperTypeWithSameErasure(declaringErasure) != null) return true;
+			if (currentType.findSuperTypeWithSameErasure(declaringClass) != null) return true;
 			//depth++;
 			currentType = currentType.enclosingType();
 		} while (currentType != null);
@@ -992,9 +990,7 @@
 /**
  * @return the JSR 175 annotations that annotate this type.
  */
-public IAnnotationInstance[] getAnnotations()
-{
+public IAnnotationInstance[] getAnnotations() {
 	return TypeConstants.NoAnnotations;
 }
-
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index 00a7468..8c10a6b 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -40,10 +40,7 @@
 	public final static int AUTOBOX_COMPATIBLE = 1;
 	public final static int VARARGS_COMPATIBLE = 2;
 
-	public int kind;
-	public Scope parent;
-
-   /* Answer an int describing the relationship between the given types.
+	/* Answer an int describing the relationship between the given types.
 	*
 	* 		NotRelated 
 	* 		EqualOrMoreSpecific : left is compatible with right
@@ -56,7 +53,6 @@
 			return MoreGeneric;
 		return NotRelated;
 	}
-	
 	public static TypeBinding getBaseType(char[] name) {
 		// list should be optimized (with most often used first)
 		int length = name.length;
@@ -118,6 +114,76 @@
 		}
 		return null;
 	}
+
+   // 5.1.10
+	public static ReferenceBinding[] greaterLowerBound(ReferenceBinding[] types) {
+		if (types == null) return null;
+		int length = types.length;
+		if (length == 0) return null;
+		ReferenceBinding[] result = types;
+		int removed = 0;
+		for (int i = 0; i < length; i++) {
+			ReferenceBinding iType = result[i];
+			if (iType == null) continue;
+			for (int j = 0; j < length; j++) {
+				if (i == j) continue;
+				ReferenceBinding jType = result[j];
+				if (jType == null) continue;
+				if (iType.isCompatibleWith(jType)) { // if Vi <: Vj, Vj is removed
+					if (result == types) { // defensive copy
+						System.arraycopy(result, 0, result = new ReferenceBinding[length], 0, length);
+					}
+					result[j] = null;
+					removed ++;
+				}
+			}
+		}
+		if (removed == 0) return result;
+		if (length == removed) return null;
+		ReferenceBinding[] trimmedResult = new ReferenceBinding[length - removed];
+		for (int i = 0, index = 0; i < length; i++) {
+			ReferenceBinding iType = result[i];
+			if (iType != null) {
+				trimmedResult[index++] = iType;
+			}
+		}
+		return trimmedResult;
+	}
+	
+	// 5.1.10
+	public static TypeBinding[] greaterLowerBound(TypeBinding[] types) {
+		if (types == null) return null;
+		int length = types.length;
+		if (length == 0) return null;
+		TypeBinding[] result = types;
+		int removed = 0;
+		for (int i = 0; i < length; i++) {
+			TypeBinding iType = result[i];
+			if (iType == null) continue;
+			for (int j = 0; j < length; j++) {
+				if (i == j) continue;
+				TypeBinding jType = result[j];
+				if (jType == null) continue;
+				if (iType.isCompatibleWith(jType)) { // if Vi <: Vj, Vj is removed
+					if (result == types) { // defensive copy
+						System.arraycopy(result, 0, result = new TypeBinding[length], 0, length);
+					}
+					result[j] = null;
+					removed ++;
+				}
+			}
+		}
+		if (removed == 0) return result;
+		if (length == removed) return null;
+		TypeBinding[] trimmedResult = new TypeBinding[length - removed];
+		for (int i = 0, index = 0; i < length; i++) {
+			TypeBinding iType = result[i];
+			if (iType != null) {
+				trimmedResult[index++] = iType;
+			}
+		}
+		return trimmedResult;
+	}
 	
 	/**
 	 * Returns an array of types, where original types got substituted given a substitution.
@@ -175,18 +241,18 @@
 					substitutedArguments = substitute(substitution, originalArguments);
 				}
 				if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
-					identicalVariables: { // if substituted with original variables, then answer the generic type itself
-						if (substitutedEnclosing != null) {
-							//if (!(substitutedEnclosing instanceof SourceTypeBinding)) break identicalVariables;
-							if (substitutedEnclosing != originalEnclosing) break identicalVariables;						
-						}
-						if (originalParameterizedType.type.isBinaryBinding()) break identicalVariables; // generic binary is never used as is, see 85262
-						TypeVariableBinding[] originalVariables = originalParameterizedType.type.typeVariables();
-						for (int i = 0, length = originalVariables.length; i < length; i++) {
-							if (substitutedArguments[i] != originalVariables[i]) break identicalVariables;
-						}
-						return originalParameterizedType.type;
-					}
+//					identicalVariables: { // if substituted with original variables, then answer the generic type itself
+//						if (substitutedEnclosing != null) {
+//							//if (!(substitutedEnclosing instanceof SourceTypeBinding)) break identicalVariables;
+//							if (substitutedEnclosing != originalEnclosing) break identicalVariables;						
+//						}
+//						if (originalParameterizedType.type.isBinaryBinding()) break identicalVariables; // generic binary is never used as is, see 85262
+//						TypeVariableBinding[] originalVariables = originalParameterizedType.type.typeVariables();
+//						for (int i = 0, length = originalVariables.length; i < length; i++) {
+//							if (substitutedArguments[i] != originalVariables[i]) break identicalVariables;
+//						}
+//						return originalParameterizedType.type;
+//					}
 					return originalParameterizedType.environment.createParameterizedType(
 							originalParameterizedType.type, substitutedArguments, substitutedEnclosing);
 				}
@@ -244,10 +310,10 @@
 			    // treat as if parameterized with its type variables (non generic type gets 'null' arguments)
 				originalArguments = originalReferenceType.typeVariables();
 				substitutedArguments = substitute(substitution, originalArguments);
-				if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
-					return substitution.environment().createParameterizedType(originalReferenceType, substitutedArguments, substitutedEnclosing);
-				}
-				break;
+//				if (substitutedArguments != originalArguments || substitutedEnclosing != originalEnclosing) {
+				return substitution.environment().createParameterizedType(originalReferenceType, substitutedArguments, substitutedEnclosing);
+//				}
+//				break;
 		}
 		return originalType;
 	}	
@@ -274,10 +340,14 @@
 	    return substitutedTypes;
 	}
 
+	public int kind;
+
+	public Scope parent;	
+
 	protected Scope(int kind, Scope parent) {
 		this.kind = kind;
 		this.parent = parent;
-	}
+	}	
 
 	/*
 	 * Boxing primitive
@@ -286,7 +356,7 @@
 		if (type.isBaseType())
 			return environment().computeBoxingType(type);
 		return type;
-	}	
+	}
 
 	public final ClassScope classScope() {
 		Scope scope = this;
@@ -296,8 +366,8 @@
 			scope = scope.parent;
 		} while (scope != null);
 		return null;
-	}	
-
+	}
+	
 	public final CompilationUnitScope compilationUnitScope() {
 		Scope lastScope = null;
 		Scope scope = this;
@@ -307,7 +377,7 @@
 		} while (scope != null);
 		return (CompilationUnitScope) lastScope;
 	}
-
+	
 	/**
 	 * Finds the most specific compiler options
 	 */
@@ -315,7 +385,7 @@
 
 		return compilationUnitScope().environment.globalOptions;
 	}
-	
+
 	/**
 	 * Internal use only
 	 * Given a method, returns null if arguments cannot be converted to parameters.
@@ -519,7 +589,7 @@
 		// do not cache obvious invalid types
 		return new ArrayBinding(type, dimension, environment());
 	}
-	
+
 	public TypeVariableBinding[] createTypeVariables(TypeParameter[] typeParameters, Binding declaringElement) {
 		// do not construct type variables if source < 1.5
 		if (typeParameters == null || compilerOptions().sourceLevel < ClassFileConstants.JDK1_5)
@@ -573,7 +643,7 @@
 		}
 		return null; // may answer null if no type around
 	}
-
+	
 	public final MethodScope enclosingMethodScope() {
 		Scope scope = this;
 		while ((scope = scope.parent) != null) {
@@ -582,6 +652,18 @@
 		return null; // may answer null if no method around
 	}
 
+	/* Answer the scope receiver type (could be parameterized)
+	*/
+	public final ReferenceBinding enclosingReceiverType() {
+		Scope scope = this;
+		do {
+			if (scope instanceof ClassScope) {
+				return environment().convertToParameterizedType(((ClassScope) scope).referenceContext.binding);
+			}
+			scope = scope.parent;
+		} while (scope != null);
+		return null;
+	}
 	/**
 	 * Returns the immediately enclosing reference context, starting from current scope parent.
 	 * If starting on a class, it will skip current class. If starting on unitScope, returns null.
@@ -600,8 +682,8 @@
 		}
 		return null;
 	}
-	
-	/* Answer the receiver's enclosing source type.
+
+	/* Answer the scope enclosing source type (could be generic)
 	*/
 	public final SourceTypeBinding enclosingSourceType() {
 		Scope scope = this;
@@ -612,6 +694,7 @@
 		} while (scope != null);
 		return null;
 	}
+
 	public final LookupEnvironment environment() {
 		Scope scope, unitScope = this;
 		while ((scope = unitScope.parent) != null)
@@ -691,15 +774,15 @@
 		if ((enclosingType.tagBits & TagBits.HasNoMemberTypes) != 0)
 			return null; // know it has no member types (nor inherited member types)
 
-		SourceTypeBinding enclosingSourceType = enclosingSourceType();
+		ReferenceBinding enclosingReceiverType = enclosingReceiverType();
 		CompilationUnitScope unitScope = compilationUnitScope();
 		unitScope.recordReference(enclosingType, typeName);
 		ReferenceBinding memberType = enclosingType.getMemberType(typeName);
 		if (memberType != null) {
 			unitScope.recordTypeReference(memberType);
-			if (enclosingSourceType == null
+			if (enclosingReceiverType == null
 				? memberType.canBeSeenBy(getCurrentPackage())
-				: memberType.canBeSeenBy(enclosingType, enclosingSourceType))
+				: memberType.canBeSeenBy(enclosingType, enclosingReceiverType))
 					return memberType;
 			return new ProblemReferenceBinding(typeName, memberType, ProblemReasons.NotVisible);
 		}
@@ -877,13 +960,13 @@
 			return new ProblemFieldBinding(notVisibleField, currentType, fieldName, ProblemReasons.NotVisible);
 		return null;
 	}
-
+	
 	// Internal use only
 	public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) {
 		if ((enclosingType.tagBits & TagBits.HasNoMemberTypes) != 0)
 			return null; // know it has no member types (nor inherited member types)
 
-		SourceTypeBinding enclosingSourceType = enclosingSourceType();
+		ReferenceBinding enclosingSourceType = enclosingSourceType();
 		PackageBinding currentPackage = getCurrentPackage();
 		CompilationUnitScope unitScope = compilationUnitScope();
 		unitScope.recordReference(enclosingType, typeName);
@@ -1161,7 +1244,6 @@
 			// and foo(X, Y), when the argument types are (int, float, Y)
 			// so answer the method with the most argType matches and least parameter type mismatches
 			int bestArgMatches = -1;
-			int bestParamMatches = -1;
 			MethodBinding bestGuess = (MethodBinding) found.elementAt(0); // if no good match so just use the first one found
 			int argLength = argumentTypes.length;
 			foundSize = found.size;
@@ -1179,19 +1261,9 @@
 						}
 					}
 				}
-				int paramMatches = 0;
-				next: for (int p = 0; p < paramLength; p++) {
-					TypeBinding param = params[p];
-					for (int a = p == 0 ? 0 : p - 1; a < argLength && a < p + 1; a++) { // look one slot before & after to see if the type matches
-						if (param == argumentTypes[a]) {
-							paramMatches++;
-							continue next;
-						}
-					}
-				}
-				if (argMatches + paramMatches < bestArgMatches + bestParamMatches)
+				if (argMatches < bestArgMatches)
 					continue nextMethod;
-				if (argMatches + paramMatches == bestArgMatches + bestParamMatches) {
+				if (argMatches == bestArgMatches) {
 					int diff1 = paramLength < argLength ? 2 * (argLength - paramLength) : paramLength - argLength;
 					int bestLength = bestGuess.parameters.length;
 					int diff2 = bestLength < argLength ? 2 * (argLength - bestLength) : bestLength - argLength;
@@ -1199,7 +1271,6 @@
 						continue nextMethod;
 				}
 				bestArgMatches = argMatches;
-				bestParamMatches = paramMatches;
 				bestGuess = methodBinding;
 			}
 			return bestGuess;
@@ -1255,7 +1326,7 @@
 			? mostSpecificClassMethodBinding(candidates, visiblesCount, invocationSite)
 			: mostSpecificInterfaceMethodBinding(candidates, visiblesCount, invocationSite);
 	}
-	
+
 	// Internal use only
 	public MethodBinding findMethodForArray(
 		ArrayBinding receiverType,
@@ -1461,9 +1532,9 @@
 							break;
 						case CLASS_SCOPE :
 							ClassScope classScope = (ClassScope) scope;
-							SourceTypeBinding enclosingType = classScope.referenceContext.binding;
+							ReferenceBinding receiverType = classScope.enclosingReceiverType();
 							if (!insideTypeAnnotation) {
-								FieldBinding fieldBinding = classScope.findField(enclosingType, name, invocationSite, needResolve);
+								FieldBinding fieldBinding = classScope.findField(receiverType, name, invocationSite, needResolve);
 								// Use next line instead if willing to enable protected access accross inner types
 								// FieldBinding fieldBinding = findField(enclosingType, name, invocationSite);
 								
@@ -1499,13 +1570,13 @@
 														ProblemReasons.NonStaticReferenceInStaticContext);
 											}
 										}
-										if (enclosingType == fieldBinding.declaringClass || compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) {
+										if (receiverType == fieldBinding.declaringClass || compilerOptions().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);
+													invocationSite.setActualReceiverType(receiverType);
 												}
 												// return the fieldBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
 												return insideProblem == null ? fieldBinding : insideProblem;
@@ -1525,7 +1596,7 @@
 									if (foundField == null || (foundField.problemId() == ProblemReasons.NotVisible && fieldBinding.problemId() != ProblemReasons.NotVisible)) {
 										// only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is...
 										foundDepth = depth;
-										foundActualReceiverType = enclosingType;
+										foundActualReceiverType = receiverType;
 										foundInsideProblem = insideProblem;
 										foundField = fieldBinding;
 									}
@@ -1533,7 +1604,7 @@
 							}
 							insideTypeAnnotation = false;
 							depth++;
-							insideStaticContext |= enclosingType.isStatic();
+							insideStaticContext |= receiverType.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.
@@ -1631,6 +1702,8 @@
 					return binding;
 			}
 			if (problemField != null) return problemField;
+			if (binding != null && binding.problemId() != ProblemReasons.NotFound)
+				return binding; // answer the better problem binding
 			return new ProblemBinding(name, enclosingSourceType(), ProblemReasons.NotFound);
 		} catch (AbortCompilation e) {
 			e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
@@ -1752,7 +1825,7 @@
 			throw e;
 		}			
 	}
-
+	
 	/* API
 	 *	
 	 *	Answer the method binding that corresponds to selector, argumentTypes.
@@ -1788,7 +1861,7 @@
 					break;
 				case CLASS_SCOPE :
 					ClassScope classScope = (ClassScope) scope;
-					SourceTypeBinding receiverType = classScope.referenceContext.binding;
+					ReferenceBinding receiverType = classScope.enclosingReceiverType();
 					if (!insideTypeAnnotation) {
 						boolean isExactMatch = true;
 						// retrieve an exact visible match (if possible)
@@ -1822,11 +1895,21 @@
 								if (!isExactMatch) {
 									MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes, invocationSite);
 									if (compatibleMethod == null) {
-										if (foundMethod == null || foundMethod.problemId() == ProblemReasons.NotVisible)
+										// likely not a match in the first place, 2 cases are possible
+										// first is when methodBinding was found thru inheritance starting from an nested type - in this case do not want to search outer scope
+										// second is when normal search turned up only this selector match so NotFound is expected
+										// except in 1.5 when static import methods can match correctly
+										if (foundMethod == null || foundMethod.problemId() == ProblemReasons.NotVisible) {
+											if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 && !receiverType.isNestedType()) {
+												foundFuzzyProblem = new ProblemMethodBinding(methodBinding, selector, argumentTypes, ProblemReasons.NotFound);
+												break; // need to search for static import method matches
+											}
 											// inherited mismatch is reported directly, not looking at enclosing matches
 											return new ProblemMethodBinding(methodBinding, selector, argumentTypes, ProblemReasons.NotFound);
-										// make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
-										fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, ProblemReasons.InheritedNameHidesEnclosingName);
+										} else {
+											// make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
+											fuzzyProblem = new ProblemMethodBinding(methodBinding, selector, methodBinding.parameters, ProblemReasons.InheritedNameHidesEnclosingName);
+										}
 									} else if (!compatibleMethod.isValidBinding()) {
 										fuzzyProblem = compatibleMethod;
 									} else {
@@ -1915,13 +1998,6 @@
 			scope = scope.parent;
 		}
 
-		if (foundFuzzyProblem != null)
-			return foundFuzzyProblem;
-		if (foundInsideProblem != null)
-			return foundInsideProblem;
-		if (foundMethod != null)
-			return foundMethod;
-
 		if (insideStaticContext && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
 			// at this point the scope is a compilation unit scope & need to check for imported static methods
 			CompilationUnitScope unitScope = (CompilationUnitScope) scope;
@@ -2006,9 +2082,17 @@
 				return foundMethod;
 			}
 		}
+
+		if (foundFuzzyProblem != null)
+			return foundFuzzyProblem;
+		if (foundInsideProblem != null)
+			return foundInsideProblem;
+		if (foundMethod != null)
+			return foundMethod;
+
 		return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
 	}
-
+	
 	public final ReferenceBinding getJavaIoSerializable() {
 		compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
 		ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
@@ -2017,7 +2101,7 @@
 		problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, referenceCompilationUnit());
 		return null; // will not get here since the above error aborts the compilation
 	}
-	
+
 	public final ReferenceBinding getJavaLangAnnotationAnnotation() {
 		compilationUnitScope().recordQualifiedReference(JAVA_LANG_ANNOTATION_ANNOTATION);
 		ReferenceBinding type = environment().getType(JAVA_LANG_ANNOTATION_ANNOTATION);
@@ -2026,7 +2110,7 @@
 		problemReporter().isClassPathCorrect(JAVA_LANG_ANNOTATION_ANNOTATION, referenceCompilationUnit());
 		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);
@@ -2034,7 +2118,6 @@
 		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);
@@ -2069,6 +2152,7 @@
 		problemReporter().isClassPathCorrect(JAVA_LANG_ITERABLE, 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);
@@ -2077,7 +2161,6 @@
 		problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
 		return null; // will not get here since the above error aborts the compilation
 	}
-
 	public final ReferenceBinding getJavaLangString() {
 		compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
 		ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
@@ -2095,6 +2178,7 @@
 		problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, referenceCompilationUnit());
 		return null; // will not get here since the above error aborts the compilation
 	}
+
 	public final ReferenceBinding getJavaUtilIterator() {
 		compilationUnitScope().recordQualifiedReference(JAVA_UTIL_ITERATOR);
 		ReferenceBinding type = environment().getType(JAVA_UTIL_ITERATOR);
@@ -2317,7 +2401,7 @@
 		}
 		return typeBinding;
 	}
-
+	
 	/* Internal use only 
 	*/
 	final Binding getTypeOrPackage(char[] name, int mask) {
@@ -2539,7 +2623,7 @@
 		}
 		return foundType;
 	}
-
+	
 	// Added for code assist... NOT Public API
 	// DO NOT USE to resolve import references since this method assumes 'A.B' is relative to a single type import of 'p1.A'
 	// when it may actually mean the type B in the package A
@@ -2606,76 +2690,6 @@
 			}
 		}
 		return qualifiedType;
-	}
-	
-	// 5.1.10
-	public static TypeBinding[] greaterLowerBound(TypeBinding[] types) {
-		if (types == null) return null;
-		int length = types.length;
-		if (length == 0) return null;
-		TypeBinding[] result = types;
-		int removed = 0;
-		for (int i = 0; i < length; i++) {
-			TypeBinding iType = result[i];
-			if (iType == null) continue;
-			for (int j = 0; j < length; j++) {
-				if (i == j) continue;
-				TypeBinding jType = result[j];
-				if (jType == null) continue;
-				if (iType.isCompatibleWith(jType)) { // if Vi <: Vj, Vj is removed
-					if (result == types) { // defensive copy
-						System.arraycopy(result, 0, result = new TypeBinding[length], 0, length);
-					}
-					result[j] = null;
-					removed ++;
-				}
-			}
-		}
-		if (removed == 0) return result;
-		if (length == removed) return null;
-		TypeBinding[] trimmedResult = new TypeBinding[length - removed];
-		for (int i = 0, index = 0; i < length; i++) {
-			TypeBinding iType = result[i];
-			if (iType != null) {
-				trimmedResult[index++] = iType;
-			}
-		}
-		return trimmedResult;
-	}
-	
-	// 5.1.10
-	public static ReferenceBinding[] greaterLowerBound(ReferenceBinding[] types) {
-		if (types == null) return null;
-		int length = types.length;
-		if (length == 0) return null;
-		ReferenceBinding[] result = types;
-		int removed = 0;
-		for (int i = 0; i < length; i++) {
-			ReferenceBinding iType = result[i];
-			if (iType == null) continue;
-			for (int j = 0; j < length; j++) {
-				if (i == j) continue;
-				ReferenceBinding jType = result[j];
-				if (jType == null) continue;
-				if (iType.isCompatibleWith(jType)) { // if Vi <: Vj, Vj is removed
-					if (result == types) { // defensive copy
-						System.arraycopy(result, 0, result = new ReferenceBinding[length], 0, length);
-					}
-					result[j] = null;
-					removed ++;
-				}
-			}
-		}
-		if (removed == 0) return result;
-		if (length == removed) return null;
-		ReferenceBinding[] trimmedResult = new ReferenceBinding[length - removed];
-		for (int i = 0, index = 0; i < length; i++) {
-			ReferenceBinding iType = result[i];
-			if (iType != null) {
-				trimmedResult[index++] = iType;
-			}
-		}
-		return trimmedResult;
 	}	
 
 	/**
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 5dfb632..88f3f37 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -13,7 +13,6 @@
 import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.Iterator;
-import java.util.Map;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
@@ -511,69 +510,6 @@
 	}
 	return accessMethod;
 }
-/**
- * Collect the substitutes into a map for certain type variables inside the receiver type
- * e.g.   Collection<T>.collectSubstitutes(Collection<List<X>>, Map), will populate Map with: T --> List<X>
- * Constraints:
- *   A << F   corresponds to:   F.collectSubstitutes(..., A, ..., 1)
- *   A = F   corresponds to:      F.collectSubstitutes(..., A, ..., 0)
- *   A >> F   corresponds to:   F.collectSubstitutes(..., A, ..., 2)
- */
-public void collectSubstitutes(Scope currentScope, TypeBinding actualType, Map substitutes, int constraint) {
-	
-	if (actualType == NullBinding) return;
-	if (!(actualType instanceof ReferenceBinding)) return;
-	TypeVariableBinding[] variables = this.typeVariables;
-	if (variables == NoTypeVariables) return;
-	// generic type is acting as parameterized type with its own parameters as arguments
-	
-	ReferenceBinding formalEquivalent, actualEquivalent;
-	switch (constraint) {
-		case CONSTRAINT_EQUAL :
-		case CONSTRAINT_EXTENDS :
-			formalEquivalent = this;
-	        actualEquivalent = ((ReferenceBinding)actualType).findSuperTypeWithSameErasure(this);
-	        if (actualEquivalent == null) return;
-	        break;
-		case CONSTRAINT_SUPER :
-        default:
-	        formalEquivalent = this.findSuperTypeWithSameErasure(actualType);
-	        if (formalEquivalent == null) return;
-	        actualEquivalent = (ReferenceBinding) actualType;
-	        break;
-	}
-    TypeBinding[] formalArguments;
-    switch (formalEquivalent.kind()) {
-    	case Binding.GENERIC_TYPE :
-    		formalArguments = formalEquivalent.typeVariables();
-    		break;
-    	case Binding.PARAMETERIZED_TYPE :
-    		formalArguments = ((ParameterizedTypeBinding)formalEquivalent).arguments;
-    		break;
-    	case Binding.RAW_TYPE :
-    		substitutes.clear(); // clear all variables to indicate raw generic method in the end
-    	default :
-    		return;
-    }
-    TypeBinding[] actualArguments;
-    switch (actualEquivalent.kind()) {
-    	case Binding.GENERIC_TYPE :
-    		actualArguments = actualEquivalent.typeVariables();
-    		break;
-    	case Binding.PARAMETERIZED_TYPE :
-    		actualArguments = ((ParameterizedTypeBinding)actualEquivalent).arguments;
-    		break;
-    	case Binding.RAW_TYPE :
-    		substitutes.clear(); // clear all variables to indicate raw generic method in the end
-    		return;
-    	default :
-    		return;
-    }
-    for (int i = 0, length = formalArguments.length; i < length; i++) {
-    	TypeBinding formalArgument = formalArguments[i];
-        formalArgument.collectSubstitutes(scope, actualArguments[i], substitutes, formalArgument.isWildcard() ? constraint : CONSTRAINT_EQUAL);
-    }
-}
 public int kind() {
 	if (this.typeVariables != NoTypeVariables) return Binding.GENERIC_TYPE;
 	return Binding.TYPE;
@@ -616,8 +552,6 @@
 	// check @Deprecated annotation
 	if ((this.getAnnotationTagBits() & AnnotationDeprecated) != 0) {
 		this.modifiers |= ClassFileConstants.AccDeprecated;
-	} else if ((this.modifiers & ClassFileConstants.AccDeprecated) != 0 && scope != null && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
-		scope.problemReporter().missingDeprecatedAnnotationForType(scope.referenceContext);
 	}
 	ReferenceBinding enclosingType = this.enclosingType();
 	if (enclosingType != null && enclosingType.isViewedAsDeprecated() && !this.isDeprecated())
@@ -696,13 +630,6 @@
         sig.append(this.superInterfaces[i].genericTypeSignature());
 	return sig.toString().toCharArray();
 }
-
-public IAnnotationInstance[] getAnnotations()
-{
-	getAnnotationTagBits();
-	return this.annotations;
-}
-
 /**
  * Compute the tagbits for standard annotations. For source types, these could require
  * lazily resolving corresponding annotation nodes, in case of forward references.
@@ -1156,8 +1083,6 @@
 	if (this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
 		if ((field.getAnnotationTagBits() & AnnotationDeprecated) != 0)
 			field.modifiers |= ClassFileConstants.AccDeprecated;
-		else if ((field.modifiers & ClassFileConstants.AccDeprecated) != 0)
-			this.scope.problemReporter().missingDeprecatedAnnotationForField(field.sourceField());
 	}
 	if (isViewedAsDeprecated() && !field.isDeprecated())
 		field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;	
@@ -1211,8 +1136,6 @@
 	if (this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
 		if ((method.getAnnotationTagBits() & AnnotationDeprecated) != 0)
 			method.modifiers |= ClassFileConstants.AccDeprecated;
-		else if ((method.modifiers & ClassFileConstants.AccDeprecated) != 0)
-			this.scope.problemReporter().missingDeprecatedAnnotationForMethod(method.sourceMethod());
 	}
 	if (isViewedAsDeprecated() && !method.isDeprecated())
 		method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
@@ -1238,7 +1161,7 @@
 			resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].resolveType(methodDecl.scope, true /* check bounds*/);
 			if (resolvedExceptionType == null)
 				continue;
-			if (resolvedExceptionType.isGenericType() || resolvedExceptionType.isBoundParameterizedType()) {
+			if (resolvedExceptionType.isBoundParameterizedType()) {
 				methodDecl.scope.problemReporter().invalidParameterizedExceptionType(resolvedExceptionType, exceptionTypes[i]);
 				continue;
 			}
@@ -1508,4 +1431,9 @@
 	for (int i = memberTypes.length; --i >= 0;)
 		 ((SourceTypeBinding) memberTypes[i]).verifyMethods(verifier);
 }
+
+public IAnnotationInstance[] getAnnotations() {
+	getAnnotationTagBits();
+	return this.annotations;
+}
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
index e374bb4..f2cb553 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
@@ -244,6 +244,26 @@
 }
 
 /**
+ * Returns true if the type is parameterized using its own type variables as arguments
+ */
+public boolean isParameterizedWithOwnVariables() {
+	if (this.kind() != Binding.PARAMETERIZED_TYPE) return false;
+	ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) this;
+	if (paramType.arguments == null) return false;
+	TypeVariableBinding[] variables = this.erasure().typeVariables();
+	for (int i = 0, length = variables.length; i < length; i++) {
+		if (variables[i] != paramType.arguments[i]) return false;
+	}
+	ReferenceBinding enclosing = paramType.enclosingType();
+	if (enclosing != null 
+			&& enclosing.erasure().isGenericType()
+			&& !enclosing.isParameterizedWithOwnVariables()) {
+		return false;
+	}
+	return true;
+}
+
+/**
  * Returns true if the two types are statically known to be different at compile-time,
  * e.g. a type variable is not provably known to be distinct from another type
  */
@@ -615,7 +635,6 @@
 		return false;
 
 	while (compatible.isRawType()) {
-		if (targetType.isGenericType()) return true;
 		if (targetType.isBoundParameterizedType()) return true;
 
 		if (compatible.isStatic()) break;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
index 857eefc..c2802ab 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
@@ -130,7 +130,7 @@
 					TypeBinding match = referenceArgument.findSuperTypeWithSameErasure(substitutedSuperType);
 					if (match != null){
 						// Enum#RAW is not a substitute for <E extends Enum<E>> (86838)
-						if (match.isRawType() && (substitutedSuperType.isGenericType()||substitutedSuperType.isBoundParameterizedType()))
+						if (match.isRawType() && substitutedSuperType.isBoundParameterizedType())
 							unchecked = true;
 					}
 				} 
@@ -148,7 +148,7 @@
 					TypeBinding match = referenceArgument.findSuperTypeWithSameErasure(substitutedSuperType);
 					if (match != null){
 						// Enum#RAW is not a substitute for <E extends Enum<E>> (86838)
-						if (match.isRawType() && (substitutedSuperType.isGenericType()||substitutedSuperType.isBoundParameterizedType()))
+						if (match.isRawType() && substitutedSuperType.isBoundParameterizedType())
 							unchecked = true;
 					}
 				}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
index c8af66a..083ecd7 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
@@ -18,7 +18,7 @@
 	public int modifiers;
 	public TypeBinding type;
 	public char[] name;
-	private Constant constant;
+	protected Constant constant;
 	public int id; // for flow-analysis (position in flowInfo bit vector)
 	public long tagBits;
 	public IAnnotationInstance[] annotations;
@@ -40,10 +40,6 @@
 	/* Answer true if the receiver is final and cannot be changed
 	*/
 	
-	public boolean isConstantValue() {
-		return constant != Constant.NotAConstant;
-	}
-	
 	public final boolean isFinal() {
 		return (modifiers & ClassFileConstants.AccFinal) != 0;
 	}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java b/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
index a077af2..cceeeef 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
@@ -28,6 +28,9 @@
 	public final static int SELECTION_PARSER = 3;
 	public final static int COMPLETION_PARSER = 4;
 	public final static int SOURCE_PARSER = 5;
+	protected final static int PARSER_KIND = 0x00FF;
+	protected final static int TEXT_PARSE = 0x0100; // flag saying that text must be stored
+	protected final static int TEXT_VERIF = 0x0200; // flag saying that text must be verified
 	
 	// Parser recovery states
 	protected final static int QUALIFIED_NAME_RECOVERY = 1;
@@ -141,6 +144,9 @@
 			char previousChar = 0;
 			int invalidTagLineEnd = -1;
 			int invalidInlineTagLineEnd = -1;
+			boolean pushText = (this.kind & TEXT_PARSE) != 0;
+			boolean verifText = (this.kind & TEXT_VERIF) != 0;
+			boolean isDomParser = (this.kind & DOM_PARSER) != 0;
 			
 			// Loop on each comment character
 			while (!abort && this.index < this.javadocEnd) {
@@ -188,18 +194,18 @@
 								}
 								validComment = false;
 								if (this.textStart != -1 && this.textStart < previousPosition) {
-									if (this.kind != COMPIL_PARSER) pushText(this.textStart, previousPosition);
+									if (pushText) pushText(this.textStart, previousPosition);
 								}
-								if (this.kind == DOM_PARSER) refreshInlineTagPosition(previousPosition);
+								if (isDomParser) refreshInlineTagPosition(previousPosition);
 							}
 							if (previousChar == '{') {
 								if (this.textStart != -1 && this.textStart < this.inlineTagStart) {
-									if (this.kind != COMPIL_PARSER) pushText(this.textStart, this.inlineTagStart);
+									if (pushText) pushText(this.textStart, this.inlineTagStart);
 								}
 								this.inlineTagStarted = true;
 								invalidInlineTagLineEnd = this.lineEnd;
 							} else if (this.textStart != -1 && this.textStart < invalidTagLineEnd) {
-								if (this.kind != COMPIL_PARSER) pushText(this.textStart, invalidTagLineEnd);
+								if (pushText) pushText(this.textStart, invalidTagLineEnd);
 							}
 							this.scanner.resetTo(this.index, this.javadocEnd);
 							this.currentTokenType = -1; // flush token cache at line begin
@@ -210,7 +216,7 @@
 									validComment = false;
 									// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600
 									// for DOM AST node, store tag as text in case of invalid syntax
-									if (this.kind == DOM_PARSER) {
+									if (isDomParser) {
 										createTag();
 										this.textStart = this.tagSourceEnd+1;
 										invalidTagLineEnd  = this.lineEnd;
@@ -219,28 +225,26 @@
 							} catch (InvalidInputException e) {
 								consumeToken();
 							}
-						} else {
-							if (this.kind == COMPIL_PARSER && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) {
-								refreshReturnStatement();
-							}
+						} else if (verifText && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) {
+							refreshReturnStatement();
 						}
 						this.lineStarted = true;
 						break;
 					case '\r':
 					case '\n':
 						if (this.lineStarted && this.textStart < previousPosition) {
-							if (this.kind != COMPIL_PARSER) pushText(this.textStart, previousPosition);
+							if (pushText) pushText(this.textStart, previousPosition);
 						}
 						this.lineStarted = false;
 						// Fix bug 51650
 						this.textStart = -1;
 						break;
 					case '}' :
-						if (this.kind == COMPIL_PARSER && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) {
+						if (verifText && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) {
 							refreshReturnStatement();
 						}
 						if (this.inlineTagStarted) {
-							if (this.kind != COMPIL_PARSER) {
+							if (pushText) {
 								if (this.lineStarted && this.textStart != -1 && this.textStart < previousPosition) {
 								pushText(this.textStart, previousPosition);
 								}
@@ -256,7 +260,7 @@
 						this.lineStarted = true;
 						break;
 					case '{' :
-						if (this.kind == COMPIL_PARSER && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) {
+						if (verifText && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) {
 							refreshReturnStatement();
 						}
 						if (this.inlineTagStarted) {
@@ -267,7 +271,7 @@
 								int end = previousPosition<invalidInlineTagLineEnd ? previousPosition : invalidInlineTagLineEnd;
 								this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end);
 							}
-							if (this.kind != COMPIL_PARSER) {
+							if (pushText) {
 								if (this.lineStarted && this.textStart != -1 && this.textStart < previousPosition) {
 									pushText(this.textStart, previousPosition);
 								}
@@ -287,7 +291,7 @@
 						// do nothing for space or '*' characters
 						break;
 					default :
-						if (this.kind == COMPIL_PARSER && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) {
+						if (verifText && this.tagValue == TAG_RETURN_VALUE && this.returnStatement != null) {
 							refreshReturnStatement();
 						}
 						if (!this.lineStarted) {
@@ -306,13 +310,13 @@
 					if (this.index >= this.javadocEnd) end = invalidInlineTagLineEnd;
 					this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end);
 				}
-				if (this.kind != COMPIL_PARSER) {
+				if (pushText) {
 					if (this.lineStarted && this.textStart != -1 && this.textStart < previousPosition) {
 						pushText(this.textStart, previousPosition);
 					}
 					refreshInlineTagPosition(previousPosition);
 				}
-			} else if (this.kind != COMPIL_PARSER && this.lineStarted && this.textStart < previousPosition) {
+			} else if (pushText && this.lineStarted && this.textStart < previousPosition) {
 				pushText(this.textStart, previousPosition);
 			}
 			updateDocComment();
@@ -686,14 +690,15 @@
 		int end = this.tagSourceEnd;
 		boolean tokenWhiteSpace = this.scanner.tokenizeWhiteSpace;
 		this.scanner.tokenizeWhiteSpace = true;
-//		this.scanner.tokenizeLineSeparator = true;
 		
 		// Verify that there are whitespaces after tag
-		int token = readToken();
-		if (token != TerminalTokens.TokenNameWHITESPACE) {
+		boolean isCompletionParser = (this.kind & COMPLETION_PARSER) != 0;
+		if (this.scanner.currentCharacter != ' ' && !Character.isWhitespace(this.scanner.currentCharacter)) {
 			if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidTag(start, this.scanner.getCurrentTokenEndPosition());
-			if (this.kind != COMPLETION_PARSER) this.scanner.currentPosition = start;
-			this.index = start;
+			if (!isCompletionParser) {
+				this.scanner.currentPosition = start;
+				this.index = start;
+			}
 			this.currentTokenType = -1;
 			this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
 			return false;
@@ -706,6 +711,7 @@
 		boolean isTypeParam = false;
 		boolean valid = true, empty = true;
 		boolean mayBeGeneric = this.sourceLevel >= ClassFileConstants.JDK1_5;
+		int token = -1;
 		nextToken: while (true) {
 			this.currentTokenType = -1;
 			try {
@@ -756,8 +762,10 @@
 							this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end);
 						else
 							this.sourceParser.problemReporter().javadocInvalidParamTagName(start, end);
-					this.scanner.currentPosition = start;
-					this.index = start;
+					if (!isCompletionParser) {
+						this.scanner.currentPosition = start;
+						this.index = start;
+					}
 					this.currentTokenType = -1;
 					this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
 					return false;
@@ -780,8 +788,10 @@
 						// if not valid fall through next case to report error
 					case TerminalTokens.TokenNameEOF:
 						if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end);
-						this.scanner.currentPosition = start;
-						this.index = start;
+						if (!isCompletionParser) {
+							this.scanner.currentPosition = start;
+							this.index = start;
+						}
 						this.currentTokenType = -1;
 						this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
 						return false;
@@ -821,8 +831,10 @@
 						// if not valid fall through next case to report error
 					case TerminalTokens.TokenNameEOF:
 						if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidParamTypeParameter(start, end);
-						this.scanner.currentPosition = start;
-						this.index = start;
+						if (!isCompletionParser) {
+							this.scanner.currentPosition = start;
+							this.index = start;
+						}
 						this.currentTokenType = -1;
 						this.scanner.tokenizeWhiteSpace = tokenWhiteSpace;
 						return false;
@@ -861,7 +873,7 @@
 		
 		// Report problem
 		this.currentTokenType = -1;
-		if (this.kind == COMPLETION_PARSER) return false;
+		if (isCompletionParser) return false;
 		end = hasMultiLines ? this.lineEnd: this.scanner.getCurrentTokenEndPosition();
 		while ((token=readToken()) != TerminalTokens.TokenNameWHITESPACE && token != TerminalTokens.TokenNameEOF) {
 			this.currentTokenType = -1;
@@ -892,6 +904,7 @@
 
 		// Scan tokens
 		int primitiveToken = -1;
+		int parserKind = this.kind & PARSER_KIND;
 		nextToken : for (int iToken = 0; ; iToken++) {
 			int token = readTokenSafely();
 			switch (token) {
@@ -929,12 +942,18 @@
 
 				default :
 					if (iToken == 0) {
+						if (this.identifierPtr>=0) {
+							this.lastIdentifierEndPosition = (int) this.identifierPositionStack[this.identifierPtr];
+						}
 						return null;
 					}
 					if ((iToken % 2) == 0) { // cannot leave on a dot
-						switch (this.kind) {
+						switch (parserKind) {
 							case COMPLETION_PARSER:
-								return syntaxRecoverQualifiedName();
+								if (this.identifierPtr>=0) {
+									this.lastIdentifierEndPosition = (int) this.identifierPositionStack[this.identifierPtr];
+								}
+								return syntaxRecoverQualifiedName(primitiveToken);
 							case DOM_PARSER:
 								if (this.currentTokenType != -1) {
 									// Reset position: we want to rescan last token
@@ -950,12 +969,14 @@
 			}
 		}
 		// Reset position: we want to rescan last token
-		if (this.kind != COMPLETION_PARSER && this.currentTokenType != -1) {
+		if (parserKind != COMPLETION_PARSER && this.currentTokenType != -1) {
 			this.index = this.tokenPreviousPosition;
 			this.scanner.currentPosition = this.tokenPreviousPosition;
 			this.currentTokenType = -1;
 		}
-		this.lastIdentifierEndPosition = (int) this.identifierPositionStack[this.identifierPtr];
+		if (this.identifierPtr>=0) {
+			this.lastIdentifierEndPosition = (int) this.identifierPositionStack[this.identifierPtr];
+		}
 		return createTypeReference(primitiveToken);
 	}
 
@@ -1024,8 +1045,8 @@
 						}
 						return false;
 					case TerminalTokens.TokenNameERROR :
+						consumeToken();
 						if (this.scanner.currentCharacter == '#') { // @see ...#member
-							consumeToken();
 							reference = parseMember(typeRef);
 							if (reference != null) {
 								return pushSeeRef(reference);
@@ -1057,7 +1078,7 @@
 				this.scanner.currentPosition = this.tokenPreviousPosition;
 				this.currentTokenType = -1;
 				if (this.tagValue == TAG_VALUE_VALUE) {
-					if (this.kind == DOM_PARSER) createTag();
+					if ((this.kind & DOM_PARSER) != 0) createTag();
 					return true;
 				}
 				if (this.reportProblems) {
@@ -1067,8 +1088,10 @@
 			}
 
 			// Reset position at the end of type reference
-			this.index = this.lastIdentifierEndPosition+1;
-			this.scanner.currentPosition = this.index;
+			if (this.lastIdentifierEndPosition > this.javadocStart) {
+				this.index = this.lastIdentifierEndPosition+1;
+				this.scanner.currentPosition = this.index;
+			}
 			this.currentTokenType = -1;
 
 			// In case of @value, we have an invalid reference (only static field refs are valid for this tag)
@@ -1326,7 +1349,7 @@
 	/*
 	 * Entry point for recovery on invalid syntax
 	 */
-	protected Object syntaxRecoverQualifiedName() throws InvalidInputException {
+	protected Object syntaxRecoverQualifiedName(int primitiveToken) throws InvalidInputException {
 		// do nothing, just an entry point for recovery
 		return null;
 	}
@@ -1405,12 +1428,13 @@
 	 * Verify that end of the line only contains space characters or end of comment.
 	 * Note that end of comment may be preceeding by several contiguous '*' chars.
 	 */
-	private boolean verifyEndLine(int textPosition) {
+	protected boolean verifyEndLine(int textPosition) {
+		boolean domParser = (this.kind & DOM_PARSER) != 0;
 		// Special case for inline tag
 		if (this.inlineTagStarted) {
 			// expecting closing brace
 			if (peekChar() == '}') {
-				if (this.kind == DOM_PARSER) {
+				if (domParser) {
 					createTag();
 					pushText(textPosition, this.starPosition);
 				}
@@ -1427,7 +1451,7 @@
 			switch (ch) {
 				case '\r':
 				case '\n':
-					if (this.kind == DOM_PARSER) {
+					if (domParser) {
 						createTag();
 						pushText(textPosition, previousPosition);
 					}
@@ -1443,7 +1467,7 @@
 					break;
 				case '/':
 					if (this.starPosition >= textPosition) {
-						if (this.kind == DOM_PARSER) {
+						if (domParser) {
 							createTag();
 							pushText(textPosition, this.starPosition);
 						}
@@ -1468,7 +1492,7 @@
 	 * 	3- are the end of comment (several contiguous star ('*') characters may be
 	 * 	    found before the last slash ('/') character).
 	 */
-	private boolean verifySpaceOrEndComment() {
+	protected boolean verifySpaceOrEndComment() {
 		int startPosition = this.index;
 		// Whitespace or inline tag closing brace
 		char ch = peekChar();
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java b/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
index cec206c..34bc9fb 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
@@ -32,7 +32,7 @@
 
 	public JavadocParser(Parser sourceParser) {
 		super(sourceParser);
-		this.kind = COMPIL_PARSER;
+		this.kind = COMPIL_PARSER | TEXT_VERIF;
 	}
 
 	/* (non-Javadoc)
@@ -57,7 +57,7 @@
 		
 		// If there's no tag in javadoc, return without parsing it
 		if (this.firstTagPosition == 0) {
-			switch (this.kind) {
+			switch (this.kind & PARSER_KIND) {
 				case COMPIL_PARSER:
 				case SOURCE_PARSER:
 					return false;
@@ -362,132 +362,88 @@
 		}
 		this.tagSourceStart = this.scanner.getCurrentTokenStartPosition();
 		this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+		char[] tagName = this.scanner.getCurrentIdentifierSource();
 	
 		// Try to get tag name other than java identifier
 		// (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51660)
-		char pc = peekChar();
-		boolean validTag = false;
-		switch (token) {
-			case TerminalTokens.TokenNameIdentifier:
-			case TerminalTokens.TokenNamereturn:
-			case TerminalTokens.TokenNamethrows:
-			case TerminalTokens.TokenNameabstract:
-			case TerminalTokens.TokenNameassert:
-			case TerminalTokens.TokenNameboolean:
-			case TerminalTokens.TokenNamebreak:
-			case TerminalTokens.TokenNamebyte:
-			case TerminalTokens.TokenNamecase:
-			case TerminalTokens.TokenNamecatch:
-			case TerminalTokens.TokenNamechar:
-			case TerminalTokens.TokenNameclass:
-			case TerminalTokens.TokenNamecontinue:
-			case TerminalTokens.TokenNamedefault:
-			case TerminalTokens.TokenNamedo:
-			case TerminalTokens.TokenNamedouble:
-			case TerminalTokens.TokenNameelse:
-			case TerminalTokens.TokenNameextends:
-			case TerminalTokens.TokenNamefalse:
-			case TerminalTokens.TokenNamefinal:
-			case TerminalTokens.TokenNamefinally:
-			case TerminalTokens.TokenNamefloat:
-			case TerminalTokens.TokenNamefor:
-			case TerminalTokens.TokenNameif:
-			case TerminalTokens.TokenNameimplements:
-			case TerminalTokens.TokenNameimport:
-			case TerminalTokens.TokenNameinstanceof:
-			case TerminalTokens.TokenNameint:
-			case TerminalTokens.TokenNameinterface:
-			case TerminalTokens.TokenNamelong:
-			case TerminalTokens.TokenNamenative:
-			case TerminalTokens.TokenNamenew:
-			case TerminalTokens.TokenNamenull:
-			case TerminalTokens.TokenNamepackage:
-			case TerminalTokens.TokenNameprivate:
-			case TerminalTokens.TokenNameprotected:
-			case TerminalTokens.TokenNamepublic:
-			case TerminalTokens.TokenNameshort:
-			case TerminalTokens.TokenNamestatic:
-			case TerminalTokens.TokenNamestrictfp:
-			case TerminalTokens.TokenNamesuper:
-			case TerminalTokens.TokenNameswitch:
-			case TerminalTokens.TokenNamesynchronized:
-			case TerminalTokens.TokenNamethis:
-			case TerminalTokens.TokenNamethrow:
-			case TerminalTokens.TokenNametransient:
-			case TerminalTokens.TokenNametrue:
-			case TerminalTokens.TokenNametry:
-			case TerminalTokens.TokenNamevoid:
-			case TerminalTokens.TokenNamevolatile:
-			case TerminalTokens.TokenNamewhile:
-				validTag= true;
-		}
-		tagNameToken: while (token != TerminalTokens.TokenNameEOF && this.index < this.scanner.eofPosition) {
-			// !, ", #, %, &, ', -, :, <, >, * chars and spaces are not allowed in tag names
-			switch (pc) {
-				case '}':
-				case '*': // break for '*' as this is perhaps the end of comment (bug 65288)
-					break tagNameToken;
-				case '!':
-				case '#':
-				case '%':
-				case '&':
-				case '\'':
-				case '"':
-				case ':':
-				case '<':
-				case '>':
-					validTag = false;
-					// fall thru next case to read character and resynch scanner
-				case '-': // allowed in tag names as this character is often used in doclets (bug 68087)
-					readChar();
-					this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
-					this.scanner.currentPosition = this.index;
-					break;
-				default:
-					if (pc == ' ' || Character.isWhitespace(pc)) break tagNameToken;
-					token = readTokenAndConsume();
-					this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
-					break;
+		if (this.scanner.currentCharacter != ' ' && !Character.isWhitespace(this.scanner.currentCharacter)) {
+			boolean validTag = true;
+			tagNameToken: while (token != TerminalTokens.TokenNameEOF && this.index < this.scanner.eofPosition) {
+				int length = tagName.length;
+				// !, ", #, %, &, ', -, :, <, >, * chars and spaces are not allowed in tag names
+				switch (this.scanner.currentCharacter) {
+					case '}':
+					case '*': // break for '*' as this is perhaps the end of comment (bug 65288)
+						break tagNameToken;
+					case '!':
+					case '#':
+					case '%':
+					case '&':
+					case '\'':
+					case '"':
+					case ':':
+					case '<':
+					case '>':
+					case '@':
+						validTag = false;
+						this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+						this.index = this.scanner.currentPosition;
+						break;
+					case '-': // allowed in tag names as this character is often used in doclets (bug 68087)
+						System.arraycopy(tagName, 0, tagName = new char[length+1], 0, length);
+						tagName[length] = this.scanner.currentCharacter;
+						this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+						this.index = this.scanner.currentPosition;
+						break;
+					default:
+						if (this.scanner.currentCharacter == ' ' || Character.isWhitespace(this.scanner.currentCharacter)) {
+							break tagNameToken;
+						}
+						token = readTokenAndConsume();
+						char[] ident = this.scanner.getCurrentIdentifierSource();
+						System.arraycopy(tagName, 0, tagName = new char[length+ident.length], 0, length);
+						System.arraycopy(ident, 0, tagName, length, ident.length);
+						this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+						break;
+				}
+				this.scanner.getNextChar();
 			}
-			pc = peekChar();
+			if (!validTag) {
+				if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidTag(this.tagSourceStart, this.tagSourceEnd);
+				return false;
+			}
 		}
-		if (!validTag) {
-			this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
-			if (this.reportProblems) this.sourceParser.problemReporter().javadocInvalidTag(this.tagSourceStart, this.tagSourceEnd);
-			return false;
-		}
-		int length = this.tagSourceEnd-this.tagSourceStart+1;
+		int length = tagName.length;
 		if (length == 0) return false; // may happen for some parser (completion for example)
 		this.index = this.tagSourceEnd+1;
 		this.scanner.currentPosition = this.tagSourceEnd+1;
-
+	
 		// Decide which parse to perform depending on tag name
 		this.tagValue = NO_TAG_VALUE;
-		char firstChar = this.source[this.tagSourceStart];
 		switch (token) {
 			case TerminalTokens.TokenNameIdentifier :
-				switch (firstChar) {
+				switch (tagName[0]) {
 					case 'c':
-						if (length == TAG_CATEGORY_LENGTH && CharOperation.equals(TAG_CATEGORY, this.source, this.tagSourceStart, this.tagSourceEnd+1)) {
+						if (length == TAG_CATEGORY_LENGTH && CharOperation.equals(TAG_CATEGORY, tagName)) {
 							this.tagValue = TAG_CATEGORY_VALUE;
 							valid = parseIdentifierTag(false); // TODO (frederic) reconsider parameter value when @category will be significant in spec
 						}
 						break;
 					case 'd':
-						if (length == TAG_DEPRECATED_LENGTH && CharOperation.equals(TAG_DEPRECATED, this.source, this.tagSourceStart, this.tagSourceEnd+1)) {
+						if (length == TAG_DEPRECATED_LENGTH && CharOperation.equals(TAG_DEPRECATED, tagName)) {
 							this.deprecated = true;
 							valid = true;
 							this.tagValue = TAG_DEPRECATED_VALUE;
 						}
 						break;
 					case 'e':
-						if (length == TAG_EXCEPTION_LENGTH && CharOperation.equals(TAG_EXCEPTION, this.source, this.tagSourceStart, this.tagSourceEnd+1)) {
+						if (length == TAG_EXCEPTION_LENGTH && CharOperation.equals(TAG_EXCEPTION, tagName)) {
 							this.tagValue = TAG_EXCEPTION_VALUE;
 							valid = parseThrows();
 						}
 						break;
 					case 'i':
-						if (length == TAG_INHERITDOC_LENGTH && CharOperation.equals(TAG_INHERITDOC, this.source, this.tagSourceStart, this.tagSourceEnd+1)) {
+						if (length == TAG_INHERITDOC_LENGTH && CharOperation.equals(TAG_INHERITDOC, tagName)) {
 							// inhibits inherited flag when tags have been already stored
 							// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51606
 							// Note that for DOM_PARSER, nodes stack may be not empty even no '@' tag
@@ -501,9 +457,9 @@
 						}
 						break;
 					case 'l':
-						if (length == TAG_LINK_LENGTH && CharOperation.equals(TAG_LINK, this.source, this.tagSourceStart, this.tagSourceEnd+1)) {
+						if (length == TAG_LINK_LENGTH && CharOperation.equals(TAG_LINK, tagName)) {
 							this.tagValue = TAG_LINK_VALUE;
-							if (this.inlineTagStarted || this.kind == COMPLETION_PARSER) {
+							if (this.inlineTagStarted || (this.kind & COMPLETION_PARSER) != 0) {
 								valid= parseReference();
 							} else {
 								// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
@@ -512,7 +468,7 @@
 								if (this.sourceParser != null)
 									this.sourceParser.problemReporter().javadocUnexpectedTag(this.tagSourceStart, this.tagSourceEnd);
 							}
-						} else if (length == TAG_LINKPLAIN_LENGTH && CharOperation.equals(TAG_LINKPLAIN, this.source, this.tagSourceStart, this.tagSourceEnd+1)) {
+						} else if (length == TAG_LINKPLAIN_LENGTH && CharOperation.equals(TAG_LINKPLAIN, tagName)) {
 							this.tagValue = TAG_LINKPLAIN_VALUE;
 							if (this.inlineTagStarted) {
 								valid = parseReference();
@@ -524,13 +480,13 @@
 						}
 						break;
 					case 'p':
-						if (length == TAG_PARAM_LENGTH && CharOperation.equals(TAG_PARAM, this.source, this.tagSourceStart, this.tagSourceEnd+1)) {
+						if (length == TAG_PARAM_LENGTH && CharOperation.equals(TAG_PARAM, tagName)) {
 							this.tagValue = TAG_PARAM_VALUE;
 							valid = parseParam();
 						}
 						break;
 					case 's':
-						if (length == TAG_SEE_LENGTH && this.source[this.tagSourceStart+1] == TAG_SEE[1] &&  this.source[this.tagSourceEnd] == TAG_SEE[2]) {
+						if (length == TAG_SEE_LENGTH && CharOperation.equals(TAG_SEE, tagName)) {
 							if (this.inlineTagStarted) {
 								// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
 								// Cannot have @see inside inline comment
@@ -544,7 +500,7 @@
 						}
 						break;
 					case 'v':
-						if (this.sourceLevel >= ClassFileConstants.JDK1_5 && length == TAG_VALUE_LENGTH && CharOperation.equals(TAG_VALUE, this.source, this.tagSourceStart, this.tagSourceEnd+1)) {
+						if (this.sourceLevel >= ClassFileConstants.JDK1_5 && length == TAG_VALUE_LENGTH && CharOperation.equals(TAG_VALUE, tagName)) {
 							this.tagValue = TAG_VALUE_VALUE;
 							if (this.inlineTagStarted) {
 								valid = parseReference();
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java b/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java
index 75b1253..d761afe 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/JavadocTagConstants.java
@@ -42,16 +42,16 @@
 
 	// tags lengthes
 	public static final int TAG_DEPRECATED_LENGTH = TAG_DEPRECATED.length;
-	public static final int TAG_PARAM_LENGTH = TAG_PARAM.length;;
-	public static final int TAG_RETURN_LENGTH = TAG_RETURN.length;;
-	public static final int TAG_THROWS_LENGTH = TAG_THROWS.length;;
-	public static final int TAG_EXCEPTION_LENGTH = TAG_EXCEPTION.length;;
-	public static final int TAG_SEE_LENGTH = TAG_SEE.length;;
-	public static final int TAG_LINK_LENGTH = TAG_LINK.length;;
-	public static final int TAG_LINKPLAIN_LENGTH = TAG_LINKPLAIN.length;;
-	public static final int TAG_INHERITDOC_LENGTH = TAG_INHERITDOC.length;;
-	public static final int TAG_VALUE_LENGTH = TAG_VALUE.length;;
-	public static final int TAG_CATEGORY_LENGTH = TAG_CATEGORY.length;;
+	public static final int TAG_PARAM_LENGTH = TAG_PARAM.length;
+	public static final int TAG_RETURN_LENGTH = TAG_RETURN.length;
+	public static final int TAG_THROWS_LENGTH = TAG_THROWS.length;
+	public static final int TAG_EXCEPTION_LENGTH = TAG_EXCEPTION.length;
+	public static final int TAG_SEE_LENGTH = TAG_SEE.length;
+	public static final int TAG_LINK_LENGTH = TAG_LINK.length;
+	public static final int TAG_LINKPLAIN_LENGTH = TAG_LINKPLAIN.length;
+	public static final int TAG_INHERITDOC_LENGTH = TAG_INHERITDOC.length;
+	public static final int TAG_VALUE_LENGTH = TAG_VALUE.length;
+	public static final int TAG_CATEGORY_LENGTH = TAG_CATEGORY.length;
 
 
 	// tags value
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index 5cc9cc2..1ca4799 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -1109,6 +1109,14 @@
 		// remove the position of the '@' token as we don't have modifiers
 		annotationTypeDeclaration.declarationSourceStart = atPosition;
 	}
+
+	// Store secondary info
+	if ((annotationTypeDeclaration.bits & ASTNode.IsMemberType) == 0 && (annotationTypeDeclaration.bits & ASTNode.IsLocalType) == 0) {
+		if (this.compilationUnit != null && !CharOperation.equals(annotationTypeDeclaration.name, this.compilationUnit.getMainTypeName())) {
+			annotationTypeDeclaration.bits |= ASTNode.IsSecondaryType;
+		}
+	}
+
 	// consume annotations
 	int length;
 	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
@@ -1873,6 +1881,14 @@
 	if (typeDecl.modifiersSourceStart >= 0) {
 		typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
 	}
+
+	// Store secondary info
+	if ((typeDecl.bits & ASTNode.IsMemberType) == 0 && (typeDecl.bits & ASTNode.IsLocalType) == 0) {
+		if (this.compilationUnit != null && !CharOperation.equals(typeDecl.name, this.compilationUnit.getMainTypeName())) {
+			typeDecl.bits |= ASTNode.IsSecondaryType;
+		}
+	}
+
 	// consume annotations
 	int length;
 	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
@@ -2680,6 +2696,11 @@
 			(AbstractVariableDeclaration) this.astStack[this.astPtr]; 
 		declaration.declarationSourceStart = previousVariable.declarationSourceStart;
 		declaration.modifiers = previousVariable.modifiers;
+		final Annotation[] annotations = previousVariable.annotations;
+		if (annotations != null) {
+			final int annotationsLength = annotations.length;
+			System.arraycopy(annotations, 0, declaration.annotations = new Annotation[annotationsLength], 0, annotationsLength);
+		}
 	}
 
 	if (extendedDimension == 0) {
@@ -2740,7 +2761,15 @@
    enumConstant.modifiersSourceStart = this.intStack[this.intPtr--];
    enumConstant.modifiers = this.intStack[this.intPtr--];
    enumConstant.declarationSourceStart = enumConstant.modifiersSourceStart;
-   // consume annotations
+
+	// Store secondary info
+	if ((enumConstant.bits & ASTNode.IsMemberType) == 0 && (enumConstant.bits & ASTNode.IsLocalType) == 0) {
+		if (this.compilationUnit != null && !CharOperation.equals(enumConstant.name, this.compilationUnit.getMainTypeName())) {
+			enumConstant.bits |= ASTNode.IsSecondaryType;
+		}
+	}
+
+	// consume annotations
    int length;
    if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
       System.arraycopy(
@@ -3451,6 +3480,14 @@
 	if (typeDecl.modifiersSourceStart >= 0) {
 		typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
 	}
+
+	// Store secondary info
+	if ((typeDecl.bits & ASTNode.IsMemberType) == 0 && (typeDecl.bits & ASTNode.IsLocalType) == 0) {
+		if (this.compilationUnit != null && !CharOperation.equals(typeDecl.name, this.compilationUnit.getMainTypeName())) {
+			typeDecl.bits |= ASTNode.IsSecondaryType;
+		}
+	}
+
 	// consume annotations
 	int length;
 	if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
@@ -3633,6 +3670,9 @@
 	// report the problem and continue the parsing - narrowing the problem onto the method
 	problemReporter().abstractMethodNeedingNoBody(md);
 }
+protected void consumeLabel() {
+	// Do nothing
+}
 protected void consumeLeftParen() {
 	// PushLPAREN ::= '('
 	pushOnIntStack(this.lParenPos);
@@ -5025,1171 +5065,1175 @@
 		    consumeEmptyStatement();  
 			break;
  
-    case 269 : if (DEBUG) { System.out.println("LabeledStatement ::= Identifier COLON Statement"); }  //$NON-NLS-1$
+    case 269 : if (DEBUG) { System.out.println("LabeledStatement ::= Label COLON Statement"); }  //$NON-NLS-1$
 		    consumeStatementLabel() ;  
 			break;
  
-    case 270 : if (DEBUG) { System.out.println("LabeledStatementNoShortIf ::= Identifier COLON..."); }  //$NON-NLS-1$
+    case 270 : if (DEBUG) { System.out.println("LabeledStatementNoShortIf ::= Label COLON..."); }  //$NON-NLS-1$
 		    consumeStatementLabel() ;  
 			break;
  
-     case 271 : if (DEBUG) { System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON"); }  //$NON-NLS-1$
+    case 271 : if (DEBUG) { System.out.println("Label ::= Identifier"); }  //$NON-NLS-1$
+		    consumeLabel() ;  
+			break;
+ 
+     case 272 : if (DEBUG) { System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON"); }  //$NON-NLS-1$
 		    consumeExpressionStatement();  
 			break;
  
-    case 280 : if (DEBUG) { System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+    case 281 : if (DEBUG) { System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
 		    consumeStatementIfNoElse();  
 			break;
  
-    case 281 : if (DEBUG) { System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+    case 282 : if (DEBUG) { System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
 		    consumeStatementIfWithElse();  
 			break;
  
-    case 282 : if (DEBUG) { System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression..."); }  //$NON-NLS-1$
+    case 283 : if (DEBUG) { System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression..."); }  //$NON-NLS-1$
 		    consumeStatementIfWithElse();  
 			break;
  
-    case 283 : if (DEBUG) { System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+    case 284 : if (DEBUG) { System.out.println("SwitchStatement ::= switch LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
 		    consumeStatementSwitch() ;  
 			break;
  
-    case 284 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE RBRACE"); }  //$NON-NLS-1$
+    case 285 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE RBRACE"); }  //$NON-NLS-1$
 		    consumeEmptySwitchBlock() ;  
 			break;
  
-    case 287 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements..."); }  //$NON-NLS-1$
+    case 288 : if (DEBUG) { System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements..."); }  //$NON-NLS-1$
 		    consumeSwitchBlock() ;  
 			break;
  
-    case 289 : if (DEBUG) { System.out.println("SwitchBlockStatements ::= SwitchBlockStatements..."); }  //$NON-NLS-1$
+    case 290 : if (DEBUG) { System.out.println("SwitchBlockStatements ::= SwitchBlockStatements..."); }  //$NON-NLS-1$
 		    consumeSwitchBlockStatements() ;  
 			break;
  
-    case 290 : if (DEBUG) { System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements"); }  //$NON-NLS-1$
+    case 291 : if (DEBUG) { System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements"); }  //$NON-NLS-1$
 		    consumeSwitchBlockStatement() ;  
 			break;
  
-    case 292 : if (DEBUG) { System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel"); }  //$NON-NLS-1$
+    case 293 : if (DEBUG) { System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel"); }  //$NON-NLS-1$
 		    consumeSwitchLabels() ;  
 			break;
  
-     case 293 : if (DEBUG) { System.out.println("SwitchLabel ::= case ConstantExpression COLON"); }  //$NON-NLS-1$
+     case 294 : if (DEBUG) { System.out.println("SwitchLabel ::= case ConstantExpression COLON"); }  //$NON-NLS-1$
 		    consumeCaseLabel();  
 			break;
  
-     case 294 : if (DEBUG) { System.out.println("SwitchLabel ::= default COLON"); }  //$NON-NLS-1$
+     case 295 : if (DEBUG) { System.out.println("SwitchLabel ::= default COLON"); }  //$NON-NLS-1$
 		    consumeDefaultLabel();  
 			break;
  
-    case 295 : if (DEBUG) { System.out.println("WhileStatement ::= while LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
+    case 296 : if (DEBUG) { System.out.println("WhileStatement ::= while LPAREN Expression RPAREN..."); }  //$NON-NLS-1$
 		    consumeStatementWhile() ;  
 			break;
  
-    case 296 : if (DEBUG) { System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression..."); }  //$NON-NLS-1$
+    case 297 : if (DEBUG) { System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression..."); }  //$NON-NLS-1$
 		    consumeStatementWhile() ;  
 			break;
  
-    case 297 : if (DEBUG) { System.out.println("DoStatement ::= do Statement while LPAREN Expression..."); }  //$NON-NLS-1$
+    case 298 : if (DEBUG) { System.out.println("DoStatement ::= do Statement while LPAREN Expression..."); }  //$NON-NLS-1$
 		    consumeStatementDo() ;  
 			break;
  
-    case 298 : if (DEBUG) { System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON..."); }  //$NON-NLS-1$
+    case 299 : if (DEBUG) { System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON..."); }  //$NON-NLS-1$
 		    consumeStatementFor() ;  
 			break;
  
-    case 299 : if (DEBUG) { System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt..."); }  //$NON-NLS-1$
+    case 300 : if (DEBUG) { System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt..."); }  //$NON-NLS-1$
 		    consumeStatementFor() ;  
 			break;
  
-    case 300 : if (DEBUG) { System.out.println("ForInit ::= StatementExpressionList"); }  //$NON-NLS-1$
+    case 301 : if (DEBUG) { System.out.println("ForInit ::= StatementExpressionList"); }  //$NON-NLS-1$
 		    consumeForInit() ;  
 			break;
  
-    case 304 : if (DEBUG) { System.out.println("StatementExpressionList ::= StatementExpressionList..."); }  //$NON-NLS-1$
+    case 305 : if (DEBUG) { System.out.println("StatementExpressionList ::= StatementExpressionList..."); }  //$NON-NLS-1$
 		    consumeStatementExpressionList() ;  
 			break;
  
-    case 305 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression SEMICOLON"); }  //$NON-NLS-1$
+    case 306 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression SEMICOLON"); }  //$NON-NLS-1$
 		    consumeSimpleAssertStatement() ;  
 			break;
  
-    case 306 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression COLON Expression"); }  //$NON-NLS-1$
+    case 307 : if (DEBUG) { System.out.println("AssertStatement ::= assert Expression COLON Expression"); }  //$NON-NLS-1$
 		    consumeAssertStatement() ;  
 			break;
  
-    case 307 : if (DEBUG) { System.out.println("BreakStatement ::= break SEMICOLON"); }  //$NON-NLS-1$
+    case 308 : if (DEBUG) { System.out.println("BreakStatement ::= break SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementBreak() ;  
 			break;
  
-    case 308 : if (DEBUG) { System.out.println("BreakStatement ::= break Identifier SEMICOLON"); }  //$NON-NLS-1$
+    case 309 : if (DEBUG) { System.out.println("BreakStatement ::= break Identifier SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementBreakWithLabel() ;  
 			break;
  
-    case 309 : if (DEBUG) { System.out.println("ContinueStatement ::= continue SEMICOLON"); }  //$NON-NLS-1$
+    case 310 : if (DEBUG) { System.out.println("ContinueStatement ::= continue SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementContinue() ;  
 			break;
  
-    case 310 : if (DEBUG) { System.out.println("ContinueStatement ::= continue Identifier SEMICOLON"); }  //$NON-NLS-1$
+    case 311 : if (DEBUG) { System.out.println("ContinueStatement ::= continue Identifier SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementContinueWithLabel() ;  
 			break;
  
-    case 311 : if (DEBUG) { System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON"); }  //$NON-NLS-1$
+    case 312 : if (DEBUG) { System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementReturn() ;  
 			break;
  
-    case 312 : if (DEBUG) { System.out.println("ThrowStatement ::= throw Expression SEMICOLON"); }  //$NON-NLS-1$
+    case 313 : if (DEBUG) { System.out.println("ThrowStatement ::= throw Expression SEMICOLON"); }  //$NON-NLS-1$
 		    consumeStatementThrow();  
 			break;
  
-    case 313 : if (DEBUG) { System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN..."); }  //$NON-NLS-1$
+    case 314 : if (DEBUG) { System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN..."); }  //$NON-NLS-1$
 		    consumeStatementSynchronized();  
 			break;
  
-    case 314 : if (DEBUG) { System.out.println("OnlySynchronized ::= synchronized"); }  //$NON-NLS-1$
+    case 315 : if (DEBUG) { System.out.println("OnlySynchronized ::= synchronized"); }  //$NON-NLS-1$
 		    consumeOnlySynchronized();  
 			break;
  
-    case 315 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catches"); }  //$NON-NLS-1$
+    case 316 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catches"); }  //$NON-NLS-1$
 		    consumeStatementTry(false);  
 			break;
  
-    case 316 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catchesopt Finally"); }  //$NON-NLS-1$
+    case 317 : if (DEBUG) { System.out.println("TryStatement ::= try TryBlock Catchesopt Finally"); }  //$NON-NLS-1$
 		    consumeStatementTry(true);  
 			break;
  
-    case 318 : if (DEBUG) { System.out.println("ExitTryBlock ::="); }  //$NON-NLS-1$
+    case 319 : if (DEBUG) { System.out.println("ExitTryBlock ::="); }  //$NON-NLS-1$
 		    consumeExitTryBlock();  
 			break;
  
-    case 320 : if (DEBUG) { System.out.println("Catches ::= Catches CatchClause"); }  //$NON-NLS-1$
+    case 321 : if (DEBUG) { System.out.println("Catches ::= Catches CatchClause"); }  //$NON-NLS-1$
 		    consumeCatches();  
 			break;
  
-    case 321 : if (DEBUG) { System.out.println("CatchClause ::= catch LPAREN FormalParameter RPAREN..."); }  //$NON-NLS-1$
+    case 322 : if (DEBUG) { System.out.println("CatchClause ::= catch LPAREN FormalParameter RPAREN..."); }  //$NON-NLS-1$
 		    consumeStatementCatch() ;  
 			break;
  
-    case 323 : if (DEBUG) { System.out.println("PushLPAREN ::= LPAREN"); }  //$NON-NLS-1$
+    case 324 : if (DEBUG) { System.out.println("PushLPAREN ::= LPAREN"); }  //$NON-NLS-1$
 		    consumeLeftParen();  
 			break;
  
-    case 324 : if (DEBUG) { System.out.println("PushRPAREN ::= RPAREN"); }  //$NON-NLS-1$
+    case 325 : if (DEBUG) { System.out.println("PushRPAREN ::= RPAREN"); }  //$NON-NLS-1$
 		    consumeRightParen();  
 			break;
  
-    case 329 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= this"); }  //$NON-NLS-1$
+    case 330 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= this"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayThis();  
 			break;
  
-    case 330 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression_NotName..."); }  //$NON-NLS-1$
+    case 331 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression_NotName..."); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArray();  
 			break;
  
-    case 331 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Name PushRPAREN"); }  //$NON-NLS-1$
+    case 332 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PushLPAREN Name PushRPAREN"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayWithName();  
 			break;
  
-    case 334 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT this"); }  //$NON-NLS-1$
+    case 335 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT this"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayNameThis();  
 			break;
  
-    case 335 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT super"); }  //$NON-NLS-1$
+    case 336 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT super"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayNameSuper();  
 			break;
  
-    case 336 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT class"); }  //$NON-NLS-1$
+    case 337 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayName();  
 			break;
  
-    case 337 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name Dims DOT class"); }  //$NON-NLS-1$
+    case 338 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= Name Dims DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayArrayType();  
 			break;
  
-    case 338 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType Dims DOT class"); }  //$NON-NLS-1$
+    case 339 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType Dims DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayPrimitiveArrayType();  
 			break;
  
-    case 339 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); }  //$NON-NLS-1$
+    case 340 : if (DEBUG) { System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class"); }  //$NON-NLS-1$
 		    consumePrimaryNoNewArrayPrimitiveType();  
 			break;
  
-    case 342 : if (DEBUG) { System.out.println("AllocationHeader ::= new ClassType LPAREN..."); }  //$NON-NLS-1$
+    case 343 : if (DEBUG) { System.out.println("AllocationHeader ::= new ClassType LPAREN..."); }  //$NON-NLS-1$
 		    consumeAllocationHeader();  
 			break;
  
-    case 343 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new..."); }  //$NON-NLS-1$
+    case 344 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionWithTypeArguments();  
 			break;
  
-    case 344 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new ClassType LPAREN"); }  //$NON-NLS-1$
+    case 345 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= new ClassType LPAREN"); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpression();  
 			break;
  
-    case 345 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
+    case 346 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ;  
 			break;
  
-    case 346 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
-		    consumeClassInstanceCreationExpressionQualified() ;  
-			break;
- 
-    case 347 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
+    case 347 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::= Primary DOT new..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionQualified() ;  
 			break;
  
     case 348 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
+		    consumeClassInstanceCreationExpressionQualified() ;  
+			break;
+ 
+    case 349 : if (DEBUG) { System.out.println("ClassInstanceCreationExpression ::=..."); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionQualifiedWithTypeArguments() ;  
 			break;
  
-    case 349 : if (DEBUG) { System.out.println("ClassInstanceCreationExpressionName ::= Name DOT"); }  //$NON-NLS-1$
+    case 350 : if (DEBUG) { System.out.println("ClassInstanceCreationExpressionName ::= Name DOT"); }  //$NON-NLS-1$
 		    consumeClassInstanceCreationExpressionName() ;  
 			break;
  
-    case 350 : if (DEBUG) { System.out.println("ClassBodyopt ::="); }  //$NON-NLS-1$
+    case 351 : if (DEBUG) { System.out.println("ClassBodyopt ::="); }  //$NON-NLS-1$
 		    consumeClassBodyopt();  
 			break;
  
-    case 352 : if (DEBUG) { System.out.println("EnterAnonymousClassBody ::="); }  //$NON-NLS-1$
+    case 353 : if (DEBUG) { System.out.println("EnterAnonymousClassBody ::="); }  //$NON-NLS-1$
 		    consumeEnterAnonymousClassBody();  
 			break;
  
-    case 354 : if (DEBUG) { System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); }  //$NON-NLS-1$
+    case 355 : if (DEBUG) { System.out.println("ArgumentList ::= ArgumentList COMMA Expression"); }  //$NON-NLS-1$
 		    consumeArgumentList();  
 			break;
  
-    case 355 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new PrimitiveType..."); }  //$NON-NLS-1$
+    case 356 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new PrimitiveType..."); }  //$NON-NLS-1$
 		    consumeArrayCreationHeader();  
 			break;
  
-    case 356 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); }  //$NON-NLS-1$
+    case 357 : if (DEBUG) { System.out.println("ArrayCreationHeader ::= new ClassOrInterfaceType..."); }  //$NON-NLS-1$
 		    consumeArrayCreationHeader();  
 			break;
  
-    case 357 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
+    case 358 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithoutInitializer();  
 			break;
  
-    case 358 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType"); }  //$NON-NLS-1$
+    case 359 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new PrimitiveType"); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithInitializer();  
 			break;
  
-    case 359 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
+    case 360 : if (DEBUG) { System.out.println("ArrayCreationWithoutArrayInitializer ::= new..."); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithoutInitializer();  
 			break;
  
-    case 360 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new..."); }  //$NON-NLS-1$
+    case 361 : if (DEBUG) { System.out.println("ArrayCreationWithArrayInitializer ::= new..."); }  //$NON-NLS-1$
 		    consumeArrayCreationExpressionWithInitializer();  
 			break;
  
-    case 362 : if (DEBUG) { System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs..."); }  //$NON-NLS-1$
+    case 363 : if (DEBUG) { System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs..."); }  //$NON-NLS-1$
 		    consumeDimWithOrWithOutExprs();  
 			break;
  
-     case 364 : if (DEBUG) { System.out.println("DimWithOrWithOutExpr ::= LBRACKET RBRACKET"); }  //$NON-NLS-1$
+     case 365 : if (DEBUG) { System.out.println("DimWithOrWithOutExpr ::= LBRACKET RBRACKET"); }  //$NON-NLS-1$
 		    consumeDimWithOrWithOutExpr();  
 			break;
  
-     case 365 : if (DEBUG) { System.out.println("Dims ::= DimsLoop"); }  //$NON-NLS-1$
+     case 366 : if (DEBUG) { System.out.println("Dims ::= DimsLoop"); }  //$NON-NLS-1$
 		    consumeDims();  
 			break;
  
-     case 368 : if (DEBUG) { System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); }  //$NON-NLS-1$
+     case 369 : if (DEBUG) { System.out.println("OneDimLoop ::= LBRACKET RBRACKET"); }  //$NON-NLS-1$
 		    consumeOneDimLoop();  
 			break;
  
-    case 369 : if (DEBUG) { System.out.println("FieldAccess ::= Primary DOT Identifier"); }  //$NON-NLS-1$
+    case 370 : if (DEBUG) { System.out.println("FieldAccess ::= Primary DOT Identifier"); }  //$NON-NLS-1$
 		    consumeFieldAccess(false);  
 			break;
  
-    case 370 : if (DEBUG) { System.out.println("FieldAccess ::= super DOT Identifier"); }  //$NON-NLS-1$
+    case 371 : if (DEBUG) { System.out.println("FieldAccess ::= super DOT Identifier"); }  //$NON-NLS-1$
 		    consumeFieldAccess(true);  
 			break;
  
-    case 371 : if (DEBUG) { System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
+    case 372 : if (DEBUG) { System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
 		    consumeMethodInvocationName();  
 			break;
  
-    case 372 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 373 : if (DEBUG) { System.out.println("MethodInvocation ::= Name DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationNameWithTypeArguments();  
 			break;
  
-    case 373 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 374 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationPrimaryWithTypeArguments();  
 			break;
  
-    case 374 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN..."); }  //$NON-NLS-1$
+    case 375 : if (DEBUG) { System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationPrimary();  
 			break;
  
-    case 375 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
+    case 376 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT OnlyTypeArguments..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationSuperWithTypeArguments();  
 			break;
  
-    case 376 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT Identifier LPAREN..."); }  //$NON-NLS-1$
+    case 377 : if (DEBUG) { System.out.println("MethodInvocation ::= super DOT Identifier LPAREN..."); }  //$NON-NLS-1$
 		    consumeMethodInvocationSuper();  
 			break;
  
-    case 377 : if (DEBUG) { System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); }  //$NON-NLS-1$
+    case 378 : if (DEBUG) { System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET"); }  //$NON-NLS-1$
 		    consumeArrayAccess(true);  
 			break;
  
-    case 378 : if (DEBUG) { System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression..."); }  //$NON-NLS-1$
+    case 379 : if (DEBUG) { System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression..."); }  //$NON-NLS-1$
 		    consumeArrayAccess(false);  
 			break;
  
-    case 379 : if (DEBUG) { System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer..."); }  //$NON-NLS-1$
+    case 380 : if (DEBUG) { System.out.println("ArrayAccess ::= ArrayCreationWithArrayInitializer..."); }  //$NON-NLS-1$
 		    consumeArrayAccess(false);  
 			break;
  
-    case 381 : if (DEBUG) { System.out.println("PostfixExpression ::= Name"); }  //$NON-NLS-1$
+    case 382 : if (DEBUG) { System.out.println("PostfixExpression ::= Name"); }  //$NON-NLS-1$
 		    consumePostfixExpression();  
 			break;
  
-    case 384 : if (DEBUG) { System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); }  //$NON-NLS-1$
+    case 385 : if (DEBUG) { System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS"); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.PLUS,true);  
 			break;
  
-    case 385 : if (DEBUG) { System.out.println("PostDecrementExpression ::= PostfixExpression..."); }  //$NON-NLS-1$
+    case 386 : if (DEBUG) { System.out.println("PostDecrementExpression ::= PostfixExpression..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.MINUS,true);  
 			break;
  
-    case 386 : if (DEBUG) { System.out.println("PushPosition ::="); }  //$NON-NLS-1$
+    case 387 : if (DEBUG) { System.out.println("PushPosition ::="); }  //$NON-NLS-1$
 		    consumePushPosition();  
 			break;
  
-    case 389 : if (DEBUG) { System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
+    case 390 : if (DEBUG) { System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.PLUS);  
 			break;
  
-    case 390 : if (DEBUG) { System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
+    case 391 : if (DEBUG) { System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression"); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.MINUS);  
 			break;
  
-    case 392 : if (DEBUG) { System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition..."); }  //$NON-NLS-1$
+    case 393 : if (DEBUG) { System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.PLUS,false);  
 			break;
  
-    case 393 : if (DEBUG) { System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition..."); }  //$NON-NLS-1$
+    case 394 : if (DEBUG) { System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.MINUS,false);  
 			break;
  
-    case 395 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition..."); }  //$NON-NLS-1$
+    case 396 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.TWIDDLE);  
 			break;
  
-    case 396 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition..."); }  //$NON-NLS-1$
+    case 397 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition..."); }  //$NON-NLS-1$
 		    consumeUnaryExpression(OperatorIds.NOT);  
 			break;
  
-    case 398 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt..."); }  //$NON-NLS-1$
+    case 399 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithPrimitiveType();  
 			break;
  
-    case 399 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
+    case 400 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithGenericsArray();  
 			break;
  
-    case 400 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
+    case 401 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithQualifiedGenericsArray();  
 			break;
  
-    case 401 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name PushRPAREN..."); }  //$NON-NLS-1$
+    case 402 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name PushRPAREN..."); }  //$NON-NLS-1$
 		    consumeCastExpressionLL1();  
 			break;
  
-    case 402 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name Dims PushRPAREN..."); }  //$NON-NLS-1$
+    case 403 : if (DEBUG) { System.out.println("CastExpression ::= PushLPAREN Name Dims PushRPAREN..."); }  //$NON-NLS-1$
 		    consumeCastExpressionWithNameArray();  
 			break;
  
-    case 403 : if (DEBUG) { System.out.println("OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments"); }  //$NON-NLS-1$
+    case 404 : if (DEBUG) { System.out.println("OnlyTypeArgumentsForCastExpression ::= OnlyTypeArguments"); }  //$NON-NLS-1$
 		    consumeOnlyTypeArgumentsForCastExpression();  
 			break;
  
-    case 404 : if (DEBUG) { System.out.println("InsideCastExpression ::="); }  //$NON-NLS-1$
+    case 405 : if (DEBUG) { System.out.println("InsideCastExpression ::="); }  //$NON-NLS-1$
 		    consumeInsideCastExpression();  
 			break;
  
-    case 405 : if (DEBUG) { System.out.println("InsideCastExpressionLL1 ::="); }  //$NON-NLS-1$
+    case 406 : if (DEBUG) { System.out.println("InsideCastExpressionLL1 ::="); }  //$NON-NLS-1$
 		    consumeInsideCastExpressionLL1();  
 			break;
  
-    case 406 : if (DEBUG) { System.out.println("InsideCastExpressionWithQualifiedGenerics ::="); }  //$NON-NLS-1$
+    case 407 : if (DEBUG) { System.out.println("InsideCastExpressionWithQualifiedGenerics ::="); }  //$NON-NLS-1$
 		    consumeInsideCastExpressionWithQualifiedGenerics();  
 			break;
  
-    case 408 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.MULTIPLY);  
-			break;
- 
     case 409 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.DIVIDE);  
+		    consumeBinaryExpression(OperatorIds.MULTIPLY);  
 			break;
  
     case 410 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.REMAINDER);  
-			break;
- 
-    case 412 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.PLUS);  
-			break;
- 
-    case 413 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.MINUS);  
-			break;
- 
-    case 415 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.LEFT_SHIFT);  
-			break;
- 
-    case 416 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);  
-			break;
- 
-    case 417 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);  
-			break;
- 
-    case 419 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.LESS);  
-			break;
- 
-    case 420 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.GREATER);  
-			break;
- 
-    case 421 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL"); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.LESS_EQUAL);  
-			break;
- 
-    case 422 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.GREATER_EQUAL);  
-			break;
- 
-    case 424 : if (DEBUG) { System.out.println("InstanceofExpression ::= InstanceofExpression instanceof"); }  //$NON-NLS-1$
-		    consumeInstanceOfExpression();  
-			break;
- 
-    case 426 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); }  //$NON-NLS-1$
-		    consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);  
-			break;
- 
-    case 427 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); }  //$NON-NLS-1$
-		    consumeEqualityExpression(OperatorIds.NOT_EQUAL);  
-			break;
- 
-    case 429 : if (DEBUG) { System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.AND);  
-			break;
- 
-    case 431 : if (DEBUG) { System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.XOR);  
-			break;
- 
-    case 433 : if (DEBUG) { System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.OR);  
-			break;
- 
-    case 435 : if (DEBUG) { System.out.println("ConditionalAndExpression ::= ConditionalAndExpression..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.AND_AND);  
-			break;
- 
-    case 437 : if (DEBUG) { System.out.println("ConditionalOrExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.OR_OR);  
-			break;
- 
-    case 439 : if (DEBUG) { System.out.println("ConditionalExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
-		    consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;  
-			break;
- 
-    case 442 : if (DEBUG) { System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); }  //$NON-NLS-1$
-		    consumeAssignment();  
-			break;
- 
-    case 444 : if (DEBUG) { System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); }  //$NON-NLS-1$
-		    ignoreExpressionAssignment(); 
-			break;
- 
-    case 445 : if (DEBUG) { System.out.println("AssignmentOperator ::= EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(EQUAL);  
-			break;
- 
-    case 446 : if (DEBUG) { System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(MULTIPLY);  
-			break;
- 
-    case 447 : if (DEBUG) { System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(DIVIDE);  
-			break;
- 
-    case 448 : if (DEBUG) { System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(REMAINDER);  
-			break;
- 
-    case 449 : if (DEBUG) { System.out.println("AssignmentOperator ::= PLUS_EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(PLUS);  
-			break;
- 
-    case 450 : if (DEBUG) { System.out.println("AssignmentOperator ::= MINUS_EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(MINUS);  
-			break;
- 
-    case 451 : if (DEBUG) { System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(LEFT_SHIFT);  
-			break;
- 
-    case 452 : if (DEBUG) { System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(RIGHT_SHIFT);  
-			break;
- 
-    case 453 : if (DEBUG) { System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);  
-			break;
- 
-    case 454 : if (DEBUG) { System.out.println("AssignmentOperator ::= AND_EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(AND);  
-			break;
- 
-    case 455 : if (DEBUG) { System.out.println("AssignmentOperator ::= XOR_EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(XOR);  
-			break;
- 
-    case 456 : if (DEBUG) { System.out.println("AssignmentOperator ::= OR_EQUAL"); }  //$NON-NLS-1$
-		    consumeAssignmentOperator(OR);  
-			break;
- 
-    case 460 : if (DEBUG) { System.out.println("Expressionopt ::="); }  //$NON-NLS-1$
-		    consumeEmptyExpression();  
-			break;
- 
-    case 465 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::="); }  //$NON-NLS-1$
-		    consumeEmptyClassBodyDeclarationsopt();  
-			break;
- 
-    case 466 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
-		    consumeClassBodyDeclarationsopt();  
-			break;
- 
-     case 467 : if (DEBUG) { System.out.println("Modifiersopt ::="); }  //$NON-NLS-1$
-		    consumeDefaultModifiers();  
-			break;
- 
-    case 468 : if (DEBUG) { System.out.println("Modifiersopt ::= Modifiers"); }  //$NON-NLS-1$
-		    consumeModifiers();  
-			break;
- 
-    case 469 : if (DEBUG) { System.out.println("BlockStatementsopt ::="); }  //$NON-NLS-1$
-		    consumeEmptyBlockStatementsopt();  
-			break;
- 
-     case 471 : if (DEBUG) { System.out.println("Dimsopt ::="); }  //$NON-NLS-1$
-		    consumeEmptyDimsopt();  
-			break;
- 
-     case 473 : if (DEBUG) { System.out.println("ArgumentListopt ::="); }  //$NON-NLS-1$
-		    consumeEmptyArgumentListopt();  
-			break;
- 
-    case 477 : if (DEBUG) { System.out.println("FormalParameterListopt ::="); }  //$NON-NLS-1$
-		    consumeFormalParameterListopt();  
-			break;
- 
-     case 481 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::="); }  //$NON-NLS-1$
-		    consumeEmptyInterfaceMemberDeclarationsopt();  
-			break;
- 
-     case 482 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
-		    consumeInterfaceMemberDeclarationsopt();  
-			break;
- 
-    case 483 : if (DEBUG) { System.out.println("NestedType ::="); }  //$NON-NLS-1$
-		    consumeNestedType();  
-			break;
-
-     case 484 : if (DEBUG) { System.out.println("ForInitopt ::="); }  //$NON-NLS-1$
-		    consumeEmptyForInitopt();  
-			break;
- 
-     case 486 : if (DEBUG) { System.out.println("ForUpdateopt ::="); }  //$NON-NLS-1$
-		    consumeEmptyForUpdateopt();  
-			break;
- 
-     case 490 : if (DEBUG) { System.out.println("Catchesopt ::="); }  //$NON-NLS-1$
-		    consumeEmptyCatchesopt();  
-			break;
- 
-     case 492 : if (DEBUG) { System.out.println("EnumDeclaration ::= EnumHeader EnumBody"); }  //$NON-NLS-1$
-		    consumeEnumDeclaration();  
-			break;
- 
-     case 493 : if (DEBUG) { System.out.println("EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt"); }  //$NON-NLS-1$
-		    consumeEnumHeader();  
-			break;
- 
-     case 494 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier"); }  //$NON-NLS-1$
-		    consumeEnumHeaderName();  
-			break;
- 
-     case 495 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumBodyDeclarationsopt RBRACE"); }  //$NON-NLS-1$
-		    consumeEnumBodyNoConstants();  
-			break;
- 
-     case 496 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE COMMA EnumBodyDeclarationsopt..."); }  //$NON-NLS-1$
-		    consumeEnumBodyNoConstants();  
-			break;
- 
-     case 497 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants COMMA..."); }  //$NON-NLS-1$
-		    consumeEnumBodyWithConstants();  
-			break;
- 
-     case 498 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants..."); }  //$NON-NLS-1$
-		    consumeEnumBodyWithConstants();  
-			break;
- 
-    case 500 : if (DEBUG) { System.out.println("EnumConstants ::= EnumConstants COMMA EnumConstant"); }  //$NON-NLS-1$
-		    consumeEnumConstants();  
-			break;
- 
-    case 501 : if (DEBUG) { System.out.println("EnumConstantHeaderName ::= Modifiersopt Identifier"); }  //$NON-NLS-1$
-		    consumeEnumConstantHeaderName();  
-			break;
- 
-    case 502 : if (DEBUG) { System.out.println("EnumConstantHeader ::= EnumConstantHeaderName..."); }  //$NON-NLS-1$
-		    consumeEnumConstantHeader();  
-			break;
- 
-    case 503 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader ForceNoDiet..."); }  //$NON-NLS-1$
-		    consumeEnumConstantWithClassBody();  
-			break;
- 
-    case 504 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader"); }  //$NON-NLS-1$
-		    consumeEnumConstantNoClassBody();  
-			break;
- 
-    case 505 : if (DEBUG) { System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
-		    consumeArguments();  
-			break;
- 
-    case 506 : if (DEBUG) { System.out.println("Argumentsopt ::="); }  //$NON-NLS-1$
-		    consumeEmptyArguments();  
-			break;
- 
-    case 508 : if (DEBUG) { System.out.println("EnumDeclarations ::= SEMICOLON ClassBodyDeclarationsopt"); }  //$NON-NLS-1$
-		    consumeEnumDeclarations();  
-			break;
- 
-    case 509 : if (DEBUG) { System.out.println("EnumBodyDeclarationsopt ::="); }  //$NON-NLS-1$
-		    consumeEmptyEnumDeclarations();  
-			break;
- 
-    case 511 : if (DEBUG) { System.out.println("EnhancedForStatement ::= EnhancedForStatementHeader..."); }  //$NON-NLS-1$
-		    consumeEnhancedForStatement();  
-			break;
- 
-    case 512 : if (DEBUG) { System.out.println("EnhancedForStatementNoShortIf ::=..."); }  //$NON-NLS-1$
-		    consumeEnhancedForStatement();  
-			break;
- 
-    case 513 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Type..."); }  //$NON-NLS-1$
-		    consumeEnhancedForStatementHeaderInit(false);  
-			break;
- 
-    case 514 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Modifiers"); }  //$NON-NLS-1$
-		    consumeEnhancedForStatementHeaderInit(true);  
-			break;
- 
-    case 515 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::=..."); }  //$NON-NLS-1$
-		    consumeEnhancedForStatementHeader();  
-			break;
- 
-    case 516 : if (DEBUG) { System.out.println("SingleStaticImportDeclaration ::=..."); }  //$NON-NLS-1$
-		    consumeImportDeclaration();  
-			break;
- 
-    case 517 : if (DEBUG) { System.out.println("SingleStaticImportDeclarationName ::= import static Name"); }  //$NON-NLS-1$
-		    consumeSingleStaticImportDeclarationName();  
-			break;
- 
-    case 518 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclaration ::=..."); }  //$NON-NLS-1$
-		    consumeImportDeclaration();  
-			break;
- 
-    case 519 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclarationName ::= import static..."); }  //$NON-NLS-1$
-		    consumeStaticImportOnDemandDeclarationName();  
-			break;
- 
-    case 520 : if (DEBUG) { System.out.println("TypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
-		    consumeTypeArguments();  
-			break;
- 
-    case 521 : if (DEBUG) { System.out.println("OnlyTypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
-		    consumeOnlyTypeArguments();  
-			break;
- 
-    case 523 : if (DEBUG) { System.out.println("TypeArgumentList1 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
-		    consumeTypeArgumentList1();  
-			break;
- 
-    case 525 : if (DEBUG) { System.out.println("TypeArgumentList ::= TypeArgumentList COMMA TypeArgument"); }  //$NON-NLS-1$
-		    consumeTypeArgumentList();  
-			break;
- 
-    case 526 : if (DEBUG) { System.out.println("TypeArgument ::= ReferenceType"); }  //$NON-NLS-1$
-		    consumeTypeArgument();  
-			break;
- 
-    case 530 : if (DEBUG) { System.out.println("ReferenceType1 ::= ReferenceType GREATER"); }  //$NON-NLS-1$
-		    consumeReferenceType1();  
-			break;
- 
-    case 531 : if (DEBUG) { System.out.println("ReferenceType1 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
-		    consumeTypeArgumentReferenceType1();  
-			break;
- 
-    case 533 : if (DEBUG) { System.out.println("TypeArgumentList2 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
-		    consumeTypeArgumentList2();  
-			break;
- 
-    case 536 : if (DEBUG) { System.out.println("ReferenceType2 ::= ReferenceType RIGHT_SHIFT"); }  //$NON-NLS-1$
-		    consumeReferenceType2();  
-			break;
- 
-    case 537 : if (DEBUG) { System.out.println("ReferenceType2 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
-		    consumeTypeArgumentReferenceType2();  
-			break;
- 
-    case 539 : if (DEBUG) { System.out.println("TypeArgumentList3 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
-		    consumeTypeArgumentList3();  
-			break;
- 
-    case 542 : if (DEBUG) { System.out.println("ReferenceType3 ::= ReferenceType UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
-		    consumeReferenceType3();  
-			break;
- 
-    case 543 : if (DEBUG) { System.out.println("Wildcard ::= QUESTION"); }  //$NON-NLS-1$
-		    consumeWildcard();  
-			break;
- 
-    case 544 : if (DEBUG) { System.out.println("Wildcard ::= QUESTION WildcardBounds"); }  //$NON-NLS-1$
-		    consumeWildcardWithBounds();  
-			break;
- 
-    case 545 : if (DEBUG) { System.out.println("WildcardBounds ::= extends ReferenceType"); }  //$NON-NLS-1$
-		    consumeWildcardBoundsExtends();  
-			break;
- 
-    case 546 : if (DEBUG) { System.out.println("WildcardBounds ::= super ReferenceType"); }  //$NON-NLS-1$
-		    consumeWildcardBoundsSuper();  
-			break;
- 
-    case 547 : if (DEBUG) { System.out.println("Wildcard1 ::= QUESTION GREATER"); }  //$NON-NLS-1$
-		    consumeWildcard1();  
-			break;
- 
-    case 548 : if (DEBUG) { System.out.println("Wildcard1 ::= QUESTION WildcardBounds1"); }  //$NON-NLS-1$
-		    consumeWildcard1WithBounds();  
-			break;
- 
-    case 549 : if (DEBUG) { System.out.println("WildcardBounds1 ::= extends ReferenceType1"); }  //$NON-NLS-1$
-		    consumeWildcardBounds1Extends();  
-			break;
- 
-    case 550 : if (DEBUG) { System.out.println("WildcardBounds1 ::= super ReferenceType1"); }  //$NON-NLS-1$
-		    consumeWildcardBounds1Super();  
-			break;
- 
-    case 551 : if (DEBUG) { System.out.println("Wildcard2 ::= QUESTION RIGHT_SHIFT"); }  //$NON-NLS-1$
-		    consumeWildcard2();  
-			break;
- 
-    case 552 : if (DEBUG) { System.out.println("Wildcard2 ::= QUESTION WildcardBounds2"); }  //$NON-NLS-1$
-		    consumeWildcard2WithBounds();  
-			break;
- 
-    case 553 : if (DEBUG) { System.out.println("WildcardBounds2 ::= extends ReferenceType2"); }  //$NON-NLS-1$
-		    consumeWildcardBounds2Extends();  
-			break;
- 
-    case 554 : if (DEBUG) { System.out.println("WildcardBounds2 ::= super ReferenceType2"); }  //$NON-NLS-1$
-		    consumeWildcardBounds2Super();  
-			break;
- 
-    case 555 : if (DEBUG) { System.out.println("Wildcard3 ::= QUESTION UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
-		    consumeWildcard3();  
-			break;
- 
-    case 556 : if (DEBUG) { System.out.println("Wildcard3 ::= QUESTION WildcardBounds3"); }  //$NON-NLS-1$
-		    consumeWildcard3WithBounds();  
-			break;
- 
-    case 557 : if (DEBUG) { System.out.println("WildcardBounds3 ::= extends ReferenceType3"); }  //$NON-NLS-1$
-		    consumeWildcardBounds3Extends();  
-			break;
- 
-    case 558 : if (DEBUG) { System.out.println("WildcardBounds3 ::= super ReferenceType3"); }  //$NON-NLS-1$
-		    consumeWildcardBounds3Super();  
-			break;
- 
-    case 559 : if (DEBUG) { System.out.println("TypeParameterHeader ::= Identifier"); }  //$NON-NLS-1$
-		    consumeTypeParameterHeader();  
-			break;
- 
-    case 560 : if (DEBUG) { System.out.println("TypeParameters ::= LESS TypeParameterList1"); }  //$NON-NLS-1$
-		    consumeTypeParameters();  
-			break;
- 
-    case 562 : if (DEBUG) { System.out.println("TypeParameterList ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
-		    consumeTypeParameterList();  
-			break;
- 
-    case 564 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
-		    consumeTypeParameterWithExtends();  
-			break;
- 
-    case 565 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
-		    consumeTypeParameterWithExtendsAndBounds();  
-			break;
- 
-    case 567 : if (DEBUG) { System.out.println("AdditionalBoundList ::= AdditionalBoundList..."); }  //$NON-NLS-1$
-		    consumeAdditionalBoundList();  
-			break;
- 
-    case 568 : if (DEBUG) { System.out.println("AdditionalBound ::= AND ReferenceType"); }  //$NON-NLS-1$
-		    consumeAdditionalBound();  
-			break;
- 
-    case 570 : if (DEBUG) { System.out.println("TypeParameterList1 ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
-		    consumeTypeParameterList1();  
-			break;
- 
-    case 571 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader GREATER"); }  //$NON-NLS-1$
-		    consumeTypeParameter1();  
-			break;
- 
-    case 572 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
-		    consumeTypeParameter1WithExtends();  
-			break;
- 
-    case 573 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
-		    consumeTypeParameter1WithExtendsAndBounds();  
-			break;
- 
-    case 575 : if (DEBUG) { System.out.println("AdditionalBoundList1 ::= AdditionalBoundList..."); }  //$NON-NLS-1$
-		    consumeAdditionalBoundList1();  
-			break;
- 
-    case 576 : if (DEBUG) { System.out.println("AdditionalBound1 ::= AND ReferenceType1"); }  //$NON-NLS-1$
-		    consumeAdditionalBound1();  
-			break;
- 
-    case 582 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= PLUS PushPosition..."); }  //$NON-NLS-1$
-		    consumeUnaryExpression(OperatorIds.PLUS);  
-			break;
- 
-    case 583 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= MINUS PushPosition..."); }  //$NON-NLS-1$
-		    consumeUnaryExpression(OperatorIds.MINUS);  
-			break;
- 
-    case 586 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= TWIDDLE..."); }  //$NON-NLS-1$
-		    consumeUnaryExpression(OperatorIds.TWIDDLE);  
-			break;
- 
-    case 587 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= NOT PushPosition"); }  //$NON-NLS-1$
-		    consumeUnaryExpression(OperatorIds.NOT);  
-			break;
- 
-    case 590 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
-		    consumeBinaryExpression(OperatorIds.MULTIPLY);  
-			break;
- 
-    case 591 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name MULTIPLY..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.MULTIPLY);  
-			break;
- 
-    case 592 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.DIVIDE);  
 			break;
  
-    case 593 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name DIVIDE..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.DIVIDE);  
-			break;
- 
-    case 594 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 411 : if (DEBUG) { System.out.println("MultiplicativeExpression ::= MultiplicativeExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.REMAINDER);  
 			break;
  
-    case 595 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name REMAINDER..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.REMAINDER);  
-			break;
- 
-    case 597 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 413 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression PLUS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.PLUS);  
 			break;
  
-    case 598 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name PLUS..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.PLUS);  
-			break;
- 
-    case 599 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 414 : if (DEBUG) { System.out.println("AdditiveExpression ::= AdditiveExpression MINUS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.MINUS);  
 			break;
  
-    case 600 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name MINUS..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.MINUS);  
-			break;
- 
-    case 602 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+    case 416 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LEFT_SHIFT);  
 			break;
  
-    case 603 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name LEFT_SHIFT..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.LEFT_SHIFT);  
-			break;
- 
-    case 604 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+    case 417 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);  
 			break;
  
-    case 605 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name RIGHT_SHIFT..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.RIGHT_SHIFT);  
-			break;
- 
-    case 606 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+    case 418 : if (DEBUG) { System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);  
 			break;
  
-    case 607 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name UNSIGNED_RIGHT_SHIFT..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.UNSIGNED_RIGHT_SHIFT);  
-			break;
- 
-    case 609 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); }  //$NON-NLS-1$
+    case 420 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LESS);  
 			break;
  
-    case 610 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.LESS);  
-			break;
- 
-    case 611 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); }  //$NON-NLS-1$
+    case 421 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression GREATER..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.GREATER);  
 			break;
  
-    case 612 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.GREATER);  
-			break;
- 
-    case 613 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 422 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL"); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.LESS_EQUAL);  
 			break;
  
-    case 614 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS_EQUAL..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.LESS_EQUAL);  
-			break;
- 
-    case 615 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 423 : if (DEBUG) { System.out.println("RelationalExpression ::= RelationalExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.GREATER_EQUAL);  
 			break;
  
-    case 616 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER_EQUAL..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.GREATER_EQUAL);  
-			break;
- 
-    case 618 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::= Name instanceof..."); }  //$NON-NLS-1$
-		    consumeInstanceOfExpressionWithName();  
-			break;
- 
-    case 619 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 425 : if (DEBUG) { System.out.println("InstanceofExpression ::= InstanceofExpression instanceof"); }  //$NON-NLS-1$
 		    consumeInstanceOfExpression();  
 			break;
  
-    case 621 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 427 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL..."); }  //$NON-NLS-1$
 		    consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);  
 			break;
  
-    case 622 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name EQUAL_EQUAL..."); }  //$NON-NLS-1$
-		    consumeEqualityExpressionWithName(OperatorIds.EQUAL_EQUAL);  
-			break;
- 
-    case 623 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 428 : if (DEBUG) { System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL..."); }  //$NON-NLS-1$
 		    consumeEqualityExpression(OperatorIds.NOT_EQUAL);  
 			break;
  
-    case 624 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name NOT_EQUAL..."); }  //$NON-NLS-1$
-		    consumeEqualityExpressionWithName(OperatorIds.NOT_EQUAL);  
-			break;
- 
-    case 626 : if (DEBUG) { System.out.println("AndExpression_NotName ::= AndExpression_NotName AND..."); }  //$NON-NLS-1$
+    case 430 : if (DEBUG) { System.out.println("AndExpression ::= AndExpression AND EqualityExpression"); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.AND);  
 			break;
  
-    case 627 : if (DEBUG) { System.out.println("AndExpression_NotName ::= Name AND EqualityExpression"); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.AND);  
-			break;
- 
-    case 629 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 432 : if (DEBUG) { System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.XOR);  
 			break;
  
-    case 630 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::= Name XOR AndExpression"); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.XOR);  
-			break;
- 
-    case 632 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 434 : if (DEBUG) { System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.OR);  
 			break;
  
-    case 633 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::= Name OR..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.OR);  
-			break;
- 
-    case 635 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 436 : if (DEBUG) { System.out.println("ConditionalAndExpression ::= ConditionalAndExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.AND_AND);  
 			break;
  
-    case 636 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::= Name AND_AND..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.AND_AND);  
-			break;
- 
-    case 638 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 438 : if (DEBUG) { System.out.println("ConditionalOrExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
 		    consumeBinaryExpression(OperatorIds.OR_OR);  
 			break;
  
-    case 639 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::= Name OR_OR..."); }  //$NON-NLS-1$
-		    consumeBinaryExpressionWithName(OperatorIds.OR_OR);  
-			break;
- 
-    case 641 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::=..."); }  //$NON-NLS-1$
+    case 440 : if (DEBUG) { System.out.println("ConditionalExpression ::= ConditionalOrExpression..."); }  //$NON-NLS-1$
 		    consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;  
 			break;
  
-    case 642 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::= Name QUESTION..."); }  //$NON-NLS-1$
+    case 443 : if (DEBUG) { System.out.println("Assignment ::= PostfixExpression AssignmentOperator..."); }  //$NON-NLS-1$
+		    consumeAssignment();  
+			break;
+ 
+    case 445 : if (DEBUG) { System.out.println("Assignment ::= InvalidArrayInitializerAssignement"); }  //$NON-NLS-1$
+		    ignoreExpressionAssignment(); 
+			break;
+ 
+    case 446 : if (DEBUG) { System.out.println("AssignmentOperator ::= EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(EQUAL);  
+			break;
+ 
+    case 447 : if (DEBUG) { System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(MULTIPLY);  
+			break;
+ 
+    case 448 : if (DEBUG) { System.out.println("AssignmentOperator ::= DIVIDE_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(DIVIDE);  
+			break;
+ 
+    case 449 : if (DEBUG) { System.out.println("AssignmentOperator ::= REMAINDER_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(REMAINDER);  
+			break;
+ 
+    case 450 : if (DEBUG) { System.out.println("AssignmentOperator ::= PLUS_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(PLUS);  
+			break;
+ 
+    case 451 : if (DEBUG) { System.out.println("AssignmentOperator ::= MINUS_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(MINUS);  
+			break;
+ 
+    case 452 : if (DEBUG) { System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(LEFT_SHIFT);  
+			break;
+ 
+    case 453 : if (DEBUG) { System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(RIGHT_SHIFT);  
+			break;
+ 
+    case 454 : if (DEBUG) { System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);  
+			break;
+ 
+    case 455 : if (DEBUG) { System.out.println("AssignmentOperator ::= AND_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(AND);  
+			break;
+ 
+    case 456 : if (DEBUG) { System.out.println("AssignmentOperator ::= XOR_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(XOR);  
+			break;
+ 
+    case 457 : if (DEBUG) { System.out.println("AssignmentOperator ::= OR_EQUAL"); }  //$NON-NLS-1$
+		    consumeAssignmentOperator(OR);  
+			break;
+ 
+    case 461 : if (DEBUG) { System.out.println("Expressionopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyExpression();  
+			break;
+ 
+    case 466 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyClassBodyDeclarationsopt();  
+			break;
+ 
+    case 467 : if (DEBUG) { System.out.println("ClassBodyDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
+		    consumeClassBodyDeclarationsopt();  
+			break;
+ 
+     case 468 : if (DEBUG) { System.out.println("Modifiersopt ::="); }  //$NON-NLS-1$
+		    consumeDefaultModifiers();  
+			break;
+ 
+    case 469 : if (DEBUG) { System.out.println("Modifiersopt ::= Modifiers"); }  //$NON-NLS-1$
+		    consumeModifiers();  
+			break;
+ 
+    case 470 : if (DEBUG) { System.out.println("BlockStatementsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyBlockStatementsopt();  
+			break;
+ 
+     case 472 : if (DEBUG) { System.out.println("Dimsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyDimsopt();  
+			break;
+ 
+     case 474 : if (DEBUG) { System.out.println("ArgumentListopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyArgumentListopt();  
+			break;
+ 
+    case 478 : if (DEBUG) { System.out.println("FormalParameterListopt ::="); }  //$NON-NLS-1$
+		    consumeFormalParameterListopt();  
+			break;
+ 
+     case 482 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyInterfaceMemberDeclarationsopt();  
+			break;
+ 
+     case 483 : if (DEBUG) { System.out.println("InterfaceMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
+		    consumeInterfaceMemberDeclarationsopt();  
+			break;
+ 
+    case 484 : if (DEBUG) { System.out.println("NestedType ::="); }  //$NON-NLS-1$
+		    consumeNestedType();  
+			break;
+
+     case 485 : if (DEBUG) { System.out.println("ForInitopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyForInitopt();  
+			break;
+ 
+     case 487 : if (DEBUG) { System.out.println("ForUpdateopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyForUpdateopt();  
+			break;
+ 
+     case 491 : if (DEBUG) { System.out.println("Catchesopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyCatchesopt();  
+			break;
+ 
+     case 493 : if (DEBUG) { System.out.println("EnumDeclaration ::= EnumHeader EnumBody"); }  //$NON-NLS-1$
+		    consumeEnumDeclaration();  
+			break;
+ 
+     case 494 : if (DEBUG) { System.out.println("EnumHeader ::= EnumHeaderName ClassHeaderImplementsopt"); }  //$NON-NLS-1$
+		    consumeEnumHeader();  
+			break;
+ 
+     case 495 : if (DEBUG) { System.out.println("EnumHeaderName ::= Modifiersopt enum Identifier"); }  //$NON-NLS-1$
+		    consumeEnumHeaderName();  
+			break;
+ 
+     case 496 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumBodyDeclarationsopt RBRACE"); }  //$NON-NLS-1$
+		    consumeEnumBodyNoConstants();  
+			break;
+ 
+     case 497 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE COMMA EnumBodyDeclarationsopt..."); }  //$NON-NLS-1$
+		    consumeEnumBodyNoConstants();  
+			break;
+ 
+     case 498 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants COMMA..."); }  //$NON-NLS-1$
+		    consumeEnumBodyWithConstants();  
+			break;
+ 
+     case 499 : if (DEBUG) { System.out.println("EnumBody ::= LBRACE EnumConstants..."); }  //$NON-NLS-1$
+		    consumeEnumBodyWithConstants();  
+			break;
+ 
+    case 501 : if (DEBUG) { System.out.println("EnumConstants ::= EnumConstants COMMA EnumConstant"); }  //$NON-NLS-1$
+		    consumeEnumConstants();  
+			break;
+ 
+    case 502 : if (DEBUG) { System.out.println("EnumConstantHeaderName ::= Modifiersopt Identifier"); }  //$NON-NLS-1$
+		    consumeEnumConstantHeaderName();  
+			break;
+ 
+    case 503 : if (DEBUG) { System.out.println("EnumConstantHeader ::= EnumConstantHeaderName..."); }  //$NON-NLS-1$
+		    consumeEnumConstantHeader();  
+			break;
+ 
+    case 504 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader ForceNoDiet..."); }  //$NON-NLS-1$
+		    consumeEnumConstantWithClassBody();  
+			break;
+ 
+    case 505 : if (DEBUG) { System.out.println("EnumConstant ::= EnumConstantHeader"); }  //$NON-NLS-1$
+		    consumeEnumConstantNoClassBody();  
+			break;
+ 
+    case 506 : if (DEBUG) { System.out.println("Arguments ::= LPAREN ArgumentListopt RPAREN"); }  //$NON-NLS-1$
+		    consumeArguments();  
+			break;
+ 
+    case 507 : if (DEBUG) { System.out.println("Argumentsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyArguments();  
+			break;
+ 
+    case 509 : if (DEBUG) { System.out.println("EnumDeclarations ::= SEMICOLON ClassBodyDeclarationsopt"); }  //$NON-NLS-1$
+		    consumeEnumDeclarations();  
+			break;
+ 
+    case 510 : if (DEBUG) { System.out.println("EnumBodyDeclarationsopt ::="); }  //$NON-NLS-1$
+		    consumeEmptyEnumDeclarations();  
+			break;
+ 
+    case 512 : if (DEBUG) { System.out.println("EnhancedForStatement ::= EnhancedForStatementHeader..."); }  //$NON-NLS-1$
+		    consumeEnhancedForStatement();  
+			break;
+ 
+    case 513 : if (DEBUG) { System.out.println("EnhancedForStatementNoShortIf ::=..."); }  //$NON-NLS-1$
+		    consumeEnhancedForStatement();  
+			break;
+ 
+    case 514 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Type..."); }  //$NON-NLS-1$
+		    consumeEnhancedForStatementHeaderInit(false);  
+			break;
+ 
+    case 515 : if (DEBUG) { System.out.println("EnhancedForStatementHeaderInit ::= for LPAREN Modifiers"); }  //$NON-NLS-1$
+		    consumeEnhancedForStatementHeaderInit(true);  
+			break;
+ 
+    case 516 : if (DEBUG) { System.out.println("EnhancedForStatementHeader ::=..."); }  //$NON-NLS-1$
+		    consumeEnhancedForStatementHeader();  
+			break;
+ 
+    case 517 : if (DEBUG) { System.out.println("SingleStaticImportDeclaration ::=..."); }  //$NON-NLS-1$
+		    consumeImportDeclaration();  
+			break;
+ 
+    case 518 : if (DEBUG) { System.out.println("SingleStaticImportDeclarationName ::= import static Name"); }  //$NON-NLS-1$
+		    consumeSingleStaticImportDeclarationName();  
+			break;
+ 
+    case 519 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclaration ::=..."); }  //$NON-NLS-1$
+		    consumeImportDeclaration();  
+			break;
+ 
+    case 520 : if (DEBUG) { System.out.println("StaticImportOnDemandDeclarationName ::= import static..."); }  //$NON-NLS-1$
+		    consumeStaticImportOnDemandDeclarationName();  
+			break;
+ 
+    case 521 : if (DEBUG) { System.out.println("TypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
+		    consumeTypeArguments();  
+			break;
+ 
+    case 522 : if (DEBUG) { System.out.println("OnlyTypeArguments ::= LESS TypeArgumentList1"); }  //$NON-NLS-1$
+		    consumeOnlyTypeArguments();  
+			break;
+ 
+    case 524 : if (DEBUG) { System.out.println("TypeArgumentList1 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
+		    consumeTypeArgumentList1();  
+			break;
+ 
+    case 526 : if (DEBUG) { System.out.println("TypeArgumentList ::= TypeArgumentList COMMA TypeArgument"); }  //$NON-NLS-1$
+		    consumeTypeArgumentList();  
+			break;
+ 
+    case 527 : if (DEBUG) { System.out.println("TypeArgument ::= ReferenceType"); }  //$NON-NLS-1$
+		    consumeTypeArgument();  
+			break;
+ 
+    case 531 : if (DEBUG) { System.out.println("ReferenceType1 ::= ReferenceType GREATER"); }  //$NON-NLS-1$
+		    consumeReferenceType1();  
+			break;
+ 
+    case 532 : if (DEBUG) { System.out.println("ReferenceType1 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
+		    consumeTypeArgumentReferenceType1();  
+			break;
+ 
+    case 534 : if (DEBUG) { System.out.println("TypeArgumentList2 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
+		    consumeTypeArgumentList2();  
+			break;
+ 
+    case 537 : if (DEBUG) { System.out.println("ReferenceType2 ::= ReferenceType RIGHT_SHIFT"); }  //$NON-NLS-1$
+		    consumeReferenceType2();  
+			break;
+ 
+    case 538 : if (DEBUG) { System.out.println("ReferenceType2 ::= ClassOrInterface LESS..."); }  //$NON-NLS-1$
+		    consumeTypeArgumentReferenceType2();  
+			break;
+ 
+    case 540 : if (DEBUG) { System.out.println("TypeArgumentList3 ::= TypeArgumentList COMMA..."); }  //$NON-NLS-1$
+		    consumeTypeArgumentList3();  
+			break;
+ 
+    case 543 : if (DEBUG) { System.out.println("ReferenceType3 ::= ReferenceType UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
+		    consumeReferenceType3();  
+			break;
+ 
+    case 544 : if (DEBUG) { System.out.println("Wildcard ::= QUESTION"); }  //$NON-NLS-1$
+		    consumeWildcard();  
+			break;
+ 
+    case 545 : if (DEBUG) { System.out.println("Wildcard ::= QUESTION WildcardBounds"); }  //$NON-NLS-1$
+		    consumeWildcardWithBounds();  
+			break;
+ 
+    case 546 : if (DEBUG) { System.out.println("WildcardBounds ::= extends ReferenceType"); }  //$NON-NLS-1$
+		    consumeWildcardBoundsExtends();  
+			break;
+ 
+    case 547 : if (DEBUG) { System.out.println("WildcardBounds ::= super ReferenceType"); }  //$NON-NLS-1$
+		    consumeWildcardBoundsSuper();  
+			break;
+ 
+    case 548 : if (DEBUG) { System.out.println("Wildcard1 ::= QUESTION GREATER"); }  //$NON-NLS-1$
+		    consumeWildcard1();  
+			break;
+ 
+    case 549 : if (DEBUG) { System.out.println("Wildcard1 ::= QUESTION WildcardBounds1"); }  //$NON-NLS-1$
+		    consumeWildcard1WithBounds();  
+			break;
+ 
+    case 550 : if (DEBUG) { System.out.println("WildcardBounds1 ::= extends ReferenceType1"); }  //$NON-NLS-1$
+		    consumeWildcardBounds1Extends();  
+			break;
+ 
+    case 551 : if (DEBUG) { System.out.println("WildcardBounds1 ::= super ReferenceType1"); }  //$NON-NLS-1$
+		    consumeWildcardBounds1Super();  
+			break;
+ 
+    case 552 : if (DEBUG) { System.out.println("Wildcard2 ::= QUESTION RIGHT_SHIFT"); }  //$NON-NLS-1$
+		    consumeWildcard2();  
+			break;
+ 
+    case 553 : if (DEBUG) { System.out.println("Wildcard2 ::= QUESTION WildcardBounds2"); }  //$NON-NLS-1$
+		    consumeWildcard2WithBounds();  
+			break;
+ 
+    case 554 : if (DEBUG) { System.out.println("WildcardBounds2 ::= extends ReferenceType2"); }  //$NON-NLS-1$
+		    consumeWildcardBounds2Extends();  
+			break;
+ 
+    case 555 : if (DEBUG) { System.out.println("WildcardBounds2 ::= super ReferenceType2"); }  //$NON-NLS-1$
+		    consumeWildcardBounds2Super();  
+			break;
+ 
+    case 556 : if (DEBUG) { System.out.println("Wildcard3 ::= QUESTION UNSIGNED_RIGHT_SHIFT"); }  //$NON-NLS-1$
+		    consumeWildcard3();  
+			break;
+ 
+    case 557 : if (DEBUG) { System.out.println("Wildcard3 ::= QUESTION WildcardBounds3"); }  //$NON-NLS-1$
+		    consumeWildcard3WithBounds();  
+			break;
+ 
+    case 558 : if (DEBUG) { System.out.println("WildcardBounds3 ::= extends ReferenceType3"); }  //$NON-NLS-1$
+		    consumeWildcardBounds3Extends();  
+			break;
+ 
+    case 559 : if (DEBUG) { System.out.println("WildcardBounds3 ::= super ReferenceType3"); }  //$NON-NLS-1$
+		    consumeWildcardBounds3Super();  
+			break;
+ 
+    case 560 : if (DEBUG) { System.out.println("TypeParameterHeader ::= Identifier"); }  //$NON-NLS-1$
+		    consumeTypeParameterHeader();  
+			break;
+ 
+    case 561 : if (DEBUG) { System.out.println("TypeParameters ::= LESS TypeParameterList1"); }  //$NON-NLS-1$
+		    consumeTypeParameters();  
+			break;
+ 
+    case 563 : if (DEBUG) { System.out.println("TypeParameterList ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
+		    consumeTypeParameterList();  
+			break;
+ 
+    case 565 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+		    consumeTypeParameterWithExtends();  
+			break;
+ 
+    case 566 : if (DEBUG) { System.out.println("TypeParameter ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+		    consumeTypeParameterWithExtendsAndBounds();  
+			break;
+ 
+    case 568 : if (DEBUG) { System.out.println("AdditionalBoundList ::= AdditionalBoundList..."); }  //$NON-NLS-1$
+		    consumeAdditionalBoundList();  
+			break;
+ 
+    case 569 : if (DEBUG) { System.out.println("AdditionalBound ::= AND ReferenceType"); }  //$NON-NLS-1$
+		    consumeAdditionalBound();  
+			break;
+ 
+    case 571 : if (DEBUG) { System.out.println("TypeParameterList1 ::= TypeParameterList COMMA..."); }  //$NON-NLS-1$
+		    consumeTypeParameterList1();  
+			break;
+ 
+    case 572 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader GREATER"); }  //$NON-NLS-1$
+		    consumeTypeParameter1();  
+			break;
+ 
+    case 573 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+		    consumeTypeParameter1WithExtends();  
+			break;
+ 
+    case 574 : if (DEBUG) { System.out.println("TypeParameter1 ::= TypeParameterHeader extends..."); }  //$NON-NLS-1$
+		    consumeTypeParameter1WithExtendsAndBounds();  
+			break;
+ 
+    case 576 : if (DEBUG) { System.out.println("AdditionalBoundList1 ::= AdditionalBoundList..."); }  //$NON-NLS-1$
+		    consumeAdditionalBoundList1();  
+			break;
+ 
+    case 577 : if (DEBUG) { System.out.println("AdditionalBound1 ::= AND ReferenceType1"); }  //$NON-NLS-1$
+		    consumeAdditionalBound1();  
+			break;
+ 
+    case 583 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= PLUS PushPosition..."); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.PLUS);  
+			break;
+ 
+    case 584 : if (DEBUG) { System.out.println("UnaryExpression_NotName ::= MINUS PushPosition..."); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.MINUS);  
+			break;
+ 
+    case 587 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= TWIDDLE..."); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.TWIDDLE);  
+			break;
+ 
+    case 588 : if (DEBUG) { System.out.println("UnaryExpressionNotPlusMinus_NotName ::= NOT PushPosition"); }  //$NON-NLS-1$
+		    consumeUnaryExpression(OperatorIds.NOT);  
+			break;
+ 
+    case 591 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.MULTIPLY);  
+			break;
+ 
+    case 592 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name MULTIPLY..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.MULTIPLY);  
+			break;
+ 
+    case 593 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.DIVIDE);  
+			break;
+ 
+    case 594 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name DIVIDE..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.DIVIDE);  
+			break;
+ 
+    case 595 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.REMAINDER);  
+			break;
+ 
+    case 596 : if (DEBUG) { System.out.println("MultiplicativeExpression_NotName ::= Name REMAINDER..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.REMAINDER);  
+			break;
+ 
+    case 598 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.PLUS);  
+			break;
+ 
+    case 599 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name PLUS..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.PLUS);  
+			break;
+ 
+    case 600 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.MINUS);  
+			break;
+ 
+    case 601 : if (DEBUG) { System.out.println("AdditiveExpression_NotName ::= Name MINUS..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.MINUS);  
+			break;
+ 
+    case 603 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.LEFT_SHIFT);  
+			break;
+ 
+    case 604 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name LEFT_SHIFT..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.LEFT_SHIFT);  
+			break;
+ 
+    case 605 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.RIGHT_SHIFT);  
+			break;
+ 
+    case 606 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name RIGHT_SHIFT..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.RIGHT_SHIFT);  
+			break;
+ 
+    case 607 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= ShiftExpression_NotName..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.UNSIGNED_RIGHT_SHIFT);  
+			break;
+ 
+    case 608 : if (DEBUG) { System.out.println("ShiftExpression_NotName ::= Name UNSIGNED_RIGHT_SHIFT..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.UNSIGNED_RIGHT_SHIFT);  
+			break;
+ 
+    case 610 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.LESS);  
+			break;
+ 
+    case 611 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.LESS);  
+			break;
+ 
+    case 612 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= ShiftExpression_NotName"); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.GREATER);  
+			break;
+ 
+    case 613 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.GREATER);  
+			break;
+ 
+    case 614 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.LESS_EQUAL);  
+			break;
+ 
+    case 615 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name LESS_EQUAL..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.LESS_EQUAL);  
+			break;
+ 
+    case 616 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.GREATER_EQUAL);  
+			break;
+ 
+    case 617 : if (DEBUG) { System.out.println("RelationalExpression_NotName ::= Name GREATER_EQUAL..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.GREATER_EQUAL);  
+			break;
+ 
+    case 619 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::= Name instanceof..."); }  //$NON-NLS-1$
+		    consumeInstanceOfExpressionWithName();  
+			break;
+ 
+    case 620 : if (DEBUG) { System.out.println("InstanceofExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeInstanceOfExpression();  
+			break;
+ 
+    case 622 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeEqualityExpression(OperatorIds.EQUAL_EQUAL);  
+			break;
+ 
+    case 623 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name EQUAL_EQUAL..."); }  //$NON-NLS-1$
+		    consumeEqualityExpressionWithName(OperatorIds.EQUAL_EQUAL);  
+			break;
+ 
+    case 624 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeEqualityExpression(OperatorIds.NOT_EQUAL);  
+			break;
+ 
+    case 625 : if (DEBUG) { System.out.println("EqualityExpression_NotName ::= Name NOT_EQUAL..."); }  //$NON-NLS-1$
+		    consumeEqualityExpressionWithName(OperatorIds.NOT_EQUAL);  
+			break;
+ 
+    case 627 : if (DEBUG) { System.out.println("AndExpression_NotName ::= AndExpression_NotName AND..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.AND);  
+			break;
+ 
+    case 628 : if (DEBUG) { System.out.println("AndExpression_NotName ::= Name AND EqualityExpression"); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.AND);  
+			break;
+ 
+    case 630 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.XOR);  
+			break;
+ 
+    case 631 : if (DEBUG) { System.out.println("ExclusiveOrExpression_NotName ::= Name XOR AndExpression"); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.XOR);  
+			break;
+ 
+    case 633 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.OR);  
+			break;
+ 
+    case 634 : if (DEBUG) { System.out.println("InclusiveOrExpression_NotName ::= Name OR..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.OR);  
+			break;
+ 
+    case 636 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.AND_AND);  
+			break;
+ 
+    case 637 : if (DEBUG) { System.out.println("ConditionalAndExpression_NotName ::= Name AND_AND..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.AND_AND);  
+			break;
+ 
+    case 639 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeBinaryExpression(OperatorIds.OR_OR);  
+			break;
+ 
+    case 640 : if (DEBUG) { System.out.println("ConditionalOrExpression_NotName ::= Name OR_OR..."); }  //$NON-NLS-1$
+		    consumeBinaryExpressionWithName(OperatorIds.OR_OR);  
+			break;
+ 
+    case 642 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::=..."); }  //$NON-NLS-1$
+		    consumeConditionalExpression(OperatorIds.QUESTIONCOLON) ;  
+			break;
+ 
+    case 643 : if (DEBUG) { System.out.println("ConditionalExpression_NotName ::= Name QUESTION..."); }  //$NON-NLS-1$
 		    consumeConditionalExpressionWithName(OperatorIds.QUESTIONCOLON) ;  
 			break;
  
-    case 646 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); }  //$NON-NLS-1$
+    case 647 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= Modifiers AT..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeaderName() ;  
 			break;
  
-    case 647 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); }  //$NON-NLS-1$
+    case 648 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeaderName ::= AT..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeaderName() ;  
 			break;
  
-    case 648 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeader ::=..."); }  //$NON-NLS-1$
+    case 649 : if (DEBUG) { System.out.println("AnnotationTypeDeclarationHeader ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclarationHeader() ;  
 			break;
  
-    case 649 : if (DEBUG) { System.out.println("AnnotationTypeDeclaration ::=..."); }  //$NON-NLS-1$
+    case 650 : if (DEBUG) { System.out.println("AnnotationTypeDeclaration ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeDeclaration() ;  
 			break;
  
-    case 651 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::="); }  //$NON-NLS-1$
+    case 652 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyAnnotationTypeMemberDeclarationsopt() ;  
 			break;
  
-    case 652 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
+    case 653 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarationsopt ::= NestedType..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeMemberDeclarationsopt() ;  
 			break;
  
-    case 654 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarations ::=..."); }  //$NON-NLS-1$
+    case 655 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclarations ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeMemberDeclarations() ;  
 			break;
  
-    case 655 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt..."); }  //$NON-NLS-1$
+    case 656 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt..."); }  //$NON-NLS-1$
 		    consumeMethodHeaderNameWithTypeParameters(true);  
 			break;
  
-    case 656 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+    case 657 : if (DEBUG) { System.out.println("AnnotationMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
 		    consumeMethodHeaderName(true);  
 			break;
  
-    case 657 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::="); }  //$NON-NLS-1$
+    case 658 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyMethodHeaderDefaultValue() ;  
 			break;
  
-    case 658 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::= DefaultValue"); }  //$NON-NLS-1$
+    case 659 : if (DEBUG) { System.out.println("AnnotationMethodHeaderDefaultValueopt ::= DefaultValue"); }  //$NON-NLS-1$
 		    consumeMethodHeaderDefaultValue();  
 			break;
  
-    case 659 : if (DEBUG) { System.out.println("AnnotationMethodHeader ::= AnnotationMethodHeaderName..."); }  //$NON-NLS-1$
+    case 660 : if (DEBUG) { System.out.println("AnnotationMethodHeader ::= AnnotationMethodHeaderName..."); }  //$NON-NLS-1$
 		    consumeMethodHeader();  
 			break;
  
-    case 660 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclaration ::=..."); }  //$NON-NLS-1$
+    case 661 : if (DEBUG) { System.out.println("AnnotationTypeMemberDeclaration ::=..."); }  //$NON-NLS-1$
 		    consumeAnnotationTypeMemberDeclaration() ;  
 			break;
  
-    case 668 : if (DEBUG) { System.out.println("AnnotationName ::= AT Name"); }  //$NON-NLS-1$
+    case 669 : if (DEBUG) { System.out.println("AnnotationName ::= AT Name"); }  //$NON-NLS-1$
 		    consumeAnnotationName() ;  
 			break;
  
-    case 669 : if (DEBUG) { System.out.println("NormalAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
+    case 670 : if (DEBUG) { System.out.println("NormalAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
 		    consumeNormalAnnotation() ;  
 			break;
  
-    case 670 : if (DEBUG) { System.out.println("MemberValuePairsopt ::="); }  //$NON-NLS-1$
+    case 671 : if (DEBUG) { System.out.println("MemberValuePairsopt ::="); }  //$NON-NLS-1$
 		    consumeEmptyMemberValuePairsopt() ;  
 			break;
  
-    case 673 : if (DEBUG) { System.out.println("MemberValuePairs ::= MemberValuePairs COMMA..."); }  //$NON-NLS-1$
+    case 674 : if (DEBUG) { System.out.println("MemberValuePairs ::= MemberValuePairs COMMA..."); }  //$NON-NLS-1$
 		    consumeMemberValuePairs() ;  
 			break;
  
-    case 674 : if (DEBUG) { System.out.println("MemberValuePair ::= SimpleName EQUAL EnterMemberValue..."); }  //$NON-NLS-1$
+    case 675 : if (DEBUG) { System.out.println("MemberValuePair ::= SimpleName EQUAL EnterMemberValue..."); }  //$NON-NLS-1$
 		    consumeMemberValuePair() ;  
 			break;
  
-    case 675 : if (DEBUG) { System.out.println("EnterMemberValue ::="); }  //$NON-NLS-1$
+    case 676 : if (DEBUG) { System.out.println("EnterMemberValue ::="); }  //$NON-NLS-1$
 		    consumeEnterMemberValue() ;  
 			break;
  
-    case 676 : if (DEBUG) { System.out.println("ExitMemberValue ::="); }  //$NON-NLS-1$
+    case 677 : if (DEBUG) { System.out.println("ExitMemberValue ::="); }  //$NON-NLS-1$
 		    consumeExitMemberValue() ;  
 			break;
  
-    case 678 : if (DEBUG) { System.out.println("MemberValue ::= Name"); }  //$NON-NLS-1$
+    case 679 : if (DEBUG) { System.out.println("MemberValue ::= Name"); }  //$NON-NLS-1$
 		    consumeMemberValueAsName() ;  
 			break;
  
-    case 681 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
-		    consumeMemberValueArrayInitializer() ;  
-			break;
- 
     case 682 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
 		    consumeMemberValueArrayInitializer() ;  
 			break;
  
     case 683 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
-		    consumeEmptyMemberValueArrayInitializer() ;  
+		    consumeMemberValueArrayInitializer() ;  
 			break;
  
     case 684 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
 		    consumeEmptyMemberValueArrayInitializer() ;  
 			break;
  
-    case 686 : if (DEBUG) { System.out.println("MemberValues ::= MemberValues COMMA MemberValue"); }  //$NON-NLS-1$
+    case 685 : if (DEBUG) { System.out.println("MemberValueArrayInitializer ::= LBRACE PushLeftBrace..."); }  //$NON-NLS-1$
+		    consumeEmptyMemberValueArrayInitializer() ;  
+			break;
+ 
+    case 687 : if (DEBUG) { System.out.println("MemberValues ::= MemberValues COMMA MemberValue"); }  //$NON-NLS-1$
 		    consumeMemberValues() ;  
 			break;
  
-    case 687 : if (DEBUG) { System.out.println("MarkerAnnotation ::= AnnotationName"); }  //$NON-NLS-1$
+    case 688 : if (DEBUG) { System.out.println("MarkerAnnotation ::= AnnotationName"); }  //$NON-NLS-1$
 		    consumeMarkerAnnotation() ;  
 			break;
  
-    case 688 : if (DEBUG) { System.out.println("SingleMemberAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
+    case 689 : if (DEBUG) { System.out.println("SingleMemberAnnotation ::= AnnotationName LPAREN..."); }  //$NON-NLS-1$
 		    consumeSingleMemberAnnotation() ;  
 			break;
  
-    case 689 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt TypeParameters"); }  //$NON-NLS-1$
+    case 690 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt TypeParameters"); }  //$NON-NLS-1$
 		    consumeRecoveryMethodHeaderNameWithTypeParameters();  
 			break;
  
-    case 690 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
+    case 691 : if (DEBUG) { System.out.println("RecoveryMethodHeaderName ::= Modifiersopt Type..."); }  //$NON-NLS-1$
 		    consumeRecoveryMethodHeaderName();  
 			break;
  
-    case 691 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
+    case 692 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
 		    consumeMethodHeader();  
 			break;
  
-    case 692 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
+    case 693 : if (DEBUG) { System.out.println("RecoveryMethodHeader ::= RecoveryMethodHeaderName..."); }  //$NON-NLS-1$
 		    consumeMethodHeader();  
 			break;
  
@@ -6864,14 +6908,14 @@
 		case TokenNameStringLiteral :
 			StringLiteral stringLiteral;
 			if (this.recordStringLiterals && this.checkExternalizeStrings) {
-				stringLiteral = new StringLiteral(
+				stringLiteral = this.createStringLiteral(
 					this.scanner.getCurrentTokenSourceString(), 
 					this.scanner.startPosition, 
 					this.scanner.currentPosition - 1,
 					this.scanner.getLineNumber(this.scanner.startPosition));
 				this.compilationUnit.recordStringLiteral(stringLiteral);
 			} else {
-				stringLiteral = new StringLiteral(
+				stringLiteral = this.createStringLiteral(
 					this.scanner.getCurrentTokenSourceString(), 
 					this.scanner.startPosition, 
 					this.scanner.currentPosition - 1,
@@ -7422,6 +7466,9 @@
 protected LocalDeclaration createLocalDeclaration(char[] localDeclarationName, int sourceStart, int sourceEnd) {
 	return new LocalDeclaration(localDeclarationName, sourceStart, sourceEnd);
 }
+protected StringLiteral createStringLiteral(char[] token, int start, int end, int lineNumber) {
+	return new StringLiteral(token, start, end, lineNumber);
+}
 protected RecoveredType currentRecoveryType() {
 	if(this.currentElement != null) {
 		if(this.currentElement instanceof RecoveredType) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java b/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
index 6d5124a..7abedb1 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
@@ -16,20 +16,20 @@
 
 	int ERROR_SYMBOL = 110,
 		MAX_NAME_LENGTH = 41,
-		NUM_STATES = 954,
+		NUM_STATES = 955,
 
 		NT_OFFSET = 110,
 		SCOPE_UBOUND = 131,
 		SCOPE_SIZE = 132,
-		LA_STATE_OFFSET = 12754,
+		LA_STATE_OFFSET = 12731,
 		MAX_LA = 1,
-		NUM_RULES = 692,
+		NUM_RULES = 693,
 		NUM_TERMINALS = 110,
-		NUM_NON_TERMINALS = 307,
-		NUM_SYMBOLS = 417,
-		START_STATE = 803,
+		NUM_NON_TERMINALS = 308,
+		NUM_SYMBOLS = 418,
+		START_STATE = 723,
 		EOFT_SYMBOL = 66,
 		EOLT_SYMBOL = 66,
-		ACCEPT_ACTION = 12753,
-		ERROR_ACTION = 12754;
+		ACCEPT_ACTION = 12730,
+		ERROR_ACTION = 12731;
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java b/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
index 458be60..4f300ec 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
@@ -309,6 +309,7 @@
 		}
 		previous = src[i];
 	}
+	boolean containsEmptyTask = false;
 	for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
 		// retrieve message start and end positions
 		int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length;
@@ -337,8 +338,12 @@
 			if (end == -1)
 				end = max_value;
 		}
-		if (msgStart == end)
-			continue; // empty
+		if (msgStart == end) {
+			// if the description is empty, we might want to see if two tags are not sharing the same message
+			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=110797
+			containsEmptyTask = true;
+			continue;
+		}
 		// trim the message
 		while (CharOperation.isWhitespace(src[end]) && msgStart <= end)
 			end--;
@@ -352,6 +357,19 @@
 		System.arraycopy(src, msgStart, message, 0, messageLength);
 		this.foundTaskMessages[i] = message;
 	}
+	if (containsEmptyTask) {
+		for (int i = foundTaskIndex, max = this.foundTaskCount; i < max; i++) {
+			if (this.foundTaskMessages[i].length == 0) {
+				loop: for (int j = i + 1; j < max; j++) {
+					if (this.foundTaskMessages[j].length != 0) {
+						this.foundTaskMessages[i] = this.foundTaskMessages[j];
+						this.foundTaskPositions[i][1] = this.foundTaskPositions[j][1];
+						break loop;
+					}
+				}
+			}
+		}
+	}
 }
 
 public char[] getCurrentIdentifierSource() {
@@ -430,7 +448,7 @@
 		this.startPosition, 
 		this.currentPosition - this.startPosition); 
 }
-public final char[] getCurrentTokenSourceString() {
+public char[] getCurrentTokenSourceString() {
 	//return the token REAL source (aka unicodes are precomputed).
 	//REMOVE the two " that are at the beginning and the end.
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
index ece1322..a09b256 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
index f9ba796..5eab3f6 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
index 2230ac7..9883c17 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
index 87232dc..4ca4d42 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
index 8b49cbf..7de1556 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
index 9fec62f..5b0cc0c 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
index 184209f..5c59af1 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
index 3f70725..e2a1e5c 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
index ad05167..5441c69 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
index 562da1e..9e83aa6 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser21.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
index c7ff194..7c2b3a2 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
index c509727..1108a25 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
index 996b862..c555266 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
index 7b07994..eaab663 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
index 113dc3f..a432a42 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc b/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
index 2e556b6..70ddd33 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
Binary files differ
diff --git a/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.properties b/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.properties
index a5f06a0..737fce4 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.properties
+++ b/compiler/org/eclipse/jdt/internal/compiler/parser/readableNames.properties
@@ -171,6 +171,7 @@
 InternalCompilationUnit=CompilationUnit
 InvalidArrayInitializerAssignement=ArrayInitializerAssignement
 InvalidConstructorDeclaration=InvalidConstructorDeclaration
+Label=Label
 LabeledStatement=LabeledStatement
 LabeledStatementNoShortIf=LabeledStatement
 Literal=Literal
diff --git a/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 8b446c6..6b5d5db 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -1028,6 +1028,14 @@
 		method.sourceStart(),
 		method.sourceEnd());
 }
+public void enumConstantsCannotBeSurroundedByParenthesis(Expression expression) {
+	this.handle(
+		IProblem.EnumConstantsCannotBeSurroundedByParenthesis,
+		NoArgument,
+		NoArgument,
+		expression.sourceStart,
+		expression.sourceEnd);
+}
 public void enumStaticFieldUsedDuringInitialization(FieldBinding field, ASTNode location) {
 	this.handle(
 		IProblem.EnumStaticFieldInInInitializerContext,
@@ -5427,7 +5435,8 @@
 	TypeBinding erasedLeaf = erasedCastType.leafComponentType();
 	int dim = erasedCastType.dimensions();
 	if (erasedLeaf.isGenericType()) {
-		erasedCastType = scope.environment().createRawType((ReferenceBinding)erasedLeaf, erasedLeaf.enclosingType());
+		ReferenceBinding leafEnclosing = scope.environment().convertToParameterizedType(erasedLeaf.enclosingType());
+		erasedCastType = scope.environment().createRawType((ReferenceBinding)erasedLeaf, leafEnclosing);
 		if (dim > 0) erasedCastType = scope.environment().createArrayType(erasedCastType, dim);
 	}	
 	this.handle(
diff --git a/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index 71185e9..33b9477 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -354,6 +354,7 @@
 
 440 = 'assert' should not be used as an identifier, since it is a reserved keyword from source level 1.4 on
 441 = 'enum' should not be used as an identifier, since it is a reserved keyword from source level 5.0 on
+442 = Enum contants cannot be surrounded by parenthesis
 
 450 = {0} {1}
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/util/Util.java b/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
index 0ab2a36..efd6186 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
@@ -17,6 +17,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 import org.eclipse.jdt.core.compiler.CharOperation;
@@ -188,9 +189,14 @@
 	public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding)
 		throws IOException {
 		InputStreamReader reader = null;
-		reader = encoding == null
-					? new InputStreamReader(stream)
-					: new InputStreamReader(stream, encoding);
+		try {
+			reader = encoding == null
+						? new InputStreamReader(stream)
+						: new InputStreamReader(stream, encoding);
+		} catch (UnsupportedEncodingException e) {
+			// encoding is not supported
+			reader =  new InputStreamReader(stream);
+		}
 		char[] contents;
 		if (length == -1) {
 			contents = CharOperation.NO_CHAR;
diff --git a/dom/org/eclipse/jdt/core/dom/ASTParser.java b/dom/org/eclipse/jdt/core/dom/ASTParser.java
index d03b39a..f58c4a1 100644
--- a/dom/org/eclipse/jdt/core/dom/ASTParser.java
+++ b/dom/org/eclipse/jdt/core/dom/ASTParser.java
@@ -372,7 +372,7 @@
 	 * client to retrieve the following pieces of information 
 	 * available there:
 	 * <ul>
-	 * <li>{@linkplain CompilationUnit#lineNumber(int) Line number map}. Line
+	 * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
 	 * numbers start at 1 and only cover the subrange scanned
 	 * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
 	 * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
@@ -849,7 +849,7 @@
 	 * client to retrieve the following pieces of information 
 	 * available there:
 	 * <ul>
-	 * <li>{@linkplain CompilationUnit#lineNumber(int) Line number map}. Line
+	 * <li>{@linkplain CompilationUnit#getLineNumber(int) Line number map}. Line
 	 * numbers start at 1 and only cover the subrange scanned
 	 * (<code>source[offset]</code> through <code>source[offset+length-1]</code>).</li>
 	 * <li>{@linkplain CompilationUnit#getMessages() Compiler messages}
diff --git a/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java b/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java
index f423a29..c2c10c6 100644
--- a/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java
+++ b/dom/org/eclipse/jdt/core/dom/ASTSyntaxErrorPropagator.java
@@ -119,6 +119,27 @@
 	/*
 	 * Method declared on ASTVisitor.
 	 */
+	public boolean visit(AnnotationTypeDeclaration node) {
+		return checkAndTagAsMalformed(node);		
+	}
+	
+	/*
+	 * Method declared on ASTVisitor.
+	 */
+	public boolean visit(EnumDeclaration node) {
+		return checkAndTagAsMalformed(node);		
+	}
+	
+	/*
+	 * Method declared on ASTVisitor.
+	 */
+	public boolean visit(TypeDeclaration node) {
+		return checkAndTagAsMalformed(node);		
+	}
+	
+	/*
+	 * Method declared on ASTVisitor.
+	 */
 	public boolean visit(Initializer node) {
 		return checkAndTagAsMalformed(node);		
 	}
diff --git a/dom/org/eclipse/jdt/core/dom/CompilationUnit.java b/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
index 06c9cc1..7c1523c 100644
--- a/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
+++ b/dom/org/eclipse/jdt/core/dom/CompilationUnit.java
@@ -50,12 +50,14 @@
 public class CompilationUnit extends ASTNode {
 
 	/**
-	 * The "package" structural property of this node type.
-	 * 
-	 * @since 3.0
+	 * Canonical empty list of messages.
 	 */
-	public static final ChildPropertyDescriptor PACKAGE_PROPERTY = 
-		new ChildPropertyDescriptor(CompilationUnit.class, "package", PackageDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
+	private static final Message[] EMPTY_MESSAGES = new Message[0];
+	
+	/**
+	 * Canonical empty list of problems.
+	 */
+	private static final IProblem[] EMPTY_PROBLEMS = new IProblem[0];
 	
 	/**
 	 * The "imports" structural property of this node type.
@@ -66,12 +68,12 @@
 		new ChildListPropertyDescriptor(CompilationUnit.class, "imports", ImportDeclaration.class, NO_CYCLE_RISK); //$NON-NLS-1$
 	
 	/**
-	 * The "types" structural property of this node type.
+	 * The "package" structural property of this node type.
 	 * 
 	 * @since 3.0
 	 */
-	public static final ChildListPropertyDescriptor TYPES_PROPERTY =
-		new ChildListPropertyDescriptor(CompilationUnit.class, "types", AbstractTypeDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+	public static final ChildPropertyDescriptor PACKAGE_PROPERTY = 
+		new ChildPropertyDescriptor(CompilationUnit.class, "package", PackageDeclaration.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
 	
 	/**
 	 * A list of property descriptors (element type: 
@@ -80,7 +82,15 @@
 	 * @since 3.0
 	 */
 	private static final List PROPERTY_DESCRIPTORS;
-	
+
+	/**
+	 * The "types" structural property of this node type.
+	 * 
+	 * @since 3.0
+	 */
+	public static final ChildListPropertyDescriptor TYPES_PROPERTY =
+		new ChildListPropertyDescriptor(CompilationUnit.class, "types", AbstractTypeDeclaration.class, CYCLE_RISK); //$NON-NLS-1$
+			
 	static {
 		List properyList = new ArrayList(4);
 		createPropertyList(CompilationUnit.class, properyList);
@@ -89,7 +99,7 @@
 		addProperty(TYPES_PROPERTY, properyList);
 		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
 	}
-
+	
 	/**
 	 * Returns a list of structural property descriptors for this node type.
 	 * Clients must not modify the result.
@@ -104,71 +114,6 @@
 	public static List propertyDescriptors(int apiLevel) {
 		return PROPERTY_DESCRIPTORS;
 	}
-			
-	/**
-	 * The comment table, or <code>null</code> if none; initially
-	 * <code>null</code>. This array is the storage underlying
-	 * the <code>optionalCommentList</code> ArrayList.
-	 * @since 3.0
-	 */
-	Comment[] optionalCommentTable = null;
-	
-	/**
-	 * The comment list (element type: <code>Comment</code>, 
-	 * or <code>null</code> if none; initially <code>null</code>.
-	 * @since 3.0
-	 */
-	private List optionalCommentList = null;
-	
-	/**
-	 * The package declaration, or <code>null</code> if none; initially
-	 * <code>null</code>.
-	 */
-	private PackageDeclaration optionalPackageDeclaration = null;
-	
-	/**
-	 * The list of import declarations in textual order order; 
-	 * initially none (elementType: <code>ImportDeclaration</code>).
-	 */
-	private ASTNode.NodeList imports =
-		new ASTNode.NodeList(IMPORTS_PROPERTY);
-	
-	/**
-	 * The list of type declarations in textual order order; 
-	 * initially none (elementType: <code>AbstractTypeDeclaration</code>)
-	 */
-	private ASTNode.NodeList types =
-		new ASTNode.NodeList(TYPES_PROPERTY);
-	
-	/**
-	 * Line end table. If <code>lineEndTable[i] == p</code> then the
-	 * line number <code>i+1</code> ends at character position 
-	 * <code>p</code>. Except for the last line, the positions are that
-	 * of the last character of the line delimiter. 
-	 * For example, the source string <code>A\nB\nC</code> has
-	 * line end table {1, 3} (if \n is one character).
-	 */
-	private int[] lineEndTable = new int[0];
-
-	/**
-	 * Canonical empty list of messages.
-	 */
-	private static final Message[] EMPTY_MESSAGES = new Message[0];
-
-	/**
-	 * Canonical empty list of problems.
-	 */
-	private static final IProblem[] EMPTY_PROBLEMS = new IProblem[0];
-
-	/**
-	 * Messages reported by the compiler during parsing or name resolution.
-	 */
-	private Message[] messages;
-	
-	/**
-	 * Problems reported by the compiler during parsing or name resolution.
-	 */
-	private IProblem[] problems = EMPTY_PROBLEMS;
 	
 	/**
 	 * The comment mapper, or <code>null</code> if none; 
@@ -185,26 +130,61 @@
 	private IJavaElement element = null;
 	
 	/**
-	 * Sets the line end table for this compilation unit.
-	 * If <code>lineEndTable[i] == p</code> then line number <code>i+1</code> 
-	 * ends at character position <code>p</code>. Except for the last line, the 
-	 * positions are that of (the last character of) the line delimiter.
-	 * For example, the source string <code>A\nB\nC</code> has
-	 * line end table {1, 3, 4}.
-	 * 
-	 * @param lineEndTable the line end table
+	 * The list of import declarations in textual order order; 
+	 * initially none (elementType: <code>ImportDeclaration</code>).
 	 */
-	void setLineEndTable(int[] lineEndTable) {
-		if (lineEndTable == null) {
-			throw new NullPointerException();
-		}
-		// alternate root is *not* considered a structural property
-		// but we protect them nevertheless
-		checkModifiable();
-		this.lineEndTable = lineEndTable;
-	}
+	private ASTNode.NodeList imports =
+		new ASTNode.NodeList(IMPORTS_PROPERTY);
+	
+	/**
+	 * Line end table. If <code>lineEndTable[i] == p</code> then the
+	 * line number <code>i+1</code> ends at character position 
+	 * <code>p</code>. Except for the last line, the positions are that
+	 * of the last character of the line delimiter. 
+	 * For example, the source string <code>A\nB\nC</code> has
+	 * line end table {1, 3} (if \n is one character).
+	 */
+	private int[] lineEndTable = new int[0];
 
 	/**
+	 * Messages reported by the compiler during parsing or name resolution.
+	 */
+	private Message[] messages;
+
+	/**
+	 * The comment list (element type: <code>Comment</code>, 
+	 * or <code>null</code> if none; initially <code>null</code>.
+	 * @since 3.0
+	 */
+	private List optionalCommentList = null;
+
+	/**
+	 * The comment table, or <code>null</code> if none; initially
+	 * <code>null</code>. This array is the storage underlying
+	 * the <code>optionalCommentList</code> ArrayList.
+	 * @since 3.0
+	 */
+	Comment[] optionalCommentTable = null;
+	
+	/**
+	 * The package declaration, or <code>null</code> if none; initially
+	 * <code>null</code>.
+	 */
+	private PackageDeclaration optionalPackageDeclaration = null;
+	
+	/**
+	 * Problems reported by the compiler during parsing or name resolution.
+	 */
+	private IProblem[] problems = EMPTY_PROBLEMS;
+	
+	/**
+	 * The list of type declarations in textual order order; 
+	 * initially none (elementType: <code>AbstractTypeDeclaration</code>)
+	 */
+	private ASTNode.NodeList types =
+		new ASTNode.NodeList(TYPES_PROPERTY);
+	
+	/**
 	 * Creates a new AST node for a compilation owned by the given AST.
 	 * The compilation unit initially has no package declaration, no
 	 * import declarations, and no type declarations.
@@ -222,47 +202,16 @@
 
 	/* (omit javadoc for this method)
 	 * Method declared on ASTNode.
-	 * @since 3.0
 	 */
-	final List internalStructuralPropertiesForType(int apiLevel) {
-		return propertyDescriptors(apiLevel);
-	}
-	
-	/* (omit javadoc for this method)
-	 * Method declared on ASTNode.
-	 */
-	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
-		if (property == PACKAGE_PROPERTY) {
-			if (get) {
-				return getPackage();
-			} else {
-				setPackage((PackageDeclaration) child);
-				return null;
-			}
+	void accept0(ASTVisitor visitor) {
+		boolean visitChildren = visitor.visit(this);
+		if (visitChildren) {
+			// visit children in normal left to right reading order
+			acceptChild(visitor, getPackage());
+			acceptChildren(visitor, this.imports);
+			acceptChildren(visitor, this.types);
 		}
-		// allow default implementation to flag the error
-		return super.internalGetSetChildProperty(property, get, child);
-	}
-	
-	/* (omit javadoc for this method)
-	 * Method declared on ASTNode.
-	 */
-	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
-		if (property == IMPORTS_PROPERTY) {
-			return imports();
-		}
-		if (property == TYPES_PROPERTY) {
-			return types();
-		}
-		// allow default implementation to flag the error
-		return super.internalGetChildListProperty(property);
-	}
-	
-	/* (omit javadoc for this method)
-	 * Method declared on ASTNode.
-	 */
-	final int getNodeType0() {
-		return COMPILATION_UNIT;
+		visitor.endVisit(this);
 	}
 
 	/* (omit javadoc for this method)
@@ -278,88 +227,49 @@
 		result.types().addAll(ASTNode.copySubtrees(target, types()));
 		return result;
 	}
-
-	/* (omit javadoc for this method)
-	 * Method declared on ASTNode.
+	
+	
+	/**
+	 * Returns the column number corresponding to the given source character
+	 * position in the original source string. Column number are zero-based. 
+	 * Return <code>-1</code> if it is beyond the valid range or <code>-2</code>
+	 * if the column number information is unknown.
+	 * 
+	 * @param position a 0-based character position, possibly
+	 *   negative or out of range
+	 * @return the 0-based column number, or <code>-1</code> if the character
+	 *    position does not correspond to a source line in the original
+	 *    source file or <code>-2</code> if column number information is unknown for this
+	 *    compilation unit
+	 * @see ASTParser
+	 * @since 3.2
 	 */
-	final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
-		// dispatch to correct overloaded match method
-		return matcher.match(this, other);
-	}
-
-	/* (omit javadoc for this method)
-	 * Method declared on ASTNode.
-	 */
-	void accept0(ASTVisitor visitor) {
-		boolean visitChildren = visitor.visit(this);
-		if (visitChildren) {
-			// visit children in normal left to right reading order
-			acceptChild(visitor, getPackage());
-			acceptChildren(visitor, this.imports);
-			acceptChildren(visitor, this.types);
+	public int getColumnNumber(final int position) {
+		if (this.lineEndTable == null) return -2;
+		final int line = getLineNumber(position);
+		if (line == -1) {
+			return -1;
 		}
-		visitor.endVisit(this);
+		if (line == 1) {
+			if (position >= getStartPosition() + getLength()) return -1;
+			return position;
+		}
+		// length is different from 0
+		int length = this.lineEndTable.length;
+		// -1 to for one-based to zero-based conversion.
+		// -1, again, to get previous line.
+		final int previousLineOffset = this.lineEndTable[line - 2];
+		 // previousLineOffset + 1 is the first character of the current line
+		final int offsetForLine = previousLineOffset + 1;
+		final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 :	this.lineEndTable[line - 1];
+		if (offsetForLine > currentLineEnd) {
+			return -1;
+		} else {
+			return position - offsetForLine;
+		}
 	}
 	
 	/**
-	 * Returns the node for the package declaration of this compilation 
-	 * unit, or <code>null</code> if this compilation unit is in the 
-	 * default package.
-	 * 
-	 * @return the package declaration node, or <code>null</code> if none
-	 */ 
-	public PackageDeclaration getPackage() {
-		return this.optionalPackageDeclaration;
-	}
-	
-	/**
-	 * Sets or clears the package declaration of this compilation unit 
-	 * node to the given package declaration node.
-	 * 
-	 * @param pkgDecl the new package declaration node, or 
-	 *   <code>null</code> if this compilation unit does not have a package
-	 *   declaration (that is in the default package)
-	 * @exception IllegalArgumentException if:
-	 * <ul>
-	 * <li>the node belongs to a different AST</li>
-	 * <li>the node already has a parent</li>
-	 * </ul>
-	 */ 
-	public void setPackage(PackageDeclaration pkgDecl) {
-		ASTNode oldChild = this.optionalPackageDeclaration;
-		preReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
-		this.optionalPackageDeclaration = pkgDecl;
-		postReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
-	}
-
-	/**
-	 * 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
-	 *    (elementType: <code>ImportDeclaration</code>)
-	 */ 
-	public List imports() {
-		return this.imports;
-	}
-	
-	/**
-	 * Returns the live list of nodes for the top-level type declarations of this 
-	 * compilation unit, in order of appearance.
-     * <p>
-     * Note that in JLS3, the types may include both enum declarations
-     * and annotation type declarations introduced in J2SE 5.
-     * For JLS2, the elements are always <code>TypeDeclaration</code>.
-     * </p>
-	 * 
-	 * @return the live list of top-level type declaration
-	 *    nodes (elementType: <code>AbstractTypeDeclaration</code>)
-	 */ 
-	public List types() {
-		return this.types;
-	}
-
-	/**
 	 * Finds the corresponding AST node in the given compilation unit from 
 	 * which the given binding originated. Returns <code>null</code> if the
 	 * binding does not correspond to any node in this compilation unit.
@@ -429,7 +339,7 @@
 	public ASTNode findDeclaringNode(IResolvedAnnotation resolvedAnnotation) {
 		return this.ast.getBindingResolver().findDeclaringNode(resolvedAnnotation);
 	}
-
+	
 	/**
 	 * Finds the corresponding AST node in the given compilation unit from 
 	 * which the binding with the given key originated. Returns
@@ -480,6 +390,57 @@
 	}
 	
 	/**
+	 * Returns a list of the comments encountered while parsing
+	 * this compilation unit.
+	 * <p>
+	 * Since the Java language allows comments to appear most anywhere
+	 * in the source text, it is problematic to locate comments in relation
+	 * to the structure of an AST. The one exception is doc comments 
+	 * which, by convention, immediately precede type, field, and
+	 * method declarations; these comments are located in the AST
+	 * by {@link  BodyDeclaration#getJavadoc BodyDeclaration.getJavadoc}.
+	 * Other comments do not show up in the AST. The table of comments
+	 * is provided for clients that need to find the source ranges of
+	 * all comments in the original source string. It includes entries
+	 * for comments of all kinds (line, block, and doc), arranged in order
+	 * of increasing source position. 
+	 * </p>
+	 * Note on comment parenting: The {@link ASTNode#getParent() getParent()}
+	 * of a doc comment associated with a body declaration is the body
+	 * declaration node; for these comment nodes
+	 * {@link ASTNode#getRoot() getRoot()} will return the compilation unit
+	 * (assuming an unmodified AST) reflecting the fact that these nodes
+	 * are property located in the AST for the compilation unit.
+	 * However, for other comment nodes, {@link ASTNode#getParent() getParent()}
+	 * will return <code>null</code>, and {@link ASTNode#getRoot() getRoot()}
+	 * will return the comment node itself, indicating that these comment nodes
+	 * are not directly connected to the AST for the compilation unit. The 
+	 * {@link Comment#getAlternateRoot Comment.getAlternateRoot}
+	 * method provides a way to navigate from a comment to its compilation
+	 * unit.
+	 * </p>
+	 * <p>
+	 * A note on visitors: The only comment nodes that will be visited when
+	 * visiting a compilation unit are the doc comments parented by body
+	 * declarations. To visit all comments in normal reading order, iterate
+	 * over the comment table and call {@link ASTNode#accept(ASTVisitor) accept}
+	 * on each element.
+	 * </p>
+	 * <p>
+	 * Clients cannot modify the resulting list.
+	 * </p>
+	 * 
+	 * @return an unmodifiable list of comments in increasing order of source
+	 * start position, or <code>null</code> if comment information
+	 * for this compilation unit is not available
+	 * @see ASTParser
+	 * @since 3.0
+	 */
+	public List getCommentList() {
+		return this.optionalCommentList;
+	}
+
+	/**
 	 * Returns the internal comment mapper.
 	 * 
 	 * @return the comment mapper, or <code>null</code> if none.
@@ -490,42 +451,6 @@
 	}
 
 	/**
-	 * Initializes the internal comment mapper with the given
-	 * scanner.
-	 * 
-	 * @param scanner the scanner
-	 * @since 3.0
-	 */
-	void initCommentMapper(Scanner scanner) {
-		this.commentMapper = new DefaultCommentMapper(this.optionalCommentTable);
-		this.commentMapper.initialize(this, scanner);
-	}
-
-	/**
-	 * Returns the extended start position of the given node. Unlike
-	 * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
-	 * the extended source range may include comments and whitespace
-	 * immediately before or after the normal source range for the node.
-	 * 
-	 * @param node the node
-	 * @return the 0-based character index, or <code>-1</code>
-	 *    if no source position information is recorded for this node
-	 * @see #getExtendedLength(ASTNode)
-	 * @since 3.0
-	 */
-	public int getExtendedStartPosition(ASTNode node) {
-		if (node == null) {
-			throw new IllegalArgumentException();
-		}
-		if (this.commentMapper == null || node.getAST() != getAST()) {
-			// fall back: use best info available
-			return node.getStartPosition();
-		} else {
-			return this.commentMapper.getExtendedStartPosition(node);
-		}
-	}
-
-	/**
 	 * Returns the extended source length of the given node. Unlike
 	 * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
 	 * the extended source range may include comments and whitespace
@@ -548,6 +473,256 @@
 			return this.commentMapper.getExtendedLength(node);
 		}
 	}
+
+	/**
+	 * Returns the extended start position of the given node. Unlike
+	 * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
+	 * the extended source range may include comments and whitespace
+	 * immediately before or after the normal source range for the node.
+	 * 
+	 * @param node the node
+	 * @return the 0-based character index, or <code>-1</code>
+	 *    if no source position information is recorded for this node
+	 * @see #getExtendedLength(ASTNode)
+	 * @since 3.0
+	 */
+	public int getExtendedStartPosition(ASTNode node) {
+		if (node == null) {
+			throw new IllegalArgumentException();
+		}
+		if (this.commentMapper == null || node.getAST() != getAST()) {
+			// fall back: use best info available
+			return node.getStartPosition();
+		} else {
+			return this.commentMapper.getExtendedStartPosition(node);
+		}
+	}
+	
+	/**
+	 * The Java element (an <code>org.eclipse.jdt.core.ICompilationUnit</code> or an <code>org.eclipse.jdt.core.IClassFile</code>) 
+	 * this compilation unit was created from, or <code>null</code> if it was not created from a Java element.
+	 * 
+	 * @return the Java element this compilation unit was created from, or <code>null</code> if none
+	 * @since 3.1
+	 */
+	public IJavaElement getJavaElement() {
+		return this.element;
+	}
+	
+	/**
+	 * Returns the list of messages reported by the compiler during the parsing 
+	 * or the type checking of this compilation unit. This list might be a subset of 
+	 * errors detected and reported by a Java compiler.
+	 * <p>
+	 * This list of messages is suitable for simple clients that do little
+	 * more than log the messages or display them to the user. Clients that
+	 * need further details should call <code>getProblems</code> to get
+	 * compiler problem objects.
+	 * </p>
+	 *
+	 * @return the list of messages, possibly empty
+	 * @see #getProblems()
+	 * @see ASTParser
+	 */
+	public Message[] getMessages() {
+		if (this.messages == null) {
+			int problemLength = this.problems.length;
+			if (problemLength == 0) {
+				this.messages = EMPTY_MESSAGES;
+			} else {
+				this.messages = new Message[problemLength];
+				for (int i = 0; i < problemLength; i++) {
+					IProblem problem = this.problems[i];
+					int start = problem.getSourceStart();
+					int end = problem.getSourceEnd();
+					messages[i] = new Message(problem.getMessage(), start, end - start + 1);
+				}
+			}
+		}
+		return this.messages;
+	}
+
+	/* (omit javadoc for this method)
+	 * Method declared on ASTNode.
+	 */
+	final int getNodeType0() {
+		return COMPILATION_UNIT;
+	}
+	
+	/**
+	 * Returns the node for the package declaration of this compilation 
+	 * unit, or <code>null</code> if this compilation unit is in the 
+	 * default package.
+	 * 
+	 * @return the package declaration node, or <code>null</code> if none
+	 */ 
+	public PackageDeclaration getPackage() {
+		return this.optionalPackageDeclaration;
+	}
+	
+	/**
+	 * Given a line number and column number, returns the corresponding 
+	 * position in the original source string.
+	 * Returns -2 if no line number information is available for this
+	 * compilation unit. 
+	 * Returns the total size of the source string if <code>line</code>
+	 * is greater than the actual number lines in the unit.
+	 * Returns -1 if <code>column</code> is less than 0,  
+	 * or the position of the last character of the line if <code>column</code>
+	 * is beyond the legal range, or the given line number is less than one. 
+	 * 
+	 * @param line the one-based line number
+	 * @param column the zero-based column number
+	 * @return the 0-based character position in the source string; 
+	 * <code>-2</code> if line/column number information is not known 
+	 * for this compilation unit or <code>-1</code> the inputs are not valid
+	 * @since 3.2
+	 */
+	 public int getPosition(int line, int column) {
+		if (this.lineEndTable == null) return -2;
+		if (line < 1 || column < 0) return -1;
+		int length;
+		if ((length = this.lineEndTable.length) == 0) {
+			if (line != 1) return -1;
+			return column >= getStartPosition() + getLength() ? -1 : column;
+		}
+		if (line == 1) {
+			final int endOfLine = this.lineEndTable[0];
+			return column > endOfLine ? -1 : column;			
+		} else if( line > length + 1 ) {
+			// greater than the number of lines in the source string.
+			return -1;
+		}		
+		// -1 to for one-based to zero-based conversion.
+		// -1, again, to get previous line.
+		final int previousLineOffset = this.lineEndTable[line - 2];
+		 // previousLineOffset + 1 is the first character of the current line
+		final int offsetForLine = previousLineOffset + 1;
+		final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 : this.lineEndTable[line-1];
+		if ((offsetForLine + column) > currentLineEnd) {  
+			return -1;
+		} else {  
+			return offsetForLine + column;
+		}
+	}
+
+	/**
+	 * Returns the list of detailed problem reports noted by the compiler
+	 * during the parsing or the type checking of this compilation unit. This
+	 * list might be a subset of errors detected and reported by a Java
+	 * compiler.
+	 * <p>
+	 * Simple clients that do little more than log the messages or display
+	 * them to the user should probably call <code>getMessages</code> instead.
+	 * </p>
+	 * 
+	 * @return the list of detailed problem objects, possibly empty
+	 * @see #getMessages()
+	 * @see ASTParser
+	 * @since 2.1
+	 */
+	public IProblem[] getProblems() {
+		return this.problems;
+	}
+
+	/**
+	 * 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
+	 *    (elementType: <code>ImportDeclaration</code>)
+	 */ 
+	public List imports() {
+		return this.imports;
+	}
+
+	/**
+	 * Return the index in the whole comments list {@link #getCommentList() }
+	 * of the first leading comments associated with the given node. 
+	 * 
+	 * @param node the node
+	 * @return 0-based index of first leading comment or -1 if node has no associated
+	 * 	comment before its start position.
+	 * @since 3.2
+	 */
+	public int firstLeadingCommentIndex(ASTNode node) {
+		if (node == null) {
+			throw new IllegalArgumentException();
+		}
+		if (this.commentMapper == null || node.getAST() != getAST()) {
+			return -1;
+		}
+		return this.commentMapper.firstLeadingCommentIndex(node);
+	}
+
+	/**
+	 * Return the index in the whole comments list {@link #getCommentList() }
+	 * of the last trailing comments associated with the given node. 
+	 * 
+	 * @param node the node
+	 * @return 0-based index of last trailing comment or -1 if node has no
+	 * 	associated comment after its end position.
+	 * @since 3.2
+	 */
+	public int lastTrailingCommentIndex(ASTNode node) {
+		if (node == null) {
+			throw new IllegalArgumentException();
+		}
+		if (this.commentMapper == null || node.getAST() != getAST()) {
+			return -1;
+		}
+		return this.commentMapper.lastTrailingCommentIndex(node);
+	}
+	
+	/**
+	 * Initializes the internal comment mapper with the given
+	 * scanner.
+	 * 
+	 * @param scanner the scanner
+	 * @since 3.0
+	 */
+	void initCommentMapper(Scanner scanner) {
+		this.commentMapper = new DefaultCommentMapper(this.optionalCommentTable);
+		this.commentMapper.initialize(this, scanner);
+	}
+
+	/* (omit javadoc for this method)
+	 * Method declared on ASTNode.
+	 */
+	final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+		if (property == IMPORTS_PROPERTY) {
+			return imports();
+		}
+		if (property == TYPES_PROPERTY) {
+			return types();
+		}
+		// allow default implementation to flag the error
+		return super.internalGetChildListProperty(property);
+	}
+
+	/* (omit javadoc for this method)
+	 * Method declared on ASTNode.
+	 */
+	final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+		if (property == PACKAGE_PROPERTY) {
+			if (get) {
+				return getPackage();
+			} else {
+				setPackage((PackageDeclaration) child);
+				return null;
+			}
+		}
+		// allow default implementation to flag the error
+		return super.internalGetSetChildProperty(property, get, child);
+	}
+
+	/* (omit javadoc for this method)
+	 * Method declared on ASTNode.
+	 * @since 3.0
+	 */
+	final List internalStructuralPropertiesForType(int apiLevel) {
+		return propertyDescriptors(apiLevel);
+	}
 		
 	/**
 	 * Returns the line number corresponding to the given source character
@@ -567,60 +742,13 @@
 	 *    position does not correspond to a source line in the original
 	 *    source file or if line number information is not known for this
 	 *    compilation unit
+	 * @deprecated Use getLineNumber(int) instead. Be careful to handle the negative values.
 	 * @see ASTParser
-	 * @deprecated Use getLineNumber(int) instead. Be careful to check the negative returned value
+	 * @see #getLineNumber(int) 
 	 */
 	public int lineNumber(int position) {
-		if (this.lineEndTable == null) return 1;
-		int length = this.lineEndTable.length;
-		if (length == 0) {
-			// no line number info
-			return 1;
-		}
-		int low = 0;
-		if (position <= this.lineEndTable[low]) {
-			// position illegal or before the first line delimiter
-			return 1;
-		}
-		// assert position > lineEndTable[low+1]  && low == 0
-		int hi = length - 1;
-		if (position > this.lineEndTable[hi]) {
-			// position beyond the last line separator
-			if (position >= getStartPosition() + getLength()) {
-				// this is beyond the end of the source length
-				return 1;
-			} else {
-				return length + 1;
-			}
-		}
-		// assert lineEndTable[low]  < position <= lineEndTable[hi]
-		// && low == 0 && hi == length - 1 && low < hi
-		
-		// binary search line end table
-		while (true) {
-			// invariant lineEndTable[low] < position <= lineEndTable[hi]
-			// && 0 <= low < hi <= length - 1
-			// reducing measure hi - low
-			if (low + 1 == hi) {
-				// assert lineEndTable[low] < position <= lineEndTable[low+1]
-				// position is on line low+1 (line number is low+2)
-				return low + 2;
-			}
-			// assert hi - low >= 2, so average is truly in between
-			int mid = (low + hi) / 2;
-			// assert 0 <= low < mid < hi <= length - 1
-			if (position <= this.lineEndTable[mid]) {
-				// assert lineEndTable[low] < position <= lineEndTable[mid]
-				// && 0 <= low < mid < hi <= length - 1
-				hi = mid;
-			} else {
-				// position > lineEndTable[mid]
-				// assert lineEndTable[mid] < position <= lineEndTable[hi]
-				// && 0 <= low < mid < hi <= length - 1
-				low = mid;
-			}
-			// in both cases, invariant reachieved with reduced measure
-		}
+		int lineNumber = getLineNumber(position);
+		return lineNumber < 1 ? 1 : lineNumber;
 	}
 	
 	/**
@@ -642,6 +770,7 @@
 	 *    source file or <code>-2</code> if line number information is not known for this
 	 *    compilation unit
 	 * @see ASTParser
+	 * @since 3.2
 	 */
 	public int getLineNumber(int position) {
 		if (this.lineEndTable == null) return -2;
@@ -701,257 +830,82 @@
 			// in both cases, invariant reachieved with reduced measure
 		}
 	}
-	
-	/**
-	 * Returns the column number corresponding to the given source character
-	 * position in the original source string. Column number are zero-based. 
-	 * Return zero if it is beyond the valid range.
-	 * 
-	 * @param position a 0-based character position, possibly
-	 *   negative or out of range
-	 * @return the 0-based coloumn number, or <code>0</code> if the character
-	 *    position does not correspond to a source line in the original
-	 *    source file or if column number information is not known for this
-	 *    compilation unit
-	 * @see ASTParser
-	 * @deprecated Use getColumnNumber(int) instead. Be careful to check the negative returned values.
-	 * @since 3.2
-	 */
-	public int columnNumber(final int position) {
-		final int line = lineNumber(position);
-		if (this.lineEndTable == null) return 0;
-		final int length = this.lineEndTable.length;
-		if (line == 1) {
-			if (length == 0 || position >= getStartPosition() + getLength())
-				return 0;
-			return position;
-		}
-		// -1 to for one-based to zero-based conversion.
-		// -1, again, to get previous line.
-		final int previousLineOffset = this.lineEndTable[line - 2];
-		 // previousLineOffset + 1 is the first character of the current line
-		final int offsetForLine = previousLineOffset + 1;
-		final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 :	this.lineEndTable[line - 1];
-		if (offsetForLine > currentLineEnd) {
-			return 0;
-		} else {
-			return position - offsetForLine;
-		}
-	}
-	
-	/**
-	 * Given a line number and column number, returns the corresponding 
-	 * position in the original source string.
-	 * Returns -2 if no line number information is available for this
-	 * compilation unit. 
-	 * Returns the total size of the source string if <code>line</code>
-	 * is greater than the actual number lines in the unit.
-	 * Returns -1 if <code>column</code> is less than 0,  
-	 * or the position of the last character of the line if <code>column</code>
-	 * is beyond the legal range, or the given line number is less than one. 
-	 * 
-	 * @param line the one-based line number
-	 * @param column the zero-based column number
-	 * @return the 0-based character position in the source string; 
-	 * <code>-2</code> if line/column number information is not known 
-	 * for this compilation unit or <code>-1</code> the inputs are not valid
-	 * @since 3.2
-	 */
-	 public int getPosition(int line, int column) {
-		if (this.lineEndTable == null) return -2;
-		if (line < 1 || column < 0) return -1;
-		int length;
-		if ((length = this.lineEndTable.length) == 0) {
-			if (line != 1) return -1;
-			return column >= getStartPosition() + getLength() ? -1 : column;
-		}
-		if (line == 1) {
-			final int endOfLine = this.lineEndTable[0];
-			return column > endOfLine ? -1 : column;			
-		} else if( line > length + 1 ) {
-			// greater than the number of lines in the source string.
-			return -1;
-		}		
-		// -1 to for one-based to zero-based conversion.
-		// -1, again, to get previous line.
-		final int previousLineOffset = this.lineEndTable[line - 2];
-		 // previousLineOffset + 1 is the first character of the current line
-		final int offsetForLine = previousLineOffset + 1;
-		final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 : this.lineEndTable[line-1];
-		if ((offsetForLine + column) > currentLineEnd) {  
-			return -1;
-		} else {  
-			return offsetForLine + column;
-		}
-	}
 
-	/**
-	 * The Java element (an <code>org.eclipse.jdt.core.ICompilationUnit</code> or an <code>org.eclipse.jdt.core.IClassFile</code>) 
-	 * this compilation unit was created from, or <code>null</code> if it was not created from a Java element.
-	 * 
-	 * @return the Java element this compilation unit was created from, or <code>null</code> if none
-	 * @since 3.1
+	/* (omit javadoc for this method)
+	 * Method declared on ASTNode.
 	 */
-	public IJavaElement getJavaElement() {
-		return this.element;
+	int memSize() {
+		int size = BASE_NODE_SIZE + 8 * 4;
+		if (this.lineEndTable != null) {
+			size += HEADERS + 4 * this.lineEndTable.length;
+		}
+		if (this.optionalCommentTable != null) {
+			size += HEADERS + 4 * this.optionalCommentTable.length;
+		}
+		// ignore the space taken up by optionalCommentList
+		return size;
 	}
 	
 	/**
-	 * Returns the list of messages reported by the compiler during the parsing 
-	 * or the type checking of this compilation unit. This list might be a subset of 
-	 * errors detected and reported by a Java compiler.
-	 * <p>
-	 * This list of messages is suitable for simple clients that do little
-	 * more than log the messages or display them to the user. Clients that
-	 * need further details should call <code>getProblems</code> to get
-	 * compiler problem objects.
-	 * </p>
+	 * Enables the recording of changes to this compilation
+	 * unit and its descendents. The compilation unit must have
+	 * been created by <code>ASTParser</code> and still be in
+	 * its original state. Once recording is on,
+	 * arbitrary changes to the subtree rooted at this compilation
+	 * unit are recorded internally. Once the modification has
+	 * been completed, call <code>rewrite</code> to get an object
+	 * representing the corresponding edits to the original 
+	 * source code string.
 	 *
-	 * @return the list of messages, possibly empty
-	 * @see #getProblems()
-	 * @see ASTParser
-	 */
-	public Message[] getMessages() {
-		if (this.messages == null) {
-			int problemLength = this.problems.length;
-			if (problemLength == 0) {
-				this.messages = EMPTY_MESSAGES;
-			} else {
-				this.messages = new Message[problemLength];
-				for (int i = 0; i < problemLength; i++) {
-					IProblem problem = this.problems[i];
-					int start = problem.getSourceStart();
-					int end = problem.getSourceEnd();
-					messages[i] = new Message(problem.getMessage(), start, end - start + 1);
-				}
-			}
-		}
-		return this.messages;
-	}
-
-	/**
-	 * Returns the list of detailed problem reports noted by the compiler
-	 * during the parsing or the type checking of this compilation unit. This
-	 * list might be a subset of errors detected and reported by a Java
-	 * compiler.
-	 * <p>
-	 * Simple clients that do little more than log the messages or display
-	 * them to the user should probably call <code>getMessages</code> instead.
-	 * </p>
-	 * 
-	 * @return the list of detailed problem objects, possibly empty
-	 * @see #getMessages()
-	 * @see ASTParser
-	 * @since 2.1
-	 */
-	public IProblem[] getProblems() {
-		return this.problems;
-	}
-
-	/**
-	 * Sets the array of problems reported by the compiler during the parsing or
-	 * name resolution of this compilation unit.
-	 * 
-	 * @param problems the list of problems
-	 */
-	void setProblems(IProblem[] problems) {
-		if (problems == null) {
-			throw new IllegalArgumentException();
-		}
-		this.problems = problems;
-	}
-		
-	/**
-	 * Returns the column number corresponding to the given source character
-	 * position in the original source string. Column number are zero-based. 
-	 * Return <code>-1</code> if it is beyond the valid range or <code>-2</code>
-	 * if the column number information is unknown.
-	 * 
-	 * @param position a 0-based character position, possibly
-	 *   negative or out of range
-	 * @return the 0-based column number, or <code>-1</code> if the character
-	 *    position does not correspond to a source line in the original
-	 *    source file or <code>-2</code> if column number information is unknown for this
-	 *    compilation unit
-	 * @see ASTParser
-	 * @since 3.2
-	 */
-	public int getColumnNumber(final int position) {
-		if (this.lineEndTable == null) return -2;
-		final int line = getLineNumber(position);
-		if (line == -1) {
-			return -1;
-		}
-		if (line == 1) {
-			if (position >= getStartPosition() + getLength()) return -1;
-			return position;
-		}
-		// length is different from 0
-		int length = this.lineEndTable.length;
-		// -1 to for one-based to zero-based conversion.
-		// -1, again, to get previous line.
-		final int previousLineOffset = this.lineEndTable[line - 2];
-		 // previousLineOffset + 1 is the first character of the current line
-		final int offsetForLine = previousLineOffset + 1;
-		final int currentLineEnd = line == length + 1 ? getStartPosition() + getLength() - 1 :	this.lineEndTable[line - 1];
-		if (offsetForLine > currentLineEnd) {
-			return -1;
-		} else {
-			return position - offsetForLine;
-		}
-	}
-	
-	/**
-	 * Returns a list of the comments encountered while parsing
-	 * this compilation unit.
-	 * <p>
-	 * Since the Java language allows comments to appear most anywhere
-	 * in the source text, it is problematic to locate comments in relation
-	 * to the structure of an AST. The one exception is doc comments 
-	 * which, by convention, immediately precede type, field, and
-	 * method declarations; these comments are located in the AST
-	 * by {@link  BodyDeclaration#getJavadoc BodyDeclaration.getJavadoc}.
-	 * Other comments do not show up in the AST. The table of comments
-	 * is provided for clients that need to find the source ranges of
-	 * all comments in the original source string. It includes entries
-	 * for comments of all kinds (line, block, and doc), arranged in order
-	 * of increasing source position. 
-	 * </p>
-	 * Note on comment parenting: The {@link ASTNode#getParent() getParent()}
-	 * of a doc comment associated with a body declaration is the body
-	 * declaration node; for these comment nodes
-	 * {@link ASTNode#getRoot() getRoot()} will return the compilation unit
-	 * (assuming an unmodified AST) reflecting the fact that these nodes
-	 * are property located in the AST for the compilation unit.
-	 * However, for other comment nodes, {@link ASTNode#getParent() getParent()}
-	 * will return <code>null</code>, and {@link ASTNode#getRoot() getRoot()}
-	 * will return the comment node itself, indicating that these comment nodes
-	 * are not directly connected to the AST for the compilation unit. The 
-	 * {@link Comment#getAlternateRoot Comment.getAlternateRoot}
-	 * method provides a way to navigate from a comment to its compilation
-	 * unit.
-	 * </p>
-	 * <p>
-	 * A note on visitors: The only comment nodes that will be visited when
-	 * visiting a compilation unit are the doc comments parented by body
-	 * declarations. To visit all comments in normal reading order, iterate
-	 * over the comment table and call {@link ASTNode#accept(ASTVisitor) accept}
-	 * on each element.
-	 * </p>
-	 * <p>
-	 * Clients cannot modify the resulting list.
-	 * </p>
-	 * 
-	 * @return an unmodifiable list of comments in increasing order of source
-	 * start position, or <code>null</code> if comment information
-	 * for this compilation unit is not available
-	 * @see ASTParser
+	 * @exception IllegalArgumentException if this compilation unit is
+	 * marked as unmodifiable, or if this compilation unit has already 
+	 * been tampered with, or recording has already been enabled
 	 * @since 3.0
 	 */
-	public List getCommentList() {
-		return this.optionalCommentList;
+	public void recordModifications() {
+		getAST().recordModifications(this);
 	}
-	
+
+	/**
+	 * Converts all modifications recorded for this compilation
+	 * unit into an object representing the corresponding text
+	 * edits to the given document containing the original source
+	 * code for this compilation unit.
+	 * <p>
+	 * The compilation unit must have been created by
+	 * <code>ASTParser</code> from the source code string in the
+	 * given document, and recording must have been turned
+	 * on with a prior call to <code>recordModifications</code>
+	 * while the AST was still in its original state.
+	 * </p>
+	 * <p>
+	 * Calling this methods does not discard the modifications
+	 * on record. Subsequence modifications made to the AST
+	 * are added to the ones already on record. If this method
+	 * is called again later, the resulting text edit object will
+	 * accurately reflect the net cumulative affect of all those
+	 * changes.
+	 * </p>
+	 * 
+	 * @param document original document containing source code
+	 * for this compilation unit
+	 * @param options the table of formatter options
+	 * (key type: <code>String</code>; value type: <code>String</code>);
+	 * or <code>null</code> to use the standard global options
+	 * {@link org.eclipse.jdt.core.JavaCore#getOptions() JavaCore.getOptions()}.
+	 * @return text edit object describing the changes to the
+	 * document corresponding to the recorded AST modifications
+	 * @exception IllegalArgumentException if the document passed is
+	 * <code>null</code> or does not correspond to this AST
+	 * @exception IllegalStateException if <code>recordModifications</code>
+	 * was not called to enable recording
+	 * @see #recordModifications()
+	 * @since 3.0
+	 */
+	public TextEdit rewrite(IDocument document, Map options) {
+		return getAST().rewrite(document, options);
+	}
+
 	/**
 	 * Sets the list of the comments encountered while parsing
 	 * this compilation unit.
@@ -991,7 +945,7 @@
 			this.optionalCommentList = Collections.unmodifiableList(commentList);
 		}
 	}
-	
+		
 	/**
 	 * Sets the Java element (an <code>org.eclipse.jdt.core.ICompilationUnit</code> or an <code>org.eclipse.jdt.core.IClassFile</code>) 
 	 * this compilation unit was created from, or <code>null</code> if it was not created from a Java element.
@@ -1002,21 +956,67 @@
 	void setJavaElement(IJavaElement element) {
 		this.element = element;
 	}
+	
+	/**
+	 * Sets the line end table for this compilation unit.
+	 * If <code>lineEndTable[i] == p</code> then line number <code>i+1</code> 
+	 * ends at character position <code>p</code>. Except for the last line, the 
+	 * positions are that of (the last character of) the line delimiter.
+	 * For example, the source string <code>A\nB\nC</code> has
+	 * line end table {1, 3, 4}.
+	 * 
+	 * @param lineEndTable the line end table
+	 */
+	void setLineEndTable(int[] lineEndTable) {
+		if (lineEndTable == null) {
+			throw new NullPointerException();
+		}
+		// alternate root is *not* considered a structural property
+		// but we protect them nevertheless
+		checkModifiable();
+		this.lineEndTable = lineEndTable;
+	}
+	
+	/**
+	 * Sets or clears the package declaration of this compilation unit 
+	 * node to the given package declaration node.
+	 * 
+	 * @param pkgDecl the new package declaration node, or 
+	 *   <code>null</code> if this compilation unit does not have a package
+	 *   declaration (that is in the default package)
+	 * @exception IllegalArgumentException if:
+	 * <ul>
+	 * <li>the node belongs to a different AST</li>
+	 * <li>the node already has a parent</li>
+	 * </ul>
+	 */ 
+	public void setPackage(PackageDeclaration pkgDecl) {
+		ASTNode oldChild = this.optionalPackageDeclaration;
+		preReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
+		this.optionalPackageDeclaration = pkgDecl;
+		postReplaceChild(oldChild, pkgDecl, PACKAGE_PROPERTY);
+	}
 
 
+	/**
+	 * Sets the array of problems reported by the compiler during the parsing or
+	 * name resolution of this compilation unit.
+	 * 
+	 * @param problems the list of problems
+	 */
+	void setProblems(IProblem[] problems) {
+		if (problems == null) {
+			throw new IllegalArgumentException();
+		}
+		this.problems = problems;
+	}
+	
 	/* (omit javadoc for this method)
 	 * Method declared on ASTNode.
 	 */
-	int memSize() {
-		int size = BASE_NODE_SIZE + 8 * 4;
-		if (this.lineEndTable != null) {
-			size += HEADERS + 4 * this.lineEndTable.length;
-		}
-		if (this.optionalCommentTable != null) {
-			size += HEADERS + 4 * this.optionalCommentTable.length;
-		}
-		// ignore the space taken up by optionalCommentList
-		return size;
+	final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+		// dispatch to correct overloaded match method
+		return matcher.match(this, other);
 	}
 	
 	/* (omit javadoc for this method)
@@ -1042,63 +1042,19 @@
 	}
 	
 	/**
-	 * Enables the recording of changes to this compilation
-	 * unit and its descendents. The compilation unit must have
-	 * been created by <code>ASTParser</code> and still be in
-	 * its original state. Once recording is on,
-	 * arbitrary changes to the subtree rooted at this compilation
-	 * unit are recorded internally. Once the modification has
-	 * been completed, call <code>rewrite</code> to get an object
-	 * representing the corresponding edits to the original 
-	 * source code string.
-	 *
-	 * @exception IllegalArgumentException if this compilation unit is
-	 * marked as unmodifiable, or if this compilation unit has already 
-	 * been tampered with, or recording has already been enabled
-	 * @since 3.0
-	 */
-	public void recordModifications() {
-		getAST().recordModifications(this);
-	}
-	
-	/**
-	 * Converts all modifications recorded for this compilation
-	 * unit into an object representing the corresponding text
-	 * edits to the given document containing the original source
-	 * code for this compilation unit.
-	 * <p>
-	 * The compilation unit must have been created by
-	 * <code>ASTParser</code> from the source code string in the
-	 * given document, and recording must have been turned
-	 * on with a prior call to <code>recordModifications</code>
-	 * while the AST was still in its original state.
-	 * </p>
-	 * <p>
-	 * Calling this methods does not discard the modifications
-	 * on record. Subsequence modifications made to the AST
-	 * are added to the ones already on record. If this method
-	 * is called again later, the resulting text edit object will
-	 * accurately reflect the net cumulative affect of all those
-	 * changes.
-	 * </p>
+	 * Returns the live list of nodes for the top-level type declarations of this 
+	 * compilation unit, in order of appearance.
+     * <p>
+     * Note that in JLS3, the types may include both enum declarations
+     * and annotation type declarations introduced in J2SE 5.
+     * For JLS2, the elements are always <code>TypeDeclaration</code>.
+     * </p>
 	 * 
-	 * @param document original document containing source code
-	 * for this compilation unit
-	 * @param options the table of formatter options
-	 * (key type: <code>String</code>; value type: <code>String</code>);
-	 * or <code>null</code> to use the standard global options
-	 * {@link org.eclipse.jdt.core.JavaCore#getOptions() JavaCore.getOptions()}.
-	 * @return text edit object describing the changes to the
-	 * document corresponding to the recorded AST modifications
-	 * @exception IllegalArgumentException if the document passed is
-	 * <code>null</code> or does not correspond to this AST
-	 * @exception IllegalStateException if <code>recordModifications</code>
-	 * was not called to enable recording
-	 * @see #recordModifications()
-	 * @since 3.0
-	 */
-	public TextEdit rewrite(IDocument document, Map options) {
-		return getAST().rewrite(document, options);
+	 * @return the live list of top-level type declaration
+	 *    nodes (elementType: <code>AbstractTypeDeclaration</code>)
+	 */ 
+	public List types() {
+		return this.types;
 	}
 }
 
diff --git a/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java b/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
index 83f1e97..b3abfa8 100644
--- a/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
+++ b/dom/org/eclipse/jdt/core/dom/CompilationUnitResolver.java
@@ -666,56 +666,70 @@
 			beginToCompile(sourceUnits, bindingKeys);
 			// process all units (some more could be injected in the loop by the lookup environment)
 			for (; i < this.totalUnits; i++) {
+				if (this.requestedSources.size() == 0 && this.requestedKeys.size() == 0) {
+					// no need to keep resolving if no more ASTs and no more binding keys are needed
+					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=114935
+					// cleanup remaining units
+					for (; i < this.totalUnits; i++) {
+						this.unitsToProcess[i].cleanUp();
+						this.unitsToProcess[i] = null;
+					}
+					break;
+				}
 				unit = this.unitsToProcess[i];
 				try {
-					char[] fileName = unit.compilationResult.getFileName();
-					
-					// only process requested units
-					if (this.requestedKeys.containsKey(fileName) || this.requestedSources.containsKey(fileName)) {
-						super.process(unit, i); // this.process(...) is optimized to not process already known units
+					super.process(unit, i); // this.process(...) is optimized to not process already known units
 
-						// requested AST
-						ICompilationUnit source = (ICompilationUnit) this.requestedSources.get(fileName);
-						if (source != null) {
-							// convert AST
-							CompilationResult compilationResult = unit.compilationResult;
-							org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationResult.compilationUnit;
-							char[] contents = sourceUnit.getContents();
-							AST ast = AST.newAST(apiLevel);
-							ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
-							ASTConverter converter = new ASTConverter(compilerOptions, true/*need to resolve bindings*/, this.monitor);
-							BindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables);
-							ast.setBindingResolver(resolver);
-							converter.setAST(ast);
-							CompilationUnit compilationUnit = converter.convert(unit, contents);
-							compilationUnit.setJavaElement(source);
-							compilationUnit.setLineEndTable(compilationResult.getLineSeparatorPositions());
-							ast.setDefaultNodeFlag(0);
-							ast.setOriginalModificationCount(ast.modificationCount());
-							
-							// pass it to requestor
-							astRequestor.acceptAST(source, compilationUnit);
-							
-							worked(1);
-						} 
+					// requested AST
+					char[] fileName = unit.compilationResult.getFileName();					
+					ICompilationUnit source = (ICompilationUnit) this.requestedSources.get(fileName);
+					if (source != null) {
+						// convert AST
+						CompilationResult compilationResult = unit.compilationResult;
+						org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationResult.compilationUnit;
+						char[] contents = sourceUnit.getContents();
+						AST ast = AST.newAST(apiLevel);
+						ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
+						ASTConverter converter = new ASTConverter(compilerOptions, true/*need to resolve bindings*/, this.monitor);
+						BindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables);
+						ast.setBindingResolver(resolver);
+						converter.setAST(ast);
+						CompilationUnit compilationUnit = converter.convert(unit, contents);
+						compilationUnit.setJavaElement(source);
+						compilationUnit.setLineEndTable(compilationResult.getLineSeparatorPositions());
+						ast.setDefaultNodeFlag(0);
+						ast.setOriginalModificationCount(ast.modificationCount());
 						
-						// requested binding
-						Object key = this.requestedKeys.get(fileName);
-						if (key instanceof BindingKeyResolver) {
-							reportBinding(key, astRequestor, owner, unit);
+						// pass it to requestor
+						astRequestor.acceptAST(source, compilationUnit);
+						
+						worked(1);
+					} 
+					
+					// requested binding
+					Object key = this.requestedKeys.get(fileName);
+					if (key instanceof BindingKeyResolver) {
+						reportBinding(key, astRequestor, owner, unit);
+						worked(1);
+					} else if (key instanceof ArrayList) {
+						Iterator iterator = ((ArrayList) key).iterator();
+						while (iterator.hasNext()) {
+							reportBinding(iterator.next(), astRequestor, owner, unit);
 							worked(1);
-						} else if (key instanceof ArrayList) {
-							Iterator iterator = ((ArrayList) key).iterator();
-							while (iterator.hasNext()) {
-								reportBinding(iterator.next(), astRequestor, owner, unit);
-								worked(1);
-							}
 						}
+					}
+					
+					// remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
+					this.requestedSources.removeKey(fileName);
+					this.requestedKeys.removeKey(fileName);
 						
-						// remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
-						this.requestedSources.removeKey(fileName);
-						this.requestedKeys.removeKey(fileName);
+/*	Code used to fault in types and resolve which is no longer necessary as all questions asked to forward references are
+ * lazily resolved.
+ * Code used to be:
+					if (this.requestedKeys.containsKey(fileName) || this.requestedSources.containsKey(fileName)) {
+					   ...
 					} else {
+
 						if (unit.scope != null)
 							unit.scope.faultInTypes();// still force resolution of signatures, so clients can query DOM AST
 				
@@ -726,7 +740,7 @@
 						
 						// note that if this has a performance penalty on clients, the above code should be removed
 						// the following patch would workaround bug 111822:
-/*
+
 Index: FieldReference.java
 ===================================================================
 RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java,v
@@ -751,7 +765,6 @@
  
  		fieldDecl.resolve(originalField.isStatic() //side effect on binding 
 */					
-					}
 				} finally {
 					// cleanup compilation unit result
 					unit.cleanUp();
diff --git a/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java b/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java
index 6e938a4..ff75342 100644
--- a/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java
+++ b/dom/org/eclipse/jdt/core/dom/DefaultCommentMapper.java
@@ -29,10 +29,10 @@
 	// extended nodes storage
 	int leadingPtr;
 	ASTNode[] leadingNodes;
-	int[][] leadingIndexes;
+	long[] leadingIndexes;
 	int trailingPtr, lastTrailingPtr;
 	ASTNode[] trailingNodes;
-	int[][] trailingIndexes;
+	long[] trailingIndexes;
 	static final int STORAGE_INCREMENT = 16;
 
 	/**
@@ -110,48 +110,6 @@
 	}
 
 	/**
-	 * Return all leading comments of a given node.
-	 * @param node
-	 * @return an array of Comment or null if there's no leading comment
-	 */
-	Comment[] getLeadingComments(ASTNode node) {
-		if (this.leadingPtr >= 0) {
-			int[] range = null;
-			for (int i=0; range==null && i<=this.leadingPtr; i++) {
-				if (this.leadingNodes[i] == node) range = this.leadingIndexes[i];
-			}
-			if (range != null) {
-				int length = range[1]-range[0]+1;
-				Comment[] leadComments = new Comment[length];
-				System.arraycopy(this.comments, range[0], leadComments, 0, length);
-				return  leadComments;
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Return all trailing comments of a given node.
-	 * @param node
-	 * @return an array of Comment or null if there's no trailing comment
-	 */
-	Comment[] getTrailingComments(ASTNode node) {
-		if (this.trailingPtr >= 0) {
-			int[] range = null;
-			for (int i=0; range==null && i<=this.trailingPtr; i++) {
-				if (this.trailingNodes[i] == node) range = this.trailingIndexes[i];
-			}
-			if (range != null) {
-				int length = range[1]-range[0]+1;
-				Comment[] trailComments = new Comment[length];
-				System.arraycopy(this.comments, range[0], trailComments, 0, length);
-				return  trailComments;
-			}
-		}
-		return null;
-	}
-
-	/**
 	 * Returns the extended start position of the given node. Unlike
 	 * {@link ASTNode#getStartPosition()} and {@link ASTNode#getLength()},
 	 * the extended source range may include comments and whitespace
@@ -165,12 +123,12 @@
 	 */
 	public int getExtendedStartPosition(ASTNode node) {
 		if (this.leadingPtr >= 0) {
-			int[] range = null;
-			for (int i=0; range==null && i<=this.leadingPtr; i++) {
+			long range = -1;
+			for (int i=0; range<0 && i<=this.leadingPtr; i++) {
 				if (this.leadingNodes[i] == node) range = this.leadingIndexes[i];
 			}
-			if (range != null) {
-				return  this.comments[range[0]].getStartPosition() ;
+			if (range >= 0) {
+				return  this.comments[(int)(range>>32)].getStartPosition() ;
 			}
 		}
 		return node.getStartPosition();
@@ -182,12 +140,12 @@
 	public int getExtendedEnd(ASTNode node) {
 		int end = node.getStartPosition() + node.getLength();
 		if (this.trailingPtr >= 0) {
-			int[] range = null;
-			for (int i=0; range==null && i<=this.trailingPtr; i++) {
+			long range = -1;
+			for (int i=0; range<0 && i<=this.trailingPtr; i++) {
 				if (this.trailingNodes[i] == node) range = this.trailingIndexes[i];
 			}
-			if (range != null) {
-				Comment lastComment = this.comments[range[1]];
+			if (range >= 0) {
+				Comment lastComment = this.comments[(int) range];
 				end = lastComment.getStartPosition() + lastComment.getLength();
 			}
 		}
@@ -211,6 +169,40 @@
 		return getExtendedEnd(node) - getExtendedStartPosition(node) + 1;
 	}
 
+	/**
+	 * Return index of first leading comment of a given node.
+	 * 
+	 * @param node
+	 * @return index of first leading comment or -1 if node has no leading comment
+	 */
+	int firstLeadingCommentIndex(ASTNode node) {
+		if (this.leadingPtr >= 0) {
+			for (int i=0; i<=this.leadingPtr; i++) {
+				if (this.leadingNodes[i] == node) {
+					return (int) (this.leadingIndexes[i]>>32);
+				}
+			}
+		}
+		return -1;
+	}
+
+	/**
+	 * Return index of last trailing comment of a given node.
+	 * 
+	 * @param node
+	 * @return index of last trailing comment or -1 if node has no trailing comment
+	 */
+	int lastTrailingCommentIndex(ASTNode node) {
+		if (this.trailingPtr >= 0) {
+			for (int i=0; i<=this.trailingPtr; i++) {
+				if (this.trailingNodes[i] == node) {
+					return (int) this.trailingIndexes[i];
+				}
+			}
+		}
+		return -1;
+	}
+
 	/*
 	 * Initialize leading and trailing comments tables in whole nodes hierarchy of a compilation
 	 * unit.
@@ -245,13 +237,13 @@
 		int leadingCount = this.leadingPtr + 1;
 		if (leadingCount > 0 && leadingCount < this.leadingIndexes.length) {
 			System.arraycopy(this.leadingNodes, 0, this.leadingNodes = new ASTNode[leadingCount], 0, leadingCount);
-			System.arraycopy(this.leadingIndexes, 0, this.leadingIndexes= new int[leadingCount][], 0, leadingCount);
+			System.arraycopy(this.leadingIndexes, 0, this.leadingIndexes= new long[leadingCount], 0, leadingCount);
 		}
 		
 		// Reduce trailing arrays if necessary
 		if (this.trailingPtr >= 0) {
 			// remove last remaining unresolved nodes
-			while (this.trailingIndexes[this.trailingPtr][0] == -1) {
+			while (this.trailingIndexes[this.trailingPtr] == -1) {
 				this.trailingPtr--;
 				if (this.trailingPtr < 0) {
 					this.trailingIndexes = null;
@@ -264,7 +256,7 @@
 			int trailingCount = this.trailingPtr + 1;
 			if (trailingCount > 0 && trailingCount < this.trailingIndexes.length) {
 				System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[trailingCount], 0, trailingCount);
-				System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes= new int[trailingCount][], 0, trailingCount);
+				System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes= new long[trailingCount], 0, trailingCount);
 			}
 		}
 	}
@@ -374,14 +366,14 @@
 			if (startIdx <= endIdx) {
 				if (++this.leadingPtr == 0) {
 					this.leadingNodes = new ASTNode[STORAGE_INCREMENT];
-					this.leadingIndexes = new int[STORAGE_INCREMENT][];
+					this.leadingIndexes = new long[STORAGE_INCREMENT];
 				} else if (this.leadingPtr == this.leadingNodes.length) {
 					int newLength = (this.leadingPtr*3/2)+STORAGE_INCREMENT;
 					System.arraycopy(this.leadingNodes, 0, this.leadingNodes = new ASTNode[newLength], 0, this.leadingPtr);
-					System.arraycopy(this.leadingIndexes, 0, this.leadingIndexes = new int[newLength][], 0, this.leadingPtr);
+					System.arraycopy(this.leadingIndexes, 0, this.leadingIndexes = new long[newLength], 0, this.leadingPtr);
 				}
 				this.leadingNodes[this.leadingPtr] = node;
-				this.leadingIndexes[this.leadingPtr] = new int[] { startIdx, endIdx };
+				this.leadingIndexes[this.leadingPtr] = (((long)startIdx)<<32) + endIdx;
 				extended = this.comments[endIdx].getStartPosition();
 			}
 		}
@@ -416,15 +408,15 @@
 			// special case for last child of its parent
 			if (++this.trailingPtr == 0) {
 				this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
-				this.trailingIndexes = new int[STORAGE_INCREMENT][];
+				this.trailingIndexes = new long[STORAGE_INCREMENT];
 				this.lastTrailingPtr = -1;
 			} else if (this.trailingPtr == this.trailingNodes.length) {
 				int newLength = (this.trailingPtr*3/2)+STORAGE_INCREMENT;
 				System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr);
-				System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new int[newLength][], 0, this.trailingPtr);
+				System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr);
 			}
 			this.trailingNodes[this.trailingPtr] = node;
-			this.trailingIndexes[this.trailingPtr] = new int[] { -1, -1 };
+			this.trailingIndexes[this.trailingPtr] = -1;
 			return nodeEnd;
 		}
 		int extended = nodeEnd;
@@ -504,15 +496,15 @@
 			// Store trailing comments indexes
 			if (++this.trailingPtr == 0) {
 				this.trailingNodes = new ASTNode[STORAGE_INCREMENT];
-				this.trailingIndexes = new int[STORAGE_INCREMENT][];
+				this.trailingIndexes = new long[STORAGE_INCREMENT];
 				this.lastTrailingPtr = -1;
 			} else if (this.trailingPtr == this.trailingNodes.length) {
 				int newLength = (this.trailingPtr*3/2)+STORAGE_INCREMENT;
 				System.arraycopy(this.trailingNodes, 0, this.trailingNodes = new ASTNode[newLength], 0, this.trailingPtr);
-				System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new int[newLength][], 0, this.trailingPtr);
+				System.arraycopy(this.trailingIndexes, 0, this.trailingIndexes = new long[newLength], 0, this.trailingPtr);
 			}
 			this.trailingNodes[this.trailingPtr] = node;
-			int[] nodeRange = new int[] { startIdx, endIdx };
+			long nodeRange = (((long)startIdx)<<32) + endIdx;
 			this.trailingIndexes[this.trailingPtr] = nodeRange;
 			// Compute new extended end
 			extended = this.comments[endIdx].getStartPosition()+this.comments[endIdx].getLength()-1;
@@ -520,8 +512,8 @@
 			ASTNode previousNode = node;
 			int ptr = this.trailingPtr - 1; // children extended end were stored before
 			while (ptr >= 0) {
-				int[] range = this.trailingIndexes[ptr];
-				if (range[0] != -1 || range[1] != -1) break; // there's no more unresolved nodes
+				long range = this.trailingIndexes[ptr];
+				if (range != -1) break; // there's no more unresolved nodes
 				ASTNode unresolved = this.trailingNodes[ptr];
 				if (previousNode != unresolved.getParent()) break; // we're no longer in node ancestor hierarchy
 				this.trailingIndexes[ptr] = nodeRange;
diff --git a/dom/org/eclipse/jdt/core/dom/DocCommentParser.java b/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
index 754e477..083a086 100644
--- a/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
+++ b/dom/org/eclipse/jdt/core/dom/DocCommentParser.java
@@ -27,9 +27,6 @@
  */
 class DocCommentParser extends AbstractCommentParser {
 
-	// Public fields
-	
-	// Private fields
 	private Javadoc docComment;
 	private AST ast;
 
@@ -39,7 +36,7 @@
 		this.scanner = scanner;
 		this.sourceLevel = this.ast.apiLevel() >= AST.JLS3 ? ClassFileConstants.JDK1_5 : ClassFileConstants.JDK1_3;
 		this.checkDocComment = check;
-		this.kind = DOM_PARSER;
+		this.kind = DOM_PARSER | TEXT_PARSE;
 	}
 
 	/* (non-Javadoc)
@@ -354,38 +351,47 @@
 		int token = readTokenAndConsume();
 		this.tagSourceStart = this.scanner.getCurrentTokenStartPosition();
 		this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+		char[] tagName = this.scanner.getCurrentIdentifierSource();
 
 		// Try to get tag name other than java identifier
 		// (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51660)
-		int tk = token;
-		char pc = peekChar();
-		tagNameToken: while (tk != TerminalTokens.TokenNameEOF) {
-			this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
-			token = tk;
-			// !, ", #, %, &, ', -, :, <, >, * chars and spaces are not allowed in tag names
-			switch (pc) {
-				case '}':
-				case '!':
-				case '#':
-				case '%':
-				case '&':
-				case '\'':
-				case '"':
-				case ':':
-				// case '-': allowed in tag names as this character is often used in doclets (bug 68087)
-				case '<':
-				case '>':
-				case '*': // break for '*' as this is perhaps the end of comment (bug 65288)
-					break tagNameToken;
-				default:
-					if (pc == ' ' || Character.isWhitespace(pc)) break tagNameToken;
+		if (this.scanner.currentCharacter != ' ' && !Character.isWhitespace(this.scanner.currentCharacter)) {
+			tagNameToken: while (token != TerminalTokens.TokenNameEOF && this.index < this.scanner.eofPosition) {
+				int length = tagName.length;
+				// !, ", #, %, &, ', -, :, <, >, * chars and spaces are not allowed in tag names
+				switch (this.scanner.currentCharacter) {
+					case '}':
+					case '*': // break for '*' as this is perhaps the end of comment (bug 65288)
+					case '!':
+					case '#':
+					case '%':
+					case '&':
+					case '\'':
+					case '"':
+					case ':':
+					case '<':
+					case '>':
+						break tagNameToken;
+					case '-': // allowed in tag names as this character is often used in doclets (bug 68087)
+						System.arraycopy(tagName, 0, tagName = new char[length+1], 0, length);
+						tagName[length] = this.scanner.currentCharacter;
+						break;
+					default:
+						if (this.scanner.currentCharacter == ' ' || Character.isWhitespace(this.scanner.currentCharacter)) {
+							break tagNameToken;
+						}
+						token = readTokenAndConsume();
+						char[] ident = this.scanner.getCurrentIdentifierSource();
+						System.arraycopy(tagName, 0, tagName = new char[length+ident.length], 0, length);
+						System.arraycopy(ident, 0, tagName, length, ident.length);
+						break;
+				}
+				this.tagSourceEnd = this.scanner.getCurrentTokenEndPosition();
+				this.scanner.getNextChar();
+				this.index = this.scanner.currentPosition;
 			}
-			tk = readTokenAndConsume();
-			pc = peekChar();
 		}
-		int length = this.tagSourceEnd-this.tagSourceStart+1;
-		char[] tag = new char[length];
-		System.arraycopy(this.source, this.tagSourceStart, tag, 0, length);
+		int length = tagName.length;
 		this.index = this.tagSourceEnd+1;
 		this.scanner.currentPosition = this.tagSourceEnd+1;
 		this.tagSourceStart = previousPosition;
@@ -395,9 +401,18 @@
 		boolean valid = true;
 		switch (token) {
 			case TerminalTokens.TokenNameIdentifier :
-				switch (tag[0]) {
+				switch (tagName[0]) {
+					case 'c':
+						if (length == TAG_CATEGORY_LENGTH && CharOperation.equals(TAG_CATEGORY, tagName)) {
+							this.tagValue = TAG_CATEGORY_VALUE;
+							valid = parseIdentifierTag(false); // TODO (frederic) reconsider parameter value when @category will be significant in spec
+						} else {
+							this.tagValue = TAG_OTHERS_VALUE;
+							createTag();
+						}
+						break;
 					case 'd':
-						if (CharOperation.equals(tag, TAG_DEPRECATED)) {
+						if (length == TAG_DEPRECATED_LENGTH && CharOperation.equals(TAG_DEPRECATED, tagName)) {
 							this.deprecated = true;
 							this.tagValue = TAG_DEPRECATED_VALUE;
 						} else {
@@ -406,7 +421,7 @@
 						createTag();
 					break;
 					case 'i':
-						if (CharOperation.equals(tag, TAG_INHERITDOC)) {
+						if (length == TAG_INHERITDOC_LENGTH && CharOperation.equals(TAG_INHERITDOC, tagName)) {
 							// inhibits inherited flag when tags have been already stored
 							// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51606
 							// Note that for DOM_PARSER, nodes stack may be not empty even no '@' tag
@@ -422,7 +437,7 @@
 						createTag();
 					break;
 					case 'p':
-						if (CharOperation.equals(tag, TAG_PARAM)) {
+						if (length == TAG_PARAM_LENGTH && CharOperation.equals(TAG_PARAM, tagName)) {
 							this.tagValue = TAG_PARAM_VALUE;
 							valid = parseParam();
 						} else {
@@ -431,7 +446,7 @@
 						}
 					break;
 					case 'e':
-						if (CharOperation.equals(tag, TAG_EXCEPTION)) {
+						if (length == TAG_EXCEPTION_LENGTH && CharOperation.equals(TAG_EXCEPTION, tagName)) {
 							this.tagValue = TAG_EXCEPTION_VALUE;
 							valid = parseThrows();
 						} else {
@@ -440,7 +455,7 @@
 						}
 					break;
 					case 's':
-						if (CharOperation.equals(tag, TAG_SEE)) {
+						if (length == TAG_SEE_LENGTH && CharOperation.equals(TAG_SEE, tagName)) {
 							this.tagValue = TAG_SEE_VALUE;
 							if (this.inlineTagStarted) {
 								// bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53290
@@ -455,9 +470,9 @@
 						}
 					break;
 					case 'l':
-						if (CharOperation.equals(tag, TAG_LINK)) {
+						if (length == TAG_LINK_LENGTH && CharOperation.equals(TAG_LINK, tagName)) {
 							this.tagValue = TAG_LINK_VALUE;
-						} else if (CharOperation.equals(tag, TAG_LINKPLAIN)) {
+						} else if (length == TAG_LINKPLAIN_LENGTH && CharOperation.equals(TAG_LINKPLAIN, tagName)) {
 							this.tagValue = TAG_LINKPLAIN_VALUE;
 						}
 						if (this.tagValue != NO_TAG_VALUE)  {
@@ -474,7 +489,7 @@
 						}
 					break;
 					case 'v':
-						if (this.sourceLevel >= ClassFileConstants.JDK1_5 && CharOperation.equals(tag, TAG_VALUE)) {
+						if (this.sourceLevel >= ClassFileConstants.JDK1_5 && length == TAG_VALUE_LENGTH && CharOperation.equals(TAG_VALUE, tagName)) {
 							this.tagValue = TAG_VALUE_VALUE;
 							if (this.inlineTagStarted) {
 								valid = parseReference();
diff --git a/dom/org/eclipse/jdt/core/dom/InternalASTRewrite.java b/dom/org/eclipse/jdt/core/dom/InternalASTRewrite.java
index 1d6b034..c2a574b 100644
--- a/dom/org/eclipse/jdt/core/dom/InternalASTRewrite.java
+++ b/dom/org/eclipse/jdt/core/dom/InternalASTRewrite.java
@@ -17,11 +17,13 @@
 import org.eclipse.text.edits.TextEdit;
 
 import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.TextUtilities;
 
 import org.eclipse.jdt.core.dom.SimplePropertyDescriptor;
 import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
 import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
 import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer;
+import org.eclipse.jdt.internal.core.dom.rewrite.LineInformation;
 import org.eclipse.jdt.internal.core.dom.rewrite.ListRewriteEvent;
 import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
 import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
@@ -82,7 +84,11 @@
 					return new SourceRange(extendedStartPosition, extendedLength);
 				}
 			};
-			ASTRewriteAnalyzer visitor = new ASTRewriteAnalyzer(document, result, this.eventStore, this.nodeStore, options, xsrComputer);
+			char[] content= document.get().toCharArray();
+			LineInformation lineInfo= LineInformation.create(document);
+			String lineDelim= TextUtilities.getDefaultLineDelimiter(document);
+			
+			ASTRewriteAnalyzer visitor = new ASTRewriteAnalyzer(content, lineInfo, lineDelim, result, this.eventStore, this.nodeStore, options, xsrComputer);
 			rootNode.accept(visitor);
 		}
 		return result;
diff --git a/dom/org/eclipse/jdt/core/dom/VariableBinding.java b/dom/org/eclipse/jdt/core/dom/VariableBinding.java
index ef41b1a..fe20386 100644
--- a/dom/org/eclipse/jdt/core/dom/VariableBinding.java
+++ b/dom/org/eclipse/jdt/core/dom/VariableBinding.java
@@ -46,9 +46,8 @@
 	 * @since 3.0
 	 */
 	public Object getConstantValue() {
-		if (!this.binding.isConstantValue()) return null;
 		Constant c = this.binding.constant();
-		if (c == null) return null;
+		if (c == null || c == Constant.NotAConstant) return null;
 		switch (c.typeID()) {
 			case TypeIds.T_boolean:
 				return Boolean.valueOf(c.booleanValue());
diff --git a/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java b/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java
index 63a1fa0..d572a91 100644
--- a/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java
+++ b/dom/org/eclipse/jdt/core/dom/rewrite/ASTRewrite.java
@@ -13,29 +13,31 @@
 import java.util.Iterator;
 import java.util.Map;
 
-import org.eclipse.text.edits.MultiTextEdit;
-import org.eclipse.text.edits.TextEdit;
-import org.eclipse.text.edits.TextEditGroup;
-
-import org.eclipse.jface.text.IDocument;
-
+import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.JavaCore;
-
+import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
 import org.eclipse.jdt.core.dom.Block;
 import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
+import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
-
 import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer;
+import org.eclipse.jdt.internal.core.dom.rewrite.LineInformation;
 import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
 import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
 import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore;
 import org.eclipse.jdt.internal.core.dom.rewrite.TrackedNodePosition;
 import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.TextUtilities;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.TextEdit;
+import org.eclipse.text.edits.TextEditGroup;
 
 /**
- * Infrastucture for modifying code by describing changes to AST nodes.
+ * Infrastructure for modifying code by describing changes to AST nodes.
  * The AST rewriter collects descriptions of modifications to nodes and
  * translates these descriptions into text edits that can then be applied to
  * the original source. The key thing is that this is all done without actually
@@ -60,16 +62,14 @@
  * ASTRewrite rewriter = ASTRewrite.create(ast);
  * TypeDeclaration td = (TypeDeclaration) cu.types().get(0);
  * ITrackedNodePosition tdLocation = rewriter.track(td);
- * ListRewriter lrw = rewriter.getListRewrite(cu,
- *                       CompilationUnit.IMPORTS_PROPERTY);
+ * ListRewriter lrw = rewriter.getListRewrite(cu, CompilationUnit.IMPORTS_PROPERTY);
  * lrw.insertLast(id, null);
  * TextEdit edits = rewriter.rewriteAST(document, null);
  * UndoEdit undo = edits.apply(document);
- * assert "import java.util.List;\nimport java.util.Set;\nclass X {}"
- *   .equals(doc.get().toCharArray());
+ * assert "import java.util.List;\nimport java.util.Set;\nclass X {}".equals(doc.get().toCharArray());
  * // tdLocation.getStartPosition() and tdLocation.getLength()
  * // are new source range for "class X {}" in doc.get()
- * </pre>
+ * </pre> 
  * <p>
  * This class is not intended to be subclassed.
  * </p>
@@ -172,21 +172,86 @@
 		if (document == null) {
 			throw new IllegalArgumentException();
 		}
-		TextEdit result= new MultiTextEdit();
 		
 		ASTNode rootNode= getRootNode();
-		if (rootNode != null) {
-			//validateASTNotModified(rootNode);
-			
-			TargetSourceRangeComputer sourceRangeComputer= getExtendedSourceRangeComputer();
-			
-			this.eventStore.prepareMovedNodes(sourceRangeComputer);
-
-			ASTRewriteAnalyzer visitor= new ASTRewriteAnalyzer(document, result, this.eventStore, this.nodeStore, options, sourceRangeComputer);
-			rootNode.accept(visitor); // throws IllegalArgumentException
-			
-			this.eventStore.revertMovedNodes();
+		if (rootNode == null) {
+			return new MultiTextEdit(); // no changes
 		}
+			
+		char[] content= document.get().toCharArray();
+		LineInformation lineInfo= LineInformation.create(document);
+		String lineDelim= TextUtilities.getDefaultLineDelimiter(document);
+		
+		return internalRewriteAST(content, lineInfo, lineDelim, options, rootNode);
+	}
+	
+	/**
+	 * Converts all modifications recorded by this rewriter into an object representing the the corresponding text
+	 * edits to the source of a {@link ICompilationUnit} from which the AST was created from.
+	 * The compilation unit itself is not modified.
+	 * <p>
+	 * Important: This API can only be used if the modified AST has been created from a
+	 * {@link ICompilationUnit}. That means {@link ASTParser#setSource(ICompilationUnit)}
+	 * has been used when initializing the {@link ASTParser}. A {@link IllegalArgumentException} is thrown
+	 * otherwise. Use {@link #rewriteAST(IDocument, Map)} for all ASTs not created from a {@link ICompilationUnit}.
+	 * </p>
+	 * <p>
+	 * For nodes in the original that are being replaced or deleted,
+	 * this rewriter computes the adjusted source ranges
+	 * by calling <code>getTargetSourceRangeComputer().computeSourceRange(node)</code>.
+	 * </p>
+	 * <p>
+	 * Calling this methods does not discard the modifications
+	 * on record. Subsequence modifications are added to the ones
+	 * already on record. If this method is called again later,
+	 * the resulting text edit object will accurately reflect
+	 * the net cumulative affect of all those changes.
+	 * </p>
+	 * 
+	 * @return text edit object describing the changes to the
+	 * document corresponding to the changes recorded by this rewriter
+	 * @throws JavaModelException A {@link JavaModelException} is thrown when
+	 * the underlying compilation units buffer could not be accessed.
+	 * @throws IllegalArgumentException An {@link IllegalArgumentException}
+	 * is thrown if the document passed does not correspond to the AST that is rewritten.
+	 * 
+	 * @since 3.2
+	 */
+	public TextEdit rewriteAST() throws JavaModelException, IllegalArgumentException {
+		ASTNode rootNode= getRootNode();
+		if (rootNode == null) {
+			return new MultiTextEdit(); // no changes
+		}
+		
+		ASTNode root= rootNode.getRoot();
+		if (!(root instanceof CompilationUnit)) {
+			throw new IllegalArgumentException("This API can only be used if the AST is created from a compilation unit"); //$NON-NLS-1$
+		}
+		CompilationUnit astRoot= (CompilationUnit) root;
+		if (!(astRoot.getJavaElement() instanceof ICompilationUnit)) {
+			throw new IllegalArgumentException("This API can only be used if the AST is created from a compilation unit"); //$NON-NLS-1$
+		}
+		ICompilationUnit cu= (ICompilationUnit) astRoot.getJavaElement();
+		
+		char[] content= cu.getBuffer().getCharacters();
+		LineInformation lineInfo= LineInformation.create(astRoot);
+		String lineDelim= cu.findRecommendedLineSeparator();
+		Map options= cu.getJavaProject().getOptions(true);
+		
+		return internalRewriteAST(content, lineInfo, lineDelim, options, rootNode);
+	}
+	
+	private TextEdit internalRewriteAST(char[] content, LineInformation lineInfo, String lineDelim, Map options, ASTNode rootNode) {
+		TextEdit result= new MultiTextEdit();
+		//validateASTNotModified(rootNode);
+		
+		TargetSourceRangeComputer sourceRangeComputer= getExtendedSourceRangeComputer();
+		this.eventStore.prepareMovedNodes(sourceRangeComputer);
+		
+		ASTRewriteAnalyzer visitor= new ASTRewriteAnalyzer(content, lineInfo, lineDelim, result, this.eventStore, this.nodeStore, options, sourceRangeComputer);
+		rootNode.accept(visitor); // throws IllegalArgumentException
+		
+		this.eventStore.revertMovedNodes();
 		return result;
 	}
 	
@@ -320,7 +385,7 @@
 		if (node == null || property == null) {
 			throw new IllegalArgumentException();
 		}
-		validateIsInsideAST(node);
+		validateIsCorrectAST(node);
 		validatePropertyType(property, value);
 
 		NodeRewriteEvent nodeEvent= this.eventStore.getNodeEvent(node, property, true);
@@ -375,11 +440,13 @@
 		return new TrackedNodePosition(group, node);
 	}	
 			
-	private void validateIsInsideAST(ASTNode node) {
+	private void validateIsExistingNode(ASTNode node) {
 		if (node.getStartPosition() == -1) {
 			throw new IllegalArgumentException("Node is not an existing node"); //$NON-NLS-1$
 		}
+	}
 	
+	private void validateIsCorrectAST(ASTNode node) {
 		if (node.getAST() != getAST()) {
 			throw new IllegalArgumentException("Node is not inside the AST"); //$NON-NLS-1$
 		}
@@ -469,7 +536,8 @@
 		if (node == null) {
 			throw new IllegalArgumentException();
 		}
-		validateIsInsideAST(node);
+		validateIsExistingNode(node);
+		validateIsCorrectAST(node);
 		CopySourceInfo info= getRewriteEventStore().markAsCopySource(node.getParent(), node.getLocationInParent(), node, isMove);
 	
 		ASTNode placeholder= getNodeStore().newPlaceholderNode(node.getNodeType());
@@ -531,7 +599,7 @@
 	
 	/**
 	 * Sets a custom target source range computer for this AST rewriter. This is advanced feature to modify how
-	 * comments are assotiated with nodes, which should be done only in special cases.
+	 * comments are associated with nodes, which should be done only in special cases.
 	 * 
 	 * @param computer a target source range computer,
 	 * or <code>null</code> to restore the default value of
diff --git a/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
index e135af7..f2a9cd6 100644
--- a/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
+++ b/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
@@ -17,39 +17,21 @@
 import java.util.Map;
 import java.util.Stack;
 
-import org.eclipse.text.edits.CopySourceEdit;
-import org.eclipse.text.edits.CopyTargetEdit;
-import org.eclipse.text.edits.DeleteEdit;
-import org.eclipse.text.edits.InsertEdit;
-import org.eclipse.text.edits.MoveSourceEdit;
-import org.eclipse.text.edits.MoveTargetEdit;
-import org.eclipse.text.edits.RangeMarker;
-import org.eclipse.text.edits.ReplaceEdit;
-import org.eclipse.text.edits.TextEdit;
-import org.eclipse.text.edits.TextEditGroup;
-
 import org.eclipse.core.runtime.CoreException;
-
-import org.eclipse.jface.text.Assert;
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.IRegion;
-import org.eclipse.jface.text.TextUtilities;
-
 import org.eclipse.jdt.core.ToolFactory;
 import org.eclipse.jdt.core.compiler.IScanner;
 import org.eclipse.jdt.core.compiler.ITerminalSymbols;
-
 import org.eclipse.jdt.core.dom.*;
 import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
 import org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer.SourceRange;
-
 import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.BlockContext;
 import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.NodeMarker;
 import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.Prefix;
 import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore.CopyPlaceholderData;
 import org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore.StringPlaceholderData;
 import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
+import org.eclipse.jface.text.Assert;
+import org.eclipse.text.edits.*;
 
 
 /**
@@ -58,14 +40,14 @@
  * Idea:
  * - Get the AST for existing code 
  * - Describe changes
- * - This visitor analyses the changes or annotations and generates text edits
+ * - This visitor analyzes the changes or annotations and generates text edits
  * (text manipulation API) that describe the required code changes. 
  */
 public final class ASTRewriteAnalyzer extends ASTVisitor {
 	
 	/**
-	 * Internal synonynm for deprecated constant AST.JLS2
-	 * to alleviate deprecation warnings.
+	 * Internal synonym for deprecated constant AST.JLS2
+	 * to alleviate deprecated warnings.
 	 * @deprecated
 	 */
 	/*package*/ static final int JLS2_INTERNAL = AST.JLS2;
@@ -78,7 +60,8 @@
 	private final Map sourceCopyInfoToEdit;
 	private final Stack sourceCopyEndNodes;
 	
-	private final IDocument document;
+	private final char[] content;
+	private final LineInformation lineInfo;
 	private final ASTRewriteFormatter formatter;
 	private final NodeInfoStore nodeInfos;
 	private final TargetSourceRangeComputer extendedSourceRangeComputer;
@@ -86,16 +69,17 @@
 	/*
 	 * Constructor for ASTRewriteAnalyzer.
 	 */
-	public ASTRewriteAnalyzer(IDocument document, TextEdit rootEdit, RewriteEventStore eventStore, NodeInfoStore nodeInfos, Map options, TargetSourceRangeComputer extendedSourceRangeComputer) {
+	public ASTRewriteAnalyzer(char[] content, LineInformation lineInfo, String lineDelim, TextEdit rootEdit, RewriteEventStore eventStore, NodeInfoStore nodeInfos, Map options, TargetSourceRangeComputer extendedSourceRangeComputer) {
 		this.eventStore= eventStore;
-		this.document= document;
+		this.content= content;
+		this.lineInfo= lineInfo;
 		this.nodeInfos= nodeInfos;
 		this.tokenScanner= null;
 		this.currentEdit= rootEdit;
 		this.sourceCopyInfoToEdit= new IdentityHashMap();
 		this.sourceCopyEndNodes= new Stack();
-
-		this.formatter= new ASTRewriteFormatter(nodeInfos, eventStore, options, TextUtilities.getDefaultLineDelimiter(document));
+		
+		this.formatter= new ASTRewriteFormatter(nodeInfos, eventStore, options, lineDelim);
 		
 		this.extendedSourceRangeComputer = extendedSourceRangeComputer;
 	}
@@ -103,14 +87,18 @@
 	final TokenScanner getScanner() {
 		if (this.tokenScanner == null) {
 			IScanner scanner= ToolFactory.createScanner(true, false, false, false);
-			scanner.setSource(getDocument().get().toCharArray());
-			this.tokenScanner= new TokenScanner(scanner, getDocument());
+			scanner.setSource(this.content);
+			this.tokenScanner= new TokenScanner(scanner);
 		}
 		return this.tokenScanner;
 	}
 	
-	final IDocument getDocument() {
-		return this.document;
+	final char[] getContent() {
+		return this.content;
+	}
+	
+	final LineInformation getLineInformation() {
+		return this.lineInfo;
 	}
 	
 	/**
@@ -219,14 +207,23 @@
 	    return this.formatter.createIndentString(indent);
 	}
 	
-	final String getIndentAtOffset(int pos) {
-		try {
-			IRegion line= getDocument().getLineInformationOfOffset(pos);
-			String str= getDocument().get(line.getOffset(), line.getLength());
-			return this.formatter.getIndentString(str);
-		} catch (BadLocationException e) {
-			return ""; //$NON-NLS-1$
+	final private String getIndentOfLine(int pos) {
+		int line= getLineInformation().getLineOfOffset(pos);
+		if (pos >= 0) {
+			char[] cont= getContent();
+			int lineStart= getLineInformation().getLineOffset(line);
+		    int i= lineStart;
+			while (i < cont.length && Indents.isIndentChar(content[i])) {
+			    i++;
+			}
+			return new String(cont, lineStart, i - lineStart);
 		}
+		return new String();
+	}
+	
+		
+	final String getIndentAtOffset(int pos) {
+		return this.formatter.getIndentString(getIndentOfLine(pos));
 	}
 	
 	final void doTextInsert(int offset, String insertString, TextEditGroup editGroup) {
@@ -804,30 +801,28 @@
 		}
 
 		private int countEmptyLines(ASTNode last) {
-			IDocument doc= getDocument();
-			try {
-				int lastLine= doc.getLineOfOffset(last.getStartPosition() + last.getLength());
-				int scanLine= lastLine + 1;
-				int numLines= doc.getNumberOfLines();
-				while(scanLine < numLines && containsOnlyWhitespaces(doc, scanLine)) {
-					scanLine++;
+			LineInformation lineInformation= getLineInformation();
+			int lastLine= lineInformation.getLineOfOffset(getExtendedEnd(last));
+			if (lastLine >= 0) {
+				int startLine= lastLine + 1;
+				int start= lineInformation.getLineOffset(startLine);
+				if (start < 0) {
+					return 0;
 				}
-				return scanLine - lastLine - 1;
-			} catch (BadLocationException e) {
-				handleException(e);
-				return 0;
-			}	
-		}
-		
-		private boolean containsOnlyWhitespaces(IDocument doc, int line) throws BadLocationException {
-			int offset= doc.getLineOffset(line);
-			int end= offset + doc.getLineLength(line);
-			while (offset < end && Character.isWhitespace(doc.getChar(offset))) {
-				offset++;
+				char[] cont= getContent();
+				int i= start;
+				while (i < cont.length && Character.isWhitespace(cont[i])) {
+					i++;
+				}
+				if (i > start) {
+					lastLine= lineInformation.getLineOfOffset(i);
+					if (lastLine > startLine) {
+						return lastLine - startLine;
+					}
+				}
 			}
-			return offset == end;
-		}
-		
+			return 0;
+		}		
 	}
 		
 	private int rewriteParagraphList(ASTNode parent, StructuralPropertyDescriptor property, int insertPos, int insertIndent, int separator, int lead) {
@@ -994,14 +989,8 @@
 		return pos;
 	}
 	
-	final int getIndent(int pos) {
-		try {
-			IRegion line= getDocument().getLineInformationOfOffset(pos);
-			String str= getDocument().get(line.getOffset(), line.getLength());
-			return this.formatter.computeIndentUnits(str);
-		} catch (BadLocationException e) {
-			return 0;
-		}
+	final int getIndent(int offset) {
+		return this.formatter.computeIndentUnits(getIndentOfLine(offset));
 	}
 
 	final void doTextInsert(int insertOffset, ASTNode node, int initialIndentLevel, boolean removeLeadingIndent, TextEditGroup editGroup) {		
@@ -2892,17 +2881,13 @@
 		
 	private int findTagNameEnd(TagElement tagNode) {
 		if (tagNode.getTagName() != null) {
-		    try {
-		        IDocument doc = getDocument();
-		        int len= doc.getLength();
-		        int i= tagNode.getStartPosition();
-		        while (i < len && !Indents.isIndentChar(doc.getChar(i))) {
-		            i++;
-		        }
-		        return i;
-		    } catch (BadLocationException e) {
-		        handleException(e);
-		    }
+			char[] cont= getContent();
+		    int len= cont.length;
+			int i= tagNode.getStartPosition();
+			while (i < len && !Indents.isIndentChar(cont[i])) {
+			    i++;
+			}
+			return i;
 		}
 	    return tagNode.getStartPosition();
 	}
diff --git a/dom/org/eclipse/jdt/internal/core/dom/rewrite/LineInformation.java b/dom/org/eclipse/jdt/internal/core/dom/rewrite/LineInformation.java
new file mode 100644
index 0000000..9b2e3eb
--- /dev/null
+++ b/dom/org/eclipse/jdt/internal/core/dom/rewrite/LineInformation.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.core.dom.rewrite;
+
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+
+/**
+ * 
+ */
+public abstract class LineInformation {
+	
+	public static LineInformation create(final IDocument doc) {
+		return new LineInformation() {
+			public int getLineOfOffset(int offset) {
+				try {
+					return doc.getLineOfOffset(offset);
+				} catch (BadLocationException e) {
+					return -1;
+				}
+			}
+
+			public int getLineOffset(int line) {
+				try {
+					return doc.getLineOffset(line);
+				} catch (BadLocationException e) {
+					return -1;
+				}
+			}
+		};
+	}
+	
+	public static LineInformation create(final CompilationUnit astRoot) {
+		return new LineInformation() {
+			public int getLineOfOffset(int offset) {
+				return astRoot.getLineNumber(offset) - 1;
+			}
+			public int getLineOffset(int line) {
+				return astRoot.getPosition(line + 1, 0);
+			}
+		};
+	}
+	
+	
+	
+	public abstract int getLineOfOffset(int offset);
+	public abstract int getLineOffset(int line);
+	
+}
diff --git a/dom/org/eclipse/jdt/internal/core/dom/rewrite/TokenScanner.java b/dom/org/eclipse/jdt/internal/core/dom/rewrite/TokenScanner.java
index 67f20a0..1cd93f6 100644
--- a/dom/org/eclipse/jdt/internal/core/dom/rewrite/TokenScanner.java
+++ b/dom/org/eclipse/jdt/internal/core/dom/rewrite/TokenScanner.java
@@ -13,13 +13,7 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
-
-import org.eclipse.jface.text.BadLocationException;
-import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.IRegion;
-
 import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.ToolFactory;
 import org.eclipse.jdt.core.compiler.IScanner;
 import org.eclipse.jdt.core.compiler.ITerminalSymbols;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
@@ -34,40 +28,17 @@
 	public static final int DOCUMENT_ERROR= 20003;
 	
 	private final IScanner scanner;
-	private final IDocument document;
 	private final int endPosition;
 	
 	/**
 	 * Creates a TokenScanner
-	 * @param scanner The scanner to be wrapped. The scanner has to support line information
-	 * if the comment position methods are used.
+	 * @param scanner The scanner to be wrapped
 	 */
 	public TokenScanner(IScanner scanner) {
-		this(scanner, null);
-	}
-	
-	/**
-	 * Creates a TokenScanner
-	 * @param scanner The scanner to be wrapped
-	 * @param document The document used for line information if specified
-	 */
-	public TokenScanner(IScanner scanner, IDocument document) {
 		this.scanner= scanner;
 		this.endPosition= this.scanner.getSource().length - 1;
-		this.document= document;
 	}
-	
-	/**
-	 * Creates a TokenScanner
-	 * @param document The textbuffer to create the scanner on
-	 */
-	public TokenScanner(IDocument document) {
-		this.scanner= ToolFactory.createScanner(true, false, false, false);
-		this.scanner.setSource(document.get().toCharArray());
-		this.document= document;
-		this.endPosition= this.scanner.getSource().length - 1;
-	}		
-		
+			
 	/**
 	 * Returns the wrapped scanner
 	 * @return IScanner
@@ -126,26 +97,7 @@
 		} while (ignoreComments && isComment(curr));
 		return curr;
 	}
-	
-	/**
-	 * Reads the next token.
-	 * @param ignoreComments If set, comments will be overread.
-	 * @return Return the token id.
-	 * @exception CoreException Thrown when the end of the file has been reached (code END_OF_FILE)
-	 * or a lexical error was detected while scanning (code LEXICAL_ERROR)
-	 */
-	private int readNextWithEOF(boolean ignoreComments) throws CoreException {
-		int curr= 0;
-		do {
-			try {
-				curr= this.scanner.getNextToken();
-			} catch (InvalidInputException e) {
-				throw new CoreException(createError(LEXICAL_ERROR, e.getMessage(), e));
-			}
-		} while (ignoreComments && isComment(curr));
-		return curr;
-	}	
-	
+		
 	/**
 	 * Reads the next token from the given offset.
 	 * @param offset The offset to start reading from.
@@ -254,148 +206,6 @@
 		}
 		return res;
 	}
-	
-	/**
-	 * Evaluates the start offset of comments directly ahead of a token specified by its start offset
-	 * 
-	 * @param lastPos An offset to before the node start offset. Can be 0 but better is the end location of the previous node. 
-	 * @param nodeStart Start offset of the node to find the comments for.
-	 * @return Returns the start offset of comments directly ahead of a token.
-	 * @exception CoreException Thrown when a lexical error was detected while scanning (code LEXICAL_ERROR)
-	 */		
-	public int getTokenCommentStart(int lastPos, int nodeStart) throws CoreException {
-		setOffset(lastPos);
-
-		int prevEndPos= lastPos;
-		int prevEndLine= prevEndPos > 0 ? getLineOfOffset(prevEndPos - 1) : 0;
-		int nodeLine= getLineOfOffset(nodeStart);
-		
-		int res= -1;
-
-		int curr= readNextWithEOF(false);
-		int currStartPos= getCurrentStartOffset();
-		int currStartLine= getLineOfOffset(currStartPos);
-		while (curr != ITerminalSymbols.TokenNameEOF && nodeStart > currStartPos) {
-			if (TokenScanner.isComment(curr)) {
-				int linesDifference= currStartLine - prevEndLine;
-				if ((linesDifference > 1) || (res == -1 && (linesDifference != 0 || nodeLine == currStartLine))) {
-					res= currStartPos; // begin new
-				}
-			} else {
-				res= -1;
-			}
-			
-			if (curr == ITerminalSymbols.TokenNameCOMMENT_LINE) {
-				prevEndLine= currStartLine;
-			} else {
-				prevEndLine= getLineOfOffset(getCurrentEndOffset() - 1);
-			}					
-			curr= readNextWithEOF(false);
-			currStartPos= getCurrentStartOffset();
-			currStartLine= getLineOfOffset(currStartPos);
-		}
-		if (res == -1 || curr == ITerminalSymbols.TokenNameEOF) {
-			return nodeStart;
-		}
-		if (currStartLine - prevEndLine > 1) {
-			return nodeStart;
-		}			
-		return res;
-	}
-	
-	/**
-	 * Looks for comments after a node and returns the end position of the comment still belonging to the node.
-	 * @param nodeEnd The end position of the node
-	 * @param nextTokenStart The start positoion of the next node. Optional, can be -1
-	 * the line information shoould be taken from the scanner object
-	 * @return Returns returns the end position of the comment still belonging to the node.
-	 * @exception CoreException Thrown when the end of the file has been reached (code END_OF_FILE)
-	 * or a lexical error was detected while scanning (code LEXICAL_ERROR)
-	 */		
-	public int getTokenCommentEnd(int nodeEnd, int nextTokenStart) throws CoreException {
-		// assign comments to the previous comments as long they are all on the same line as the
-		// node end position or if they are on the next line but there is a separation from the next
-		// node
-		// } //aa
-		// // aa
-		//
-		// // bb
-		// public void b...
-		//
-		// } /* cc */ /*
-		// cc/*
-		// /*dd*/
-		// public void d...
-		
-		int prevEndLine= getLineOfOffset(nodeEnd - 1);
-		int prevEndPos= nodeEnd;
-		int res= nodeEnd;
-		boolean sameLineComment= true;
-		
-		setOffset(nodeEnd);
-		
-		
-		int curr= readNextWithEOF(false);
-		while (curr == ITerminalSymbols.TokenNameCOMMENT_LINE || curr == ITerminalSymbols.TokenNameCOMMENT_BLOCK) {
-			int currStartLine= getLineOfOffset(getCurrentStartOffset());
-			int linesDifference= currStartLine - prevEndLine;
-
-			if (linesDifference > 1) {
-				return prevEndPos; // separated comments
-			}
-
-			if (curr == ITerminalSymbols.TokenNameCOMMENT_LINE) {
-				prevEndPos= getLineEnd(currStartLine);
-				prevEndLine= currStartLine;
-			} else {
-				prevEndPos= getCurrentEndOffset();
-				prevEndLine= getLineOfOffset(prevEndPos - 1);
-			}
-			if (sameLineComment) {
-				if (linesDifference == 0) {
-					res= prevEndPos;
-				} else {
-					sameLineComment= false;
-				}
-			}
-			curr= readNextWithEOF(false);
-		}
-		if (curr == ITerminalSymbols.TokenNameEOF) {
-			return prevEndPos;
-		}
-		int currStartLine= getLineOfOffset(getCurrentStartOffset());
-		int linesDifference= currStartLine - prevEndLine;
-		if (linesDifference > 1) {
-			return prevEndPos; // separated comments
-		}
-		return res;
-	}
-	
-	private int getLineOfOffset(int offset) throws CoreException {
-		if (this.document != null) {
-			try {
-				return this.document.getLineOfOffset(offset);
-			} catch (BadLocationException e) {
-				String message= "Illegal offset: " + offset; //$NON-NLS-1$
-				throw new CoreException(createError(DOCUMENT_ERROR, message, e));
-			}
-		}
-		return getScanner().getLineNumber(offset);
-	}
-	
-	private int getLineEnd(int line) throws CoreException {
-		if (this.document != null) {
-			try {
-				IRegion region= this.document.getLineInformation(line);
-				return region.getOffset() + region.getLength();
-			} catch (BadLocationException e) {
-				String message= "Illegal line: " + line; //$NON-NLS-1$
-				throw new CoreException(createError(DOCUMENT_ERROR, message, e));
-			}
-		}
-		return getScanner().getLineEnd(line);
-	}			
-	
 		
 	public static boolean isComment(int token) {
 		return token == ITerminalSymbols.TokenNameCOMMENT_BLOCK || token == ITerminalSymbols.TokenNameCOMMENT_JAVADOC 
diff --git a/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java b/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java
index 356f0c7..23bc45a 100644
--- a/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java
+++ b/eval/org/eclipse/jdt/internal/eval/CodeSnippetAllocationExpression.java
@@ -15,6 +15,7 @@
 import org.eclipse.jdt.internal.compiler.ast.Expression;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 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.FieldBinding;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
@@ -120,7 +121,7 @@
 }
 public TypeBinding resolveType(BlockScope scope) {
 	// Propagate the type checking to the arguments, and check if the constructor is defined.
-	this.constant = NotAConstant;
+	this.constant = Constant.NotAConstant;
 	this.resolvedType = this.type.resolveType(scope, true /* check bounds*/); // will check for null after args are resolved
 
 	// buffering the arguments' types
diff --git a/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java b/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
index 6e2d14d..e015aca 100644
--- a/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
+++ b/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java
@@ -14,7 +14,6 @@
 import org.eclipse.jdt.internal.compiler.ClassFile;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 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.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
@@ -141,11 +140,6 @@
 	// add its fields
 	FieldBinding[] fields = typeBinding.fields;
 	if ((fields != null) && (fields != NoFields)) {
-		for (int i = 0, max = fields.length; i < max; i++) {
-			if (fields[i].constant() == null) {
-				FieldReference.getConstantFor(fields[i], null, false, null);
-			}
-		}
 		classFile.addFieldInfos();
 	} else {
 		// we have to set the number of fields to be equals to 0
diff --git a/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java b/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java
index 30f6ff2..f04b326 100644
--- a/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java
+++ b/eval/org/eclipse/jdt/internal/eval/CodeSnippetFieldReference.java
@@ -19,6 +19,7 @@
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+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.ParameterizedFieldBinding;
@@ -77,7 +78,7 @@
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 
 	int pc = codeStream.position;
-	if (this.constant != NotAConstant) {
+	if (this.constant != Constant.NotAConstant) {
 		if (valueRequired) {
 			codeStream.generateConstant(this.constant, this.implicitConversion);
 		}
@@ -85,7 +86,8 @@
 		boolean isStatic = this.codegenBinding.isStatic();
 		this.receiver.generateCode(currentScope, codeStream, !isStatic);
 		if (valueRequired) {
-			if (!this.codegenBinding.isConstantValue()) {
+			Constant fieldConstant = this.codegenBinding.constant();
+			if (fieldConstant == Constant.NotAConstant) {
 				if (this.codegenBinding.declaringClass == null) { // array length
 					codeStream.arraylength();
 				} else {
@@ -109,7 +111,7 @@
 					codeStream.invokeObjectGetClass(); // perform null check
 					codeStream.pop();
 				}
-				codeStream.generateConstant(this.codegenBinding.constant(), this.implicitConversion);
+				codeStream.generateConstant(fieldConstant, this.implicitConversion);
 			}
 		} else {
 			if (!isStatic){
@@ -313,7 +315,7 @@
 	if (this.binding.declaringClass != someReceiverType
 			&& !someReceiverType.isArrayType()
 			&& this.binding.declaringClass != null // array.length
-			&& !this.binding.isConstantValue()) {
+			&& this.binding.constant() == Constant.NotAConstant) {
 	
 		CompilerOptions options = currentScope.compilerOptions();
 		if ((options.targetJDK >= ClassFileConstants.JDK1_2
@@ -336,7 +338,7 @@
 	// regular receiver reference 
 	this.receiverType = this.receiver.resolveType(scope);
 	if (this.receiverType == null){
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		return null;
 	}
 	// the case receiverType.isArrayType and token = 'length' is handled by the scope API
@@ -350,12 +352,12 @@
 				if (this.evaluationContext.declaringTypeName != null) {
 					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;
+						this.constant = Constant.NotAConstant;
 						scope.problemReporter().invalidField(this, this.receiverType);
 						return null;
 					}
 				} else {
-					this.constant = NotAConstant;
+					this.constant = Constant.NotAConstant;
 					scope.problemReporter().invalidField(this, this.receiverType);
 					return null;
 				}
@@ -365,7 +367,7 @@
 	}
 
 	if (!this.binding.isValidBinding()) {
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		if (isNotVisible) {
 			this.codegenBinding = this.binding = firstAttempt;
 		}
@@ -377,9 +379,9 @@
 		scope.problemReporter().deprecatedField(this.binding, this);
 	}
 	// check for this.x in static is done in the resolution of the receiver
-	this.constant = FieldReference.getConstantFor(this.binding, this, this.receiver.isImplicitThis(), scope);
+	this.constant = this.receiver.isImplicitThis() ? this.binding.constant() : Constant.NotAConstant;
 	if (!this.receiver.isThis()) {
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 	}
 	return this.resolvedType = this.binding.type;
 }
diff --git a/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java b/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java
index f660807..020a717 100644
--- a/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java
+++ b/eval/org/eclipse/jdt/internal/eval/CodeSnippetMessageSend.java
@@ -19,6 +19,7 @@
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
 import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
@@ -198,7 +199,7 @@
 	// Answer the signature return type
 	// Base type promotion
 
-	this.constant = NotAConstant;
+	this.constant = Constant.NotAConstant;
 	boolean receiverCast = false, argsContainCast = false; 
 	if (this.receiver instanceof CastExpression) {
 		this.receiver.bits |= DisableUnnecessaryCastCheck; // will check later on
@@ -267,12 +268,12 @@
 			if (this.evaluationContext.declaringTypeName != null) {
 				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;
+					this.constant = Constant.NotAConstant;
 					scope.problemReporter().invalidMethod(this, this.binding);
 					return null;
 				}
 			} else {
-				this.constant = NotAConstant;
+				this.constant = Constant.NotAConstant;
 				scope.problemReporter().invalidMethod(this, this.binding);
 				return null;
 			}
diff --git a/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java b/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java
index 15dce9f..215d419 100644
--- a/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java
+++ b/eval/org/eclipse/jdt/internal/eval/CodeSnippetQualifiedNameReference.java
@@ -13,7 +13,6 @@
 import org.eclipse.jdt.internal.compiler.ast.Assignment;
 import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
 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.ast.QualifiedNameReference;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -84,7 +83,7 @@
 }
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 	int pc = codeStream.position;
-	if (this.constant != NotAConstant) {
+	if (this.constant != Constant.NotAConstant) {
 		if (valueRequired) {
 			codeStream.generateConstant(this.constant, this.implicitConversion);
 		}
@@ -95,13 +94,14 @@
 				codeStream.arraylength();
 				codeStream.generateImplicitConversion(this.implicitConversion);
 			} else {
-				if (lastFieldBinding.isConstantValue()) {
+				Constant fieldConstant = lastFieldBinding.constant();
+				if (fieldConstant != Constant.NotAConstant) {
 					if (!lastFieldBinding.isStatic()){
 						codeStream.invokeObjectGetClass();
 						codeStream.pop();
 					}
 					// inline the last field constant
-					codeStream.generateConstant(lastFieldBinding.constant(), this.implicitConversion);
+					codeStream.generateConstant(fieldConstant, this.implicitConversion);
 				} else {	
 					if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
 						if (lastFieldBinding.isStatic()) {
@@ -294,7 +294,7 @@
 			lastFieldBinding = (FieldBinding) this.codegenBinding;
 			lastGenericCast = this.genericCast;
 			// if first field is actually constant, we can inline it
-			if (lastFieldBinding.isConstantValue()) {
+			if (lastFieldBinding.constant() != Constant.NotAConstant) {
 				break;
 			}
 			if (needValue) {
@@ -327,8 +327,9 @@
 			if (!needValue) break; // no value needed
 			LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
 			// regular local variable read
-			if (localBinding.isConstantValue()) {
-				codeStream.generateConstant(localBinding.constant(), 0);
+			Constant localConstant = localBinding.constant();
+			if (localConstant != Constant.NotAConstant) {
+				codeStream.generateConstant(localConstant, 0);
 				// no implicit conversion
 			} else {
 				// outer local?
@@ -352,12 +353,13 @@
 				needValue = !nextField.isStatic();
 				if (needValue) {
 					if (lastFieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-						if (lastFieldBinding.isConstantValue()) {
+						Constant fieldConstant = lastFieldBinding.constant();
+						if (fieldConstant != Constant.NotAConstant) {
 							if (lastFieldBinding != this.codegenBinding && !lastFieldBinding.isStatic()) {
 								codeStream.invokeObjectGetClass(); // perform null check
 								codeStream.pop();
 							}
-							codeStream.generateConstant(lastFieldBinding.constant(), 0);
+							codeStream.generateConstant(fieldConstant, 0);
 						} else if (lastFieldBinding.isStatic()) {
 							codeStream.getstatic(lastFieldBinding);
 						} else {
@@ -418,7 +420,7 @@
 	TypeBinding type = ((VariableBinding) this.binding).type;
 	int index = this.indexOfFirstFieldBinding;
 	if (index == length) { //	restrictiveFlag == FIELD
-		this.constant = FieldReference.getConstantFor((FieldBinding) this.binding, this, false, scope);
+		this.constant = ((FieldBinding) this.binding).constant();
 		return type;
 	}
 
@@ -427,10 +429,7 @@
 	this.otherCodegenBindings = this.otherBindings = new FieldBinding[otherBindingsLength];
 	
 	// fill the first constant (the one of the binding)
-	this.constant =
-		((this.bits & Binding.FIELD) != 0)
-			? FieldReference.getConstantFor((FieldBinding) this.binding, this, false, scope)
-			: ((VariableBinding) this.binding).constant();
+	this.constant =((VariableBinding) this.binding).constant();
 
 	// iteration on each field	
 	while (index < length) {
@@ -449,7 +448,7 @@
 						return super.reportError(scope);
 					}
 				} else {
-					this.constant = NotAConstant; //don't fill other constants slots...
+					this.constant = Constant.NotAConstant; //don't fill other constants slots...
 					scope.problemReporter().invalidField(this, field, index, type);
 					return null;
 				}
@@ -462,15 +461,14 @@
 			if (isFieldUseDeprecated(field, scope, (this.bits & IsStrictlyAssigned) !=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;
+			if (this.constant != Constant.NotAConstant){
+				this.constant = field.constant();
 			}
 			type = field.type;
 			index++;
 		} else {
-			this.constant = NotAConstant; //don't fill other constants slots...
+			this.constant = Constant.NotAConstant; //don't fill other constants slots...
 			scope.problemReporter().invalidField(this, field, index, type);
 			return null;
 		}
@@ -523,7 +521,7 @@
 		if (fieldBinding.declaringClass != lastReceiverType
 				&& !lastReceiverType.isArrayType()
 				&& fieldBinding.declaringClass != null // array.length
-				&& !fieldBinding.isConstantValue()) {
+				&& fieldBinding.constant() == Constant.NotAConstant) {
 			CompilerOptions options = currentScope.compilerOptions();
 			if ((options.targetJDK >= ClassFileConstants.JDK1_2
 					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || (index < 0 ? fieldBinding != binding : index > 0) || this.indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
diff --git a/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java b/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java
index 024e753..c89eb9d 100644
--- a/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java
+++ b/eval/org/eclipse/jdt/internal/eval/CodeSnippetReturnStatement.java
@@ -16,6 +16,7 @@
 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.Constant;
 import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
 import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
 import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
@@ -123,7 +124,7 @@
 				return;
 			}
 			// in constant case, the implicit conversion cannot be left uninitialized
-			if (this.expression.constant != NotAConstant) {
+			if (this.expression.constant != Constant.NotAConstant) {
 				// fake 'no implicit conversion' (the return type is always void)
 				this.expression.implicitConversion = this.expression.constant.typeID() << 4;
 			}
diff --git a/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java b/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
index 36fbe99..b0308de 100644
--- a/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
+++ b/eval/org/eclipse/jdt/internal/eval/CodeSnippetSingleNameReference.java
@@ -14,7 +14,6 @@
 import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
 import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
 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.ast.SingleNameReference;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -93,11 +92,11 @@
 			scope.problemReporter().staticFieldAccessToNonStaticVariable(
 				this,
 				fieldBinding);
-			this.constant = NotAConstant;
+			this.constant = Constant.NotAConstant;
 			return null;
 		}
 	}
-	this.constant = FieldReference.getConstantFor(fieldBinding, this, true, scope);
+	this.constant = fieldBinding.constant();
 
 	if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssigned) !=0)) {
 		scope.problemReporter().deprecatedField(fieldBinding, this);
@@ -123,7 +122,7 @@
 		if ((operation.right instanceof SingleNameReference)
 			&& ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
 			&& ((variableReference = (SingleNameReference) operation.right).binding == this.binding)
-			&& (operation.left.constant != NotAConstant) // exclude non constant expressions, since could have side-effect
+			&& (operation.left.constant != Constant.NotAConstant) // exclude non constant expressions, since could have side-effect
 			&& (((operation.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString) // exclude string concatenation which would occur backwards
 			&& (((operation.right.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) != T_JavaLangString)) { // 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
@@ -184,7 +183,7 @@
 			if (localBinding.resolvedPosition != -1) {
 				assignment.expression.generateCode(currentScope, codeStream, true);
 			} else {
-				if (assignment.expression.constant != NotAConstant) {
+				if (assignment.expression.constant != Constant.NotAConstant) {
 					// assigning an unused local to a constant value = no actual assignment is necessary
 					if (valueRequired) {
 						codeStream.generateConstant(assignment.expression.constant, assignment.implicitConversion);
@@ -218,70 +217,72 @@
 }
 public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
 	int pc = codeStream.position;
-	if (this.constant != NotAConstant) {
+	if (this.constant != Constant.NotAConstant) {
 		if (valueRequired) {
 			codeStream.generateConstant(this.constant, this.implicitConversion);
 		}
 	} else {
 		switch (this.bits & RestrictiveFlagMASK) {
 			case Binding.FIELD : // reading a field
-				FieldBinding fieldBinding;
-				if (valueRequired) {
-					if (!(fieldBinding = (FieldBinding) this.codegenBinding).isConstantValue()) { // directly use inlined value for constant fields
-						if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
-							 // directly use inlined value for constant fields
-							boolean isStatic;
-							if (!(isStatic = fieldBinding.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*/);
-									codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
-								} else {
-									generateReceiver(codeStream);
-								}
-							}
-							// managing private access							
-							if (isStatic) {
-								codeStream.getstatic(fieldBinding);
+				if (!valueRequired) 
+					break;
+				FieldBinding fieldBinding = (FieldBinding) this.codegenBinding;
+				Constant fieldConstant = fieldBinding.constant();
+				if (fieldConstant == Constant.NotAConstant) { // directly use inlined value for constant fields
+					if (fieldBinding.canBeSeenBy(getReceiverType(currentScope), this, currentScope)) {
+						 // directly use inlined value for constant fields
+						boolean isStatic;
+						if (!(isStatic = fieldBinding.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*/);
+								codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
 							} else {
-								codeStream.getfield(fieldBinding);
+								generateReceiver(codeStream);
+							}
+						}
+						// managing private access							
+						if (isStatic) {
+							codeStream.getstatic(fieldBinding);
+						} else {
+							codeStream.getfield(fieldBinding);
+						}
+					} else {
+						// managing private access
+						if (!fieldBinding.isStatic()) {
+							if ((this.bits & DepthMASK) != 0) {
+								// internal error, per construction we should have found it
+								// not yet supported
+								currentScope.problemReporter().needImplementation();
+							} else {
+								generateReceiver(codeStream);
 							}
 						} else {
-							// managing private access
-							if (!fieldBinding.isStatic()) {
-								if ((this.bits & DepthMASK) != 0) {
-									// internal error, per construction we should have found it
-									// not yet supported
-									currentScope.problemReporter().needImplementation();
-								} else {
-									generateReceiver(codeStream);
-								}
-							} else {
-								codeStream.aconst_null();
-							}
-							((CodeSnippetCodeStream)codeStream).generateEmulatedReadAccessForField(fieldBinding);
+							codeStream.aconst_null();
 						}
-						if (this.genericCast != null) codeStream.checkcast(this.genericCast);		
-						codeStream.generateImplicitConversion(this.implicitConversion);
-					} else { // directly use the inlined value
-						codeStream.generateConstant(fieldBinding.constant(), this.implicitConversion);
+						((CodeSnippetCodeStream)codeStream).generateEmulatedReadAccessForField(fieldBinding);
 					}
+					if (this.genericCast != null) codeStream.checkcast(this.genericCast);		
+					codeStream.generateImplicitConversion(this.implicitConversion);
+				} else { // directly use the inlined value
+					codeStream.generateConstant(fieldConstant, this.implicitConversion);
 				}
 				break;
 			case Binding.LOCAL : // reading a local
 				LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
-				if (valueRequired) {
-					// outer local?
-					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);
-					} else {
-						// regular local variable read
-						codeStream.load(localBinding);
-					}
-					codeStream.generateImplicitConversion(this.implicitConversion);
+				if (!valueRequired)
+					break;
+				// outer local?
+				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);
+				} else {
+					// regular local variable read
+					codeStream.load(localBinding);
 				}
+				codeStream.generateImplicitConversion(this.implicitConversion);
+				break;
 		}
 	}
 	codeStream.recordPositionsFrom(pc, this.sourceStart);
@@ -347,7 +348,7 @@
 					codeStream.store(localBinding, false);
 					return;
 				case T_int :
-					if (((assignConstant = expression.constant) != NotAConstant) 
+					if (((assignConstant = expression.constant) != Constant.NotAConstant) 
 						&& (assignConstant.typeID() != T_float) // only for integral types
 						&& (assignConstant.typeID() != T_double)		
 						&& ((increment = assignConstant.intValue()) == (short) increment)) { // 16 bits value
@@ -568,7 +569,7 @@
 
 	if (!flowInfo.isReachable()) return;
 	//If inlinable field, forget the access emulation, the code gen will directly target it
-	if (this.constant != NotAConstant)
+	if (this.constant != Constant.NotAConstant)
 		return;	
 	// if field from parameterized type got found, use the original field at codegen time
 	if (this.binding instanceof ParameterizedFieldBinding) {
@@ -589,7 +590,7 @@
 		// and not from Object or implicit static field access.	
 		if (fieldBinding.declaringClass != this.delegateThis.type
 				&& fieldBinding.declaringClass != null // array.length
-				&& !fieldBinding.isConstantValue()) {
+				&& fieldBinding.constant() == Constant.NotAConstant) {
 			CompilerOptions options = currentScope.compilerOptions();
 			if ((options.targetJDK >= ClassFileConstants.JDK1_2
 					&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic())
diff --git a/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java b/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java
index 38ce515..1b91d01 100644
--- a/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java
+++ b/eval/org/eclipse/jdt/internal/eval/CodeSnippetThisReference.java
@@ -12,6 +12,7 @@
 
 import org.eclipse.jdt.internal.compiler.ast.ThisReference;
 import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+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.InvocationSite;
@@ -86,7 +87,7 @@
 	public TypeBinding resolveType(BlockScope scope) {
 	
 		// implicit this
-		this.constant = NotAConstant;
+		this.constant = Constant.NotAConstant;
 		TypeBinding snippetType = null;
 		if (this.isImplicit || checkAccess(scope.methodScope())){
 			snippetType = scope.enclosingSourceType();
diff --git a/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java b/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
index f6f9fe2..7453bb6 100644
--- a/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
+++ b/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
@@ -4962,8 +4962,9 @@
 				} else if (!wasACase) {
 					this.scribe.printNewLine();
 				}
+				this.scribe.printComment();
 			}
-		}		
+		}
 		
 		if ((wasACase || wasAStatement) && this.preferences.indent_switchstatements_compare_to_cases) {
 			this.scribe.unIndent();
diff --git a/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor2.java b/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor2.java
index ba47c2d..08d0401 100644
--- a/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor2.java
+++ b/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor2.java
@@ -3068,6 +3068,7 @@
 				if (!wasACase) {
 					this.scribe.printNewLine();
 				}
+				this.scribe.printComment();
 			}
 		}		
 		
diff --git a/formatter/org/eclipse/jdt/internal/formatter/Scribe2.java b/formatter/org/eclipse/jdt/internal/formatter/Scribe2.java
index 84c89e7..7ecd4eb 100644
--- a/formatter/org/eclipse/jdt/internal/formatter/Scribe2.java
+++ b/formatter/org/eclipse/jdt/internal/formatter/Scribe2.java
@@ -542,14 +542,14 @@
 				return comment1.getStartPosition() - comment2.getStartPosition();
 			}
 		});
-		final int lineNumber = this.unit.lineNumber(sourceStart);
+		final int lineNumber = this.unit.getLineNumber(sourceStart);
 		if (index < 0) {
 			index = -index - 1;
 			final int commentLength = this.comments.size();
 			for (int i = index; i < commentLength; i++) {
 				Comment currentComment = (Comment) comments.get(i);
 				final int start = currentComment.getStartPosition();
-				if (this.unit.lineNumber(start) == lineNumber) {
+				if (this.unit.getLineNumber(start) == lineNumber) {
 					if (currentComment.isLineComment()) {
 						return CharOperation.indexOf(Scanner.TAG_PREFIX, this.scanner.source, true, start) != -1;
 					}
diff --git a/grammar/java_1_5.g b/grammar/java_1_5.g
index cfce289..8881e65 100644
--- a/grammar/java_1_5.g
+++ b/grammar/java_1_5.g
@@ -910,14 +910,18 @@
 /.$putCase consumeEmptyStatement(); $break ./
 /:$readableName EmptyStatement:/
 
-LabeledStatement ::= 'Identifier' ':' Statement
+LabeledStatement ::= Label ':' Statement
 /.$putCase consumeStatementLabel() ; $break ./
 /:$readableName LabeledStatement:/
 
-LabeledStatementNoShortIf ::= 'Identifier' ':' StatementNoShortIf
+LabeledStatementNoShortIf ::= Label ':' StatementNoShortIf
 /.$putCase consumeStatementLabel() ; $break ./
 /:$readableName LabeledStatement:/
 
+Label ::= 'Identifier'
+/.$putCase consumeLabel() ; $break ./
+/:$readableName Label:/
+
 ExpressionStatement ::= StatementExpression ';'
 /. $putCase consumeExpressionStatement(); $break ./
 ExpressionStatement ::= ExplicitConstructorInvocation
diff --git a/model/org/eclipse/jdt/core/CompletionContext.java b/model/org/eclipse/jdt/core/CompletionContext.java
index 57ab3d2..bf3d026 100644
--- a/model/org/eclipse/jdt/core/CompletionContext.java
+++ b/model/org/eclipse/jdt/core/CompletionContext.java
@@ -24,6 +24,25 @@
 public final class CompletionContext extends InternalCompletionContext {
 
 	/**
+	 * The completion token is unknown.
+	 * @since 3.2
+	 */
+	public static final int TOKEN_KIND_UNKNOWN = 0;
+	
+	/**
+	 * The completion token is a name.
+	 * @since 3.2
+	 */
+	public static final int TOKEN_KIND_NAME = 1;
+	/**
+	 * The completion token is a string literal.
+	 * The string literal ends quote can be not present the source.
+	 * <code>"foo"</code> or <code>"foo</code>. 
+	 * @since 3.2
+	 */
+	
+	public static final int TOKEN_KIND_STRING_LITERAL = 2;
+	/**
 	 * Tell user whether completion takes place in a javadoc comment or not.
 	 * 
 	 * @return boolean true if completion takes place in a javadoc comment, false otherwise.
@@ -88,4 +107,136 @@
 	public char[][] getExpectedTypesKeys() {
 		return this.expectedTypesKeys;
 	}
+	
+	/**
+	 * Returns the completed token.
+	 * This token is either the identifier or Java language keyword
+	 * or the string literal under, immediately preceding, 
+	 * the original request offset. If the original request offset
+	 * is not within or immediately after an identifier or keyword or
+	 * a string literal then the returned value is <code>null</code>.
+	 * 
+	 * @return completed token or <code>null</code>
+	 * @since 3.2
+	 */
+	public char[] getToken() {
+		return this.token;
+	}
+	
+	/**
+	 * Returns the kind of completion token being proposed.
+	 * <p>
+	 * The set of different kinds of completion token is
+	 * expected to change over time. It is strongly recommended
+	 * that clients do <b>not</b> assume that the kind is one of the
+	 * ones they know about, and code defensively for the
+	 * possibility of unexpected future growth.
+	 * </p>
+	 * 
+	 * @return the kind; one of the kind constants declared on
+	 * this class whose name starts with <code>TOKEN_KIND</code>,
+	 * or possibly a kind unknown to the caller
+	 * @since 3.2
+	 */
+	public int getTokenKind() {
+		return this.tokenKind;
+	}
+	
+	/**
+	 * Returns the character index of the start of the
+	 * subrange in the source file buffer containing the
+	 * relevant token being completed. This
+	 * token is either the identifier or Java language keyword
+	 * under, or immediately preceding, the original request 
+	 * offset. If the original request offset is not within
+	 * or immediately after an identifier or keyword, then the
+	 * position returned is original request offset and the
+	 * token range is empty.
+	 * 
+	 * @return character index of token start position (inclusive)
+	 * @since 3.2
+	 */
+	public int getTokenStart() {
+		return this.tokenStart;
+	}
+	
+	/**
+	 * Returns the character index of the end (exclusive) of the subrange
+	 * in the source file buffer containing the
+	 * relevant token. When there is no relevant token, the
+	 * range is empty
+	 * (<code>getTokenEnd() == getTokenStart()</code>).
+	 * 
+	 * @return character index of token end position (exclusive)
+	 * @since 3.2
+	 */
+	public int getTokenEnd() {
+		return this.tokenEnd;
+	}
+	
+	/**
+	 * Returns the offset position in the source file buffer
+	 * after which code assist is requested.
+	 * 
+	 * @return offset position in the source file buffer
+	 * @since 3.2
+	 */
+	public int getOffset() {
+		return this.offset;
+	}
+	
+	public String toString() {
+		StringBuffer buffer = new StringBuffer();
+		
+		buffer.append("completion offset="); //$NON-NLS-1$
+		buffer.append(this.offset);
+		buffer.append('\n');
+		
+		buffer.append("completion range=["); //$NON-NLS-1$
+		buffer.append(this.tokenStart);
+		buffer.append(", "); //$NON-NLS-1$
+		buffer.append(this.tokenEnd);
+		buffer.append("]\n"); //$NON-NLS-1$
+		
+		buffer.append("completion token="); //$NON-NLS-1$
+		String string = "null"; //$NON-NLS-1$
+		if(token == null) {
+			buffer.append(string);
+		} else {
+			buffer.append('\"');
+			buffer.append(this.token);
+			buffer.append('\"');
+		}
+		buffer.append('\n');
+		
+		buffer.append("expectedTypesSignatures="); //$NON-NLS-1$
+		if(this.expectedTypesSignatures == null) {
+			buffer.append(string);
+		} else {
+			buffer.append('{');
+			for (int i = 0; i < this.expectedTypesSignatures.length; i++) {
+				if(i > 0) buffer.append(',');
+				buffer.append(this.expectedTypesSignatures[i]);
+				
+			}
+			buffer.append('}');
+		}
+		buffer.append('\n');
+		
+		buffer.append("expectedTypesKeys="); //$NON-NLS-1$
+		if(expectedTypesSignatures == null) {
+			buffer.append(string);
+		} else {
+			buffer.append('{');
+			for (int i = 0; i < this.expectedTypesKeys.length; i++) {
+				if(i > 0) buffer.append(',');
+				buffer.append(this.expectedTypesKeys[i]);
+				
+			}
+			buffer.append('}');
+		}
+		buffer.append('\n');
+			
+		return buffer.toString();
+	}
 }
diff --git a/model/org/eclipse/jdt/core/ICompilationUnit.java b/model/org/eclipse/jdt/core/ICompilationUnit.java
index e714fac..885b640 100644
--- a/model/org/eclipse/jdt/core/ICompilationUnit.java
+++ b/model/org/eclipse/jdt/core/ICompilationUnit.java
@@ -407,7 +407,7 @@
  * 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
+ * @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. 
diff --git a/model/org/eclipse/jdt/core/IJavaElement.java b/model/org/eclipse/jdt/core/IJavaElement.java
index ba23088..6e86fd2 100644
--- a/model/org/eclipse/jdt/core/IJavaElement.java
+++ b/model/org/eclipse/jdt/core/IJavaElement.java
@@ -13,6 +13,7 @@
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.jobs.ISchedulingRule;
 
 /**
@@ -157,6 +158,35 @@
 	 * @since 2.0
 	 */
 	IJavaElement getAncestor(int ancestorType);
+	
+	/**
+	 * <p>Returns the Javadoc as an html source if this element has an attached javadoc,
+	 * null otherwise.</p> 
+	 * <p>This should be used only for binary elements. Source elements will always return null.
+	 * The encoding used to read the javadoc is the one defined by the content type of the
+	 * file. If none is defined, then the specified encoding will be used as the default encoding.</p>
+	 * <p>In case of the javadoc doesn't exist for this element, null is returned.</p>
+	 * 
+	 * <p>The html is extracted from the attached javadoc and provided as is. No
+	 * transformation or validation is done.</p>
+	 *
+	 * <p>If the default encoding is set to null, the default encoding of the project is used. If
+	 * the default encoding of the project is not supported, then the platform encoding is used.</p>
+	 * 
+	 * <p>NOTE: This API is subject to change before the 3.2 release.</p>
+	 * 
+	 * @param monitor the given progress monitor
+	 * @param defaultEncoding the given default encoding
+	 * @exception JavaModelException if:<ul>
+	 *  <li>this element does not exist</li>
+	 *  <li>retrieving the attached javadoc fails (timed-out, invalid URL, ...)
+	 *  <li>the format of the javadoc doesn't match expected standards (different anchors,...)</li>
+	 *  </ul>
+	 * @return the extracted javadoc from the attached javadoc, null if none
+	 * @see IClasspathAttribute#JAVADOC_LOCATION_ATTRIBUTE_NAME
+	 * @since 3.2
+	 */
+	String getAttachedJavadoc(IProgressMonitor monitor, String defaultEncoding) throws JavaModelException;	
 
 	/**
 	 * Returns the resource that corresponds directly to this element,
diff --git a/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java b/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
index 65b294d..ce36778 100644
--- a/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
+++ b/model/org/eclipse/jdt/core/IJavaModelStatusConstants.java
@@ -306,5 +306,18 @@
 	 * Status constant indicating that a compiler option is invalid.
 	 * @since 3.1
 	 */
-//	public static final int INVALID_COMPILER_OPTION = 1007;	
+//	public static final int INVALID_COMPILER_OPTION = 1007;
+	/**
+	 * <p>Status constant indicating that the attached javadoc content cannot be retrieved due to multiple reasons:
+	 * invalid url, timed-out,...</p>
+	 * 
+	 * @since 3.2
+	 */
+	public static final int CANNOT_RETRIEVE_ATTACHED_JAVADOC = 1008;
+	/**
+	 * <p>Status constant indicating that the attached javadoc content format is unrecognized.</p>
+	 * 
+	 * @since 3.2
+	 */
+	public static final int UNKNOWN_JAVADOC_FORMAT = 1009;
 }
diff --git a/model/org/eclipse/jdt/core/IJavaProject.java b/model/org/eclipse/jdt/core/IJavaProject.java
index 9323f87..fa19900 100644
--- a/model/org/eclipse/jdt/core/IJavaProject.java
+++ b/model/org/eclipse/jdt/core/IJavaProject.java
@@ -188,8 +188,7 @@
 	 * 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>.
+	 * To find secondary types use {@link #findType(String, IProgressMonitor)} instead.
 	 * 
 	 * @param fullyQualifiedName the given fully qualified name
 	 * @exception JavaModelException if this project does not exist or if an
@@ -201,6 +200,21 @@
 	 */
 	IType findType(String fullyQualifiedName) throws JavaModelException;
 	/**
+	 * Same functionality as {@link #findType(String)} but also look for secondary
+	 * types if given name does not match a compilation unit name.
+	 * 
+	 * @param fullyQualifiedName the given fully qualified name
+	 * @param progressMonitor the progress monitor to report progress to,
+	 * 	or <code>null</code> if no progress monitor is provided
+	 * @exception JavaModelException if this project 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.2
+	 */
+	IType findType(String fullyQualifiedName, IProgressMonitor progressMonitor) 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,
@@ -212,8 +226,8 @@
 	 * 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>.
+	 * To find secondary types use {@link #findType(String, WorkingCopyOwner, IProgressMonitor)}
+	 * instead.
 	 * 
 	 * @param fullyQualifiedName the given fully qualified name
 	 * @param owner the owner of the returned type's compilation unit
@@ -226,6 +240,23 @@
 	 */
 	IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException;
 	/**
+	 * Same functionality as {@link #findType(String, WorkingCopyOwner)}
+	 * but also look for secondary types if given name does not match
+	 * a compilation unit name.
+	 * 
+	 * @param fullyQualifiedName the given fully qualified name
+	 * @param owner the owner of the returned type's compilation unit
+	 * @param progressMonitor the progress monitor to report progress to,
+	 * 	or <code>null</code> if no progress monitor is provided
+	 * @exception JavaModelException if this project 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.2
+	 */
+	IType findType(String fullyQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) 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.
@@ -237,8 +268,8 @@
 	 * 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>.
+	 * To find secondary types use {@link #findType(String, String, IProgressMonitor)}
+	 * instead.
 	 * 
 	 * @param packageName the given package name
 	 * @param typeQualifiedName the given type qualified name
@@ -252,6 +283,22 @@
 	 */
 	IType findType(String packageName, String typeQualifiedName) throws JavaModelException;
 	/**
+	 * Same functionality as {@link #findType(String, String)} but also look for
+	 * secondary types if given name does not match a compilation unit name.
+	 * 
+	 * @param packageName the given package name
+	 * @param typeQualifiedName the given type qualified name
+	 * @param progressMonitor the progress monitor to report progress to,
+	 * 	or <code>null</code> if no progress monitor is provided
+	 * @exception JavaModelException if this project 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.2
+	 */
+	IType findType(String packageName, String typeQualifiedName, IProgressMonitor progressMonitor) 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.
@@ -265,8 +312,8 @@
 	 * 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>.
+	 * To find secondary types use {@link #findType(String, String, WorkingCopyOwner, IProgressMonitor)}
+	 * instead.
 	 * 
 	 * @param packageName the given package name
 	 * @param typeQualifiedName the given type qualified name
@@ -280,6 +327,23 @@
 	 * @since 3.0
 	 */
 	IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException;
+	/**
+	 * Same functionality as {@link #findType(String, String, WorkingCopyOwner)}
+	 * but also look for secondary types if given name does not match a compilation unit name.
+	 * 
+	 * @param packageName the given package name
+	 * @param typeQualifiedName the given type qualified name
+	 * @param owner the owner of the returned type's compilation unit
+	 * @param progressMonitor the progress monitor to report progress to,
+	 * 	or <code>null</code> if no progress monitor is provided
+	 * @exception JavaModelException if this project 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.2
+	 */
+	IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException;
 	
 	/**
 	 * Returns all of the existing package fragment roots that exist
@@ -805,6 +869,85 @@
 		throws JavaModelException;
 
 	/**
+	 * Sets the both the classpath of this project and its default output
+	 * location at once. The classpath is defined using a list of classpath
+	 * entries. In particular such a classpath may contain classpath variable 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>.
+	 * <p>
+	 * 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.
+	 * </p><p>
+	 * If it is specified that this operation cannot modify resources, the .classpath file will not be written to disk
+	 * and no error marker will be generated. To synchronize the .classpath with the in-memory classpath,
+	 * one can use <code>setRawClasspath(readRawClasspath(), false, monitor)</code>.
+	 * </p><p>
+	 * Setting the classpath to <code>null</code> specifies a default classpath
+	 * (the project root). Setting the classpath to an empty array specifies an
+	 * empty classpath.
+	 * </p><p>
+	 * If a cycle is detected while setting this classpath (and if resources can be modified), an error marker will be added
+	 * to the project closing the cycle.
+	 * To avoid this problem, use <code>hasClasspathCycle(IClasspathEntry[] entries)</code>
+	 * before setting the classpath.
+	 * <p>
+	 * This operation acquires a lock on the workspace's root.
+	 *
+	 * @param entries a list of classpath entries
+	 * @param outputLocation the default output location
+	 * @param canModifyResources whether resources should be written to disk if needed
+	 * @param monitor the given progress monitor
+	 * @exception JavaModelException if the classpath could not be set. Reasons include:
+	 * <ul>
+	 * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+	 * <li> The classpath is being modified during resource change event notification (CORE_EXCEPTION)
+	 * <li> The classpath failed the validation check as defined by <code>JavaConventions#validateClasspath</code>
+	 * </ul>
+	 * @see IClasspathEntry
+	 * @since 3.2
+	 */
+	void setRawClasspath(IClasspathEntry[] entries, IPath outputLocation, boolean canModifyResources, IProgressMonitor monitor) throws JavaModelException;
+	
+	/**
+	 * Sets the classpath of this project using a list of classpath entries. In particular such a classpath may contain
+	 * classpath variable 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>.
+	 * <p>
+	 * 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.
+	 * </p><p>
+	 * If it is specified that this operation cannot modify resources, the .classpath file will not be written to disk
+	 * and no error marker will be generated. To synchronize the .classpath with the in-memory classpath,
+	 * one can use <code>setRawClasspath(readRawClasspath(), false, monitor)</code>.
+	 * </p><p>
+	 * Setting the classpath to <code>null</code> specifies a default classpath
+	 * (the project root). Setting the classpath to an empty array specifies an
+	 * empty classpath.
+	 * </p><p>
+	 * If a cycle is detected while setting this classpath (and if resources can be modified), an error marker will be added
+	 * to the project closing the cycle.
+	 * To avoid this problem, use <code>hasClasspathCycle(IClasspathEntry[] entries)</code>
+	 * before setting the classpath.
+	 * <p>
+	 * This operation acquires a lock on the workspace's root.
+	 *
+	 * @param entries a list of classpath entries
+	 * @param canModifyResources whether resources should be written to disk if needed
+	 * @param monitor the given progress monitor
+	 * @exception JavaModelException if the classpath could not be set. Reasons include:
+	 * <ul>
+	 * <li> This Java element does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+	 * <li> The classpath is being modified during resource change event notification (CORE_EXCEPTION)
+	 * <li> The classpath failed the validation check as defined by <code>JavaConventions#validateClasspath</code>
+	 * </ul>
+	 * @see IClasspathEntry
+	 * @since 3.2
+	 */
+	void setRawClasspath(IClasspathEntry[] entries, boolean canModifyResources, IProgressMonitor monitor) throws JavaModelException;
+	
+	/**
 	 * Sets the classpath of this project using a list of classpath entries. In particular such a classpath may contain
 	 * classpath variable 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>.
diff --git a/model/org/eclipse/jdt/core/IMember.java b/model/org/eclipse/jdt/core/IMember.java
index eabeb42..12e3094 100644
--- a/model/org/eclipse/jdt/core/IMember.java
+++ b/model/org/eclipse/jdt/core/IMember.java
@@ -79,11 +79,14 @@
  * extracted from the corresponding source.</p>
  * <p>If this element is from a binary, the javadoc is extracted from the
  * attached source if present.</p>
+ * <p>If this element's openable is not consistent, then null is returned.</p>
  *
  * @exception JavaModelException if this element does not exist or if an
  *      exception occurs while accessing its corresponding resource.
  * @return a source range corresponding to the javadoc source or <code>null</code>
- * if no source is available or the element has no javadoc comment.
+ * if no source is available, this element has no javadoc comment or
+ * this element's openable is not consistent
+ * @see IOpenable#isConsistent()
  * @since 3.2
  */
 ISourceRange getJavadocRange() throws JavaModelException;
@@ -102,6 +105,25 @@
  */
 ISourceRange getNameRange() throws JavaModelException;
 /**
+ * Returns the position relative to the order this member is defined in the source.
+ * Numbering starts at 1 (thus the first occurrence is occurrence 1, not occurrence 0).
+ * <p>
+ * Two members m1 and m2 that are equal (e.g. 2 fields with the same name in 
+ * the same type) can be distinguished using their occurrence counts. If member 
+ * m1 appears first in the source, it will have an occurrence count of 1. If member 
+ * m2 appears right after member m1, it will have an occurrence count of 2.
+ * </p><p>
+ * The occurrence count can be used to distinguish initializers inside a type
+ * or anonymous types inside a method.
+ * </p><p>
+ * This is a handle-only method.  The member may or may not be present.
+ * </p>
+ * 
+ * @return the position relative to the order this member is defined in the source
+ * @since 3.2
+ */
+int getOccurrenceCount();
+/**
  * 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.
diff --git a/model/org/eclipse/jdt/core/IMethod.java b/model/org/eclipse/jdt/core/IMethod.java
index 92c3bd4..f7084b8 100644
--- a/model/org/eclipse/jdt/core/IMethod.java
+++ b/model/org/eclipse/jdt/core/IMethod.java
@@ -99,8 +99,8 @@
 String getKey();
 /**
  * Returns the names of parameters in this method.
- * For binary types, these names are invented as "arg"+i, where i starts at 1 
- * (even if source is associated with the binary).
+ * For binary types, associated source or attached Javadoc are used to retrieve the names.
+ * If none can be retrieved, then these names are invented as "arg"+i, where i starts at 0.
  * Returns an empty array if this method has no parameters.
  *
  * <p>For example, a method declared as <code>public void foo(String text, int length)</code>
@@ -131,6 +131,23 @@
  */
 String[] getParameterTypes();
 /**
+ * Returns the names of parameters in this method.
+ * For binary types, these names are invented as "arg"+i, where i starts at 0 
+ * (even if source is associated with the binary or if Javdoc is attached to the binary).
+ * Returns an empty array if this method has no parameters.
+ *
+ * <p>For example, a method declared as <code>public void foo(String text, int length)</code>
+ * would return the array <code>{"text","length"}</code>. For the same method in a
+ * binary, this would return <code>{"arg0", "arg1"}</code>.
+ * </p>
+ *
+ * @exception JavaModelException if this element does not exist or if an
+ *      exception occurs while accessing its corresponding resource.
+ * @return the names of parameters in this method, an empty array if this method has no parameters
+ * @since 3.2
+ */
+String[] getRawParameterNames() throws JavaModelException;
+/**
  * Returns the type signature of the return value of this method.
  * For constructors, this returns the signature for void.
  * <p>
diff --git a/model/org/eclipse/jdt/core/IOpenable.java b/model/org/eclipse/jdt/core/IOpenable.java
index d0f4e5d..b07e67e 100644
--- a/model/org/eclipse/jdt/core/IOpenable.java
+++ b/model/org/eclipse/jdt/core/IOpenable.java
@@ -55,6 +55,19 @@
  */
 public void close() throws JavaModelException;
 /**
+ * Finds and returns the recommended line separator for this element.
+ * The element's buffer is first searched and the first line separator in this buffer is returned if any.
+ * Otherwise the preference {@link org.eclipse.core.runtime.Platform#PREF_LINE_SEPARATOR} 
+ * on this element's project or workspace is returned.
+ * Finally if no such preference is set, the system line separator is returned.
+ * 
+ * @return the recommended line separator for this element
+ * @exception JavaModelException if this element does not exist or if an
+ *		exception occurs while accessing its corresponding resource.
+ * @since 3.2
+ */
+public String findRecommendedLineSeparator() throws JavaModelException;
+/**
  * Returns the buffer opened for this element, or <code>null</code>
  * if this element does not have a buffer.
  *
diff --git a/model/org/eclipse/jdt/core/IType.java b/model/org/eclipse/jdt/core/IType.java
index 56c2db5..b522190 100644
--- a/model/org/eclipse/jdt/core/IType.java
+++ b/model/org/eclipse/jdt/core/IType.java
@@ -679,7 +679,7 @@
 	 * <li>the type qualified name of a class B defined as a member of a class A
 	 *     using the '$' separator is "A$B"</li>
 	 * <li>the type qualified name of a binary type whose class file is A$B.class
-	 *     using the '.' separator is "A.B"</li>
+	 *     using the '.' separator is "A$B"</li>
 	 * <li>the type qualified name of a binary type whose class file is A$B.class
 	 *     using the '$' separator is "A$B"</li>
 	 * <li>the type qualified name of an anonymous binary type whose class file is A$1.class
diff --git a/model/org/eclipse/jdt/core/JavaCore.java b/model/org/eclipse/jdt/core/JavaCore.java
index 2294c10..3a0a642 100644
--- a/model/org/eclipse/jdt/core/JavaCore.java
+++ b/model/org/eclipse/jdt/core/JavaCore.java
@@ -54,17 +54,42 @@
  *                                 COMPILER_PB_MISSING_JAVADOC_COMMENTS_OVERRIDING
  *                                 COMPILER_PB_DEPRECATION_WHEN_OVERRIDING_DEPRECATED_METHOD
  *                                 COMPILER_PB_UNUSED_DECLARED_THROWN_EXCEPTION_WHEN_OVERRIDING
+ *     IBM Corporation - added the following constants:
+ *                                 TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC
  *******************************************************************************/
 package org.eclipse.jdt.core;
 
 import java.io.File;
-import java.util.*;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
 
-import org.eclipse.core.resources.*;
-import org.eclipse.core.runtime.*;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IMarkerDelta;
+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.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+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.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.QualifiedName;
+import org.eclipse.core.runtime.SubProgressMonitor;
 import org.eclipse.core.runtime.jobs.ISchedulingRule;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.compiler.ICompilationParticipant;
+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;
@@ -72,7 +97,6 @@
 import org.eclipse.jdt.core.search.TypeNameRequestor;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.*;
-import org.eclipse.jdt.internal.core.Assert;
 import org.eclipse.jdt.internal.core.builder.JavaBuilder;
 import org.eclipse.jdt.internal.core.builder.State;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
@@ -866,6 +890,24 @@
 	 */
 	public static final String CODEASSIST_DISCOURAGED_REFERENCE_CHECK= PLUGIN_ID + ".codeComplete.discouragedReferenceCheck"; //$NON-NLS-1$
 	
+	// TODO (olivier) remove warning for name change before 3.2 release
+	/**
+	 * Possible  configurable option ID.
+	 * The name of this option is subject to change before 3.2 release.
+	 * @see #getDefaultOptions()
+	 * @since 3.2
+	 * @deprecated Use TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC instead
+	 */
+	public static final String CODEASSIST_TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC = PLUGIN_ID + ".codeAssist.timeoutForParameterNameFromAttachedJavadoc"; //$NON-NLS-1$
+
+	/**
+	 * Possible  configurable option ID.
+	 * The name of this option is subject to change before 3.2 release.
+	 * @see #getDefaultOptions()
+	 * @since 3.2
+	 */
+	public static final String TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC = PLUGIN_ID + ".timeoutForParameterNameFromAttachedJavadoc"; //$NON-NLS-1$
+
 	// *************** Possible values for configurable options. ********************
 	
 	/**
@@ -1046,6 +1088,16 @@
 	public static final String NEVER = "never"; //$NON-NLS-1$
 
 	/**
+	 * Value of the content-type for Java source files. Use this value to retrieve the Java content type
+	 * from the content type manager, and to add new Java-like extensions to this content type.
+	 * 
+	 * @see org.eclipse.core.runtime.content.IContentTypeManager#getContentType(String)
+	 * @see #getJavaLikeExtensions()
+	 * @since 3.2
+	 */
+	public static final String JAVA_SOURCE_CONTENT_TYPE = JavaCore.PLUGIN_ID+".javaSource" ; //$NON-NLS-1$
+
+	/**
 	 * Creates the Java core plug-in.
 	 * <p>
 	 * The plug-in instance is created automatically by the 
@@ -1060,19 +1112,6 @@
 	}
 
 	/**
-	 * Add a compilation participant listener dynamically.  It is not necessary
-	 * to call this for listeners registered with the compilationParticipants
-	 * extension point.
-	 * 
-	 * @param icp the listener
-	 * @param eventMask the set of events for which the listener will be notified,
-	 * built by ORing together values from CompilationParticipantEvent.
-	 */
-	public static void addCompilationParticipant(ICompilationParticipant icp, int eventMask) {
-		JavaModelManager.getJavaModelManager().getCompilationParticipants().add(icp, eventMask);
-	}
-
-	/**
 	 * Adds the given listener for changes to Java elements.
 	 * Has no effect if an identical listener is already registered.
 	 *
@@ -1620,28 +1659,6 @@
 	}
 
 	/**
-	 * Returns an immutable list containing the subset of registered
-	 * listeners that have requested notification of at least one of
-	 * the events in the flags mask.
-	 * The first time this is called, it loads listeners from plugins,
-	 * which may cause plugins to be loaded.  
-	 * 
-	 * <p>
-	 * Note that a deadlock situation can occur if a plugin's <code>start()</code> 
-	 * method blocks on a thread that calls <code>getCompilationParticipants()</code>.  
-	 * See <code>JavaModelManager.CompilationParticipants.getCompilationParticipants()</code>
-	 * for a complete description of the circumstances under which this deadlock can occur.
-	 * 
-	 * @param eventMask an ORed combination of values from ICompilationParticipant.
-	 * @param project the java project that will the participants will operate against
-	 * @return an immutable list of ICompilationParticipant.
-	 * @see JavaModelManager.CompilationParticipants#getCompilationParticipants
-	 */
-	public static List getCompilationParticipants(int eventMask, IJavaProject project) {
-		return JavaModelManager.getJavaModelManager().getCompilationParticipants().getCompilationParticipants(eventMask, project);
-	}
-	
-	/**
 	 * Returns a table of all known configurable options with their default values.
 	 * These options allow to configure the behaviour of the underlying components.
 	 * The client may safely use the result as a template that they can modify and
@@ -2076,7 +2093,7 @@
 	 *    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"
+	 *     - default:           "public"
 	 * 
 	 * COMPILER / Reporting Invalid Javadoc Tags
 	 *    When enabled, the compiler will signal unbound or unexpected reference tags in Javadoc.
@@ -2087,7 +2104,7 @@
 	 *    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"
+	 *     - default:           "disabled"
 	 * 
 	 * COMPILER / Reporting Invalid Javadoc Tags with Deprecated References
 	 *    Specify whether the compiler will report deprecated references used in Javadoc tags.
@@ -2095,7 +2112,7 @@
 	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility".
 	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef"
 	 *     - possible values:   { "enabled", "disabled" }
-	 *     - default:           "enabled"
+	 *     - default:           "disabled"
 	 * 
 	 * COMPILER / Reporting Invalid Javadoc Tags with Not Visible References
 	 *    Specify whether the compiler will report non-visible references used in Javadoc tags.
@@ -2103,7 +2120,7 @@
 	 *    also see the setting "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility".
 	 *     - option id:         "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef"
 	 *     - possible values:   { "enabled", "disabled" }
-	 *     - default:           "enabled"
+	 *     - default:           "disabled"
 	 * 
 	 * COMPILER / Reporting Missing Javadoc Tags
 	 *    This is the generic control for the severity of Javadoc missing tag problems.
@@ -2119,7 +2136,7 @@
 	 *    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"
+	 *     - default:           "public"
 	 * 
 	 * COMPILER / Reporting Missing Javadoc Tags on Overriding Methods
 	 *    Specify whether the compiler will verify overriding methods in order to report Javadoc missing tag problems.
@@ -2304,6 +2321,13 @@
 	 *     - possible values:   { "enabled", "disabled" }
 	 *     - default:           "enabled"
 	 * 
+	 *	JAVACORE / Set the timeout value for retrieving the method's parameter names from javadoc
+	 *    Timeout in milliseconds to retrieve the method's parameter names from javadoc.
+	 *    If the value is 0, the parameter names are not fetched and the raw names are returned.
+	 *     - option id:         "org.eclipse.jdt.core.timeoutForParameterNameFromAttachedJavadoc"
+	 *     - possible values:	"&lt;n&gt;", where n is an integer greater than or equal to 0
+	 *     - default:           "50"
+	 * 
 	 *	FORMATTER / Inserting New Line Before Opening Brace
 	 *    When Insert, a new line is inserted before an opening brace, otherwise nothing
 	 *    is inserted
@@ -2458,7 +2482,8 @@
 	 *    When active, completion show proposals whose name match to the CamelCase pattern.
 	 *     - option id:         "org.eclipse.jdt.core.codeComplete.camelCaseMatch"
 	 *     - possible values:   { "enabled", "disabled" }
-	 *     - default:           "disabled"
+	 *     - default:           "enabled"
+	 *     
 	 * </pre>
 	 * 
 	 * @return a mutable table containing the default settings of all known options
@@ -2501,6 +2526,20 @@
 	}
 	
 	/**
+	 * Returns the list of known Java-like extensions.
+	 * Java like extension are defined in the {@link org.eclipse.core.runtime.Platform#getContentTypeManager() 
+	 * content type manager} for the {@link #JAVA_SOURCE_CONTENT_TYPE}.
+	 * Note that a Java-like extension doesn't include the leading dot ('.').
+	 * Also note that the "java" extension is always defined as a Java-like extension.
+	 * 
+	 * @return the list of known Java-like extensions.
+	 * @since 3.2
+	 */
+	public static String[] getJavaLikeExtensions() {
+		return CharOperation.toStrings(Util.getJavaLikeExtensions());
+	}
+	
+	/**
 	 * Helper method for returning one option value only. Equivalent to <code>(String)JavaCore.getOptions().get(optionName)</code>
 	 * Note that it may answer <code>null</code> if this option does not exist.
 	 * <p>
@@ -2749,110 +2788,114 @@
 	 * @since 3.1
 	 */
 	public static void initializeAfterLoad(IProgressMonitor monitor) throws CoreException {
-		Job job = new Job(Messages.javamodel_initialization) {
-			protected IStatus run(IProgressMonitor progressMonitor) {
-				// dummy query for waiting until the indexes are ready and classpath containers/variables are initialized
-				SearchEngine engine = new SearchEngine();
-				IJavaSearchScope scope = SearchEngine.createWorkspaceScope(); // initialize all containers and variables
-				try {
-					engine.searchAllTypeNames(
-						null,
-						"!@$#!@".toCharArray(), //$NON-NLS-1$
-						SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
-						IJavaSearchConstants.CLASS,
-						scope, 
-						new TypeNameRequestor() {
-							public void acceptType(
-								int modifiers,
-								char[] packageName,
-								char[] simpleTypeName,
-								char[][] enclosingTypeNames,
-								String path) {
-								// no type to accept
-							}
-						},
-						// will not activate index query caches if indexes are not ready, since it would take to long
-						// to wait until indexes are fully rebuild
-						IJavaSearchConstants.CANCEL_IF_NOT_READY_TO_SEARCH,
-						progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 99) // 99% of the time is spent in the dummy search
-					); 
-				} catch (JavaModelException e) {
-					// /search failed: ignore
-				} catch (OperationCanceledException e) {
-					if (progressMonitor != null && progressMonitor.isCanceled())
-						throw e;
-					// else indexes were not ready: catch the exception so that jars are still refreshed
-				}
-				
-				// check if the build state version number has changed since last session
-				// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=98969)
-				QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "stateVersionNumber"); //$NON-NLS-1$
-				IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
-				String versionNumber = null;
-				try {
-					versionNumber = root.getPersistentProperty(qName);
-				} catch (CoreException e) {
-					// could not read version number: consider it is new
-				}
-				final JavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
-				String newVersionNumber = Byte.toString(State.VERSION);
-				if (!newVersionNumber.equals(versionNumber)) {
-					// build state version number has changed: touch every projects to force a rebuild
-					if (JavaBuilder.DEBUG)
-						System.out.println("Build state version number has changed"); //$NON-NLS-1$
-					IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
-						public void run(IProgressMonitor progressMonitor2) throws CoreException {
-							IJavaProject[] projects = null;
-							try {
-								projects = model.getJavaProjects();
-							} catch (JavaModelException e) {
-								// could not get Java projects: ignore
-							}
-							if (projects != null) {
-								for (int i = 0, length = projects.length; i < length; i++) {
-									IJavaProject project = projects[i];
-									try {
-										if (JavaBuilder.DEBUG)
-											System.out.println("Touching " + project.getElementName()); //$NON-NLS-1$
-										project.getProject().touch(progressMonitor2);
-									} catch (CoreException e) {
-										// could not touch this project: ignore
-									}
+		try {
+			if (monitor != null) monitor.beginTask(Messages.javamodel_initialization, 100);
+			// dummy query for waiting until the indexes are ready and classpath containers/variables are initialized
+			SearchEngine engine = new SearchEngine();
+			IJavaSearchScope scope = SearchEngine.createWorkspaceScope(); // initialize all containers and variables
+			try {
+				engine.searchAllTypeNames(
+					null,
+					"!@$#!@".toCharArray(), //$NON-NLS-1$
+					SearchPattern.R_PATTERN_MATCH | SearchPattern.R_CASE_SENSITIVE,
+					IJavaSearchConstants.CLASS,
+					scope, 
+					new TypeNameRequestor() {
+						public void acceptType(
+							int modifiers,
+							char[] packageName,
+							char[] simpleTypeName,
+							char[][] enclosingTypeNames,
+							String path) {
+							// no type to accept
+						}
+					},
+					// will not activate index query caches if indexes are not ready, since it would take to long
+					// to wait until indexes are fully rebuild
+					IJavaSearchConstants.CANCEL_IF_NOT_READY_TO_SEARCH,
+					monitor == null ? null : new SubProgressMonitor(monitor, 99) // 99% of the time is spent in the dummy search
+				); 
+			} catch (JavaModelException e) {
+				// /search failed: ignore
+			} catch (OperationCanceledException e) {
+				if (monitor != null && monitor.isCanceled())
+					throw e;
+				// else indexes were not ready: catch the exception so that jars are still refreshed
+			}
+			
+			// check if the build state version number has changed since last session
+			// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=98969)
+			QualifiedName qName = new QualifiedName(JavaCore.PLUGIN_ID, "stateVersionNumber"); //$NON-NLS-1$
+			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+			String versionNumber = null;
+			try {
+				versionNumber = root.getPersistentProperty(qName);
+			} catch (CoreException e) {
+				// could not read version number: consider it is new
+			}
+			final JavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
+			String newVersionNumber = Byte.toString(State.VERSION);
+			if (!newVersionNumber.equals(versionNumber)) {
+				// build state version number has changed: touch every projects to force a rebuild
+				if (JavaBuilder.DEBUG)
+					System.out.println("Build state version number has changed"); //$NON-NLS-1$
+				IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
+					public void run(IProgressMonitor progressMonitor2) throws CoreException {
+						IJavaProject[] projects = null;
+						try {
+							projects = model.getJavaProjects();
+						} catch (JavaModelException e) {
+							// could not get Java projects: ignore
+						}
+						if (projects != null) {
+							for (int i = 0, length = projects.length; i < length; i++) {
+								IJavaProject project = projects[i];
+								try {
+									if (JavaBuilder.DEBUG)
+										System.out.println("Touching " + project.getElementName()); //$NON-NLS-1$
+									project.getProject().touch(progressMonitor2);
+								} catch (CoreException e) {
+									// could not touch this project: ignore
 								}
 							}
 						}
-					};
-					try {
-						ResourcesPlugin.getWorkspace().run(runnable, progressMonitor);
-					} catch (CoreException e) {
-						// could not touch all projects
 					}
-					try {
-						root.setPersistentProperty(qName, newVersionNumber);
-					} catch (CoreException e) {
-						Util.log(e, "Could not persist build state version number"); //$NON-NLS-1$
-					}
-				}
-				
-				// ensure external jars are refreshed (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=93668)
+				};
 				try {
-					model.refreshExternalArchives(
-						null/*refresh all projects*/, 
-						progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 1) // 1% of the time is spent in jar refresh
-					);
-				} catch (JavaModelException e) {
-					// refreshing failed: ignore
+					ResourcesPlugin.getWorkspace().run(runnable, monitor);
+				} catch (CoreException e) {
+					// could not touch all projects
 				}
-				
-				return Status.OK_STATUS;
+				try {
+					root.setPersistentProperty(qName, newVersionNumber);
+				} catch (CoreException e) {
+					Util.log(e, "Could not persist build state version number"); //$NON-NLS-1$
+				}
 			}
-			public boolean belongsTo(Object family) {
-				return PLUGIN_ID.equals(family);
+			
+			// ensure external jars are refreshed (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=93668)
+			try {
+				model.refreshExternalArchives(
+					null/*refresh all projects*/, 
+					monitor == null ? null : new SubProgressMonitor(monitor, 1) // 1% of the time is spent in jar refresh
+				);
+			} catch (JavaModelException e) {
+				// refreshing failed: ignore
 			}
-		};
-		job.setPriority(Job.SHORT);
-		job.schedule(2000);	 // wait for the startup activity to calm down
-		
+		} finally {
+			if (monitor != null) monitor.done();
+		}
+	}
+	
+	/**
+	 * Returns whether the given file name's extension is a Java-like extension.
+	 * 
+	 * @return whether the given file name's extension is a Java-like extension
+	 * @see #getJavaLikeExtensions()
+	 * @since 3.2
+	 */
+	public static boolean isJavaLikeFileName(String fileName) {
+		return Util.isJavaLikeFileName(fileName);
 	}
 	
 	/**
@@ -3795,17 +3838,6 @@
 	}
 
 	/**
-	 * Removes the specified compilation participant listener.  Has no effect
-	 * if the listener was not on the list, or if it was registered via the 
-	 * compilationParticipant extension point rather than a call to 
-	 * addCompilationParticipant.
-	 * @param icp the listener to remove
-	 */
-	public static void removeCompilationParticipant(ICompilationParticipant icp) {
-		JavaModelManager.getJavaModelManager().getCompilationParticipants().remove(icp);
-	}
-
-	/**
 	 * Removes the given element changed listener.
 	 * Has no affect if an identical listener is not registered.
 	 *
@@ -3816,6 +3848,19 @@
 	}
 
 	/**
+	 * Removes the file extension from the given file name, if it has a Java-like file
+	 * extension. Otherwise the file name itself is returned.
+	 * Note this removes the dot ('.') before the extension as well.
+	 * 
+	 * @param fileName the name of a file
+	 * @return the fileName without the Java-like extension
+	 * @since 3.2
+	 */
+	public static String removeJavaLikeExtension(String fileName) {
+		return Util.getNameWithoutJavaLikeExtension(fileName);
+	}
+	
+	/**
 	 * Removes the given pre-processing resource changed listener.
 	 * <p>
 	 * Has no affect if an identical listener is not registered.
diff --git a/model/org/eclipse/jdt/core/NamingConventions.java b/model/org/eclipse/jdt/core/NamingConventions.java
index 19cac72..30d9c80 100644
--- a/model/org/eclipse/jdt/core/NamingConventions.java
+++ b/model/org/eclipse/jdt/core/NamingConventions.java
@@ -23,14 +23,14 @@
  * <p>
  * The possible options are :
  * <ul>
- * <li>CODEASSIST_FIELD_PREFIXES : Define the Prefixes for Field Name.</li>
- * <li>CODEASSIST_STATIC_FIELD_PREFIXES : Define the Prefixes for Static Field Name.</li>
- * <li>CODEASSIST_LOCAL_PREFIXES : Define the Prefixes for Local Variable Name.</li>
- * <li>CODEASSIST_ARGUMENT_PREFIXES : Define the Prefixes for Argument Name.</li>
- * <li>CODEASSIST_FIELD_SUFFIXES : Define the Suffixes for Field Name.</li>
- * <li>CODEASSIST_STATIC_FIELD_SUFFIXES : Define the Suffixes for Static Field Name.</li>
- * <li>CODEASSIST_LOCAL_SUFFIXES : Define the Suffixes for Local Variable Name.</li>
- * <li>CODEASSIST_ARGUMENT_SUFFIXES : Define the Suffixes for Argument Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_FIELD_PREFIXES} : Define the Prefixes for Field Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES} : Define the Prefixes for Static Field Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_LOCAL_PREFIXES} : Define the Prefixes for Local Variable Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_ARGUMENT_PREFIXES} : Define the Prefixes for Argument Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} : Define the Suffixes for Field Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} : Define the Suffixes for Static Field Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_LOCAL_SUFFIXES} : Define the Suffixes for Local Variable Name.</li>
+ * <li> {@link JavaCore#CODEASSIST_ARGUMENT_SUFFIXES} : Define the Suffixes for Argument Name.</li>
  * </ul>
  * </p>
  * <p>
@@ -282,8 +282,8 @@
 	 * name <code>preArgsuf</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_ARGUMENT_PREFIXES and
-	 * CODEASSIST_ARGUMENT_SUFFIXES.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_ARGUMENT_PREFIXES} and
+	 *  {@link JavaCore#CODEASSIST_ARGUMENT_SUFFIXES}.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -313,8 +313,8 @@
 	 * name <code>preArgsuf</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_ARGUMENT_PREFIXES and
-	 * CODEASSIST_ARGUMENT_SUFFIXES.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_ARGUMENT_PREFIXES} and
+	 *  {@link JavaCore#CODEASSIST_ARGUMENT_SUFFIXES}.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -340,9 +340,9 @@
 	 * name <code>preFieldsuf</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES, 
-	 * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
-	 * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+	 * This method is affected by the following JavaCore options : {@link JavaCore#CODEASSIST_FIELD_PREFIXES} } , 
+	 *  {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and  {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+	 *  {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -376,9 +376,9 @@
 	 * name <code>preFieldsuf</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES, 
-	 * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
-	 * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_FIELD_PREFIXES}, 
+	 *  {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and  {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+	 *  {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -406,8 +406,8 @@
 	 * name <code>preLocalsuf</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_LOCAL_PREFIXES and 
-	 * CODEASSIST_LOCAL_SUFFIXES.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_LOCAL_PREFIXES} and 
+	 *  {@link JavaCore#CODEASSIST_LOCAL_SUFFIXES}.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -437,8 +437,8 @@
 	 * name <code>preLocalsuf</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_LOCAL_PREFIXES and 
-	 * CODEASSIST_LOCAL_SUFFIXES.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_LOCAL_PREFIXES} and 
+	 *  {@link JavaCore#CODEASSIST_LOCAL_SUFFIXES}.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -465,8 +465,8 @@
 	 * and <code>name</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_ARGUMENT_PREFIXES and 
-	 * CODEASSIST_ARGUMENT_SUFFIXES.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_ARGUMENT_PREFIXES} and 
+	 *  {@link JavaCore#CODEASSIST_ARGUMENT_SUFFIXES}.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -506,8 +506,8 @@
 	 * and <code>name</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_ARGUMENT_PREFIXES and 
-	 * CODEASSIST_ARGUMENT_SUFFIXES.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_ARGUMENT_PREFIXES} and 
+	 *  {@link JavaCore#CODEASSIST_ARGUMENT_SUFFIXES}.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -543,9 +543,9 @@
 	 * and <code>name</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES, 
-	 * CODEASSIST_FIELD_SUFFIXES and for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
-	 * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_FIELD_PREFIXES}, 
+	 *  {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} and for instance field and  {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+	 *  {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -589,9 +589,9 @@
 	 * and <code>name</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES, 
-	 * CODEASSIST_FIELD_SUFFIXES and for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
-	 * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_FIELD_PREFIXES}, 
+	 *  {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} and for instance field and  {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+	 *  {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -632,8 +632,8 @@
 	 * and <code>name</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_LOCAL_PREFIXES and
-	 * CODEASSIST_LOCAL_SUFFIXES.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_LOCAL_PREFIXES} and
+	 *  {@link JavaCore#CODEASSIST_LOCAL_SUFFIXES}.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -673,8 +673,8 @@
 	 * and <code>name</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_LOCAL_PREFIXES and
-	 * CODEASSIST_LOCAL_SUFFIXES.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_LOCAL_PREFIXES} and
+	 *  {@link JavaCore#CODEASSIST_LOCAL_SUFFIXES}.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -711,9 +711,9 @@
 	 * for boolean field or <code>getPreFieldNamesuf</code> for others.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES, 
-	 * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
-	 * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_FIELD_PREFIXES}, 
+	 *  {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and  {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+	 *  {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -763,9 +763,9 @@
 	 * for boolean field or <code>getPreFieldNamesuf</code> for others.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES, 
-	 * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
-	 * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_FIELD_PREFIXES}, 
+	 *  {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and  {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+	 *  {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -803,9 +803,9 @@
 	 * If there is no prefix and suffix the proposal is <code>setPreFieldNamesuf</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES, 
-	 * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
-	 * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_FIELD_PREFIXES}, 
+	 *  {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and  {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+	 *  {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
@@ -859,9 +859,9 @@
 	 * If there is no prefix and suffix the proposal is <code>setPreFieldNamesuf</code>.
 	 * </p>
 	 * <p>
-	 * This method is affected by the following JavaCore options : CODEASSIST_FIELD_PREFIXES, 
-	 * CODEASSIST_FIELD_SUFFIXES for instance field and CODEASSIST_STATIC_FIELD_PREFIXES,
-	 * CODEASSIST_STATIC_FIELD_SUFFIXES for static field.
+	 * This method is affected by the following JavaCore options :  {@link JavaCore#CODEASSIST_FIELD_PREFIXES}, 
+	 *  {@link JavaCore#CODEASSIST_FIELD_SUFFIXES} for instance field and  {@link JavaCore#CODEASSIST_STATIC_FIELD_PREFIXES},
+	 *  {@link JavaCore#CODEASSIST_STATIC_FIELD_SUFFIXES} for static field.
 	 * </p>
 	 * <p>
 	 * For a complete description of these configurable options, see <code>getDefaultOptions</code>.
diff --git a/model/org/eclipse/jdt/core/ToolFactory.java b/model/org/eclipse/jdt/core/ToolFactory.java
index f30a2c4..d028255 100644
--- a/model/org/eclipse/jdt/core/ToolFactory.java
+++ b/model/org/eclipse/jdt/core/ToolFactory.java
@@ -13,10 +13,12 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URI;
 import java.util.Map;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import org.eclipse.core.filesystem.EFS;
 import org.eclipse.core.runtime.*;
 import org.eclipse.jdt.core.compiler.IScanner;
 import org.eclipse.jdt.core.formatter.CodeFormatter;
@@ -155,9 +157,20 @@
 					String entryName = org.eclipse.jdt.internal.core.util.Util.concatWith(packageFragment.names, classFileName, '/');
 					return createDefaultClassFileReader(archiveName, entryName, decodingFlag);
 				} else {
-					IPath location = classfile.getResource().getLocation();
-					if (location == null) return null;
-					return createDefaultClassFileReader(location.toOSString(), decodingFlag);
+					URI uri = classfile.getResource().getLocationURI();
+					if (uri == null) return null;
+					InputStream in = null;
+					try {
+						in = EFS.getStore(uri).openInputStream(EFS.NONE, null);
+						return createDefaultClassFileReader(in, decodingFlag);
+					} finally {
+						if (in != null)
+							try {
+								in.close();
+							} catch (IOException e) {
+								// ignore
+							}
+					}
 				}
 			} catch(CoreException e){
 				// unable to read
diff --git a/model/org/eclipse/jdt/core/WorkingCopyOwner.java b/model/org/eclipse/jdt/core/WorkingCopyOwner.java
index 24e5ece..31cca7f 100644
--- a/model/org/eclipse/jdt/core/WorkingCopyOwner.java
+++ b/model/org/eclipse/jdt/core/WorkingCopyOwner.java
@@ -10,7 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.core;
 
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.internal.core.BufferManager;
+import org.eclipse.jdt.internal.core.CompilationUnit;
 import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
 
 /**
@@ -66,5 +68,36 @@
 
 		return BufferManager.getDefaultBufferManager().createBuffer(workingCopy);
 	}
+	
+	/**
+	 * Returns a new working copy with the given name using this working copy owner to 
+	 * create its buffer. This working copy doesn't belong to any package, thus its 
+	 * parent is always <code>null</code> and it cannot be resolved in any way.
+	 * Problems are never reported and a DOM AST created using this working copy
+	 * will not have bindings resolved.
+	 * <p>
+	 * When the working copy instance is created, an ADDED IJavaElementDelta is 
+	 * reported on this working copy.
+	 * </p><p>
+	 * Once done with the working copy, users of this method must discard it using 
+	 * {@link ICompilationUnit#discardWorkingCopy()}.
+	 * </p><p>
+	 * Note that when such working copy is committed, only its buffer is saved (
+	 * see {@link IBuffer#save(IProgressMonitor, boolean)}) but no resource is created.
+	 * </p><p>
+	 * This method is not intended to be overriden by clients.
+	 * </p>
+	 * @param monitor a progress monitor used to report progress while opening this 
+	 *   working copy or <code>null</code> if no progress should be reported 
+	 * @throws JavaModelException if the contents of this working copy can
+	 *   not be determined. 
+	 * @return a new working copy
+	 * @since 3.2
+	 */
+	public final ICompilationUnit newWorkingCopy(String name, IProgressMonitor monitor) throws JavaModelException {
+		CompilationUnit result = new CompilationUnit(null/*no parent*/, name, this);
+		result.becomeWorkingCopy(null/*no problems*/, monitor);
+		return result;
+	}
 
 }
diff --git a/model/org/eclipse/jdt/core/compiler/BrokenClasspathBuildFailureEvent.java b/model/org/eclipse/jdt/core/compiler/BrokenClasspathBuildFailureEvent.java
deleted file mode 100644
index d3169fe..0000000
--- a/model/org/eclipse/jdt/core/compiler/BrokenClasspathBuildFailureEvent.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    mkaufman@bea.com - initial API and implementation
- *******************************************************************************/
-
-
-package org.eclipse.jdt.core.compiler;
-
-import org.eclipse.jdt.core.IJavaProject;
-
-/**
- * An event class passed into ICompilationParticipant's notify() method when a build
- * has a catastrophic error that prevents the build from even running (e.g., a 
- * classpath error).
- * 
- *  @see ICompilationParticipant#notify(CompilationParticipantEvent)
- *  @since 3.2
- */
-public class BrokenClasspathBuildFailureEvent extends CompilationParticipantEvent {
-
-	public BrokenClasspathBuildFailureEvent( IJavaProject jp )
-	{
-		super( jp );
-	}
-	
-	/**
-	* @return an integer flag indicating the kind of event.  In this case, 
-	* BROKEN_CLASSPATH_BUILD_FAILURE_EVENT
-	* @see ICompilationParticipant#BROKEN_CLASSPATH_BUILD_FAILURE_EVENT
-	*/
-	public int           getKind()              { return ICompilationParticipant.BROKEN_CLASSPATH_BUILD_FAILURE_EVENT; }
-}
diff --git a/model/org/eclipse/jdt/core/compiler/BrokenClasspathBuildFailureResult.java b/model/org/eclipse/jdt/core/compiler/BrokenClasspathBuildFailureResult.java
deleted file mode 100644
index 9fce189..0000000
--- a/model/org/eclipse/jdt/core/compiler/BrokenClasspathBuildFailureResult.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    mkaufman@bea.com - initial API and implementation
- *******************************************************************************/
-
-
-package org.eclipse.jdt.core.compiler;
-
-/**
- * An result class used as a return value from ICompilationParticipant's notify() method 
- * when responding to a CatastrophicBuildFailureEvent.
- * 
- * @see ICompilationParticipant#notify(CompilationParticipantEvent)
- * @since 3.2
- */
-public class BrokenClasspathBuildFailureResult extends
-		CompilationParticipantResult {
-	/**
-	* @return an integer flag indicating the kind of event.  In this case, 
-	* BROKEN_CLASSPATH_BUILD_FAILURE_EVENT
-	* @see ICompilationParticipant#BROKEN_CLASSPATH_BUILD_FAILURE_EVENT
-	*/
-	public int getKind() { return ICompilationParticipant.BROKEN_CLASSPATH_BUILD_FAILURE_EVENT; }
-}
diff --git a/model/org/eclipse/jdt/core/compiler/CleanCompilationEvent.java b/model/org/eclipse/jdt/core/compiler/CleanCompilationEvent.java
deleted file mode 100644
index ec4dd8d..0000000
--- a/model/org/eclipse/jdt/core/compiler/CleanCompilationEvent.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc. 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    mkaufman@bea.com - initial API and implementation
- *    
- *******************************************************************************/
-
-package org.eclipse.jdt.core.compiler;
-
-import org.eclipse.jdt.core.IJavaProject;
-
-/**
- * An event class passed into ICompilationParticipant's notify() method when a
- * "clean" has been requested. 
- * 
- * @see ICompilationParticipant#notify(CompilationParticipantEvent)
- * @since 3.2
- */
-public class CleanCompilationEvent extends CompilationParticipantEvent {
-
-	public CleanCompilationEvent( IJavaProject p ) { super( p ); }
-	
-	/**
-	 * @return an integer flag indicating that this is a clean event.
-	 * @see ICompilationParticipant#CLEAN_EVENT
-	 * @see CompilationParticipantEvent#getKind()
-	 */
-	public int getKind() { return ICompilationParticipant.CLEAN_EVENT; }
-	
-}
diff --git a/model/org/eclipse/jdt/core/compiler/CleanCompilationResult.java b/model/org/eclipse/jdt/core/compiler/CleanCompilationResult.java
deleted file mode 100644
index eae341a..0000000
--- a/model/org/eclipse/jdt/core/compiler/CleanCompilationResult.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc. 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    mkaufman@bea.com - initial API and implementation
- *    
- *******************************************************************************/
-
-package org.eclipse.jdt.core.compiler;
-
-/**
- * An result class returned from an ICompilationParticipant's notify() method in 
- * response to a clean event;
- * 
- * @see ICompilationParticipant#notify(CompilationParticipantEvent)
- * @since 3.2
- */
-public class CleanCompilationResult extends CompilationParticipantResult {
-
-	/**
-	 * @return an integer flag indicating that this is result for a post-build event.
-	 * @see ICompilationParticipant#CLEAN_EVENT
-	 * @see CompilationParticipantResult#getKind()
-	 */
-	public int getKind() { return ICompilationParticipant.CLEAN_EVENT; }
-	
-}
diff --git a/model/org/eclipse/jdt/core/compiler/CompilationParticipant.java b/model/org/eclipse/jdt/core/compiler/CompilationParticipant.java
new file mode 100644
index 0000000..372e2da
--- /dev/null
+++ b/model/org/eclipse/jdt/core/compiler/CompilationParticipant.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    mkaufman@bea.com - initial API as ICompilationParticipant
+ *    IBM - changed from interface ICompilationParticipant to abstract class CompilationParticipant
+ *    IBM - rewrote spec
+ *    
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.compiler;
+
+import org.eclipse.jdt.core.IJavaProject;
+
+/**
+ * A compilation participant is notified of events occuring during the compilation process.
+ * The compilation process not only involves generating .class files (i.e. building), it also involve
+ * cleaning the output directory, reconciling a working copy, etc.
+ * So the notified events are the result of a build action, a clean action, a reconcile operation 
+ * (for a working copy), etc.
+ * <p>
+ * Clients wishing to participate in the compilation process must suclass this class, and implement
+ * {@link #isActive(IJavaProject)}, {@link #aboutToBuild(IJavaProject)}, 
+ * {@link #reconcile(ReconcileContext)}, etc.
+* </p><p>
+ * This class is intended to be subclassed by clients.
+ * </p>
+ * @since 3.2
+ */
+public abstract class CompilationParticipant {
+
+public static int READY_FOR_BUILD = 1;
+public static int NEEDS_FULL_BUILD = 2;
+
+/**
+ * Notifies this participant that a build is about to start and provides it the opportunity to
+ * create missing source folders for generated source files.
+ * Only sent to participants interested in the project.
+ * <p>
+ * Default is to return <code>READY_FOR_BUILD</code>.
+ * </p>
+ * @param project the project about to build
+ * @return READY_FOR_BUILD or NEEDS_FULL_BUILD
+ */
+public int aboutToBuild(IJavaProject project) {
+	return READY_FOR_BUILD;
+}
+
+/**
+ * Notifies this participant that a compile operation is about to start and provides it the opportunity to
+ * generate source files based on the source files about to be compiled.
+ * Only sent to participants interested in the current build project and answer false to isAnnotationProcessor().
+ *
+ * @param files is an array of CompilationParticipantResult
+  */
+public void buildStarting(ICompilationParticipantResult[] files) {
+	// do nothing by default
+}
+
+/**
+ * Notifies this participant that a clean is about to start and provides it the opportunity to
+ * delete generated source files.
+ * Only sent to participants interested in the project.
+ * @param project the project about to be cleaned
+ */
+public void cleanStarting(IJavaProject project) {
+	// do nothing by default
+}
+
+/**
+ * Returns whether this participant is active for a given project.
+ * <p>
+ * Default is to return <code>false</code>.
+ * </p><p>
+ * For efficiency, participants that are not interested in the 
+ * given project should return <code>false</code> for that project.
+ * </p>
+ * @param project the project to participate in
+ * @return whether this participant is active for a given project
+ */
+public boolean isActive(IJavaProject project) {
+	return false;
+}
+
+/**
+ * Returns whether this participant is interested in only Annotations.
+ * <p>
+ * Default is to return <code>false</code>.
+ * </p>
+ * @return whether this participant is interested in only Annotations.
+ */
+public boolean isAnnotationProcessor() {
+	return false;
+}
+
+/**
+ * Notifies this participant that a compile operation has found source files that define Annotations.
+ * When isBatchBuild is true, then filesWithAnnotations contains all source files in the project that
+ * declare annotations.
+ * Only sent to participants interested in the current build project and answer true to isAnnotationProcessor().
+ *
+ * @param filesWithAnnotations is an array of CompilationParticipantResult
+  */
+public void processAnnotations(ICompilationParticipantResult[] filesWithAnnotations, boolean isBatchBuild) {
+	// do nothing by default
+}
+
+/**
+ * Notifies this participant that a reconcile operation is happening. The participant can act on this reconcile
+ * operation by using the given context. Other participant can then see the result of this participation
+ * on this context.
+ * <p>
+ * Note that a participant should not modify the buffer of the working copy that is being reconciled.
+ * </p><p>
+ * Default is to do nothing.
+ * </p>
+ * @param context the reconcile context to act on
+  */
+public void reconcile(ReconcileContext context) {
+	// do nothing by default
+}
+
+}
diff --git a/model/org/eclipse/jdt/core/compiler/CompilationParticipantEvent.java b/model/org/eclipse/jdt/core/compiler/CompilationParticipantEvent.java
deleted file mode 100644
index 62bfd4a..0000000
--- a/model/org/eclipse/jdt/core/compiler/CompilationParticipantEvent.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc. 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    mkaufman@bea.com - initial API and implementation
- *    
- *******************************************************************************/
-
-package org.eclipse.jdt.core.compiler;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.jdt.core.IJavaProject;
-
-/**
- * Generic base class for an event passed into ICompilationParticipant's notify() method.  
- * This is subclassed to provide event-specific return information.
- * 
- * @see ICompilationParticipant#notify(CompilationParticipantEvent)
- * @since 3.2
- */
-public  class CompilationParticipantEvent {
-
-	/** 
-	 * Construct a new CompilationParticipantEvent for the specified IJavaProject
-	 * @param jp The IJavaProject that this compilation event is occurring on
-	 */
-	public CompilationParticipantEvent( IJavaProject jp)
-	{
-		_javaProject = jp;
-	}
-
-	/**
-	 * @return an integer flag indicating the kind of event.  One of the *_EVENT 
-	 * constants in ICompilationParticipant
-	 * @see ICompilationParticipant#GENERIC_EVENT
-	 */
-	public int           getKind()              { return ICompilationParticipant.GENERIC_EVENT; }
-	
-	/**
-	 * @return the IProject for this event
-	 */
-	public IProject      getProject()           { return _javaProject.getProject(); }
-
-	/**
-	 * @return the IJavaProject for this event
-	 */
-	public IJavaProject  getJavaProject()       { return _javaProject; }
-	
-	private IJavaProject _javaProject;
-}
diff --git a/model/org/eclipse/jdt/core/compiler/CompilationParticipantResult.java b/model/org/eclipse/jdt/core/compiler/CompilationParticipantResult.java
deleted file mode 100644
index 7c7d71b..0000000
--- a/model/org/eclipse/jdt/core/compiler/CompilationParticipantResult.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc. 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    mkaufman@bea.com - initial API and implementation
- *    
- *******************************************************************************/
-
-package org.eclipse.jdt.core.compiler;
-
-/**
- * A generic result object returned from ICompilationParticipant#notify.  This is subclassed
- * to provide event-specific return information.
- * 
- * @see ICompilationParticipant#notify(CompilationParticipantEvent)
- * @since 3.2
- */
-public class CompilationParticipantResult {
-
-	/**
-	 * @return an integer flag indicating the kind of event this is a result for.  
-	 * One of the *_EVENT constants in ICompilationParticipant.
-	 * @see ICompilationParticipant#GENERIC_EVENT
-	 */
-	public int getKind() { return ICompilationParticipant.GENERIC_EVENT; }
-	
-}
diff --git a/model/org/eclipse/jdt/core/compiler/ICompilationParticipant.java b/model/org/eclipse/jdt/core/compiler/ICompilationParticipant.java
deleted file mode 100644
index 28213e9..0000000
--- a/model/org/eclipse/jdt/core/compiler/ICompilationParticipant.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc. 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    mkaufman@bea.com - initial API and implementation
- *    
- *******************************************************************************/
-
-package org.eclipse.jdt.core.compiler;
-
-import org.eclipse.jdt.core.IJavaProject;
-
-/**
- * Interface to extend when for a client that wants to participate in the compilation process
- */
-public interface ICompilationParticipant {
-	
-	/**
-	 * Called when a compilation event is fired
-	 */
-	public CompilationParticipantResult notify( CompilationParticipantEvent e );
-
-	/**
-	 * During project compilation, this method is called on the compilation
-	 * participant to discover if it is interested in this project.<P>
-	 * 
-	 * For efficiency, participants that are not interested in a 
-	 * given project should return false for that project.<P>
-	 */
-	public boolean doesParticipateInProject( IJavaProject project );
-	
-	
-	/** 
-	 * a flag indicating a generic event 
-	 */
-	public static final int GENERIC_EVENT        = 1;
-	
-	/** 
-	 * a flag indicating an event fired before reconcile 
-	 */
-	public static final int PRE_RECONCILE_EVENT = 2;
-	
-	/** 
-	 * a flag indicating an event fired before a build 
-	 */
-	public static final int PRE_BUILD_EVENT      = 4;
-	
-	/** 
-	 * a flag indicating an event fired before a clean operation 
-	 */
-	public static final int CLEAN_EVENT          = 8;
-	
-	/**
-	 * a flag indicating an event fired when there is a catastrophic build 
-	 * failure, such as a broken classpath.
-	 */
-	public static final int BROKEN_CLASSPATH_BUILD_FAILURE_EVENT = 16;
-	
-}
diff --git a/model/org/eclipse/jdt/core/compiler/ICompilationParticipantResult.java b/model/org/eclipse/jdt/core/compiler/ICompilationParticipantResult.java
new file mode 100644
index 0000000..93f0fa2
--- /dev/null
+++ b/model/org/eclipse/jdt/core/compiler/ICompilationParticipantResult.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *    
+ *******************************************************************************/
+package org.eclipse.jdt.core.compiler;
+
+import org.eclipse.core.resources.IFile;
+
+public interface ICompilationParticipantResult {
+
+/**
+ * Returns the contents of the compilation unit.
+ */
+char[] getContents();
+
+/**
+ * Returns the IFile representing the compilation unit.
+ */
+IFile getFile();
+
+/**
+ * Record the added/changed generated files that need to be compiled.
+ */
+void recordAddedGeneratedFiles(IFile[] addedGeneratedFiles);
+
+/**
+ * Record the generated files that need to be deleted.
+ */
+void recordDeletedGeneratedFiles(IFile[] deletedGeneratedFiles);
+
+/**
+ * Record new problems to report against this compilationUnit.
+ */
+void recordNewProblems(IProblem[] newProblems);
+
+/**
+ * Record the fully-qualified type names of any new dependencies, each name is of the form 'p1.p2.A.B'.
+ */
+void recordDependencies(String[] typeNameDependencies);
+}
diff --git a/model/org/eclipse/jdt/core/compiler/PreBuildCompilationEvent.java b/model/org/eclipse/jdt/core/compiler/PreBuildCompilationEvent.java
deleted file mode 100644
index 4c64679..0000000
--- a/model/org/eclipse/jdt/core/compiler/PreBuildCompilationEvent.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc. 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    mkaufman@bea.com - initial API and implementation
- *    
- *******************************************************************************/
-
-package org.eclipse.jdt.core.compiler;
-
-import org.eclipse.core.resources.IFile;
-import org.eclipse.jdt.core.IJavaProject;
-
-/**
- * An event class passed into ICompilationParticipant's notify() method before a build
- * has completed.
- * 
- * @see ICompilationParticipant#notify(CompilationParticipantEvent)
- * @since 3.2
- */
-public class PreBuildCompilationEvent extends CompilationParticipantEvent {
-	
-	/**
-	 * @param files - IFile[] of the files about to be compiled
-	 * @param jp - the IJavaProject for the IFiles[] being compiled
-	 * @param isFullBuild <code>true</code> to indicate a full build, build after a clean.
-	 */
-	public PreBuildCompilationEvent( IFile[] files, IJavaProject jp, boolean isFullBuild ) 
-	{ 
-		super( jp );
-		_files = files;
-		_isFullBuild = isFullBuild;
-	}
-	
-	/**
-	 * @return -  IFile[] containing the files about to be compiled
-	 */
-	public IFile[] getFiles()  { return _files; }
-	
-	/**
-	 * @return <code>true</code> iff this the build is going to be a clean/full build.
-	 * Return <code>false</code> otherwise.
-	 */
-	public boolean isFullBuild(){ return _isFullBuild; }
-	
-	/**
-	 * @return an integer flag indicating that this is a pre-build event.
-	 * @see ICompilationParticipant#PRE_BUILD_EVENT
-	 * @see CompilationParticipantEvent#getKind()
-	 */
-	public final int getKind() { return ICompilationParticipant.PRE_BUILD_EVENT; }
-
-	private IFile[] _files;
-	
-	private final boolean _isFullBuild;
-	
-}
diff --git a/model/org/eclipse/jdt/core/compiler/PreBuildCompilationResult.java b/model/org/eclipse/jdt/core/compiler/PreBuildCompilationResult.java
deleted file mode 100644
index e60ae0d..0000000
--- a/model/org/eclipse/jdt/core/compiler/PreBuildCompilationResult.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc. 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    mkaufman@bea.com - initial API and implementation
- *    
- *******************************************************************************/
-
-package org.eclipse.jdt.core.compiler;
-
-import java.util.Map;
-
-import org.eclipse.core.resources.IFile;
-
-/**
- * An result class used as a return value from ICompilationParticipant's notify() method 
- * when responding to a pre-build event.
- * 
- * @see ICompilationParticipant#notify(CompilationParticipantEvent)
- * @since 3.2
- */
-public class PreBuildCompilationResult extends CompilationParticipantResult {
-
-	/**
-	 * Construct a new PreBuildCompilationResult.  
-	 * 
-	 * @param newFiles  - array of newly generated files that need to be inserted into
-	 *                 the compilation loop
-	 * @param newDependencyInfo - Map<IFile, Set<String>> where each entry in the map
-	 *        is the set of fully-qualified type names which are new dependencies 
-	 *        for the IFile.  The JDT will record these new dependencies in its depdency
-	 *        matrix. 
-	 */
-	public PreBuildCompilationResult( IFile[] newFiles, IFile[] deletedFiles, Map newDependencyInfo, Map newProblems, boolean classPathChanged )
-	{
-		_newFiles = newFiles;
-		_deletedFiles = deletedFiles;
-		_newDependencyInfo = newDependencyInfo;
-		_newProblems = newProblems;
-		_projectClasspathChanged = classPathChanged;
-	}
-	
-	/** 
-	 * 
-	 * @return IFile[] that is the set of new files to be added into the compilation
-	 * set.
-	 */
-	public IFile[] getNewFiles() { return _newFiles; }
-	
-	/** 
-	 * 
-	 * @return IFile[] that is the set of files to be deleted from the compilation set
-	 */
-	public IFile[] getDeletedFiles() { return _deletedFiles; }
-		
-	/**
-	 * 
-	 * @return Map<IFile, Set<String>> that maps IFile to the fully-qualified type
-	 * names of any new dependencies that need to be added into the JDT's dependency
-	 * matrix.
-	 */
-	public Map     getNewDependencies() { return _newDependencyInfo; }
-	
-	/**
-	 * 
-	 * @return Map<IFile, List<IProblem>> that maps the files built to the problems 
-	 * encountered during prebuild compilation.
-	 */
-	public Map 	   getProblems(){ return _newProblems; }
-	
-	/**
-	 * @return an integer flag indicating that this is result for a pre-build event.
-	 * @see ICompilationParticipant#PRE_BUILD_EVENT
-	 * @see CompilationParticipantEvent#getKind()
-	 */
-	public final int getKind() { return ICompilationParticipant.PRE_BUILD_EVENT; }
-	
-	/**
-	 * @return boolean indicating if the project's classpath was changed by the
-	 * compilation participant.  Defaults to false. 
-	 */
-	public boolean getProjectClasspathChanged() { return _projectClasspathChanged; }
-	
-	/**
-	 *  sets the value of this PreBuildCompilationResult _hasClasspathChanged member.
-	 *  Should be called by a client if the ICompilationParticipant has modified
-	 *  the projects ClasspathEntries in any way (for example, by adding a new source
-	 *  path to the project).  
-	 */
-	public void    setProjectClasspathChanged( boolean b ) { _projectClasspathChanged = b; }
-	
-	private IFile[] _newFiles;
-	private IFile[] _deletedFiles;
-	private Map     _newDependencyInfo;
-	private Map		_newProblems;
-	private boolean _projectClasspathChanged;
-	
-}
diff --git a/model/org/eclipse/jdt/core/compiler/PreReconcileCompilationEvent.java b/model/org/eclipse/jdt/core/compiler/PreReconcileCompilationEvent.java
deleted file mode 100644
index cb9ae14..0000000
--- a/model/org/eclipse/jdt/core/compiler/PreReconcileCompilationEvent.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc. 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    mkaufman@bea.com - initial API and implementation
- *    
- *******************************************************************************/
-
-package org.eclipse.jdt.core.compiler;
-
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaProject;
-
-/**
- * An event class passed into ICompilationParticipant's notify() method before a reconcile
- * has begun.
- * 
- *  @see ICompilationParticipant#notify(CompilationParticipantEvent)
- *  @since 3.2
- */
-public class PreReconcileCompilationEvent extends CompilationParticipantEvent {
-
-	/**
-	 * constructs a new PreReconcileCompilationEvent
-	 * 
-	 * @param cu - the ICompilationUnit that is about to be reconciled
-	 * @param jp - the java project for the ICompilationUnit that will be reconciled
-	 */
-	public PreReconcileCompilationEvent( ICompilationUnit cu, IJavaProject jp )
-	{
-		super( jp );
-		_compilationUnit = cu;
-	}
-	
-	
-	/** @return the ICompilationUnit that will be reconciled */
-	public ICompilationUnit getCompilationUnit() { return _compilationUnit; }
-	
-	/**
-	 * @return an integer flag indicating that this is a pre-reconcile event.
-	 * @see ICompilationParticipant#PRE_RECONCILE_EVENT
-	 * @see CompilationParticipantEvent#getKind()
-	 */
-	public final int getKind() { return ICompilationParticipant.PRE_RECONCILE_EVENT; }
-
-	private ICompilationUnit _compilationUnit;
-	
-}
diff --git a/model/org/eclipse/jdt/core/compiler/PreReconcileCompilationResult.java b/model/org/eclipse/jdt/core/compiler/PreReconcileCompilationResult.java
deleted file mode 100644
index 9d9c67f..0000000
--- a/model/org/eclipse/jdt/core/compiler/PreReconcileCompilationResult.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2005 BEA Systems, Inc. 
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    mkaufman@bea.com - initial API and implementation
- *    
- *******************************************************************************/
-
-package org.eclipse.jdt.core.compiler;
-
-/**
- * An result class used as a return value from ICompilationParticipant's notify() method 
- * when responding to a pre-reconcile event.
- * 
- * @see ICompilationParticipant#notify(CompilationParticipantEvent)
- * @since 3.2
- */
-public class PreReconcileCompilationResult extends CompilationParticipantResult {
-
-	public PreReconcileCompilationResult(final IProblem[] problems )
-	{
-		_problems = problems;
-	}
-	
-	/**
-	 * @return an integer flag indicating that this is result for a pre-reconcile event.
-	 * @see ICompilationParticipant#PRE_RECONCILE_EVENT
-	 * @see CompilationParticipantEvent#getKind()
-	 */
-	public final int getKind() { return ICompilationParticipant.PRE_RECONCILE_EVENT; }
-	
-	/**
-	 * @return the array of problems generated by the participant during reconcile 
-	 */
-	public IProblem[] getProblems(){ return _problems; }
-
-	private final IProblem[] _problems;
-
-}
diff --git a/model/org/eclipse/jdt/core/compiler/ReconcileContext.java b/model/org/eclipse/jdt/core/compiler/ReconcileContext.java
new file mode 100644
index 0000000..f2d3aa5
--- /dev/null
+++ b/model/org/eclipse/jdt/core/compiler/ReconcileContext.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others. 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    mkaufman@bea.com - initial API and implementation
+ *    IBM - renamed from PreReconcileCompilationResult to ReconcileContext
+ *    IBM - rewrote spec
+ *    
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.compiler;
+
+import java.util.HashMap;
+
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElementDelta;
+import org.eclipse.jdt.core.IJavaModelMarker;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.internal.core.CompilationUnit;
+import org.eclipse.jdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.ReconcileWorkingCopyOperation;
+
+/**
+ * The context of a reconcile event that is notified to interested compilation 
+ * participants while a reconcile operation is running.
+ * <p>
+ * A reconcile participant can get the AST for the reconcile-operation using
+ * {@link #getAST(int, boolean)}. If the participant modifies in any way the AST 
+ * (either by modifying the source of the working copy, or modifying another entity 
+ * that would result in different bindings for the AST), it is expected to reset the 
+ * AST in the context using {@link #resetAST()}.
+ * </p><p>
+ * A reconcile participant can also create and return problems using 
+ * {@link #putProblems(String, CategorizedProblem[])}. These problems are then reported 
+ * to the problem requestor of the reconcile operation.
+ * </p><p>
+ * This class is not intended to be instanciated or subclassed by clients.
+ * </p>
+ * 
+ * @see CompilationParticipant#reconcile(ReconcileContext)
+ * @since 3.2
+ */
+public class ReconcileContext {
+	
+	private ReconcileWorkingCopyOperation operation;
+	private CompilationUnit workingCopy;
+
+/**
+ * Creates a reconcile context for the given reconcile operation.
+ * <p>
+ * This constructor is not intended to be called by clients.
+ * </p>
+ * 
+ * @param operation the reconcile operation
+ */
+public ReconcileContext(ReconcileWorkingCopyOperation operation, CompilationUnit workingCopy) {
+	this.operation = operation;
+	this.workingCopy = workingCopy;
+}
+
+/**
+ * Returns the AST created from the current state of the working copy.
+ * Creates one if none exists yet.
+ * Returns <code>null</code> if the current state of the working copy
+ * doesn't allow the AST to be created (e.g. if the working copy's content 
+ * cannot be parsed).
+ * <p>
+ * If the requested AST level is different from the {@link #getASTLevel() current AST level}
+ * or if binding resolutions is requested when no {@link #isResolvingBindings() binding resolution}
+ * was requested when reconciling, then a different AST is created. Note that this AST does not 
+ * become the current AST and it is only valid for the requestor.
+ * </p>
+ * 
+ * @param astLevel the level of AST requested
+ * @param resolveBindings whether the bindings in the returned AST should be resolved
+ * @return the AST created from the current state of the working copy,
+ *   or <code>null</code> if none could be created
+ * @exception JavaModelException  if the contents of the working copy
+ *		cannot be accessed. Reasons include:
+ * <ul>
+ * <li> The working copy does not exist (ELEMENT_DOES_NOT_EXIST)</li>
+ * </ul>
+ */
+public org.eclipse.jdt.core.dom.CompilationUnit getAST(int astLevel, boolean resolveBindings) throws JavaModelException {
+	if (this.operation.astLevel != astLevel || !this.operation.resolveBindings & resolveBindings) {
+		// create AST (optionally resolving bindings)
+		ASTParser parser = ASTParser.newParser(astLevel);
+		parser.setCompilerOptions(workingCopy.getJavaProject().getOptions(true));
+		if (resolveBindings && JavaProject.hasJavaNature(workingCopy.getJavaProject().getProject()))
+			parser.setResolveBindings(true);
+		parser.setSource(workingCopy);
+		return (org.eclipse.jdt.core.dom.CompilationUnit) parser.createAST(this.operation.progressMonitor);		
+	}
+	return this.operation.makeConsistent(this.workingCopy, null/*don't report problems to the working copy's problem requestor*/);
+}
+
+/**
+ * Returns the AST level requested by the reconcile operation.
+ * It is either {@link ICompilationUnit#NO_AST}, or one of the JLS constants defined on {@link AST}.
+ * 
+ * @return the AST level requested by the reconcile operation
+ */
+public int getASTLevel() {
+	return this.operation.astLevel;
+}
+
+/**
+ * Returns whether the reconcile operation is resolving bindings.
+ * 
+ * @return whether the reconcile operation is resolving bindings
+ */
+public boolean isResolvingBindings() {
+	return this.operation.resolveBindings;
+}
+
+/**
+ * Returns the delta describing the change to the working copy being reconciled.
+ * Returns <code>null</code> if there is no change.
+ * Note that the delta's AST is not yet positionnned at this stage. Use {@link #getAST(int, boolean)}
+ * to get the current AST.
+ *
+ * @return the delta describing the change, or <code>null</code> if none
+ */
+public IJavaElementDelta getDelta() {
+	return this.operation.deltaBuilder.delta;
+}
+
+/**
+ * Returns the problems to be reported to the problem requestor of the reconcile operation
+ * for the given marker type.
+ * Returns <code>null</code> if no problems need to be reported for this marker type.
+ * 
+ * @param markerType the given marker type
+ * @return problems to be reported to the problem requesto
+ */
+public CategorizedProblem[] getProblems(String markerType) {
+	if (this.operation.problems == null) return null;
+	return (CategorizedProblem[]) this.operation.problems.get(markerType);
+}
+
+/**
+ * Returns the working copy this context refers to.
+ * 
+ * @return the working copy this context refers to
+ */
+public ICompilationUnit getWorkingCopy() {
+	return this.workingCopy;
+}
+
+/**
+ * Resets the AST carried by this context.
+ * A compilation participant that modifies the environment that would result in different 
+ * bindings for the AST is expected to reset the AST on this context, so that other 
+ * participants don't get a stale AST.
+ * <p>
+ * Note that resetting the AST will not restart the reconcile process. Only further 
+ * participants will see the new AST. Thus participants running before the one that
+ * resets the AST will have a stale view of the AST and its problems. Use 
+ * the compilation participant extension point to order the participants.
+ * </p>
+ */
+public void resetAST() {
+	this.operation.ast = null;
+	putProblems(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, null);
+	putProblems(IJavaModelMarker.TASK_MARKER, null);
+}
+
+/**
+ * Sets the problems to be reported to the problem requestor of the reconcile operation
+ * for the given marker type.
+ * <code>null</code> indicates that no problems need to be reported.
+ * <p>
+ * Using this functionality, a participant that resolves problems for a given marker type 
+ * can hide those problems since they don't exist any longer.
+ * </p>
+ * 
+ * @param markerType the marker type of the given problems
+ * @param problems  the problems to be reported to the problem requestor of the reconcile operation,
+ *   or <code>null</code> if none
+ */
+public void putProblems(String markerType, CategorizedProblem[] problems) {
+	if (this.operation.problems == null)
+		this.operation.problems = new HashMap();
+	this.operation.problems.put(markerType, problems);
+}
+
+}
diff --git a/model/org/eclipse/jdt/core/util/IStackMapFrame.java b/model/org/eclipse/jdt/core/util/IStackMapFrame.java
new file mode 100644
index 0000000..52c43a5
--- /dev/null
+++ b/model/org/eclipse/jdt/core/util/IStackMapFrame.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.util;
+
+/**
+ * Description of a stack map frame as specified in the JVM specifications.
+ * 
+ * This interface may be implemented by clients. 
+ * 
+ * @since 3.2
+ */
+public interface IStackMapFrame {
+	
+	/**
+	 * Answer back the frame type for this entry.
+	 * <table>
+	 * <tr>
+	 * <th align="left">Type</th>
+	 * <th align="left">Range</th>
+	 * </tr>
+	 * <tr>
+	 * <td>SAME</td>
+	 * <td>0-63</td>
+	 * </tr>
+	 * <tr>
+	 * <td>SAME_LOCALS_1_STACK_ITEM</td>
+	 * <td>64-127</td>
+	 * </tr>
+	 * <tr>
+	 * <td>SAME_LOCALS_1_STACK_ITEM_EXTENDED</td>
+	 * <td>247</td>
+	 * </tr>
+	 * <tr>
+	 * <td>CHOP</td>
+	 * <td>248-250</td>
+	 * </tr>
+	 * <tr>
+	 * <td>SAME_FRAME_EXTENDED</td>
+	 * <td>251</td>
+	 * </tr>
+	 * <tr>
+	 * <td>APPEND</td>
+	 * <td>252-254</td>
+	 * </tr>
+	 * <tr>
+	 * <td>FULL_FRAME</td>
+	 * <td>255</td>
+	 * </tr>
+	 * </table> 
+	 * 
+	 * @return the frame type for this entry
+	 */
+	int getFrameType();
+
+	/**
+	 * Answer back the offset delta.
+	 * <p>This is not defined only for the frame types SAME and SAME_LOCALS_1_STACK_ITEM.</p>  
+	 * 
+	 * @return the offset delta
+	 */
+	int getOffsetDelta();
+
+	/**
+	 * Answer back the number of locals.
+	 * <p>This is defined only for the frame type FULL_FRAME.</p>
+	 * 
+	 * @return the number of locals
+	 */
+	int getNumberOfLocals();
+
+	/**
+	 * Answer back verification infos for the defined locals.
+	 * <p>This is defined only for frame types APPEND and FULL_FRAME.
+	 * 
+	 * @return verification infos for the defined locals
+	 */
+	IVerificationTypeInfo[] getLocals();
+
+	/**
+	 * Answer back the number of stack items
+	 * <p>This is defined only for the frame types SAME_LOCALS_1_STACK_ITEM, SAME_LOCALS_1_STACK_ITEM_EXTENDED and FULL_FRAME.
+	 * For SAME_LOCALS_1_STACK_ITEM and SAME_LOCALS_1_STACK_ITEM_EXTENDED, the answer is implicitely 1.</p>
+	 * 
+	 * @return the number of stack items
+	 */
+	int getNumberOfStackItems();
+	
+	/**
+	 * Answer back the verification infos for the stack items.
+	 * 
+	 * @return the verification infos for the stack items
+	 */
+	IVerificationTypeInfo[] getStackItems();
+}
diff --git a/model/org/eclipse/jdt/core/util/IStackMapTableAttribute.java b/model/org/eclipse/jdt/core/util/IStackMapTableAttribute.java
new file mode 100644
index 0000000..d38c354
--- /dev/null
+++ b/model/org/eclipse/jdt/core/util/IStackMapTableAttribute.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.util;
+
+/**
+ * This class represents a stack map table attribute.
+ * 
+ * @since 3.2
+ */
+public interface IStackMapTableAttribute extends IClassFileAttribute {
+	
+	/**
+	 * Answer back the number of stack map frames of this atribute as specified in
+	 * the JVM specifications.
+	 * 
+	 * @return the number of stack map frames of this atribute as specified in
+	 * the JVM specifications
+	 */
+	int getNumberOfEntries();
+
+	/**
+	 * Answer back the stack map frames for this attribute as specified
+	 * in the JVM specifications.
+	 * 
+	 * @return the stack map frames for this attribute as specified
+	 * in the JVM specifications
+	 */
+	IStackMapFrame[] getStackMapFrame();
+}
diff --git a/model/org/eclipse/jdt/core/util/IVerificationTypeInfo.java b/model/org/eclipse/jdt/core/util/IVerificationTypeInfo.java
index e78fcbb..c71d3a0 100644
--- a/model/org/eclipse/jdt/core/util/IVerificationTypeInfo.java
+++ b/model/org/eclipse/jdt/core/util/IVerificationTypeInfo.java
@@ -19,6 +19,52 @@
  */
 public interface IVerificationTypeInfo {
 	/**
+	 * The tag value representing top variable info
+	 * @since 3.2
+	 */
+	public static final int ITEM_TOP = 0;
+	/**
+	 * The tag value representing integer variable info
+	 * @since 3.2
+	 */
+	public static final int ITEM_INTEGER = 1;
+	/**
+	 * The tag value representing float variable info
+	 * @since 3.2
+	 */
+	public static final int ITEM_FLOAT = 2;
+	/**
+	 * The tag value representing double variable info
+	 * @since 3.2
+	 */
+	public static final int ITEM_DOUBLE = 3;
+	/**
+	 * The tag value representing long variable info
+	 * @since 3.2
+	 */
+	public static final int ITEM_LONG = 4;
+	/**
+	 * The tag value representing null variable info
+	 * @since 3.2
+	 */
+	public static final int ITEM_NULL = 5;
+	/**
+	 * The tag value representing uninitialized this variable info
+	 * @since 3.2
+	 */
+	public static final int ITEM_UNINITIALIZED_THIS = 6;
+	/**
+	 * The tag value representing object variable info
+	 * @since 3.2
+	 */
+	public static final int ITEM_OBJECT = 7;
+	/**
+	 * The tag value representing uninitialized variable info
+	 * @since 3.2
+	 */
+	public static final int ITEM_UNINITIALIZED = 8;
+	
+	/**
 	 * Answer back the tag of this verification type info as described in the JVM specifications.
 	 * <ul>
 	 * <li>0 for the top type</li>
diff --git a/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java b/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
index 59ce62f..eeea18b 100644
--- a/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
+++ b/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
@@ -473,6 +473,11 @@
 		declaration.declarationSourceStart = previousVariable.declarationSourceStart;
 		declaration.modifiers = previousVariable.modifiers;
 		declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
+		final Annotation[] annotations = previousVariable.annotations;
+		if (annotations != null) {
+			final int annotationsLength = annotations.length;
+			System.arraycopy(annotations, 0, declaration.annotations = new Annotation[annotationsLength], 0, annotationsLength);
+		}
 	}
 
 	localIntPtr = intPtr;
diff --git a/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java b/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
index e1b36e3..63e1952 100644
--- a/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
+++ b/model/org/eclipse/jdt/internal/compiler/ISourceElementRequestor.java
@@ -49,6 +49,7 @@
 		public TypeParameterInfo[] typeParameters;
 		public long[] annotationPositions;
 		public char[][] categories;
+		public boolean secondary;
 	}
 	
 	public static class TypeParameterInfo {
diff --git a/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java b/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
index c6096d1..abe88d7 100644
--- a/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
+++ b/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
@@ -57,6 +57,7 @@
 	CompilerOptions options;
 	HashtableOfObjectToInt sourceEnds = new HashtableOfObjectToInt();
 	HashMap nodesToCategories = new HashMap(); // a map from ASTNode to char[][]
+	boolean useSourceJavadocParser = true;
 	
 /**
  * An ast visitor that visits local type declarations.
@@ -94,6 +95,16 @@
 		CompilerOptions options,
 		boolean reportLocalDeclarations,
 		boolean optimizeStringLiterals) {
+	this(requestor, problemFactory, options, reportLocalDeclarations, optimizeStringLiterals, true/* use SourceJavadocParser */);
+}
+
+public SourceElementParser(
+		final ISourceElementRequestor requestor, 
+		IProblemFactory problemFactory,
+		CompilerOptions options,
+		boolean reportLocalDeclarations,
+		boolean optimizeStringLiterals,
+		boolean useSourceJavadocParser) {
 	// we want to notify all syntax error with the acceptProblem API
 	// To do so, we define the record method of the ProblemReporter
 	super(new ProblemReporter(
@@ -115,7 +126,10 @@
 		this.localDeclarationVisitor = new LocalDeclarationVisitor();
 	}
 	// set specific javadoc parser
-	this.javadocParser = new SourceJavadocParser(this);
+	this.useSourceJavadocParser = useSourceJavadocParser;
+	if (useSourceJavadocParser) {
+		this.javadocParser = new SourceJavadocParser(this);
+	}
 }
 
 public void checkComment() {
@@ -1246,6 +1260,7 @@
 			typeInfo.typeParameters = getTypeParameterInfos(typeDeclaration.typeParameters);
 			typeInfo.annotationPositions = collectAnnotationPositions(typeDeclaration.annotations);
 			typeInfo.categories = (char[][]) this.nodesToCategories.get(typeDeclaration);
+			typeInfo.secondary = typeDeclaration.isSecondary();
 			requestor.enterType(typeInfo);
 			switch (kind) {
 				case TypeDeclaration.CLASS_DECL :
@@ -1323,11 +1338,13 @@
 	}
 }
 private void rememberCategories() {
-	SourceJavadocParser sourceJavadocParser = (SourceJavadocParser) this.javadocParser;
-	char[][] categories =  sourceJavadocParser.categories;
-	if (categories.length > 0) {
-		this.nodesToCategories.put(this.astStack[this.astPtr], categories);
-		sourceJavadocParser.categories = CharOperation.NO_CHAR_CHAR;
+	if (this.useSourceJavadocParser) {
+		SourceJavadocParser sourceJavadocParser = (SourceJavadocParser) this.javadocParser;
+		char[][] categories =  sourceJavadocParser.categories;
+		if (categories.length > 0) {
+			this.nodesToCategories.put(this.astStack[this.astPtr], categories);
+			sourceJavadocParser.categories = CharOperation.NO_CHAR_CHAR;
+		}
 	}
 }
 private int sourceEnd(TypeDeclaration typeDeclaration) {
diff --git a/model/org/eclipse/jdt/internal/compiler/SourceJavadocParser.java b/model/org/eclipse/jdt/internal/compiler/SourceJavadocParser.java
index 6acb1bd..f17d917 100644
--- a/model/org/eclipse/jdt/internal/compiler/SourceJavadocParser.java
+++ b/model/org/eclipse/jdt/internal/compiler/SourceJavadocParser.java
@@ -22,7 +22,7 @@
 
 public SourceJavadocParser(Parser sourceParser) {
 	super(sourceParser);
-	this.kind = SOURCE_PARSER;
+	this.kind = SOURCE_PARSER | TEXT_VERIF;
 }
 
 public boolean checkDeprecation(int commentPtr) {
diff --git a/model/org/eclipse/jdt/internal/core/ASTHolderCUInfo.java b/model/org/eclipse/jdt/internal/core/ASTHolderCUInfo.java
index 6990e7a..0101f87 100644
--- a/model/org/eclipse/jdt/internal/core/ASTHolderCUInfo.java
+++ b/model/org/eclipse/jdt/internal/core/ASTHolderCUInfo.java
@@ -10,9 +10,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.util.HashMap;
+
 import org.eclipse.jdt.core.dom.CompilationUnit;
 
 public class ASTHolderCUInfo extends CompilationUnitElementInfo {
 	int astLevel;
+	boolean resolveBindings;
+	HashMap problems = null;
 	CompilationUnit ast;
 }
diff --git a/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java b/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
index 200f766..62845b2 100644
--- a/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
+++ b/model/org/eclipse/jdt/internal/core/BasicCompilationUnit.java
@@ -119,7 +119,7 @@
 			start = separator;
 	
 		int end = CharOperation.lastIndexOf('$', this.fileName);
-		if (end == -1) {
+		if (end == -1 || !Util.isClassFileName(this.fileName)) {
 			end = CharOperation.lastIndexOf('.', this.fileName);
 			if (end == -1)
 				end = this.fileName.length;
diff --git a/model/org/eclipse/jdt/internal/core/BecomeWorkingCopyOperation.java b/model/org/eclipse/jdt/internal/core/BecomeWorkingCopyOperation.java
index 932a72f..a8e608e 100644
--- a/model/org/eclipse/jdt/internal/core/BecomeWorkingCopyOperation.java
+++ b/model/org/eclipse/jdt/internal/core/BecomeWorkingCopyOperation.java
@@ -39,13 +39,13 @@
 
 		if (!workingCopy.isPrimary()) {
 			// report added java delta for a non-primary working copy
-			JavaElementDelta delta = new JavaElementDelta(this.getJavaModel());
+			JavaElementDelta delta = new JavaElementDelta(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());
+				JavaElementDelta delta = new JavaElementDelta(getJavaModel());
 				delta.changed(workingCopy, IJavaElementDelta.F_PRIMARY_WORKING_COPY);
 				addDelta(delta);
 			} else {
diff --git a/model/org/eclipse/jdt/internal/core/BinaryField.java b/model/org/eclipse/jdt/internal/core/BinaryField.java
index 6e5066c..eafb15d 100644
--- a/model/org/eclipse/jdt/internal/core/BinaryField.java
+++ b/model/org/eclipse/jdt/internal/core/BinaryField.java
@@ -10,8 +10,10 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IField;
+import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.internal.compiler.env.IBinaryField;
@@ -105,4 +107,24 @@
 		}
 	}
 }
+public String getAttachedJavadoc(IProgressMonitor monitor, String defaultEncoding) throws JavaModelException {
+	String contents = ((BinaryType) this.getDeclaringType()).getJavadocContents(monitor, defaultEncoding);
+	if (contents == null) return null;
+	int indexAnchor = contents.indexOf(
+			JavadocConstants.ANCHOR_PREFIX_START + this.getElementName() + JavadocConstants.ANCHOR_PREFIX_END);
+	if (indexAnchor == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+	int indexOfEndLink = contents.indexOf(JavadocConstants.ANCHOR_SUFFIX, indexAnchor);
+	if (indexOfEndLink == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+	int indexOfNextField = contents.indexOf(JavadocConstants.ANCHOR_PREFIX_START, indexOfEndLink);
+	int indexOfBottom = contents.indexOf(JavadocConstants.CONSTRUCTOR_DETAIL, indexOfEndLink);
+	if (indexOfBottom == -1) {
+		indexOfBottom = contents.indexOf(JavadocConstants.METHOD_DETAIL, indexOfEndLink);
+		if (indexOfBottom == -1) {
+			indexOfBottom = contents.indexOf(JavadocConstants.END_OF_CLASS_DATA, indexOfEndLink);
+		}
+	}
+	indexOfNextField= Math.min(indexOfNextField, indexOfBottom);
+	if (indexOfNextField == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+	return contents.substring(indexOfEndLink + JavadocConstants.ANCHOR_SUFFIX_LENGTH, indexOfNextField);
+}
 }
diff --git a/model/org/eclipse/jdt/internal/core/BinaryMethod.java b/model/org/eclipse/jdt/internal/core/BinaryMethod.java
index 1cedf39..89f1c14 100644
--- a/model/org/eclipse/jdt/internal/core/BinaryMethod.java
+++ b/model/org/eclipse/jdt/internal/core/BinaryMethod.java
@@ -10,16 +10,12 @@
  *******************************************************************************/
 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.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.CharOperation;
-import org.eclipse.jdt.internal.compiler.SourceElementRequestorAdapter;
 import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
 import org.eclipse.jdt.internal.core.util.Util;
 
 /**
@@ -27,34 +23,6 @@
  */
 
 /* package */ class BinaryMethod extends BinaryMember implements IMethod {
-	
-	class DecodeParametersNames extends SourceElementRequestorAdapter {
-			String[] parametersNames;
-		
-			public void enterMethod(MethodInfo methodInfo) {
-					if (methodInfo.parameterNames != null) {
-						int length = methodInfo.parameterNames.length;
-						this.parametersNames = new String[length];
-						for (int i = 0; i < length; i++) {
-							this.parametersNames[i] = new String(methodInfo.parameterNames[i]);
-						}
-					}
-				}
-				
-			public void enterConstructor(MethodInfo methodInfo) {
-					if (methodInfo.parameterNames != null) {
-						int length = methodInfo.parameterNames.length;
-						this.parametersNames = new String[length];
-						for (int i = 0; i < length; i++) {
-							this.parametersNames[i] = new String(methodInfo.parameterNames[i]);
-						}
-					}
-				}
-				
-				public String[] getParametersNames() {
-					return this.parametersNames;
-				}
-	}
 
 	/**
 	 * The parameter type signatures of the method - stored locally
@@ -67,17 +35,14 @@
 	 */
 	protected String[] parameterNames;
 
-	/**
-	 * An empty list of Strings
-	 */
-	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 (paramTypes == null) {
-		this.parameterTypes= NO_TYPES;
+		this.parameterTypes= CharOperation.NO_STRINGS;
 	} else {
 		this.parameterTypes= paramTypes;
 	}
@@ -100,7 +65,7 @@
 		if (this.exceptionTypes == null || this.exceptionTypes.length == 0) {
 			char[][] eTypeNames = info.getExceptionTypeNames();
 			if (eTypeNames == null || eTypeNames.length == 0) {
-				this.exceptionTypes = NO_TYPES;
+				this.exceptionTypes = CharOperation.NO_STRINGS;
 			} else {
 				eTypeNames = ClassFile.translatedNames(eTypeNames);
 				this.exceptionTypes = new String[eTypeNames.length];
@@ -168,42 +133,132 @@
  * Look for source attachment information to retrieve the actual parameter names as stated in source.
  */
 public String[] getParameterNames() throws JavaModelException {
-	if (this.parameterNames == null) {
+	if (this.parameterNames != null) 
+		return this.parameterNames;
 
-		// force source mapping if not already done
-		IType type = (IType) getParent();
-		SourceMapper mapper = getSourceMapper();
-		if (mapper != null) {
-			char[][] paramNames = mapper.getMethodParameterNames(this);
-			
-			// map source and try to find parameter names
-			if(paramNames == null) {
-				char[] source = mapper.findSource(type);
-				if (source != null){
-					mapper.mapSource(type, source);
-				}
-				paramNames = mapper.getMethodParameterNames(this);
+	// force source mapping if not already done
+	IType type = (IType) getParent();
+	SourceMapper mapper = getSourceMapper();
+	if (mapper != null) {
+		char[][] paramNames = mapper.getMethodParameterNames(this);
+		
+		// map source and try to find parameter names
+		if(paramNames == null) {
+			char[] source = mapper.findSource(type);
+			if (source != null){
+				mapper.mapSource(type, source);
 			}
-			
-			// if parameter names exist, convert parameter names to String array
-			if(paramNames != null) {
-				this.parameterNames = new String[paramNames.length];
-				for (int i = 0; i < paramNames.length; i++) {
-					this.parameterNames[i] = new String(paramNames[i]);
-				}
-			}
+			paramNames = mapper.getMethodParameterNames(this);
 		}
-		// if still no parameter names, produce fake ones
-		if (this.parameterNames == null) {
-			IBinaryMethod info = (IBinaryMethod) getElementInfo();
-			int paramCount = Signature.getParameterCount(new String(info.getMethodDescriptor()));
-			this.parameterNames = new String[paramCount];
-			for (int i = 0; i < paramCount; i++) {
-				this.parameterNames[i] = "arg" + i; //$NON-NLS-1$
+		
+		// if parameter names exist, convert parameter names to String array
+		if(paramNames != null) {
+			this.parameterNames = new String[paramNames.length];
+			for (int i = 0; i < paramNames.length; i++) {
+				this.parameterNames[i] = new String(paramNames[i]);
+			}
+			return this.parameterNames;
+		}
+	}
+	
+	// try to see if we can retrieve the names from the attached javadoc
+	IBinaryMethod info = (IBinaryMethod) getElementInfo();
+	final int paramCount = Signature.getParameterCount(new String(info.getMethodDescriptor()));
+	if (paramCount != 0) {
+ 		String javadocContents = null;
+ 		IType declaringType = this.getDeclaringType();
+		PerProjectInfo projectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.getJavaProject().getProject());
+ 		synchronized (projectInfo.javadocCache) {
+ 			javadocContents = (String) projectInfo.javadocCache.get(declaringType);
+ 			if (javadocContents == null) {
+ 				projectInfo.javadocCache.put(declaringType, BinaryType.EMPTY_JAVADOC);
+ 			}
+ 		}
+ 		if (javadocContents == null) {
+ 			long timeOut = 50; // default value
+ 			try {
+ 				String option = this.getJavaProject().getOption(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, true);
+ 				if (option != null) {
+ 					timeOut = Long.parseLong(option);
+ 				}
+ 			} catch(NumberFormatException e) {
+ 				// ignore
+ 			}
+ 			if (timeOut == 0) {
+ 				// don't try to fetch the values
+ 				return this.parameterNames = getRawParameterNames(paramCount);
+ 			}
+ 			final class ParametersNameCollector {
+ 				String javadoc;
+ 				public void setJavadoc(String s) {
+ 					this.javadoc = s;
+ 				}
+ 				public String getJavadoc() {
+ 					return this.javadoc;
+ 				}
+ 	 		}
+ 			/*
+ 			 * The declaring type is not in the cache yet. The thread wil retrieve the javadoc contents
+ 			 */
+	 		final ParametersNameCollector nameCollector = new ParametersNameCollector();
+			Thread collect = new Thread() {
+				public void run() {
+					try {
+						// this call has a side-effect on the per project info cache
+						nameCollector.setJavadoc(BinaryMethod.this.getAttachedJavadoc(null, "UTF-8")); //$NON-NLS-1$
+			        } catch (JavaModelException e) {
+	 		        	// ignore
+	 		        }
+					synchronized(nameCollector) {
+						nameCollector.notify();
+					}
+				}
+			};
+			collect.start();
+			synchronized(nameCollector) {
+				try {
+					nameCollector.wait(timeOut);
+				} catch (InterruptedException e) {
+					// ignore
+				}
+			}
+			javadocContents = nameCollector.getJavadoc();
+ 		} else if (javadocContents != BinaryType.EMPTY_JAVADOC){
+ 			// need to extract the part relative to the binary method since javadoc contains the javadoc for the declaring type
+ 			javadocContents = extractJavadoc(declaringType, javadocContents);
+ 		} else {
+ 			// we don't want to set the parameter names
+ 			return getRawParameterNames(paramCount);
+ 		}
+		if (javadocContents != null && javadocContents != BinaryType.EMPTY_JAVADOC) {
+			final int indexOfOpenParen = javadocContents.indexOf('(');
+			if (indexOfOpenParen != -1) {
+				final int indexOfClosingParen = javadocContents.indexOf(')', indexOfOpenParen);
+				if (indexOfClosingParen != -1) {
+					final char[] paramsSource =
+						CharOperation.replace(
+							javadocContents.substring(indexOfOpenParen + 1, indexOfClosingParen).toCharArray(),
+							"&nbsp;".toCharArray(), //$NON-NLS-1$
+							new char[] {' '});
+					final char[][] params = CharOperation.splitOn(',', paramsSource);
+					final int paramsLength = params.length;
+					this.parameterNames = new String[paramsLength];
+					for (int i = 0; i < paramsLength; i++) {
+						final char[] param = params[i];
+						int indexOfSpace = CharOperation.lastIndexOf(' ', param);
+						if (indexOfSpace != -1) {
+							this.parameterNames[i] = String.valueOf(param, indexOfSpace + 1, param.length - indexOfSpace -1);
+						} else {
+							this.parameterNames[i] = "arg" + i; //$NON-NLS-1$
+						}
+					}
+					return this.parameterNames;
+				}
 			}
 		}
 	}
-	return this.parameterNames;
+	// if still no parameter names, produce fake ones
+	return this.parameterNames = getRawParameterNames(paramCount);
 }
 /*
  * @see IMethod
@@ -243,6 +298,19 @@
 	return CharOperation.toStrings(typeParams);
 }
 
+public String[] getRawParameterNames() throws JavaModelException {
+	IBinaryMethod info = (IBinaryMethod) getElementInfo();
+	int paramCount = Signature.getParameterCount(new String(info.getMethodDescriptor()));
+	return getRawParameterNames(paramCount);
+}
+private String[] getRawParameterNames(int paramCount) {
+	String[] result = new String[paramCount];
+	for (int i = 0; i < paramCount; i++) {
+		result[i] = "arg" + i; //$NON-NLS-1$
+	}
+	return result;
+}
+
 /*
  * @see IMethod
  */
@@ -387,4 +455,86 @@
 		buffer.append(this.occurrenceCount);
 	}
 }
+public String getAttachedJavadoc(IProgressMonitor monitor, String defaultEncoding) throws JavaModelException {
+	IType declaringType = this.getDeclaringType();
+
+	String contents = ((BinaryType) declaringType).getJavadocContents(monitor, defaultEncoding);
+	return extractJavadoc(declaringType, contents);
+}
+private String extractJavadoc(IType declaringType, String contents) throws JavaModelException {
+	if (contents == null) return null;
+
+	String typeQualifiedName = null;
+	final boolean declaringTypeIsMember = declaringType.isMember();
+	if (declaringTypeIsMember) {
+		IType currentType = declaringType;
+		StringBuffer buffer = new StringBuffer();
+		while (currentType != null) {
+			buffer.insert(0, currentType.getElementName());
+			currentType = currentType.getDeclaringType();
+			if (currentType != null) {
+				buffer.insert(0, '.');
+			}
+		}
+		typeQualifiedName = new String(buffer.toString());
+	} else {
+		typeQualifiedName = declaringType.getElementName();
+	}
+	String methodName = this.getElementName();
+	if (this.isConstructor()) {
+		methodName = typeQualifiedName;
+	}
+	String anchor = Signature.toString(this.getSignature().replace('/', '.'), methodName, null, true, false, Flags.isVarargs(this.getFlags()));
+	if (declaringTypeIsMember) {
+
+		int depth = 0;
+		final String packageFragmentName = declaringType.getPackageFragment().getElementName();
+		// might need to remove a part of the signature corresponding to the synthetic argument
+		final IJavaProject javaProject = declaringType.getJavaProject();
+		char[][] typeNames = CharOperation.splitOn('.', typeQualifiedName.toCharArray());
+		if (!Flags.isStatic(declaringType.getFlags())) depth++;
+		StringBuffer typeName = new StringBuffer();
+		for (int i = 0, max = typeNames.length; i < max; i++) {
+			if (typeName.length() == 0) {
+				typeName.append(typeNames[i]);
+			} else {
+				typeName.append('.').append(typeNames[i]);
+			}
+			IType resolvedType = javaProject.findType(packageFragmentName, String.valueOf(typeName));
+			if (resolvedType != null && resolvedType.isMember() && !Flags.isStatic(resolvedType.getFlags())) depth++;
+		}
+		if (depth != 0) {
+			int indexOfOpeningParen = anchor.indexOf('(');
+			if (indexOfOpeningParen == -1) return null;
+			int index = indexOfOpeningParen;
+			indexOfOpeningParen++;
+			for (int i = 0; i < depth; i++) {
+				int indexOfComma = anchor.indexOf(',', index);
+				if (indexOfComma != -1) {
+					index = indexOfComma + 2;
+				}
+			}
+			anchor = anchor.substring(0, indexOfOpeningParen) + anchor.substring(index);
+		}
+	}
+	int indexAnchor = contents.indexOf(JavadocConstants.ANCHOR_PREFIX_START + anchor + JavadocConstants.ANCHOR_PREFIX_END);
+	if (indexAnchor == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+	int indexOfEndLink = contents.indexOf(JavadocConstants.ANCHOR_SUFFIX, indexAnchor);
+	if (indexOfEndLink == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+	int indexOfNextMethod = contents.indexOf(JavadocConstants.ANCHOR_PREFIX_START, indexOfEndLink);
+	// find bottom
+	int indexOfBottom = -1;
+	if (this.isConstructor()) {
+		indexOfBottom = contents.indexOf(JavadocConstants.METHOD_DETAIL, indexOfEndLink);
+		if (indexOfBottom == -1) {
+			indexOfBottom = contents.indexOf(JavadocConstants.END_OF_CLASS_DATA, indexOfEndLink);
+		}
+	} else {
+		indexOfBottom = contents.indexOf(JavadocConstants.END_OF_CLASS_DATA, indexOfEndLink);
+	}
+	if (indexOfBottom == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+	indexOfNextMethod = Math.min(indexOfNextMethod, indexOfBottom);
+	if (indexOfNextMethod == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+	return contents.substring(indexOfEndLink + JavadocConstants.ANCHOR_SUFFIX_LENGTH, indexOfNextMethod);
+}
 }
diff --git a/model/org/eclipse/jdt/internal/core/BinaryType.java b/model/org/eclipse/jdt/internal/core/BinaryType.java
index 0a1c08c..a2e65a8 100644
--- a/model/org/eclipse/jdt/internal/core/BinaryType.java
+++ b/model/org/eclipse/jdt/internal/core/BinaryType.java
@@ -11,10 +11,12 @@
 package org.eclipse.jdt.internal.core;
 
 import java.io.InputStream;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
 
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.search.SearchEngine;
@@ -23,6 +25,7 @@
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
 import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
 import org.eclipse.jdt.internal.core.util.Messages;
@@ -41,6 +44,7 @@
 	private static final IType[] NO_TYPES = new IType[0];
 	private static final IInitializer[] NO_INITIALIZERS = new IInitializer[0];
 	private static final String[] NO_STRINGS = new String[0];
+	public static final String EMPTY_JAVADOC = new String();
 	
 protected BinaryType(JavaElement parent, String name) {
 	super(parent, name);
@@ -982,4 +986,84 @@
 	else
 		buffer.append("<anonymous>"); //$NON-NLS-1$
 }
+public String getAttachedJavadoc(IProgressMonitor monitor, String defaultEncoding) throws JavaModelException {
+	final String contents = getJavadocContents(monitor, defaultEncoding);
+	if (contents == null) return null;
+	final int indexOfStartOfClassData = contents.indexOf(JavadocConstants.START_OF_CLASS_DATA);
+	if (indexOfStartOfClassData == -1) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+	int indexOfNextSummary = contents.indexOf(JavadocConstants.NESTED_CLASS_SUMMARY);
+	if (this.isEnum() && indexOfNextSummary == -1) {
+		// try to find enum constant summary start
+		indexOfNextSummary = contents.indexOf(JavadocConstants.ENUM_CONSTANT_SUMMARY);
+	}
+	if (this.isAnnotation() && indexOfNextSummary == -1) {
+		// try to find enum constant summary start
+		indexOfNextSummary = contents.indexOf(JavadocConstants.ANNOTATION_TYPE_MEMBER_SUMMARY);
+	}
+	if (indexOfNextSummary == -1) {
+		// try to find field summary start
+		indexOfNextSummary = contents.indexOf(JavadocConstants.FIELD_SUMMARY);
+	}
+	if (indexOfNextSummary == -1) {
+		// try to find constructor summary start
+		indexOfNextSummary = contents.indexOf(JavadocConstants.CONSTRUCTOR_SUMMARY);
+	}
+	if (indexOfNextSummary == -1) {
+		// try to find method summary start
+		indexOfNextSummary = contents.indexOf(JavadocConstants.METHOD_SUMMARY);
+	}
+	if (indexOfNextSummary == -1) {
+		// we take the end of class data
+		indexOfNextSummary = contents.indexOf(JavadocConstants.END_OF_CLASS_DATA);
+	}
+	if (indexOfNextSummary == -1) {
+		throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, this));
+	}
+	return contents.substring(indexOfStartOfClassData + JavadocConstants.START_OF_CLASS_DATA_LENGTH, indexOfNextSummary);
+}
+public String getJavadocContents(IProgressMonitor monitor, String defaultEncoding) throws JavaModelException {
+	PerProjectInfo projectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.getJavaProject().getProject());
+	String cachedJavadoc = null;
+	synchronized (projectInfo.javadocCache) {
+		cachedJavadoc = (String) projectInfo.javadocCache.get(this);
+	}
+	if (cachedJavadoc != null && cachedJavadoc != EMPTY_JAVADOC) {
+		return cachedJavadoc;
+	}
+	
+	URL baseLocation= getJavadocBaseLocation();
+	if (baseLocation == null) {
+		return null;
+	}
+	StringBuffer pathBuffer = new StringBuffer(baseLocation.toExternalForm());
+
+	if (!(pathBuffer.charAt(pathBuffer.length() - 1) == '/')) {
+		pathBuffer.append('/');
+	}
+	IPackageFragment pack= this.getPackageFragment();
+	String typeQualifiedName = null;
+	if (this.isMember()) {
+		IType currentType = this;
+		StringBuffer typeName = new StringBuffer();
+		while (currentType != null) {
+			typeName.insert(0, currentType.getElementName());
+			currentType = currentType.getDeclaringType();
+			if (currentType != null) {
+				typeName.insert(0, '.');
+			}
+		}
+		typeQualifiedName = new String(typeName.toString());
+	} else {
+		typeQualifiedName = this.getElementName();
+	}
+	
+	pathBuffer.append(pack.getElementName().replace('.', '/')).append('/').append(typeQualifiedName).append(JavadocConstants.HTML_EXTENSION);
+	
+	if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+	final String contents = getURLContents(String.valueOf(pathBuffer), defaultEncoding);
+	synchronized (projectInfo.javadocCache) {
+		projectInfo.javadocCache.put(this, contents);
+	}
+	return contents;
+}
 }
diff --git a/model/org/eclipse/jdt/internal/core/ClassFile.java b/model/org/eclipse/jdt/internal/core/ClassFile.java
index dc3482a..58e3abd 100644
--- a/model/org/eclipse/jdt/internal/core/ClassFile.java
+++ b/model/org/eclipse/jdt/internal/core/ClassFile.java
@@ -24,16 +24,6 @@
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.IBuffer;
-import org.eclipse.jdt.core.IClassFile;
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaModelStatusConstants;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.IParent;
-import org.eclipse.jdt.core.ISourceRange;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
@@ -213,6 +203,9 @@
 	}
 	return elt;
 }
+public String getAttachedJavadoc(IProgressMonitor monitor, String defaultEncoding) throws JavaModelException {
+	return this.getType().getAttachedJavadoc(monitor, defaultEncoding);
+}
 /**
  * Returns the <code>ClassFileReader</code>specific for this IClassFile, based
  * on its underlying resource, or <code>null</code> if unable to create
@@ -569,6 +562,7 @@
 						entryName.append('/');
 					}
 					entryName.append(sourceFileWithoutExtension);
+					entryName.append('.');
 					entryName.append(javaLikeExtensions[i]);
 					ZipEntry zipEntry = jar.getEntry(entryName.toString());
 					if (zipEntry != null) {
diff --git a/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java b/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
index 19b321b..b855659 100644
--- a/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
+++ b/model/org/eclipse/jdt/internal/core/CommitWorkingCopyOperation.java
@@ -70,6 +70,13 @@
 			beginTask(Messages.workingCopy_commit, 2); 
 			CompilationUnit workingCopy = getCompilationUnit();
 			IFile resource = (IFile)workingCopy.getResource();
+			
+			if (resource == null) {
+				// case of a working copy without a resource
+				workingCopy.getBuffer().save(this.progressMonitor, this.force);
+				return;
+			}
+			
 			ICompilationUnit primary = workingCopy.getPrimary();
 			boolean isPrimary = workingCopy.isPrimary();
 
@@ -178,6 +185,7 @@
 	}
 	protected ISchedulingRule getSchedulingRule() {
 		IResource resource = getElementToProcess().getResource();
+		if (resource == null) return null;
 		IWorkspace workspace = resource.getWorkspace();
 		if (resource.exists()) {
 			return workspace.getRuleFactory().modifyRule(resource);
diff --git a/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/model/org/eclipse/jdt/internal/core/CompilationUnit.java
index 205403f..e7030f3 100644
--- a/model/org/eclipse/jdt/internal/core/CompilationUnit.java
+++ b/model/org/eclipse/jdt/internal/core/CompilationUnit.java
@@ -16,7 +16,6 @@
 import org.eclipse.core.runtime.*;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
@@ -47,7 +46,7 @@
  * Constructs a handle to a compilation unit with the given name in the
  * specified package for the specified owner
  */
-protected CompilationUnit(PackageFragment parent, String name, WorkingCopyOwner owner) {
+public CompilationUnit(PackageFragment parent, String name, WorkingCopyOwner owner) {
 	super(parent);
 	this.name = name;
 	this.owner = owner;
@@ -109,14 +108,28 @@
 	CompilationUnitStructureRequestor requestor = new CompilationUnitStructureRequestor(this, unitInfo, newElements);
 	JavaModelManager.PerWorkingCopyInfo perWorkingCopyInfo = getPerWorkingCopyInfo();
 	IJavaProject project = getJavaProject();
-	boolean computeProblems = JavaProject.hasJavaNature(project.getProject()) && perWorkingCopyInfo != null && perWorkingCopyInfo.isActive();
+
+	boolean createAST;
+	boolean resolveBindings;
+	HashMap problems;
+	if (info instanceof ASTHolderCUInfo) {
+		ASTHolderCUInfo astHolder = (ASTHolderCUInfo) info;
+		createAST = astHolder.astLevel != NO_AST;
+		resolveBindings = astHolder.resolveBindings;
+		problems = astHolder.problems;
+	} else {
+		createAST = false;
+		resolveBindings = false;
+		problems = null;
+	}
+	
+	boolean computeProblems = perWorkingCopyInfo != null && perWorkingCopyInfo.isActive() && project != null && JavaProject.hasJavaNature(project.getProject());
 	IProblemFactory problemFactory = new DefaultProblemFactory();
-	Map options = project.getOptions(true);
+	Map options = project == null ? JavaCore.getOptions() : project.getOptions(true);
 	if (!computeProblems) {
 		// disable task tags checking to speed up parsing
 		options.put(JavaCore.COMPILER_TASK_TAGS, ""); //$NON-NLS-1$
 	}
-	boolean createAST = info instanceof ASTHolderCUInfo;
 	SourceElementParser parser = new SourceElementParser(
 		requestor, 
 		problemFactory, 
@@ -124,10 +137,11 @@
 		true/*report local declarations*/,
 		!createAST /*optimize string literals only if not creating a DOM AST*/);
 	parser.reportOnlyOneSyntaxError = !computeProblems;
-	if (!computeProblems && !createAST) // disable javadoc parsing if not computing problems and not creating ast
+	if (!computeProblems && !resolveBindings && !createAST) // disable javadoc parsing if not computing problems, not resolving and not creating ast
 		parser.javadocParser.checkDocComment = false;
 	requestor.parser = parser;
-	CompilationUnitDeclaration unit = parser.parseCompilationUnit(new org.eclipse.jdt.internal.compiler.env.ICompilationUnit() {
+	CompilationUnitDeclaration unit = parser.parseCompilationUnit(
+		new org.eclipse.jdt.internal.compiler.env.ICompilationUnit() {
 			public char[] getContents() {
 				return contents;
 			}
@@ -140,7 +154,8 @@
 			public char[] getFileName() {
 				return CompilationUnit.this.getFileName();
 			}
-		}, true /*full parse to find local elements*/);
+		}, 
+		true /*full parse to find local elements*/);
 	
 	// update timestamp (might be IResource.NULL_STAMP if original does not exist)
 	if (underlyingResource == null) {
@@ -153,10 +168,27 @@
 	// compute other problems if needed
 	CompilationUnitDeclaration compilationUnitDeclaration = null;
 	try {
-		if (computeProblems){
-			perWorkingCopyInfo.beginReporting();
-			compilationUnitDeclaration = CompilationUnitProblemFinder.process(unit, this, contents, parser, this.owner, perWorkingCopyInfo, !createAST/*reset env if not creating AST*/, pm);
-			perWorkingCopyInfo.endReporting();
+		if (computeProblems) {
+			if (problems == null) {
+				// report problems to the problem requestor
+				problems = new HashMap();
+				compilationUnitDeclaration = CompilationUnitProblemFinder.process(unit, this, contents, parser, this.owner, problems, createAST, pm);
+				try {
+					perWorkingCopyInfo.beginReporting();
+					for (Iterator iteraror = problems.values().iterator(); iteraror.hasNext();) {
+						CategorizedProblem[] categorizedProblems = (CategorizedProblem[]) iteraror.next();
+						if (categorizedProblems == null) continue;
+						for (int i = 0, length = categorizedProblems.length; i < length; i++) {
+							perWorkingCopyInfo.acceptProblem(categorizedProblems[i]);
+						}
+					}
+				} finally {
+					perWorkingCopyInfo.endReporting();
+				}
+			} else {
+				// collect problems
+				compilationUnitDeclaration = CompilationUnitProblemFinder.process(unit, this, contents, parser, this.owner, problems, createAST, pm);
+			}
 		}
 		
 		if (createAST) {
@@ -495,8 +527,8 @@
  * @see ICompilationUnit#findPrimaryType()
  */
 public IType findPrimaryType() {
-	String typeName = Signature.getQualifier(this.getElementName());
-	IType primaryType= this.getType(typeName);
+	String typeName = Util.getNameWithoutJavaLikeExtension(getElementName());
+	IType primaryType= getType(typeName);
 	if (primaryType.exists()) {
 		return primaryType;
 	}
@@ -580,8 +612,8 @@
  * @see IJavaElement#getCorrespondingResource()
  */
 public IResource getCorrespondingResource() throws JavaModelException {
-	IPackageFragmentRoot root= (IPackageFragmentRoot)getParent().getParent();
-	if (root.isArchive()) {
+	PackageFragmentRoot root = getPackageFragmentRoot();
+	if (root == null || root.isArchive()) {
 		return null;
 	} else {
 		return getUnderlyingResource();
@@ -730,6 +762,7 @@
  */
 public char[][] getPackageName() {
 	PackageFragment packageFragment = (PackageFragment) getParent();
+	if (packageFragment == null) return CharOperation.NO_CHAR_CHAR;
 	return Util.toCharArrays(packageFragment.names);
 }
 
@@ -737,11 +770,12 @@
  * @see IJavaElement#getPath()
  */
 public IPath getPath() {
-	PackageFragmentRoot root = this.getPackageFragmentRoot();
+	PackageFragmentRoot root = getPackageFragmentRoot();
+	if (root == null) return new Path(getElementName()); // working copy not in workspace
 	if (root.isArchive()) {
 		return root.getPath();
 	} else {
-		return this.getParent().getPath().append(this.getElementName());
+		return getParent().getPath().append(getElementName());
 	}
 }
 /*
@@ -768,11 +802,12 @@
  * @see IJavaElement#getResource()
  */
 public IResource getResource() {
-	PackageFragmentRoot root = this.getPackageFragmentRoot();
+	PackageFragmentRoot root = getPackageFragmentRoot();
+	if (root == null) return null; // working copy not in workspace
 	if (root.isArchive()) {
 		return root.getResource();
 	} else {
-		return ((IContainer)this.getParent().getResource()).getFile(new Path(this.getElementName()));
+		return ((IContainer) getParent().getResource()).getFile(new Path(getElementName()));
 	}
 }
 /**
@@ -876,7 +911,9 @@
 	// timestamp
 	Object info = JavaModelManager.getJavaModelManager().getInfo(this);
 	if (info == null) return false;
-	return ((CompilationUnitElementInfo)info).timestamp != getResource().getModificationStamp();
+	IResource resource = getResource();
+	if (resource == null) return false;
+	return ((CompilationUnitElementInfo)info).timestamp != resource.getModificationStamp();
 }
 /**
  * @see IWorkingCopy#isBasedOn(IResource)
@@ -904,6 +941,7 @@
 }
 protected IStatus validateCompilationUnit(IResource resource) {
 	IPackageFragmentRoot root = getPackageFragmentRoot();
+	// root never null as validation is not done for working copies
 	try {
 		if (root.getKind() != IPackageFragmentRoot.K_SOURCE) 
 			return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, root);
@@ -932,16 +970,18 @@
  * @see IOpenable#makeConsistent(IProgressMonitor)
  */
 public void makeConsistent(IProgressMonitor monitor) throws JavaModelException {
-	makeConsistent(false/*don't create AST*/, 0, monitor);
+	makeConsistent(NO_AST, false/*don't resolve bindings*/, null/*don't collect problems but report them*/, monitor);
 }
-public org.eclipse.jdt.core.dom.CompilationUnit makeConsistent(boolean createAST, int astLevel, IProgressMonitor monitor) throws JavaModelException {
+public org.eclipse.jdt.core.dom.CompilationUnit makeConsistent(int astLevel, boolean resolveBindings, HashMap problems, IProgressMonitor monitor) throws JavaModelException {
 	if (isConsistent()) return null;
 		
 	// create a new info and make it the current info
 	// (this will remove the info and its children just before storing the new infos)
-	if (createAST) {
+	if (astLevel != NO_AST || problems != null) {
 		ASTHolderCUInfo info = new ASTHolderCUInfo();
 		info.astLevel = astLevel;
+		info.resolveBindings = resolveBindings;
+		info.problems = problems;
 		openWhenClosed(info, monitor);
 		org.eclipse.jdt.core.dom.CompilationUnit result = info.ast;
 		info.ast = null;
@@ -1049,24 +1089,12 @@
 	if (workingCopyOwner == null) workingCopyOwner = DefaultWorkingCopyOwner.PRIMARY;
 	
 	
-	boolean createAST = false;
-	switch(astLevel) {
-		case JLS2_INTERNAL :
-		case AST.JLS3 :
-			// client asking for level 2 or level 3 ASTs; these are supported
-			createAST = true;
-			break;
-		default:
-			// client asking for no AST (0) or unknown ast level
-			// either way, request denied
-			createAST = false;
-	}
 	PerformanceStats stats = null;
 	if(ReconcileWorkingCopyOperation.PERF) {
 		stats = PerformanceStats.getStats(JavaModelManager.RECONCILE_PERF, this);
 		stats.startRun(new String(this.getFileName()));
 	}
-	ReconcileWorkingCopyOperation op = new ReconcileWorkingCopyOperation(this, createAST, astLevel, forceProblemDetection, workingCopyOwner);
+	ReconcileWorkingCopyOperation op = new ReconcileWorkingCopyOperation(this, astLevel, forceProblemDetection, workingCopyOwner);
 	op.runOperation(monitor);
 	if(ReconcileWorkingCopyOperation.PERF) {
 		stats.endRun();
diff --git a/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java b/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
index ad0b386..07b4754 100644
--- a/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
+++ b/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
@@ -10,19 +10,16 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.Compiler;
-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.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
@@ -79,9 +76,10 @@
 		IErrorHandlingPolicy policy,
 		Map settings,
 		ICompilerRequestor requestor,
-		IProblemFactory problemFactory) {
+		IProblemFactory problemFactory,
+		boolean parseLiteralExpressionsAsConstants ) {
 
-		super(environment, policy, settings, requestor, problemFactory, true);
+		super(environment, policy, settings, requestor, problemFactory, parseLiteralExpressionsAsConstants );
 	}
 
 	/**
@@ -135,8 +133,8 @@
 		char[] contents,
 		Parser parser,
 		WorkingCopyOwner workingCopyOwner,
-		IProblemRequestor problemRequestor,
-		boolean resetEnvironment,
+		HashMap problems,
+		boolean creatingAST,
 		IProgressMonitor monitor)
 		throws JavaModelException {
 
@@ -152,7 +150,8 @@
 				getHandlingPolicy(),
 				project.getOptions(true),
 				getRequestor(),
-				problemFactory);
+				problemFactory,
+				!creatingAST); // optimize string literal only if not creating a DOM AST
 			if (parser != null) {
 				problemFinder.parser = parser;
 			}
@@ -179,7 +178,21 @@
 					true, // analyze code
 					true); // generate code
 			}
-			reportProblems(unit, problemRequestor, monitor);
+			CompilationResult unitResult = unit.compilationResult;
+			IProblem[] unitProblems = unitResult.getProblems();
+			int length = unitProblems == null ? 0 : unitProblems.length;
+			if (length > 0) {
+				CategorizedProblem[] categorizedProblems = new CategorizedProblem[length];
+				System.arraycopy(unitProblems, 0, categorizedProblems, 0, length);
+				problems.put(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER, categorizedProblems);
+			}
+			unitProblems = unitResult.getTasks();
+			length = unitProblems == null ? 0 : unitProblems.length;
+			if (length > 0) {
+				CategorizedProblem[] categorizedProblems = new CategorizedProblem[length];
+				System.arraycopy(unitProblems, 0, categorizedProblems, 0, length);
+				problems.put(IJavaModelMarker.TASK_MARKER, categorizedProblems);
+			}
 			if (NameLookup.VERBOSE) {
 				System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
 				System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
@@ -197,8 +210,8 @@
 			if (problemFactory != null)
 				problemFactory.monitor = null; // don't hold a reference to this external object
 			// NB: unit.cleanUp() is done by caller
-			if (problemFinder != null && resetEnvironment)
-				problemFinder.lookupEnvironment.reset();			
+			if (problemFinder != null && !creatingAST)
+				problemFinder.lookupEnvironment.reset();		
 		}
 	}
 
@@ -206,25 +219,12 @@
 		ICompilationUnit unitElement, 
 		char[] contents,
 		WorkingCopyOwner workingCopyOwner,
-		IProblemRequestor problemRequestor,
-		boolean resetEnvironment,
+		HashMap problems,
+		boolean creatingAST,
 		IProgressMonitor monitor)
 		throws JavaModelException {
 			
-		return process(null/*no CompilationUnitDeclaration*/, unitElement, contents, null/*use default Parser*/, workingCopyOwner, problemRequestor, resetEnvironment, 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]);				
-		}
+		return process(null/*no CompilationUnitDeclaration*/, unitElement, contents, null/*use default Parser*/, workingCopyOwner, problems, creatingAST, monitor);
 	}
 
 	/* (non-Javadoc)
diff --git a/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java b/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java
index 3df206b..0aee474 100644
--- a/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java
+++ b/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java
@@ -222,7 +222,9 @@
 	    info.newResolvedPath = newResolvedPath;
 	    info.newRawPath = newRawPath;
 	    if (canChangeResources) {
-            this.projectUpdates.remove(project); // remove possibly awaiting one
+	    	synchronized (this) {
+	            this.projectUpdates.remove(project); // remove possibly awaiting one
+			}
 	        info.updateProjectReferencesIfNecessary();
 	        return;
 	    }
diff --git a/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index e4a13ae..2673542 100644
--- a/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -2401,6 +2401,7 @@
 						break;
 					case IResourceDelta.REMOVED :
 						indexManager.remove(Util.relativePath(file.getFullPath(), 1/*remove project segment*/), file.getProject().getFullPath());
+						this.manager.removeFromSecondaryTypesCache(file);
 						break;
 				}
 		}
diff --git a/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java b/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
index f8bc2dc..321b891 100644
--- a/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
+++ b/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
@@ -85,7 +85,13 @@
 		defaultOptionsMap.put(JavaCore.CODEASSIST_ARGUMENT_SUFFIXES, ""); //$NON-NLS-1$
 		defaultOptionsMap.put(JavaCore.CODEASSIST_FORBIDDEN_REFERENCE_CHECK, JavaCore.ENABLED);
 		defaultOptionsMap.put(JavaCore.CODEASSIST_DISCOURAGED_REFERENCE_CHECK, JavaCore.DISABLED);
-		defaultOptionsMap.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH, JavaCore.DISABLED);
+		defaultOptionsMap.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH, JavaCore.ENABLED);
+		
+		// Time out for parameter names
+		defaultOptionsMap.put(JavaCore.TIMEOUT_FOR_PARAMETER_NAME_FROM_ATTACHED_JAVADOC, "50"); //$NON-NLS-1$
+		// TODO (olivier) To remove after M4
+		// deprecated constant
+		defaultOptionsMap.put("org.eclipse.jdt.core.codeAssist.timeoutForParameterNameFromAttachedJavadoc", "50"); //$NON-NLS-1$//$NON-NLS-2$
 		
 		// Store default values to default preferences
 	 	IEclipsePreferences defaultPreferences = new DefaultScope().getNode(JavaCore.PLUGIN_ID);
diff --git a/model/org/eclipse/jdt/internal/core/JavaElement.java b/model/org/eclipse/jdt/internal/core/JavaElement.java
index 2e4d750..4eae7b3 100644
--- a/model/org/eclipse/jdt/internal/core/JavaElement.java
+++ b/model/org/eclipse/jdt/internal/core/JavaElement.java
@@ -10,6 +10,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.io.BufferedInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -29,6 +36,7 @@
  * @see IJavaElement
  */
 public abstract class JavaElement extends PlatformObject implements IJavaElement {
+//	private static final QualifiedName PROJECT_JAVADOC= new QualifiedName(JavaCore.PLUGIN_ID, "project_javadoc_location"); //$NON-NLS-1$
 
 	public static final char JEM_ESCAPE = '\\';
 	public static final char JEM_JAVAPROJECT = '=';
@@ -155,6 +163,7 @@
 	 * Puts the newly created element info in the given map.
 	 */
 	protected abstract void generateInfos(Object info, HashMap newElements, IProgressMonitor pm) throws JavaModelException;
+	
 	/**
 	 * @see IJavaElement
 	 */
@@ -612,4 +621,123 @@
 	protected void toStringName(StringBuffer buffer) {
 		buffer.append(getElementName());
 	}
+	
+	protected URL getJavadocBaseLocation() throws JavaModelException {
+		IPackageFragmentRoot root= (IPackageFragmentRoot) this.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
+		if (root == null) {
+			return null;
+		}
+
+		if (root.getKind() == IPackageFragmentRoot.K_BINARY) {
+			IClasspathEntry entry= root.getRawClasspathEntry();
+			if (entry == null) {
+				return null;
+			}
+			if (entry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
+				entry= getRealClasspathEntry(root.getJavaProject(), entry.getPath(), root.getPath());
+				if (entry == null) {
+					return null;
+				}
+			}
+			return getLibraryJavadocLocation(entry);
+		}
+		return null;
+	}
+	
+	private static IClasspathEntry getRealClasspathEntry(IJavaProject jproject, IPath containerPath, IPath libPath) throws JavaModelException {
+		IClasspathContainer container= JavaCore.getClasspathContainer(containerPath, jproject);
+		if (container != null) {
+			IClasspathEntry[] entries= container.getClasspathEntries();
+			for (int i= 0; i < entries.length; i++) {
+				IClasspathEntry curr= entries[i];
+				IClasspathEntry resolved= JavaCore.getResolvedClasspathEntry(curr);
+				if (resolved != null && libPath.equals(resolved.getPath())) {
+					return curr; // return the real entry
+				}
+			}
+		}
+		return null; // not found
+	}
+	
+	protected static URL getLibraryJavadocLocation(IClasspathEntry entry) throws JavaModelException {
+		switch(entry.getEntryKind()) {
+			case IClasspathEntry.CPE_LIBRARY :
+			case IClasspathEntry.CPE_VARIABLE :
+				break;
+			default :
+				throw new IllegalArgumentException("Entry must be of kind CPE_LIBRARY or CPE_VARIABLE"); //$NON-NLS-1$
+		}
+		
+		IClasspathAttribute[] extraAttributes= entry.getExtraAttributes();
+		for (int i= 0; i < extraAttributes.length; i++) {
+			IClasspathAttribute attrib= extraAttributes[i];
+			if (IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME.equals(attrib.getName())) {
+				String value = attrib.getValue();
+				try {
+					return new URL(value);
+				} catch (MalformedURLException e) {
+					throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, value));
+				}
+			}
+		}
+		return null;
+	}
+	
+	/*
+	 * @see IJavaElement#getAttachedJavadoc(IProgressMonitor, String)
+	 */
+	public String getAttachedJavadoc(IProgressMonitor monitor, String defaultEncoding) throws JavaModelException {
+		return null;
+	}
+	/*
+	 * We don't use getContentEncoding() on the URL connection, because it might leave open streams behind.
+	 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=117890 
+	 * 
+	 */
+	protected String getURLContents(String docUrlValue, String defaultEncoding) throws JavaModelException {
+		InputStream stream = null;
+		try {
+			String encoding = defaultEncoding;
+			try {
+				if (encoding == null) {
+					encoding = this.getJavaProject().getProject().getDefaultCharset();
+				}
+			} catch (CoreException e) {
+				// ignore
+			}
+			// long time = System.currentTimeMillis();
+			URL docUrl = new URL(docUrlValue);
+			URLConnection connection = docUrl.openConnection();
+			// System.out.println("Time spent " + (System.currentTimeMillis() - time) + "ms for opening connection for " + docUrlValue); //$NON-NLS-1$//$NON-NLS-2$
+			// time = System.currentTimeMillis();
+			if ("jar".equals(docUrl.getProtocol())) { //$NON-NLS-1$
+				// if jar protocol is using a cache, some file descriptors are left behind and the resource cannot be deleted
+				connection.setUseCaches(false);
+			}
+			stream = new BufferedInputStream(connection.getInputStream());
+			// System.out.println("Time spent " + (System.currentTimeMillis() - time) + "ms for getting stream for " + docUrlValue); //$NON-NLS-1$//$NON-NLS-2$
+			// time = System.currentTimeMillis();
+			char[] contents = org.eclipse.jdt.internal.compiler.util.Util.getInputStreamAsCharArray(stream, -1, encoding);
+			// System.out.println("Time spent " + (System.currentTimeMillis() - time) + "ms for reading stream for " + docUrlValue); //$NON-NLS-1$//$NON-NLS-2$
+			if (contents != null) {
+				// System.out.println("Size = " + (contents.length / 1024) + "kb");//$NON-NLS-1$//$NON-NLS-2$
+				return String.valueOf(contents);
+			}
+ 		} catch (MalformedURLException e) {
+ 			throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, this));
+		} catch (FileNotFoundException e) {
+			// ignore. see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=120559
+		} catch(IOException e) {
+			throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, this));
+		} finally {
+			if (stream != null) {
+				try {
+					stream.close();
+				} catch (IOException e) {
+					// ignore
+				}
+			}
+		}
+		return null;
+	}
 }
diff --git a/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java b/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
index 815755e..3c1a3fd 100644
--- a/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/JavaElementDeltaBuilder.java
@@ -62,7 +62,7 @@
 	/**
 	 * Change delta
 	 */
-	JavaElementDelta delta;
+	public JavaElementDelta delta = null;
 
 	/**
 	 * List of added elements
@@ -133,6 +133,12 @@
  * unit and its new content.
  */
 public void buildDeltas() {
+	this.delta = new JavaElementDelta(this.javaElement);
+	// if building a delta on a compilation unit or below, 
+	// it's a fine grained delta
+	if (this.javaElement.getElementType() >= IJavaElement.COMPILATION_UNIT) {
+		this.delta.fineGrained();
+	}
 	this.recordNewPositions(this.javaElement, 0);
 	this.findAdditions(this.javaElement, 0);
 	this.findDeletions();
@@ -302,15 +308,7 @@
 	this.oldPositions = new HashMap(20);
 	this.newPositions = new HashMap(20);
 	this.putOldPosition(this.javaElement, new ListItem(null, null));
-	this.putNewPosition(this.javaElement, new ListItem(null, null));
-	this.delta = new JavaElementDelta(javaElement);
-	
-	// if building a delta on a compilation unit or below, 
-	// it's a fine grained delta
-	if (javaElement.getElementType() >= IJavaElement.COMPILATION_UNIT) {
-		this.delta.fineGrained();
-	}
-	
+	this.putNewPosition(this.javaElement, new ListItem(null, null));	
 	this.added = new ArrayList(5);
 	this.removed = new ArrayList(5);
 }
@@ -425,7 +423,7 @@
 public String toString() {
 	StringBuffer buffer = new StringBuffer();
 	buffer.append("Built delta:\n"); //$NON-NLS-1$
-	buffer.append(this.delta.toString());
+	buffer.append(this.delta == null ? "<null>" : this.delta.toString()); //$NON-NLS-1$
 	return buffer.toString();
 }
 /**
diff --git a/model/org/eclipse/jdt/internal/core/JavaModel.java b/model/org/eclipse/jdt/internal/core/JavaModel.java
index cbebfbe..a556127 100644
--- a/model/org/eclipse/jdt/internal/core/JavaModel.java
+++ b/model/org/eclipse/jdt/internal/core/JavaModel.java
@@ -358,6 +358,9 @@
 	if (!path.isAbsolute()) return null; 
 
 	// lookup - outside the container
+	return getTargetAsExternalFile(path, checkResourceExistence);	
+}
+private synchronized static Object getTargetAsExternalFile(IPath path, boolean checkResourceExistence) {
 	File externalFile = new File(path.toOSString());
 	if (!checkResourceExistence) {
 		return externalFile;
@@ -373,7 +376,7 @@
 			return externalFile;
 		}
 	}
-	return null;	
+	return null;
 }
 
 /**
@@ -387,7 +390,7 @@
  * Helper method - returns the file item (ie. which returns true to {@link java.io.File#isFile()},
  * or null if unbound
  */
-public static File getFile(Object target) {
+public static synchronized File getFile(Object target) {
 	if (existingExternalConfirmedFiles.contains(target))
 		return (File) target;
 	if (target instanceof File) {
diff --git a/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index 68e69dd..7953ad2 100644
--- a/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -20,6 +20,8 @@
 
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.content.IContentTypeManager.ContentTypeChangeEvent;
+import org.eclipse.core.runtime.content.IContentTypeManager.IContentTypeChangeListener;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.core.runtime.preferences.DefaultScope;
 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
@@ -27,18 +29,21 @@
 import org.eclipse.core.runtime.preferences.InstanceScope;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.compiler.ICompilationParticipant;
+import org.eclipse.jdt.core.compiler.CompilationParticipant;
 import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
 import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 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.BasicSearchEngine;
+import org.eclipse.jdt.internal.core.search.IRestrictedAccessTypeRequestor;
 import org.eclipse.jdt.internal.core.search.JavaWorkspaceScope;
 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.LRUCache;
 import org.eclipse.jdt.internal.core.util.Messages;
 import org.eclipse.jdt.internal.core.util.Util;
 import org.eclipse.jdt.internal.core.util.WeakHashSet;
@@ -59,7 +64,7 @@
  * The single instance of <code>JavaModelManager</code> is available from
  * the static method <code>JavaModelManager.getJavaModelManager()</code>.
  */
-public class JavaModelManager implements ISaveParticipant { 	
+public class JavaModelManager implements ISaveParticipant, IContentTypeChangeListener { 	
  
 	/**
 	 * Unique handle onto the JavaModel
@@ -127,11 +132,6 @@
 	public static final String COMPILATION_PARTICIPANT_EXTPOINT_ID = "compilationParticipant" ; //$NON-NLS-1$
 	
 	/**
-	 * Value of the content-type for Java source files
-	 */
-	public static final String JAVA_SOURCE_CONTENT_TYPE = JavaCore.PLUGIN_ID+".javaSource" ; //$NON-NLS-1$
-
-	/**
 	 * Special value used for recognizing ongoing initialization and breaking initialization cycles
 	 */
 	public final static IPath VARIABLE_INITIALIZATION_IN_PROGRESS = new Path("Variable Initialization In Progress"); //$NON-NLS-1$
@@ -169,6 +169,9 @@
 	
 	private static final String ENABLE_NEW_FORMATTER = JavaCore.PLUGIN_ID + "/formatter/enable_new" ; //$NON-NLS-1$
 
+	private final static String DIRTY_CACHE = "***dirty***"; //$NON-NLS-1$
+	private final static HashMap NO_SECONDARY_TYPES = new HashMap(0);
+
 	public static boolean PERF_VARIABLE_INITIALIZER = false;
 	public static boolean PERF_CONTAINER_INITIALIZER = false;
 	
@@ -182,6 +185,110 @@
 	static final int PREF_INSTANCE = 0;
 	static final int PREF_DEFAULT = 1;
 
+	static final CompilationParticipant[] NO_PARTICIPANTS = new CompilationParticipant[0];
+	
+	public class CompilationParticipants {
+	
+		/*
+		 * The registered compilation participants
+		 */
+		private CompilationParticipant[] registeredParticipants = null;
+				
+		public CompilationParticipant[] getCompilationParticipants(IJavaProject project) {
+			CompilationParticipant[] participants = getRegisteredParticipants();
+			if (participants == NO_PARTICIPANTS)
+				return null;
+			int length = participants.length;
+			CompilationParticipant[] result = new CompilationParticipant[length];
+			int index = 0;
+			for (int i = 0; i < length; i++) {
+				CompilationParticipant participant = participants[i];
+				if (participant.isActive(project))
+					result[index++] = participant;
+			}
+			if (index == 0)
+				return null;
+			if (index < length)
+				System.arraycopy(result, 0, result = new CompilationParticipant[index], 0, index);
+			return result;
+		}
+		
+		private CompilationParticipant[] getRegisteredParticipants() {
+			if (this.registeredParticipants != null) {
+				return this.registeredParticipants;
+			}
+			IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(JavaCore.PLUGIN_ID, COMPILATION_PARTICIPANT_EXTPOINT_ID);
+			if (extension == null)
+				return this.registeredParticipants = NO_PARTICIPANTS;
+			final HashMap modifyingEnv = new HashMap();
+			final HashMap creatingProblems = new HashMap();
+			final HashMap others = new HashMap();
+			IExtension[] extensions = extension.getExtensions();
+			// for all extensions of this point...
+			for(int i = 0; i < extensions.length; i++) {
+				IConfigurationElement[] configElements = extensions[i].getConfigurationElements();
+				// for all config elements named "compilationParticipant"
+				for(int j = 0; j < configElements.length; j++) {
+					final IConfigurationElement configElement = configElements[j];
+					String elementName =configElement.getName();
+					if (!("compilationParticipant".equals(elementName))) { //$NON-NLS-1$
+						continue;
+					}
+					Platform.run(new ISafeRunnable() {
+						public void handleException(Throwable exception) {
+							Util.log(exception, "Exception occurred while creating compilation participant"); //$NON-NLS-1$
+						}
+						public void run() throws Exception {
+							Object execExt = configElement.createExecutableExtension("class"); //$NON-NLS-1$ 
+							if (execExt instanceof CompilationParticipant) {
+								if ("true".equals(configElement.getAttribute("modifiesEnvironment"))) //$NON-NLS-1$ //$NON-NLS-2$
+									modifyingEnv.put(configElement, execExt);
+								else if ("true".equals(configElement.getAttribute("createsProblems"))) //$NON-NLS-1$ //$NON-NLS-2$
+									creatingProblems.put(configElement, execExt);
+								else
+									others.put(configElement, execExt);
+							}
+						}
+					});
+				}
+			}
+			int size = modifyingEnv.size() + creatingProblems.size() + others.size();
+			if (size == 0)
+				return this.registeredParticipants = NO_PARTICIPANTS;
+			CompilationParticipant[] result = new CompilationParticipant[size];
+			int index = 0;
+			index = sortParticipants(modifyingEnv, result, index);
+			index = sortParticipants(creatingProblems, result, index);
+			index = sortParticipants(others, result, index);
+			return this.registeredParticipants = result;
+		}
+		
+		private int sortParticipants(HashMap group, CompilationParticipant[] participants, int index) {
+			int size = group.size();
+			if (size == 0) return index;
+			Object[] elements = group.keySet().toArray();
+			Util.sort(elements, new Util.Comparer() {
+				public int compare(Object a, Object b) {
+					if (a == b) return 0;
+					String id = ((IConfigurationElement) a).getAttribute("id"); //$NON-NLS-1$
+					if (id == null) return -1;
+					IConfigurationElement[] requiredElements = ((IConfigurationElement) b).getChildren("requires"); //$NON-NLS-1$
+					for (int i = 0, length = requiredElements.length; i < length; i++) {
+						IConfigurationElement required = requiredElements[i];
+						if (id.equals(required.getAttribute("id"))) //$NON-NLS-1$
+							return 1;
+					}
+					return -1;
+				}
+			});
+			for (int i = 0; i < size; i++)
+				participants[index+i] = (CompilationParticipant) group.get(elements[i]);
+			return index + size;
+		}
+	}
+			
+	public final CompilationParticipants compilationParticipants = new CompilationParticipants();
+	
 	/**
 	 * Returns whether the given full path (for a package) conflicts with the output location
 	 * of the given project.
@@ -698,6 +805,7 @@
 	protected WeakHashMap searchScopes = new WeakHashMap();
 
 	public static class PerProjectInfo {
+		private static final int JAVADOC_CACHE_INITIAL_SIZE = 10;
 		
 		public IProject project;
 		public Object savedState;
@@ -709,12 +817,15 @@
 		
 		public IEclipsePreferences preferences;
 		public Hashtable options;
+		public HashMap secondaryTypes;
+		public LRUCache javadocCache;
 		
 		public PerProjectInfo(IProject project) {
 
 			this.triedRead = false;
 			this.savedState = null;
 			this.project = project;
+			this.javadocCache = new LRUCache(JAVADOC_CACHE_INITIAL_SIZE);
 		}
 		
 		public void rememberExternalLibTimestamps() {
@@ -743,6 +854,7 @@
 			this.rawClasspath = newRawClasspath;
 			this.resolvedClasspath = null;
 			this.resolvedPathToRawEntries = null;
+			this.javadocCache = new LRUCache(JAVADOC_CACHE_INITIAL_SIZE);
 		}
 		public String toString() {
 			StringBuffer buffer = new StringBuffer();
@@ -1054,130 +1166,6 @@
 		}
 		return container;			
 	}
-	
-	public class CompilationParticipants {
-		
-		/** Map<ICompilationParticipant, eventMask> registered by plugins */
-		private Map pluginCPs;
-		
-		/** Map<ICompilationParticipant, eventMask> from calls to add() */
-		private Map dynamicCPs = new HashMap();
-		
-		/**
-		 * @see JavaCore#addCompilationParticipant(ICompilationParticipant, int)
-		 */
-		public synchronized void add(ICompilationParticipant icp, int eventMask) {
-			dynamicCPs.put(icp, new Integer(eventMask));
-		}
-
-		/**
-		 * @see JavaCore#removeCompilationParticipant(ICompilationParticipant)
-		 */
-		public synchronized void remove(ICompilationParticipant icp) {
-			dynamicCPs.remove(icp);
-		}
-		
-		/**
-		 * Returns an immutable list containing the subset of registered
-		 * listeners that have requested notification of at least one of
-		 * the events in the flags mask.
-		 * The first time this is called, it loads listeners from plugins,
-		 * which may cause plugins to be loaded.  
-		 * 
-		 * <p>
-		 * The initialization of ICompilationParticipants  is synchronized.  A deadlock may 
-		 * occur if all of the following conditions are true:  
-		 *  
-		 *  <li>A plugin defines <code>ICompilationParticipants</code></li>
-		 *  <li>That plugin's <code>start()</code> method spawns a thread which causes 
-		 *  <code>getCompilationParticipants()</code> to be invoked</li>
-		 *  <li>The <code>start()</code> method blocks waiting for the spawned thread to complete.</li> 
-		 *  
-		 *  Note that a build and reconcile operations will cause <code>getCompilationParticipants()</code> to 
-		 *  be called.
-		 *  
-		 * @param eventMask an ORed combination of values from ICompilationParticipant.
-		 * @param project the java project on which the compilation participant will
-		 * operate
-		 * @return an immutable list of ICompilationParticipant.
-		 */
-		public List getCompilationParticipants(int eventMask, IJavaProject project) {
-			initPlugins();
-			List filteredICPs = new ArrayList();
-			Iterator it;
-			synchronized(this) {
-				it = dynamicCPs.entrySet().iterator();
-				while (it.hasNext()) {
-					Map.Entry cp = (Map.Entry)it.next();
-					if (0 != (((Integer)cp.getValue()).intValue() | eventMask)) {
-						ICompilationParticipant participant = (ICompilationParticipant)cp.getKey();
-						if (participant.doesParticipateInProject(project))
-							filteredICPs.add(participant);
-					}
-				}
-			}
-			it = pluginCPs.entrySet().iterator();
-			while (it.hasNext()) {
-				Map.Entry cp = (Map.Entry)it.next();
-				if (0 != (((Integer)cp.getValue()).intValue() | eventMask)) {
-					ICompilationParticipant participant = (ICompilationParticipant)cp.getKey();
-					if (participant.doesParticipateInProject(project))
-						filteredICPs.add(participant);
-				}
-			}
-			return Collections.unmodifiableList(filteredICPs);
-		}
-		
-		private synchronized void initPlugins() {
-			if (null != pluginCPs) {
-				return;
-			}
-			pluginCPs = new HashMap();
-
-			IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(
-					JavaCore.PLUGIN_ID, COMPILATION_PARTICIPANT_EXTPOINT_ID);
-			if (extension == null) 
-				return;
-			IExtension[] extensions = extension.getExtensions();
-			for(int iExtension = 0; iExtension < extensions.length; iExtension++){
-				// for all extensions of this point...
-				for(int i = 0; i < extensions.length; i++){
-					IConfigurationElement [] configElements = extensions[i].getConfigurationElements();
-					// for all config elements named "compilationParticipant"
-					for(int j = 0; j < configElements.length; j++){
-						String elementName = configElements[j].getName();
-						if (!("compilationParticipant".equals(elementName))) { //$NON-NLS-1$ - name of configElement
-							continue;
-						}
-						String eventMaskStr = configElements[j].getAttribute("eventMask"); //$NON-NLS-1$ - name of attribute
-						try {
-							Integer eventMask;
-							if (null != eventMaskStr) {
-								eventMask = Integer.decode(eventMaskStr);
-							}
-							else {
-								// if mask is unspecified, send it all events
-								eventMask = new Integer(-1); 
-							}
-							Object execExt = configElements[j].createExecutableExtension("class"); //$NON-NLS-1$ - attribute name
-							if (execExt instanceof ICompilationParticipant){
-								pluginCPs.put(execExt, eventMask);
-							}
-						} catch(CoreException e) {
-							// TODO: what is the right way to handle exceptions?
-							e.printStackTrace();
-						}
-					}
-				}
-			}
-		}
-	}
-	
-	private final CompilationParticipants compilationParticipants = new CompilationParticipants();
-	
-	public CompilationParticipants getCompilationParticipants() {
-		return compilationParticipants;
-	}
 
 	public DeltaProcessor getDeltaProcessor() {
 		return this.deltaState.getDeltaProcessor();
@@ -1442,7 +1430,115 @@
 		}
 	    return null; // break cycle
 	}
-	
+
+	/**
+	 * Get all secondary types for a project and store result in per project info cache.
+	 * 
+	 * @param project Project we want get secondary types from
+	 * @return HashMap Table of secondary type names->path for given project
+	 */
+	public HashMap getSecondaryTypes(IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor) throws JavaModelException {
+		if (VERBOSE) {
+			StringBuffer buffer = new StringBuffer("JavaModelManager.getSecondaryTypesPaths("); //$NON-NLS-1$
+			buffer.append(project.getElementName());
+			buffer.append(')');
+			Util.verbose(buffer.toString());
+		}
+
+		// Wait the end of indexing if requested
+		final PerProjectInfo projectInfo = getPerProjectInfoCheckExistence(project.getProject());
+		IndexManager manager = getIndexManager();
+		boolean indexing = manager.awaitingJobsCount() > 0;
+		if (indexing && waitForIndexes) {
+			while (manager.awaitingJobsCount() > 0) {
+				if (monitor != null && monitor.isCanceled()) {
+					if (projectInfo.secondaryTypes == null) return NO_SECONDARY_TYPES;
+					return projectInfo.secondaryTypes;
+				}
+				try {
+					Thread.sleep(10);
+				} catch (InterruptedException e) {
+					if (projectInfo.secondaryTypes == null) return NO_SECONDARY_TYPES;
+					return projectInfo.secondaryTypes;
+				}
+			}
+		}
+
+		// Return cache if not empty and not dirty
+		if (projectInfo.secondaryTypes != null && projectInfo.secondaryTypes.get(DIRTY_CACHE) == null) {
+			return projectInfo.secondaryTypes;
+		}
+		
+		// Return cache if not waiting for indexing
+		if (indexing && !waitForIndexes) {
+			if (projectInfo.secondaryTypes == null) {
+				return NO_SECONDARY_TYPES; // cache is not initialized return empty one
+			}
+			return projectInfo.secondaryTypes; // cache is dirty => return current one...
+		}
+
+		// Init variables for search
+		final HashMap secondaryTypes = new HashMap(3);
+		IRestrictedAccessTypeRequestor nameRequestor = new IRestrictedAccessTypeRequestor() {
+			public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path, AccessRestriction access) {
+				String key = packageName==null ? "" : new String(packageName); //$NON-NLS-1$
+				HashMap types = (HashMap) secondaryTypes.get(key);
+				if (types == null) types = new HashMap(3);
+				types.put(new String(simpleTypeName), path);
+				secondaryTypes.put(key, types);
+			}
+		};
+
+		// Build scope using prereq projects but only source folders
+		IPackageFragmentRoot[] allRoots = project.getAllPackageFragmentRoots();
+		int length = allRoots.length, size = 0;
+		IPackageFragmentRoot[] allSourceFolders = new IPackageFragmentRoot[length];
+		for (int i=0; i<length; i++) {
+			if (allRoots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
+				allSourceFolders[size++] = allRoots[i];
+			}
+		}
+		if (size < length) {
+			System.arraycopy(allSourceFolders, 0, allSourceFolders = new IPackageFragmentRoot[size], 0, size);
+		}
+
+		// Search all secondary types on scope
+		new BasicSearchEngine().searchAllSecondaryTypeNames(allSourceFolders, nameRequestor, monitor);
+		if (VERBOSE) {
+			System.out.print(Thread.currentThread() + "	-> secondary paths: ");  //$NON-NLS-1$
+			System.out.println();
+			Iterator keys = secondaryTypes.keySet().iterator();
+			while (keys.hasNext()) {
+				String qualifiedName = (String) keys.next();
+				Util.verbose("		- "+qualifiedName+'-'+secondaryTypes.get(qualifiedName) ); //$NON-NLS-1$
+			}
+		}
+
+		// Build types from paths
+		Iterator packages = secondaryTypes.keySet().iterator();
+		while (packages.hasNext()) {
+			String packName = (String) packages.next();
+			HashMap types = (HashMap) secondaryTypes.get(packName);
+			Iterator names = types.keySet().iterator();
+			while (names.hasNext()) {
+				String typeName = (String) names.next();
+				String path = (String) types.get(typeName);
+				if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(path)) {
+					IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(path));
+					ICompilationUnit unit = JavaModelManager.createCompilationUnitFrom(file, null);
+					IType type = unit.getType(typeName);
+					types.put(typeName, type); // replace stored path with type itself
+				}
+			}
+		}
+
+		// Store result in per project info cache if still null or dirty (may have been set by another thread...)
+		if (projectInfo.secondaryTypes == null || projectInfo.secondaryTypes.get(DIRTY_CACHE) != null) {
+			projectInfo.secondaryTypes = secondaryTypes;
+		}
+		return projectInfo.secondaryTypes;
+	}
+
 	/**
 	 * Returns the temporary cache for newly opened elements for the current thread.
 	 * Creates it if not already created.
@@ -2300,7 +2396,87 @@
 		// used by tests to simulate a startup
 		MANAGER = new JavaModelManager();
 	}
-	
+
+	/**
+	 * Remove a file from its project secondary types cache.
+	 * 
+	 * @param file File to remove
+	 */
+	public void removeFromSecondaryTypesCache(IFile file) {
+		if (VERBOSE) {
+			StringBuffer buffer = new StringBuffer("JavaModelManager.removeSecondaryTypePaths("); //$NON-NLS-1$
+			buffer.append(file.getName());
+			buffer.append(')');
+			Util.verbose(buffer.toString());
+		}
+		if (file != null) {
+			PerProjectInfo projectInfo = getPerProjectInfo(file.getProject(), false);
+			if (projectInfo != null && projectInfo.secondaryTypes != null) {
+				if (VERBOSE) {
+					Util.verbose("-> remove file from cache of project: "+file.getProject().getName()); //$NON-NLS-1$
+				}
+				Iterator packages = projectInfo.secondaryTypes.keySet().iterator();
+				while (packages.hasNext()) {
+					String packName = (String) packages.next();
+					Object object = projectInfo.secondaryTypes.get(packName);
+					if (object instanceof HashMap) {
+						HashMap types = (HashMap) object;
+						Iterator names = types.keySet().iterator();
+						while (names.hasNext()) {
+							String typeName = (String) names.next();
+							IType type = (IType) types.get(typeName);
+							if (file.equals(type.getResource())) {
+								types.remove(typeName);
+								if (types.size() == 0) {
+									projectInfo.secondaryTypes.remove(packName);
+								}
+								return;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Reset secondary types cache for a project got from given path.
+	 * If secondary types cache already exist, do not reset it now to avoid
+	 * cache desynchronization (this reset is done in indexing thread...).
+	 * Instead flag the cache as dirty to store the fact that current cache
+	 * should be recomputed when indexing will be ended.
+	 * 
+	 * @param path Path of file containing a secondary type
+	 */
+	public void resetSecondaryTypesCache(String path) {
+		if (VERBOSE) {
+			StringBuffer buffer = new StringBuffer("JavaModelManager.resetSecondaryTypePaths("); //$NON-NLS-1$
+			buffer.append(path);
+			buffer.append(')');
+			Util.verbose(buffer.toString());
+		}
+		IWorkspaceRoot wRoot = ResourcesPlugin.getWorkspace().getRoot();
+		IResource resource = wRoot.findMember(path);
+		if (resource != null) {
+			PerProjectInfo projectInfo = getPerProjectInfo(resource.getProject(), false);
+			if (projectInfo != null) {
+				if (VERBOSE) {
+					Util.verbose("-> reset cache for project: "+resource.getProject().getName()); //$NON-NLS-1$
+				}
+				if (projectInfo.secondaryTypes != null) {
+					Object dirty = projectInfo.secondaryTypes.get(DIRTY_CACHE);
+					if (dirty == null) {
+						projectInfo.secondaryTypes.put(DIRTY_CACHE, resource);
+					} else {
+						HashSet resources = (dirty instanceof HashSet) ? (HashSet) dirty : new HashSet(3);
+						resources.add(resource);
+						projectInfo.secondaryTypes.put(DIRTY_CACHE, resource);
+					}
+				}
+			}
+		}
+	}
+
 	/*
 	 * Resets the temporary cache for newly created elements to null.
 	 */
@@ -2641,6 +2817,9 @@
 				}
 			};
 			JavaCore.getPlugin().getPluginPreferences().addPropertyChangeListener(propertyListener);
+			
+			// Listen to content-type changes
+			 Platform.getContentTypeManager().addContentTypeChangeListener(this);
 
 			// retrieve variable values
 			loadVariablesAndContainers();
@@ -2706,6 +2885,9 @@
 		IWorkspace workspace = ResourcesPlugin.getWorkspace();
 		workspace.removeResourceChangeListener(this.deltaState);
 		workspace.removeSaveParticipant(javaCore);
+		
+		// Stop listening to content-type changes
+		Platform.getContentTypeManager().removeContentTypeChangeListener(this);
 	
 		if (this.indexManager != null){ // no more indexing
 			this.indexManager.shutdown();
@@ -2963,4 +3145,9 @@
 		variablePut(variableName, newPath);
 		return true;
 	}
+
+	public void contentTypeChanged(ContentTypeChangeEvent event) {
+		Util.resetJavaLikeExtensions();
+		
+	}
 }
diff --git a/model/org/eclipse/jdt/internal/core/JavaModelOperation.java b/model/org/eclipse/jdt/internal/core/JavaModelOperation.java
index 1bd8cc8..92e3e4b 100644
--- a/model/org/eclipse/jdt/internal/core/JavaModelOperation.java
+++ b/model/org/eclipse/jdt/internal/core/JavaModelOperation.java
@@ -93,7 +93,7 @@
 	/**
 	 * The progress monitor passed into this operation
 	 */
-	protected IProgressMonitor progressMonitor= null;
+	public IProgressMonitor progressMonitor= null;
 	/**
 	 * A flag indicating whether this operation is nested.
 	 */
@@ -398,7 +398,7 @@
 	 * Returns null if no such attribute is found.
 	 */
 	protected Object getAttribute(Object key) {
-		ArrayList stack = this.getCurrentOperationStack();
+		ArrayList stack = getCurrentOperationStack();
 		if (stack.size() == 0) return null;
 		JavaModelOperation topLevelOp = (JavaModelOperation)stack.get(0);
 		if (topLevelOp.attributes == null) {
@@ -420,7 +420,7 @@
 	 * Returns the stack of operations running in the current thread.
 	 * Returns an empty stack if no operations are currently running in this thread. 
 	 */
-	protected ArrayList getCurrentOperationStack() {
+	protected static ArrayList getCurrentOperationStack() {
 		ArrayList stack = (ArrayList)operationStacks.get();
 		if (stack == null) {
 			stack = new ArrayList();
@@ -458,11 +458,7 @@
 	 * Returns the Java Model this operation is operating in.
 	 */
 	public IJavaModel getJavaModel() {
-		if (elementsToProcess == null || elementsToProcess.length == 0) {
-			return getParentElement().getJavaModel();
-		} else {
-			return elementsToProcess[0].getJavaModel();
-		}
+		return JavaModelManager.getJavaModelManager().getJavaModel();
 	}
 	protected IPath[] getNestedFolders(IPackageFragmentRoot root) throws JavaModelException {
 		IPath rootPath = root.getPath();
@@ -557,7 +553,7 @@
 	protected boolean isTopLevelOperation() {
 		ArrayList stack;
 		return 
-			(stack = this.getCurrentOperationStack()).size() > 0
+			(stack = getCurrentOperationStack()).size() > 0
 			&& stack.get(0) == this;
 	}
 	/*
@@ -814,7 +810,7 @@
 	 * Registers the given attribute at the given key with the top level operation.
 	 */
 	protected void setAttribute(Object key, Object attribute) {
-		JavaModelOperation topLevelOp = (JavaModelOperation)this.getCurrentOperationStack().get(0);
+		JavaModelOperation topLevelOp = (JavaModelOperation) getCurrentOperationStack().get(0);
 		if (topLevelOp.attributes == null) {
 			topLevelOp.attributes = new HashMap();
 		}
diff --git a/model/org/eclipse/jdt/internal/core/JavaModelStatus.java b/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
index 5f2895b..ad07343 100644
--- a/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
+++ b/model/org/eclipse/jdt/internal/core/JavaModelStatus.java
@@ -360,6 +360,16 @@
 						path.makeRelative().toString(),
 						string,
 					});
+			case CANNOT_RETRIEVE_ATTACHED_JAVADOC :
+				if (elements != null && elements.length == 1) {
+					return Messages.bind(Messages.status_cannot_retrieve_attached_javadoc, ((JavaElement)elements[0]).toStringWithAncestors()); 
+				}
+				if (this.string != null) {
+					return Messages.bind(Messages.status_cannot_retrieve_attached_javadoc, this.string);
+				}
+				break;
+			case UNKNOWN_JAVADOC_FORMAT :
+				return Messages.bind(Messages.status_unknown_javadoc_format, ((JavaElement)elements[0]).toStringWithAncestors()); 
 			}
 			if (string != null) {
 				return string;
diff --git a/model/org/eclipse/jdt/internal/core/JavaProject.java b/model/org/eclipse/jdt/internal/core/JavaProject.java
index e8dee7a..a982b89 100644
--- a/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -380,8 +380,6 @@
 		info.setChildren(
 			computePackageFragmentRoots(classpath, false, null /*no reverse map*/));		
 	}
-	
-
 
 	/**
 	 * Internal computation of an expanded classpath. It will eliminate duplicates, and produce copies
@@ -1064,7 +1062,10 @@
 				IType type = lookup.findType(
 					qualifiedName,
 					false,
-					NameLookup.ACCEPT_ALL);
+					NameLookup.ACCEPT_ALL,
+					true/* consider secondary types */,
+					false/* do NOT wait for indexes */,
+					null);
 
 				if (type != null) {
 					return type.getParent();
@@ -1151,48 +1152,49 @@
 		}
 		return new IPackageFragmentRoot[] {};
 	}
-	
+
 	/**
 	 * @see IJavaProject#findType(String)
 	 */
 	public IType findType(String fullyQualifiedName) throws JavaModelException {
 		return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
 	}
-	
 	/**
-	 * @see IJavaProject#findType(String, String)
+	 * @see IJavaProject#findType(String, IProgressMonitor)
 	 */
-	public IType findType(String packageName, String typeQualifiedName) throws JavaModelException {
-		return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
+	public IType findType(String fullyQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException {
+		return findType(fullyQualifiedName, DefaultWorkingCopyOwner.PRIMARY, progressMonitor);
 	}
-
-	/**
-	 * @see IJavaProject#findType(String, String, WorkingCopyOwner)
-	 */
-	public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
-		NameLookup lookup = newNameLookup(owner);
-		return lookup.findType(
-			typeQualifiedName, 
-			packageName,
-			false,
-			NameLookup.ACCEPT_ALL);
-	}	
-
 	/**
 	 * @see IJavaProject#findType(String, WorkingCopyOwner)
 	 */
 	public IType findType(String fullyQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
-		
 		NameLookup lookup = newNameLookup(owner);
+		return findType(fullyQualifiedName, lookup, false, null);
+	}
+	/**
+	 * @see IJavaProject#findType(String, WorkingCopyOwner, IProgressMonitor)
+	 */
+	public IType findType(String fullyQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException {
+		NameLookup lookup = newNameLookup(owner);
+		return findType(fullyQualifiedName, lookup, true, progressMonitor);
+	}
+	/*
+	 * Internal findType with instanciated name lookup
+	 */
+	IType findType(String fullyQualifiedName, NameLookup lookup, boolean considerSecondaryTypes, IProgressMonitor progressMonitor) throws JavaModelException {
 		IType type = lookup.findType(
 			fullyQualifiedName,
 			false,
-			NameLookup.ACCEPT_ALL);
+			NameLookup.ACCEPT_ALL,
+			considerSecondaryTypes,
+			true, /* wait for indexes (only if consider secondary types)*/
+			progressMonitor);
 		if (type == null) {
 			// try to find enclosing type
 			int lastDot = fullyQualifiedName.lastIndexOf('.');
 			if (lastDot == -1) return null;
-			type = this.findType(fullyQualifiedName.substring(0, lastDot));
+			type = findType(fullyQualifiedName.substring(0, lastDot), lookup, considerSecondaryTypes, progressMonitor);
 			if (type != null) {
 				type = type.getType(fullyQualifiedName.substring(lastDot+1));
 				if (!type.exists()) {
@@ -1202,6 +1204,56 @@
 		}
 		return type;
 	}
+
+	/**
+	 * @see IJavaProject#findType(String, String)
+	 */
+	public IType findType(String packageName, String typeQualifiedName) throws JavaModelException {
+		return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY);
+	}
+	/**
+	 * @see IJavaProject#findType(String, String, IProgressMonitor)
+	 */
+	public IType findType(String packageName, String typeQualifiedName, IProgressMonitor progressMonitor) throws JavaModelException {
+		return findType(packageName, typeQualifiedName, DefaultWorkingCopyOwner.PRIMARY, progressMonitor);
+	}
+	/**
+	 * @see IJavaProject#findType(String, String, WorkingCopyOwner)
+	 */
+	public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner) throws JavaModelException {
+		NameLookup lookup = newNameLookup(owner);
+		return findType(
+			packageName,
+			typeQualifiedName, 
+			lookup,
+			false, // do not consider secondary types
+			null);
+	}	
+	/**
+	 * @see IJavaProject#findType(String, String, WorkingCopyOwner, IProgressMonitor)
+	 */
+	public IType findType(String packageName, String typeQualifiedName, WorkingCopyOwner owner, IProgressMonitor progressMonitor) throws JavaModelException {
+		NameLookup lookup = newNameLookup(owner);
+		return findType(
+			packageName,
+			typeQualifiedName, 
+			lookup,
+			true, // consider secondary types
+			progressMonitor);
+	}	
+	/*
+	 * Internal findType with instanciated name lookup
+	 */
+	IType findType(String packageName, String typeQualifiedName, NameLookup lookup, boolean considerSecondaryTypes, IProgressMonitor progressMonitor) throws JavaModelException {
+		return lookup.findType(
+			typeQualifiedName, 
+			packageName,
+			false,
+			NameLookup.ACCEPT_ALL,
+			considerSecondaryTypes,
+			true, // wait for indexes (in case we need to consider secondary types)
+			progressMonitor);
+	}	
 	
 	/**
 	 * Remove all markers denoting classpath problems
@@ -2169,20 +2221,23 @@
 			// when a project is imported, we get a first delta for the addition of the .project, but the .classpath is not accessible
 			// so default to using java.io.File
 			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=96258
-			File file  = rscFile.getLocation().toFile();
-			if (file.exists()) {
-				byte[] bytes;
-				try {
-					bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file);
-				} catch (IOException e) {
-					return null;
-				}
-				try {
-					property = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8
-				} catch (UnsupportedEncodingException e) {
-					Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$
-					// fallback to default
-					property = new String(bytes);
+			IPath location = rscFile.getLocation();
+			if (location != null) {
+				File file = location.toFile();
+				if (file.exists()) {
+					byte[] bytes;
+					try {
+						bytes = org.eclipse.jdt.internal.compiler.util.Util.getFileByteContent(file);
+					} catch (IOException e) {
+						return null;
+					}
+					try {
+						property = new String(bytes, org.eclipse.jdt.internal.compiler.util.Util.UTF_8); // .classpath always encoded with UTF-8
+					} catch (UnsupportedEncodingException e) {
+						Util.log(e, "Could not read .classpath with UTF-8 encoding"); //$NON-NLS-1$
+						// fallback to default
+						property = new String(bytes);
+					}
 				}
 			}
 		}
@@ -2846,6 +2901,44 @@
 	}
 
 	/**
+	 * @see IJavaProject#setRawClasspath(IClasspathEntry[],boolean,IProgressMonitor)
+	 */
+	public void setRawClasspath(
+		IClasspathEntry[] entries,
+		boolean canModifyResources,
+		IProgressMonitor monitor)
+		throws JavaModelException {
+
+		setRawClasspath(
+			entries, 
+			SetClasspathOperation.DO_NOT_SET_OUTPUT,
+			monitor, 
+			canModifyResources, 
+			getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
+			true, // needValidation
+			canModifyResources); // save only if modifying resources is allowed
+	}
+
+	/**
+	 * @see IJavaProject#setRawClasspath(IClasspathEntry[],IPath,boolean,IProgressMonitor)
+	 */
+	public void setRawClasspath(
+		IClasspathEntry[] entries,
+		IPath output,
+		boolean canModifyResources,
+		IProgressMonitor monitor)
+		throws JavaModelException {
+
+		setRawClasspath(
+			entries, 
+			output,
+			monitor, 
+			canModifyResources, 
+			getResolvedClasspath(true/*ignoreUnresolvedEntry*/, false/*don't generateMarkerOnError*/, false/*don't returnResolutionInProgress*/),
+			true, // needValidation
+			canModifyResources); // save only if modifying resources is allowed
+	}
+	/**
 	 * @see IJavaProject#setRawClasspath(IClasspathEntry[],IPath,IProgressMonitor)
 	 */
 	public void setRawClasspath(
diff --git a/model/org/eclipse/jdt/internal/core/JavadocConstants.java b/model/org/eclipse/jdt/internal/core/JavadocConstants.java
new file mode 100644
index 0000000..f0735d9
--- /dev/null
+++ b/model/org/eclipse/jdt/internal/core/JavadocConstants.java
@@ -0,0 +1,23 @@
+package org.eclipse.jdt.internal.core;
+
+public interface JavadocConstants {
+
+	String ANCHOR_PREFIX_END = "\""; //$NON-NLS-1$
+	String ANCHOR_PREFIX_START = "<A NAME=\""; //$NON-NLS-1$
+	String ANCHOR_SUFFIX = "</A>"; //$NON-NLS-1$
+	int ANCHOR_SUFFIX_LENGTH = JavadocConstants.ANCHOR_SUFFIX.length();
+	String CONSTRUCTOR_DETAIL = "<!-- ========= CONSTRUCTOR DETAIL ======== -->"; //$NON-NLS-1$
+	String CONSTRUCTOR_SUMMARY = "<!-- ======== CONSTRUCTOR SUMMARY ======== -->"; //$NON-NLS-1$
+	String FIELD_SUMMARY = "<!-- =========== FIELD SUMMARY =========== -->"; //$NON-NLS-1$
+	String ENUM_CONSTANT_SUMMARY = "<!-- =========== ENUM CONSTANT SUMMARY =========== -->"; //$NON-NLS-1$
+	String ANNOTATION_TYPE_MEMBER_SUMMARY = "<!-- =========== ANNOTATION TYPE REQUIRED MEMBER SUMMARY =========== -->"; //$NON-NLS-1$
+	String END_OF_CLASS_DATA = "<!-- ========= END OF CLASS DATA ========= -->"; //$NON-NLS-1$
+	String HTML_EXTENSION = ".html"; //$NON-NLS-1$
+	String INDEX_FILE_NAME = "index.html"; //$NON-NLS-1$
+	String METHOD_DETAIL = "<!-- ============ METHOD DETAIL ========== -->"; //$NON-NLS-1$
+	String METHOD_SUMMARY = "<!-- ========== METHOD SUMMARY =========== -->"; //$NON-NLS-1$
+	String NESTED_CLASS_SUMMARY = "<!-- ======== NESTED CLASS SUMMARY ======== -->"; //$NON-NLS-1$
+	String PACKAGE_FILE_NAME = "package-summary.html"; //$NON-NLS-1$
+	String START_OF_CLASS_DATA = "<!-- ======== START OF CLASS DATA ======== -->"; //$NON-NLS-1$
+	int START_OF_CLASS_DATA_LENGTH = JavadocConstants.START_OF_CLASS_DATA.length();
+}
diff --git a/model/org/eclipse/jdt/internal/core/Member.java b/model/org/eclipse/jdt/internal/core/Member.java
index cb2c6cd..8d9dec0 100644
--- a/model/org/eclipse/jdt/internal/core/Member.java
+++ b/model/org/eclipse/jdt/internal/core/Member.java
@@ -253,7 +253,16 @@
 public ISourceRange getJavadocRange() throws JavaModelException {
 	ISourceRange range= this.getSourceRange();
 	if (range == null) return null;
-	IBuffer buf= this.isBinary() ? this.getClassFile().getBuffer() : this.getCompilationUnit().getBuffer();
+	IBuffer buf= null;
+	if (this.isBinary()) {
+		buf = this.getClassFile().getBuffer();
+	} else {
+		ICompilationUnit compilationUnit = this.getCompilationUnit();
+		if (!compilationUnit.isConsistent()) {
+			return null;
+		}
+		buf = compilationUnit.getBuffer();
+	}
 	final int start= range.getOffset();
 	final int length= range.getLength();
 	if (length > 0 && buf.getChar(start) == '/') {
diff --git a/model/org/eclipse/jdt/internal/core/NameLookup.java b/model/org/eclipse/jdt/internal/core/NameLookup.java
index 27c9342..7e5b1f4 100644
--- a/model/org/eclipse/jdt/internal/core/NameLookup.java
+++ b/model/org/eclipse/jdt/internal/core/NameLookup.java
@@ -15,22 +15,20 @@
 
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.IProgressMonitor;
 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.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.*;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
@@ -113,17 +111,17 @@
 	 * Allows working copies to take precedence over compilation units.
 	 */
 	protected HashMap typesInWorkingCopies;
-	
+
 	public long timeSpentInSeekTypesInSourcePackage = 0;
 	public long timeSpentInSeekTypesInBinaryPackage = 0;
 
 	public NameLookup(IPackageFragmentRoot[] packageFragmentRoots, HashtableOfArrayToObject packageFragments, ICompilationUnit[] workingCopies, Map rootToResolvedEntries) {
 		long start = -1;
 		if (VERBOSE) {
-			System.out.println(Thread.currentThread() + " BUILDING NameLoopkup");  //$NON-NLS-1$
-			System.out.println(Thread.currentThread() + " -> pkg roots size: " + (packageFragmentRoots == null ? 0 : packageFragmentRoots.length));  //$NON-NLS-1$
-			System.out.println(Thread.currentThread() + " -> pkgs size: " + (packageFragments == null ? 0 : packageFragments.size()));  //$NON-NLS-1$
-			System.out.println(Thread.currentThread() + " -> working copy size: " + (workingCopies == null ? 0 : workingCopies.length));  //$NON-NLS-1$
+			Util.verbose(" BUILDING NameLoopkup");  //$NON-NLS-1$
+			Util.verbose(" -> pkg roots size: " + (packageFragmentRoots == null ? 0 : packageFragmentRoots.length));  //$NON-NLS-1$
+			Util.verbose(" -> pkgs size: " + (packageFragments == null ? 0 : packageFragments.size()));  //$NON-NLS-1$
+			Util.verbose(" -> working copy size: " + (workingCopies == null ? 0 : workingCopies.length));  //$NON-NLS-1$
 			start = System.currentTimeMillis();
 		}
 		this.packageFragmentRoots = packageFragmentRoots;
@@ -201,7 +199,7 @@
 		}
 		this.rootToResolvedEntries = rootToResolvedEntries;
         if (VERBOSE) {
-            System.out.println(Thread.currentThread() + " -> spent: " + (start - System.currentTimeMillis()) + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
+            Util.verbose(" -> spent: " + (start - System.currentTimeMillis()) + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
         }
 	}
 
@@ -483,34 +481,87 @@
 		return null;
 	}
 
+	/*
+	 * Find secondary type for a project.
+	 */
+	private IType findSecondaryType(String packageName, String typeName, IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor) {
+		if (VERBOSE) {
+			Util.verbose("NameLookup FIND SECONDARY TYPES:"); //$NON-NLS-1$
+			Util.verbose(" -> pkg name: " + packageName);  //$NON-NLS-1$
+			Util.verbose(" -> type name: " + typeName);  //$NON-NLS-1$
+			Util.verbose(" -> projects: "+project.getElementName()); //$NON-NLS-1$
+		}
+		JavaModelManager manager = JavaModelManager.getJavaModelManager();
+		try {
+			IJavaProject javaProject = project;
+			HashMap secondaryTypePaths = manager.getSecondaryTypes(javaProject, waitForIndexes, monitor);
+			if (secondaryTypePaths.size() > 0) {
+				HashMap types = (HashMap) secondaryTypePaths.get(packageName==null?"":packageName); //$NON-NLS-1$
+				if (types != null && types.size() > 0) {
+					IType type = (IType) types.get(typeName);
+					if (type != null) {
+						if (VERBOSE) {
+							Util.verbose(" -> type: " + type.getElementName());  //$NON-NLS-1$
+						}
+						return type;
+					}
+				}
+			}
+		}
+		catch (JavaModelException jme) {
+			// give up
+		}
+		return null;
+	}
+
 	/**
-	 * 
+	 * Find type considering secondary types but without waiting for indexes.
+	 * It means that secondary types may be not found under certain circumstances...
+	 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=118789"
 	 */
 	public IType findType(String typeName, String packageName, boolean partialMatch, int acceptFlags) {
+		return findType(typeName,
+			packageName,
+			partialMatch,
+			acceptFlags,
+			true/* consider secondary types */,
+			false/* do NOT wait for indexes */,
+			null);
+	}
+
+	/**
+	 * Find type. Considering secondary types and waiting for indexes depends on given corresponding parameters.
+	 */
+	public IType findType(String typeName, String packageName, boolean partialMatch, int acceptFlags, boolean considerSecondaryTypes, boolean waitForIndexes, IProgressMonitor monitor) {
 		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$
 		}
+
+		// Look for concerned package fragments
 		JavaElementRequestor elementRequestor = new JavaElementRequestor();
 		seekPackageFragments(packageName, false, elementRequestor);
 		IPackageFragment[] packages= elementRequestor.getPackageFragments();
 
-		for (int i= 0, length= packages.length; i < length; i++) {
-			IType type= findType(typeName, packages[i], partialMatch, acceptFlags);
-			if (type != null)
+		// Try to find type in package fragments list
+		IType type = null;
+		int length= packages.length;
+		IJavaProject project = null;
+		for (int i= 0; i < length; i++) {
+			type = findType(typeName, packages[i], partialMatch, acceptFlags);
+			if (type != null) {
 				return type;
+			}
+			if (considerSecondaryTypes && project == null) {
+				project = packages[i].getJavaProject();
+			}
 		}
-		return null;
-	}
-	
-	private IType getMemberType(IType type, String name, int dot) {
-		while (dot != -1) {
-			int start = dot+1;
-			dot = name.indexOf('.', start);
-			String typeName = name.substring(start, dot == -1 ? name.length() : dot);
-			type = type.getType(typeName);
+
+		// If type was not found, try to find it as secondary in source folders
+		if (considerSecondaryTypes && project != null) {
+			type = findSecondaryType(packageName, typeName, project, waitForIndexes, monitor);
 		}
 		return type;
 	}
@@ -528,6 +579,37 @@
 	 *	only exact name matches qualify when <code>false</code>
 	 * @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
 	 * 	are desired results. If no flags are specified, all types are returned.
+	 * @param considerSecondaryTypes flag to know whether secondary types has to be considered
+	 * 	during the search
+	 *
+	 * @see #ACCEPT_CLASSES
+	 * @see #ACCEPT_INTERFACES
+	 * @see #ACCEPT_ENUMS
+	 * @see #ACCEPT_ANNOTATIONS
+	 */
+	public IType findType(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, boolean considerSecondaryTypes) {
+		IType type = findType(name, pkg, partialMatch, acceptFlags);
+		if (type == null && considerSecondaryTypes) {
+			type = findSecondaryType(pkg.getElementName(), name, pkg.getJavaProject(), false, null);
+		}
+		return type;
+	}
+
+	/**
+	 * Returns the first type in the given package whose name
+	 * matches the given (unqualified) name, or <code>null</code> if none
+	 * exist. Specifying a <code>null</code> package will result in no matches.
+	 * The domain of the search is bounded by the Java project from which 
+	 * this name lookup was obtained.
+	 * <br>
+	 *	Note that this method does not find secondary types.
+	 * <br>
+	 * @param name the name of the type to find
+	 * @param pkg the package to search
+	 * @param partialMatch partial name matches qualify when <code>true</code>,
+	 *	only exact name matches qualify when <code>false</code>
+	 * @param acceptFlags a bit mask describing if classes, interfaces or both classes and interfaces
+	 * 	are desired results. If no flags are specified, all types are returned.
 	 *
 	 * @see #ACCEPT_CLASSES
 	 * @see #ACCEPT_INTERFACES
@@ -540,68 +622,7 @@
 		// Return first found (ignore duplicates).
 		SingleTypeRequestor typeRequestor = new SingleTypeRequestor();
 		seekTypes(name, pkg, partialMatch, acceptFlags, typeRequestor);
-		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();
-			TypeNameRequestor nameRequestor = new TypeNameRequestor() {
-				public void acceptType(int modifiers, char[] packageName, char[] simpleTypeName, char[][] enclosingTypeNames, String path) {
-					if (enclosingTypeNames == null || enclosingTypeNames.length == 0) { // accept only top level types
-						int kind = modifiers & (ClassFileConstants.AccInterface|ClassFileConstants.AccEnum|ClassFileConstants.AccAnnotation);
-						switch (kind) {
-							case ClassFileConstants.AccAnnotation:
-							case ClassFileConstants.AccAnnotation|ClassFileConstants.AccInterface:
-								if ((acceptFlags & ACCEPT_ANNOTATIONS) != 0) paths.add(path);
-								break;
-							case ClassFileConstants.AccEnum:
-								if ((acceptFlags & ACCEPT_ENUMS) != 0) paths.add(path);
-								break;
-							case ClassFileConstants.AccInterface:
-								if ((acceptFlags & ACCEPT_INTERFACES) != 0) paths.add(path);
-								break;
-							default:
-								if ((acceptFlags & ACCEPT_CLASSES) != 0) paths.add(path);
-								break;
-						}
-					}
-				}
-			};
-
-			int matchMode = partialMatch ? SearchPattern.R_PREFIX_MATCH : SearchPattern.R_EXACT_MATCH;
-			int matchRule = !partialMatch ? matchMode | SearchPattern.R_CASE_SENSITIVE : matchMode;
-			new SearchEngine().searchAllTypeNames(
-				pkg.getElementName().toCharArray(),
-				typeName.toCharArray(),
-				matchRule,
-				IJavaSearchConstants.TYPE,
-				SearchEngine.createJavaSearchScope(new IJavaElement[] {pkg}, false),
-				nameRequestor,
-				IJavaSearchConstants.CANCEL_IF_NOT_READY_TO_SEARCH,
-				null);
-
-			if (!paths.isEmpty()) {
-				IWorkspace workspace = ResourcesPlugin.getWorkspace();
-				for (int i = 0, l = paths.size(); i < l; i++) {
-					String pathname = (String) paths.get(i);
-					if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(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;
+		return typeRequestor.getType();
 	}
 
 	/**
@@ -621,6 +642,9 @@
 	 * @see #ACCEPT_ANNOTATIONS
 	 */
 	public IType findType(String name, boolean partialMatch, int acceptFlags) {
+		return findType(name, partialMatch, acceptFlags, true/*consider secondary types*/, true/*wait for indexes*/, null);
+	}
+	public IType findType(String name, boolean partialMatch, int acceptFlags, boolean considerSecondaryTypes, boolean waitForIndexes, IProgressMonitor monitor) {
 		int index= name.lastIndexOf('.');
 		String className= null, packageName= null;
 		if (index == -1) {
@@ -630,7 +654,17 @@
 			packageName= name.substring(0, index);
 			className= name.substring(index + 1);
 		}
-		return findType(className, packageName, partialMatch, acceptFlags);
+		return findType(className, packageName, partialMatch, acceptFlags, considerSecondaryTypes, waitForIndexes, monitor);
+	}
+
+	private IType getMemberType(IType type, String name, int dot) {
+		while (dot != -1) {
+			int start = dot+1;
+			dot = name.indexOf('.', start);
+			String typeName = name.substring(start, dot == -1 ? name.length() : dot);
+			type = type.getType(typeName);
+		}
+		return type;
 	}
 
 	/**
@@ -681,9 +715,9 @@
 	 */
 	public void seekPackageFragments(String name, boolean partialMatch, IJavaElementRequestor requestor) {
 /*		if (VERBOSE) {
-			System.out.println(Thread.currentThread() + " SEEKING PACKAGE FRAGMENTS");  //$NON-NLS-1$
-			System.out.println(Thread.currentThread() + " -> name: " + name);  //$NON-NLS-1$
-			System.out.println(Thread.currentThread() + " -> partial match:" + partialMatch);  //$NON-NLS-1$
+			Util.verbose(" SEEKING PACKAGE FRAGMENTS");  //$NON-NLS-1$
+			Util.verbose(" -> name: " + name);  //$NON-NLS-1$
+			Util.verbose(" -> partial match:" + partialMatch);  //$NON-NLS-1$
 		}
 */		if (partialMatch) {
 			String[] splittedName = Util.splitOn('.', name, 0, name.length());
@@ -749,10 +783,10 @@
 	 */
 	public void seekTypes(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
 /*		if (VERBOSE) {
-			System.out.println(Thread.currentThread() + " SEEKING TYPES");  //$NON-NLS-1$
-			System.out.println(Thread.currentThread() + " -> name: " + name);  //$NON-NLS-1$
-			System.out.println(Thread.currentThread() + " -> pkg: " + ((JavaElement) pkg).toStringWithAncestors());  //$NON-NLS-1$
-			System.out.println(Thread.currentThread() + " -> partial match:" + partialMatch);  //$NON-NLS-1$
+			Util.verbose(" SEEKING TYPES");  //$NON-NLS-1$
+			Util.verbose(" -> name: " + name);  //$NON-NLS-1$
+			Util.verbose(" -> pkg: " + ((JavaElement) pkg).toStringWithAncestors());  //$NON-NLS-1$
+			Util.verbose(" -> partial match:" + partialMatch);  //$NON-NLS-1$
 		}
 */
 		String matchName= partialMatch ? name.toLowerCase() : name;
@@ -810,37 +844,51 @@
 				return; // the package is not present
 			}
 			int length= classFiles.length;
-	
-			String unqualifiedName= name;
-			int index= name.lastIndexOf('$');
-			if (index != -1) {
-				//the type name of the inner type
-				unqualifiedName= Util.localTypeName(name, index, name.length());
-				// unqualifiedName is empty if the name ends with a '$' sign.
-				// See http://dev.eclipse.org/bugs/show_bug.cgi?id=14642
-			}
-			String matchName= partialMatch ? name.toLowerCase() : name;
-			for (int i= 0; i < length; i++) {
-				if (requestor.isCanceled())
-					return;
-				IClassFile classFile= classFiles[i];
-				String elementName = classFile.getElementName();
-				if (partialMatch) elementName = elementName.toLowerCase();
-	
-				/**
-				 * Must use startWith because matchName will never have the 
-				 * extension ".class" and the elementName always will.
-				 */
-				if (elementName.startsWith(matchName)) {
-					IType type= null;
-					try {
-						type= classFile.getType();
-					} catch (JavaModelException npe) {
-						continue; // the classFile is not present
-					}
-					if (!partialMatch || (type.getElementName().length() > 0 && !Character.isDigit(type.getElementName().charAt(0)))) { //not an anonymous type
-						if (nameMatches(unqualifiedName, type, partialMatch) && acceptType(type, acceptFlags, false/*not a source type*/))
+			if (!partialMatch) {
+				// exact match
+				for (int i= 0; i < length; i++) {
+					if (requestor.isCanceled()) return;
+					ClassFile classFile= (ClassFile) classFiles[i];
+					if (name.equals(classFile.name)) { // ClassFile#name contains the name of the .class file without the .class extension
+						IType type = classFile.getType();
+						if (acceptType(type, acceptFlags, false/*not a source type*/)) {
 							requestor.acceptType(type);
+							break;  // since an exact match was requested, no other matching type can exist
+						}
+					}
+				}
+			} else {
+				String unqualifiedName = name;
+				int index = name.lastIndexOf('$');
+				if (index != -1) {
+					//the type name of the inner type
+					unqualifiedName = Util.localTypeName(name, index, name.length());
+					// unqualifiedName is empty if the name ends with a '$' sign.
+					// See http://dev.eclipse.org/bugs/show_bug.cgi?id=14642
+				}
+				String matchName = name.toLowerCase();
+				for (int i = 0; i < length; i++) {
+					if (requestor.isCanceled())
+						return;
+					IClassFile classFile= classFiles[i];
+					String elementName = classFile.getElementName();
+					elementName = elementName.toLowerCase();
+		
+					/**
+					 * Must use startWith because matchName will never have the 
+					 * extension ".class" and the elementName always will.
+					 */
+					if (elementName.startsWith(matchName)) {
+						IType type= null;
+						try {
+							type = classFile.getType();
+						} catch (JavaModelException npe) {
+							continue; // the classFile is not present
+						}
+						if ((type.getElementName().length() > 0 && !Character.isDigit(type.getElementName().charAt(0)))) { //not an anonymous type
+							if (nameMatches(unqualifiedName, type, true/*partial match*/) && acceptType(type, acceptFlags, false/*not a source type*/))
+								requestor.acceptType(type);
+						}
 					}
 				}
 			}
diff --git a/model/org/eclipse/jdt/internal/core/Openable.java b/model/org/eclipse/jdt/internal/core/Openable.java
index 5aa1ebe..532a393 100644
--- a/model/org/eclipse/jdt/internal/core/Openable.java
+++ b/model/org/eclipse/jdt/internal/core/Openable.java
@@ -15,15 +15,13 @@
 import java.util.Map;
 
 import org.eclipse.core.resources.*;
-import org.eclipse.core.resources.IContainer;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.core.runtime.PerformanceStats;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.internal.codeassist.CompletionEngine;
 import org.eclipse.jdt.internal.codeassist.SelectionEngine;
+import org.eclipse.jdt.internal.core.util.Util;
 
 
 /**
@@ -191,6 +189,11 @@
 	}
 	return super.exists();
 }
+public String findRecommendedLineSeparator() throws JavaModelException {
+	IBuffer buffer = getBuffer();
+	String source = buffer == null ? null : buffer.getContents();
+	return Util.getLineSeparator(source, getJavaProject());
+}
 protected void generateInfos(Object info, HashMap newElements, IProgressMonitor monitor) throws JavaModelException {
 
 	if (JavaModelManager.VERBOSE){
@@ -466,12 +469,7 @@
  * Find enclosing package fragment root if any
  */
 public PackageFragmentRoot getPackageFragmentRoot() {
-	IJavaElement current = this;
-	do {
-		if (current instanceof PackageFragmentRoot) return (PackageFragmentRoot)current;
-		current = current.getParent();
-	} while(current != null);
-	return null;
+	return (PackageFragmentRoot) getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
 }
 
 }
diff --git a/model/org/eclipse/jdt/internal/core/PackageFragment.java b/model/org/eclipse/jdt/internal/core/PackageFragment.java
index f2065fa..0e4fb46 100644
--- a/model/org/eclipse/jdt/internal/core/PackageFragment.java
+++ b/model/org/eclipse/jdt/internal/core/PackageFragment.java
@@ -10,8 +10,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
-import java.util.*;
+import java.net.URL;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Map;
 
 import org.eclipse.core.resources.IContainer;
@@ -20,15 +21,20 @@
 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.*;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaModelStatusConstants;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.IParent;
+import org.eclipse.jdt.core.ISourceManipulation;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.WorkingCopyOwner;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
 import org.eclipse.jdt.internal.core.util.Messages;
 import org.eclipse.jdt.internal.core.util.Util;
@@ -430,4 +436,37 @@
 		}
 	}
 }
+/*
+ * @see IJavaElement#getAttachedJavadoc(IProgressMonitor)
+ */
+public String getAttachedJavadoc(IProgressMonitor monitor, String defaultEncoding) throws JavaModelException {
+	PerProjectInfo projectInfo = JavaModelManager.getJavaModelManager().getPerProjectInfoCheckExistence(this.getJavaProject().getProject());
+	String cachedJavadoc = null;
+	synchronized (projectInfo.javadocCache) {
+		cachedJavadoc = (String) projectInfo.javadocCache.get(this);
+	}
+	if (cachedJavadoc != null) {
+		return cachedJavadoc;
+	}
+	URL baseLocation= getJavadocBaseLocation();
+	if (baseLocation == null) {
+		return null;
+	}
+	StringBuffer pathBuffer = new StringBuffer(baseLocation.toExternalForm());
+
+	if (!(pathBuffer.charAt(pathBuffer.length() - 1) == '/')) {
+		pathBuffer.append('/');
+	}
+	String packPath= this.getElementName().replace('.', '/');
+	pathBuffer.append(packPath).append('/').append(JavadocConstants.PACKAGE_FILE_NAME);
+	
+	if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+	final String contents = getURLContents(String.valueOf(pathBuffer), defaultEncoding);
+	if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
+	if (contents == null) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, this));
+	synchronized (projectInfo.javadocCache) {
+		projectInfo.javadocCache.put(this, contents);
+	}
+	return contents;
+}
 }
diff --git a/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java b/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
index 8f89b67..7e8daa7 100644
--- a/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
+++ b/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
@@ -10,20 +10,21 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 
+import org.eclipse.core.runtime.ISafeRunnable;
 import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
 import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.compiler.CompilationParticipantResult;
-import org.eclipse.jdt.core.compiler.ICompilationParticipant;
-import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.core.compiler.PreReconcileCompilationEvent;
-import org.eclipse.jdt.core.compiler.PreReconcileCompilationResult;
+import org.eclipse.jdt.core.compiler.CategorizedProblem;
+import org.eclipse.jdt.core.compiler.CompilationParticipant;
+import org.eclipse.jdt.core.compiler.ReconcileContext;
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.core.util.Messages;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Reconcile a working copy and signal the changes through a delta.
@@ -31,82 +32,78 @@
 public class ReconcileWorkingCopyOperation extends JavaModelOperation {
 	public static boolean PERF = false;
 	
-	boolean createAST;
-	int astLevel;
+	public int astLevel;
+	public boolean resolveBindings;
+	public HashMap problems;
 	boolean forceProblemDetection;
 	WorkingCopyOwner workingCopyOwner;
-	org.eclipse.jdt.core.dom.CompilationUnit ast;
+	public org.eclipse.jdt.core.dom.CompilationUnit ast;
+	public JavaElementDeltaBuilder deltaBuilder;
 	
-	public ReconcileWorkingCopyOperation(IJavaElement workingCopy, boolean creatAST, int astLevel, boolean forceProblemDetection, WorkingCopyOwner workingCopyOwner) {
+	public ReconcileWorkingCopyOperation(IJavaElement workingCopy, int astLevel, boolean forceProblemDetection, WorkingCopyOwner workingCopyOwner) {
 		super(new IJavaElement[] {workingCopy});
-		this.createAST = creatAST;
 		this.astLevel = astLevel;
 		this.forceProblemDetection = forceProblemDetection;
 		this.workingCopyOwner = workingCopyOwner;
 	}
+	
 	/**
 	 * @exception JavaModelException if setting the source
 	 * 	of the original compilation unit fails
 	 */
 	protected void executeOperation() throws JavaModelException {
-		if (this.progressMonitor != null){
+		if (this.progressMonitor != null) {
 			if (this.progressMonitor.isCanceled()) 
 				throw new OperationCanceledException();
 			this.progressMonitor.beginTask(Messages.element_reconciling, 2); 
 		}
 	
-		notifyCompilationParticipants();
-		
 		CompilationUnit workingCopy = getWorkingCopy();
-		boolean wasConsistent = workingCopy.isConsistent();
-		try {
-			if (!wasConsistent) {
-				// create the delta builder (this remembers the current content of the cu)
-				JavaElementDeltaBuilder deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
-				
-				// update the element infos with the content of the working copy
-				this.ast = workingCopy.makeConsistent(this.createAST, this.astLevel, this.progressMonitor);
-				deltaBuilder.buildDeltas();
-
-				if (progressMonitor != null) progressMonitor.worked(2);
-			
-				// register the deltas
-				JavaElementDelta delta = deltaBuilder.delta;
-				if (delta != null) {
-					delta.changedAST(this.ast);
-					addReconcileDelta(workingCopy, delta);
-				}
-			} else {
-				// force problem detection? - if structure was consistent
-				if (this.forceProblemDetection) {
-					IProblemRequestor problemRequestor = workingCopy.getPerWorkingCopyInfo();
-					boolean computeProblems = JavaProject.hasJavaNature(workingCopy.getJavaProject().getProject()) && problemRequestor != null && problemRequestor.isActive();
-					if (computeProblems) {
-					    CompilationUnitDeclaration unit = null;
-					    try {
-							problemRequestor.beginReporting();
-							char[] contents = workingCopy.getContents();
-							unit = CompilationUnitProblemFinder.process(workingCopy, contents, this.workingCopyOwner, problemRequestor, !this.createAST/*reset env if not creating AST*/, this.progressMonitor);
-							problemRequestor.endReporting();
-							if (progressMonitor != null) progressMonitor.worked(1);
-							if (this.createAST && unit != null) {
-								Map options = workingCopy.getJavaProject().getOptions(true);
-								this.ast = AST.convertCompilationUnit(this.astLevel, unit, contents, options, true/*isResolved*/, workingCopy, this.progressMonitor);
-								JavaElementDelta delta = new JavaElementDelta(workingCopy);
-								delta.changedAST(this.ast);
-								addReconcileDelta(workingCopy, delta);
-								if (progressMonitor != null) progressMonitor.worked(1);
-							}
-					    } finally {
-					        if (unit != null) {
-					            unit.cleanUp();
-					        }
-					    }
+		IProblemRequestor problemRequestor = workingCopy.getPerWorkingCopyInfo();
+		this.resolveBindings |= problemRequestor != null && problemRequestor.isActive();
+		
+		// create the delta builder (this remembers the current content of the cu)
+		this.deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
+		
+		// make working copy consistent if needed and compute AST if needed
+		makeConsistent(workingCopy, problemRequestor);
+		
+		// notify reconcile participants
+		notifyParticipants(workingCopy);
+		
+		// recreate ast if needed
+		if (this.ast == null && (this.astLevel > ICompilationUnit.NO_AST || this.resolveBindings))
+			makeConsistent(workingCopy, problemRequestor);
+	
+		// report problems
+		if (this.problems != null) {
+			try {
+				problemRequestor.beginReporting();
+				for (Iterator iteraror = this.problems.values().iterator(); iteraror.hasNext();) {
+					CategorizedProblem[] categorizedProblems = (CategorizedProblem[]) iteraror.next();
+					if (categorizedProblems == null) continue;
+					for (int i = 0, length = categorizedProblems.length; i < length; i++) {
+						CategorizedProblem problem = categorizedProblems[i];
+						if (JavaModelManager.VERBOSE){
+							System.out.println("PROBLEM FOUND while reconciling : " + problem.getMessage());//$NON-NLS-1$
+						}
+						if (this.progressMonitor != null && this.progressMonitor.isCanceled()) break;
+						problemRequestor.acceptProblem(problem);
 					}
 				}
+			} finally {
+				problemRequestor.endReporting();
+			}
+		}
+		
+		// report delta
+		try {
+			JavaElementDelta delta = this.deltaBuilder.delta;
+			if (delta != null) {
+				addReconcileDelta(workingCopy, delta);
 			}
 		} finally {
-			if (progressMonitor != null) progressMonitor.done();
+			if (this.progressMonitor != null) this.progressMonitor.done();
 		}
 	}
 	/**
@@ -121,6 +118,92 @@
 	public boolean isReadOnly() {
 		return true;
 	}
+	/*
+	 * Makes the given working copy consistent, computes the delta and computes an AST if needed.
+	 * Returns the AST.
+	 */
+	public org.eclipse.jdt.core.dom.CompilationUnit makeConsistent(CompilationUnit workingCopy, IProblemRequestor problemRequestor) throws JavaModelException {
+		if (!workingCopy.isConsistent()) {
+			// make working copy consistent
+			if (this.problems == null) this.problems = new HashMap();
+			this.ast = workingCopy.makeConsistent(this.astLevel, this.resolveBindings, this.problems, this.progressMonitor);
+			this.deltaBuilder.buildDeltas();
+			if (this.ast != null && this.deltaBuilder.delta != null)
+				this.deltaBuilder.delta.changedAST(this.ast);
+			return this.ast;
+		} 
+		if (this.ast != null) return this.ast; // no need to recompute AST if known already
+		if (this.forceProblemDetection && this.resolveBindings) {
+			if (JavaProject.hasJavaNature(workingCopy.getJavaProject().getProject())) {
+				if (this.problems == null) this.problems = new HashMap();
+			    CompilationUnitDeclaration unit = null;
+			    try {
+			    	// find problems
+					char[] contents = workingCopy.getContents();
+					unit = 
+						CompilationUnitProblemFinder.process(
+							workingCopy, 
+							contents, 
+							this.workingCopyOwner, 
+							this.problems, 
+							this.astLevel != ICompilationUnit.NO_AST/*creating AST if level is not NO_AST */, 
+							this.progressMonitor);
+					if (this.progressMonitor != null) this.progressMonitor.worked(1);
+					
+					// create AST if needed
+					if (this.astLevel != ICompilationUnit.NO_AST && unit != null) {
+						Map options = workingCopy.getJavaProject().getOptions(true);
+						this.ast = 
+							AST.convertCompilationUnit(
+								this.astLevel, 
+								unit, 
+								contents, 
+								options, 
+								true/*isResolved*/, 
+								workingCopy, 
+								this.progressMonitor);
+						if (this.ast != null) {
+							this.deltaBuilder.delta = new JavaElementDelta(workingCopy);
+							this.deltaBuilder.delta.changedAST(this.ast);
+						}
+						if (this.progressMonitor != null) this.progressMonitor.worked(1);
+					}
+			    } finally {
+			        if (unit != null) {
+			            unit.cleanUp();
+			        }
+			    }
+			} // else working copy not in a Java project
+			return this.ast;
+		} 
+		return null;
+	}
+	private void notifyParticipants(final CompilationUnit workingCopy) {
+		IJavaProject javaProject = getWorkingCopy().getJavaProject();
+		CompilationParticipant[] participants = JavaModelManager.getJavaModelManager().compilationParticipants.getCompilationParticipants(javaProject);	
+		if (participants == null) return;
+
+		final ReconcileContext context = new ReconcileContext(this, workingCopy);
+		for (int i = 0, length = participants.length; i < length; i++) {
+			final CompilationParticipant participant = participants[i];
+			Platform.run(new ISafeRunnable() {
+				public void handleException(Throwable exception) {
+					if (exception instanceof Error) {
+						throw (Error) exception; // errors are not supposed to be caught
+					} else if (exception instanceof OperationCanceledException)
+						throw (OperationCanceledException) exception;
+					else if (exception instanceof UnsupportedOperationException) {
+						// might want to disable participant as it tried to modify the buffer of the working copy being reconciled
+						Util.log(exception, "Reconcile participant attempted to modify the buffer of the working copy being reconciled"); //$NON-NLS-1$
+					} else
+						Util.log(exception, "Exception occurred in reconcile participant"); //$NON-NLS-1$
+				}
+				public void run() throws Exception {
+					participant.reconcile(context);
+				}
+			});
+		}
+	}
 	protected IJavaModelStatus verify() {
 		IJavaModelStatus status = super.verify();
 		if (!status.isOK()) {
@@ -133,30 +216,5 @@
 		return status;
 	}
 
-	private void notifyCompilationParticipants() {
-		CompilationUnit workingCopy = getWorkingCopy();
-		final IProblemRequestor problemRequestor = workingCopy.getPerWorkingCopyInfo();
-		
-		IJavaProject javaProject = workingCopy.getJavaProject();
-		List l = JavaCore.getCompilationParticipants(ICompilationParticipant.PRE_RECONCILE_EVENT, javaProject);	
 
-		// we want to go through ICompilationParticipant only if there are participants
-		// and the compilation unit is not consistent or we are forcing problem detection
-		if ( ( l != null && l.size() > 0 ) && ( !workingCopy.isConsistent() || forceProblemDetection )) {	
-			PreReconcileCompilationEvent prce = new PreReconcileCompilationEvent( workingCopy, javaProject );
-			Iterator it = l.iterator();
-			while ( it.hasNext() ) {
-				ICompilationParticipant p = (ICompilationParticipant)it.next(); 
-				final CompilationParticipantResult result = p.notify(prce);
-				if (result.getKind() == ICompilationParticipant.PRE_RECONCILE_EVENT) {
-					final PreReconcileCompilationResult postResult = (PreReconcileCompilationResult)result;
-					final IProblem[] problems = postResult.getProblems();	
-					if( problemRequestor != null && problems != null ){
-						for(int i=0, len=problems.length; i<len; i++ )
-							problemRequestor.acceptProblem(problems[i]);
-					}
-				}
-			}
-		}
-	}
 }
diff --git a/model/org/eclipse/jdt/internal/core/SelectionRequestor.java b/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
index 4df9f01..8bfebeb 100644
--- a/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
+++ b/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
@@ -723,7 +723,7 @@
 			false);
 		// iterate type lookup in each package fragment
 		for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) {
-			type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags);
+			type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags, true/*consider secondary types*/);
 			if (type != null) break;	
 		}
 		if (type == null) {
@@ -803,7 +803,7 @@
 			false);
 		// iterate type lookup in each package fragment
 		for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) {
-			type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags);
+			type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags, true/*consider secondary types*/);
 			if (type != null) break;	
 		}
 		if (type == null) {
diff --git a/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java b/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
index 5abd51a..9ae5bfc 100644
--- a/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
+++ b/model/org/eclipse/jdt/internal/core/SetClasspathOperation.java
@@ -22,6 +22,7 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaElementDelta;
@@ -557,6 +558,9 @@
 			updateAffectedProjects(project.getProject().getFullPath());
 		}
 	}
+	protected ISchedulingRule getSchedulingRule() {
+		return null; // no lock taken while setting the classpath
+	}
 	/*
 	 * Returns the source attachment flag for the delta between the 2 give source paths.
 	 * Returns either F_SOURCEATTACHED, F_SOURCEDETACHED, F_SOURCEATTACHED | F_SOURCEDETACHED
diff --git a/model/org/eclipse/jdt/internal/core/SourceMethod.java b/model/org/eclipse/jdt/internal/core/SourceMethod.java
index e337487..16623b7 100644
--- a/model/org/eclipse/jdt/internal/core/SourceMethod.java
+++ b/model/org/eclipse/jdt/internal/core/SourceMethod.java
@@ -11,11 +11,6 @@
 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;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.lookup.Binding;
 import org.eclipse.jdt.internal.core.util.Util;
@@ -170,6 +165,9 @@
 	IJavaElement primaryParent = this.parent.getPrimaryElement(false);
 	return ((IType)primaryParent).getMethod(this.name, this.parameterTypes);
 }
+public String[] getRawParameterNames() throws JavaModelException {
+	return getParameterNames();
+}
 /**
  * @see IMethod
  */
diff --git a/model/org/eclipse/jdt/internal/core/SourceRefElement.java b/model/org/eclipse/jdt/internal/core/SourceRefElement.java
index daff756..824761f 100644
--- a/model/org/eclipse/jdt/internal/core/SourceRefElement.java
+++ b/model/org/eclipse/jdt/internal/core/SourceRefElement.java
@@ -16,13 +16,6 @@
 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.IOpenable;
-import org.eclipse.jdt.core.ISourceRange;
-import org.eclipse.jdt.core.ISourceReference;
-import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jdt.internal.core.util.DOMFinder;
@@ -158,6 +151,12 @@
 	String token = memento.nextToken();
 	return getHandleFromMemento(token, memento, owner);
 }
+/*
+ * @see IMember#getOccurrenceCount()
+ */
+public int getOccurrenceCount() {
+	return this.occurrenceCount;
+}
 /**
  * Return the first instance of IOpenable in the hierarchy of this
  * type (going up the hierarchy from this type);
diff --git a/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java b/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
index 4871dc4..33b2093 100644
--- a/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
@@ -15,22 +15,18 @@
 
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.*;
-import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.internal.compiler.*;
-import org.eclipse.jdt.internal.compiler.ClassFile;
 import org.eclipse.jdt.internal.compiler.Compiler;
-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.*;
-import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
 import org.eclipse.jdt.internal.core.util.Messages;
+import org.eclipse.jdt.internal.core.util.SimpleSet;
 import org.eclipse.jdt.internal.core.util.Util;
 
 import java.io.*;
 import java.util.*;
 
-
 /**
  * The abstract superclass of Java builders.
  * Provides the building and compilation mechanism
@@ -53,21 +49,17 @@
 
 private boolean inCompiler;
 
-/** 
- * this is a Map<IFile, Set<String>> where each String is a fully-qualified name
- * of an extra dependency introduced by a compilation participant.
- */
-private Map extraDependencyMap;
+protected SimpleSet filesDeclaringAnnotation = null;
 
 public static int MAX_AT_ONCE = 1000;
 public final static String[] JAVA_PROBLEM_MARKER_ATTRIBUTE_NAMES = {
-					IMarker.MESSAGE, 
-					IMarker.SEVERITY, 
-					IJavaModelMarker.ID, 
-					IMarker.CHAR_START, 
-					IMarker.CHAR_END, 
-					IMarker.LINE_NUMBER, 
-					IJavaModelMarker.ARGUMENTS};
+	IMarker.MESSAGE, 
+	IMarker.SEVERITY, 
+	IJavaModelMarker.ID, 
+	IMarker.CHAR_START, 
+	IMarker.CHAR_END, 
+	IMarker.LINE_NUMBER, 
+	IJavaModelMarker.ARGUMENTS};
 public final static String[] JAVA_TASK_MARKER_ATTRIBUTE_NAMES = {
 	IMarker.MESSAGE, 
 	IMarker.PRIORITY, 
@@ -82,18 +74,31 @@
 public final static Integer P_NORMAL = new Integer(IMarker.PRIORITY_NORMAL);
 public final static Integer P_LOW = new Integer(IMarker.PRIORITY_LOW);
 
-protected AbstractImageBuilder(JavaBuilder javaBuilder) {
-	this.javaBuilder = javaBuilder;
-	this.newState = new State(javaBuilder);
-
+protected AbstractImageBuilder(JavaBuilder javaBuilder, boolean buildStarting, State newState) {
 	// local copies
+	this.javaBuilder = javaBuilder;
 	this.nameEnvironment = javaBuilder.nameEnvironment;
 	this.sourceLocations = this.nameEnvironment.sourceLocations;
 	this.notifier = javaBuilder.notifier;
 
-	this.compiler = newCompiler();
-	this.workQueue = new WorkQueue();
-	this.problemSourceFiles = new ArrayList(3);
+	if (buildStarting) {
+		this.newState = newState == null ? new State(javaBuilder) : newState;
+		this.compiler = newCompiler();
+		this.workQueue = new WorkQueue();
+		this.problemSourceFiles = new ArrayList(3);
+
+		if (this.javaBuilder.participants != null) {
+			for (int i = 0, l = this.javaBuilder.participants.length; i < l; i++) {
+				if (this.javaBuilder.participants[i].isAnnotationProcessor()) {
+					// initialize this set so the builder knows to gather CUs that define Annotation types
+					// each Annotation processor participant is then asked to process these files AFTER
+					// the compile loop. The normal dependency loop will then recompile all affected types
+					this.filesDeclaringAnnotation = new SimpleSet(1);
+					break;
+				}
+			}
+		}
+	}
 }
 
 public void acceptResult(CompilationResult result) {
@@ -175,6 +180,9 @@
 					createProblemFor(compilationUnit.resource, null, Messages.build_inconsistentClassFile, JavaCore.ERROR); 
 			}
 		}
+		if (result.declaresAnnotations && this.filesDeclaringAnnotation != null) // only initialized if an annotation processor is attached
+			this.filesDeclaringAnnotation.add(compilationUnit);
+
 		finishedWith(typeLocator, result, compilationUnit.getMainTypeName(), definedTypeNames, duplicateTypeNames);
 		notifier.compiled(compilationUnit);
 	}
@@ -196,8 +204,16 @@
 * if they are affected by the changes.
 */
 protected void compile(SourceFile[] units) {
-	int unitsLength = units.length;
+	if (this.filesDeclaringAnnotation != null && this.filesDeclaringAnnotation.elementSize > 0)
+		// will add files that declare annotations in acceptResult() & then processAnnotations() before exitting this method
+		this.filesDeclaringAnnotation.clear();
 
+	// notify CompilationParticipants (that !isAnnotationProcessor()) which source files are about to be compiled
+	CompilationParticipantResult[] participantResults = notifyParticipants(units);
+	if (participantResults != null)
+		units = processParticipantResults(participantResults, units);
+
+	int unitsLength = units.length;
 	this.compiledAllAtOnce = unitsLength <= MAX_AT_ONCE;
 	if (this.compiledAllAtOnce) {
 		// do them all now
@@ -228,230 +244,16 @@
 			System.arraycopy(units, i, additionalUnits, 0, additionalUnits.length);
 			compilingFirstGroup = false;
 			compile(toCompile, additionalUnits);
-		}	
-	}
-}
-
-
-/**
- *  notify the ICompilationParticipants of the pre-build event 
- *  @return a map that maps source units to problems encountered during the prebuild process.
- */
-private  Map notifyCompilationParticipants(ICompilationUnit[] sourceUnits, Set newFiles, Set deletedFiles, Map extraDependencies ) {
-	List cps = JavaCore
-			.getCompilationParticipants( ICompilationParticipant.PRE_BUILD_EVENT,
-					javaBuilder.javaProject );
-	if ( cps.isEmpty() ) {
-		return null;
-	}
-
-	IFile[] files = new IFile[sourceUnits.length];
-	for ( int i = 0; i < files.length; i++ ) {
-		if ( sourceUnits[i] instanceof SourceFile ) {
-			files[i] = ( ( SourceFile ) sourceUnits[i] ).getFile();
-		} else {
-			String fname = new String( sourceUnits[i].getFileName() );
-			files[i] = javaBuilder.javaProject.getProject().getFile( fname );
 		}
 	}
-	PreBuildCompilationEvent pbce = new PreBuildCompilationEvent( files, 
-			javaBuilder.javaProject,
-			!javaBuilder.nameEnvironment.isIncrementalBuild);
 
-	java.util.Iterator it = cps.iterator();
-	Map ifiles2problems = new HashMap();
-	boolean classpathChanged = false;
-	while ( it.hasNext() ) {
-		ICompilationParticipant p = ( ICompilationParticipant ) it.next();
+	if (participantResults != null)
+		for (int i = participantResults.length; --i >= 0;)
+			if (participantResults[i] != null)
+				recordParticipantResult(participantResults[i]);
 
-		CompilationParticipantResult cpr = p.notify( pbce );
-		if ( cpr instanceof PreBuildCompilationResult ) {
-			PreBuildCompilationResult pbcr = ( PreBuildCompilationResult ) cpr;
-
-			IFile[] f = pbcr.getNewFiles();
-			if ( f != null ) {
-				for ( int i = 0; i < f.length; i++ )
-					newFiles.add( f[i] );
-			}
-			
-			f = pbcr.getDeletedFiles();
-			if ( f != null ) { 
-				for ( int i = 0; i < f.length; i++ ) 
-					deletedFiles.add( f[i] );
-			}
-			
-			mergeMaps( pbcr.getNewDependencies(), extraDependencies );
-			mergeMaps( pbcr.getProblems(), ifiles2problems );
-			
-			classpathChanged  |= pbcr.getProjectClasspathChanged();
-		}
-	}
-	
-	if ( newFiles.size() > 0 ) {
-		
-		// if project classpath has changed, then we need to reset the name environments
-		if ( classpathChanged )
-			resetNameEnvironment();
-		
-		Set newFiles_2 = new HashSet();
-		Set deletedFiles_2 = new HashSet();
-		ICompilationUnit[] newFileArray = ifileSet2SourceFileArray( newFiles );
-		final Map newFiles2Problems = notifyCompilationParticipants( newFileArray, newFiles_2, deletedFiles_2, extraDependencies );
-		newFiles.addAll( newFiles_2 );
-		deletedFiles.addAll( deletedFiles_2 );
-		
-		mergeMaps( newFiles2Problems, ifiles2problems);
-	}
-	
-	return convertKey(files, sourceUnits, ifiles2problems);
-}	
-
-/**
- * Convert the key of the map from <code>IFile</code> to the corresponding <code>ICompilationUnit</code>
- * @param files parallel to <code>units</code>. The <code>IFile</code> of the corresponding <code>ICompilationUnit</code> 
- * @param units parallel to <code>files</code>. The <code>ICompilationUnit</code> of the corresponding <code>IFile</code>
- * @param problems Map between <code>IFile</code> and its list of <code>IProblem</code>
- *                        Content of this map will be destructively modified.
- * @return a map between <code>ICompilationUnit</code> and its list of <code>IProblem</code>
- */
-private Map convertKey(final IFile[] files, final ICompilationUnit[] units, Map problems)
-{	
-	for( int i=0, len=files.length; i<len; i++ ){				
-		Object val = problems.remove(files[i]);
-		if( val != null )
-			problems.put(units[i], val);
-	}
-	
-	return problems;
-}
-
-/** 
- *   Given a Map which maps from a key to a value, where key is an arbitrary 
- *   type, and where value is a Collection, mergeMaps will ensure that for a key 
- *   k with value v in source, all of the elements in the Collection v will be 
- *   moved into the Collection v' corresponding to key k in the destination Map. 
- * 
- * @param source - The source map from some key to a Collection.
- * @param destination - The destination map from some key to a Collection
- */
-private static void mergeMaps( Map source, Map destination ) {
-	Iterator keys = source.keySet().iterator();
-	while( keys.hasNext() ) {
-		Object key = keys.next();
-		Object val = destination.get( key );
-		if ( val != null ) {
-			Collection c = (Collection) val;
-			c.addAll( (Collection)source.get( key ) );
-		}
-		else {
-			destination.put( key, source.get( key ) );
-		}
-	}
-}
-
-
-
-/** 
- * given a source file, determine which of the project's source folders the file lives 
- */
-protected ClasspathMultiDirectory getSourceLocationForFile(IFile file) {
-	ClasspathMultiDirectory md = null;
-	md = sourceLocations[0];
-	if ( sourceLocations.length > 1 ) {
-		IPath sourceFileFullPath = file.getFullPath();
-		for ( int j = 0, m = sourceLocations.length; j < m; j++ ) {
-			if ( sourceLocations[j].sourceFolder.getFullPath()
-					.isPrefixOf( sourceFileFullPath ) ) {
-				md = sourceLocations[j];
-				if ( md.exclusionPatterns == null
-						&& md.inclusionPatterns == null )
-					break;
-				if ( !Util.isExcluded( file, md.inclusionPatterns,
-						md.exclusionPatterns ) )
-					break;
-			}
-		}
-	}
-	return md;
-}
-
-/**
- * copies IFile entries in a Set<IFile> into SourceFile entries into a SourceFile[]. 
- * Copying starts at the specified start position.
- */
-private void ifileSet2SourceFileArray( Set ifiles, SourceFile[] sourceFiles, int start ) {
-	Iterator it = ifiles.iterator();
-	while ( it.hasNext() ) {
-		IFile f = ( IFile ) it.next();
-		sourceFiles[start++] = new SourceFile( f, getSourceLocationForFile( f ) );
-	}	
-}
-
-/**
- *  Given a Set<IFile>, this method returns a SourceFile[] where each entry 
- *  in the array corresponds to an entry in the set.
- */
-private SourceFile[] ifileSet2SourceFileArray( Set ifiles ) {
-	SourceFile[] sf = new SourceFile[ ifiles.size() ];
-	ifileSet2SourceFileArray( ifiles, sf, 0 );
-	return sf;
-}
-
-private void resetNameEnvironment() {
-	
-	SimpleLookupTable binaryLocationsPerProject = new SimpleLookupTable(3);
-	NameEnvironment newNameEnvironment = null; 
-	try {
-		newNameEnvironment = new NameEnvironment(this.javaBuilder.workspaceRoot, this.javaBuilder.javaProject, binaryLocationsPerProject);
-	}
-	catch( CoreException ce ) {
-		// TODO:  log exception
-		ce.printStackTrace();
-	}
-	
-	if ( newNameEnvironment != null ) {
-		this.nameEnvironment.cleanup();
-		this.javaBuilder.binaryLocationsPerProject = new SimpleLookupTable(3);
-		this.javaBuilder.nameEnvironment = newNameEnvironment;
-		this.nameEnvironment = this.javaBuilder.nameEnvironment;
-		this.sourceLocations = this.nameEnvironment.sourceLocations;
-		this.compiler = newCompiler();
-	}
-}
-
-private SourceFile[] updateSourceUnits( SourceFile[] units, Set newFiles, Set deletedFiles ) {
-	
-	if ( newFiles.size() == 0 && deletedFiles.size() == 0 )
-		return units;
-	else if ( deletedFiles.size() == 0 ) {
-		// files have only been added
-		SourceFile[] newUnits = new SourceFile[ units.length + newFiles.size() ];
-		System.arraycopy( units, 0, newUnits, 0, units.length );
-		ifileSet2SourceFileArray( newFiles, newUnits, units.length );
-		return newUnits;
-	}
-	else {
-		// files have been added & deleted.  Deal with deleted files first.  If 
-		// someone reports that a file has been added and deleted, then it will be 
-		// added.
-		HashSet unitSet = new HashSet();
-		for ( int i=0; i<units.length; i++ )
-			unitSet.add( units[i].getFile() );
-		Iterator it = deletedFiles.iterator();
-		while ( it.hasNext() )	{
-			IFile f = (IFile) it.next();
-			if ( unitSet.contains( f ) )
-				unitSet.remove( f );
-			handleFileDeletedByCompilationParticipant( f );
-		}
-		unitSet.addAll( newFiles );
-		return ifileSet2SourceFileArray( unitSet );
-	}
-}
-
-protected void handleFileDeletedByCompilationParticipant( IFile f )
-{
-	// noop
+	if (this.filesDeclaringAnnotation != null)
+		processAnnotations();
 }
 
 void compile(SourceFile[] units, SourceFile[] additionalUnits) {
@@ -476,21 +278,7 @@
 	notifier.checkCancel();
 	try {
 		inCompiler = true;
-		
-		// notify compilation participants, 
-		Set newFiles = new HashSet();
-		Set deletedFiles = new HashSet();
-		extraDependencyMap = new HashMap();
-		Map units2Problems = notifyCompilationParticipants( units, newFiles, deletedFiles, extraDependencyMap );
-
-		// update units array with the new & deleted files
-		units = updateSourceUnits( units, newFiles, deletedFiles );
-		
-		compiler.compile(units, units2Problems);
-		
-		// we should be done with this map here, so null it out for GC
-		extraDependencyMap = null;
-		
+		compiler.compile(units);
 	} catch (AbortCompilation ignored) {
 		// ignore the AbortCompilcation coming from BuildNotifier.checkCancelWithinCompiler()
 		// the Compiler failed after the user has chose to cancel... likely due to an OutOfMemory error
@@ -518,71 +306,38 @@
 	}
 }
 
-protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName, ArrayList definedTypeNames, ArrayList duplicateTypeNames) {
-		
-	char[][][] qualifiedRefs = result.qualifiedReferences;
-	char[][] simpleRefs = result.simpleNameReferences;
-	
-	if ( extraDependencyMap != null && extraDependencyMap.size() > 0 ) {
-		IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile( new Path( new String( result.fileName ) ));
-		Set s  = (Set)extraDependencyMap.get( f );
-		if ( s != null && s.size() > 0 ) {
-			NameSet simpleNameSet = new NameSet( simpleRefs.length + s.size() );
-			QualifiedNameSet qualifiedNameSet = new QualifiedNameSet( qualifiedRefs.length + s.size() );
+protected void deleteGeneratedFiles(IFile[] deletedGeneratedFiles) {
+	// no op by default
+}
 
-			//
-			// add in all of the existing refs to the sets to filter out duplicates
-			//
-			for ( int i = 0; i< simpleRefs.length; i++ ) 
-				simpleNameSet.add( simpleRefs[i] );
+protected SourceFile findSourceFile(IFile file) {
+	if (!file.exists()) return null;
 
-			for ( int i = 0; i< qualifiedRefs.length; i++ ) 
-				qualifiedNameSet.add( qualifiedRefs[i] );
-
-			//
-			// get all of the the parts of the new dependencies into sets
-			// for  a dependency "a.b.c.d", we want the qualifiedNameSet to include
-			// "a.b.c.d", "a.b.c" & "a.b" and we want the simple name set to include
-			// "a", "b", "c" & "d".
-			//
-			Iterator it = s.iterator();
-			while ( it.hasNext() ) {
-				char[] array = ((String) it.next() ).toCharArray();
-				char[][] parts = CharOperation.splitOn('.', array );
-				for ( int i = 0; i<parts.length; i++ )
-					simpleNameSet.add( parts[i] );
-				
-				for( int i = parts.length - 1; i > 0; --i ) {
-					qualifiedNameSet.add( parts );
-					parts = CharOperation.subarray( parts, 0, i );
-				}
+	// assumes the file exists in at least one of the source folders & is not excluded
+	ClasspathMultiDirectory md = sourceLocations[0];
+	if (sourceLocations.length > 1) {
+		IPath sourceFileFullPath = file.getFullPath();
+		for (int j = 0, m = sourceLocations.length; j < m; j++) {
+			if (sourceLocations[j].sourceFolder.getFullPath().isPrefixOf(sourceFileFullPath)) {
+				md = sourceLocations[j];
+				if (md.exclusionPatterns == null && md.inclusionPatterns == null)
+					break;
+				if (!Util.isExcluded(file, md.inclusionPatterns, md.exclusionPatterns))
+					break;
 			}
-	
-			//
-			// strip out any null entries in the arrays retrieved from the sets.
-			//
-			simpleRefs = new char[ simpleNameSet.elementSize][];
-			char[][] names = simpleNameSet.names;
-			int j = 0;
-			for ( int i = 0; i<names.length; i++ )
-				if ( names[i] != null)
-					simpleRefs[j++] = names[i];
-			
-			qualifiedRefs = new char[ qualifiedNameSet.elementSize ][][];
-			j = 0;
-			char[][][] qnames = qualifiedNameSet.qualifiedNames;
-			for ( int i = 0; i< qnames.length; i++ )
-				if ( qnames[i] != null )
-					qualifiedRefs[j++] = qnames[i];
-			
 		}
 	}
-		
+	return new SourceFile(file, md);
+}
+
+protected void finishedWith(String sourceLocator, CompilationResult result, char[] mainTypeName, ArrayList definedTypeNames, ArrayList duplicateTypeNames) {
 	if (duplicateTypeNames == null) {
-		newState.record(sourceLocator, qualifiedRefs, simpleRefs, mainTypeName, definedTypeNames);
+		newState.record(sourceLocator, result.qualifiedReferences, result.simpleNameReferences, mainTypeName, definedTypeNames);
 		return;
 	}
-	
+
+	char[][][] qualifiedRefs = result.qualifiedReferences;
+	char[][] simpleRefs = result.simpleNameReferences;
 	// for each duplicate type p1.p2.A, add the type name A (package was already added)
 	next : for (int i = 0, l = duplicateTypeNames.size(); i < l; i++) {
 		char[][] compoundName = (char[][]) duplicateTypeNames.get(i);
@@ -615,6 +370,18 @@
 	return imageBuilderException;
 }
 
+protected boolean isExcludedFromProject(IPath childPath) throws JavaModelException {
+	// answer whether the folder should be ignored when walking the project as a source folder
+	if (childPath.segmentCount() > 2) return false; // is a subfolder of a package
+
+	for (int j = 0, k = sourceLocations.length; j < k; j++) {
+		if (childPath.equals(sourceLocations[j].binaryFolder.getFullPath())) return true;
+		if (childPath.equals(sourceLocations[j].sourceFolder.getFullPath())) return true;
+	}
+	// skip default output folder which may not be used by any source folder
+	return childPath.equals(javaBuilder.javaProject.getOutputLocation());
+}
+
 protected Compiler newCompiler() {
 	// disable entire javadoc support if not interested in diagnostics
 	Map projectOptions = javaBuilder.javaProject.getOptions(true);
@@ -655,16 +422,97 @@
 	return newCompiler;
 }
 
-protected boolean isExcludedFromProject(IPath childPath) throws JavaModelException {
-	// answer whether the folder should be ignored when walking the project as a source folder
-	if (childPath.segmentCount() > 2) return false; // is a subfolder of a package
-
-	for (int j = 0, k = sourceLocations.length; j < k; j++) {
-		if (childPath.equals(sourceLocations[j].binaryFolder.getFullPath())) return true;
-		if (childPath.equals(sourceLocations[j].sourceFolder.getFullPath())) return true;
+protected CompilationParticipantResult[] notifyParticipants(SourceFile[] unitsAboutToCompile) {
+	// TODO (kent) do we expect to have more than one participant?
+	// and if so should we pass the generated files from the each processor to the others to process?
+	CompilationParticipantResult[] results = null;
+	for (int i = 0, l = this.javaBuilder.participants == null ? 0 : this.javaBuilder.participants.length; i < l; i++) {
+		if (!this.javaBuilder.participants[i].isAnnotationProcessor()) {
+			if (results == null) {
+				results = new CompilationParticipantResult[unitsAboutToCompile.length];
+				for (int j = unitsAboutToCompile.length; --j >= 0;)
+					results[j] = new CompilationParticipantResult(unitsAboutToCompile[j]);
+			}
+			this.javaBuilder.participants[i].buildStarting(results);
+		}
 	}
-	// skip default output folder which may not be used by any source folder
-	return childPath.equals(javaBuilder.javaProject.getOutputLocation());
+	return results;
+}
+
+protected abstract void processAnnotationResults(CompilationParticipantResult[] results);
+
+protected void processAnnotations() {
+	int size = this.filesDeclaringAnnotation.elementSize;
+	if (size == 0) return;
+
+	Object[] values = this.filesDeclaringAnnotation.values;
+	CompilationParticipantResult[] results = new CompilationParticipantResult[size];
+	for (int i = values.length; --i >= 0 && size > 0;)
+		if (values[i] != null)
+			results[--size] = new CompilationParticipantResult((SourceFile) values[i]);
+
+ 	// TODO (kent) do we expect to have more than one annotation processor participant?
+	// and if so should we pass the generated files from the each processor to the others to process?
+	for (int i = 0, l = this.javaBuilder.participants.length; i < l; i++)
+		if (this.javaBuilder.participants[i].isAnnotationProcessor())
+			this.javaBuilder.participants[i].processAnnotations(results, this instanceof BatchImageBuilder);
+	processAnnotationResults(results);
+}
+
+protected SourceFile[] processParticipantResults(CompilationParticipantResult[] results, SourceFile[] unitsAboutToCompile) {
+	SimpleSet newUnits = null;
+	for (int i = results.length; --i >= 0;) {
+		CompilationParticipantResult result = results[i];
+		if (result == null) continue;
+
+		IFile[] deletedGeneratedFiles = result.deletedFiles;
+		if (deletedGeneratedFiles != null)
+			deleteGeneratedFiles(deletedGeneratedFiles);
+
+		IFile[] addedGeneratedFiles = result.addedFiles;
+		if (addedGeneratedFiles != null) {
+			for (int j = addedGeneratedFiles.length; --j >= 0;) {
+				SourceFile sourceFile = findSourceFile(addedGeneratedFiles[j]);
+				if (sourceFile == null) continue;
+				if (newUnits == null)
+					newUnits = new SimpleSet(unitsAboutToCompile.length + 3);
+				if (!newUnits.includes(sourceFile))
+					newUnits.add(sourceFile);
+			}
+		}
+	}
+	if (newUnits == null)
+		return unitsAboutToCompile;
+
+	for (int i = unitsAboutToCompile.length; --i >= 0;)
+		newUnits.add(unitsAboutToCompile[i]);
+	SourceFile[] result = new SourceFile[newUnits.elementSize];
+	newUnits.asArray(result);
+	return result;
+}
+
+protected void recordParticipantResult(CompilationParticipantResult result) {
+	// any added/changed/deleted generated files have already been taken care
+	// just record the problems and dependencies - do not expect there to be many
+	// must be called after we're finished with the compilation unit results but before incremental loop adds affected files
+	IProblem[] problems = result.problems;
+	if (problems != null && problems.length > 0) {
+		// existing problems have already been removed so just add these as new problems
+		this.notifier.updateProblemCounts(problems);
+		try {
+			storeProblemsFor(result.sourceFile, problems);
+		} catch (CoreException e) {
+			// must continue with compile loop so just log the CoreException
+			e.printStackTrace();
+		}
+	}
+
+	String[] dependencies = result.dependencies;
+	if (dependencies != null) {
+		ReferenceCollection refs = (ReferenceCollection) this.newState.references.get(result.sourceFile.typeLocator());
+		if (refs != null)
+			refs.addDependencies(dependencies);
+	}
 }
 
 /**
@@ -703,7 +551,8 @@
 					new Integer(problem.getSourceEnd() + 1),
 					new Integer(problem.getSourceLineNumber()),
 					Util.getProblemArgumentsForMarker(problem.getArguments())
-				});
+				}
+			);
 		}
 
 /* Do NOT want to populate the Java Model just to find the matching Java element.
diff --git a/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java b/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
index e82f24c..2c81cd9 100644
--- a/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
@@ -14,8 +14,6 @@
 import org.eclipse.core.runtime.*;
 
 import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.compiler.ICompilationParticipant;
-import org.eclipse.jdt.core.compiler.CleanCompilationEvent;
 import org.eclipse.jdt.internal.core.util.Messages;
 import org.eclipse.jdt.internal.core.util.Util;
 
@@ -23,8 +21,8 @@
 
 public class BatchImageBuilder extends AbstractImageBuilder {
 
-protected BatchImageBuilder(JavaBuilder javaBuilder) {
-	super(javaBuilder);
+protected BatchImageBuilder(JavaBuilder javaBuilder, boolean buildStarting) {
+	super(javaBuilder, buildStarting, null);
 	this.nameEnvironment.isIncrementalBuild = false;
 }
 
@@ -100,30 +98,14 @@
 	}
 }
 
-private void notifyCompilationParticipantsOfClean()
-{
-	List cps = JavaCore.getCompilationParticipants( 
-			ICompilationParticipant.CLEAN_EVENT, javaBuilder.javaProject );
-		
-	if ( cps.isEmpty() ) 
-		return;
-
-	CleanCompilationEvent pbce = new CleanCompilationEvent(	javaBuilder.javaProject );
-
-	java.util.Iterator it = cps.iterator();
-	while ( it.hasNext() ) {
-		ICompilationParticipant p = ( ICompilationParticipant ) it.next();
-		p.notify( pbce );
-	}
-}
-	
 protected void cleanOutputFolders(boolean copyBack) throws CoreException {
 	boolean deleteAll = JavaCore.CLEAN.equals(
 		javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER, true));
 	if (deleteAll) {
-		
-		notifyCompilationParticipantsOfClean();
-		
+		if (this.javaBuilder.participants != null)
+			for (int i = 0, l = this.javaBuilder.participants.length; i < l; i++)
+				this.javaBuilder.participants[i].cleanStarting(this.javaBuilder.javaProject);
+
 		ArrayList visited = new ArrayList(sourceLocations.length);
 		for (int i = 0, l = sourceLocations.length; i < l; i++) {
 			notifier.subTask(Messages.build_cleaningOutput); 
@@ -306,6 +288,36 @@
 	return null;
 }
 
+protected void processAnnotationResults(CompilationParticipantResult[] results) {
+	// called AFTER the build loop once all source files have been compiled
+
+	// to compile the compilation participant results, we need to incrementally recompile all affected types
+	// whenever the generated types are initially added or structurally changed
+
+	// this is a copy of the incremental build loop
+	IncrementalImageBuilder incrementalBuilder = new IncrementalImageBuilder(this);
+	try {
+		incrementalBuilder.resetCollections();
+		incrementalBuilder.processAnnotationResults(results);
+		incrementalBuilder.addAffectedSourceFiles(); // pick up any affected source files of the deleted generated files
+
+		while (incrementalBuilder.sourceFiles.size() > 0) {
+			SourceFile[] allSourceFiles = new SourceFile[incrementalBuilder.sourceFiles.size()];
+			incrementalBuilder.sourceFiles.toArray(allSourceFiles);
+			incrementalBuilder.resetCollections();
+
+			incrementalBuilder.workQueue.addAll(allSourceFiles);
+			incrementalBuilder.compile(allSourceFiles);
+			incrementalBuilder.removeSecondaryTypes();
+			incrementalBuilder.addAffectedSourceFiles();
+		}
+	} catch (CoreException e) {
+		throw internalException(e);
+	} finally {
+		incrementalBuilder.cleanUp();
+	}
+}
+
 public String toString() {
 	return "batch image builder for:\n\tnew state: " + newState; //$NON-NLS-1$
 }
diff --git a/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java b/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
index 24d54a9..f338b0f 100644
--- a/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
+++ b/model/org/eclipse/jdt/internal/core/builder/ClasspathDirectory.java
@@ -10,20 +10,23 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.builder;
 
+import java.io.IOException;
+
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
 
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.core.util.Util;
 
 public class ClasspathDirectory extends ClasspathLocation {
 
 IContainer binaryFolder; // includes .class files for a single directory
 boolean isOutputFolder;
-String binaryLocation;
 SimpleLookupTable directoryCache;
 String[] missingPackageHolder = new String[1];
 AccessRuleSet accessRuleSet;
@@ -31,8 +34,6 @@
 ClasspathDirectory(IContainer binaryFolder, boolean isOutputFolder, AccessRuleSet accessRuleSet) {
 	this.binaryFolder = binaryFolder;
 	this.isOutputFolder = isOutputFolder;
-	IPath location = binaryFolder.getLocation();
-	this.binaryLocation = location != null ? location.addTrailingSeparator().toString() : ""; //$NON-NLS-1$
 	this.directoryCache = new SimpleLookupTable(5);
 	this.accessRuleSet = accessRuleSet;
 }
@@ -94,34 +95,21 @@
 public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String qualifiedBinaryFileName) {
 	if (!doesFileExist(binaryFileName, qualifiedPackageName, qualifiedBinaryFileName)) return null; // most common case
 
+	ClassFileReader reader = null;
 	try {
-		ClassFileReader reader = ClassFileReader.read(binaryLocation + qualifiedBinaryFileName);
-		if (reader != null) {
-			if (this.accessRuleSet == null)
-				return new NameEnvironmentAnswer(reader, null);
-			String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
-			return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()));
-		}
-	} 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) {
-							if (this.accessRuleSet == null)
-								return new NameEnvironmentAnswer(reader, null);
-							String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
-							return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()));
-						}
-					} catch (Exception ignored) { // treat as if class file is missing
-					}
-				}
-			}
-		}
+		reader = Util.newClassFileReader(this.binaryFolder.getFile(new Path(qualifiedBinaryFileName)));
+	} catch (CoreException e) {
+		return null;
+	} catch (ClassFormatException e) {
+		return null;
+	} catch (IOException e) {
+		return null;
+	}
+	if (reader != null) {
+		if (this.accessRuleSet == null)
+			return new NameEnvironmentAnswer(reader, null);
+		String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
+		return new NameEnvironmentAnswer(reader, this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()));
 	}
 	return null;
 }
@@ -154,7 +142,7 @@
 }
 
 public String debugPathString() {
-	return this.binaryLocation;
+	return this.binaryFolder.getFullPath().toString();
 }
 
 
diff --git a/model/org/eclipse/jdt/internal/core/builder/CompilationParticipantResult.java b/model/org/eclipse/jdt/internal/core/builder/CompilationParticipantResult.java
new file mode 100644
index 0000000..6450835
--- /dev/null
+++ b/model/org/eclipse/jdt/internal/core/builder/CompilationParticipantResult.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM - rewrote spec
+ *    
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.core.builder;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jdt.core.compiler.*;
+
+public class CompilationParticipantResult implements ICompilationParticipantResult {
+	SourceFile sourceFile;
+	IFile[] addedFiles; // added/changed generated source files that need to be compiled
+	IFile[] deletedFiles; // previously generated source files that should be deleted
+	IProblem[] problems; // new problems to report against this compilationUnit
+	String[] dependencies; // fully-qualified type names of any new dependencies, each name is of the form 'p1.p2.A.B'
+
+CompilationParticipantResult(SourceFile sourceFile) {
+	this.sourceFile = sourceFile;
+	this.addedFiles = null;
+	this.deletedFiles = null;
+	this.problems = null;
+	this.dependencies = null;
+}
+
+public char[] getContents() {
+	return this.sourceFile.getContents();
+}
+
+public IFile getFile() {
+	return this.sourceFile.resource;
+}
+
+public void recordAddedGeneratedFiles(IFile[] addedGeneratedFiles) {
+	int length2 = addedGeneratedFiles.length;
+	if (length2 == 0) return;
+
+	int length1 = this.addedFiles == null ? 0 : this.addedFiles.length;
+	IFile[] merged = new IFile[length1 + length2];
+	if (length1 > 0) // always make a copy even if currently empty
+		System.arraycopy(this.addedFiles, 0, merged, 0, length1);
+	System.arraycopy(addedGeneratedFiles, 0, merged, length1, length2);
+	this.addedFiles = merged;
+}
+
+public void recordDeletedGeneratedFiles(IFile[] deletedGeneratedFiles) {
+	int length2 = deletedGeneratedFiles.length;
+	if (length2 == 0) return;
+
+	int length1 = this.deletedFiles == null ? 0 : this.deletedFiles.length;
+	IFile[] merged = new IFile[length1 + length2];
+	if (length1 > 0) // always make a copy even if currently empty
+		System.arraycopy(this.deletedFiles, 0, merged, 0, length1);
+	System.arraycopy(deletedGeneratedFiles, 0, merged, length1, length2);
+	this.deletedFiles = merged;
+}
+
+public void recordDependencies(String[] typeNameDependencies) {
+	int length2 = typeNameDependencies.length;
+	if (length2 == 0) return;
+
+	int length1 = this.dependencies == null ? 0 : this.dependencies.length;
+	String[] merged = new String[length1 + length2];
+	if (length1 > 0) // always make a copy even if currently empty
+		System.arraycopy(this.dependencies, 0, merged, 0, length1);
+	System.arraycopy(typeNameDependencies, 0, merged, length1, length2);
+	this.dependencies = merged;
+}
+
+public void recordNewProblems(IProblem[] newProblems) {
+	int length2 = newProblems.length;
+	if (length2 == 0) return;
+
+	int length1 = this.problems == null ? 0 : this.problems.length;
+	IProblem[] merged = new IProblem[length1 + length2];
+	if (length1 > 0) // always make a copy even if currently empty
+		System.arraycopy(this.problems, 0, merged, 0, length1);
+	System.arraycopy(problems, 0, merged, length1, length2);
+	this.problems = merged;
+}
+
+public String toString() {
+	return this.sourceFile.toString();
+}
+}
diff --git a/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java b/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
index 2c695b2..df37e59 100644
--- a/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
@@ -14,7 +14,6 @@
 import org.eclipse.core.runtime.*;
 
 import org.eclipse.jdt.core.compiler.*;
-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.compiler.problem.*;
@@ -24,6 +23,7 @@
 import org.eclipse.jdt.internal.core.util.Util;
 
 import java.io.*;
+import java.net.URI;
 import java.util.*;
 
 /**
@@ -42,16 +42,14 @@
 public static int MaxCompileLoop = 5; // perform a full build if it takes more than ? incremental compile loops
 
 protected IncrementalImageBuilder(JavaBuilder javaBuilder) {
-	super(javaBuilder);
+	super(javaBuilder, true, null);
 	this.nameEnvironment.isIncrementalBuild = true;
 	this.newState.copyFrom(javaBuilder.lastState);
+}
 
-	this.sourceFiles = new ArrayList(33);
-	this.previousSourceFiles = null;
-	this.qualifiedStrings = new StringSet(3);
-	this.simpleStrings = new StringSet(3);
-	this.hasStructuralChanges = false;
-	this.compileLoop = 0;
+protected IncrementalImageBuilder(BatchImageBuilder batchBuilder) {
+	super(batchBuilder.javaBuilder, true, batchBuilder.newState);
+	this.nameEnvironment.isIncrementalBuild = true;
 }
 
 public boolean build(SimpleLookupTable deltas) {
@@ -151,29 +149,15 @@
 		if (refs != null && refs.includes(qualifiedNames, simpleNames)) {
 			String typeLocator = (String) keyTable[i];
 			IFile file = javaBuilder.currentProject.getFile(typeLocator);
-			if (file.exists()) {
-				ClasspathMultiDirectory md = sourceLocations[0];
-				if (sourceLocations.length > 1) {
-					IPath sourceFileFullPath = file.getFullPath();
-					for (int j = 0, m = sourceLocations.length; j < m; j++) {
-						if (sourceLocations[j].sourceFolder.getFullPath().isPrefixOf(sourceFileFullPath)) {
-							md = sourceLocations[j];
-							if (md.exclusionPatterns == null && md.inclusionPatterns == null)
-								break;
-							if (!Util.isExcluded(file, md.inclusionPatterns, md.exclusionPatterns))
-								break;
-						}
-					}
-				}
-				SourceFile sourceFile = new SourceFile(file, md);
-				if (sourceFiles.contains(sourceFile)) continue next;
-				if (compiledAllAtOnce && previousSourceFiles != null && previousSourceFiles.contains(sourceFile))
-					continue next; // can skip previously compiled files since already saw hierarchy related problems
+			SourceFile sourceFile = findSourceFile(file);
+			if (sourceFile == null) continue next;
+			if (sourceFiles.contains(sourceFile)) continue next;
+			if (compiledAllAtOnce && previousSourceFiles != null && previousSourceFiles.contains(sourceFile))
+				continue next; // can skip previously compiled files since already saw hierarchy related problems
 
-				if (JavaBuilder.DEBUG)
-					System.out.println("  adding affected source file " + typeLocator); //$NON-NLS-1$
-				sourceFiles.add(sourceFile);
-			}
+			if (JavaBuilder.DEBUG)
+				System.out.println("  adding affected source file " + typeLocator); //$NON-NLS-1$
+			sourceFiles.add(sourceFile);
 		}
 	}
 }
@@ -208,6 +192,34 @@
 	this.compileLoop = 0;
 }
 
+protected void deleteGeneratedFiles(IFile[] deletedGeneratedFiles) {
+	// delete generated files and recompile any affected source files
+	try {
+		for (int j = deletedGeneratedFiles.length; --j >= 0;) {
+			SourceFile sourceFile = findSourceFile(deletedGeneratedFiles[j]);
+			if (sourceFile == null) continue;
+			String typeLocator = sourceFile.typeLocator();
+			int mdSegmentCount = sourceFile.sourceLocation.sourceFolder.getFullPath().segmentCount();
+			IPath typePath = sourceFile.resource.getFullPath().removeFirstSegments(mdSegmentCount).removeFileExtension();
+			char[][] definedTypeNames = newState.getDefinedTypeNamesFor(typeLocator);
+			if (definedTypeNames == null) { // defined a single type matching typePath
+				removeClassFile(typePath, sourceFile.sourceLocation.binaryFolder);
+			} else {
+				addDependentsOf(typePath, true); // add dependents of the source file since it may be involved in a name collision
+				if (definedTypeNames.length > 0) { // skip it if it failed to successfully define a type
+					IPath packagePath = typePath.removeLastSegments(1);
+					for (int d = 0, l = definedTypeNames.length; d < l; d++)
+						removeClassFile(packagePath.append(new String(definedTypeNames[d])), sourceFile.sourceLocation.binaryFolder);
+				}
+			}
+			this.newState.removeLocator(typeLocator);
+		}
+	} catch (CoreException e) {
+		// must continue with compile loop so just log the CoreException
+		e.printStackTrace();
+	}
+}
+
 protected boolean findAffectedSourceFiles(IResourceDelta delta, ClasspathLocation[] classFoldersAndJars, IProject prereqProject) {
 	for (int i = 0, l = classFoldersAndJars.length; i < l; i++) {
 		ClasspathLocation bLocation = classFoldersAndJars[i];
@@ -242,51 +254,6 @@
 	return true;
 }
 
-protected void handleFileDeletedByCompilationParticipant( IFile f )
-{
-	try
-	{
-	ClasspathMultiDirectory md = getSourceLocationForFile( f );
-	int segmentCount = md.sourceFolder.getFullPath().segmentCount();
-	IPath typePath = f.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
-	String typeLocator = f.getProjectRelativePath().toString();
-	char[][] definedTypeNames = newState.getDefinedTypeNamesFor(typeLocator);
-	if (definedTypeNames == null) { // defined a single type matching typePath
-		removeClassFile(typePath, md.binaryFolder);
-		/*
-		if ((sourceDelta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
-			// remove problems and tasks for a compilation unit that is being moved (to another package or renamed)
-			// if the target file is a compilation unit, the new cu will be recompiled
-			// if the target file is a non-java resource, then markers are removed
-			// see bug 2857
-			IResource movedFile = javaBuilder.workspaceRoot.getFile(sourceDelta.getMovedToPath());
-			JavaBuilder.removeProblemsAndTasksFor(movedFile); 
-		}
-		*/
-	} else {
-		if (JavaBuilder.DEBUG)
-			System.out.println("Found removed source file " + typePath.toString()); //$NON-NLS-1$
-		addDependentsOf(typePath, true); // add dependents of the source file since it may be involved in a name collision
-		if (definedTypeNames.length > 0) { // skip it if it failed to successfully define a type
-			IPath packagePath = typePath.removeLastSegments(1);
-			for (int i = 0, l = definedTypeNames.length; i < l; i++)
-				removeClassFile(packagePath.append(new String(definedTypeNames[i])), md.binaryFolder);
-		}
-	}
-	newState.removeLocator(typeLocator);
-	}
-	catch ( CoreException ce )
-	{
-		// TODO:  handle this exception
-		ce.printStackTrace();
-	}
-	catch( Exception e )
-	{
-		e.printStackTrace();
-	}
-}
-
-
 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
@@ -577,6 +544,28 @@
 	super.finishedWith(sourceLocator, result, mainTypeName, definedTypeNames, duplicateTypeNames);
 }
 
+protected void processAnnotationResults(CompilationParticipantResult[] results) {
+	for (int i = results.length; --i >= 0;) {
+		CompilationParticipantResult result = results[i];
+		if (result == null) continue;
+
+		IFile[] deletedGeneratedFiles = result.deletedFiles;
+		if (deletedGeneratedFiles != null)
+			deleteGeneratedFiles(deletedGeneratedFiles);
+
+		IFile[] addedGeneratedFiles = result.addedFiles;
+		if (addedGeneratedFiles != null) {
+			for (int j = addedGeneratedFiles.length; --j >= 0;) {
+				SourceFile sourceFile = findSourceFile(addedGeneratedFiles[j]);
+				if (sourceFile != null && !sourceFiles.contains(sourceFile))
+					this.sourceFiles.add(sourceFile);
+			}
+		}
+
+		recordParticipantResult(result);
+	}
+}
+
 protected void removeClassFile(IPath typePath, IContainer outputFolder) throws CoreException {
 	if (typePath.lastSegment().indexOf('$') == -1) { // is not a nested type
 		newState.removeQualifiedTypeName(typePath.toString());
@@ -612,12 +601,21 @@
 }
 
 protected void resetCollections() {
-	previousSourceFiles = sourceFiles.isEmpty() ? null : (ArrayList) sourceFiles.clone();
+	if (this.sourceFiles == null) {
+		this.sourceFiles = new ArrayList(33);
+		this.previousSourceFiles = null;
+		this.qualifiedStrings = new StringSet(3);
+		this.simpleStrings = new StringSet(3);
+		this.hasStructuralChanges = false;
+		this.compileLoop = 0;
+	} else {
+		this.previousSourceFiles = this.sourceFiles.isEmpty() ? null : (ArrayList) this.sourceFiles.clone();
 
-	sourceFiles.clear();
-	qualifiedStrings.clear();
-	simpleStrings.clear();
-	workQueue.clear();
+		this.sourceFiles.clear();
+		this.qualifiedStrings.clear();
+		this.simpleStrings.clear();
+		this.workQueue.clear();
+	}
 }
 
 protected void updateProblemsFor(SourceFile sourceFile, CompilationResult result) throws CoreException {
@@ -677,9 +675,10 @@
 				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
-		ClassFileReader reader = new ClassFileReader(oldBytes, location.toString().toCharArray());
+		URI uri = file.getLocationURI();
+		if (uri == null) return false; // unable to determine location of this class file
+		String filePath = uri.getPath();
+		ClassFileReader reader = new ClassFileReader(oldBytes, filePath.toCharArray());
 		// ignore local types since they're only visible inside a single method
 		if (!(reader.isLocal() || reader.isAnonymous()) && reader.hasStructuralChanges(newBytes)) {
 			if (JavaBuilder.DEBUG)
diff --git a/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java b/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
index e595666..3e7d8e6 100644
--- a/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
@@ -14,9 +14,7 @@
 import org.eclipse.core.runtime.*;
 
 import org.eclipse.jdt.core.*;
-import org.eclipse.jdt.core.compiler.BrokenClasspathBuildFailureEvent;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.compiler.ICompilationParticipant;
+import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.*;
 import org.eclipse.jdt.internal.core.util.Messages;
@@ -30,6 +28,7 @@
 IProject currentProject;
 JavaProject javaProject;
 IWorkspaceRoot workspaceRoot;
+CompilationParticipant[] participants;
 NameEnvironment nameEnvironment;
 SimpleLookupTable binaryLocationsPerProject; // maps a project to its binary resources (output folders, class folders, zip/jar files)
 State lastState;
@@ -131,7 +130,7 @@
 	boolean ok = false;
 	try {
 		notifier.checkCancel();
-		initializeBuilder();
+		kind = initializeBuilder(kind, true);
 
 		if (isWorthBuilding()) {
 			if (kind == FULL_BUILD) {
@@ -211,7 +210,7 @@
 	if (DEBUG && lastState != null)
 		System.out.println("Clearing last state : " + lastState); //$NON-NLS-1$
 	clearLastState();
-	BatchImageBuilder imageBuilder = new BatchImageBuilder(this);
+	BatchImageBuilder imageBuilder = new BatchImageBuilder(this, true);
 	imageBuilder.build();
 	recordNewState(imageBuilder.newState);
 }
@@ -241,12 +240,12 @@
 	try {
 		notifier.checkCancel();
 
-		initializeBuilder();
+		initializeBuilder(CLEAN_BUILD, true);
 		if (DEBUG)
 			System.out.println("Clearing last state as part of clean : " + lastState); //$NON-NLS-1$
 		clearLastState();
 		removeProblemsAndTasksFor(currentProject);
-		new BatchImageBuilder(this).cleanOutputFolders(false);
+		new BatchImageBuilder(this, false).cleanOutputFolders(false);
 	} catch (CoreException e) {
 		Util.log(e, "JavaBuilder handling CoreException while cleaning: " + currentProject.getName()); //$NON-NLS-1$
 		IMarker marker = currentProject.createMarker(IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER);
@@ -262,6 +261,7 @@
 }
 
 private void cleanup() {
+	this.participants = null;
 	this.nameEnvironment = null;
 	this.binaryLocationsPerProject = null;
 	this.lastState = null;
@@ -482,46 +482,59 @@
 	return false;
 }
 
-private void initializeBuilder() throws CoreException {
+private int initializeBuilder(int kind, boolean forBuild) throws CoreException {
+	// some calls just need the nameEnvironment initialized so skip the rest
 	this.javaProject = (JavaProject) JavaCore.create(currentProject);
 	this.workspaceRoot = currentProject.getWorkspace().getRoot();
 
-	// Flush the existing external files cache if this is the beginning of a build cycle
-	String projectName = currentProject.getName();
-	if (builtProjects == null || builtProjects.contains(projectName)) {
-		JavaModel.flushExternalFileCache();
-		builtProjects = new ArrayList();
+	if (forBuild) {
+		// cache the known participants for this project
+		this.participants = JavaModelManager.getJavaModelManager().compilationParticipants.getCompilationParticipants(this.javaProject);
+		if (this.participants != null)
+			for (int i = 0, l = this.participants.length; i < l; i++)
+				if (this.participants[i].aboutToBuild(this.javaProject) == CompilationParticipant.NEEDS_FULL_BUILD)
+					kind = FULL_BUILD;
+	
+		// Flush the existing external files cache if this is the beginning of a build cycle
+		String projectName = currentProject.getName();
+		if (builtProjects == null || builtProjects.contains(projectName)) {
+			JavaModel.flushExternalFileCache();
+			builtProjects = new ArrayList();
+		}
+		builtProjects.add(projectName);
 	}
-	builtProjects.add(projectName);
 
 	this.binaryLocationsPerProject = new SimpleLookupTable(3);
 	this.nameEnvironment = new NameEnvironment(workspaceRoot, javaProject, binaryLocationsPerProject);
 
-	String filterSequence = javaProject.getOption(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, true);
-	char[][] filters = filterSequence != null && filterSequence.length() > 0
-		? CharOperation.splitAndTrimOn(',', filterSequence.toCharArray())
-		: null;
-	if (filters == null) {
-		this.extraResourceFileFilters = null;
-		this.extraResourceFolderFilters = null;
-	} else {
-		int fileCount = 0, folderCount = 0;
-		for (int i = 0, l = filters.length; i < l; i++) {
-			char[] f = filters[i];
-			if (f.length == 0) continue;
-			if (f[f.length - 1] == '/') folderCount++; else fileCount++;
-		}
-		this.extraResourceFileFilters = new char[fileCount][];
-		this.extraResourceFolderFilters = new String[folderCount];
-		for (int i = 0, l = filters.length; i < l; i++) {
-			char[] f = filters[i];
-			if (f.length == 0) continue;
-			if (f[f.length - 1] == '/')
-				extraResourceFolderFilters[--folderCount] = new String(f, 0, f.length - 1);
-			else
-				extraResourceFileFilters[--fileCount] = f;
+	if (forBuild) {
+		String filterSequence = javaProject.getOption(JavaCore.CORE_JAVA_BUILD_RESOURCE_COPY_FILTER, true);
+		char[][] filters = filterSequence != null && filterSequence.length() > 0
+			? CharOperation.splitAndTrimOn(',', filterSequence.toCharArray())
+			: null;
+		if (filters == null) {
+			this.extraResourceFileFilters = null;
+			this.extraResourceFolderFilters = null;
+		} else {
+			int fileCount = 0, folderCount = 0;
+			for (int i = 0, l = filters.length; i < l; i++) {
+				char[] f = filters[i];
+				if (f.length == 0) continue;
+				if (f[f.length - 1] == '/') folderCount++; else fileCount++;
+			}
+			this.extraResourceFileFilters = new char[fileCount][];
+			this.extraResourceFolderFilters = new String[folderCount];
+			for (int i = 0, l = filters.length; i < l; i++) {
+				char[] f = filters[i];
+				if (f.length == 0) continue;
+				if (f[f.length - 1] == '/')
+					extraResourceFolderFilters[--folderCount] = new String(f, 0, f.length - 1);
+				else
+					extraResourceFileFilters[--fileCount] = f;
+			}
 		}
 	}
+	return kind;
 }
 
 private boolean isClasspathBroken(IClasspathEntry[] classpath, IProject p) throws CoreException {
@@ -535,32 +548,11 @@
 	return false;
 }
 
-private void notifyCompilationParticipants() {
-	
-	List cps = JavaCore
-		.getCompilationParticipants( ICompilationParticipant.BROKEN_CLASSPATH_BUILD_FAILURE_EVENT, javaProject );
-	if ( cps == null || cps.isEmpty() )
-		return;
-		
-	BrokenClasspathBuildFailureEvent event = new BrokenClasspathBuildFailureEvent( javaProject );
-	Iterator it = cps.iterator();
-	while ( it.hasNext() ) {
-		ICompilationParticipant cp = (ICompilationParticipant) it.next();
-		cp.notify( event );
-	}
-}
-
-
 private boolean isWorthBuilding() throws CoreException {
 	boolean abortBuilds =
 		JavaCore.ABORT.equals(javaProject.getOption(JavaCore.CORE_JAVA_BUILD_INVALID_CLASSPATH, true));
 	if (!abortBuilds) return true;
 
-	
-	// if classpath is broken, let the compilation participants have a chance to fix it
-	if ( isClasspathBroken( javaProject.getRawClasspath(), currentProject ))
-		notifyCompilationParticipants();
-
 	// Abort build only if there are classpath errors
 	if (isClasspathBroken(javaProject.getRawClasspath(), currentProject)) {
 		if (DEBUG)
diff --git a/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java b/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
index 3521aec..f3ed02e 100644
--- a/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
+++ b/model/org/eclipse/jdt/internal/core/builder/ReferenceCollection.java
@@ -23,6 +23,38 @@
 	this.simpleNameReferences = internSimpleNames(simpleNameReferences, true);
 }
 
+void addDependencies(String[] typeNameDependencies) {
+	// if each qualified type name is already known then all of its subNames can be skipped
+	// and its expected that very few qualified names in typeNameDependencies need to be added
+	// but could always take 'p1.p2.p3.X' and make all qualified names 'p1' 'p1.p2' 'p1.p2.p3' 'p1.p2.p3.X', then intern
+	char[][][] qNames = new char[typeNameDependencies.length][][];
+	for (int i = typeNameDependencies.length; --i >= 0;)
+		qNames[i] = CharOperation.splitOn('.', typeNameDependencies[i].toCharArray());
+	qNames = internQualifiedNames(qNames);
+
+	next : for (int i = qNames.length; --i >= 0;) {
+		char[][] qualifiedTypeName = qNames[i];
+		while (!includes(qualifiedTypeName)) {
+			if (qualifiedTypeName.length == 1) {
+				if (!includes(qualifiedTypeName[0])) {
+					int length = this.simpleNameReferences.length;
+					System.arraycopy(this.simpleNameReferences, 0, this.simpleNameReferences = new char[length + 1][], 0, length);
+					this.simpleNameReferences[length] = qualifiedTypeName[0];
+				}
+				continue next;
+			} else {
+				int length = this.qualifiedNameReferences.length;
+				System.arraycopy(this.qualifiedNameReferences, 0, this.qualifiedNameReferences = new char[length + 1][][], 0, length);
+				this.qualifiedNameReferences[length] = qualifiedTypeName;
+
+				qualifiedTypeName = CharOperation.subarray(qualifiedTypeName, 0, qualifiedTypeName.length - 1);
+				char[][][] temp = internQualifiedNames(new char[][][] {qualifiedTypeName});
+				qualifiedTypeName = temp[0];
+			}		
+		}
+	}
+}
+
 boolean includes(char[] simpleName) {
 	for (int i = 0, l = simpleNameReferences.length; i < l; i++)
 		if (simpleName == simpleNameReferences[i]) return true;
@@ -157,7 +189,7 @@
 		keepers[index++] = internedNames.add(qualifiedName);
 	}
 	if (length > index) {
-		if (length == 0) return EmptyQualifiedNames;
+		if (index == 0) return EmptyQualifiedNames;
 		System.arraycopy(keepers, 0, keepers = new char[index][][], 0, index);
 	}
 	return keepers;
diff --git a/model/org/eclipse/jdt/internal/core/builder/State.java b/model/org/eclipse/jdt/internal/core/builder/State.java
index f3230c9..50f5376 100644
--- a/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -146,7 +146,7 @@
 
 void record(String typeLocator, char[][][] qualifiedRefs, char[][] simpleRefs, char[] mainTypeName, ArrayList typeNames) {
 	if (typeNames.size() == 1 && CharOperation.equals(mainTypeName, (char[]) typeNames.get(0))) {
-			references.put(typeLocator, new ReferenceCollection(qualifiedRefs, simpleRefs));
+		references.put(typeLocator, new ReferenceCollection(qualifiedRefs, simpleRefs));
 	} else {
 		char[][] definedTypeNames = new char[typeNames.size()][]; // can be empty when no types are defined
 		typeNames.toArray(definedTypeNames);
diff --git a/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java b/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
index 0ca1ba0..bf936de 100644
--- a/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyBuilder.java
@@ -13,6 +13,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.OperationCanceledException;
@@ -25,6 +27,7 @@
 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
 import org.eclipse.jdt.internal.core.*;
+import org.eclipse.jdt.internal.core.util.ResourceCompilationUnit;
 import org.eclipse.jdt.internal.core.util.Util;
 
 public abstract class HierarchyBuilder {
@@ -233,7 +236,12 @@
 		char[] bName = typeInfo.getName();
 		qualifiedName = new String(ClassFile.translatedName(bName));
 		if (qualifiedName.equals(this.focusQualifiedName)) return getType();
-		return this.nameLookup.findType(qualifiedName, false, flag);
+		return this.nameLookup.findType(qualifiedName,
+			false,
+			flag,
+			true/* consider secondary types */,
+			false/* do NOT wait for indexes */,
+			null);
 	}
 	protected void worked(IProgressMonitor monitor, int work) {
 		if (monitor != null) {
@@ -247,9 +255,9 @@
 /**
  * Create an ICompilationUnit info from the given compilation unit on disk.
  */
-protected ICompilationUnit createCompilationUnitFromPath(Openable handle, String osPath) {
+protected ICompilationUnit createCompilationUnitFromPath(Openable handle, IFile file) {
 	final char[] elementName = handle.getElementName().toCharArray();
-	return new BasicCompilationUnit(null/* no source*/, null/* no package */, osPath, handle) {
+	return new ResourceCompilationUnit(file) {
 		public char[] getFileName() {
 			return elementName;
 		}
@@ -259,10 +267,10 @@
  * Creates the type info from the given class file on disk and
  * adds it to the given list of infos.
  */
-protected IBinaryType createInfoFromClassFile(Openable handle, String osPath) {
+protected IBinaryType createInfoFromClassFile(Openable handle, IResource file) {
 	IBinaryType info = null;
 	try {
-		info = org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader.read(osPath);
+		info = Util.newClassFileReader(file);
 	} catch (org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException e) {
 		if (TypeHierarchy.DEBUG) {
 			e.printStackTrace();
@@ -273,6 +281,11 @@
 			e.printStackTrace();
 		}
 		return null;
+	} catch (CoreException e) {
+		if (TypeHierarchy.DEBUG) {
+			e.printStackTrace();
+		}
+		return null;
 	}						
 	this.infoToHandle.put(info, handle);
 	return info;
diff --git a/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java b/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
index 7df02b7..7a47dcf 100644
--- a/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
+++ b/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
@@ -27,6 +27,7 @@
 import java.util.HashSet;
 import java.util.Map;
 
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -40,9 +41,6 @@
 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.TypeDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
@@ -52,18 +50,12 @@
 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.lookup.BinaryTypeBinding;
-import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
-import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
-import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
 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.ProblemReporter;
 import org.eclipse.jdt.internal.compiler.util.Messages;
 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.HandleFactory;
 
@@ -569,9 +561,8 @@
 					if (containsLocalType) 	parsedUnit.bits |= ASTNode.HasAllMethodBodies;
 				} else {
 					// create parsed unit from file
-					IResource file = cu.getResource();
-					String osPath = file.getLocation().toOSString();
-					ICompilationUnit sourceUnit = this.builder.createCompilationUnitFromPath(openable, osPath);
+					IFile file = (IFile) cu.getResource();
+					ICompilationUnit sourceUnit = this.builder.createCompilationUnitFromPath(openable, file);
 					
 					CompilationResult unitResult = new CompilationResult(sourceUnit, i, openablesLength, this.options.maxProblemsPerUnit); 
 					parsedUnit = parser.dietParse(sourceUnit, unitResult);
@@ -608,8 +599,7 @@
 						binaryType = this.builder.createInfoFromClassFileInJar(classFile);
 					} else {
 						IResource file = classFile.getResource();
-						String osPath = file.getLocation().toOSString();
-						binaryType = this.builder.createInfoFromClassFile(classFile, osPath);
+						binaryType = this.builder.createInfoFromClassFile(classFile, file);
 					}
 				}
 				if (binaryType != null) {
diff --git a/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java b/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
index 33740f9..7ec2ed9 100644
--- a/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/hierarchy/IndexBasedHierarchyBuilder.java
@@ -12,6 +12,8 @@
 
 import java.util.*;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.SubProgressMonitor;
@@ -326,19 +328,19 @@
 		if (monitor != null) monitor.done();
 	}
 }
-protected ICompilationUnit createCompilationUnitFromPath(Openable handle, String osPath) {
-	ICompilationUnit unit = super.createCompilationUnitFromPath(handle, osPath);
+protected ICompilationUnit createCompilationUnitFromPath(Openable handle, IFile file) {
+	ICompilationUnit unit = super.createCompilationUnitFromPath(handle, file);
 	this.cuToHandle.put(unit, handle);
 	return unit;
 }
-protected IBinaryType createInfoFromClassFile(Openable classFile, String osPath) {
+protected IBinaryType createInfoFromClassFile(Openable classFile, IResource file) {
 	String documentPath = classFile.getPath().toString();
 	IBinaryType binaryType = (IBinaryType)this.binariesFromIndexMatches.get(documentPath);
 	if (binaryType != null) {
 		this.infoToHandle.put(binaryType, classFile);
 		return binaryType;
 	} else {
-		return super.createInfoFromClassFile(classFile, osPath);
+		return super.createInfoFromClassFile(classFile, file);
 	}
 }
 protected IBinaryType createInfoFromClassFileInJar(Openable classFile) {
diff --git a/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java b/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java
index 81b4fe7..8784815 100644
--- a/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java
+++ b/model/org/eclipse/jdt/internal/core/util/BindingKeyParser.java
@@ -772,6 +772,16 @@
 	private void parseRawType() {
 		this.scanner.skipParametersEnd();
 		consumeRawType();
+		this.scanner.skipTypeEnd();
+		parseFlags();
+	 	if (this.scanner.isAtMemberTypeStart() && this.scanner.nextToken() == Scanner.TYPE) {
+	 		char[] typeName = this.scanner.getTokenSource();
+			if (this.scanner.isAtParametersStart()) {
+				this.scanner.skipParametersStart();
+		 		parseParameterizedType(typeName, this.scanner.isAtRawTypeEnd());
+			} else
+				consumeParameterizedType(typeName, true/*raw*/);
+	 	}
 	}
 	
 	private void parseReturnType() {
diff --git a/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java b/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
index 27c74f2..0fea3a1 100644
--- a/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
+++ b/model/org/eclipse/jdt/internal/core/util/BindingKeyResolver.java
@@ -264,8 +264,13 @@
 	public void consumeParameterizedType(char[] simpleTypeName, boolean isRaw) {
 		TypeBinding[] arguments = getTypeBindingArguments();
 		if (simpleTypeName != null) {
-			// parameterized member type with parameterized enclosing type
-			this.genericType = this.genericType.getMemberType(simpleTypeName);
+			if (this.genericType == null) {
+				// parameterized member type with raw enclosing type
+				this.genericType = ((ReferenceBinding) this.typeBinding).getMemberType(simpleTypeName);
+			} else {
+				// parameterized member type with parameterized enclosing type
+				this.genericType = this.genericType.getMemberType(simpleTypeName);
+			}
 			if (!isRaw)
 				this.typeBinding = this.environment.createParameterizedType(this.genericType, arguments, (ReferenceBinding) this.typeBinding);
 			else
@@ -298,7 +303,7 @@
 	
 	public void consumeRawType() {
 		if (this.typeBinding == null) return;
-		this.typeBinding = this.environment.createRawType((ReferenceBinding) this.typeBinding, this.typeBinding.enclosingType());
+		this.typeBinding = this.environment.convertToRawType(this.typeBinding);
 	}
 	public void consumeSecondaryType(char[] simpleTypeName) {
 		if (this.parsedUnit == null) return;
diff --git a/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/model/org/eclipse/jdt/internal/core/util/Disassembler.java
index d374898..55ffb71 100644
--- a/model/org/eclipse/jdt/internal/core/util/Disassembler.java
+++ b/model/org/eclipse/jdt/internal/core/util/Disassembler.java
@@ -10,8 +10,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.util;
 
-import java.text.NumberFormat;
-
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.compiler.CharOperation;
@@ -328,11 +326,11 @@
 		final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(methodInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
 		// disassemble compact version of annotations
 		if (runtimeInvisibleAnnotationsAttribute != null) {
-			disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+			disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
 			writeNewLine(buffer, lineSeparator, tabNumber);
 		}
 		if (runtimeVisibleAnnotationsAttribute != null) {
-			disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+			disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
 			writeNewLine(buffer, lineSeparator, tabNumber);
 		}
 		final int accessFlags = methodInfo.getAccessFlags();
@@ -438,11 +436,11 @@
 		if (checkMode(mode, DETAILED)) {
 			// disassemble compact version of annotations
 			if (runtimeInvisibleAnnotationsAttribute != null) {
-				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
 				writeNewLine(buffer, lineSeparator, tabNumber);
 			}
 			if (runtimeVisibleAnnotationsAttribute != null) {
-				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
 				writeNewLine(buffer, lineSeparator, tabNumber);
 			}
 		}
@@ -497,14 +495,14 @@
 		if (checkMode(mode, DETAILED)) {
 			if (annotationDefaultAttribute != null) {
 				buffer.append(" default "); //$NON-NLS-1$
-				disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber);
+				disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode);
 			}
 		}
 		if (checkMode(mode, WORKING_COPY)) {
 			// put the annotation default attribute if needed
 			if (annotationDefaultAttribute != null) {
 				buffer.append(" default "); //$NON-NLS-1$
-				disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber);
+				disassembleAsModifier((IAnnotationDefaultAttribute) annotationDefaultAttribute, buffer, lineSeparator, tabNumber, mode);
 			}
 			if (((accessFlags & IModifierConstants.ACC_NATIVE) == 0)
 					&& ((accessFlags & IModifierConstants.ACC_ABSTRACT) == 0)) {
@@ -643,6 +641,8 @@
 				versionNumber = JavaCore.VERSION_1_4;
 			} else if (minorVersion == 0 && majorVersion == 49) {
 				versionNumber = JavaCore.VERSION_1_5;
+			} else if (minorVersion == 0 && majorVersion == 50) {
+				versionNumber = JavaCore.VERSION_1_6;
 			}
 			buffer.append(
 				Messages.bind(Messages.classfileformat_versiondetails,
@@ -678,11 +678,11 @@
 		if (checkMode(mode, DETAILED)) {
 			// disassemble compact version of annotations
 			if (runtimeInvisibleAnnotationsAttribute != null) {
-				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 1);
+				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, 1, mode);
 				writeNewLine(buffer, lineSeparator, 0);
 			}
 			if (runtimeVisibleAnnotationsAttribute != null) {
-				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 1);
+				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, 1, mode);
 				writeNewLine(buffer, lineSeparator, 0);
 			}
 		}
@@ -874,8 +874,10 @@
 			writeNewLine(buffer, lineSeparator, tabNumber + 1);
 		}
 		final int exceptionTableLength = codeAttribute.getExceptionTableLength();
+		boolean isFirstAttribute = true;
 		if (exceptionTableLength != 0) {
 			final int tabNumberForExceptionAttribute = tabNumber + 2;
+			isFirstAttribute = false;
 			dumpTab(tabNumberForExceptionAttribute, buffer);
 			final IExceptionTableEntry[] exceptionTableEntries = codeAttribute.getExceptionTable();
 			buffer.append(Messages.disassembler_exceptiontableheader); 
@@ -913,13 +915,17 @@
 					Integer.toString(exceptionTableEntry.getHandlerPC()),
 					new String(catchType)
 				}));
-			writeNewLine(buffer, lineSeparator, 0);
 		}
 		final ILineNumberAttribute lineNumberAttribute = codeAttribute.getLineNumberAttribute();
 		final int lineAttributeLength = lineNumberAttribute == null ? 0 : lineNumberAttribute.getLineNumberTableLength();
 		if (lineAttributeLength != 0) {
 			int tabNumberForLineAttribute = tabNumber + 2;
-			dumpTab(tabNumberForLineAttribute, buffer);
+			if (!isFirstAttribute) {
+				writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute);
+			} else {
+				dumpTab(tabNumberForLineAttribute, buffer);
+				isFirstAttribute = false;
+			}
 			buffer.append(Messages.disassembler_linenumberattributeheader); 
 			writeNewLine(buffer, lineSeparator, tabNumberForLineAttribute + 1);
 			int[][] lineattributesEntries = lineNumberAttribute.getLineNumberTable();
@@ -941,7 +947,12 @@
 		final int localVariableAttributeLength = localVariableAttribute == null ? 0 : localVariableAttribute.getLocalVariableTableLength();
 		if (localVariableAttributeLength != 0) {
 			int tabNumberForLocalVariableAttribute = tabNumber + 2;
-			writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
+			if (!isFirstAttribute) {
+				writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
+			} else {
+				isFirstAttribute = false;
+				dumpTab(tabNumberForLocalVariableAttribute, buffer);
+			}
 			buffer.append(Messages.disassembler_localvariabletableattributeheader); 
 			writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
 			ILocalVariableTableEntry[] localVariableTableEntries = localVariableAttribute.getLocalVariableTable();
@@ -976,12 +987,17 @@
 					Integer.toString(index),
 					new String(returnClassName(typeName, '.', mode))
 				}));
-		} 
+		}
 		final ILocalVariableTypeTableAttribute localVariableTypeAttribute= (ILocalVariableTypeTableAttribute) getAttribute(IAttributeNamesConstants.LOCAL_VARIABLE_TYPE_TABLE, codeAttribute);
 		final int localVariableTypeTableLength = localVariableTypeAttribute == null ? 0 : localVariableTypeAttribute.getLocalVariableTypeTableLength();
 		if (localVariableTypeTableLength != 0) {
 			int tabNumberForLocalVariableAttribute = tabNumber + 2;
-			writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
+			if (!isFirstAttribute) {
+				writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute);
+			} else {
+				isFirstAttribute = false;
+				dumpTab(tabNumberForLocalVariableAttribute, buffer);
+			}
 			buffer.append(Messages.disassembler_localvariabletypetableattributeheader); 
 			writeNewLine(buffer, lineSeparator, tabNumberForLocalVariableAttribute + 1);
 			ILocalVariableTypeTableEntry[] localVariableTypeTableEntries = localVariableTypeAttribute.getLocalVariableTypeTable();
@@ -1023,11 +1039,36 @@
 			for (int i = 0; i < length; i++) {
 				IClassFileAttribute attribute = attributes[i];
 				if (CharOperation.equals(attribute.getAttributeName(), IAttributeNamesConstants.STACK_MAP_TABLE)) {
-					disassemble((StackMapTableAttribute) attribute, buffer, lineSeparator, tabNumber + 1);
+					IStackMapTableAttribute stackMapTableAttribute = (IStackMapTableAttribute) attribute;
+					if (!isFirstAttribute) {
+						writeNewLine(buffer, lineSeparator, tabNumber + 2);
+					} else {
+						isFirstAttribute = false;
+						dumpTab(tabNumber + 1, buffer);
+					}
+					int numberOfEntries = stackMapTableAttribute.getNumberOfEntries();
+					buffer.append(Messages.bind(Messages.disassembler_stackmaptableattributeheader, Integer.toString(numberOfEntries)));
+					if (numberOfEntries != 0) {
+						writeNewLine(buffer, lineSeparator, tabNumber + 3);
+						final IStackMapFrame[] stackMapFrames = stackMapTableAttribute.getStackMapFrame();
+						for (int j = 0; j < numberOfEntries; j++) {
+							disassemble(stackMapFrames[j], buffer, lineSeparator, tabNumber + 3, mode);
+						}
+					}
 				} else if (attribute != lineNumberAttribute
 						&& attribute != localVariableAttribute
 						&& attribute != localVariableTypeAttribute) {
-					disassemble(attribute, buffer, lineSeparator, tabNumber + 1);
+					if (!isFirstAttribute) {
+						writeNewLine(buffer, lineSeparator, tabNumber + 2);
+					} else {
+						isFirstAttribute = false;
+						dumpTab(tabNumber + 1, buffer);
+					}
+					buffer.append(Messages.bind(Messages.disassembler_genericattributeheader,
+						new String[] {
+							new String(attribute.getAttributeName()),
+							Long.toString(attribute.getAttributeLength())
+						}));
 				}
 			}
 		}		
@@ -1168,17 +1209,17 @@
 		}
 	}
 	
-	private void disassembleEnumConstants(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, char[][] argumentTypes) {
+	private void disassembleEnumConstants(IFieldInfo fieldInfo, StringBuffer buffer, String lineSeparator, int tabNumber, char[][] argumentTypes, int mode) {
 		writeNewLine(buffer, lineSeparator, tabNumber);
 		final IClassFileAttribute runtimeVisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_VISIBLE_ANNOTATIONS);
 		final IClassFileAttribute runtimeInvisibleAnnotationsAttribute = Util.getAttribute(fieldInfo, IAttributeNamesConstants.RUNTIME_INVISIBLE_ANNOTATIONS);
 		// disassemble compact version of annotations
 		if (runtimeInvisibleAnnotationsAttribute != null) {
-			disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+			disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
 			writeNewLine(buffer, lineSeparator, tabNumber);
 		}
 		if (runtimeVisibleAnnotationsAttribute != null) {
-			disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+			disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
 			writeNewLine(buffer, lineSeparator, tabNumber);
 		}
 		buffer.append(new String(fieldInfo.getName()));
@@ -1245,11 +1286,11 @@
 		if (checkMode(mode, DETAILED)) {
 			// disassemble compact version of annotations
 			if (runtimeInvisibleAnnotationsAttribute != null) {
-				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+				disassembleAsModifier((IRuntimeInvisibleAnnotationsAttribute) runtimeInvisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
 				writeNewLine(buffer, lineSeparator, tabNumber);
 			}
 			if (runtimeVisibleAnnotationsAttribute != null) {
-				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1);
+				disassembleAsModifier((IRuntimeVisibleAnnotationsAttribute) runtimeVisibleAnnotationsAttribute, buffer, lineSeparator, tabNumber + 1, mode);
 				writeNewLine(buffer, lineSeparator, tabNumber);
 			}
 		}
@@ -1497,36 +1538,144 @@
 		}
 	}
 
-
-	private void disassemble(StackMapTableAttribute attribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
-		writeNewLine(buffer, lineSeparator, tabNumber + 1);
-		buffer.append(Messages.bind(Messages.disassembler_stackmaptableattributeheader,
-			new String[] {
-				Long.toString(attribute.getAttributeLength()),
-				getBytesAsString(attribute.getBytes(), lineSeparator, tabNumber)
-			}));
-	}
-
-	private void disassembleAsModifier(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber) {
-		final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.');
-		buffer.append('@').append(Signature.toCharArray(typeName)).append('(');
-		final IAnnotationComponent[] components = annotation.getComponents();
-		for (int i = 0, max = components.length; i < max; i++) {
-			if (i > 0) {
-				buffer.append(',');
-				writeNewLine(buffer, lineSeparator, tabNumber);
+	private String disassemble(IVerificationTypeInfo[] infos, String lineSeparator, int tabNumber, int mode) {
+		StringBuffer buffer = new StringBuffer();
+		for (int i = 0, max = infos.length; i < max; i++) {
+			if(i != 0) buffer.append(',');
+			switch(infos[i].getTag()) {
+				case IVerificationTypeInfo.ITEM_DOUBLE :
+					buffer.append("double"); //$NON-NLS-1$
+					break;
+				case IVerificationTypeInfo.ITEM_FLOAT :
+					buffer.append("float"); //$NON-NLS-1$
+					break;
+				case IVerificationTypeInfo.ITEM_INTEGER :
+					buffer.append("int"); //$NON-NLS-1$
+					break;
+				case IVerificationTypeInfo.ITEM_LONG :
+					buffer.append("long"); //$NON-NLS-1$
+					break;
+				case IVerificationTypeInfo.ITEM_NULL :
+					buffer.append("null"); //$NON-NLS-1$
+					break;
+				case IVerificationTypeInfo.ITEM_OBJECT :
+					final char[] classTypeName = infos[i].getClassTypeName();
+					CharOperation.replace(classTypeName, '/', '.');
+					buffer.append(returnClassName(classTypeName, '.', mode));
+					break;
+				case IVerificationTypeInfo.ITEM_TOP :
+					buffer.append("top"); //$NON-NLS-1$
+					break;
+				case IVerificationTypeInfo.ITEM_UNINITIALIZED :
+					buffer.append("uninitialized"); //$NON-NLS-1$
+					break;
+				case IVerificationTypeInfo.ITEM_UNINITIALIZED_THIS :
+					buffer.append("uninitialized_this"); //$NON-NLS-1$
 			}
-			disassembleAsModifier(components[i], buffer, lineSeparator, tabNumber + 1);
 		}
-		buffer.append(')');
+		return String.valueOf(buffer);
+	}
+	private void disassemble(IStackMapFrame frame, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+		// disassemble each frame
+		int type = frame.getFrameType();
+		switch(type) {
+			case 247 : // SAME_LOCALS_1_STACK_ITEM_EXTENDED
+				buffer.append(
+					Messages.bind(
+						Messages.disassembler_frame_same_locals_1_stack_item_extended,
+						Integer.toString(frame.getOffsetDelta()),
+						disassemble(frame.getStackItems(), lineSeparator, tabNumber + 1, mode)));
+				writeNewLine(buffer, lineSeparator, tabNumber);
+				break;
+			case 248 :
+			case 249 :
+			case 250:
+				// CHOP
+				buffer.append(
+						Messages.bind(
+							Messages.disassembler_frame_chop,
+							Integer.toString(frame.getOffsetDelta()),
+							Integer.toString(251 - type)));
+				writeNewLine(buffer, lineSeparator, tabNumber);
+				break;
+			case 251 :
+				// SAME_FRAME_EXTENDED
+				buffer.append(
+						Messages.bind(
+							Messages.disassembler_frame_same_frame_extended,
+							Integer.toString(frame.getOffsetDelta())));
+				writeNewLine(buffer, lineSeparator, tabNumber);
+				break;
+			case 252 :
+			case 253 :
+			case 254 :
+				// APPEND
+				buffer.append(
+						Messages.bind(
+							Messages.disassembler_frame_append,
+							Integer.toString(frame.getOffsetDelta()),
+							disassemble(frame.getLocals(), lineSeparator, tabNumber + 1, mode)));
+				writeNewLine(buffer, lineSeparator, tabNumber);
+				break;
+			case 255 :
+				// FULL_FRAME
+				buffer.append(
+						Messages.bind(
+							Messages.disassembler_frame_full_frame,
+							new String[] {
+								Integer.toString(frame.getOffsetDelta()),
+								Integer.toString(frame.getNumberOfLocals()),
+								disassemble(frame.getLocals(), lineSeparator, tabNumber + 1, mode),
+								Integer.toString(frame.getNumberOfStackItems()),
+								disassemble(frame.getStackItems(), lineSeparator, tabNumber + 1, mode),
+								dumpNewLineWithTabs(lineSeparator, tabNumber + 2)
+							}));
+				writeNewLine(buffer, lineSeparator, tabNumber);
+				break;
+			default:
+				if (type <= 63) {
+					// SAME_FRAME
+					buffer.append(
+							Messages.bind(
+								Messages.disassembler_frame_same_frame,
+								Integer.toString(type)));
+					writeNewLine(buffer, lineSeparator, tabNumber);
+				} else if (type <= 127) {
+					// SAME_LOCALS_1_STACK_ITEM
+					buffer.append(
+							Messages.bind(
+								Messages.disassembler_frame_same_locals_1_stack_item,
+								Integer.toString(type - 64),
+								disassemble(frame.getStackItems(), lineSeparator, tabNumber + 1, mode)));
+					writeNewLine(buffer, lineSeparator, tabNumber);
+				}
+		}
+	}
+	
+	private void disassembleAsModifier(IAnnotation annotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
+		final char[] typeName = CharOperation.replaceOnCopy(annotation.getTypeName(), '/', '.');
+		buffer.append('@').append(returnClassName(Signature.toCharArray(typeName), '.', mode));
+		final IAnnotationComponent[] components = annotation.getComponents();
+		final int length = components.length;
+		if (length != 0) {
+			buffer.append('(');
+			for (int i = 0; i < length; i++) {
+				if (i > 0) {
+					buffer.append(',');
+					writeNewLine(buffer, lineSeparator, tabNumber);
+				}
+				disassembleAsModifier(components[i], buffer, lineSeparator, tabNumber + 1, mode);
+			}
+			buffer.append(')');
+		}
 	}
 
-	private void disassembleAsModifier(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber) {
+	private void disassembleAsModifier(IAnnotationComponent annotationComponent, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
 		buffer.append(annotationComponent.getComponentName()).append('=');
-		disassembleAsModifier(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1);
+		disassembleAsModifier(annotationComponent.getComponentValue(), buffer, lineSeparator, tabNumber + 1, mode);
 	}
 
-	private void disassembleAsModifier(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber) {
+	private void disassembleAsModifier(IAnnotationComponentValue annotationComponentValue, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
 		switch(annotationComponentValue.getTag()) {
 			case IAnnotationComponentValue.BYTE_TAG:
 			case IAnnotationComponentValue.CHAR_TAG:
@@ -1584,7 +1733,7 @@
 				break;
 			case IAnnotationComponentValue.ANNOTATION_TAG:
 				IAnnotation annotation = annotationComponentValue.getAnnotationValue();
-				disassembleAsModifier(annotation, buffer, lineSeparator, tabNumber + 1);
+				disassembleAsModifier(annotation, buffer, lineSeparator, tabNumber + 1, mode);
 				break;
 			case IAnnotationComponentValue.ARRAY_TAG:
 				final IAnnotationComponentValue[] annotationComponentValues = annotationComponentValue.getAnnotationComponentValues();
@@ -1593,77 +1742,31 @@
 					if (i > 0) {
 						buffer.append(',');
 					}
-					disassembleAsModifier(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1);
+					disassembleAsModifier(annotationComponentValues[i], buffer, lineSeparator, tabNumber + 1, mode);
 				}
 				buffer.append('}');
 		}
 	}
 
-	private void disassembleAsModifier(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+	private void disassembleAsModifier(IAnnotationDefaultAttribute annotationDefaultAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
 		IAnnotationComponentValue componentValue = annotationDefaultAttribute.getMemberValue();
-		disassembleAsModifier(componentValue, buffer, lineSeparator, tabNumber + 1);
+		disassembleAsModifier(componentValue, buffer, lineSeparator, tabNumber + 1, mode);
 	}
 	
-	private void disassembleAsModifier(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+	private void disassembleAsModifier(IRuntimeInvisibleAnnotationsAttribute runtimeInvisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
 		IAnnotation[] annotations = runtimeInvisibleAnnotationsAttribute.getAnnotations();
 		for (int i = 0, max = annotations.length; i < max; i++) {
-			disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1);
+			disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
 		}
 	}
 
-	private void disassembleAsModifier(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+	private void disassembleAsModifier(IRuntimeVisibleAnnotationsAttribute runtimeVisibleAnnotationsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
 		IAnnotation[] annotations = runtimeVisibleAnnotationsAttribute.getAnnotations();
 		for (int i = 0, max = annotations.length; i < max; i++) {
-			disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1);
+			disassembleAsModifier(annotations[i], buffer, lineSeparator, tabNumber + 1, mode);
 		}
 	}
 
-	private String getBytesAsString(final byte[] bytes, final String lineSeparator, final int tabNumber) {
-		StringBuffer buffer = new StringBuffer();
-		NumberFormat format = NumberFormat.getInstance();
-		format.setMaximumIntegerDigits(3);
-		format.setMinimumIntegerDigits(3);
-		final int length = bytes.length;
-		if (length == 0) {
-			return "{}"; //$NON-NLS-1$
-		} else {
-			buffer.append('{');
-			writeNewLine(buffer, lineSeparator, tabNumber + 2);
-			String hexString = Integer.toHexString(bytes[0] & 0xFF);
-			switch(hexString.length()) {
-				case 1 :
-					buffer.append('0');
-					break;
-			}
-			buffer.append(hexString).append(' ');
-			hexString = Integer.toHexString(bytes[1] & 0xFF);
-			switch(hexString.length()) {
-				case 1 :
-					buffer.append('0');
-					break;
-			}
-			buffer.append(hexString);
-			for (int i = 2; i < length; i++) {
-				if ((i - 2) % 11 == 0) {
-					writeNewLine(buffer, lineSeparator, tabNumber + 2);
-				} else {
-					buffer.append(' ');
-				}
-				final int currentByte = bytes[i] & 0xFF;
-				hexString = Integer.toHexString(currentByte).toUpperCase();
-				switch(hexString.length()) {
-					case 1 :
-						buffer.append('0');
-						break;
-				}
-				buffer.append(hexString).append('(').append(format.format(currentByte)).append(')');
-			}
-			writeNewLine(buffer, lineSeparator, tabNumber + 1);
-			buffer.append('}');
-		}
-		return String.valueOf(buffer);
-	}
-
 	private void disassembleTypeMembers(IClassFileReader classFileReader, char[] className, StringBuffer buffer, String lineSeparator, int tabNumber, int mode, boolean isEnum) {
 		IFieldInfo[] fields = classFileReader.getFieldInfos();
 		if (isEnum && checkMode(mode, WORKING_COPY)) {
@@ -1676,7 +1779,7 @@
 				final int accessFlags = fieldInfo.getAccessFlags();
 				if ((accessFlags & IModifierConstants.ACC_ENUM) != 0) {
 					writeNewLine(buffer, lineSeparator, tabNumber);
-					disassembleEnumConstants(fields[index], buffer, lineSeparator, tabNumber, constructorArguments);
+					disassembleEnumConstants(fields[index], buffer, lineSeparator, tabNumber, constructorArguments, mode);
 				} else {
 					break enumConstantLoop;
 				}
@@ -1756,6 +1859,12 @@
 		for (int i = 0; i < tabNumber; i++) {
 			buffer.append(Messages.disassembler_indentation); 
 		}
+	}
+	
+	private final String dumpNewLineWithTabs(String lineSeparator, int tabNumber) {
+		StringBuffer buffer = new StringBuffer();
+		writeNewLine(buffer, lineSeparator, tabNumber);
+		return String.valueOf(buffer);
 	} 
 	
 	/**
diff --git a/model/org/eclipse/jdt/internal/core/util/Messages.java b/model/org/eclipse/jdt/internal/core/util/Messages.java
index d21b182..8780506 100644
--- a/model/org/eclipse/jdt/internal/core/util/Messages.java
+++ b/model/org/eclipse/jdt/internal/core/util/Messages.java
@@ -98,6 +98,7 @@
 	public static String build_prereqProjectHasClasspathProblems;
 	public static String build_prereqProjectMustBeRebuilt;
 	public static String build_abortDueToClasspathProblems;
+	public static String status_cannot_retrieve_attached_javadoc;	
 	public static String status_cannotUseDeviceOnPath;
 	public static String status_coreException;
 	public static String status_defaultPackageReadOnly;
@@ -119,6 +120,7 @@
 	public static String status_OK;
 	public static String status_readOnly;
 	public static String status_targetException;
+	public static String status_unknown_javadoc_format;
 	public static String status_updateConflict;
 	public static String classpath_buildPath;
 	public static String classpath_cannotNestEntryInEntry;
@@ -314,6 +316,14 @@
 	public static String classfileformat_linenumbertableentry;
 	public static String classfileformat_localvariabletableentry;
 	public static String classfileformat_versionUnknown;
+	
+	public static String disassembler_frame_same_locals_1_stack_item_extended;
+	public static String disassembler_frame_chop;
+	public static String disassembler_frame_same_frame_extended;
+	public static String disassembler_frame_append;
+	public static String disassembler_frame_full_frame;
+	public static String disassembler_frame_same_frame;
+	public static String disassembler_frame_same_locals_1_stack_item;
 
 	static {
 		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/model/org/eclipse/jdt/internal/core/util/PublicScanner.java b/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
index 7d1d092..b2f61ca 100644
--- a/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
+++ b/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
@@ -307,6 +307,7 @@
 		}
 		previous = src[i];
 	}
+	boolean containsEmptyTask = false;
 	for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
 		// retrieve message start and end positions
 		int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length;
@@ -335,8 +336,12 @@
 			if (end == -1)
 				end = max_value;
 		}
-		if (msgStart == end)
-			continue; // empty
+		if (msgStart == end) {
+			// if the description is empty, we might want to see if two tags are not sharing the same message
+			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=110797
+			containsEmptyTask = true;
+			continue;
+		}
 		// trim the message
 		while (CharOperation.isWhitespace(src[end]) && msgStart <= end)
 			end--;
@@ -350,6 +355,19 @@
 		System.arraycopy(src, msgStart, message, 0, messageLength);
 		this.foundTaskMessages[i] = message;
 	}
+	if (containsEmptyTask) {
+		for (int i = foundTaskIndex, max = this.foundTaskCount; i < max; i++) {
+			if (this.foundTaskMessages[i].length == 0) {
+				loop: for (int j = i + 1; j < max; j++) {
+					if (this.foundTaskMessages[j].length != 0) {
+						this.foundTaskMessages[i] = this.foundTaskMessages[j];
+						this.foundTaskPositions[i][1] = this.foundTaskPositions[j][1];
+						break loop;
+					}
+				}
+			}
+		}
+	}
 }
 
 public char[] getCurrentIdentifierSource() {
@@ -428,7 +446,7 @@
 		this.startPosition, 
 		this.currentPosition - this.startPosition); 
 }
-public final char[] getCurrentTokenSourceString() {
+public char[] getCurrentTokenSourceString() {
 	//return the token REAL source (aka unicodes are precomputed).
 	//REMOVE the two " that are at the beginning and the end.
 
@@ -2201,7 +2219,7 @@
 				try {
 					currentTag = new NLSTag(pos + sourceDelta, end + sourceDelta, currentLine, extractInt(s, start, end));
 				} catch (NumberFormatException e) {
-					currentTag = new NLSTag(pos + currentStartPosition, currentStartPosition + end, currentLine, -1);
+					currentTag = new NLSTag(pos + sourceDelta, end + sourceDelta, currentLine, -1);
 				}
 				if (this.nlsTagsPtr == this.nlsTags.length) {
 					// resize
diff --git a/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java b/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java
new file mode 100644
index 0000000..81401ac
--- /dev/null
+++ b/model/org/eclipse/jdt/internal/core/util/ResourceCompilationUnit.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
+
+/**
+ * An ICompilationUnit that retrieves its contents using an IFile
+ */
+public class ResourceCompilationUnit extends CompilationUnit {
+	
+	private IFile file;
+	
+	public ResourceCompilationUnit(IFile file) {
+		super(null/*no contents*/, file.getLocationURI() == null ? file.getFullPath().toString() : file.getLocationURI().getPath(), null/*encoding is used only when retrieving the contents*/);
+		this.file = file;
+	}
+
+	public char[] getContents() {
+		if (this.contents != null)
+			return this.contents;   // answer the cached source
+	
+		// otherwise retrieve it
+		try {
+			return Util.getResourceContentsAsCharArray(this.file);
+		} catch (JavaModelException e) {
+			return CharOperation.NO_CHAR;
+		}
+	}
+}
diff --git a/model/org/eclipse/jdt/internal/core/util/SimpleSet.java b/model/org/eclipse/jdt/internal/core/util/SimpleSet.java
index fe7c065..bf4dd8e 100644
--- a/model/org/eclipse/jdt/internal/core/util/SimpleSet.java
+++ b/model/org/eclipse/jdt/internal/core/util/SimpleSet.java
@@ -34,20 +34,29 @@
 }
 
 public Object add(Object object) {
-	int length = values.length;
+	int length = this.values.length;
 	int index = (object.hashCode() & 0x7FFFFFFF) % length;
 	Object current;
-	while ((current = values[index]) != null) {
-		if (current.equals(object)) return values[index] = object;
+	while ((current = this.values[index]) != null) {
+		if (current.equals(object)) return this.values[index] = object;
 		if (++index == length) index = 0;
 	}
-	values[index] = object;
+	this.values[index] = object;
 
 	// assumes the threshold is never equal to the size of the table
-	if (++elementSize > threshold) rehash();
+	if (++this.elementSize > this.threshold) rehash();
 	return object;
 }
 
+public void asArray(Object[] copy) {
+	if (this.elementSize != copy.length)
+		throw new IllegalArgumentException();
+	int index = this.elementSize;
+	for (int i = 0, l = this.values.length; i < l && index > 0; i++)
+		if (this.values[i] != null)
+			copy[--index] = this.values[i];
+}
+
 public void clear() {
 	for (int i = this.values.length; --i >= 0;)
 		this.values[i] = null;
diff --git a/model/org/eclipse/jdt/internal/core/util/StackMapFrame.java b/model/org/eclipse/jdt/internal/core/util/StackMapFrame.java
new file mode 100644
index 0000000..e913d1c
--- /dev/null
+++ b/model/org/eclipse/jdt/internal/core/util/StackMapFrame.java
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IStackMapFrame;
+import org.eclipse.jdt.core.util.IVerificationTypeInfo;
+
+/**
+ * Default implementation of IStackMapFrame
+ */
+public class StackMapFrame extends ClassFileStruct implements IStackMapFrame {
+	private static final IVerificationTypeInfo[] EMPTY_LOCALS_OR_STACK_ITEMS = new IVerificationTypeInfo[0];
+
+	private int readOffset;
+	private int frameType;
+	private int numberOfLocals;
+	private int numberOfStackItems;
+	private IVerificationTypeInfo[] locals;
+	private IVerificationTypeInfo[] stackItems;
+	private int offsetDelta;
+	
+	/**
+	 * Constructor for StackMapFrame.
+	 * 
+	 * @param classFileBytes
+	 * @param constantPool
+	 * @param offset
+	 * @throws ClassFormatException
+	 */
+	public StackMapFrame(
+			byte[] classFileBytes,
+			IConstantPool constantPool,
+			int offset) throws ClassFormatException {
+		
+		final int type = u1At(classFileBytes, 0, offset);
+		this.frameType = type;
+		switch(type) {
+			case 247 : // SAME_LOCALS_1_STACK_ITEM_EXTENDED
+				this.offsetDelta = u2At(classFileBytes, 1, offset);
+				this.numberOfStackItems = 1;
+				this.stackItems = new VerificationInfo[1];
+				this.readOffset = 1;
+				VerificationInfo info = new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset);
+				this.stackItems[0] = info;
+				this.readOffset += info.sizeInBytes();
+				this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+				this.numberOfLocals = 0;
+				break;
+			case 248 :
+			case 249 :
+			case 250:
+				// CHOP
+				this.offsetDelta = u2At(classFileBytes, 1, offset);
+				this.numberOfStackItems = 0;
+				this.stackItems = EMPTY_LOCALS_OR_STACK_ITEMS;
+				this.readOffset = 3;
+				this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+				this.numberOfLocals = 0;
+				break;
+			case 251 :
+				// SAME_FRAME_EXTENDED
+				this.offsetDelta = u2At(classFileBytes, 1, offset);
+				this.numberOfStackItems = 0;
+				this.stackItems = EMPTY_LOCALS_OR_STACK_ITEMS;
+				this.readOffset = 3;
+				this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+				this.numberOfLocals = 0;
+				break;
+			case 252 :
+			case 253 :
+			case 254 :
+				// APPEND
+				this.offsetDelta = u2At(classFileBytes, 1, offset);
+				this.numberOfStackItems = 0;
+				this.stackItems = EMPTY_LOCALS_OR_STACK_ITEMS;
+				this.readOffset = 3;
+				int diffLocals = type - 251;
+				this.numberOfLocals = diffLocals;
+				this.locals = new IVerificationTypeInfo[diffLocals];
+				for (int i = 0; i < diffLocals; i++) {
+					VerificationInfo verificationInfo = new VerificationInfo(classFileBytes, constantPool, offset + readOffset);
+					this.locals[i] = verificationInfo;
+					this.readOffset += verificationInfo.sizeInBytes();
+				}
+				break;
+			case 255 :
+				// FULL_FRAME
+				this.offsetDelta = u2At(classFileBytes, 1, offset);
+				int tempLocals = u2At(classFileBytes, 3, offset);
+				this.numberOfLocals = tempLocals;
+				this.locals = new IVerificationTypeInfo[tempLocals];
+				this.readOffset = 5;
+				for (int i = 0; i < tempLocals; i++) {
+					VerificationInfo verificationInfo = new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset);
+					this.locals[i] = verificationInfo;
+					this.readOffset += verificationInfo.sizeInBytes();
+				}
+				int tempStackItems = u2At(classFileBytes, readOffset, offset);
+				this.readOffset += 2;
+				this.numberOfStackItems = tempStackItems;
+				this.stackItems = new IVerificationTypeInfo[tempStackItems];
+				for (int i = 0; i < tempStackItems; i++) {
+					VerificationInfo verificationInfo = new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset);
+					this.stackItems[i] = verificationInfo;
+					this.readOffset += verificationInfo.sizeInBytes();
+				}
+				break;
+			default:
+				if (type <= 63) {
+					// SAME_FRAME
+					this.offsetDelta = type;
+					this.numberOfStackItems = 0;
+					this.stackItems = EMPTY_LOCALS_OR_STACK_ITEMS;
+					this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+					this.numberOfLocals = 0;
+					this.readOffset = 1;
+				} else if (type <= 127) {
+					// SAME_LOCALS_1_STACK_ITEM
+					this.offsetDelta = type - 64;
+					this.numberOfStackItems = 1;
+					this.stackItems = new VerificationInfo[1];
+					this.readOffset = 1;
+					info = new VerificationInfo(classFileBytes, constantPool, offset + this.readOffset);
+					this.stackItems[0] = info;
+					this.readOffset += info.sizeInBytes();
+					this.locals = EMPTY_LOCALS_OR_STACK_ITEMS;
+					this.numberOfLocals = 0;
+				}
+		}
+	}
+	int sizeInBytes() {
+		return this.readOffset;
+	}
+	public int getFrameType() {
+		return this.frameType;
+	}
+	public IVerificationTypeInfo[] getLocals() {
+		return this.locals;
+	}
+	public int getNumberOfLocals() {
+		return this.numberOfLocals;
+	}
+	public int getNumberOfStackItems() {
+		return this.numberOfStackItems;
+	}
+	public int getOffsetDelta() {
+		return this.offsetDelta;
+	}
+	public IVerificationTypeInfo[] getStackItems() {
+		return this.stackItems;
+	}
+}
diff --git a/model/org/eclipse/jdt/internal/core/util/StackMapTableAttribute.java b/model/org/eclipse/jdt/internal/core/util/StackMapTableAttribute.java
index 469b7a0..a184f97 100644
--- a/model/org/eclipse/jdt/internal/core/util/StackMapTableAttribute.java
+++ b/model/org/eclipse/jdt/internal/core/util/StackMapTableAttribute.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,17 +12,24 @@
 
 import org.eclipse.jdt.core.util.ClassFormatException;
 import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IStackMapFrame;
+import org.eclipse.jdt.core.util.IStackMapTableAttribute;
 /**
- * Default implementation of ILineNumberAttribute.
+ * Default implementation of IStackMapTableAttribute.
+ * @see IStackMapTableAttribute
  */
 public class StackMapTableAttribute
-	extends ClassFileAttribute {
+	extends ClassFileAttribute
+	implements IStackMapTableAttribute {
 
+	private static final IStackMapFrame[] NO_FRAMES = new IStackMapFrame[0];
 	private static final byte[] NO_ENTRIES = new byte[0];
-	
 
-	private byte[] bytes;
+	private int numberOfEntries;
+	private IStackMapFrame[] frames;
 	
+	private byte[] bytes;
+
 	/**
 	 * Constructor for LineNumberAttribute.
 	 * @param classFileBytes
@@ -31,20 +38,42 @@
 	 * @throws ClassFormatException
 	 */
 	public StackMapTableAttribute(
-		byte[] classFileBytes,
-		IConstantPool constantPool,
-		int offset)
-		throws ClassFormatException {
+			byte[] classFileBytes,
+			IConstantPool constantPool,
+			int offset)
+			throws ClassFormatException {
 		super(classFileBytes, constantPool, offset);
 		
-		final int length = (int) u4At(classFileBytes, 2, offset);
+		final int length = u2At(classFileBytes, 6, offset); 
+		this.numberOfEntries = length;
+		if (length != 0) {
+			int readOffset = 8;
+			this.frames = new IStackMapFrame[length];
+			for (int i = 0; i < length; i++) {
+				StackMapFrame frame = new StackMapFrame(classFileBytes, constantPool, offset + readOffset);
+				this.frames[i] = frame;
+				readOffset += frame.sizeInBytes();
+			}
+		} else {
+			this.frames = NO_FRAMES;
+		}
+		final int byteLength = (int) u4At(classFileBytes, 2, offset);
 		
 		if (length != 0) {
-			System.arraycopy(classFileBytes, offset + 6, this.bytes = new byte[length], 0, length);
+			System.arraycopy(classFileBytes, offset + 6, this.bytes = new byte[byteLength], 0, byteLength);
 		} else {
 			this.bytes = NO_ENTRIES;
 		}
 	}
+
+	public int getNumberOfEntries() {
+		return this.numberOfEntries;
+	}
+
+	public IStackMapFrame[] getStackMapFrame() {
+		return this.frames;
+	}
+	
 	/**
 	 */
 	public byte[] getBytes() {
diff --git a/model/org/eclipse/jdt/internal/core/util/Util.java b/model/org/eclipse/jdt/internal/core/util/Util.java
index 4c27d87..de5c146 100644
--- a/model/org/eclipse/jdt/internal/core/util/Util.java
+++ b/model/org/eclipse/jdt/internal/core/util/Util.java
@@ -11,10 +11,13 @@
 package org.eclipse.jdt.internal.core.util;
 
 import java.io.*;
+import java.net.URI;
 import java.util.*;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
 import org.eclipse.core.resources.*;
 import org.eclipse.core.runtime.*;
 import org.eclipse.core.runtime.content.IContentType;
@@ -73,6 +76,7 @@
 	private static final String EMPTY_ARGUMENT = "   "; //$NON-NLS-1$
 	
 	private static char[][] JAVA_LIKE_EXTENSIONS;
+	public static boolean ENABLE_JAVA_LIKE_EXTENSIONS = true;
 
 	private static final char[] BOOLEAN = "boolean".toCharArray(); //$NON-NLS-1$
 	private static final char[] BYTE = "byte".toCharArray(); //$NON-NLS-1$
@@ -590,9 +594,11 @@
 		char[][] javaLikeExtensions = getJavaLikeExtensions();
 		suffixes: for (int i = 0, length = javaLikeExtensions.length; i < length; i++) {
 			char[] suffix = javaLikeExtensions[i];
-			if (stringLength + suffix.length != fileNameLength) continue;
-			for (int j = stringLength; j < fileNameLength; j++) {
-				if (fileName.charAt(j) != suffix[j-stringLength]) 
+			int extensionStart = stringLength+1;
+			if (extensionStart + suffix.length != fileNameLength) continue;
+			if (fileName.charAt(stringLength) != '.') continue;
+			for (int j = extensionStart; j < fileNameLength; j++) {
+				if (fileName.charAt(j) != suffix[j-extensionStart]) 
 					continue suffixes;
 			}
 			return true;
@@ -733,30 +739,28 @@
 		}
 		return null;
 	}
+	
 	/**
 	 * Returns the registered Java like extensions.
 	 */
 	public static char[][] getJavaLikeExtensions() {
 		if (JAVA_LIKE_EXTENSIONS == null) {
 			// TODO (jerome) reenable once JDT UI supports other file extensions (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=71460)
-			if (true)
-				JAVA_LIKE_EXTENSIONS = new char[][] {SuffixConstants.SUFFIX_java};
+			if (!ENABLE_JAVA_LIKE_EXTENSIONS)
+				JAVA_LIKE_EXTENSIONS = new char[][] {SuffixConstants.EXTENSION_java.toCharArray()};
 			else {
-				IContentType javaContentType = Platform.getContentTypeManager().getContentType(JavaModelManager.JAVA_SOURCE_CONTENT_TYPE);
+				IContentType javaContentType = Platform.getContentTypeManager().getContentType(JavaCore.JAVA_SOURCE_CONTENT_TYPE);
 				String[] fileExtensions = javaContentType == null ? null : javaContentType.getFileSpecs(IContentType.FILE_EXTENSION_SPEC);
 				// note that file extensions contains "java" as it is defined in JDT Core's plugin.xml
 				int length = fileExtensions == null ? 0 : fileExtensions.length;
 				char[][] extensions = new char[length][];
 				SimpleWordSet knownExtensions = new SimpleWordSet(length); // used to ensure no duplicate extensions
-				extensions[0] = SuffixConstants.SUFFIX_java; // ensure that ".java" is first
-				knownExtensions.add(SuffixConstants.SUFFIX_java);
+				extensions[0] = SuffixConstants.EXTENSION_java.toCharArray(); // ensure that "java" is first
+				knownExtensions.add(extensions[0]);
 				int index = 1;
 				for (int i = 0; i < length; i++) {
 					String fileExtension = fileExtensions[i];
-					int extensionLength = fileExtension.length() + 1;
-					char[] extension = new char[extensionLength];
-					extension[0] = '.';
-					fileExtension.getChars(0, extensionLength-1, extension, 1);
+					char[] extension = fileExtension.toCharArray();
 					if (!knownExtensions.includes(extension)) {
 						extensions[index++] = extension;
 						knownExtensions.add(extension);
@@ -780,48 +784,45 @@
 	 */
 	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());
+			ClassFileReader reader = null;
+			if (targetLibrary instanceof IFolder) {
+				IFile classFile = findFirstClassFile((IFolder) targetLibrary); // only internal classfolders are allowed
+				if (classFile != null)
+					reader = Util.newClassFileReader(classFile);
+			} 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());
+						}
 					}
-				} 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;
 							}
 						}
-						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);
 					}
+				} catch (CoreException e) {
+					// ignore
+				} finally {
+					JavaModelManager.getJavaModelManager().closeZipFile(jar);
 				}
-				if (reader != null) {
-					return reader.getVersion();
-				}
-		} catch(JavaModelException e) {
+			}
+			if (reader != null) {
+				return reader.getVersion();
+			}
+		} catch (CoreException e) {
 			// ignore
 		} catch(ClassFormatException e) {
 			// ignore
@@ -1152,6 +1153,7 @@
 	/*
 	 * Returns the index of the Java like extension of the given file name
 	 * or -1 if it doesn't end with a known Java like extension. 
+	 * Note this is the index of the '.' even if it is not considered part of the extension.
 	 */
 	public static int indexOfJavaLikeExtension(String fileName) {
 		int fileNameLength = fileName.length();
@@ -1160,12 +1162,14 @@
 			char[] extension = javaLikeExtensions[i];
 			int extensionLength = extension.length;
 			int extensionStart = fileNameLength - extensionLength;
-			if (extensionStart < 0) continue;
+			int dotIndex = extensionStart - 1;
+			if (dotIndex < 0) continue;
+			if (fileName.charAt(dotIndex) != '.') continue;
 			for (int j = 0; j < extensionLength; j++) {
 				if (fileName.charAt(extensionStart + j) != extension[j])
 					continue extensions;
 			}
-			return extensionStart;
+			return dotIndex;
 		}
 		return -1;
 	}
@@ -1213,7 +1217,9 @@
 			case IJavaElement.COMPILATION_UNIT:
 				root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
 				resource = element.getResource();
-				if (resource != null && isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars()))
+				if (resource == null) 
+					return false;
+				if (isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars()))
 					return true;
 				return isExcluded(element.getParent());
 				
@@ -1353,6 +1359,20 @@
 		JavaCore.getPlugin().getLog().log(status);
 	}	
 	
+	public static ClassFileReader newClassFileReader(IResource resource) throws CoreException, ClassFormatException, IOException {
+		InputStream in = null;
+		try {
+			URI uri = resource.getLocationURI();
+			if (uri == null) return null;
+			IFileStore store = EFS.getStore(uri);
+			in = store.openInputStream(EFS.NONE, null);
+			return ClassFileReader.read(in, uri.getPath());
+		} finally {
+			if (in != null)
+				in.close();
+		}
+	}
+
 	/**
 	 * Normalizes the cariage returns in the given text.
 	 * They are all changed  to use the given buffer's line separator.
@@ -1784,6 +1804,13 @@
 		return new String(result);
 	}
 	
+	/*
+	 * Resets the list of Java-like extensions after a change in content-type.
+	 */
+	public static void resetJavaLikeExtensions() {
+		JAVA_LIKE_EXTENSIONS = null;
+	}
+	
 	/**
 	 * Return a new array which is the split of the given string using the given divider. The given end 
 	 * is exclusive and the given start is inclusive.
@@ -2317,7 +2344,8 @@
 			char[] extension = javaLikeExtensions[i];
 			int extensionLength = extension.length;
 			int extensionStart = fileNameLength - extensionLength;
-			if (extensionStart < 0) continue;
+			if (extensionStart-1 < 0) continue;
+			if (fileName[extensionStart-1] != '.') continue;
 			for (int j = 0; j < extensionLength; j++) {
 				if (fileName[extensionStart + j] != extension[j])
 					continue extensions;
diff --git a/model/org/eclipse/jdt/internal/core/util/VerificationInfo.java b/model/org/eclipse/jdt/internal/core/util/VerificationInfo.java
new file mode 100644
index 0000000..55a7775
--- /dev/null
+++ b/model/org/eclipse/jdt/internal/core/util/VerificationInfo.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core.util;
+
+import org.eclipse.jdt.core.util.ClassFormatException;
+import org.eclipse.jdt.core.util.IConstantPool;
+import org.eclipse.jdt.core.util.IConstantPoolConstant;
+import org.eclipse.jdt.core.util.IConstantPoolEntry;
+import org.eclipse.jdt.core.util.IVerificationTypeInfo;
+
+public class VerificationInfo extends ClassFileStruct implements IVerificationTypeInfo {
+	
+	private int tag;
+	private int offset;
+	private int constantPoolIndex;
+	private char[] classTypeName;
+	private int readOffset;
+
+	public VerificationInfo(
+			byte[] classFileBytes,
+			IConstantPool constantPool,
+			int offset) throws ClassFormatException {
+		final int t = u1At(classFileBytes, 0, offset);
+		this.tag = t;
+		this.readOffset = 1;
+		switch(t) {
+			case IVerificationTypeInfo.ITEM_OBJECT :
+				final int constantIndex = u2At(classFileBytes, 1, offset);
+				this.constantPoolIndex = constantIndex;
+				if (constantIndex != 0) {
+					IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(constantIndex);
+					if (constantPoolEntry.getKind() != IConstantPoolConstant.CONSTANT_Class) {
+						throw new ClassFormatException(ClassFormatException.INVALID_CONSTANT_POOL_ENTRY);
+					}
+					this.classTypeName = constantPoolEntry.getClassInfoName();
+				}
+				this.readOffset += 2;
+				break;
+			case IVerificationTypeInfo.ITEM_UNINITIALIZED : 
+				this.offset = u2At(classFileBytes, 1, offset);
+				this.readOffset += 2;
+		}
+	}
+	
+	public int getTag() {
+		return this.tag;
+	}
+
+	public int getOffset() {
+		return this.offset;
+	}
+
+	public int getConstantPoolIndex() {
+		return this.constantPoolIndex;
+	}
+
+	public char[] getClassTypeName() {
+		return this.classTypeName;
+	}
+	
+	public int sizeInBytes() {
+		return this.readOffset;
+	}
+}
diff --git a/model/org/eclipse/jdt/internal/core/util/messages.properties b/model/org/eclipse/jdt/internal/core/util/messages.properties
index 9dba040..45741b4 100644
--- a/model/org/eclipse/jdt/internal/core/util/messages.properties
+++ b/model/org/eclipse/jdt/internal/core/util/messages.properties
@@ -124,6 +124,8 @@
 status_readOnly = {0} is read-only
 status_targetException = Target exception
 status_updateConflict = Update conflict
+status_cannot_retrieve_attached_javadoc = Cannot retrieve the attached javadoc for {0}
+status_unknown_javadoc_format = Unknown javadoc format for {0}
 
 ### classpath
 classpath_buildPath = Build path
@@ -258,7 +260,7 @@
 disassembler_inner_name = inner name:
 disassembler_inner_accessflags = accessflags:\ 
 disassembler_genericattributeheader = Attribute: {0} Length: {1}
-disassembler_stackmaptableattributeheader = Stack map table: {0} {1}
+disassembler_stackmaptableattributeheader = Stack map table: number of frames {0}
 disassembler_signatureattributeheader = // Signature: {0}
 disassembler_indentation = \  
 disassembler_constantpoolindex =\ #
@@ -294,7 +296,19 @@
 disassembler_runtimevisibleparameterannotationsattributeheader= RuntimeVisibleParameterAnnotations:\ 
 disassembler_runtimeinvisibleparameterannotationsattributeheader= RuntimeInvisibleParameterAnnotations:\ 
 disassembler_parameterannotationentrystart=Number of annotations for parameter {0}: {1}
-
+disassembler_frame_same_locals_1_stack_item_extended=SAME_LOCALS_1_STACK_ITEM_EXTENDED: {0} [{1}]
+disassembler_frame_chop=CHOP: {0} removing {1} locals
+disassembler_frame_same_frame_extended=SAME_FRAME_EXTENDED: {0}
+disassembler_frame_append=APPEND: {0} [{1}]
+# {0} = offset delta
+# {1} = number of locals
+# {2} = locals
+# {3} = number of stack items
+# {4} = stack items
+# {5} = line separator + tabs
+disassembler_frame_full_frame=FULL_FRAME: {0} (locals: {1} stack: {3}){5}[{2}]{5}[{4}]
+disassembler_frame_same_frame=SAME_FRAME: {0}
+disassembler_frame_same_locals_1_stack_item=SAME_LOCALS_1_STACK_ITEM: {0} [{1}]
 ### classfileformat decoding
 classfileformat_versiondetails =\ (version {0} : {1}.{2}, {3})
 classfileformat_methoddescriptor = // Method descriptor #{0} {1}
diff --git a/schema/compilationParticipant.exsd b/schema/compilationParticipant.exsd
index cec9322..eee786e 100644
--- a/schema/compilationParticipant.exsd
+++ b/schema/compilationParticipant.exsd
@@ -6,9 +6,7 @@
          <meta.schema plugin="org.eclipse.jdt.core" id="compilationParticipant" name="Compilation Participants"/>
       </appInfo>
       <documentation>
-         This extension point allows clients to participate in the JDT compilation process
-         by receiving notifications at various stages of build and reconcile, via the
-         org.eclipse.jdt.core.compiler.ICompilationParticipant interface.
+         This extension point allows clients to participate in the compilation process by receiving notifications at various stages of build and reconcile, via a org.eclipse.jdt.core.compiler.CompilationParticipant.
       </documentation>
    </annotation>
 
@@ -45,22 +43,59 @@
    </element>
 
    <element name="compilationParticipant">
+      <annotation>
+         <documentation>
+            definition of a compilation participant. This definition allows to order participants. Participants are run by group. The group of participants that modify the environment is run first, then te group of participants that create problems is run, finally the group of other participants is run. Inside each group, participants are ordered using their &apos;requires&apos; attributes. If a &apos;requires&apos; attribute point to a participant that doesn&apos;t belong to the group, it is ignored.
+         </documentation>
+      </annotation>
       <complexType>
+         <sequence>
+            <element ref="requires" minOccurs="0" maxOccurs="unbounded"/>
+         </sequence>
          <attribute name="class" type="string" use="required">
             <annotation>
                <documentation>
-                  the class that implements this compilation participant.
-         This class must implement a public subclass of &lt;code&gt;org.eclipse.jdt.core.compiler.ICompilationParticipant&lt;/code&gt; with a public 0-argument constructor.
+                  the class that implements this compilation participant. This class must implement a public subclass of &lt;code&gt;org.eclipse.jdt.core.compiler.CompilationParticipant&lt;/code&gt; with a public 0-argument constructor.
                </documentation>
             </annotation>
          </attribute>
-         <attribute name="eventMask" type="string" use="required">
-         	<annotation>
-         		<documentation>
-         			the set of events for which this compilation participant wishes to be notified.
-An integer value consisting of OR-ed together constants from &lt;code&gt;org.eclipse.jdt.core.compiler.ICompilationParticipant&lt;/code&gt;.
-         		</documentation>
-         	</annotation>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  a unique identifier for this participant
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="modifiesEnvironment" type="boolean">
+            <annotation>
+               <documentation>
+                  optionally specify whether this compilation participant modifies the environment, thus affecting binding resolution. If not specified, false is assumed.
+               </documentation>
+            </annotation>
+         </attribute>
+         <attribute name="createsProblems" type="boolean">
+            <annotation>
+               <documentation>
+                  optionally specifies whether this compilation participant creates problems. If not specified, false is assumed.
+               </documentation>
+            </annotation>
+         </attribute>
+      </complexType>
+   </element>
+
+   <element name="requires">
+      <annotation>
+         <documentation>
+            a participant that is required to run this compilation participant
+         </documentation>
+      </annotation>
+      <complexType>
+         <attribute name="id" type="string" use="required">
+            <annotation>
+               <documentation>
+                  
+               </documentation>
+            </annotation>
          </attribute>
       </complexType>
    </element>
@@ -70,7 +105,7 @@
          <meta.section type="since"/>
       </appInfo>
       <documentation>
-         3.1
+         3.2
       </documentation>
    </annotation>
 
@@ -106,7 +141,7 @@
          <meta.section type="copyright"/>
       </appInfo>
       <documentation>
-         Copyright (c) 2005 BEA Systems, Inc.&lt;br&gt;
+         Copyright (c) 2005 BEA Systems, Inc and others.&lt;br&gt;
 All rights reserved. This program and the accompanying materials
 are made available under the terms of the Eclipse Public License v1.0
 which accompanies this distribution, and is available at 
diff --git a/scripts/buildExtraJars.xml b/scripts/buildExtraJars.xml
deleted file mode 100644
index 363b77b..0000000
--- a/scripts/buildExtraJars.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="org.eclipse.core.resources" default="main" basedir="..">
-
-	<property name="bootclasspath" value=""/>
-
-	<target name="main">
-		<available file="${basedir}/jdtCompilerAdapter.jar" property="do.not.rebuild"/>
-		<antcall target="build"/>
-	</target>
-
-	<target name="build" unless="do.not.rebuild">
-		<antcall target="clean"/>
-		<antcall target="jdtCompilerAdapter.jar"/>
-		<antcall target="refresh"/>
-	</target>
-
-	<target name="init" depends="properties">
-		<property name="plugin" value="org.eclipse.jdt.core"/>
-		<property name="temp.folder" value="${basedir}/temp.folder"/>
-		<property name="plugin.destination" value="${basedir}"/>
-		<property name="build.result.folder" value="${basedir}"/>
-	</target>
-
-	<target name="properties" if="eclipse.running">
-		<property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
-	</target>
-
-	<target name="jdtCompilerAdapter.jar" depends="init">
-		<property name="destdir" value="${temp.folder}/jdtCompilerAdapter.jar.bin"/>
-		<delete dir="${temp.folder}/jdtCompilerAdapter.jar.bin"/>
-		<mkdir dir="${temp.folder}/jdtCompilerAdapter.jar.bin"/>
-		<!-- compile the source code -->
-		<javac destdir="${temp.folder}/jdtCompilerAdapter.jar.bin" failonerror="false" target="1.1" source="1.3" verbose="false" debug="on" includeAntRuntime="no" bootclasspath="${bootclasspath}" classpath="../org.eclipse.core.runtime/bin;../org.eclipse.core.runtime/runtime.jar;../org.eclipse.core.resources/bin;../org.eclipse.core.resources/resources.jar;../org.apache.ant/ant.jar;../org.eclipse.jdt.core/bin;../org.eclipse.jdt.core/jdtcore.jar;">
-			<src path="antadapter/"/>
-		</javac>
-		<!-- copy necessary resources activate when we 
-		<copy todir="${temp.folder}/jdtCompilerAdapter.jar.bin">
-			<fileset dir="antadapter/" excludes="**/*.java"/>
-		</copy> -->
-		<jar jarfile="${build.result.folder}/jdtCompilerAdapter.jar" basedir="${temp.folder}/jdtCompilerAdapter.jar.bin"/>
-		<delete dir="${temp.folder}"/>
-	</target>
-
-	<target name="clean" depends="init">
-		<delete file="${build.result.folder}/jdtCompilerAdapter.jar"/>
-		<delete dir="${temp.folder}"/>
-	</target>
-
-	<target name="refresh" depends="init" if="eclipse.running">
-		<eclipse.refreshLocal resource="${plugin}" depth="infinite"/>
-	</target>
-
-</project>
\ No newline at end of file
diff --git a/scripts/exportplugin.xml b/scripts/exportplugin.xml
index e7945fc..e44bdf0 100644
--- a/scripts/exportplugin.xml
+++ b/scripts/exportplugin.xml
@@ -1,11 +1,21 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!-- build script to create a plugin from ${plugin} -->
-<project name="${plugin}" default="export plug-in [_3.1.1.apt02]" basedir=".."> 
+<project name="${plugin}" default="export plug-in [_3.2.0]" basedir="..">
 
-<target name="export plug-in [_3.1.1.apt02]">
+<target name="export plug-in [_3.2.0]">
+    <tstamp/>
+	<property name="qualifier" value="z${DSTAMP}-${TSTAMP}" />
 	<antcall target="zz_internal_export">
-		<param name="jdt_core_version" value="3.1.1.apt02"/>
+		<param name="jdt_core_version" value="3.2.0"/>
+	</antcall>
+</target>
+
+<target name="export plug-in [_3.2.0.qualifier]">
+    <tstamp/>
+	<property name="qualifier" value="z${DSTAMP}-${TSTAMP}" />
+	<antcall target="zz_internal_export">
+		<param name="jdt_core_version" value="3.2.0.${qualifier}"/>
 	</antcall>
 </target>
 
@@ -75,36 +85,35 @@
 		basedir="antbin"/>
 
 	<echo message="UPDATE ${plugin}_${jdt_core_version}.jar" />
+	<copy todir="${plugin-dir}/META-INF">
+		<fileset dir="META-INF" />
+	</copy>  
+	<replaceregexp file="${plugin-dir}/META-INF/MANIFEST.MF" match="Bundle-Version: ((\d)+\.(\d)+\.(\d)+\.)qualifier" replace="Bundle-Version: \1${qualifier}" byline="true" />
 	<zip zipfile="${plugin-dir}/${plugin}_${jdt_core_version}.jar">
 		<fileset dir=".">
 		  <include name="plugin.xml" />
 		  <include name="plugin.properties" />
-		  <include name="META-INF/**" />
 	      <include name=".options"/>
           <include name="about.html"/>
         </fileset>
+		<fileset dir="${plugin-dir}">
+			<include name="META-INF/**" />
+		</fileset>
         <fileset dir="bin" />
         <fileset file="${plugin-dir}/jdtCompilerAdapter.jar"/>
+        <zipfileset dir="batch" prefix="src"/>
+	    <zipfileset dir="codeassist" prefix="src"/>
+	    <zipfileset dir="compiler" prefix="src"/>
+	    <zipfileset dir="dom" prefix="src"/>
+	    <zipfileset dir="eval" prefix="src"/>
+	    <zipfileset dir="formatter" prefix="src"/>
+	    <zipfileset dir="model" prefix="src"/>
+	    <zipfileset dir="search" prefix="src"/>
 	</zip>
+	<delete dir="${plugin-dir}/META-INF" />
 
 	<delete file="${plugin-dir}/jdtCompilerAdapter.jar"/>
-	<echo message="UPDATE src.zip" />
-	<zip zipfile="${plugin-dir}/src.zip">
-        <fileset file="component.xml"/>	
-	    <fileset dir="batch" />
-	    <fileset dir="codeassist" />
-	    <fileset dir="compiler" />
-	    <fileset dir="dom" />
-	    <fileset dir="eval" />
-	    <fileset dir="formatter" />
-	    <fileset dir="model" />
-	    <fileset dir="search" />
-	</zip>		
 
-	<echo message="UPDATE jdtCompilerAdaptersrc.zip" />
-	<zip zipfile="${plugin-dir}/jdtCompilerAdaptersrc.zip">
-		<fileset dir="antadapter" />
-	</zip>	    
 	<echo message="UPDATE ${export-dir}/../${plugin}_${jdt_core_version}.zip" />
 	<zip zipfile="${export-dir}/../${plugin}_${jdt_core_version}.zip"
 	    basedir="${export-dir}" 
diff --git a/search/org/eclipse/jdt/core/search/SearchParticipant.java b/search/org/eclipse/jdt/core/search/SearchParticipant.java
index a61f4fa..2a7129d 100644
--- a/search/org/eclipse/jdt/core/search/SearchParticipant.java
+++ b/search/org/eclipse/jdt/core/search/SearchParticipant.java
@@ -158,6 +158,24 @@
 	public abstract void locateMatches(SearchDocument[] documents, SearchPattern pattern, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException;
 
 	/**
+	 * Removes the index for a given path. 
+	 * <p>
+	 * The given index location must represent a path in the file system to a file that
+	 * already exists and must be an index file, otherwise nothing will be done.
+	 * </p><p>
+	 * It is strongly recommended to use this method instead of deleting file directly
+	 * otherwise cached index will not be removed.
+	 * </p>
+	 * 
+	 * @param indexLocation the location in the file system to the index
+	 * @since 3.2
+	 */
+	public void removeIndex(IPath indexLocation){
+		IndexManager manager = JavaModelManager.getJavaModelManager().getIndexManager();
+		manager.removeIndexPath(indexLocation);
+	}
+
+	/**
 	 * Schedules the indexing of the given document.
 	 * Once the document is ready to be indexed, 
 	 * {@link #indexDocument(SearchDocument, IPath) indexDocument(document, indexPath)}
@@ -166,6 +184,9 @@
 	 * The given index location must represent a path in the file system to a file that
 	 * either already exists or is going to be created. If it exists, it must be an index file,
 	 * otherwise its data might be overwritten.
+	 * </p><p>
+	 * When the index is no longer needed, clients should use {@link #removeIndex(IPath) }
+	 * to discard it.
 	 * </p>
 	 * 
 	 * @param document the document to index
@@ -183,7 +204,7 @@
 		}
 		IndexManager manager = JavaModelManager.getJavaModelManager().getIndexManager();
 		String osIndexLocation = indexLocation.toOSString();
-		// TODO (jerome) should not have to create index manually, should expose API that recreates index instead
+		// TODO (frederic) should not have to create index manually, should expose API that recreates index instead
 		manager.ensureIndexExists(osIndexLocation, containerPath);
 		manager.scheduleDocumentIndexing(document, containerPath, osIndexLocation, this);
 	}
diff --git a/search/org/eclipse/jdt/core/search/SearchPattern.java b/search/org/eclipse/jdt/core/search/SearchPattern.java
index 3157179..beee415 100644
--- a/search/org/eclipse/jdt/core/search/SearchPattern.java
+++ b/search/org/eclipse/jdt/core/search/SearchPattern.java
@@ -1012,9 +1012,7 @@
  * @return a search pattern on the given string pattern, or <code>null</code> if the string pattern is ill-formed
  */
 public static SearchPattern createPattern(String stringPattern, int searchFor, int limitTo, int matchRule) {
-	// Null string not allowed, empty string only allowed for Package seach (default package)
-	if (stringPattern == null || stringPattern.length() == 0 && searchFor != IJavaSearchConstants.PACKAGE) 
-		return null;
+	if (stringPattern == null || stringPattern.length() == 0 && searchFor != IJavaSearchConstants.PACKAGE) return null;
 
 	if ((matchRule = validateMatchRule(stringPattern, matchRule)) == -1) {
 		return null;
diff --git a/search/org/eclipse/jdt/core/search/TypeReferenceMatch.java b/search/org/eclipse/jdt/core/search/TypeReferenceMatch.java
index bed49a2..9875b63 100644
--- a/search/org/eclipse/jdt/core/search/TypeReferenceMatch.java
+++ b/search/org/eclipse/jdt/core/search/TypeReferenceMatch.java
@@ -24,6 +24,9 @@
  */
 public class TypeReferenceMatch extends SearchMatch {
 
+	private IJavaElement localElement;
+	private IJavaElement[] otherElements;
+
 	/**
 	 * Creates a new type reference match.
 	 * 
@@ -40,4 +43,54 @@
 		super(enclosingElement, accuracy, offset, length, participant, resource);
 		setInsideDocComment(insideDocComment);
 	}
+
+	/**
+	 * Returns the local element of this search match.
+	 * This may be a local variable which declaring type is the referenced one
+	 * or a type parameter which extends it.
+	 * 
+	 * @return the element of the search match, or <code>null</code> if none or there's
+	 * 	no more specific local element than the element itself ({@link SearchMatch#getElement()}).
+	 * @since 3.2
+	 */
+	public final IJavaElement getLocalElement() {
+		return this.localElement;
+	}
+
+	/**
+	 * Returns other enclosing elements of this search match.
+	 *
+	 * If {@link #getLocalElement()} is not <code>null</code>, these may be other
+	 * local elements such as additional local variables of a multiple local
+	 * variables declaration. Otherwise, these may be other elements such as
+	 * additional fields of a multiple fields declaration.
+	 * 
+	 * @return the other elements of the search match, or <code>null</code> if none
+	 * @since 3.2
+	 */
+	public final IJavaElement[] getOtherElements() {
+		return this.otherElements;
+	}
+
+	/**
+	 * Sets the local element of this search match.
+	 * 
+	 * @param localElement A more specific local element that corresponds to the match,
+	 * 	or <code>null</code> if none
+	 * @since 3.2
+	 */
+	public final void setLocalElement(IJavaElement localElement) {
+		this.localElement = localElement;
+	}
+
+	/**
+	 * Sets the other elements of this search match.
+	 * 
+	 * @param otherElements the other elements of the match,
+	 * 	or <code>null</code> if none
+	 * @since 3.2
+	 */
+	public final void setOtherElements(IJavaElement[] otherElements) {
+		this.otherElements = otherElements;
+	}
 }
diff --git a/search/org/eclipse/jdt/internal/core/index/DiskIndex.java b/search/org/eclipse/jdt/internal/core/index/DiskIndex.java
index 024c78f..9998599 100644
--- a/search/org/eclipse/jdt/internal/core/index/DiskIndex.java
+++ b/search/org/eclipse/jdt/internal/core/index/DiskIndex.java
@@ -35,7 +35,7 @@
 private HashtableOfObject categoryTables; // category name -> HashtableOfObject(words -> int[] of document #'s) or offset if not read yet
 private char[] cachedCategoryName;
 
-public static final String SIGNATURE= "INDEX VERSION 1.106"; //$NON-NLS-1$
+public static final String SIGNATURE= "INDEX VERSION 1.107"; //$NON-NLS-1$
 public static boolean DEBUG = false;
 
 private static final int RE_INDEXED = -1;
@@ -488,7 +488,7 @@
 
 		// rename file by deleting previous index file & renaming temp one
 		File old = getIndexFile();
-		if (!old.delete()) {
+		if (old.exists() && !old.delete()) {
 			if (DEBUG)
 				System.out.println("mergeWith - Failed to delete " + this.fileName); //$NON-NLS-1$
 			throw new IOException("Failed to delete index file " + this.fileName); //$NON-NLS-1$
diff --git a/search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java b/search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java
index 092eb70..1566ea7 100644
--- a/search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java
+++ b/search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java
@@ -71,7 +71,7 @@
 	}
 	
 	/**
-	 * @see org.eclipse.jdt.core.search.SearchEngine#SearchEngine(ICompilationUnit[]) for detailed comment.
+	 * @see SearchEngine#SearchEngine(ICompilationUnit[]) for detailed comment.
 	 */
 	public BasicSearchEngine(ICompilationUnit[] workingCopies) {
 		this.workingCopies = workingCopies;
@@ -87,35 +87,35 @@
 		}
 	}
 	/**
-	 * @see org.eclipse.jdt.core.search.SearchEngine#SearchEngine(WorkingCopyOwner) for detailed comment.
+	 * @see SearchEngine#SearchEngine(WorkingCopyOwner) for detailed comment.
 	 */
 	public BasicSearchEngine(WorkingCopyOwner workingCopyOwner) {
 		this.workingCopyOwner = workingCopyOwner;
 	}
 
 	/**
-	 * @see org.eclipse.jdt.core.search.SearchEngine#createHierarchyScope(IType) for detailed comment.
+	 * @see SearchEngine#createHierarchyScope(IType) for detailed comment.
 	 */
 	public static IJavaSearchScope createHierarchyScope(IType type) throws JavaModelException {
 		return createHierarchyScope(type, DefaultWorkingCopyOwner.PRIMARY);
 	}
 	
 	/**
-	 * @see org.eclipse.jdt.core.search.SearchEngine#createHierarchyScope(IType,WorkingCopyOwner) for detailed comment.
+	 * @see SearchEngine#createHierarchyScope(IType,WorkingCopyOwner) for detailed comment.
 	 */
 	public static IJavaSearchScope createHierarchyScope(IType type, WorkingCopyOwner owner) throws JavaModelException {
 		return new HierarchyScope(type, owner);
 	}
 
 	/**
-	 * @see org.eclipse.jdt.core.search.SearchEngine#createJavaSearchScope(IJavaElement[]) for detailed comment.
+	 * @see SearchEngine#createJavaSearchScope(IJavaElement[]) for detailed comment.
 	 */
 	public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements) {
 		return createJavaSearchScope(elements, true);
 	}
 
 	/**
-	 * @see org.eclipse.jdt.core.search.SearchEngine#createJavaSearchScope(IJavaElement[], boolean) for detailed comment.
+	 * @see SearchEngine#createJavaSearchScope(IJavaElement[], boolean) for detailed comment.
 	 */
 	public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements, boolean includeReferencedProjects) {
 		int includeMask = IJavaSearchScope.SOURCES | IJavaSearchScope.APPLICATION_LIBRARIES | IJavaSearchScope.SYSTEM_LIBRARIES;
@@ -126,7 +126,7 @@
 	}
 
 	/**
-	 * @see org.eclipse.jdt.core.search.SearchEngine#createJavaSearchScope(IJavaElement[], int) for detailed comment.
+	 * @see SearchEngine#createJavaSearchScope(IJavaElement[], int) for detailed comment.
 	 */
 	public static IJavaSearchScope createJavaSearchScope(IJavaElement[] elements, int includeMask) {
 		JavaSearchScope scope = new JavaSearchScope();
@@ -149,9 +149,7 @@
 	}
 	
 	/**
-	 * Returns a Java search scope with the workspace as the only limit.
-	 *
-	 * @return a new workspace scope
+	 * @see SearchEngine#createWorkspaceScope() for detailed comment.
 	 */
 	public static IJavaSearchScope createWorkspaceScope() {
 		return JavaModelManager.getJavaModelManager().getWorkspaceScope();
@@ -165,7 +163,7 @@
 	 * @param scope the search result has to be limited to the given scope
 	 * @param requestor a callback object to which each match is reported
 	 */
-	public void findMatches(SearchPattern pattern, SearchParticipant[] participants, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException {
+	void findMatches(SearchPattern pattern, SearchParticipant[] participants, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException {
 		if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
 	
 		/* initialize progress monitor */
@@ -231,7 +229,7 @@
 	/**
 	 * @param matchRule
 	 */
-	private String getMatchRuleString(final int matchRule) {
+	public static String getMatchRuleString(final int matchRule) {
 		StringBuffer buffer = new StringBuffer();
 		for (int i=1; i<=8; i++) {
 			int bit = matchRule & (1<<(i-1));
@@ -266,6 +264,39 @@
 		return buffer.toString();
 	}
 
+	/**
+	 * Return kind of search corresponding to given value.
+	 * 
+	 * @param searchFor
+	 */
+	public static String getSearchForString(final int searchFor) {
+		switch (searchFor) {
+			case IJavaSearchConstants.TYPE:
+				return ("TYPE"); //$NON-NLS-1$
+			case IJavaSearchConstants.METHOD:
+				return ("METHOD"); //$NON-NLS-1$
+			case IJavaSearchConstants.PACKAGE:
+				return ("PACKAGE"); //$NON-NLS-1$
+			case IJavaSearchConstants.CONSTRUCTOR:
+				return ("CONSTRUCTOR"); //$NON-NLS-1$
+			case IJavaSearchConstants.FIELD:
+				return ("FIELD"); //$NON-NLS-1$
+			case IJavaSearchConstants.CLASS:
+				return ("CLASS"); //$NON-NLS-1$
+			case IJavaSearchConstants.INTERFACE:
+				return ("INTERFACE"); //$NON-NLS-1$
+			case IJavaSearchConstants.ENUM:
+				return ("ENUM"); //$NON-NLS-1$
+			case IJavaSearchConstants.ANNOTATION_TYPE:
+				return ("ANNOTATION_TYPE"); //$NON-NLS-1$
+			case IJavaSearchConstants.CLASS_AND_ENUM:
+				return ("CLASS_AND_ENUM"); //$NON-NLS-1$
+			case IJavaSearchConstants.CLASS_AND_INTERFACE:
+				return ("CLASS_AND_INTERFACE"); //$NON-NLS-1$
+		}
+		return "UNKNOWN"; //$NON-NLS-1$
+	}
+
 	private Parser getParser() {
 		if (this.parser == null) {
 			this.compilerOptions = new CompilerOptions(JavaCore.getOptions());
@@ -279,10 +310,8 @@
 		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) {
@@ -354,10 +383,8 @@
 		return result;
 	}
 	
-	/**
+	/*
 	 * 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) {
@@ -688,6 +715,94 @@
 	}
 
 	/**
+	 * 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). 
+	 * 
+	 */
+	public void searchAllSecondaryTypeNames(
+			IPackageFragmentRoot[] sourceFolders,
+			final IRestrictedAccessTypeRequestor nameRequestor,
+			IProgressMonitor progressMonitor)  throws JavaModelException {
+
+		if (VERBOSE) {
+			Util.verbose("BasicSearchEngine.searchAllSecondaryTypeNames(char[], char[], int, int, IJavaSearchScope, IRestrictedAccessTypeRequestor, int, IProgressMonitor)"); //$NON-NLS-1$
+			StringBuffer buffer = new StringBuffer(" -> source folders: "); //$NON-NLS-1$
+			int length = sourceFolders.length;
+			for (int i=0; i<length; i++) {
+				if (i==0) {
+					buffer.append('[');
+				} else {
+					buffer.append(',');
+				}
+				buffer.append(sourceFolders[i].getElementName());
+			}
+			buffer.append(']');
+			Util.verbose(buffer.toString());
+		}
+
+		IndexManager indexManager = JavaModelManager.getJavaModelManager().getIndexManager();
+		final TypeDeclarationPattern pattern = new SecondaryTypeDeclarationPattern();
+		
+		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, AccessRuleSet access) {
+				TypeDeclarationPattern record = (TypeDeclarationPattern)indexRecord;
+				if (record.secondary) {
+					AccessRestriction accessRestriction = null;
+					if (record.enclosingTypeNames != IIndexConstants.ONE_ZERO_CHAR  // filter out local and anonymous classes
+							&& !workingCopyPaths.contains(documentPath)) { // filter out working copies
+						if (access != null) {
+							// Compute document relative path
+							int pkgLength = (record.pkg==null || record.pkg.length==0) ? 0 : record.pkg.length+1;
+							int nameLength = record.simpleName==null ? 0 : record.simpleName.length;
+							char[] path = new char[pkgLength+nameLength];
+							int pos = 0;
+							if (pkgLength > 0) {
+								System.arraycopy(record.pkg, 0, path, pos, pkgLength-1);
+								CharOperation.replace(path, '.', '/');
+								path[pkgLength-1] = '/';
+								pos += pkgLength;
+							}
+							if (nameLength > 0) {
+								System.arraycopy(record.simpleName, 0, path, pos, nameLength);
+								pos += nameLength;
+							}
+							// Update access restriction if path is not empty
+							if (pos > 0) {
+								accessRestriction = access.getViolatedRestriction(path);
+							}
+						}
+						nameRequestor.acceptType(record.modifiers, record.pkg, record.simpleName, record.enclosingTypeNames, documentPath, accessRestriction);
+					}
+				}
+				return true;
+			}
+		};
+
+		// add type names from indexes
+		if (progressMonitor != null) {
+			progressMonitor.beginTask(Messages.engine_searching, 100); 
+		}
+		indexManager.performConcurrentJob(
+			new PatternSearchJob(
+				pattern, 
+				getDefaultSearchParticipant(), // Java search only
+				createJavaSearchScope(sourceFolders), 
+				searchRequestor),
+			IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
+			progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 100));
+	}
+
+	/**
 	 * Searches for all top-level types and member types in the given scope using  a case sensitive exact match
 	 * with the given qualified names and type names.
 	 * 
diff --git a/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java b/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
index ec22707..f1ae8fb 100644
--- a/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
+++ b/search/org/eclipse/jdt/internal/core/search/indexing/AbstractIndexer.java
@@ -23,8 +23,9 @@
 	public AbstractIndexer(SearchDocument document) {
 		this.document = document;
 	}
-	public void addAnnotationTypeDeclaration(int modifiers, char[] packageName, char[] name, char[][] enclosingTypeNames) {
-		addIndexEntry(TYPE_DECL, TypeDeclarationPattern.createIndexKey(modifiers, name, packageName, enclosingTypeNames));
+	public void addAnnotationTypeDeclaration(int modifiers, char[] packageName, char[] name, char[][] enclosingTypeNames, boolean secondary) {
+		char[] indexKey = TypeDeclarationPattern.createIndexKey(modifiers, name, packageName, enclosingTypeNames, secondary);
+		addIndexEntry(TYPE_DECL, indexKey);
 		
 		addIndexEntry(
 			SUPER_REF, 
@@ -38,8 +39,10 @@
 			char[][] enclosingTypeNames, 
 			char[] superclass, 
 			char[][] superinterfaces,
-			char[][] typeParameterSignatures) {
-		addIndexEntry(TYPE_DECL, TypeDeclarationPattern.createIndexKey(modifiers, name, packageName, enclosingTypeNames));
+			char[][] typeParameterSignatures,
+			boolean secondary) {
+		char[] indexKey = TypeDeclarationPattern.createIndexKey(modifiers, name, packageName, enclosingTypeNames, secondary);
+		addIndexEntry(TYPE_DECL, indexKey);
 
 		if (superclass != null) {
 			superclass = erasure(superclass);
@@ -84,9 +87,10 @@
 		if (innermostTypeName != simpleTypeName)
 			addIndexEntry(CONSTRUCTOR_REF, ConstructorPattern.createIndexKey(innermostTypeName, argCount));
 	}
-	public void addEnumDeclaration(int modifiers, char[] packageName, char[] name, char[][] enclosingTypeNames, char[][] superinterfaces) {
-		addIndexEntry(TYPE_DECL, TypeDeclarationPattern.createIndexKey(modifiers, name, packageName, enclosingTypeNames));
-		
+	public void addEnumDeclaration(int modifiers, char[] packageName, char[] name, char[][] enclosingTypeNames, char[][] superinterfaces, boolean secondary) {
+		char[] indexKey = TypeDeclarationPattern.createIndexKey(modifiers, name, packageName, enclosingTypeNames, secondary);
+		addIndexEntry(TYPE_DECL, indexKey);
+
 		addIndexEntry(
 			SUPER_REF, 
 			SuperTypeReferencePattern.createIndexKey(
@@ -112,8 +116,9 @@
 	protected void addIndexEntry(char[] category, char[] key) {
 		this.document.addIndexEntry(category, key);
 	}
-	public void addInterfaceDeclaration(int modifiers, char[] packageName, char[] name, char[][] enclosingTypeNames, char[][] superinterfaces, char[][] typeParameterSignatures) {
-		addIndexEntry(TYPE_DECL, TypeDeclarationPattern.createIndexKey(modifiers, name, packageName, enclosingTypeNames));
+	public void addInterfaceDeclaration(int modifiers, char[] packageName, char[] name, char[][] enclosingTypeNames, char[][] superinterfaces, char[][] typeParameterSignatures, boolean secondary) {
+		char[] indexKey = TypeDeclarationPattern.createIndexKey(modifiers, name, packageName, enclosingTypeNames, secondary);
+		addIndexEntry(TYPE_DECL, indexKey);
 
 		if (superinterfaces != null) {
 			for (int i = 0, max = superinterfaces.length; i < max; i++) {
diff --git a/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java b/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
index a862686..87707bb 100644
--- a/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
+++ b/search/org/eclipse/jdt/internal/core/search/indexing/BinaryIndexer.java
@@ -496,16 +496,16 @@
 			switch (TypeDeclaration.kind(modifiers)) {
 				case TypeDeclaration.CLASS_DECL :
 					char[] superclass = replace('/', '.', reader.getSuperclassName());
-					addClassDeclaration(modifiers, packageName, name, enclosingTypeNames, superclass, superinterfaces, typeParameterSignatures);
+					addClassDeclaration(modifiers, packageName, name, enclosingTypeNames, superclass, superinterfaces, typeParameterSignatures, false);
 					break;
 				case TypeDeclaration.INTERFACE_DECL :
-					addInterfaceDeclaration(modifiers, packageName, name, enclosingTypeNames, superinterfaces, typeParameterSignatures);
+					addInterfaceDeclaration(modifiers, packageName, name, enclosingTypeNames, superinterfaces, typeParameterSignatures, false);
 					break;
 				case TypeDeclaration.ENUM_DECL :
-					addEnumDeclaration(modifiers, packageName, name, enclosingTypeNames, superinterfaces);
+					addEnumDeclaration(modifiers, packageName, name, enclosingTypeNames, superinterfaces, false);
 					break;
 				case TypeDeclaration.ANNOTATION_TYPE_DECL :
-					addAnnotationTypeDeclaration(modifiers, packageName, name, enclosingTypeNames);
+					addAnnotationTypeDeclaration(modifiers, packageName, name, enclosingTypeNames, false);
 					break;
 			}			
 	
diff --git a/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java b/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
index b4ee43a..669bfc2 100644
--- a/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
+++ b/search/org/eclipse/jdt/internal/core/search/indexing/IIndexConstants.java
@@ -36,6 +36,7 @@
 	char CLASS_AND_ENUM_SUFFIX = IJavaSearchConstants.CLASS_AND_ENUM;
 	char CLASS_AND_INTERFACE_SUFFIX = IJavaSearchConstants.CLASS_AND_INTERFACE;
 	char SEPARATOR= '/';
+	char SECONDARY_SUFFIX = 'S';
 
 	char[] ONE_STAR = new char[] {'*'};
 	char[][] ONE_STAR_CHAR = new char[][] {ONE_STAR};
diff --git a/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java b/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
index e7b2fea..9024a8b 100644
--- a/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
+++ b/search/org/eclipse/jdt/internal/core/search/indexing/IndexAllProject.java
@@ -11,8 +11,10 @@
 package org.eclipse.jdt.internal.core.search.indexing;
 
 import java.io.IOException;
+import java.net.URI;
 import java.util.HashSet;
 
+import org.eclipse.core.filesystem.EFS;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
@@ -137,7 +139,7 @@
 										case IResource.FILE :
 											if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(proxy.getName())) {
 												IFile file = (IFile) proxy.requestResource();
-												if (file.getLocation() == null) return false;
+												if (file.getLocationURI() == null) return false;
 												if (exclusionPatterns != null || inclusionPatterns != null)
 													if (Util.isExcluded(file, inclusionPatterns, exclusionPatterns))
 														return false;
@@ -161,20 +163,21 @@
 					} else {
 						sourceFolder.accept(
 							new IResourceProxyVisitor() {
-								public boolean visit(IResourceProxy proxy) {
+								public boolean visit(IResourceProxy proxy) throws CoreException {
 									if (isCancelled) return false;
 									switch(proxy.getType()) {
 										case IResource.FILE :
 											if (org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(proxy.getName())) {
 												IFile file = (IFile) proxy.requestResource();
-												IPath location = file.getLocation();
-												if (location == null) return false;
+												URI uri = file.getLocationURI();
+												if (uri == null) return false;
 												if (exclusionPatterns != null || inclusionPatterns != null)
 													if (Util.isExcluded(file, inclusionPatterns, exclusionPatterns))
 														return false;
 												String relativePathString = Util.relativePath(file.getFullPath(), 1/*remove project segment*/);
 												indexedFileNames.put(relativePathString,
-													indexedFileNames.get(relativePathString) == null || indexLastModified < location.toFile().lastModified()
+													indexedFileNames.get(relativePathString) == null 
+															|| indexLastModified < EFS.getStore(uri).fetchInfo().getLastModified()
 														? (Object) file
 														: (Object) OK);
 											}
diff --git a/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java b/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
index c6d3057..d246b0c 100644
--- a/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
+++ b/search/org/eclipse/jdt/internal/core/search/indexing/IndexBinaryFolder.java
@@ -11,14 +11,15 @@
 package org.eclipse.jdt.internal.core.search.indexing;
 
 import java.io.IOException;
+import java.net.URI;
 
+import org.eclipse.core.filesystem.EFS;
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IResourceProxy;
 import org.eclipse.core.resources.IResourceProxyVisitor;
 import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.index.Index;
@@ -67,7 +68,7 @@
 						if (proxy.getType() == IResource.FILE) {
 							if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(proxy.getName())) {
 								IFile file = (IFile) proxy.requestResource();
-								if (file.getLocation() != null) {
+								if (file.getLocationURI() != null) {
 									String containerRelativePath = Util.relativePath(file.getFullPath(), containerPath.segmentCount());
 									indexedFileNames.put(containerRelativePath, file);
 								}
@@ -84,16 +85,18 @@
 				final long indexLastModified = index.getIndexFile().lastModified();
 				this.folder.accept(
 					new IResourceProxyVisitor() {
-						public boolean visit(IResourceProxy proxy) {
+						public boolean visit(IResourceProxy proxy) throws CoreException {
 							if (isCancelled) return false;
 							if (proxy.getType() == IResource.FILE) {
 								if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(proxy.getName())) {
 									IFile file = (IFile) proxy.requestResource();
-									IPath location = file.getLocation();
-									if (location != null) {
+									URI uri = file.getLocationURI();
+									if (uri != null) {
 										String containerRelativePath = Util.relativePath(file.getFullPath(), containerPath.segmentCount());
 										indexedFileNames.put(containerRelativePath,
-											indexedFileNames.get(containerRelativePath) == null || indexLastModified < location.toFile().lastModified()
+											indexedFileNames.get(containerRelativePath) == null 
+													|| indexLastModified < 
+													EFS.getStore(uri).fetchInfo().getLastModified()
 												? (Object) file
 												: (Object) OK);
 									}
diff --git a/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java b/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
index 4e97dcb..b52bec0 100644
--- a/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
+++ b/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java
@@ -108,10 +108,17 @@
 
 	if (indexStates != null) {
 		Object[] keys = indexStates.keyTable;
+		int keysLength = keys.length;
+		int updates = 0;
+		String locations[] = new String[keysLength];
 		for (int i = 0, l = keys.length; i < l; i++) {
 			String key = (String) keys[i];
-			if (key != null && !knownPaths.containsKey(key))
-				updateIndexState(key, null);
+			if (key != null && !knownPaths.containsKey(key)) {
+				locations[updates++] = key;
+			}
+		}
+		if (updates > 0) {
+			removeIndexesState(locations);
 		}
 	}
 
@@ -474,6 +481,36 @@
 /**
  * Removes all indexes whose paths start with (or are equal to) the given path. 
  */
+public synchronized void removeIndexPath(IPath path) {
+	Set keySet = this.indexes.keySet();
+	Iterator keys = keySet.iterator();
+	String[] locations = null;
+	int max = keySet.size();
+	int ptr = 0;
+	while (keys.hasNext()) {
+		String indexLocation = (String) keys.next();
+		IPath indexPath = new Path(indexLocation);
+		if (path.isPrefixOf(indexPath)) {
+			Index index = (Index) this.indexes.get(indexLocation);
+			if (index != null) index.monitor = null;
+			if (locations == null) locations = new String[max];
+			locations[ptr++] = indexLocation;
+			File indexFile = new File(indexLocation);
+			if (indexFile.exists()) {
+				indexFile.delete();
+			}
+		} else if (locations == null) {
+			max--;
+		}
+	}
+	for (int i=0; i<ptr; i++) {
+		this.indexes.remove(locations[i]);
+	}
+	removeIndexesState(locations);
+}
+/**
+ * Removes all indexes whose paths start with (or are equal to) the given path. 
+ */
 public synchronized void removeIndexFamily(IPath path) {
 	// only finds cached index files... shutdown removes all non-cached index files
 	ArrayList toRemove = null;
@@ -630,6 +667,23 @@
 		return new char[0];
 	}
 }
+private synchronized void removeIndexesState(String[] locations) {
+	getIndexStates(); // ensure the states are initialized
+	int length = locations.length;
+	boolean changed = false;
+	for (int i=0; i<length; i++) {
+		if (locations[i] == null) continue;
+		if ((indexStates.removeKey(locations[i]) != null)) {
+			changed = true;
+			if (VERBOSE) {
+				Util.verbose("-> index state updated to: ? for: "+locations[i]); //$NON-NLS-1$
+			}
+		}
+	}
+	if (!changed) return;
+
+	writeSavedIndexNamesFile();
+}
 private synchronized void updateIndexState(String indexLocation, Integer indexState) {
 	getIndexStates(); // ensure the states are initialized
 	if (indexState != null) {
@@ -640,6 +694,18 @@
 		indexStates.removeKey(indexLocation);
 	}
 
+	writeSavedIndexNamesFile();
+
+	if (VERBOSE) {
+		String state = "?"; //$NON-NLS-1$
+		if (indexState == SAVED_STATE) state = "SAVED"; //$NON-NLS-1$
+		else if (indexState == UPDATING_STATE) state = "UPDATING"; //$NON-NLS-1$
+		else if (indexState == UNKNOWN_STATE) state = "UNKNOWN"; //$NON-NLS-1$
+		else if (indexState == REBUILDING_STATE) state = "REBUILDING"; //$NON-NLS-1$
+		Util.verbose("-> index state updated to: " + state + " for: "+indexLocation); //$NON-NLS-1$ //$NON-NLS-2$
+	}
+}
+private void writeSavedIndexNamesFile() {
 	BufferedWriter writer = null;
 	try {
 		writer = new BufferedWriter(new FileWriter(savedIndexNamesFile));
@@ -663,13 +729,5 @@
 			}
 		}
 	}
-	if (VERBOSE) {
-		String state = "?"; //$NON-NLS-1$
-		if (indexState == SAVED_STATE) state = "SAVED"; //$NON-NLS-1$
-		else if (indexState == UPDATING_STATE) state = "UPDATING"; //$NON-NLS-1$
-		else if (indexState == UNKNOWN_STATE) state = "UNKNOWN"; //$NON-NLS-1$
-		else if (indexState == REBUILDING_STATE) state = "REBUILDING"; //$NON-NLS-1$
-		Util.verbose("-> index state updated to: " + state + " for: "+indexLocation); //$NON-NLS-1$ //$NON-NLS-2$
-	}
 }
 }
diff --git a/search/org/eclipse/jdt/internal/core/search/indexing/InternalSearchDocument.java b/search/org/eclipse/jdt/internal/core/search/indexing/InternalSearchDocument.java
index d3cf048..17e747b 100644
--- a/search/org/eclipse/jdt/internal/core/search/indexing/InternalSearchDocument.java
+++ b/search/org/eclipse/jdt/internal/core/search/indexing/InternalSearchDocument.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core.search.indexing;
 
+import org.eclipse.jdt.internal.core.JavaModelManager;
 import org.eclipse.jdt.internal.core.index.Index;
 
 /**
@@ -22,8 +23,18 @@
 	 * Hidden by API SearchDocument subclass
 	 */
 	public void addIndexEntry(char[] category, char[] key) {
-		if (this.index != null)
+		if (this.index != null) {
 			index.addIndexEntry(category, key, getContainerRelativePath());
+			if (category == IIndexConstants.TYPE_DECL && key != null) {
+				int length = key.length;
+				if (length > 1 && key[length-2] == IIndexConstants.SEPARATOR && key[length-1] == IIndexConstants.SECONDARY_SUFFIX ) {
+					// This is a key of a secondary type => reset java model manager secondary types cache for document path project
+					JavaModelManager manager = JavaModelManager.getJavaModelManager();
+					manager.resetSecondaryTypesCache(getPath());
+//					manager.addSecondaryType(getPath(), key);
+				}
+			}
+		}
 	}
 	private String getContainerRelativePath() {
 		if (this.containerRelativePath == null)
diff --git a/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java b/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java
index 684ff50..e171dee 100644
--- a/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java
+++ b/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexer.java
@@ -59,12 +59,14 @@
 			requestor, 
 			this.problemFactory, 
 			new CompilerOptions(options), 
-			true/*index local declarations*/,
-			true/*optimize string literals*/);
+			true, // index local declarations
+			true, // optimize string literals
+			false); // do not use source javadoc parser to speed up parsing
 		parser.reportOnlyOneSyntaxError = true;
 	
 		// Always check javadoc while indexing
 		parser.javadocParser.checkDocComment = true;
+		parser.javadocParser.reportProblems = false;
 		
 		// Launch the parser
 		char[] source = null;
diff --git a/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java b/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
index ecd3b10..6bbb25c 100644
--- a/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
+++ b/search/org/eclipse/jdt/internal/core/search/indexing/SourceIndexerRequestor.java
@@ -137,7 +137,7 @@
 	} else {
 		typeNames = this.enclosingTypeNames();
 	}
-	this.indexer.addAnnotationTypeDeclaration(typeInfo.modifiers, packageName, typeInfo.name, typeNames);
+	this.indexer.addAnnotationTypeDeclaration(typeInfo.modifiers, packageName, typeInfo.name, typeNames, typeInfo.secondary);
 	this.pushTypeName(typeInfo.name);	
 }
 
@@ -170,7 +170,7 @@
 			typeParameterSignatures[i] = Signature.createTypeParameterSignature(typeParameterInfo.name, typeParameterInfo.bounds == null ? CharOperation.NO_CHAR_CHAR : typeParameterInfo.bounds);
 		}
 	}
-	this.indexer.addClassDeclaration(typeInfo.modifiers, this.packageName, typeInfo.name, typeNames, typeInfo.superclass, typeInfo.superinterfaces, typeParameterSignatures);
+	this.indexer.addClassDeclaration(typeInfo.modifiers, this.packageName, typeInfo.name, typeNames, typeInfo.superclass, typeInfo.superinterfaces, typeParameterSignatures, typeInfo.secondary);
 	this.pushTypeName(typeInfo.name);
 }
 /**
@@ -199,7 +199,7 @@
 	} else {
 		typeNames = this.enclosingTypeNames();
 	}
-	this.indexer.addEnumDeclaration(typeInfo.modifiers, packageName, typeInfo.name, typeNames, typeInfo.superinterfaces);
+	this.indexer.addEnumDeclaration(typeInfo.modifiers, packageName, typeInfo.name, typeNames, typeInfo.superinterfaces, typeInfo.secondary);
 	this.pushTypeName(typeInfo.name);	
 }
 /**
@@ -237,7 +237,7 @@
 			typeParameterSignatures[i] = Signature.createTypeParameterSignature(typeParameterInfo.name, typeParameterInfo.bounds);
 		}
 	}
-	this.indexer.addInterfaceDeclaration(typeInfo.modifiers, packageName, typeInfo.name, typeNames, typeInfo.superinterfaces, typeParameterSignatures);
+	this.indexer.addInterfaceDeclaration(typeInfo.modifiers, packageName, typeInfo.name, typeNames, typeInfo.superinterfaces, typeParameterSignatures, typeInfo.secondary);
 	this.pushTypeName(typeInfo.name);	
 }
 /**
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java b/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java
index 281c168..bf16795 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/ClassFileMatchLocator.java
@@ -240,7 +240,10 @@
 	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(), pattern.isCamelCase())) return false;
+		char[] simpleName = (pattern.getMatchMode() == SearchPattern.R_PREFIX_MATCH)
+			? CharOperation.concat(pattern.simpleName, IIndexConstants.ONE_STAR)
+			: pattern.simpleName;
+		if (!checkTypeName(simpleName, pattern.pkg, fullyQualifiedTypeName, pattern.isCaseSensitive(), pattern.isCamelCase())) return false;
 	} else {
 		char[] enclosingTypeName = CharOperation.concatWith(pattern.enclosingTypeNames, '.');
 		char[] patternString = pattern.pkg == null
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java b/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
index d6a9f10..01d4260 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/ClasspathSourceDirectory.java
@@ -15,34 +15,22 @@
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
 import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.core.builder.ClasspathLocation;
+import org.eclipse.jdt.internal.core.util.ResourceCompilationUnit;
 import org.eclipse.jdt.internal.core.util.Util;
 
 public class ClasspathSourceDirectory extends ClasspathLocation {
 
 	IContainer sourceFolder;
-	String sourceLocation; 
-	String encoding;
 	SimpleLookupTable directoryCache;
-	String[] missingPackageHolder = new String[1];
+	SimpleLookupTable missingPackageHolder = new SimpleLookupTable();
 	char[][] fullExclusionPatternChars;
 	char[][] fulInclusionPatternChars;
 
 ClasspathSourceDirectory(IContainer sourceFolder, char[][] fullExclusionPatternChars, char[][] fulInclusionPatternChars) {
 	this.sourceFolder = sourceFolder;
-	IPath location = sourceFolder.getLocation();
-	this.sourceLocation = location != null ? location.addTrailingSeparator().toString() : ""; //$NON-NLS-1$
-	// Store default encoding
-	try {
-		this.encoding = this.sourceFolder.getDefaultCharset();
-	}
-	catch (CoreException ce) {
-		// let use no encoding by default
-	}
 	this.directoryCache = new SimpleLookupTable(5);
 	this.fullExclusionPatternChars = fullExclusionPatternChars;
 	this.fulInclusionPatternChars = fulInclusionPatternChars;
@@ -52,27 +40,31 @@
 	this.directoryCache = null;
 }
 
-String[] directoryList(String qualifiedPackageName) {
-	String[] dirList = (String[]) directoryCache.get(qualifiedPackageName);
-	if (dirList == missingPackageHolder) return null; // package exists in another classpath directory or jar
-	if (dirList != null) return dirList;
+SimpleLookupTable directoryTable(String qualifiedPackageName) {
+	SimpleLookupTable dirTable = (SimpleLookupTable) directoryCache.get(qualifiedPackageName);
+	if (dirTable == missingPackageHolder) return null; // package exists in another classpath directory or jar
+	if (dirTable != null) return dirTable;
 
 	try {
 		IResource container = sourceFolder.findMember(qualifiedPackageName); // this is a case-sensitive check
 		if (container instanceof IContainer) {
 			IResource[] members = ((IContainer) container).members();
-			dirList = new String[members.length];
-			int index = 0;
+			dirTable = new SimpleLookupTable();
 			for (int i = 0, l = members.length; i < l; i++) {
 				IResource m = members[i];
 				String name;
-				if (m.getType() == IResource.FILE && org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(name = m.getName()))
-					dirList[index++] = name;
+				if (m.getType() == IResource.FILE) {
+					int index = Util.indexOfJavaLikeExtension(name = m.getName());
+					if (index >= 0) {
+						String fullPath = m.getFullPath().toString();
+						if (!org.eclipse.jdt.internal.compiler.util.Util.isExcluded(fullPath.toCharArray(), this.fulInclusionPatternChars, this.fullExclusionPatternChars, false/*not a folder path*/)) {
+							dirTable.put(name.substring(0, index), m);
+						}
+					}
+				}
 			}
-			if (index < dirList.length)
-				System.arraycopy(dirList, 0, dirList = new String[index], 0, index);
-			directoryCache.put(qualifiedPackageName, dirList);
-			return dirList;
+			directoryCache.put(qualifiedPackageName, dirTable);
+			return dirTable;
 		}
 	} catch(CoreException ignored) {
 		// treat as if missing
@@ -81,16 +73,6 @@
 	return null;
 }
 
-boolean doesFileExist(String fileName, String qualifiedPackageName) {
-	String[] dirList = directoryList(qualifiedPackageName);
-	if (dirList == null) return false; // most common case
-
-	for (int i = dirList.length; --i >= 0;)
-		if (fileName.equals(dirList[i]))
-			return true;
-	return false;
-}
-
 public boolean equals(Object o) {
 	if (this == o) return true;
 	if (!(o instanceof ClasspathSourceDirectory)) return false;
@@ -99,28 +81,12 @@
 } 
 
 public NameEnvironmentAnswer findClass(String sourceFileWithoutExtension, String qualifiedPackageName, String qualifiedSourceFileWithoutExtension) {
-	
-	String sourceFolderPath = this.sourceFolder.getFullPath().toString() + IPath.SEPARATOR;
-	char[][] javaLikeExtensions = Util.getJavaLikeExtensions();
-	for (int i = 0, length = javaLikeExtensions.length; i < length; i++) {
-		String extension = new String(javaLikeExtensions[i]);
-		String sourceFileName = sourceFileWithoutExtension + extension;
-		if (!doesFileExist(sourceFileName, qualifiedPackageName)) continue; // most common case
-	
-		String qualifiedSourceFileName = qualifiedSourceFileWithoutExtension + extension;
-		String fullSourcePath = this.sourceLocation + qualifiedSourceFileName;
-		if (org.eclipse.jdt.internal.compiler.util.Util.isExcluded((sourceFolderPath + qualifiedSourceFileName).toCharArray(), this.fulInclusionPatternChars, this.fullExclusionPatternChars, false/*not a folder path*/))
-			continue;
-		IPath path = new Path(qualifiedSourceFileName);
-		IFile file = this.sourceFolder.getFile(path);
-		String fileEncoding = this.encoding;
-		try {
-			fileEncoding = file.getCharset();
+	SimpleLookupTable dirTable = directoryTable(qualifiedPackageName);
+	if (dirTable != null && dirTable.elementSize > 0) {
+		IFile file = (IFile) dirTable.get(sourceFileWithoutExtension);
+		if (file != null) {
+			return new NameEnvironmentAnswer(new ResourceCompilationUnit(file), null /* no access restriction */);
 		}
-		catch (CoreException ce) {
-			// let use default encoding
-		}
-		return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, fileEncoding), null /* no access restriction */);
 	}
 	return null;
 }
@@ -130,7 +96,7 @@
 }
 
 public boolean isPackage(String qualifiedPackageName) {
-	return directoryList(qualifiedPackageName) != null;
+	return directoryTable(qualifiedPackageName) != null;
 }
 
 public void reset() {
@@ -142,7 +108,7 @@
 }
 
 public String debugPathString() {
-	return this.sourceLocation;
+	return this.sourceFolder.getFullPath().toString();
 }
 
 }
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java b/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
index de41665..9bf8c91 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
@@ -36,7 +36,7 @@
 	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
 	if (!(node instanceof ExplicitConstructorCall)) return IMPOSSIBLE_MATCH;
 
-	if (this.pattern.parameterSimpleNames != null && (this.pattern.shouldCountParameter() || ((node.bits & ASTNode.InsideJavadoc) != 0))) {
+	if (this.pattern.parameterSimpleNames != null && (!this.pattern.varargs || ((node.bits & ASTNode.InsideJavadoc) != 0))) {
 		int length = this.pattern.parameterSimpleNames.length;
 		Expression[] args = ((ExplicitConstructorCall) node).arguments;
 		int argsLength = args == null ? 0 : args.length;
@@ -61,7 +61,7 @@
 	if (this.pattern.declaringSimpleName != null && !matchesName(this.pattern.declaringSimpleName, typeName[typeName.length-1]))
 		return IMPOSSIBLE_MATCH;
 
-	if (this.pattern.parameterSimpleNames != null && (this.pattern.shouldCountParameter() || ((node.bits & ASTNode.InsideJavadoc) != 0))) {
+	if (this.pattern.parameterSimpleNames != null && (!this.pattern.varargs || ((node.bits & ASTNode.InsideJavadoc) != 0))) {
 		int length = this.pattern.parameterSimpleNames.length;
 		Expression[] args = allocation.arguments;
 		int argsLength = args == null ? 0 : args.length;
@@ -81,7 +81,7 @@
 			return IMPOSSIBLE_MATCH;
 	}
 
-	if (this.pattern.parameterSimpleNames != null && this.pattern.shouldCountParameter()) {
+	if (this.pattern.parameterSimpleNames != null && !this.pattern.varargs) {
 		int length = this.pattern.parameterSimpleNames.length;
 		Expression[] args = allocation.arguments;
 		int argsLength = args == null ? 0 : args.length;
@@ -212,7 +212,7 @@
 		// Update match regarding declaring class type arguments
 		if (constructorBinding.declaringClass.isParameterizedType() || constructorBinding.declaringClass.isRawType()) {
 			ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding)constructorBinding.declaringClass;
-			if (!this.pattern.hasTypeArguments() && this.pattern.hasConstructorArguments()) {
+			if (!this.pattern.hasTypeArguments() && this.pattern.hasConstructorArguments() || parameterizedBinding.isParameterizedWithOwnVariables()) {
 				// special case for constructor pattern which defines arguments but no type
 				// in this case, we only use refined accuracy for constructor
 			} else if (this.pattern.hasTypeArguments() && !this.pattern.hasConstructorArguments()) {
@@ -235,7 +235,7 @@
 			if (!this.pattern.hasTypeArguments() && this.pattern.hasConstructorArguments()) {
 				// special case for constructor pattern which defines arguments but no type
 				updateMatch(parameterizedBinding, new char[][][] {this.pattern.constructorArguments}, this.pattern.hasTypeParameters(), 0, locator);
-			} else {
+			} else if (!parameterizedBinding.isParameterizedWithOwnVariables()) {
 				updateMatch(parameterizedBinding, this.pattern.getTypeArguments(), this.pattern.hasTypeParameters(), 0, locator);
 			}
 		} else if (this.pattern.hasTypeArguments()) {
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java b/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java
index 1d77a1e..8949880 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java
@@ -34,7 +34,7 @@
 public char[][] parameterQualifications;
 public char[][] parameterSimpleNames;
 public int parameterCount;
-public int flags = 0;
+public boolean varargs = false;
 
 // Signatures and arguments for generic search
 char[][][] parametersTypeSignatures;
@@ -114,7 +114,7 @@
 
 	// Set flags
 	try {
-		this.flags = method.getFlags();
+		this.varargs = (method.getFlags() & Flags.AccVarargs) != 0;
 	} catch (JavaModelException e) {
 		// do nothing
 	}
@@ -230,7 +230,7 @@
 public boolean matchesDecodedKey(SearchPattern decodedPattern) {
 	ConstructorPattern pattern = (ConstructorPattern) decodedPattern;
 
-	return (this.parameterCount == pattern.parameterCount || this.parameterCount == -1 || !shouldCountParameter())
+	return (this.parameterCount == pattern.parameterCount || this.parameterCount == -1 || this.varargs)
 		&& matchesName(this.declaringSimpleName, pattern.declaringSimpleName);
 }
 protected boolean mustResolve() {
@@ -249,7 +249,7 @@
 	switch(getMatchMode()) {
 		case R_EXACT_MATCH :
 			if (this.isCamelCase) break;
-			if (shouldCountParameter() && this.declaringSimpleName != null && this.parameterCount >= 0)
+			if (this.declaringSimpleName != null && this.parameterCount >= 0 && !this.varargs)
 				key = createIndexKey(this.declaringSimpleName, this.parameterCount);
 			else { // do a prefix query with the declaringSimpleName
 				matchRule &= ~R_EXACT_MATCH;
@@ -260,7 +260,7 @@
 			// do a prefix query with the declaringSimpleName
 			break;
 		case R_PATTERN_MATCH :
-			if (shouldCountParameter() && this.parameterCount >= 0)
+			if (this.parameterCount >= 0 && !this.varargs)
 				key = createIndexKey(this.declaringSimpleName == null ? ONE_STAR : this.declaringSimpleName, this.parameterCount);
 			else if (this.declaringSimpleName != null && this.declaringSimpleName[this.declaringSimpleName.length - 1] != '*')
 				key = CharOperation.concat(this.declaringSimpleName, ONE_STAR, SEPARATOR);
@@ -301,7 +301,4 @@
 	output.append(')');
 	return super.print(output);
 }
-boolean shouldCountParameter() {
-	return (this.flags & Flags.AccStatic) == 0 && (this.flags & Flags.AccVarargs) == 0;
-}
 }
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java b/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java
index 5904f2c..2c58d13 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/FieldLocator.java
@@ -196,7 +196,7 @@
 						break;
 					case INACCURATE_MATCH:
 						match = locator.newFieldReferenceMatch(element, elementBinding, SearchMatch.A_INACCURATE, -1, -1, reference);
-						if (fieldBinding.type.isParameterizedType() && this.pattern.hasTypeArguments()) {
+						if (fieldBinding.type != null && fieldBinding.type.isParameterizedType() && this.pattern.hasTypeArguments()) {
 							updateMatch((ParameterizedTypeBinding) fieldBinding.type, this.pattern.getTypeArguments(), locator);
 						}
 						matches[indexOfFirstFieldBinding] = match;
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java b/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
index 935ee22..ad65e33 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
@@ -61,6 +61,7 @@
 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.LocalVariable;
 import org.eclipse.jdt.internal.core.NameLookup;
 import org.eclipse.jdt.internal.core.Openable;
 import org.eclipse.jdt.internal.core.PackageFragment;
@@ -165,7 +166,6 @@
 	}
 }
 
-
 public static class WorkingCopyDocument extends JavaSearchDocument {
 	public org.eclipse.jdt.core.ICompilationUnit workingCopy;
 	WorkingCopyDocument(org.eclipse.jdt.core.ICompilationUnit workingCopy, SearchParticipant participant) {
@@ -256,7 +256,7 @@
 	IPackageFragmentRoot root = (IPackageFragmentRoot) pkg.getParent();
 	try {
 		if (!root.isArchive())
-			return ClassFileReader.read(type.getResource().getLocation().toOSString());
+			return Util.newClassFileReader(type.getResource());
 
 		IPath zipPath = root.isExternal() ? root.getPath() : root.getResource().getLocation();
 		if (zipPath == null) return null; // location is null
@@ -519,7 +519,36 @@
 
 	return createMethodHandle(type, new String(method.selector), parameterTypeSignatures);
 }
-
+/*
+ * Create binary method handle
+ */
+IMethod createBinaryMethodHandle(IType type, char[] methodSelector, char[][] argumentTypeNames, MatchLocator locator) {
+	ClassFileReader reader = MatchLocator.classFileReader(type);
+	if (reader != null) {
+		IBinaryMethod[] methods = reader.getMethods();
+		if (methods != null) {
+			int argCount = argumentTypeNames == null ? 0 : argumentTypeNames.length;
+			nextMethod : for (int i = 0, methodsLength = methods.length; i < methodsLength; i++) {
+				IBinaryMethod binaryMethod = methods[i];
+				char[] selector = binaryMethod.getSelector();
+				if (CharOperation.equals(selector, methodSelector)) {
+					char[] signature = binaryMethod.getGenericSignature();
+					if (signature == null) signature = binaryMethod.getMethodDescriptor();
+					char[][] parameterTypes = Signature.getParameterTypes(signature);
+					if (argCount != parameterTypes.length) continue nextMethod;
+					for (int j = 0; j < argCount; j++) {
+						char[] parameterTypeName = ClassFileMatchLocator.convertClassFileFormat(parameterTypes[j]);
+						if (!CharOperation.endsWith(Signature.toCharArray(Signature.getTypeErasure(parameterTypeName)), argumentTypeNames[j]))
+							continue nextMethod;
+						parameterTypes[j] = parameterTypeName;
+					}
+					return (IMethod) locator.createMethodHandle(type, new String(selector), CharOperation.toStrings(parameterTypes));
+				}
+			}
+		}
+	}
+	return null;
+}
 /*
  * Create method handle.
  * Store occurences for create handle to retrieve possible duplicate ones.
@@ -562,6 +591,34 @@
 	}
 	return ((IType) parent).getInitializer(occurrenceCount);
 }
+/**
+ * Create an handle for a local variable declartion (may be a local variable or type parameter).
+ */
+protected IJavaElement createHandle(AbstractVariableDeclaration variableDeclaration, IJavaElement parent) {
+	switch (variableDeclaration.getKind()) {
+		case AbstractVariableDeclaration.LOCAL_VARIABLE:
+			return new LocalVariable((JavaElement)parent,
+				new String(variableDeclaration.name),
+				variableDeclaration.declarationSourceStart,
+				variableDeclaration.declarationSourceEnd,
+				variableDeclaration.sourceStart,
+				variableDeclaration.sourceEnd,
+				new String(variableDeclaration.type.resolvedType.signature())
+			);
+		case AbstractVariableDeclaration.PARAMETER:
+			return new LocalVariable((JavaElement)parent,
+				new String(variableDeclaration.name),
+				variableDeclaration.declarationSourceStart,
+				variableDeclaration.declarationSourceEnd,
+				variableDeclaration.sourceStart,
+				variableDeclaration.sourceEnd,
+				new String(variableDeclaration.type.resolvedType.signature())
+			);
+		case AbstractVariableDeclaration.TYPE_PARAMETER:
+			return new org.eclipse.jdt.internal.core.TypeParameter((JavaElement)parent, new String(variableDeclaration.name));
+	}
+	return null;
+}
 /*
  * Creates hierarchy resolver if needed. 
  * Returns whether focus is visible.
@@ -707,8 +764,7 @@
 			}
 		} else {
 			// class file in a directory
-			String osPath = resource.getLocation().toOSString();
-			info = ClassFileReader.read(osPath);
+			info = Util.newClassFileReader(resource);
 		}
 		if (info == null) throw binaryType.newNotPresentException();
 		return info;
@@ -1175,15 +1231,8 @@
 				}
 				for (int k = 0, pksLength = pkgs.length; k < pksLength; k++) {
 					IPackageFragment pkg = (IPackageFragment) pkgs[k];
-					IJavaElement[] children = null;
-					try {
-						children = pkg.getChildren();
-					} catch (JavaModelException e) {
-						// package doesn't exist -> continue with next package (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75561)
-						continue;
-					}
-					if (children.length > 0 
-							&& pkgPattern.matchesName(pkgPattern.pkgName, pkg.getElementName().toCharArray())) {
+					if (!pkg.exists()) continue; // package doesn't exist -> continue with next package (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=75561)
+					if (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();
@@ -1229,7 +1278,7 @@
 		acceptFlag = NameLookup.ACCEPT_CLASSES;
 	}
 	for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) {
-		IType type = this.nameLookup.findType(typeName, pkgs[i],  false,  acceptFlag);
+		IType type = this.nameLookup.findType(typeName, pkgs[i],  false,  acceptFlag, true/*consider secondary types*/);
 		if (type != null) return type;
 	}
 
@@ -1364,7 +1413,7 @@
 	return new TypeParameterReferenceMatch(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource);
 }
 
-public SearchMatch newTypeReferenceMatch(
+public TypeReferenceMatch newTypeReferenceMatch(
 		IJavaElement enclosingElement,
 		Binding enclosingBinding,
 		int accuracy,
@@ -1379,7 +1428,7 @@
 	return new TypeReferenceMatch(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource);
 }
 
-public SearchMatch newTypeReferenceMatch(
+public TypeReferenceMatch newTypeReferenceMatch(
 		IJavaElement enclosingElement,
 		Binding enclosingBinding,
 		int accuracy,
@@ -1449,8 +1498,8 @@
 		// Move getMethodBodies to #parseAndBuildings(...) method to allow possible match resolution management
 		//getMethodBodies(unit);
 
-		boolean mustResolve = ((InternalSearchPattern)this.pattern).mustResolve || possibleMatch.nodeSet.mustResolve;
-		if (bindingsWereCreated &&  mustResolve) {
+		boolean mustResolve = (((InternalSearchPattern)this.pattern).mustResolve || possibleMatch.nodeSet.mustResolve) && bindingsWereCreated;
+		if (mustResolve) {
 			if (unit.types != null) {
 				if (BasicSearchEngine.VERBOSE)
 					System.out.println("Resolving " + this.currentPossibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
@@ -1471,7 +1520,7 @@
 		reportMatching(unit, mustResolve);
 	} catch (AbortCompilation e) {
 		// could not resolve: report inaccurate matches
-		reportMatching(unit, true); // was partially resolved
+		reportMatching(unit, false); // do not resolve when cu has errors
 		if (!(e instanceof AbortCompilationUnit)) {
 			// problem with class path
 			throw e;
@@ -1541,6 +1590,26 @@
 		} catch (Exception e) {
 			// it's just for debug purposes... ignore all exceptions in this area
 		}
+		if (match instanceof TypeReferenceMatch) {
+			try {
+				TypeReferenceMatch typeRefMatch = (TypeReferenceMatch) match;
+				JavaElement local = (JavaElement) typeRefMatch.getLocalElement();
+				if (local != null) {
+					System.out.println("\tLocal element: "+ local.toStringWithAncestors()); //$NON-NLS-1$
+				}
+				IJavaElement[] others = typeRefMatch.getOtherElements();
+				int length = others==null ? 0 : others.length;
+				if (length > 0) {
+					System.out.println("\tOther elements:"); //$NON-NLS-1$
+					for (int i=0; i<length; i++) {
+						JavaElement other = (JavaElement) others[i];
+						System.out.println("\t\t- "+ other.toStringWithAncestors()); //$NON-NLS-1$
+					}
+				}
+			} catch (Exception e) {
+				// it's just for debug purposes... ignore all exceptions in this area
+			}
+		}
 		System.out.println(match.getAccuracy() == SearchMatch.A_ACCURATE
 			? "\tAccuracy: EXACT_MATCH" //$NON-NLS-1$
 			: "\tAccuracy: POTENTIAL_MATCH"); //$NON-NLS-1$
@@ -1813,7 +1882,7 @@
  * 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 {
+protected void reportMatching(TypeDeclaration type, AbstractMethodDeclaration method, IJavaElement parent, int accuracy, boolean typeInHierarchy, MatchingNodeSet nodeSet) throws CoreException {
 	IJavaElement enclosingElement = null;
 	if (accuracy > -1) {
 		enclosingElement = createHandle(method, parent);
@@ -1829,9 +1898,18 @@
 				// ignore
 			}
 			if (encloses(enclosingElement)) {
-				int length = scanner.currentPosition - nameSourceStart;
-				SearchMatch match = this.patternLocator.newDeclarationMatch(method, enclosingElement, method.binding, accuracy, length, this);
-				if (match != null) report(match);
+				SearchMatch match = null;
+				if (method.isDefaultConstructor()) {
+					// Use type for match associated element as default constructor does not exist in source
+					int offset = type.sourceStart;
+					match = this.patternLocator.newDeclarationMatch(type, parent, type.binding, accuracy, type.sourceEnd-offset+1, this);
+				} else {
+					int length = scanner.currentPosition - nameSourceStart;
+					match = this.patternLocator.newDeclarationMatch(method, enclosingElement, method.binding, accuracy, length, this);
+				}
+				if (match != null) {
+					report(match);
+				}
 			}
 		}
 	}
@@ -1848,6 +1926,15 @@
 		}
 	}
 
+	// report the type parameters
+	TypeParameter[] typeParameters = method.typeParameters();
+	if (typeParameters != null) {
+		if (enclosingElement == null) {
+			enclosingElement = createHandle(method, parent);
+		}
+		reportMatching(typeParameters, enclosingElement, parent, method.binding, nodeSet);
+	}
+
 	// report annotations
 	if (method.annotations != null) {
 		if (enclosingElement == null) {
@@ -1867,7 +1954,7 @@
 					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, method.binding, level.intValue(), this);
+						this.patternLocator.matchReportReference(node, enclosingElement, method.binding, method.scope, level.intValue(), this);
 					}
 					return;
 				}
@@ -2033,7 +2120,7 @@
  * 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 {
+protected void reportMatching(FieldDeclaration field, FieldDeclaration[] otherFields, TypeDeclaration type, IJavaElement parent, int accuracy, boolean typeInHierarchy, MatchingNodeSet nodeSet) throws CoreException {
 	IJavaElement enclosingElement = null;
 	if (accuracy > -1) {
 		enclosingElement = createHandle(field, type, parent);
@@ -2065,17 +2152,51 @@
 	}
 
 	if (typeInHierarchy) {
-		// limit scan to end part position for multiple fields declaration (see bug 73112)
-		int end = field.endPart2Position==0 ? field.declarationSourceEnd : field.endPart2Position;
-		ASTNode[] nodes = nodeSet.matchingNodes(field.declarationSourceStart, end);
+		// Look at field declaration
+		if (field.endPart1Position != 0) { // not necessary if field is an initializer
+			ASTNode[] nodes = nodeSet.matchingNodes(field.declarationSourceStart, field.endPart1Position);
+			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);
+					if (encloses(enclosingElement)) {
+						for (int i = 0, l = nodes.length; i < l; i++) {
+							ASTNode node = nodes[i];
+							Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
+							int length = otherFields== null ? 0 : otherFields.length;
+							IJavaElement[] otherElements = null;
+							if (length > 0) {
+								int size = 0;
+								while (size<length && otherFields[size] != null) {
+									size++;
+								}
+								otherElements = new IJavaElement[size];
+								for (int j=0; j<size; j++) {
+									otherElements[j] = createHandle(otherFields[j], type, parent);
+								}
+							}
+							this.patternLocator.matchReportReference(node, enclosingElement, null, otherElements, field.binding, level.intValue(), this);
+						}
+					}
+				}
+			}
+		}
+
+		// Look in initializer
+		int fieldEnd = field.endPart2Position == 0 ? field.declarationSourceEnd : field.endPart2Position;
+		ASTNode[] nodes = nodeSet.matchingNodes(field.sourceStart, fieldEnd);
 		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)
+				if (enclosingElement == null) {
 					enclosingElement = createHandle(field, type, parent);
-				if (encloses(enclosingElement))
+				}
+				if (encloses(enclosingElement)) {
 					for (int i = 0, l = nodes.length; i < l; i++) {
 						ASTNode node = nodes[i];
 						Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
@@ -2086,8 +2207,15 @@
 								node = field;
 							}
 						}
-						this.patternLocator.matchReportReference(node, enclosingElement, field.binding, level.intValue(), this);
+						// Set block scope for initializer in case there would have other local and other elements to report
+						BlockScope blockScope = null;
+						if (field.getKind() == AbstractVariableDeclaration.INITIALIZER) {
+							Block block = ((Initializer)field).block;
+							if (block != null) blockScope = block.scope;
+						}
+						this.patternLocator.matchReportReference(node, enclosingElement, field.binding, blockScope, level.intValue(), this);
 					}
+				}
 			}
 		}
 	}
@@ -2121,36 +2249,10 @@
 	}
 
 	boolean matchedClassContainer = (this.matchContainer & PatternLocator.CLASS_CONTAINER) != 0;
-	
+
 	// report the type parameters
 	if (type.typeParameters != null) {
-		for (int i=0, l=type.typeParameters.length; i<l; i++) {
-			TypeParameter typeParameter = type.typeParameters[i];
-			if (typeParameter != null) {
-				Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeParameter);
-				if (level != null && matchedClassContainer) {
-					if (level.intValue() > -1 && enclosesElement) {
-						int offset = typeParameter.sourceStart;
-						SearchMatch match = this.patternLocator.newDeclarationMatch(typeParameter, enclosingElement, type.binding, level.intValue(), typeParameter.sourceEnd-offset+1, this);
-						report(match);
-					}
-				}
-				if (typeParameter.type != null) {
-					level = (Integer) nodeSet.matchingNodes.removeKey(typeParameter.type);
-					if (level != null && matchedClassContainer) {
-						this.patternLocator.matchReportReference(typeParameter.type, enclosingElement, type.binding, level.intValue(), this);
-					}
-				}
-				if (typeParameter.bounds != null) {
-					for (int j=0, b=typeParameter.bounds.length; j<b; j++) {
-						level = (Integer) nodeSet.matchingNodes.removeKey(typeParameter.bounds[j]);
-						if (level != null && matchedClassContainer) {
-							this.patternLocator.matchReportReference(typeParameter.bounds[j], enclosingElement, type.binding, level.intValue(), this);
-						}
-					}
-				}
-			}
-		}
+		reportMatching(type.typeParameters, enclosingElement, parent, type.binding, nodeSet);
 	}
 
 	// report annotations
@@ -2202,32 +2304,66 @@
 	boolean typeInHierarchy = type.binding == null || typeInHierarchy(type.binding);
 	matchedClassContainer = matchedClassContainer && typeInHierarchy; 
 
+	// Visit fields
 	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++) {
+		if (nodeSet.matchingNodes.elementSize == 0) return;	// end as all matching nodes were reported
+		FieldDeclaration[] otherFields = null;
+		int first = -1;
+		int length = fields.length;
+		for (int i = 0; i < length; 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);
+			boolean last = field.endPart2Position == 0 || field.declarationEnd == field.endPart2Position;
+			// Store first index of multiple field declaration
+			if (!last) {
+				if (first == -1) {
+					first = i;
+				}
+			}
+			if (first >= 0) {
+				// Store all multiple fields but first one for other elements
+				if (i > first) {
+					if (otherFields == null) {
+						otherFields = new FieldDeclaration[length-i];
+					}
+					otherFields[i-1-first] = field;
+				}
+				// On last field, report match with all other elements
+				if (last) {
+					for (int j=first; j<=i; j++) {
+						Integer level = (Integer) nodeSet.matchingNodes.removeKey(fields[j]);
+						int value = (level != null && matchedClassContainer) ? level.intValue() : -1;
+						reportMatching(fields[j], otherFields, type, enclosingElement, value, typeInHierarchy, nodeSet);
+					}
+					first = -1;
+					otherFields = null;
+				}
+			} else {
+				// Single field, report normally
+				Integer level = (Integer) nodeSet.matchingNodes.removeKey(field);
+				int value = (level != null && matchedClassContainer) ? level.intValue() : -1;
+				reportMatching(field, null, type, enclosingElement, value, typeInHierarchy, nodeSet);
+			}
 		}
 	}
 
+	// Visit methods
 	AbstractMethodDeclaration[] methods = type.methods;
 	if (methods != null) {
-		if (nodeSet.matchingNodes.elementSize == 0) return; // reported all the matching nodes
+		if (nodeSet.matchingNodes.elementSize == 0) return;	// end as all matching nodes were reported
 		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);
+			reportMatching(type, method, enclosingElement, value, typeInHierarchy, nodeSet);
 		}
 	}
 
+	// Visit types
 	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
+			if (nodeSet.matchingNodes.elementSize == 0) return;	// end as all matching nodes were reported
 			TypeDeclaration memberType = memberTypes[i];
 			Integer level = (Integer) nodeSet.matchingNodes.removeKey(memberType);
 			int value = (level != null && matchedClassContainer) ? level.intValue() : -1;
@@ -2235,6 +2371,41 @@
 		}
 	}
 }
+/**
+ * Report matches in type parameters.
+ */
+protected void reportMatching(TypeParameter[] typeParameters, IJavaElement enclosingElement, IJavaElement parent, Binding binding, MatchingNodeSet nodeSet) throws CoreException {
+	if (typeParameters == null) return;
+	for (int i=0, l=typeParameters.length; i<l; i++) {
+		TypeParameter typeParameter = typeParameters[i];
+		if (typeParameter != null) {
+			Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeParameter);
+			if (level != null) {
+				if (level.intValue() > -1 && encloses(enclosingElement)) {
+					int offset = typeParameter.sourceStart;
+					SearchMatch match = this.patternLocator.newDeclarationMatch(typeParameter, enclosingElement, binding, level.intValue(), typeParameter.sourceEnd-offset+1, this);
+					report(match);
+				}
+			}
+			if (typeParameter.type != null) {
+				level = (Integer) nodeSet.matchingNodes.removeKey(typeParameter.type);
+				if (level != null) {
+					IJavaElement localElement = createHandle(typeParameter, enclosingElement);
+					this.patternLocator.matchReportReference(typeParameter.type, enclosingElement, localElement, null, binding, level.intValue(), this);
+				}
+			}
+			if (typeParameter.bounds != null) {
+				for (int j=0, b=typeParameter.bounds.length; j<b; j++) {
+					level = (Integer) nodeSet.matchingNodes.removeKey(typeParameter.bounds[j]);
+					if (level != null) {
+						IJavaElement localElement = createHandle(typeParameter, enclosingElement);
+						this.patternLocator.matchReportReference(typeParameter.bounds[j], enclosingElement, localElement, null, binding, level.intValue(), this);
+					}
+				}
+			}
+		}
+	}
+}
 protected void reportMatchingSuper(TypeReference superReference, IJavaElement enclosingElement, Binding elementBinding, MatchingNodeSet nodeSet, boolean matchedClassContainer) throws CoreException {
 	ASTNode[] nodes = null;
 	if (superReference instanceof ParameterizedSingleTypeReference || superReference instanceof ParameterizedQualifiedTypeReference) {
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java b/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
index 35d1274..a290699 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
@@ -152,7 +152,7 @@
 	if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
 
 	if (!matchesName(this.pattern.selector, node.selector)) return IMPOSSIBLE_MATCH;
-	if (this.pattern.parameterSimpleNames != null && (this.pattern.shouldCountParameter() || ((node.bits & ASTNode.InsideJavadoc) != 0))) {
+	if (this.pattern.parameterSimpleNames != null && (!this.pattern.varargs || ((node.bits & ASTNode.InsideJavadoc) != 0))) {
 		int length = this.pattern.parameterSimpleNames.length;
 		ASTNode[] args = node.arguments;
 		int argsLength = args == null ? 0 : args.length;
@@ -363,7 +363,7 @@
 		// Update match regarding declaring class type arguments
 		if (methodBinding.declaringClass.isParameterizedType() || methodBinding.declaringClass.isRawType()) {
 			ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding)methodBinding.declaringClass;
-			if (!this.pattern.hasTypeArguments() && this.pattern.hasMethodArguments()) {
+			if (!this.pattern.hasTypeArguments() && this.pattern.hasMethodArguments() || parameterizedBinding.isParameterizedWithOwnVariables()) {
 				// special case for pattern which defines method arguments but not its declaring type
 				// in this case, we do not refine accuracy using declaring type arguments...!
 			} else {
@@ -387,7 +387,9 @@
 		isParameterized = true;
 		if (methodBinding.declaringClass.isParameterizedType() || methodBinding.declaringClass.isRawType()) {
 			ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding)methodBinding.declaringClass;
-			updateMatch(parameterizedBinding, this.pattern.getTypeArguments(), this.pattern.hasTypeParameters(), 0, locator);
+			if (!parameterizedBinding.isParameterizedWithOwnVariables()) {
+				updateMatch(parameterizedBinding, this.pattern.getTypeArguments(), this.pattern.hasTypeParameters(), 0, locator);
+			}
 		} else if (this.pattern.hasTypeArguments()) {
 			match.setRule(SearchPattern.R_ERASURE_MATCH);
 		}
@@ -481,22 +483,35 @@
 	if (type == null) return; // case of a secondary type
 
 	char[] bindingSelector = methodBinding.selector;
+	boolean isBinary = type.isBinary();
+	IMethod method = null;
 	TypeBinding[] parameters = methodBinding.original().parameters;
 	int parameterLength = parameters.length;
-	String[] parameterTypes = new String[parameterLength];
-	for (int i = 0; i  < parameterLength; i++) {
-		char[] typeName = parameters[i].shortReadableName();
-		if (parameters[i].isMemberType()) {
-			typeName = CharOperation.subarray(typeName, CharOperation.indexOf('.', typeName)+1, typeName.length);
+	if (isBinary) {
+		char[][] parameterTypes = new char[parameterLength][];
+		for (int i = 0; i<parameterLength; i++) {
+			char[] typeName = parameters[i].qualifiedSourceName();
+			for (int j=0, dim=parameters[i].dimensions(); j<dim; j++) {
+				typeName = CharOperation.concat(typeName, new char[] {'[', ']'});
+			}
+			parameterTypes[i] = typeName;
 		}
-		parameterTypes[i] = Signature.createTypeSignature(typeName, false);
+		method = locator.createBinaryMethodHandle(type, methodBinding.selector, parameterTypes, locator);
+	} else {
+		String[] parameterTypes = new String[parameterLength];
+		for (int i = 0; i  < parameterLength; i++) {
+			char[] typeName = parameters[i].shortReadableName();
+			if (parameters[i].isMemberType()) {
+				typeName = CharOperation.subarray(typeName, CharOperation.indexOf('.', typeName)+1, typeName.length);
+			}
+			parameterTypes[i] = Signature.createTypeSignature(typeName, false);
+		}
+		method = type.getMethod(new String(bindingSelector), parameterTypes);
 	}
-	IMethod method = type.getMethod(new String(bindingSelector), parameterTypes);
-	if (knownMethods.includes(method)) return;
+	if (method == null || knownMethods.includes(method)) return;
 
 	knownMethods.add(method);
 	IResource resource = type.getResource();
-	boolean isBinary = type.isBinary();
 	IBinaryType info = null;
 	if (isBinary) {
 		if (resource == null)
@@ -580,7 +595,9 @@
 }
 protected int resolveLevel(MessageSend messageSend) {
 	MethodBinding method = messageSend.binding;
-	if (method == null) return INACCURATE_MATCH;
+	if (method == null) {
+		return INACCURATE_MATCH;
+	}
 	if (messageSend.resolvedType == null) {
 		// Closest match may have different argument numbers when ProblemReason is NotFound
 		// see MessageSend#resolveType(BlockScope)
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java b/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
index 4bbb420..5b8baee 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
@@ -35,8 +35,7 @@
 public char[][] parameterQualifications;
 public char[][] parameterSimpleNames;
 public int parameterCount;
-public int flags = 0;
-public boolean mustResolveGeneric = false;
+public boolean varargs = false;
 
 // extra reference info
 protected IType declaringType;
@@ -136,7 +135,7 @@
 	
 	// Set flags
 	try {
-		this.flags = method.getFlags();
+		this.varargs = (method.getFlags() & Flags.AccVarargs) != 0;
 	} catch (JavaModelException e) {
 		// do nothing
 	}
@@ -181,28 +180,6 @@
 	// Store type signatures and arguments for method
 	methodArguments = extractMethodArguments(method);
 	if (hasMethodArguments())  ((InternalSearchPattern)this).mustResolve = true;
-	
-	// See if we must resolve specifically for generics
-	if (parameterSimpleNames != null && parameterSimpleNames.length > 0) {
-		int psLength = parameterSimpleNames.length;
-		try {
-			// Currently, we need to resolve for generic if one of method type argument
-			// equals to one of declaring type type parameter
-			ITypeParameter[] typeParameters = this.declaringType.getTypeParameters();
-			if (typeParameters != null && typeParameters.length > 0) {
-				int tpLength = typeParameters.length;
-				for (int i=0; i<psLength && !this.mustResolveGeneric; i++) {
-					for (int j=0; j<tpLength && !this.mustResolveGeneric; j++) {
-						if (CharOperation.equals(parameterSimpleNames[i], typeParameters[j].getElementName().toCharArray())) {
-							this.mustResolveGeneric = true;
-						}
-					}
-				}
-			}
-		} catch (JavaModelException e) {
-			// ignore
-		}
-	}
 }
 /*
  * Instanciate a method pattern with signatures for generics search
@@ -293,7 +270,7 @@
 public boolean matchesDecodedKey(SearchPattern decodedPattern) {
 	MethodPattern pattern = (MethodPattern) decodedPattern;
 
-	return (this.parameterCount == pattern.parameterCount || this.parameterCount == -1 || !shouldCountParameter())
+	return (this.parameterCount == pattern.parameterCount || this.parameterCount == -1 || this.varargs)
 		&& matchesName(this.selector, pattern.selector);
 }
 /**
@@ -322,7 +299,7 @@
 	switch(getMatchMode()) {
 		case R_EXACT_MATCH :
 			if (this.isCamelCase) break;
-			if (shouldCountParameter() && this.selector != null && this.parameterCount >= 0)
+			if (this.selector != null && this.parameterCount >= 0 && !this.varargs)
 				key = createIndexKey(this.selector, this.parameterCount);
 			else { // do a prefix query with the selector
 				matchRule &= ~R_EXACT_MATCH;
@@ -333,7 +310,7 @@
 			// do a prefix query with the selector
 			break;
 		case R_PATTERN_MATCH :
-			if (shouldCountParameter() && this.parameterCount >= 0)
+			if (this.parameterCount >= 0 && !this.varargs)
 				key = createIndexKey(this.selector == null ? ONE_STAR : this.selector, this.parameterCount);
 			else if (this.selector != null && this.selector[this.selector.length - 1] != '*')
 				key = CharOperation.concat(this.selector, ONE_STAR, SEPARATOR);
@@ -386,7 +363,4 @@
 		output.append("*"); //$NON-NLS-1$
 	return super.print(output);
 }
-boolean shouldCountParameter() {
-	return (this.flags & Flags.AccStatic) == 0 && (this.flags & Flags.AccVarargs) == 0;
-}
 }
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java b/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
index 4279a1b..ea0ba73 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/PatternLocator.java
@@ -391,6 +391,18 @@
 		locator.report(match);
 	}
 }
+/**
+ * Reports the match of the given reference. Also provide a local element to eventually report in match.
+ */
+protected void matchReportReference(ASTNode reference, IJavaElement element, IJavaElement localElement, IJavaElement[] otherElements, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
+	matchReportReference(reference, element, elementBinding, accuracy, locator);
+}
+/**
+ * Reports the match of the given reference. Also provide a scope to look for potential other elements.
+ */
+protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, Scope scope, int accuracy, MatchLocator locator) throws CoreException {
+	matchReportReference(reference, element, elementBinding, accuracy, locator);
+}
 public SearchMatch newDeclarationMatch(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, int length, MatchLocator locator) {
     return locator.newDeclarationMatch(element, elementBinding, accuracy, reference.sourceStart, length);
 }
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java b/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java
index e9694d6..0f4f66c 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/PossibleMatch.java
@@ -96,7 +96,7 @@
 private char[] getQualifiedName() {
 	if (this.openable instanceof CompilationUnit) {
 		// get file name
-		String fileName = this.resource.getFullPath().lastSegment();
+		String fileName = this.openable.getElementName(); // working copy on a .class file may not have a resource, so use the element name
 		// get main type name
 		char[] mainTypeName = Util.getNameWithoutJavaLikeExtension(fileName).toCharArray();
 		CompilationUnit cu = (CompilationUnit) this.openable;
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/SecondaryTypeDeclarationPattern.java b/search/org/eclipse/jdt/internal/core/search/matching/SecondaryTypeDeclarationPattern.java
new file mode 100644
index 0000000..5eaa4d4
--- /dev/null
+++ b/search/org/eclipse/jdt/internal/core/search/matching/SecondaryTypeDeclarationPattern.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-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.search.SearchPattern;
+import org.eclipse.jdt.internal.core.index.EntryResult;
+import org.eclipse.jdt.internal.core.index.Index;
+import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;
+
+public class SecondaryTypeDeclarationPattern extends TypeDeclarationPattern {
+	
+	private final static char[] SECONDARY_PATTERN_KEY = "*/S".toCharArray(); //$NON-NLS-1$
+
+public SecondaryTypeDeclarationPattern() {
+	super(null, null, null, IIndexConstants.SECONDARY_SUFFIX, R_EXACT_MATCH | R_CASE_SENSITIVE);
+}
+
+public SecondaryTypeDeclarationPattern(int matchRule) {
+	super(matchRule);
+}
+
+public SearchPattern getBlankPattern() {
+	return new SecondaryTypeDeclarationPattern(R_EXACT_MATCH | R_CASE_SENSITIVE);
+}
+protected StringBuffer print(StringBuffer output) {
+	output.append("Secondary"); //$NON-NLS-1$
+	return super.print(output);
+}
+
+/* (non-Javadoc)
+ * @see org.eclipse.jdt.internal.core.search.matching.TypeDeclarationPattern#queryIn(org.eclipse.jdt.internal.core.index.Index)
+ */
+EntryResult[] queryIn(Index index) throws IOException {
+	return index.query(CATEGORIES, SECONDARY_PATTERN_KEY, R_PATTERN_MATCH | R_CASE_SENSITIVE);
+}
+	
+}
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java b/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java
index 118dfb0..664dede 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/TypeDeclarationPattern.java
@@ -31,6 +31,7 @@
 // set to TYPE_SUFFIX for matching both classes and interfaces
 public char typeSuffix; 
 public int modifiers;
+public boolean secondary = false;
 
 protected static char[][] CATEGORIES = { TYPE_DECL };
 
@@ -81,9 +82,11 @@
 
 /*
  * Create index key for type declaration pattern:
- *		key = typeName / packageName / enclosingTypeName / typeSuffix modifiers
+ *		key = typeName / packageName / enclosingTypeName / modifiers
+ * or for secondary types
+ *		key = typeName / packageName / enclosingTypeName / modifiers / 'S'
  */
-public static char[] createIndexKey(int modifiers, char[] typeName, char[] packageName, char[][] enclosingTypeNames) { //, char typeSuffix) {
+public static char[] createIndexKey(int modifiers, char[] typeName, char[] packageName, char[][] enclosingTypeNames, boolean secondary) { //, char typeSuffix) {
 	int typeNameLength = typeName == null ? 0 : typeName.length;
 	int packageLength = packageName == null ? 0 : packageName.length;
 	int enclosingNamesLength = 0;
@@ -95,7 +98,9 @@
 		}
 	}
 
-	char[] result = new char[typeNameLength + packageLength + enclosingNamesLength + 4];
+	int resultLength = typeNameLength + packageLength + enclosingNamesLength + 4;
+	if (secondary) resultLength += 2;
+	char[] result = new char[resultLength];
 	int pos = 0;
 	if (typeNameLength > 0) {
 		System.arraycopy(typeName, 0, result, pos, typeNameLength);
@@ -119,6 +124,10 @@
 	}
 	result[pos++] = SEPARATOR;
 	result[pos] = (char) modifiers;
+	if (secondary) {
+		result[++pos] = SEPARATOR;
+		result[++pos] = 'S';
+	}
 	return result;
 }
 
@@ -170,7 +179,10 @@
 		this.enclosingTypeNames = CharOperation.equals(ONE_ZERO, names) ? ONE_ZERO_CHAR : CharOperation.splitOn('.', names);
 	}
 
-	decodeModifiers(key[key.length - 1]);
+	slash = CharOperation.indexOf(SEPARATOR, key, start = slash + 1);
+	this.secondary = slash > 0;
+	int last = this.secondary ? slash : key.length;
+	decodeModifiers(key[last-1]);
 }
 protected void decodeModifiers(char value) {
 	this.modifiers = value; // implicit cast to int type
diff --git a/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java b/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java
index 9abef24..a2b48f4 100644
--- a/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java
+++ b/search/org/eclipse/jdt/internal/core/search/matching/TypeReferenceLocator.java
@@ -255,7 +255,13 @@
 		// TODO (frederic) need to add a test for this case while searching generic types...
 		if (locator.encloses(element)) {
 			int offset = arrayRef.sourceStart;
-			match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, offset, arrayRef.sourceEnd-offset+1, arrayRef);
+			int length = arrayRef.sourceEnd-offset+1;
+			if (this.match == null) {
+				this.match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, offset, length, arrayRef);
+			} else {
+				this.match.setOffset(offset);
+				this.match.setLength(length);
+			}
 			locator.report(match);
 			return;
 		}
@@ -267,7 +273,16 @@
 	}
 	locator.reportAccurateTypeReference(match, arrayRef, this.pattern.simpleName);
 }
+/**
+ * Reports the match of the given reference.
+ */
 protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
+	matchReportReference(reference, element, null, null, elementBinding, accuracy, locator);
+}
+/**
+ * Reports the match of the given reference. Also provide a local and other elements to eventually report in match.
+ */
+protected void matchReportReference(ASTNode reference, IJavaElement element, IJavaElement localElement, IJavaElement[] otherElements, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
 	if (this.isDeclarationOfReferencedTypesPattern) {
 		if ((element = findElement(element, accuracy)) != null)
 			reportDeclaration(reference, element, locator, ((DeclarationOfReferencedTypesPattern) this.pattern).knownTypes);
@@ -275,7 +290,10 @@
 	}
 	
 	// Create search match
-	match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, reference);
+	TypeReferenceMatch refMatch = locator.newTypeReferenceMatch(element, elementBinding, accuracy, reference);
+	refMatch.setLocalElement(localElement);
+	refMatch.setOtherElements(otherElements);
+	this.match = refMatch;
 
 	// Report match depending on reference type
 	if (reference instanceof QualifiedNameReference)
@@ -293,6 +311,63 @@
 		locator.report(match);
 	}
 }
+/**
+ * Reports the match of the given reference. Also provide a scope to look for possible local and other elements.
+ */
+protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, Scope scope, int accuracy, MatchLocator locator) throws CoreException {
+	if (scope == null || (scope.kind != Scope.BLOCK_SCOPE && scope.kind != Scope.METHOD_SCOPE)) {
+		matchReportReference(reference, element, elementBinding, accuracy, locator);
+		return;
+	}
+	
+	// Look if some block scope local variable declarations include reference start position
+	BlockScope blockScope = (BlockScope) scope;
+	LocalDeclaration[] localDeclarations = blockScope.findLocalVariableDeclarations(reference.sourceStart);
+	int length = localDeclarations == null ? 0 : localDeclarations.length;
+	IJavaElement localElement = null;
+	IJavaElement[] otherElements = null;
+
+	// Some local variable declaration are matching
+	if (length > 0) {
+
+		// Set local element to first matching local declaration
+		int idx = 0;
+		for (; idx<length; idx++) {
+			if (localDeclarations[idx] == null) break;
+			if (reference.sourceStart == localDeclarations[idx].declarationSourceStart) {
+				localElement = locator.createHandle(localDeclarations[idx], element);
+				break;
+			}
+			if (idx>0 && localDeclarations[idx].sourceStart > reference.sourceStart) {
+				localElement = locator.createHandle(localDeclarations[idx-1], element);
+				break;
+			}
+		}
+		if (localElement == null && idx > 0) {
+			if (reference.sourceEnd < localDeclarations[idx-1].declarationEnd) {
+				localElement = locator.createHandle(localDeclarations[idx-1], element);
+			}
+		}
+		
+		// Store other local variable declarations in other elements
+		int size = 0;
+		for (int j=1; j<length; j++) {
+			if (localDeclarations[j] == null) break;
+			if (reference.sourceStart == localDeclarations[j].declarationSourceStart) {
+				if (otherElements == null) {
+					otherElements = new IJavaElement[length-j];
+				}
+				otherElements[size++] = locator.createHandle(localDeclarations[j], element);
+			}
+		}
+		if (size > 0 && size != (length-1)) {
+			System.arraycopy(otherElements, 0, otherElements = new IJavaElement[size], 0, size);
+		}
+	}
+	
+	// Report match with local and other elements if any
+	matchReportReference(reference, element, localElement, otherElements, elementBinding, accuracy, locator);
+}
 protected void matchReportReference(QualifiedNameReference qNameRef, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
 	Binding binding = qNameRef.binding;
 	TypeBinding typeBinding = null;
@@ -325,7 +400,9 @@
 	}
 
 	// Create search match to report
-	match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, qNameRef);
+	if (this.match == null) {
+		this.match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, qNameRef);
+	}
 
 	// try to match all enclosing types for which the token matches as well.
 	if (typeBinding instanceof ReferenceBinding) {
@@ -368,7 +445,9 @@
 	}
 
 	// Create search match to report
-	match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, qTypeRef);
+	if (this.match == null) {
+		this.match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, qTypeRef);
+	}
 
 	// try to match all enclosing types for which the token matches as well
 	if (typeBinding instanceof ReferenceBinding) {